diff --git a/.changeset/update-effect-4.0.5.md b/.changeset/update-effect-4.0.5.md new file mode 100644 index 0000000000..768ce9713e --- /dev/null +++ b/.changeset/update-effect-4.0.5.md @@ -0,0 +1,6 @@ +--- +"effect-app": patch +"@effect-app/cli": patch +--- + +Upgrade Effect packages to npm `4.0.5`. `TaggedUnion` and `ExtendTaggedUnion` reject duplicate `_tag` values at compile time, matching `Schema.toTaggedUnion`. JSON Schema for `PositiveInt` and `NonNegativeInt` now includes `Schema.Int`'s safe-integer maximum. diff --git a/.oxlintrc.json b/.oxlintrc.json index 78db57e540..fd83f94428 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -13,6 +13,13 @@ "effecttsgo/lazy-effect": "off", "effecttsgo/return-effect-in-gen": "off", "effecttsgo/run-effect-inside-effect": "off", + // Stays off. A Schema brand type argument (`{ readonly brand: unique symbol }`) + // is the wrong nominal marker here. If we brand a class, use a protected field + // so a plain object is not a class instance unless it comes from `new` / `.make`: + // class Foo extends Schema.TaggedClass()("Foo", { /* fields */ }) { + // declare protected "~brand~": never + // } + "effecttsgo/schema-class-missing-brand": "off", "effecttsgo/schema-sync-in-effect": "off", "effecttsgo/strict-effect-provide": "off", "effecttsgo/unsafe-effect-type-assertion": "off", diff --git a/package.json b/package.json index 48ead372c1..e43ce73819 100644 --- a/package.json +++ b/package.json @@ -48,29 +48,29 @@ "@effect-app/cli": "workspace:*", "@effect-app/eslint-codegen-model": "workspace:*", "@effect-app/infra": "workspace:*", - "@effect/language-service": "0.87.3", - "@effect/tsgo": "^0.47.2", - "@effect/platform-node": "4.0.2", - "@effect/vitest": "4.0.2", + "@effect/language-service": "0.87.5", + "@effect/tsgo": "^0.56.0", + "@effect/platform-node": "4.0.5", + "@effect/vitest": "4.0.5", "@tsconfig/strictest": "^2.0.8", "@types/node": "25.9.1", "@typescript-eslint/eslint-plugin": "8.60.0", "@typescript-eslint/parser": "8.60.0", "@typescript/native-preview": "7.0.0-dev.20260626.1", "dprint": "^0.54.0", - "effect": "4.0.2", + "effect": "4.0.5", "effect-app": "workspace:*", "eslint": "^10.4.1", "json5": "^2.2.3", "lint-staged": "^17.3.0", "madge": "^8.0.0", "npm-check-updates": "^22.2.1", - "oxlint": "1.82.0", - "oxlint-tsgolint": "7.0.2001", + "oxlint": "1.89.0", + "oxlint-tsgolint": "7.0.2004", "pkg-pr-new": "0.0.75", "ts-plugin-sort-import-suggestions": "^1.0.4", "typescript": "~6.0.3", "vite": "^8.0.15", - "vitest": "^4.1.7" + "vitest": "^5.0.5" } } diff --git a/packages/cli/package.json b/packages/cli/package.json index a3f9aa043d..3c65802e76 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -14,15 +14,15 @@ "effect-app-cli": "./bin.js" }, "dependencies": { - "@effect/platform-node": "4.0.2", - "effect": "4.0.2", + "@effect/platform-node": "4.0.5", + "effect": "4.0.5", "js-yaml": "4.2.0" }, "devDependencies": { "@types/js-yaml": "^4.0.9", "@types/node": "25.9.1", "typescript": "npm:@typescript/native-preview@beta", - "vitest": "^4.1.7" + "vitest": "^5.0.5" }, "typesVersions": { "*": { diff --git a/packages/e2e/package.json b/packages/e2e/package.json index 875d810d2b..8f1ef7d0cf 100644 --- a/packages/e2e/package.json +++ b/packages/e2e/package.json @@ -10,15 +10,15 @@ "effect-app": "workspace:*" }, "devDependencies": { - "@effect/atom-vue": "^4.0.2", - "@effect/platform-node": "4.0.2", - "@effect/vitest": "4.0.2", + "@effect/atom-vue": "^4.0.5", + "@effect/platform-node": "4.0.5", + "@effect/vitest": "4.0.5", "@tanstack/vue-query": "5.96.2", "@types/node": "25.9.1", "@vitejs/plugin-vue": "^6.0.7", - "effect": "^4.0.2", + "effect": "^4.0.5", "typescript": "~6.0.3", - "vitest": "^4.1.7", + "vitest": "^5.0.5", "vue": "^3.5.35" }, "scripts": { diff --git a/packages/effect-app/package.json b/packages/effect-app/package.json index df54edc9d6..161723461c 100644 --- a/packages/effect-app/package.json +++ b/packages/effect-app/package.json @@ -22,10 +22,10 @@ "@types/validator": "^13.15.10", "fast-check": "^4.9.0", "typescript": "~6.0.3", - "vitest": "^4.1.7" + "vitest": "^5.0.5" }, "peerDependencies": { - "effect": "^4.0.2" + "effect": "^4.0.5" }, "typesVersions": { "*": { diff --git a/packages/effect-app/src/Schema.ts b/packages/effect-app/src/Schema.ts index 71afd00561..01eecece89 100644 --- a/packages/effect-app/src/Schema.ts +++ b/packages/effect-app/src/Schema.ts @@ -466,8 +466,28 @@ type TaggedUnionWithTags = S.toTaggedUnion<" ) => PropertyGuardsFor } +// Mirrors effect `Schema.toTaggedUnion`: duplicate `_tag` values, including `1` and `"1"`, are rejected. +type TaggedFor = { readonly Type: { readonly [K in Tag]: PropertyKey } } +type FlattenTaggedMembers = Schemas extends readonly [infer Head, ...infer Tail] + ? Head extends S.Union ? [...FlattenTaggedMembers, ...FlattenTaggedMembers] + : [Head, ...FlattenTaggedMembers] + : [] +type DiscriminantKey = T extends number ? `${T}` : T +type EnsureUniqueDiscriminants, Seen = never> = Tags extends + readonly [infer Head extends PropertyKey, ...infer Tail extends ReadonlyArray] + ? [DiscriminantKey & Seen] extends [never] ? EnsureUniqueDiscriminants> + : never + : unknown +type TaggedDiscriminants< + Members extends ReadonlyArray>, + Flattened extends ReadonlyArray> = FlattenTaggedMembers +> = { readonly [I in keyof Flattened]: Flattened[I]["Type"]["_tag"] } +type UniqueTaggedUnion = + & S.Union + & NoInfer>> + const extendTaggedUnionWithTags = ( - schema: S.Union + schema: UniqueTaggedUnion ): TaggedUnionWithTags => extendM(schema.pipe(S.toTaggedUnion("_tag")), (tagged) => { const makeGuards = (property: string) => { @@ -491,9 +511,13 @@ const extendTaggedUnionWithTags = ( }) export const ExtendTaggedUnion = ( - schema: S.Union + schema: UniqueTaggedUnion ): TaggedUnionWithTags => extendTaggedUnionWithTags(schema) export const TaggedUnion = < Members extends TaggedUnionMembers ->(members: Members): TaggedUnionWithTags => extendTaggedUnionWithTags(S.Union(members)) +>( + members: Members & NoInfer>> +): TaggedUnionWithTags => + // `Schema.Union` does not carry the uniqueness proof checked on `members`. + extendTaggedUnionWithTags(S.Union(members) as UniqueTaggedUnion) diff --git a/packages/effect-app/test/special.test.ts b/packages/effect-app/test/special.test.ts index 9931c7757d..a5a1315dcc 100644 --- a/packages/effect-app/test/special.test.ts +++ b/packages/effect-app/test/special.test.ts @@ -1108,7 +1108,8 @@ describe("Post-processing integration — real Effect Schema types", () => { const doc = specialJsonSchemaDocument(AppSchema.PositiveInt) expect(doc.definitions["PositiveInt"]).toStrictEqual({ type: "integer", - exclusiveMinimum: 0 + exclusiveMinimum: 0, + maximum: Number.MAX_SAFE_INTEGER }) }) @@ -1152,7 +1153,8 @@ describe("Post-processing integration — real Effect Schema types", () => { const doc = specialJsonSchemaDocument(AppSchema.NonNegativeInt) expect(doc.definitions["NonNegativeInt"]).toStrictEqual({ type: "integer", - minimum: 0 + minimum: 0, + maximum: Number.MAX_SAFE_INTEGER }) }) diff --git a/packages/eslint-shared-config/src/oxlintrc.json b/packages/eslint-shared-config/src/oxlintrc.json index b0efaff4f5..14004008c0 100644 --- a/packages/eslint-shared-config/src/oxlintrc.json +++ b/packages/eslint-shared-config/src/oxlintrc.json @@ -117,6 +117,7 @@ // Surplus type-aware rules pulled in by `correctness/suspicious/perf` categories // that were NOT enabled in the original eslint config. Disabled to match prior baseline. + "typescript/no-generated-empty-object-type": "off", "typescript/no-unsafe-type-assertion": "off", "typescript/no-unsafe-enum-comparison": "off", "typescript/no-unnecessary-type-arguments": "off", diff --git a/packages/infra/package.json b/packages/infra/package.json index 4e7b53aee9..2814b8c923 100644 --- a/packages/infra/package.json +++ b/packages/infra/package.json @@ -21,7 +21,7 @@ "devDependencies": { "@azure/cosmos": "^4.9.3", "@azure/service-bus": "^7.9.5", - "@effect/sql-sqlite-node": "4.0.2", + "@effect/sql-sqlite-node": "4.0.5", "@sentry/opentelemetry": "10.55.0", "@types/better-sqlite3": "^7.6.13", "@types/node": "25.9.1", @@ -34,17 +34,17 @@ "redis": "^3.1.2", "redlock": "^4.2.0", "typescript": "~6.0.3", - "vitest": "^4.1.7" + "vitest": "^5.0.5" }, "peerDependencies": { "@azure/cosmos": "^4.9.3", "@azure/service-bus": "^7.9.5", - "@effect/vitest": "^4.0.2", + "@effect/vitest": "^4.0.5", "@sendgrid/helpers": "^8.0.0", "@sendgrid/mail": "^8.1.6", "@sentry/node": "10.55.0", "@sentry/opentelemetry": "10.55.0", - "effect": "^4.0.2", + "effect": "^4.0.5", "jwt-decode": "^4.0.0", "redis": "^3.1.2", "redlock": "^4.2.0" diff --git a/packages/vue-components/package.json b/packages/vue-components/package.json index 872c17bb25..9799b72037 100644 --- a/packages/vue-components/package.json +++ b/packages/vue-components/package.json @@ -25,7 +25,7 @@ }, "peerDependencies": { "@mdi/js": "^7.4.47", - "effect": "^4.0.2", + "effect": "^4.0.5", "intl-messageformat": "^11.2.7", "mdi-js": "^1.0.1", "primeflex": "^4.0.0", @@ -52,7 +52,7 @@ "vite": "^8.0.15", "vite-plugin-css-injected-by-js": "^5.0.1", "vitepress": "^1.6.4", - "vitest": "^4.1.7", + "vitest": "^5.0.5", "vue-router": "^5.1.0", "vue-toastification": "^2.0.0-rc.5", "vue-tsc": "^3.3.3", diff --git a/packages/vue/package.json b/packages/vue/package.json index 527fbe2337..1bf39b12d6 100644 --- a/packages/vue/package.json +++ b/packages/vue/package.json @@ -18,21 +18,21 @@ "query-string": "^9.4.0" }, "peerDependencies": { - "@effect/atom-vue": "^4.0.2", - "@effect/platform-browser": "^4.0.2", + "@effect/atom-vue": "^4.0.5", + "@effect/platform-browser": "^4.0.5", "@sentry/browser": "^10.55.0", - "effect": "^4.0.2", + "effect": "^4.0.5", "vue": "^3.5.35" }, "devDependencies": { - "@effect/vitest": "4.0.2", + "@effect/vitest": "4.0.5", "@formatjs/icu-messageformat-parser": "^3.5.10", "@types/node": "25.9.1", "@vitejs/plugin-vue": "^6.0.7", "intl-messageformat": "^11.2.7", "typescript": "~6.0.3", "vite": "^8.0.15", - "vitest": "^4.1.7" + "vitest": "^5.0.5" }, "typesVersions": { "*": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4eff72fcda..ce2ed065ec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -251,17 +251,17 @@ importers: specifier: workspace:* version: link:packages/infra "@effect/language-service": - specifier: 0.87.3 - version: 0.87.3 + specifier: 0.87.5 + version: 0.87.5 "@effect/platform-node": - specifier: 4.0.2 - version: 4.0.2(effect@4.0.2)(redis@6.2.1(@opentelemetry/api@1.9.1)) + specifier: 4.0.5 + version: 4.0.5(effect@4.0.5)(redis@6.2.1(@opentelemetry/api@1.9.1)) "@effect/tsgo": - specifier: ^0.47.2 - version: 0.47.2 + specifier: ^0.56.0 + version: 0.56.0 "@effect/vitest": - specifier: 4.0.2 - version: 4.0.2(effect@4.0.2)(vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))) + specifier: 4.0.5 + version: 4.0.5(effect@4.0.5)(vitest@5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))) "@tsconfig/strictest": specifier: ^2.0.8 version: 2.0.8 @@ -270,10 +270,10 @@ importers: version: 25.9.1 "@typescript-eslint/eslint-plugin": specifier: 8.60.0 - version: 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + version: 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript-eslint/parser": specifier: 8.60.0 - version: 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + version: 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript/native-preview": specifier: 7.0.0-dev.20260626.1 version: 7.0.0-dev.20260626.1 @@ -281,14 +281,14 @@ importers: specifier: ^0.54.0 version: 0.54.0 effect: - specifier: 4.0.2 - version: 4.0.2 + specifier: 4.0.5 + version: 4.0.5 effect-app: specifier: workspace:* version: link:packages/effect-app eslint: specifier: ^10.4.1 - version: 10.4.1(supports-color@8.1.1) + version: 10.4.1(supports-color@7.2.0) json5: specifier: ^2.2.3 version: 2.2.3 @@ -297,16 +297,16 @@ importers: version: 17.3.0 madge: specifier: ^8.0.0 - version: 8.0.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + version: 8.0.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) npm-check-updates: specifier: ^22.2.1 version: 22.2.1 oxlint: - specifier: 1.82.0 - version: 1.82.0(oxlint-tsgolint@7.0.2001) + specifier: 1.89.0 + version: 1.89.0(oxlint-tsgolint@7.0.2004) oxlint-tsgolint: - specifier: 7.0.2001 - version: 7.0.2001 + specifier: 7.0.2004 + version: 7.0.2004 pkg-pr-new: specifier: 0.0.75 version: 0.0.75 @@ -318,19 +318,19 @@ importers: version: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) vite: specifier: ^8.0.15 - version: 8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0) + version: 8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0) vitest: - specifier: ^4.1.7 - version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) + specifier: ^5.0.5 + version: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) packages/cli: dependencies: "@effect/platform-node": - specifier: 4.0.2 - version: 4.0.2(effect@4.0.2)(redis@6.2.1(@opentelemetry/api@1.9.1)) + specifier: 4.0.5 + version: 4.0.5(effect@4.0.5)(redis@6.2.1(@opentelemetry/api@1.9.1)) effect: - specifier: 4.0.2 - version: 4.0.2 + specifier: 4.0.5 + version: 4.0.5 js-yaml: specifier: 4.2.0 version: 4.2.0 @@ -345,10 +345,10 @@ importers: specifier: npm:@typescript/native-preview@beta version: "@typescript/native-preview@7.0.0-dev.20260421.2" vitest: - specifier: ^4.1.7 - version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) - publishDirectory: .publish + specifier: ^5.0.5 + version: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) linkDirectory: false + publishDirectory: .publish packages/e2e: dependencies: @@ -363,14 +363,14 @@ importers: version: link:../effect-app devDependencies: "@effect/atom-vue": - specifier: ^4.0.2 - version: 4.0.2(effect@4.0.2)(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) + specifier: ^4.0.5 + version: 4.0.5(effect@4.0.5)(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) "@effect/platform-node": - specifier: 4.0.2 - version: 4.0.2(effect@4.0.2)(redis@6.2.1(@opentelemetry/api@1.9.1)) + specifier: 4.0.5 + version: 4.0.5(effect@4.0.5)(redis@6.2.1(@opentelemetry/api@1.9.1)) "@effect/vitest": - specifier: 4.0.2 - version: 4.0.2(effect@4.0.2)(vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))) + specifier: 4.0.5 + version: 4.0.5(effect@4.0.5)(vitest@5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))) "@tanstack/vue-query": specifier: 5.96.2 version: 5.96.2(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) @@ -381,14 +381,14 @@ importers: specifier: ^6.0.7 version: 6.0.7(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) effect: - specifier: ^4.0.2 - version: 4.0.2 + specifier: ^4.0.5 + version: 4.0.5 typescript: specifier: ~6.0.3 version: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) vitest: - specifier: ^4.1.7 - version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) + specifier: ^5.0.5 + version: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) vue: specifier: ^3.5.35 version: 3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) @@ -399,8 +399,8 @@ importers: specifier: ^2.0.8 version: 2.0.8 effect: - specifier: ^4.0.2 - version: 4.0.2 + specifier: ^4.0.5 + version: 4.0.5 nanoid: specifier: ^5.1.11 version: 5.1.11 @@ -433,10 +433,10 @@ importers: specifier: ~6.0.3 version: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) vitest: - specifier: ^4.1.7 - version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) - publishDirectory: .publish + specifier: ^5.0.5 + version: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) linkDirectory: false + publishDirectory: .publish packages/eslint-codegen-model: dependencies: @@ -458,15 +458,15 @@ importers: version: link:../effect-app madge: specifier: 8.0.0 - version: 8.0.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + version: 8.0.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) oxlint: specifier: 1.67.0 - version: 1.67.0(oxlint-tsgolint@0.23.0) + version: 1.67.0(oxlint-tsgolint@7.0.2004) typescript: specifier: ~6.0.3 version: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) - publishDirectory: .publish linkDirectory: false + publishDirectory: .publish packages/eslint-shared-config: dependencies: @@ -481,16 +481,16 @@ importers: version: link:../eslint-codegen-model "@eslint/eslintrc": specifier: 3.3.5 - version: 3.3.5(supports-color@8.1.1) + version: 3.3.5(supports-color@7.2.0) "@eslint/js": specifier: 10.0.1 - version: 10.0.1(eslint@10.4.1(supports-color@8.1.1)) + version: 10.0.1(eslint@10.4.1(supports-color@7.2.0)) "@typescript-eslint/eslint-plugin": specifier: 8.60.0 - version: 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + version: 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript-eslint/parser": specifier: 8.60.0 - version: 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + version: 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) dprint-plugin-malva: specifier: 0.16.0 version: 0.16.0 @@ -502,22 +502,22 @@ importers: version: 0.6.0 eslint: specifier: ^10.4.1 - version: 10.4.1(supports-color@8.1.1) + version: 10.4.1(supports-color@7.2.0) eslint-plugin-formatjs: specifier: 6.4.13 - version: 6.4.13(eslint@10.4.1(supports-color@8.1.1)) + version: 6.4.13(eslint@10.4.1(supports-color@7.2.0)) eslint-plugin-import: specifier: 2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1) + version: 2.32.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0) eslint-plugin-sort-destructure-keys: specifier: 3.0.0 - version: 3.0.0(eslint@10.4.1(supports-color@8.1.1)) + version: 3.0.0(eslint@10.4.1(supports-color@7.2.0)) eslint-plugin-unused-imports: specifier: 4.4.1 - version: 4.4.1(@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1)) + version: 4.4.1(@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0)) eslint-plugin-vue: specifier: 10.9.1 - version: 10.9.1(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(vue-eslint-parser@10.4.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)) + version: 10.9.1(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(vue-eslint-parser@10.4.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)) globals: specifier: 17.6.0 version: 17.6.0 @@ -535,13 +535,13 @@ importers: version: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) vue-eslint-parser: specifier: 10.4.0 - version: 10.4.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1) + version: 10.4.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0) packages/infra: dependencies: "@effect/vitest": - specifier: ^4.0.2 - version: 4.0.2(effect@4.0.2)(vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))) + specifier: ^4.0.5 + version: 4.0.5(effect@4.0.5)(vitest@5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))) "@faker-js/faker": specifier: ^8.4.1 version: 8.4.1 @@ -550,13 +550,13 @@ importers: version: 8.0.0 "@sendgrid/mail": specifier: ^8.1.6 - version: 8.1.6(patch_hash=3d2dd1cd5f52d3eef1772e4be48776258a596f9277c00adf0a471f54fcd3e21a)(debug@4.4.3(supports-color@8.1.1)) + version: 8.1.6(patch_hash=3d2dd1cd5f52d3eef1772e4be48776258a596f9277c00adf0a471f54fcd3e21a)(debug@4.4.3(supports-color@7.2.0)) "@sentry/node": specifier: 10.55.0 - version: 10.55.0(supports-color@8.1.1) + version: 10.55.0(supports-color@7.2.0) effect: - specifier: ^4.0.2 - version: 4.0.2 + specifier: ^4.0.5 + version: 4.0.5 effect-app: specifier: workspace:* version: link:../effect-app @@ -578,13 +578,13 @@ importers: devDependencies: "@azure/cosmos": specifier: ^4.9.3 - version: 4.9.3(supports-color@8.1.1) + version: 4.9.3(supports-color@7.2.0) "@azure/service-bus": specifier: ^7.9.5 - version: 7.9.5(supports-color@8.1.1) + version: 7.9.5(supports-color@7.2.0) "@effect/sql-sqlite-node": - specifier: 4.0.2 - version: 4.0.2(effect@4.0.2) + specifier: 4.0.5 + version: 4.0.5(effect@4.0.5) "@sentry/opentelemetry": specifier: 10.55.0 version: 10.55.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) @@ -622,19 +622,19 @@ importers: specifier: ~6.0.3 version: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) vitest: - specifier: ^4.1.7 - version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) - publishDirectory: .publish + specifier: ^5.0.5 + version: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) linkDirectory: false + publishDirectory: .publish packages/vue: dependencies: "@effect/atom-vue": - specifier: ^4.0.2 - version: 4.0.2(effect@4.0.2)(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) + specifier: ^4.0.5 + version: 4.0.5(effect@4.0.5)(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) "@effect/platform-browser": - specifier: ^4.0.2 - version: 4.0.2(effect@4.0.2) + specifier: ^4.0.5 + version: 4.0.5(effect@4.0.5) "@formatjs/intl": specifier: ^4.1.12 version: 4.1.12 @@ -651,8 +651,8 @@ importers: specifier: ^5.4.4 version: 5.4.4 effect: - specifier: ^4.0.2 - version: 4.0.2 + specifier: ^4.0.5 + version: 4.0.5 effect-app: specifier: workspace:* version: link:../effect-app @@ -664,8 +664,8 @@ importers: version: 3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) devDependencies: "@effect/vitest": - specifier: 4.0.2 - version: 4.0.2(effect@4.0.2)(vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))) + specifier: 4.0.5 + version: 4.0.5(effect@4.0.5)(vitest@5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))) "@formatjs/icu-messageformat-parser": specifier: ^3.5.10 version: 3.5.10 @@ -685,10 +685,10 @@ importers: specifier: ^8.0.15 version: 8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0) vitest: - specifier: ^4.1.7 - version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) - publishDirectory: .publish + specifier: ^5.0.5 + version: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) linkDirectory: false + publishDirectory: .publish packages/vue-components: dependencies: @@ -705,8 +705,8 @@ importers: specifier: ^1.32.0 version: 1.32.0(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) effect: - specifier: ^4.0.2 - version: 4.0.2 + specifier: ^4.0.5 + version: 4.0.5 effect-app: specifier: workspace:* version: link:../effect-app @@ -787,8 +787,8 @@ importers: specifier: ^1.6.4 version: 1.6.4(@algolia/client-search@5.46.3)(@types/node@25.9.1)(axios@1.13.2(debug@4.4.3(supports-color@8.1.1)))(change-case@5.4.4)(jwt-decode@4.0.0)(lightningcss@1.32.0)(postcss@8.5.15)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.100.0)(search-insights@2.17.3)(terser@5.45.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) vitest: - specifier: ^4.1.7 - version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) + specifier: ^5.0.5 + version: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) vue-router: specifier: ^5.1.0 version: 5.1.0(@vue/compiler-sfc@3.5.35)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) @@ -1393,112 +1393,112 @@ packages: cpu: [x64] os: [win32] - "@effect/atom-vue@4.0.2": + "@effect/atom-vue@4.0.5": resolution: { - integrity: sha512-ftfF/0tHKEVHsT+K70nfZehcB10Y9I5AyvWSKSc3DqOonUf6y65SGT4+bhlp1gitfo8fJpXRRta+nH+KpK7ppg==, + integrity: sha512-GYnHSbdDE+2Q3AgQSNIxw0lsAUQngeP5RCW2xW9YH8KZ0eLq5DNUk3aHZyZy72M2KgM9dEU/z//vwMDBDB/c2g==, } peerDependencies: - effect: ^4.0.2 + effect: ^4.0.5 vue: ^3.5.35 - "@effect/language-service@0.87.3": + "@effect/language-service@0.87.5": resolution: { - integrity: sha512-g1OmRBZF5chbW9QMNoirPo5Bb4zzU2HfP88tR7/VSZEUxHJ1/qVb8AQ0kUh2ggctLH1I715yCwP4gkw56PTjpQ==, + integrity: sha512-np/zJgk71/PyHxtoqyUKLYcpQhoRBI+L6+1Z0ILk35JSQ/lvXzwlwOwddYZLDkeC4bdF2ukKekqKlla/F88R5w==, } hasBin: true - "@effect/platform-browser@4.0.2": + "@effect/platform-browser@4.0.5": resolution: { - integrity: sha512-juVpWmx+2e5pw3MsMSMzwsQ7sut3exkeweaQToAcn+4PKGNWvItZ72+qAalgRNQE5luPiodP507oe44gC36Vsg==, + integrity: sha512-o3H75xA91nkgIWOcp0XouIxxWxJEOFkTf7gG4qkQtZfy0tq46hJBI0U8jrUqsPruo2vCCNfM0yCoj5AG7F5BMQ==, } peerDependencies: - effect: ^4.0.2 + effect: ^4.0.5 - "@effect/platform-node-shared@4.0.2": + "@effect/platform-node-shared@4.0.5": resolution: { - integrity: sha512-xn8aDw9p/QUPt1Yi0C3HUMcycT+MjHfAe19FDUDrUuzcwq0xxskkamVSqbdykF/Dsuus4aZTsCBZA/vkhHIfbQ==, + integrity: sha512-a8rCdEkfZBGe9C6bsIjxVZuRp73svIyK5IHwHdDAVsvZXjrbkxusfI+rZ8WlX31RP1mKizwI/E72GQTNfdMWHw==, } engines: { node: ">=18.0.0" } peerDependencies: - effect: ^4.0.2 + effect: ^4.0.5 - "@effect/platform-node@4.0.2": + "@effect/platform-node@4.0.5": resolution: { - integrity: sha512-RWesXBQStnFHdD465gR5thFKgXO7FSyCKRZ56nWXB7PedNVzr8vV0nb/3MULLdri493sMz/b/pmGBTb6K8cBjQ==, + integrity: sha512-v4KD5fWvEUa4QmWFpZFbBsRhmfnTP6ETCME2r9ifyXVDPjhfpxpTZl41prjgQFMqZBHdWWCl7YC5ImbXv5ui5g==, } engines: { node: ">=18.0.0" } peerDependencies: - effect: ^4.0.2 + effect: ^4.0.5 redis: ">=5.0.0 <7.0.0" - "@effect/sql-sqlite-node@4.0.2": + "@effect/sql-sqlite-node@4.0.5": resolution: { - integrity: sha512-QjhQ6yetczGE08ZV/05Y4Cj7GNGswloRZuk2cZ4tl84C91398Ho0PhDLexihO2RHBTE1YjpUW8Mdl4KH41I/LQ==, + integrity: sha512-SHza5qNwiI4dRtUk45wvUfvZq7vB950DW2wD6npzt2aH/tesFfPlZJSDBIvwhazoK+gvDknBOONfKyFZsIF+tg==, } peerDependencies: - effect: ^4.0.2 + effect: ^4.0.5 - "@effect/tsgo-darwin-arm64@0.47.2": + "@effect/tsgo-darwin-arm64@0.56.0": resolution: { - integrity: sha512-sLYKt201VdTjSHG3rbyIdpLMNGEMiArm0OgO7kYfnA0yRV0ux0blgcucf97bx90gIvDJFSSL17QCSDPGs9jsKQ==, + integrity: sha512-08yYRU3OOw/jKzy582EF741xKvLJ2HK6GO+L2zuSR97b61ES7fER2fxg1xp4mv8u2Fc3bBRvk7026GzdKEGFgw==, } cpu: [arm64] os: [darwin] - "@effect/tsgo-darwin-x64@0.47.2": + "@effect/tsgo-darwin-x64@0.56.0": resolution: { - integrity: sha512-gW0fdFjSIacCDOjLa+vS/xWmyElbM0jX3cCTlKXGzNCyMKsP/T0MkvT2GZO/njB2jIt/XXG9qEQ5FE/Rcqt7Zg==, + integrity: sha512-UQvYvVaam+EVMYm9gfHBx1WpKwLlW+ptjb2UD7qGhZdg+GzxMbl26AhuuqV2t/dN9shZ6EcFE2+++ThISMp/9g==, } cpu: [x64] os: [darwin] - "@effect/tsgo-linux-arm64@0.47.2": + "@effect/tsgo-linux-arm64@0.56.0": resolution: { - integrity: sha512-hA3SoKGuLd0HNqJ34QcYEWwpE6tvit3xpKupwj1TaPtHpLLGdtSF7czBIknp6kR8fOvnuYLjB6aEkxXmJsTVWg==, + integrity: sha512-zzzo/w7lLqiCMuJOI+jbjIuhHob3ccmth1bD9m1E98ukMuHhIqQMOXKU9EreoQkCGeoVrxGqHbXkl6E/+68/Sg==, } cpu: [arm64] os: [linux] - "@effect/tsgo-linux-arm@0.47.2": + "@effect/tsgo-linux-arm@0.56.0": resolution: { - integrity: sha512-GT8fgQ3Pnzr0ax/AtYptztVquLAWeWoyLvQTpfI5APrs+Me+/rSwOLSA7//17ZVmNYbcGbKImX8laUYeDqByNQ==, + integrity: sha512-3WuPwP8vQPqKVpfGmKlnguuAZb7NGUyAhIHQjZnaINU6Aim7WczOy2WOmKjDPSKRlonU2WyYT+Q5T3B7f0VTLw==, } cpu: [arm] os: [linux] - "@effect/tsgo-linux-x64@0.47.2": + "@effect/tsgo-linux-x64@0.56.0": resolution: { - integrity: sha512-vELwVsUQ5VlM2jbvv7zaIPOkFsxmaS0nLqq+p0RodtkQiuScg27febnLClzKAv/Tl6GrXTBz4IBh78aBF2CvbQ==, + integrity: sha512-R0d3dGf8qKPtvjff+J9HL0UjIBIES6xZiU16rMMezI4K52b+DGQkaWi1OX3tSgGivjlV+NSN7UhPJ2pYKufglw==, } cpu: [x64] os: [linux] - "@effect/tsgo-win32-arm64@0.47.2": + "@effect/tsgo-win32-arm64@0.56.0": resolution: { - integrity: sha512-FSwpJp3XaJK9o7cOXtJcYIsvZWR/mrY4ZZyyTuRgphEZju7FwOzLeVhLr9ziyScfmisOpX2i+8v1H+PlMMZ1TQ==, + integrity: sha512-uVaLdXULUZx9U30YxlVu5PBiu+1a+9/UT2Ex7jQpIasnJy1CHWlhMbfCD/+7Ez1vqG5fLOvUESoQu5XSjs3Lnw==, } cpu: [arm64] os: [win32] - "@effect/tsgo-win32-x64@0.47.2": + "@effect/tsgo-win32-x64@0.56.0": resolution: { - integrity: sha512-Lh/N7E2p6E0tBZM+uZ40Hv/AUG81WGtw76H4pLLPAG7wFANwGSx984NwKypXqGtOXBmKqb0R/cYpszDyzbNyYA==, + integrity: sha512-Cf6SDixFTkp7Aoeg2eRwJps/2BG9lvx2m+iVRjUzxdqkTbCCNKmmOAIyDslNZm2sMwaDUw/iN/BPGqxx7xMxww==, } cpu: [x64] os: [win32] - "@effect/tsgo@0.47.2": + "@effect/tsgo@0.56.0": resolution: { - integrity: sha512-mGIelPZhTJg8g+RgiAe7wrB8NLw/lOzPGntAYBBqEJS0/I8ir1/ULKcpFQyuAfPjwkDYrg93KWv1PDGwgsgBIA==, + integrity: sha512-/S5G8RJjtaVjE/RhwFNTvWQwFAQyDGc+3Ig4Oynvlo3gJu8le4MUgM/DBjoiwkwBsQ+BhufGDCBpwojplerGlw==, } hasBin: true - "@effect/vitest@4.0.2": + "@effect/vitest@4.0.5": resolution: { - integrity: sha512-Zb72nu7iUy3rNdBp9J1Xu5oUQGwJ8cOYsUwmYgujj88aqyvASRDjOS01SjlcPViqf77csduetKdCJTVndMNfzw==, + integrity: sha512-q64paZ/i4V2NiRhTyqCmT2KiDbFjlxc2EZrZca8GGt+Nf8844946HyJM5bPk/q+YeRkFSxIrlCs+J+LSfky/wA==, } peerDependencies: - effect: ^4.0.2 + effect: ^4.0.5 vitest: ">=5.0.0 <6.0.0" "@emnapi/core@1.10.0": @@ -2318,6 +2318,11 @@ packages: integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, } + "@jridgewell/sourcemap-codec@1.6.0": + resolution: { + integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==, + } + "@jridgewell/trace-mapping@0.3.31": resolution: { integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, @@ -2916,9 +2921,9 @@ packages: cpu: [arm64] os: [darwin] - "@oxlint-tsgolint/darwin-arm64@7.0.2001": + "@oxlint-tsgolint/darwin-arm64@7.0.2004": resolution: { - integrity: sha512-CUJEdbSZ54+Xy9OXqOhWLTKZKV0BBiV7C2i/ygyVmXtkUNXx5YCzN8DpSSshTAKktoL7S+tnQ/ftFG/i7X896w==, + integrity: sha512-uJk3ttju7Lz+Nv8WG4CsLyewoL1qf/Ny8S8OksJ7Bm/F14Tc9gMfW6arM1PCc57IzH/X/I79YsCWTgxX1FKibQ==, } cpu: [arm64] os: [darwin] @@ -2930,9 +2935,9 @@ packages: cpu: [x64] os: [darwin] - "@oxlint-tsgolint/darwin-x64@7.0.2001": + "@oxlint-tsgolint/darwin-x64@7.0.2004": resolution: { - integrity: sha512-pXfBb5BqONCcgrXQNUZWXgiYmRSWJzd97S8i41VVOh6ut0tyo+cJ5FKFpczDHxiVNfj/3e7c9B4MtztNdpIVCw==, + integrity: sha512-0BFfHTzDxNDFPcu0UZAXT6CyCJHAXM0dZveyDb4KEHa2qF/DSnOKOrmvK/wFuFol9kvijbGM9JfuOsor+zWXRw==, } cpu: [x64] os: [darwin] @@ -2944,9 +2949,9 @@ packages: cpu: [arm64] os: [linux] - "@oxlint-tsgolint/linux-arm64@7.0.2001": + "@oxlint-tsgolint/linux-arm64@7.0.2004": resolution: { - integrity: sha512-roP7zujb/QDPzDwEKsFFpzNHHy91/Y7oX9vQXk78ekyZtcQj1QXDIMH33gjDdHBfRl4K9pZ36xhRgrP4Zr+R8A==, + integrity: sha512-TAehQc+qdRXyDN3nl/r/3/oPrBVrbtrDeGMkFyG6mf+XphpoJ2lAMVFLclyvrVZCw02RbKROjyw8h72XwQQHcw==, } cpu: [arm64] os: [linux] @@ -2958,9 +2963,9 @@ packages: cpu: [x64] os: [linux] - "@oxlint-tsgolint/linux-x64@7.0.2001": + "@oxlint-tsgolint/linux-x64@7.0.2004": resolution: { - integrity: sha512-UDezNqdECVmngu2TPnjaS1YoAmcTaBoI5lV9vk3VahBxoi+I5r9k3iJTT7qZoYWOXTD/7T7bNcwRgrocR6BscQ==, + integrity: sha512-LPunZvm6ZbWPfHMAyfZf9ci3HHvNEzLejO8zdqO3GoVGoSEHqqufHUD7+OgeatVSaJP7uXDJ2HaNOHIoH7go4Q==, } cpu: [x64] os: [linux] @@ -2972,9 +2977,9 @@ packages: cpu: [arm64] os: [win32] - "@oxlint-tsgolint/win32-arm64@7.0.2001": + "@oxlint-tsgolint/win32-arm64@7.0.2004": resolution: { - integrity: sha512-uJZhqB6pdXLuN+AD1F5082byyQti/NPmJA77GtcFlmT2HzRelqbNls3SaIqxpjdFgvSBF9g0yOKGBkGFg7kX8Q==, + integrity: sha512-FVWplzDImWhiuawnIZVETaQecv4GWom6Jv4Fx2xj7hhXXDZ5okEgiw1gTCImHTIQsi2ycC5oSxVwrn69bMh7iw==, } cpu: [arm64] os: [win32] @@ -2986,9 +2991,9 @@ packages: cpu: [x64] os: [win32] - "@oxlint-tsgolint/win32-x64@7.0.2001": + "@oxlint-tsgolint/win32-x64@7.0.2004": resolution: { - integrity: sha512-FkDRm8hx9OwzGQqyWG1tO5QrTLRApff9DzSgpz9QZau37BR8d1VYKOxMLGf6shPZntJFoTwIIJYT68VndYDCog==, + integrity: sha512-7PsxuUx11Ry9DYTWcljTzRbmZY9B6O9fFFfZV+aodQEMy6pfRT3fhoQRv9PtGN/89z1pPz3nFKrsFm6WqNtX7w==, } cpu: [x64] os: [win32] @@ -3001,9 +3006,9 @@ packages: cpu: [arm] os: [android] - "@oxlint/binding-android-arm-eabi@1.82.0": + "@oxlint/binding-android-arm-eabi@1.89.0": resolution: { - integrity: sha512-a3LB+C5Dsj5b/qtmG/mv5WrzuiXEpg1KF5nXWcEvaoN5TYAqkIvxPOwTPp3Jy/FoGpRo8zsTFhMElMXfeoOEzA==, + integrity: sha512-Pflpba5F3gRAQ12sWglRxvWTHEdAusNDvmi4Y5N1T5SY1AGkM7AixOnET8qkrnLJ/F32qAlNokO6eCknT8tmnw==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm] @@ -3017,9 +3022,9 @@ packages: cpu: [arm64] os: [android] - "@oxlint/binding-android-arm64@1.82.0": + "@oxlint/binding-android-arm64@1.89.0": resolution: { - integrity: sha512-OBlhRgNqFblGpGenno/aqOfJLOkQ2B8Ig3iDAalfn0H8hJGZKXPeexCRTDm6uwv6YUjSA9Xnwt1y/Bgj5ZH8uw==, + integrity: sha512-dYmyD1x7LaPlb79vZWUcpTShk8dI9z1I+IubtqrBxWNJaDhQdPHwcsvg7q5StTU4xWyd9AwPfLaTYFZY8NZgtQ==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] @@ -3033,9 +3038,9 @@ packages: cpu: [arm64] os: [darwin] - "@oxlint/binding-darwin-arm64@1.82.0": + "@oxlint/binding-darwin-arm64@1.89.0": resolution: { - integrity: sha512-dsopxqtY5ZdyT9uLHyGt1SyiLop6hi7hWI3PKpePodkRQOkLaCm+OE4fR9CAz9qdfjiFO8531tX/QDyP/psjFg==, + integrity: sha512-Z/oxOPiIqiS7fItRdxaaOEC+6GD3OpGi0IxoR0dMefzQHolsKLzScw2DNcu/5gUPok3tv+G9mslvYB5bo3i0qg==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] @@ -3049,9 +3054,9 @@ packages: cpu: [x64] os: [darwin] - "@oxlint/binding-darwin-x64@1.82.0": + "@oxlint/binding-darwin-x64@1.89.0": resolution: { - integrity: sha512-94Lu0SgTClKColU66g1VDuigV3HkcbkJBnTtZjGYfE8UPugaWDgKrm2icjC6HJVUYler2OXaHP/X0TBy8+CowQ==, + integrity: sha512-eAjTkHSjAxrdCPJxO6y5sPQL5pYLKb2kvxZz9UU7tXnOZk9I/HLtkvx9S7GHY883k+AmL/eC7mqFt+w7WCwk0w==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] @@ -3065,9 +3070,9 @@ packages: cpu: [x64] os: [freebsd] - "@oxlint/binding-freebsd-x64@1.82.0": + "@oxlint/binding-freebsd-x64@1.89.0": resolution: { - integrity: sha512-hne/V06ewhh1i0w8+l7GDNROAGCGPmyFuOwiP7YTRu0JycyStJ4785dmF8xU5p0uUwt2emvIF9vc7Xjis+cJ0g==, + integrity: sha512-0lNCA9Tl1n1FKpqy2/9ckp0kIuSrtJ/l9bMRgaEhOtM7TsOHshFuwOcvW8oA9teXLMOJT61LjEKWiaHDFGxF/w==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] @@ -3081,9 +3086,9 @@ packages: cpu: [arm] os: [linux] - "@oxlint/binding-linux-arm-gnueabihf@1.82.0": + "@oxlint/binding-linux-arm-gnueabihf@1.89.0": resolution: { - integrity: sha512-aWY2xtbZf1LneW9Qsv/n2Sp8gOu74JrlQzEtj4coHX2SHFrCfhmAumaU+sI/A5nr+yoTRTSmI/pL2s6ADlNSkw==, + integrity: sha512-OTFEvi9W+JczaZD1Caj17SGCoW8H7TE+fvx0D7ATEWa1Lohn91UMxFQ6r145SiGy/yCxeIwptMys/RAM7gSVSQ==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm] @@ -3097,9 +3102,9 @@ packages: cpu: [arm] os: [linux] - "@oxlint/binding-linux-arm-musleabihf@1.82.0": + "@oxlint/binding-linux-arm-musleabihf@1.89.0": resolution: { - integrity: sha512-Fe+TtXCXMh/5f7kWlZ2VAwsMumZWtraFlKVk1NJlL52/beGwfDE7ov+/8gVirHzWokzGu7X65hSPq0ucPDskWQ==, + integrity: sha512-fRxgNHvBLswj6MrhW2uBq5UDhPRQlCbHeq/Nf8yuG9zOxhDsXqX/mi2PX1axgsQxMm88el7HLiJAzglAnflYxw==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm] @@ -3114,9 +3119,9 @@ packages: os: [linux] libc: [glibc] - "@oxlint/binding-linux-arm64-gnu@1.82.0": + "@oxlint/binding-linux-arm64-gnu@1.89.0": resolution: { - integrity: sha512-6azCZ6OJudlvipNttXCCQcyeFfcJ/NvUZdSN1z8elo73kCHtyQC7WTiUcSjWYvJ1jaq9KDUyMAoAS/vNzhBomA==, + integrity: sha512-v9ENzHvwrQoYSWTtviH1pOYc7R9UovDxVofnck50cNmPihRRTcrg5X0UlRbLOZ7IVtxPOlh2hb7kDO+FpE8SfQ==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] @@ -3132,9 +3137,9 @@ packages: os: [linux] libc: [musl] - "@oxlint/binding-linux-arm64-musl@1.82.0": + "@oxlint/binding-linux-arm64-musl@1.89.0": resolution: { - integrity: sha512-PLEaSD8IAIIlwW4dwOd9YaxuxeOpwiXL4J24rcnE4iNtyM5j9Q9/3+gti08oXpx0u2ygNjRDx9xjWWpQonuJEw==, + integrity: sha512-vfffe8mQ484AzVadlUOFpgL+JDwhvs9hrzxTgQP1FVfi4ZEUUYeffXlzC9dFV7Dgnu5s/KrNKvfmG6HxBd/ISQ==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] @@ -3150,9 +3155,9 @@ packages: os: [linux] libc: [glibc] - "@oxlint/binding-linux-ppc64-gnu@1.82.0": + "@oxlint/binding-linux-ppc64-gnu@1.89.0": resolution: { - integrity: sha512-D94em/BwknNTn4vqxjHh5wb2oL566eFhArabqKIr0cNZMHOJuiraFp1A8tXpH05bbE5tqwEfLXTI0MWEGtn3Dw==, + integrity: sha512-Buonlp4hVS7RGNP5M7bPpGNQrenyzA2C64JcO/oz9C1c6dGOXJ7VEAnaiAMY7voou0JYyCJdvDVlFQc5DZX3DQ==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [ppc64] @@ -3168,9 +3173,9 @@ packages: os: [linux] libc: [glibc] - "@oxlint/binding-linux-riscv64-gnu@1.82.0": + "@oxlint/binding-linux-riscv64-gnu@1.89.0": resolution: { - integrity: sha512-MOprxBaoYU2D4VgxXCl3ghydThWtx7Um1lL51kGYNeQ5Al7WzsH7/tqGdNtbLrIWnjq3bsm13+nz/gRIxjrOXw==, + integrity: sha512-1eVwJJrJ3lYIPT+cm7BcBBZZXY6IQZP/oyonaruTor/MrVyWOpvnwt1oD5CLdsHg5aVBIxXodQSvt+1gK6ck5w==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [riscv64] @@ -3186,9 +3191,9 @@ packages: os: [linux] libc: [musl] - "@oxlint/binding-linux-riscv64-musl@1.82.0": + "@oxlint/binding-linux-riscv64-musl@1.89.0": resolution: { - integrity: sha512-5h55QsfJ/luDXZzC20k6SNOY1Az+dCP9WvntKtcUWh2JhckAdwApY2ZusaBTwLENnReXU+A2fJtSrYvZJNKNPg==, + integrity: sha512-fRQQsKUGShdEL5Fl9o9uhj3grkZbeXKLv0icQ5tspUCNYSDy8wzzEcP1WC2bKdTQ0rSszbKlO3iiHORxV22DLg==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [riscv64] @@ -3204,9 +3209,9 @@ packages: os: [linux] libc: [glibc] - "@oxlint/binding-linux-s390x-gnu@1.82.0": + "@oxlint/binding-linux-s390x-gnu@1.89.0": resolution: { - integrity: sha512-IE8NJNLlHr0CaXyGJPGVn0eTkUyoj1I2UfA8x7I4PSOYKsQ/6btVC7Pywrj5onk0cMH25r6Z38SoN3AvE5Zuog==, + integrity: sha512-dEtYjIy6+fHcjKklsmtmMkZRhwHr2UbzjmpvuPtQYSeN9awQ2hx5JLms5Wvri+8P/NZtD8v5hfgHALUql+/Ycg==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [s390x] @@ -3222,9 +3227,9 @@ packages: os: [linux] libc: [glibc] - "@oxlint/binding-linux-x64-gnu@1.82.0": + "@oxlint/binding-linux-x64-gnu@1.89.0": resolution: { - integrity: sha512-XUUUxaBo9XKl+J1B9EmP1cTGQPddzeURvoGkfwh/94PGnbW+hBprDljneoI2M1jzC1bzrIV3ihc7iM9UXl8+tg==, + integrity: sha512-hqjwIj5KOYM8Wjef/p7IruNi1iByLhSzbMBk62y22P/E8q7Jj0Pp+DeUTKTRYyZYCDtU1wEGlnWOnttHbyNIww==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] @@ -3240,9 +3245,9 @@ packages: os: [linux] libc: [musl] - "@oxlint/binding-linux-x64-musl@1.82.0": + "@oxlint/binding-linux-x64-musl@1.89.0": resolution: { - integrity: sha512-SWLSFulX9TDuH6yvbPYp4+VNn6jkkIvvI+KiujDM5rWBRHEfkesCC/pCneIIUr6ovkxZ5fRtpi2v5Cz5FrMJZg==, + integrity: sha512-iAQN3e6o9UgUCcdGwqRx/jYcKbG3HK7ur3rH6lTqVcQeNGZ85AeWIg6cgn/edwFQ0ofEZZItMwkzyCVTahnvEA==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] @@ -3257,9 +3262,9 @@ packages: cpu: [arm64] os: [openharmony] - "@oxlint/binding-openharmony-arm64@1.82.0": + "@oxlint/binding-openharmony-arm64@1.89.0": resolution: { - integrity: sha512-BQy35f6ZUdNr9a6c7B7orxQTcLjByGT2z3WAgmRovpRwmPYAaJ+NTplmMzhdjdJ4qSchfMNZy/Ukg+qRg6zseQ==, + integrity: sha512-MNxjEByz3N/7Q4qFQuPWvc14TpN9LoD3pECEDsJTZbP/wyB7U+hduUXEl7QAbbgVezFwsb9sWtNUO6XVBndOhg==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] @@ -3273,9 +3278,9 @@ packages: cpu: [arm64] os: [win32] - "@oxlint/binding-win32-arm64-msvc@1.82.0": + "@oxlint/binding-win32-arm64-msvc@1.89.0": resolution: { - integrity: sha512-V4QhSTg5gctZue8RJjsGi7NpQPThr/p1/HfmiMC5kfe1KFEup9SQRVub4A6kijQjdHfxj7bLL1KO3QO7/5bwMQ==, + integrity: sha512-xxe+i9wfuFso/VnoL4mfj0UlzE+cfCFiUB06vkXCMyQdgVVmItF5FfAF4tATAktSU6uHruWR+FjqvAT9cHZZzg==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [arm64] @@ -3289,9 +3294,9 @@ packages: cpu: [ia32] os: [win32] - "@oxlint/binding-win32-ia32-msvc@1.82.0": + "@oxlint/binding-win32-ia32-msvc@1.89.0": resolution: { - integrity: sha512-TUSCLaKB2yktpFAJ/r3HAUYsaV/3DT7JS4iNKyoh3a9YNwD0UG7Ezh4D8m23654vQcU6P/RQrCAjRPKe4peP/A==, + integrity: sha512-saFy07cO94E664glwgLmKLI40HgTL1PY86y4T6+ud4niX4H0Kdqjcmqmjps7mQNdBytV5guGbXDdyQtRfeLbLA==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [ia32] @@ -3305,9 +3310,9 @@ packages: cpu: [x64] os: [win32] - "@oxlint/binding-win32-x64-msvc@1.82.0": + "@oxlint/binding-win32-x64-msvc@1.89.0": resolution: { - integrity: sha512-VTVoRIWJTb+wvUX8EYoPArfFH02whuR10goFXE/LHRRX33ajRrFgqbcONXZMiF4C5rnattfkm87HqYn8jb8hmQ==, + integrity: sha512-hLFJ/o0f/dTJh/EW0vmcbREYSQO9tYgfiAAlsOkiLFiJuRRWvYtFELUXN5o2ijpSo/tlO1n+YlWN58tZwPG18A==, } engines: { node: ^20.19.0 || >=22.12.0 } cpu: [x64] @@ -3972,11 +3977,6 @@ packages: integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==, } - "@standard-schema/spec@1.1.0": - resolution: { - integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==, - } - "@storybook/builder-vite@10.4.1": resolution: { integrity: sha512-/oyQrXoNOqN8SW5hNnYP+I1uvgFxKxWXj/EP6NXYzc5SQwImofgru+D2+6gDhL0+Q//+Hx05DJoQO2omvUJ8bQ==, @@ -4558,17 +4558,12 @@ packages: integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==, } - "@vitest/expect@4.1.7": + "@vitest/mocker@5.0.5": resolution: { - integrity: sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==, - } - - "@vitest/mocker@4.1.7": - resolution: { - integrity: sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==, + integrity: sha512-xLL3lkDegJZw+MGoGaCCsFayDZthGgpAtr3Vziyfc4p7xH89K7KRPcRBBh/kEYm0Aqkt5DtTmkYpBtRV/FrHZg==, } peerDependencies: - msw: ^2.4.9 + msw: ^2.4.9 || ^3.0.0 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: @@ -4581,29 +4576,14 @@ packages: integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==, } - "@vitest/pretty-format@4.1.7": - resolution: { - integrity: sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==, - } - - "@vitest/runner@4.1.7": - resolution: { - integrity: sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==, - } - - "@vitest/snapshot@4.1.7": - resolution: { - integrity: sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==, - } - "@vitest/spy@3.2.4": resolution: { integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==, } - "@vitest/spy@4.1.7": + "@vitest/spy@5.0.5": resolution: { - integrity: sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==, + integrity: sha512-lwJRExuH417257Q5wv9QYugN9IMJkoxcrKrYxGPQkBzl7wlNpTUxD/5yNX4ESKVUIShKPgkGchYPFMWOOk0wzw==, } "@vitest/utils@3.2.4": @@ -4611,11 +4591,6 @@ packages: integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==, } - "@vitest/utils@4.1.7": - resolution: { - integrity: sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==, - } - "@volar/language-core@2.4.15": resolution: { integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==, @@ -4990,11 +4965,6 @@ packages: resolution: { integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==, } - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true ajv-keywords@5.1.0: resolution: { @@ -5366,9 +5336,9 @@ packages: } engines: { node: ">=18" } - chai@6.2.2: + chai@6.3.0: resolution: { - integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==, + integrity: sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==, } engines: { node: ">=18" } @@ -5530,11 +5500,6 @@ packages: integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==, } - convert-source-map@2.0.0: - resolution: { - integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, - } - copy-anything@4.0.5: resolution: { integrity: sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==, @@ -5864,9 +5829,9 @@ packages: engines: { node: ">=14" } hasBin: true - effect@4.0.2: + effect@4.0.5: resolution: { - integrity: sha512-YeYnLqSFrL4+tCOXRrfNP03w8FILoF/wDl+ukraJAGzXrjcS383W7LAAvGBbLatEyktmLxRq+9xJinx7QzXW5A==, + integrity: sha512-BY4/28NlpOd99yzmV741xbVGmp+1U7tks4oB7F/Png64bTa5tm5eCA6W0RiXsnuLDDoJpjfVSo4Dnq4BZb/89Q==, } electron-to-chromium@1.5.267: @@ -5936,9 +5901,9 @@ packages: } engines: { node: ">= 0.4" } - es-module-lexer@2.0.0: + es-module-lexer@2.3.2: resolution: { - integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==, + integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==, } es-object-atoms@1.1.1: @@ -6205,9 +6170,9 @@ packages: } engines: { node: ">=6" } - expect-type@1.3.0: + expect-type@1.4.0: resolution: { - integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==, + integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==, } engines: { node: ">=12.0.0" } @@ -7348,6 +7313,11 @@ packages: integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, } + magic-string@1.4.3: + resolution: { + integrity: sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==, + } + mark.js@8.11.1: resolution: { integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==, @@ -7692,10 +7662,11 @@ packages: } engines: { node: ">= 0.4" } - obug@2.1.1: + obug@3.0.0: resolution: { - integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==, + integrity: sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==, } + engines: { node: ">=12.20.0" } once@1.4.0: resolution: { @@ -7765,9 +7736,9 @@ packages: } hasBin: true - oxlint-tsgolint@7.0.2001: + oxlint-tsgolint@7.0.2004: resolution: { - integrity: sha512-KjK/XLcXr1DSyonKhsuFqJRiuKqcyG9j3LJ8nkOsrLzGvodBPqzHOKauy10asLMDI0sUpvb+1sxlzff3udZvfg==, + integrity: sha512-vQ9WDF3fiZJvRdSDosNOflerOCOpwol6vWzVDxW76RcU19cjTh7engvkHLvmv+tzedR8fAiJUVUGr6IVZdkzXQ==, } hasBin: true @@ -7786,14 +7757,14 @@ packages: vite-plus: optional: true - oxlint@1.82.0: + oxlint@1.89.0: resolution: { - integrity: sha512-+iFM1BGw1ntYJt3QngbJmjbrGxPaKMUADOXOijpWGnYcBPq8YZnQftSS1C+pVcDYy9YxqDVJKQqQkTazTQMboQ==, + integrity: sha512-a25hkfo61okGPvJz432fRIPoxlKtNnOVy9w4rzrmGgNm4iVTPwpSQlmdqNWnp6p9QyyPVfAZRgnf5XvSBZFk/A==, } engines: { node: ^20.19.0 || >=22.12.0 } hasBin: true peerDependencies: - oxlint-tsgolint: ">=7.0.2001" + oxlint-tsgolint: ">=7.0.2003" vite-plus: "*" peerDependenciesMeta: oxlint-tsgolint: @@ -7965,6 +7936,12 @@ packages: } engines: { node: ">=12" } + picomatch@4.0.7: + resolution: { + integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==, + } + engines: { node: ">=12" } + pify@4.0.1: resolution: { integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==, @@ -8611,11 +8588,6 @@ packages: } engines: { node: ">= 0.4" } - siginfo@2.0.0: - resolution: { - integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==, - } - signal-exit@3.0.7: resolution: { integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==, @@ -8692,14 +8664,9 @@ packages: integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==, } - stackback@0.0.2: - resolution: { - integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, - } - - std-env@4.0.0: + std-env@4.3.0: resolution: { - integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==, + integrity: sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==, } stop-iteration-iterator@1.1.0: @@ -8931,20 +8898,21 @@ packages: integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==, } - tinybench@2.9.0: + tinybench@6.2.2: resolution: { - integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==, + integrity: sha512-nIZ2N2dFpjBsg2hgitKu7mA+FvsIJuGJOwysRngmVRRmWgR/UyPjwJj8c/fT/dhm8EkHnF5EOogRf+0Z2qrimA==, } + engines: { node: ">=20.0.0" } - tinyexec@1.0.2: + tinyexec@1.3.0: resolution: { - integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==, + integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==, } engines: { node: ">=18" } - tinyexec@1.3.0: + tinyexec@1.3.1: resolution: { - integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==, + integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==, } engines: { node: ">=18" } @@ -8960,12 +8928,6 @@ packages: } engines: { node: ">=14.0.0" } - tinyrainbow@3.1.0: - resolution: { - integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==, - } - engines: { node: ">=14.0.0" } - tinyspy@4.0.4: resolution: { integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==, @@ -9362,25 +9324,25 @@ packages: postcss: optional: true - vitest@4.1.7: + vitest@5.0.5: resolution: { - integrity: sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==, + integrity: sha512-cPODOMF8YnkiiYtDdHo6n4wWmBrOBBbOIYH2d33M4l3CdNn72h+qMmO6uXffUN6A5AZFXNND/d+krS9mgkXRfg==, } - engines: { node: ^20.0.0 || ^22.0.0 || >=24.0.0 } + engines: { node: ^22.12.0 || ^24.0.0 || >=26.0.0 } hasBin: true peerDependencies: "@edge-runtime/vm": "*" "@opentelemetry/api": ^1.9.0 - "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 - "@vitest/browser-playwright": 4.1.7 - "@vitest/browser-preview": 4.1.7 - "@vitest/browser-webdriverio": 4.1.7 - "@vitest/coverage-istanbul": 4.1.7 - "@vitest/coverage-v8": 4.1.7 - "@vitest/ui": 4.1.7 + "@types/node": ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 5.0.5 + "@vitest/browser-preview": 5.0.5 + "@vitest/browser-webdriverio": ^5.0.0-beta.5 || >=5.0.0 + "@vitest/coverage-istanbul": 5.0.5 + "@vitest/coverage-v8": 5.0.5 + "@vitest/ui": 5.0.5 happy-dom: "*" jsdom: "*" - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: "@edge-runtime/vm": optional: true @@ -9647,11 +9609,11 @@ packages: engines: { node: ">= 8" } hasBin: true - why-is-node-running@2.3.0: + why-is-node-running@3.2.1: resolution: { - integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==, + integrity: sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==, } - engines: { node: ">=8" } + engines: { node: ">=20.11" } hasBin: true with@7.0.2: @@ -9887,13 +9849,13 @@ snapshots: "@asamuzakjp/nwsapi@2.3.9": {} - "@azure-rest/core-client@2.5.1(supports-color@8.1.1)": + "@azure-rest/core-client@2.5.1(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-auth": 1.10.1(supports-color@8.1.1) - "@azure/core-rest-pipeline": 1.22.2(supports-color@8.1.1) + "@azure/core-auth": 1.10.1(supports-color@7.2.0) + "@azure/core-rest-pipeline": 1.22.2(supports-color@7.2.0) "@azure/core-tracing": 1.3.1 - "@typespec/ts-http-runtime": 0.3.2(supports-color@8.1.1) + "@typespec/ts-http-runtime": 0.3.2(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -9906,55 +9868,55 @@ snapshots: dependencies: tslib: 2.8.1 - "@azure/core-amqp@4.4.1(supports-color@8.1.1)": + "@azure/core-amqp@4.4.1(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-auth": 1.10.1(supports-color@8.1.1) - "@azure/core-util": 1.13.1(supports-color@8.1.1) - "@azure/logger": 1.3.0(supports-color@8.1.1) + "@azure/core-auth": 1.10.1(supports-color@7.2.0) + "@azure/core-util": 1.13.1(supports-color@7.2.0) + "@azure/logger": 1.3.0(supports-color@7.2.0) buffer: 6.0.3 events: 3.3.0 process: 0.11.10 - rhea: 3.0.4(supports-color@8.1.1) - rhea-promise: 3.0.3(supports-color@8.1.1) + rhea: 3.0.4(supports-color@7.2.0) + rhea-promise: 3.0.3(supports-color@7.2.0) tslib: 2.8.1 util: 0.12.5 transitivePeerDependencies: - supports-color - "@azure/core-auth@1.10.1(supports-color@8.1.1)": + "@azure/core-auth@1.10.1(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-util": 1.13.1(supports-color@8.1.1) + "@azure/core-util": 1.13.1(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - "@azure/core-client@1.10.1(supports-color@8.1.1)": + "@azure/core-client@1.10.1(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-auth": 1.10.1(supports-color@8.1.1) - "@azure/core-rest-pipeline": 1.22.2(supports-color@8.1.1) + "@azure/core-auth": 1.10.1(supports-color@7.2.0) + "@azure/core-rest-pipeline": 1.22.2(supports-color@7.2.0) "@azure/core-tracing": 1.3.1 - "@azure/core-util": 1.13.1(supports-color@8.1.1) - "@azure/logger": 1.3.0(supports-color@8.1.1) + "@azure/core-util": 1.13.1(supports-color@7.2.0) + "@azure/logger": 1.3.0(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - "@azure/core-http-compat@2.3.1(supports-color@8.1.1)": + "@azure/core-http-compat@2.3.1(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-client": 1.10.1(supports-color@8.1.1) - "@azure/core-rest-pipeline": 1.22.2(supports-color@8.1.1) + "@azure/core-client": 1.10.1(supports-color@7.2.0) + "@azure/core-rest-pipeline": 1.22.2(supports-color@7.2.0) transitivePeerDependencies: - supports-color - "@azure/core-lro@2.7.2(supports-color@8.1.1)": + "@azure/core-lro@2.7.2(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-util": 1.13.1(supports-color@8.1.1) - "@azure/logger": 1.3.0(supports-color@8.1.1) + "@azure/core-util": 1.13.1(supports-color@7.2.0) + "@azure/logger": 1.3.0(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -9963,14 +9925,14 @@ snapshots: dependencies: tslib: 2.8.1 - "@azure/core-rest-pipeline@1.22.2(supports-color@8.1.1)": + "@azure/core-rest-pipeline@1.22.2(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-auth": 1.10.1(supports-color@8.1.1) + "@azure/core-auth": 1.10.1(supports-color@7.2.0) "@azure/core-tracing": 1.3.1 - "@azure/core-util": 1.13.1(supports-color@8.1.1) - "@azure/logger": 1.3.0(supports-color@8.1.1) - "@typespec/ts-http-runtime": 0.3.2(supports-color@8.1.1) + "@azure/core-util": 1.13.1(supports-color@7.2.0) + "@azure/logger": 1.3.0(supports-color@7.2.0) + "@typespec/ts-http-runtime": 0.3.2(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -9979,10 +9941,10 @@ snapshots: dependencies: tslib: 2.8.1 - "@azure/core-util@1.13.1(supports-color@8.1.1)": + "@azure/core-util@1.13.1(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@typespec/ts-http-runtime": 0.3.2(supports-color@8.1.1) + "@typespec/ts-http-runtime": 0.3.2(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -9992,15 +9954,15 @@ snapshots: fast-xml-parser: 5.3.3 tslib: 2.8.1 - "@azure/cosmos@4.9.3(supports-color@8.1.1)": + "@azure/cosmos@4.9.3(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-auth": 1.10.1(supports-color@8.1.1) - "@azure/core-rest-pipeline": 1.22.2(supports-color@8.1.1) + "@azure/core-auth": 1.10.1(supports-color@7.2.0) + "@azure/core-rest-pipeline": 1.22.2(supports-color@7.2.0) "@azure/core-tracing": 1.3.1 - "@azure/core-util": 1.13.1(supports-color@8.1.1) - "@azure/keyvault-keys": 4.10.0(supports-color@8.1.1) - "@azure/logger": 1.3.0(supports-color@8.1.1) + "@azure/core-util": 1.13.1(supports-color@7.2.0) + "@azure/keyvault-keys": 4.10.0(supports-color@7.2.0) + "@azure/logger": 1.3.0(supports-color@7.2.0) fast-json-stable-stringify: 2.1.0 priorityqueuejs: 2.0.0 semaphore: 1.1.0 @@ -10008,62 +9970,62 @@ snapshots: transitivePeerDependencies: - supports-color - "@azure/keyvault-common@2.0.0(supports-color@8.1.1)": + "@azure/keyvault-common@2.0.0(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 2.1.2 - "@azure/core-auth": 1.10.1(supports-color@8.1.1) - "@azure/core-client": 1.10.1(supports-color@8.1.1) - "@azure/core-rest-pipeline": 1.22.2(supports-color@8.1.1) + "@azure/core-auth": 1.10.1(supports-color@7.2.0) + "@azure/core-client": 1.10.1(supports-color@7.2.0) + "@azure/core-rest-pipeline": 1.22.2(supports-color@7.2.0) "@azure/core-tracing": 1.3.1 - "@azure/core-util": 1.13.1(supports-color@8.1.1) - "@azure/logger": 1.3.0(supports-color@8.1.1) + "@azure/core-util": 1.13.1(supports-color@7.2.0) + "@azure/logger": 1.3.0(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - "@azure/keyvault-keys@4.10.0(supports-color@8.1.1)": + "@azure/keyvault-keys@4.10.0(supports-color@7.2.0)": dependencies: - "@azure-rest/core-client": 2.5.1(supports-color@8.1.1) + "@azure-rest/core-client": 2.5.1(supports-color@7.2.0) "@azure/abort-controller": 2.1.2 - "@azure/core-auth": 1.10.1(supports-color@8.1.1) - "@azure/core-http-compat": 2.3.1(supports-color@8.1.1) - "@azure/core-lro": 2.7.2(supports-color@8.1.1) + "@azure/core-auth": 1.10.1(supports-color@7.2.0) + "@azure/core-http-compat": 2.3.1(supports-color@7.2.0) + "@azure/core-lro": 2.7.2(supports-color@7.2.0) "@azure/core-paging": 1.6.2 - "@azure/core-rest-pipeline": 1.22.2(supports-color@8.1.1) + "@azure/core-rest-pipeline": 1.22.2(supports-color@7.2.0) "@azure/core-tracing": 1.3.1 - "@azure/core-util": 1.13.1(supports-color@8.1.1) - "@azure/keyvault-common": 2.0.0(supports-color@8.1.1) - "@azure/logger": 1.3.0(supports-color@8.1.1) + "@azure/core-util": 1.13.1(supports-color@7.2.0) + "@azure/keyvault-common": 2.0.0(supports-color@7.2.0) + "@azure/logger": 1.3.0(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - "@azure/logger@1.3.0(supports-color@8.1.1)": + "@azure/logger@1.3.0(supports-color@7.2.0)": dependencies: - "@typespec/ts-http-runtime": 0.3.2(supports-color@8.1.1) + "@typespec/ts-http-runtime": 0.3.2(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - "@azure/service-bus@7.9.5(supports-color@8.1.1)": + "@azure/service-bus@7.9.5(supports-color@7.2.0)": dependencies: "@azure/abort-controller": 1.1.0 - "@azure/core-amqp": 4.4.1(supports-color@8.1.1) - "@azure/core-auth": 1.10.1(supports-color@8.1.1) - "@azure/core-client": 1.10.1(supports-color@8.1.1) + "@azure/core-amqp": 4.4.1(supports-color@7.2.0) + "@azure/core-auth": 1.10.1(supports-color@7.2.0) + "@azure/core-client": 1.10.1(supports-color@7.2.0) "@azure/core-paging": 1.6.2 - "@azure/core-rest-pipeline": 1.22.2(supports-color@8.1.1) + "@azure/core-rest-pipeline": 1.22.2(supports-color@7.2.0) "@azure/core-tracing": 1.3.1 - "@azure/core-util": 1.13.1(supports-color@8.1.1) + "@azure/core-util": 1.13.1(supports-color@7.2.0) "@azure/core-xml": 1.5.0 - "@azure/logger": 1.3.0(supports-color@8.1.1) + "@azure/logger": 1.3.0(supports-color@7.2.0) "@types/is-buffer": 2.0.2 buffer: 6.0.3 is-buffer: 2.0.5 jssha: 3.3.1 long: 5.3.2 process: 0.11.10 - rhea-promise: 3.0.3(supports-color@8.1.1) + rhea-promise: 3.0.3(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -10350,75 +10312,80 @@ snapshots: "@dprint/win32-x64@0.54.0": optional: true - "@effect/atom-vue@4.0.2(effect@4.0.2)(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))": + "@effect/atom-vue@4.0.5(effect@4.0.5)(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))": dependencies: - effect: 4.0.2 + effect: 4.0.5 vue: 3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) - "@effect/language-service@0.87.3": {} + "@effect/language-service@0.87.5": {} - "@effect/platform-browser@4.0.2(effect@4.0.2)": + "@effect/platform-browser@4.0.5(effect@4.0.5)": dependencies: - effect: 4.0.2 + effect: 4.0.5 - "@effect/platform-node-shared@4.0.2(effect@4.0.2)": + "@effect/platform-node-shared@4.0.5(effect@4.0.5)": dependencies: "@types/ws": 8.18.2 - effect: 4.0.2 + effect: 4.0.5 ws: 8.22.0 transitivePeerDependencies: - bufferutil - utf-8-validate - "@effect/platform-node@4.0.2(effect@4.0.2)(redis@6.2.1(@opentelemetry/api@1.9.1))": + "@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.2.1(@opentelemetry/api@1.9.1))": dependencies: - "@effect/platform-node-shared": 4.0.2(effect@4.0.2) - effect: 4.0.2 + "@effect/platform-node-shared": 4.0.5(effect@4.0.5) + effect: 4.0.5 redis: 6.2.1(@opentelemetry/api@1.9.1) undici: 8.11.2 transitivePeerDependencies: - bufferutil - utf-8-validate - "@effect/sql-sqlite-node@4.0.2(effect@4.0.2)": + "@effect/sql-sqlite-node@4.0.5(effect@4.0.5)": dependencies: - effect: 4.0.2 + effect: 4.0.5 - "@effect/tsgo-darwin-arm64@0.47.2": + "@effect/tsgo-darwin-arm64@0.56.0": optional: true - "@effect/tsgo-darwin-x64@0.47.2": + "@effect/tsgo-darwin-x64@0.56.0": optional: true - "@effect/tsgo-linux-arm64@0.47.2": + "@effect/tsgo-linux-arm64@0.56.0": optional: true - "@effect/tsgo-linux-arm@0.47.2": + "@effect/tsgo-linux-arm@0.56.0": optional: true - "@effect/tsgo-linux-x64@0.47.2": + "@effect/tsgo-linux-x64@0.56.0": optional: true - "@effect/tsgo-win32-arm64@0.47.2": + "@effect/tsgo-win32-arm64@0.56.0": optional: true - "@effect/tsgo-win32-x64@0.47.2": + "@effect/tsgo-win32-x64@0.56.0": optional: true - "@effect/tsgo@0.47.2": + "@effect/tsgo@0.56.0": optionalDependencies: - "@effect/tsgo-darwin-arm64": 0.47.2 - "@effect/tsgo-darwin-x64": 0.47.2 - "@effect/tsgo-linux-arm": 0.47.2 - "@effect/tsgo-linux-arm64": 0.47.2 - "@effect/tsgo-linux-x64": 0.47.2 - "@effect/tsgo-win32-arm64": 0.47.2 - "@effect/tsgo-win32-x64": 0.47.2 + "@effect/tsgo-darwin-arm64": 0.56.0 + "@effect/tsgo-darwin-x64": 0.56.0 + "@effect/tsgo-linux-arm": 0.56.0 + "@effect/tsgo-linux-arm64": 0.56.0 + "@effect/tsgo-linux-x64": 0.56.0 + "@effect/tsgo-win32-arm64": 0.56.0 + "@effect/tsgo-win32-x64": 0.56.0 - "@effect/vitest@4.0.2(effect@4.0.2)(vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)))": + "@effect/vitest@4.0.5(effect@4.0.5)(vitest@5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)))": dependencies: - effect: 4.0.2 - vitest: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) + effect: 4.0.5 + vitest: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) + + "@effect/vitest@4.0.5(effect@4.0.5)(vitest@5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)))": + dependencies: + effect: 4.0.5 + vitest: 5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) "@emnapi/core@1.10.0": dependencies: @@ -10672,17 +10639,17 @@ snapshots: "@esbuild/win32-x64@0.28.0": optional: true - "@eslint-community/eslint-utils@4.9.1(eslint@10.4.1(supports-color@8.1.1))": + "@eslint-community/eslint-utils@4.9.1(eslint@10.4.1(supports-color@7.2.0))": dependencies: - eslint: 10.4.1(supports-color@8.1.1) + eslint: 10.4.1(supports-color@7.2.0) eslint-visitor-keys: 3.4.3 "@eslint-community/regexpp@4.12.2": {} - "@eslint/config-array@0.23.5(supports-color@8.1.1)": + "@eslint/config-array@0.23.5(supports-color@7.2.0)": dependencies: "@eslint/object-schema": 3.0.5 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) minimatch: 10.2.4 transitivePeerDependencies: - supports-color @@ -10695,10 +10662,10 @@ snapshots: dependencies: "@types/json-schema": 7.0.15 - "@eslint/eslintrc@3.3.5(supports-color@8.1.1)": + "@eslint/eslintrc@3.3.5(supports-color@7.2.0)": dependencies: ajv: 6.14.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -10709,9 +10676,9 @@ snapshots: transitivePeerDependencies: - supports-color - "@eslint/js@10.0.1(eslint@10.4.1(supports-color@8.1.1))": + "@eslint/js@10.0.1(eslint@10.4.1(supports-color@7.2.0))": optionalDependencies: - eslint: 10.4.1(supports-color@8.1.1) + eslint: 10.4.1(supports-color@7.2.0) "@eslint/object-schema@3.0.5": {} @@ -10800,6 +10767,8 @@ snapshots: "@jridgewell/sourcemap-codec@1.5.5": {} + "@jridgewell/sourcemap-codec@1.6.0": {} + "@jridgewell/trace-mapping@0.3.31": dependencies: "@jridgewell/resolve-uri": 3.1.2 @@ -10866,12 +10835,12 @@ snapshots: "@opentelemetry/api": 1.9.1 "@opentelemetry/semantic-conventions": 1.40.0 - "@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1)": + "@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@7.2.0)": dependencies: "@opentelemetry/api": 1.9.1 "@opentelemetry/api-logs": 0.214.0 import-in-the-middle: 3.0.0 - require-in-the-middle: 8.0.1(supports-color@8.1.1) + require-in-the-middle: 8.0.1(supports-color@7.2.0) transitivePeerDependencies: - supports-color @@ -11086,151 +11055,151 @@ snapshots: "@oxlint-tsgolint/darwin-arm64@0.23.0": optional: true - "@oxlint-tsgolint/darwin-arm64@7.0.2001": + "@oxlint-tsgolint/darwin-arm64@7.0.2004": optional: true "@oxlint-tsgolint/darwin-x64@0.23.0": optional: true - "@oxlint-tsgolint/darwin-x64@7.0.2001": + "@oxlint-tsgolint/darwin-x64@7.0.2004": optional: true "@oxlint-tsgolint/linux-arm64@0.23.0": optional: true - "@oxlint-tsgolint/linux-arm64@7.0.2001": + "@oxlint-tsgolint/linux-arm64@7.0.2004": optional: true "@oxlint-tsgolint/linux-x64@0.23.0": optional: true - "@oxlint-tsgolint/linux-x64@7.0.2001": + "@oxlint-tsgolint/linux-x64@7.0.2004": optional: true "@oxlint-tsgolint/win32-arm64@0.23.0": optional: true - "@oxlint-tsgolint/win32-arm64@7.0.2001": + "@oxlint-tsgolint/win32-arm64@7.0.2004": optional: true "@oxlint-tsgolint/win32-x64@0.23.0": optional: true - "@oxlint-tsgolint/win32-x64@7.0.2001": + "@oxlint-tsgolint/win32-x64@7.0.2004": optional: true "@oxlint/binding-android-arm-eabi@1.67.0": optional: true - "@oxlint/binding-android-arm-eabi@1.82.0": + "@oxlint/binding-android-arm-eabi@1.89.0": optional: true "@oxlint/binding-android-arm64@1.67.0": optional: true - "@oxlint/binding-android-arm64@1.82.0": + "@oxlint/binding-android-arm64@1.89.0": optional: true "@oxlint/binding-darwin-arm64@1.67.0": optional: true - "@oxlint/binding-darwin-arm64@1.82.0": + "@oxlint/binding-darwin-arm64@1.89.0": optional: true "@oxlint/binding-darwin-x64@1.67.0": optional: true - "@oxlint/binding-darwin-x64@1.82.0": + "@oxlint/binding-darwin-x64@1.89.0": optional: true "@oxlint/binding-freebsd-x64@1.67.0": optional: true - "@oxlint/binding-freebsd-x64@1.82.0": + "@oxlint/binding-freebsd-x64@1.89.0": optional: true "@oxlint/binding-linux-arm-gnueabihf@1.67.0": optional: true - "@oxlint/binding-linux-arm-gnueabihf@1.82.0": + "@oxlint/binding-linux-arm-gnueabihf@1.89.0": optional: true "@oxlint/binding-linux-arm-musleabihf@1.67.0": optional: true - "@oxlint/binding-linux-arm-musleabihf@1.82.0": + "@oxlint/binding-linux-arm-musleabihf@1.89.0": optional: true "@oxlint/binding-linux-arm64-gnu@1.67.0": optional: true - "@oxlint/binding-linux-arm64-gnu@1.82.0": + "@oxlint/binding-linux-arm64-gnu@1.89.0": optional: true "@oxlint/binding-linux-arm64-musl@1.67.0": optional: true - "@oxlint/binding-linux-arm64-musl@1.82.0": + "@oxlint/binding-linux-arm64-musl@1.89.0": optional: true "@oxlint/binding-linux-ppc64-gnu@1.67.0": optional: true - "@oxlint/binding-linux-ppc64-gnu@1.82.0": + "@oxlint/binding-linux-ppc64-gnu@1.89.0": optional: true "@oxlint/binding-linux-riscv64-gnu@1.67.0": optional: true - "@oxlint/binding-linux-riscv64-gnu@1.82.0": + "@oxlint/binding-linux-riscv64-gnu@1.89.0": optional: true "@oxlint/binding-linux-riscv64-musl@1.67.0": optional: true - "@oxlint/binding-linux-riscv64-musl@1.82.0": + "@oxlint/binding-linux-riscv64-musl@1.89.0": optional: true "@oxlint/binding-linux-s390x-gnu@1.67.0": optional: true - "@oxlint/binding-linux-s390x-gnu@1.82.0": + "@oxlint/binding-linux-s390x-gnu@1.89.0": optional: true "@oxlint/binding-linux-x64-gnu@1.67.0": optional: true - "@oxlint/binding-linux-x64-gnu@1.82.0": + "@oxlint/binding-linux-x64-gnu@1.89.0": optional: true "@oxlint/binding-linux-x64-musl@1.67.0": optional: true - "@oxlint/binding-linux-x64-musl@1.82.0": + "@oxlint/binding-linux-x64-musl@1.89.0": optional: true "@oxlint/binding-openharmony-arm64@1.67.0": optional: true - "@oxlint/binding-openharmony-arm64@1.82.0": + "@oxlint/binding-openharmony-arm64@1.89.0": optional: true "@oxlint/binding-win32-arm64-msvc@1.67.0": optional: true - "@oxlint/binding-win32-arm64-msvc@1.82.0": + "@oxlint/binding-win32-arm64-msvc@1.89.0": optional: true "@oxlint/binding-win32-ia32-msvc@1.67.0": optional: true - "@oxlint/binding-win32-ia32-msvc@1.82.0": + "@oxlint/binding-win32-ia32-msvc@1.89.0": optional: true "@oxlint/binding-win32-x64-msvc@1.67.0": optional: true - "@oxlint/binding-win32-x64-msvc@1.82.0": + "@oxlint/binding-win32-x64-msvc@1.89.0": optional: true "@parcel/watcher-android-arm64@2.5.4": @@ -11470,10 +11439,10 @@ snapshots: "@rtsao/scc@1.1.0": {} - "@sendgrid/client@8.1.6(debug@4.4.3(supports-color@8.1.1))": + "@sendgrid/client@8.1.6(debug@4.4.3(supports-color@7.2.0))": dependencies: "@sendgrid/helpers": 8.0.0 - axios: 1.13.2(debug@4.4.3(supports-color@8.1.1)) + axios: 1.13.2(debug@4.4.3(supports-color@7.2.0)) transitivePeerDependencies: - debug @@ -11481,9 +11450,9 @@ snapshots: dependencies: deepmerge: 4.3.1 - "@sendgrid/mail@8.1.6(patch_hash=3d2dd1cd5f52d3eef1772e4be48776258a596f9277c00adf0a471f54fcd3e21a)(debug@4.4.3(supports-color@8.1.1))": + "@sendgrid/mail@8.1.6(patch_hash=3d2dd1cd5f52d3eef1772e4be48776258a596f9277c00adf0a471f54fcd3e21a)(debug@4.4.3(supports-color@7.2.0))": dependencies: - "@sendgrid/client": 8.1.6(debug@4.4.3(supports-color@8.1.1)) + "@sendgrid/client": 8.1.6(debug@4.4.3(supports-color@7.2.0)) "@sendgrid/helpers": 8.0.0 transitivePeerDependencies: - debug @@ -11516,7 +11485,7 @@ snapshots: "@sentry/core@10.55.0": {} - "@sentry/node-core@10.55.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)": + "@sentry/node-core@10.55.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@7.2.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)": dependencies: "@sentry/core": 10.55.0 "@sentry/opentelemetry": 10.55.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) @@ -11524,19 +11493,19 @@ snapshots: optionalDependencies: "@opentelemetry/api": 1.9.1 "@opentelemetry/core": 2.6.1(@opentelemetry/api@1.9.1) - "@opentelemetry/instrumentation": 0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1) + "@opentelemetry/instrumentation": 0.214.0(@opentelemetry/api@1.9.1)(supports-color@7.2.0) "@opentelemetry/sdk-trace-base": 2.6.1(@opentelemetry/api@1.9.1) "@opentelemetry/semantic-conventions": 1.40.0 - "@sentry/node@10.55.0(supports-color@8.1.1)": + "@sentry/node@10.55.0(supports-color@7.2.0)": dependencies: "@opentelemetry/api": 1.9.1 "@opentelemetry/core": 2.6.1(@opentelemetry/api@1.9.1) - "@opentelemetry/instrumentation": 0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1) + "@opentelemetry/instrumentation": 0.214.0(@opentelemetry/api@1.9.1)(supports-color@7.2.0) "@opentelemetry/sdk-trace-base": 2.6.1(@opentelemetry/api@1.9.1) "@opentelemetry/semantic-conventions": 1.40.0 "@sentry/core": 10.55.0 - "@sentry/node-core": 10.55.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) + "@sentry/node-core": 10.55.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)(supports-color@7.2.0))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) "@sentry/opentelemetry": 10.55.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) import-in-the-middle: 3.0.0 transitivePeerDependencies: @@ -11591,8 +11560,6 @@ snapshots: "@shikijs/vscode-textmate@10.0.2": {} - "@standard-schema/spec@1.1.0": {} - "@storybook/builder-vite@10.4.1(esbuild@0.28.0)(rollup@4.55.1)(storybook@10.4.1(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))(webpack@5.104.1(esbuild@0.28.0))": dependencies: "@storybook/csf-plugin": 10.4.1(esbuild@0.28.0)(rollup@4.55.1)(storybook@10.4.1(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))(webpack@5.104.1(esbuild@0.28.0)) @@ -11839,15 +11806,15 @@ snapshots: dependencies: "@types/node": 25.9.1 - "@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": + "@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": dependencies: "@eslint-community/regexpp": 4.12.2 - "@typescript-eslint/parser": 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/parser": 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript-eslint/scope-manager": 8.60.0 - "@typescript-eslint/type-utils": 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) - "@typescript-eslint/utils": 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/type-utils": 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/utils": 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript-eslint/visitor-keys": 8.60.0 - eslint: 10.4.1(supports-color@8.1.1) + eslint: 10.4.1(supports-color@7.2.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) @@ -11855,32 +11822,32 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": + "@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": dependencies: "@typescript-eslint/scope-manager": 8.60.0 "@typescript-eslint/types": 8.60.0 - "@typescript-eslint/typescript-estree": 8.60.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/typescript-estree": 8.60.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript-eslint/visitor-keys": 8.60.0 - debug: 4.4.3(supports-color@8.1.1) - eslint: 10.4.1(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) + eslint: 10.4.1(supports-color@7.2.0) typescript: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) transitivePeerDependencies: - supports-color - "@typescript-eslint/project-service@8.60.0(supports-color@8.1.1)(typescript@5.9.3)": + "@typescript-eslint/project-service@8.60.0(supports-color@7.2.0)(typescript@5.9.3)": dependencies: "@typescript-eslint/tsconfig-utils": 8.60.0(typescript@5.9.3) "@typescript-eslint/types": 8.60.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/project-service@8.60.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": + "@typescript-eslint/project-service@8.60.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": dependencies: "@typescript-eslint/tsconfig-utils": 8.60.0(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript-eslint/types": 8.60.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) typescript: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) transitivePeerDependencies: - supports-color @@ -11898,13 +11865,13 @@ snapshots: dependencies: typescript: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) - "@typescript-eslint/type-utils@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": + "@typescript-eslint/type-utils@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": dependencies: "@typescript-eslint/types": 8.60.0 - "@typescript-eslint/typescript-estree": 8.60.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) - "@typescript-eslint/utils": 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) - debug: 4.4.3(supports-color@8.1.1) - eslint: 10.4.1(supports-color@8.1.1) + "@typescript-eslint/typescript-estree": 8.60.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/utils": 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + debug: 4.4.3(supports-color@7.2.0) + eslint: 10.4.1(supports-color@7.2.0) ts-api-utils: 2.5.0(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) typescript: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) transitivePeerDependencies: @@ -11912,13 +11879,13 @@ snapshots: "@typescript-eslint/types@8.60.0": {} - "@typescript-eslint/typescript-estree@8.60.0(supports-color@8.1.1)(typescript@5.9.3)": + "@typescript-eslint/typescript-estree@8.60.0(supports-color@7.2.0)(typescript@5.9.3)": dependencies: - "@typescript-eslint/project-service": 8.60.0(supports-color@8.1.1)(typescript@5.9.3) + "@typescript-eslint/project-service": 8.60.0(supports-color@7.2.0)(typescript@5.9.3) "@typescript-eslint/tsconfig-utils": 8.60.0(typescript@5.9.3) "@typescript-eslint/types": 8.60.0 "@typescript-eslint/visitor-keys": 8.60.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) minimatch: 10.2.4 semver: 7.7.3 tinyglobby: 0.2.17 @@ -11927,13 +11894,13 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/typescript-estree@8.60.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": + "@typescript-eslint/typescript-estree@8.60.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": dependencies: - "@typescript-eslint/project-service": 8.60.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/project-service": 8.60.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript-eslint/tsconfig-utils": 8.60.0(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) "@typescript-eslint/types": 8.60.0 "@typescript-eslint/visitor-keys": 8.60.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) minimatch: 10.2.4 semver: 7.7.3 tinyglobby: 0.2.17 @@ -11942,13 +11909,13 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/utils@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": + "@typescript-eslint/utils@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))": dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@10.4.1(supports-color@8.1.1)) + "@eslint-community/eslint-utils": 4.9.1(eslint@10.4.1(supports-color@7.2.0)) "@typescript-eslint/scope-manager": 8.60.0 "@typescript-eslint/types": 8.60.0 - "@typescript-eslint/typescript-estree": 8.60.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) - eslint: 10.4.1(supports-color@8.1.1) + "@typescript-eslint/typescript-estree": 8.60.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + eslint: 10.4.1(supports-color@7.2.0) typescript: 6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54) transitivePeerDependencies: - supports-color @@ -12020,10 +11987,10 @@ snapshots: "@typescript/native-preview-win32-arm64": 7.0.0-dev.20260626.1 "@typescript/native-preview-win32-x64": 7.0.0-dev.20260626.1 - "@typespec/ts-http-runtime@0.3.2(supports-color@8.1.1)": + "@typespec/ts-http-runtime@0.3.2(supports-color@7.2.0)": dependencies: - http-proxy-agent: 7.0.2(supports-color@8.1.1) - https-proxy-agent: 7.0.6(supports-color@8.1.1) + http-proxy-agent: 7.0.2(supports-color@7.2.0) + https-proxy-agent: 7.0.6(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -12051,20 +12018,21 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - "@vitest/expect@4.1.7": + "@vitest/mocker@5.0.5(vite@8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))": dependencies: - "@standard-schema/spec": 1.1.0 - "@types/chai": 5.2.3 - "@vitest/spy": 4.1.7 - "@vitest/utils": 4.1.7 - chai: 6.2.2 - tinyrainbow: 3.1.0 + "@jridgewell/trace-mapping": 0.3.31 + "@vitest/spy": 5.0.5 + estree-walker: 3.0.3 + magic-string: 1.4.3 + optionalDependencies: + vite: 8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0) - "@vitest/mocker@4.1.7(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))": + "@vitest/mocker@5.0.5(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0))": dependencies: - "@vitest/spy": 4.1.7 + "@jridgewell/trace-mapping": 0.3.31 + "@vitest/spy": 5.0.5 estree-walker: 3.0.3 - magic-string: 0.30.21 + magic-string: 1.4.3 optionalDependencies: vite: 8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0) @@ -12072,27 +12040,11 @@ snapshots: dependencies: tinyrainbow: 2.0.0 - "@vitest/pretty-format@4.1.7": - dependencies: - tinyrainbow: 3.1.0 - - "@vitest/runner@4.1.7": - dependencies: - "@vitest/utils": 4.1.7 - pathe: 2.0.3 - - "@vitest/snapshot@4.1.7": - dependencies: - "@vitest/pretty-format": 4.1.7 - "@vitest/utils": 4.1.7 - magic-string: 0.30.21 - pathe: 2.0.3 - "@vitest/spy@3.2.4": dependencies: tinyspy: 4.0.4 - "@vitest/spy@4.1.7": {} + "@vitest/spy@5.0.5": {} "@vitest/utils@3.2.4": dependencies: @@ -12100,12 +12052,6 @@ snapshots: loupe: 3.2.1 tinyrainbow: 2.0.0 - "@vitest/utils@4.1.7": - dependencies: - "@vitest/pretty-format": 4.1.7 - convert-source-map: 2.0.0 - tinyrainbow: 3.1.0 - "@volar/language-core@2.4.15": dependencies: "@volar/source-map": 2.4.15 @@ -12427,8 +12373,8 @@ snapshots: agent-base@7.1.4: {} - ajv-formats@2.1.1(ajv@8.17.1): - optionalDependencies: + ajv-formats@2.1.1: + dependencies: ajv: 8.17.1 optional: true @@ -12587,6 +12533,14 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 + axios@1.13.2(debug@4.4.3(supports-color@7.2.0)): + dependencies: + follow-redirects: 1.15.11(debug@4.4.3(supports-color@7.2.0)) + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axios@1.13.2(debug@4.4.3(supports-color@8.1.1)): dependencies: follow-redirects: 1.15.11(debug@4.4.3(supports-color@8.1.1)) @@ -12594,6 +12548,7 @@ snapshots: proxy-from-env: 1.1.0 transitivePeerDependencies: - debug + optional: true babel-walk@3.0.0-canary-5: dependencies: @@ -12714,7 +12669,7 @@ snapshots: loupe: 3.2.1 pathval: 2.0.1 - chai@6.2.2: {} + chai@6.3.0: {} chalk@4.1.2: dependencies: @@ -12795,8 +12750,6 @@ snapshots: "@babel/parser": 7.29.3 "@babel/types": 7.29.0 - convert-source-map@2.0.0: {} - copy-anything@4.0.5: dependencies: is-what: 5.5.0 @@ -12845,17 +12798,24 @@ snapshots: de-indent@1.0.2: {} - debug@3.2.7(supports-color@8.1.1): + debug@3.2.7(supports-color@7.2.0): dependencies: ms: 2.1.3 optionalDependencies: - supports-color: 8.1.1 + supports-color: 7.2.0 + + debug@4.4.3(supports-color@7.2.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 7.2.0 debug@4.4.3(supports-color@8.1.1): dependencies: ms: 2.1.3 optionalDependencies: supports-color: 8.1.1 + optional: true decimal.js@10.6.0: {} @@ -12902,11 +12862,11 @@ snapshots: denque@1.5.1: {} - dependency-tree@11.2.0(supports-color@8.1.1): + dependency-tree@11.2.0(supports-color@7.2.0): dependencies: commander: 12.1.0 filing-cabinet: 5.0.3 - precinct: 12.2.0(supports-color@8.1.1) + precinct: 12.2.0(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -12951,16 +12911,16 @@ snapshots: detective-stylus@5.0.1: {} - detective-typescript@14.0.0(supports-color@8.1.1)(typescript@5.9.3): + detective-typescript@14.0.0(supports-color@7.2.0)(typescript@5.9.3): dependencies: - "@typescript-eslint/typescript-estree": 8.60.0(supports-color@8.1.1)(typescript@5.9.3) + "@typescript-eslint/typescript-estree": 8.60.0(supports-color@7.2.0)(typescript@5.9.3) ast-module-types: 6.0.1 node-source-walk: 7.0.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - detective-vue2@2.2.0(supports-color@8.1.1)(typescript@5.9.3): + detective-vue2@2.2.0(supports-color@7.2.0)(typescript@5.9.3): dependencies: "@dependents/detective-less": 5.0.1 "@vue/compiler-sfc": 3.5.35 @@ -12968,7 +12928,7 @@ snapshots: detective-sass: 6.0.1 detective-scss: 5.0.1 detective-stylus: 5.0.1 - detective-typescript: 14.0.0(supports-color@8.1.1)(typescript@5.9.3) + detective-typescript: 14.0.0(supports-color@7.2.0)(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -13026,7 +12986,7 @@ snapshots: minimatch: 9.0.1 semver: 7.7.3 - effect@4.0.2: {} + effect@4.0.5: {} electron-to-chromium@1.5.267: optional: true @@ -13116,7 +13076,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@2.0.0: {} + es-module-lexer@2.3.2: {} es-object-atoms@1.1.1: dependencies: @@ -13237,48 +13197,48 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-import-resolver-node@0.3.9(supports-color@8.1.1): + eslint-import-resolver-node@0.3.9(supports-color@7.2.0): dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7(supports-color@7.2.0) is-core-module: 2.16.1 resolve: 1.22.11 transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint-import-resolver-node@0.3.9(supports-color@7.2.0))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7(supports-color@7.2.0) optionalDependencies: - "@typescript-eslint/parser": 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) - eslint: 10.4.1(supports-color@8.1.1) - eslint-import-resolver-node: 0.3.9(supports-color@8.1.1) + "@typescript-eslint/parser": 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + eslint: 10.4.1(supports-color@7.2.0) + eslint-import-resolver-node: 0.3.9(supports-color@7.2.0) transitivePeerDependencies: - supports-color - eslint-plugin-formatjs@6.4.13(eslint@10.4.1(supports-color@8.1.1)): + eslint-plugin-formatjs@6.4.13(eslint@10.4.1(supports-color@7.2.0)): dependencies: "@formatjs/icu-messageformat-parser": 3.5.10 "@formatjs/ts-transformer": 4.4.11 "@types/picomatch": 4.0.2 "@unicode/unicode-17.0.0": 1.6.16 - eslint: 10.4.1(supports-color@8.1.1) + eslint: 10.4.1(supports-color@7.2.0) magic-string: 0.30.21 picomatch: 4.0.4 transitivePeerDependencies: - ts-jest - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0): dependencies: "@rtsao/scc": 1.1.0 array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7(supports-color@7.2.0) doctrine: 2.1.0 - eslint: 10.4.1(supports-color@8.1.1) - eslint-import-resolver-node: 0.3.9(supports-color@8.1.1) - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint-import-resolver-node@0.3.9(supports-color@8.1.1))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1) + eslint: 10.4.1(supports-color@7.2.0) + eslint-import-resolver-node: 0.3.9(supports-color@7.2.0) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint-import-resolver-node@0.3.9(supports-color@7.2.0))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -13290,35 +13250,35 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - "@typescript-eslint/parser": 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/parser": 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-sort-destructure-keys@3.0.0(eslint@10.4.1(supports-color@8.1.1)): + eslint-plugin-sort-destructure-keys@3.0.0(eslint@10.4.1(supports-color@7.2.0)): dependencies: - eslint: 10.4.1(supports-color@8.1.1) + eslint: 10.4.1(supports-color@7.2.0) natural-compare-lite: 1.4.0 - eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1)): + eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0)): dependencies: - eslint: 10.4.1(supports-color@8.1.1) + eslint: 10.4.1(supports-color@7.2.0) optionalDependencies: - "@typescript-eslint/eslint-plugin": 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/eslint-plugin": 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) - eslint-plugin-vue@10.9.1(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@8.1.1))(vue-eslint-parser@10.4.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)): + eslint-plugin-vue@10.9.1(@typescript-eslint/parser@8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)))(eslint@10.4.1(supports-color@7.2.0))(vue-eslint-parser@10.4.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)): dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@10.4.1(supports-color@8.1.1)) - eslint: 10.4.1(supports-color@8.1.1) + "@eslint-community/eslint-utils": 4.9.1(eslint@10.4.1(supports-color@7.2.0)) + eslint: 10.4.1(supports-color@7.2.0) natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 7.1.1 semver: 7.7.3 - vue-eslint-parser: 10.4.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1) + vue-eslint-parser: 10.4.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0) xml-name-validator: 4.0.0 optionalDependencies: - "@typescript-eslint/parser": 8.60.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) + "@typescript-eslint/parser": 8.60.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) eslint-scope@5.1.1: dependencies: @@ -13339,11 +13299,11 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.4.1(supports-color@8.1.1): + eslint@10.4.1(supports-color@7.2.0): dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@10.4.1(supports-color@8.1.1)) + "@eslint-community/eslint-utils": 4.9.1(eslint@10.4.1(supports-color@7.2.0)) "@eslint-community/regexpp": 4.12.2 - "@eslint/config-array": 0.23.5(supports-color@8.1.1) + "@eslint/config-array": 0.23.5(supports-color@7.2.0) "@eslint/config-helpers": 0.6.0 "@eslint/core": 1.2.1 "@eslint/plugin-kit": 0.7.2 @@ -13353,7 +13313,7 @@ snapshots: "@types/estree": 1.0.8 ajv: 6.14.0 cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) escape-string-regexp: 4.0.0 eslint-scope: 9.1.2 eslint-visitor-keys: 5.0.1 @@ -13415,7 +13375,7 @@ snapshots: expand-template@2.0.3: {} - expect-type@1.3.0: {} + expect-type@1.4.0: {} exsolve@1.0.8: {} @@ -13501,9 +13461,14 @@ snapshots: dependencies: tabbable: 6.4.0 + follow-redirects@1.15.11(debug@4.4.3(supports-color@7.2.0)): + optionalDependencies: + debug: 4.4.3(supports-color@7.2.0) + follow-redirects@1.15.11(debug@4.4.3(supports-color@8.1.1)): optionalDependencies: debug: 4.4.3(supports-color@8.1.1) + optional: true for-each@0.3.5: dependencies: @@ -13717,17 +13682,17 @@ snapshots: html-void-elements@3.0.0: {} - http-proxy-agent@7.0.2(supports-color@8.1.1): + http-proxy-agent@7.0.2(supports-color@7.2.0): dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.6(supports-color@8.1.1): + https-proxy-agent@7.0.6(supports-color@7.2.0): dependencies: agent-base: 7.1.4 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) transitivePeerDependencies: - supports-color @@ -14160,13 +14125,13 @@ snapshots: lz-string@1.5.0: {} - madge@8.0.0(supports-color@8.1.1)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)): + madge@8.0.0(supports-color@7.2.0)(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)): dependencies: chalk: 4.1.2 commander: 7.2.0 commondir: 1.0.1 - debug: 4.4.3(supports-color@8.1.1) - dependency-tree: 11.2.0(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) + dependency-tree: 11.2.0(supports-color@7.2.0) ora: 5.4.1 pluralize: 8.0.0 pretty-ms: 7.0.1 @@ -14187,6 +14152,10 @@ snapshots: dependencies: "@jridgewell/sourcemap-codec": 1.5.5 + magic-string@1.4.3: + dependencies: + "@jridgewell/sourcemap-codec": 1.6.0 + mark.js@8.11.1: {} math-intrinsics@1.1.0: {} @@ -14384,7 +14353,7 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - obug@2.1.1: {} + obug@3.0.0: {} once@1.4.0: dependencies: @@ -14517,14 +14486,14 @@ snapshots: "@oxlint-tsgolint/win32-arm64": 0.23.0 "@oxlint-tsgolint/win32-x64": 0.23.0 - oxlint-tsgolint@7.0.2001: + oxlint-tsgolint@7.0.2004: optionalDependencies: - "@oxlint-tsgolint/darwin-arm64": 7.0.2001 - "@oxlint-tsgolint/darwin-x64": 7.0.2001 - "@oxlint-tsgolint/linux-arm64": 7.0.2001 - "@oxlint-tsgolint/linux-x64": 7.0.2001 - "@oxlint-tsgolint/win32-arm64": 7.0.2001 - "@oxlint-tsgolint/win32-x64": 7.0.2001 + "@oxlint-tsgolint/darwin-arm64": 7.0.2004 + "@oxlint-tsgolint/darwin-x64": 7.0.2004 + "@oxlint-tsgolint/linux-arm64": 7.0.2004 + "@oxlint-tsgolint/linux-x64": 7.0.2004 + "@oxlint-tsgolint/win32-arm64": 7.0.2004 + "@oxlint-tsgolint/win32-x64": 7.0.2004 oxlint@1.67.0(oxlint-tsgolint@0.23.0): optionalDependencies: @@ -14549,28 +14518,51 @@ snapshots: "@oxlint/binding-win32-x64-msvc": 1.67.0 oxlint-tsgolint: 0.23.0 - oxlint@1.82.0(oxlint-tsgolint@7.0.2001): + oxlint@1.67.0(oxlint-tsgolint@7.0.2004): optionalDependencies: - "@oxlint/binding-android-arm-eabi": 1.82.0 - "@oxlint/binding-android-arm64": 1.82.0 - "@oxlint/binding-darwin-arm64": 1.82.0 - "@oxlint/binding-darwin-x64": 1.82.0 - "@oxlint/binding-freebsd-x64": 1.82.0 - "@oxlint/binding-linux-arm-gnueabihf": 1.82.0 - "@oxlint/binding-linux-arm-musleabihf": 1.82.0 - "@oxlint/binding-linux-arm64-gnu": 1.82.0 - "@oxlint/binding-linux-arm64-musl": 1.82.0 - "@oxlint/binding-linux-ppc64-gnu": 1.82.0 - "@oxlint/binding-linux-riscv64-gnu": 1.82.0 - "@oxlint/binding-linux-riscv64-musl": 1.82.0 - "@oxlint/binding-linux-s390x-gnu": 1.82.0 - "@oxlint/binding-linux-x64-gnu": 1.82.0 - "@oxlint/binding-linux-x64-musl": 1.82.0 - "@oxlint/binding-openharmony-arm64": 1.82.0 - "@oxlint/binding-win32-arm64-msvc": 1.82.0 - "@oxlint/binding-win32-ia32-msvc": 1.82.0 - "@oxlint/binding-win32-x64-msvc": 1.82.0 - oxlint-tsgolint: 7.0.2001 + "@oxlint/binding-android-arm-eabi": 1.67.0 + "@oxlint/binding-android-arm64": 1.67.0 + "@oxlint/binding-darwin-arm64": 1.67.0 + "@oxlint/binding-darwin-x64": 1.67.0 + "@oxlint/binding-freebsd-x64": 1.67.0 + "@oxlint/binding-linux-arm-gnueabihf": 1.67.0 + "@oxlint/binding-linux-arm-musleabihf": 1.67.0 + "@oxlint/binding-linux-arm64-gnu": 1.67.0 + "@oxlint/binding-linux-arm64-musl": 1.67.0 + "@oxlint/binding-linux-ppc64-gnu": 1.67.0 + "@oxlint/binding-linux-riscv64-gnu": 1.67.0 + "@oxlint/binding-linux-riscv64-musl": 1.67.0 + "@oxlint/binding-linux-s390x-gnu": 1.67.0 + "@oxlint/binding-linux-x64-gnu": 1.67.0 + "@oxlint/binding-linux-x64-musl": 1.67.0 + "@oxlint/binding-openharmony-arm64": 1.67.0 + "@oxlint/binding-win32-arm64-msvc": 1.67.0 + "@oxlint/binding-win32-ia32-msvc": 1.67.0 + "@oxlint/binding-win32-x64-msvc": 1.67.0 + oxlint-tsgolint: 7.0.2004 + + oxlint@1.89.0(oxlint-tsgolint@7.0.2004): + optionalDependencies: + "@oxlint/binding-android-arm-eabi": 1.89.0 + "@oxlint/binding-android-arm64": 1.89.0 + "@oxlint/binding-darwin-arm64": 1.89.0 + "@oxlint/binding-darwin-x64": 1.89.0 + "@oxlint/binding-freebsd-x64": 1.89.0 + "@oxlint/binding-linux-arm-gnueabihf": 1.89.0 + "@oxlint/binding-linux-arm-musleabihf": 1.89.0 + "@oxlint/binding-linux-arm64-gnu": 1.89.0 + "@oxlint/binding-linux-arm64-musl": 1.89.0 + "@oxlint/binding-linux-ppc64-gnu": 1.89.0 + "@oxlint/binding-linux-riscv64-gnu": 1.89.0 + "@oxlint/binding-linux-riscv64-musl": 1.89.0 + "@oxlint/binding-linux-s390x-gnu": 1.89.0 + "@oxlint/binding-linux-x64-gnu": 1.89.0 + "@oxlint/binding-linux-x64-musl": 1.89.0 + "@oxlint/binding-openharmony-arm64": 1.89.0 + "@oxlint/binding-win32-arm64-msvc": 1.89.0 + "@oxlint/binding-win32-ia32-msvc": 1.89.0 + "@oxlint/binding-win32-x64-msvc": 1.89.0 + oxlint-tsgolint: 7.0.2004 p-filter@2.1.0: dependencies: @@ -14655,6 +14647,8 @@ snapshots: picomatch@4.0.5: {} + picomatch@4.0.7: {} + pify@4.0.1: {} pkg-pr-new@0.0.75: {} @@ -14710,7 +14704,7 @@ snapshots: tar-fs: 2.1.4 tunnel-agent: 0.6.0 - precinct@12.2.0(supports-color@8.1.1): + precinct@12.2.0(supports-color@7.2.0): dependencies: "@dependents/detective-less": 5.0.1 commander: 12.1.0 @@ -14721,8 +14715,8 @@ snapshots: detective-sass: 6.0.1 detective-scss: 5.0.1 detective-stylus: 5.0.1 - detective-typescript: 14.0.0(supports-color@8.1.1)(typescript@5.9.3) - detective-vue2: 2.2.0(supports-color@8.1.1)(typescript@5.9.3) + detective-typescript: 14.0.0(supports-color@7.2.0)(typescript@5.9.3) + detective-vue2: 2.2.0(supports-color@7.2.0)(typescript@5.9.3) module-definition: 6.0.1 node-source-walk: 7.0.1 postcss: 8.5.15 @@ -14982,9 +14976,9 @@ snapshots: require-from-string@2.0.2: {} - require-in-the-middle@8.0.1(supports-color@8.1.1): + require-in-the-middle@8.0.1(supports-color@7.2.0): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) module-details-from-path: 1.0.4 transitivePeerDependencies: - supports-color @@ -15019,17 +15013,17 @@ snapshots: rfdc@1.4.1: {} - rhea-promise@3.0.3(supports-color@8.1.1): + rhea-promise@3.0.3(supports-color@7.2.0): dependencies: - debug: 4.4.3(supports-color@8.1.1) - rhea: 3.0.4(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) + rhea: 3.0.4(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color - rhea@3.0.4(supports-color@8.1.1): + rhea@3.0.4(supports-color@7.2.0): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) transitivePeerDependencies: - supports-color @@ -15144,7 +15138,7 @@ snapshots: dependencies: "@types/json-schema": 7.0.15 ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) + ajv-formats: 2.1.1 ajv-keywords: 5.1.0(ajv@8.17.1) optional: true @@ -15232,8 +15226,6 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - siginfo@2.0.0: {} - signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -15275,9 +15267,7 @@ snapshots: sprintf-js@1.0.3: {} - stackback@0.0.2: {} - - std-env@4.0.0: {} + std-env@4.3.0: {} stop-iteration-iterator@1.1.0: dependencies: @@ -15457,12 +15447,12 @@ snapshots: tiny-invariant@1.3.3: {} - tinybench@2.9.0: {} - - tinyexec@1.0.2: {} + tinybench@6.2.2: {} tinyexec@1.3.0: {} + tinyexec@1.3.1: {} + tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.4) @@ -15470,8 +15460,6 @@ snapshots: tinyrainbow@2.0.0: {} - tinyrainbow@3.1.0: {} - tinyspy@4.0.4: {} tldts-core@7.0.19: {} @@ -15707,6 +15695,22 @@ snapshots: sass: 1.100.0 terser: 5.45.0 + vite@8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.15 + rolldown: 1.0.3 + tinyglobby: 0.2.17 + optionalDependencies: + "@types/node": 25.9.1 + esbuild: 0.27.2 + fsevents: 2.3.3 + sass: 1.100.0 + terser: 5.45.0 + tsx: 4.22.4 + yaml: 2.9.0 + vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 @@ -15772,28 +15776,45 @@ snapshots: - typescript - universal-cookie - vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)): - dependencies: - "@vitest/expect": 4.1.7 - "@vitest/mocker": 4.1.7(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) - "@vitest/pretty-format": 4.1.7 - "@vitest/runner": 4.1.7 - "@vitest/snapshot": 4.1.7 - "@vitest/spy": 4.1.7 - "@vitest/utils": 4.1.7 - es-module-lexer: 2.0.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.0.0 - tinybench: 2.9.0 - tinyexec: 1.0.2 + vitest@5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)): + dependencies: + "@types/chai": 5.2.3 + "@vitest/mocker": 5.0.5(vite@8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) + chai: 6.3.0 + es-module-lexer: 2.3.2 + expect-type: 1.4.0 + magic-string: 1.4.3 + obug: 3.0.0 + picomatch: 4.0.7 + std-env: 4.3.0 + tinybench: 6.2.2 + tinyexec: 1.3.1 + tinyglobby: 0.2.17 + vite: 8.0.15(@types/node@25.9.1)(esbuild@0.27.2)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0) + why-is-node-running: 3.2.1 + optionalDependencies: + "@opentelemetry/api": 1.9.1 + "@types/node": 25.9.1 + jsdom: 29.1.1 + transitivePeerDependencies: + - msw + + vitest@5.0.5(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(jsdom@29.1.1)(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)): + dependencies: + "@types/chai": 5.2.3 + "@vitest/mocker": 5.0.5(vite@8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0)) + chai: 6.3.0 + es-module-lexer: 2.3.2 + expect-type: 1.4.0 + magic-string: 1.4.3 + obug: 3.0.0 + picomatch: 4.0.7 + std-env: 4.3.0 + tinybench: 6.2.2 + tinyexec: 1.3.1 tinyglobby: 0.2.17 - tinyrainbow: 3.1.0 vite: 8.0.15(@types/node@25.9.1)(esbuild@0.28.0)(sass@1.100.0)(terser@5.45.0)(tsx@4.22.4)(yaml@2.9.0) - why-is-node-running: 2.3.0 + why-is-node-running: 3.2.1 optionalDependencies: "@opentelemetry/api": 1.9.1 "@types/node": 25.9.1 @@ -15838,10 +15859,10 @@ snapshots: vue: 3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54)) vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.35(typescript@6.0.3(patch_hash=d2a2f8424c52b9d75deeb15b1f2367352c31126ecb19c4b469da7b943f946a54))) - vue-eslint-parser@10.4.0(eslint@10.4.1(supports-color@8.1.1))(supports-color@8.1.1): + vue-eslint-parser@10.4.0(eslint@10.4.1(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - debug: 4.4.3(supports-color@8.1.1) - eslint: 10.4.1(supports-color@8.1.1) + debug: 4.4.3(supports-color@7.2.0) + eslint: 10.4.1(supports-color@7.2.0) eslint-scope: 9.1.2 eslint-visitor-keys: 5.0.1 espree: 11.2.0 @@ -15947,7 +15968,7 @@ snapshots: browserslist: 4.28.1 chrome-trace-event: 1.0.4 enhanced-resolve: 5.22.1 - es-module-lexer: 2.0.0 + es-module-lexer: 2.3.2 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -16027,10 +16048,7 @@ snapshots: dependencies: isexe: 2.0.0 - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 + why-is-node-running@3.2.1: {} with@7.0.2: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index b83575b6a1..ddf9fed8d0 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -8,22 +8,22 @@ allowBuilds: msgpackr-extract: false vue-demi: false minimumReleaseAgeExclude: - - "@effect/tsgo-darwin-arm64@0.47.2" - - "@effect/tsgo-darwin-x64@0.47.2" - - "@effect/tsgo-linux-arm64@0.47.2" - - "@effect/tsgo-linux-arm@0.47.2" - - "@effect/tsgo-linux-x64@0.47.2" - - "@effect/tsgo-win32-arm64@0.47.2" - - "@effect/tsgo-win32-x64@0.47.2" - - "@effect/tsgo@0.47.2" - - "@effect/language-service@0.87.3" - - "@effect/atom-vue@4.0.2" - - "@effect/platform-browser@4.0.2" - - "@effect/platform-node-shared@4.0.2" - - "@effect/platform-node@4.0.2" - - "@effect/sql-sqlite-node@4.0.2" - - "@effect/vitest@4.0.2" - - effect@4.0.2 + - "@effect/tsgo-darwin-arm64@0.56.0" + - "@effect/tsgo-darwin-x64@0.56.0" + - "@effect/tsgo-linux-arm64@0.56.0" + - "@effect/tsgo-linux-arm@0.56.0" + - "@effect/tsgo-linux-x64@0.56.0" + - "@effect/tsgo-win32-arm64@0.56.0" + - "@effect/tsgo-win32-x64@0.56.0" + - "@effect/tsgo@0.56.0" + - "@effect/language-service@0.87.5" + - "@effect/atom-vue@4.0.5" + - "@effect/platform-browser@4.0.5" + - "@effect/platform-node-shared@4.0.5" + - "@effect/platform-node@4.0.5" + - "@effect/sql-sqlite-node@4.0.5" + - "@effect/vitest@4.0.5" + - effect@4.0.5 overrides: date-fns: ^4.4.0 fast-check: ^4.9.0 diff --git a/repos/effect/.agents/skills/pull-requests/SKILL.md b/repos/effect/.agents/skills/pull-requests/SKILL.md new file mode 100644 index 0000000000..5375c38f19 --- /dev/null +++ b/repos/effect/.agents/skills/pull-requests/SKILL.md @@ -0,0 +1,50 @@ +--- +name: pull-requests +description: Pull request finalization. Use when a change works and is about to be opened as a pull request, or when updating or continuing an existing one. +--- + +A pull request is ready when its tests, implementation, comments, and changeset +are each the simplest that cover the intended behavior. Draft PRs can be used +earlier; finishing means making the PR ready for review. + +## Workflow + +Run each step in a fresh-context subagent when available; otherwise run it +yourself. Pass along the task context and prior results so each step can check its gate. + +1. Keep tests focused. Read [test-development](../test-development/SKILL.md) for + test placement and type. Cover each intended behavior once, in the existing + test file for the module. + For changes needing no tests, record why. + Continue when removing any remaining case would leave intended behavior + uncovered, or no tests are needed. +2. Simplify the implementation. With the tests passing, look for a simpler or + more idiomatic version: reuse helpers and patterns from nearby source and + [effect-development](../effect-development/SKILL.md), and remove debugging + code, scaffolding, and changes unrelated to the task. + Continue when applicable targeted tests pass and every hunk in the diff + from the merge base is required by the task. +3. Review the full diff from the merge base as a maintainer would: correctness, + failure and interruption paths, resource cleanup, naming and API + consistency with neighboring modules, and documentation. Fix findings and + review again. + Continue when a review pass produces no findings. +4. Clean up. Remove comments that restate code or narrate the change; keep the + rest short and about why. Finalize the changeset with + [changesets](../changesets/SKILL.md). + Continue when comments explain only what code cannot, and the changeset + describes the final consumer impact or the no-changeset reason is recorded. +5. Run the validation in the [AGENTS.md validation table](../../AGENTS.md#validation) + for each change type in the diff. Fix failures caused by the change; if + fixes alter the diff, repeat the affected passes. + Continue when applicable checks pass or commands that cannot run and their + blockers are recorded. +6. Open or update the pull request. Title: a short imperative summary. + Description: the problem addressed, notable decisions, and `Closes #` for each + GitHub issue resolved. Do not narrate the diff. Mark the PR ready for review. + Continue when the final changes are pushed, the description matches the + final diff, and the PR is ready for review. + +The task is complete when each step's gate holds, validation has passed or +been reported as not runnable with reasons, and the pull request is ready for +review with a description matching the final diff. diff --git a/repos/effect/.changeset/config.json b/repos/effect/.changeset/config.json index de158b0487..b776b5a75b 100644 --- a/repos/effect/.changeset/config.json +++ b/repos/effect/.changeset/config.json @@ -26,6 +26,7 @@ "@effect/atom-vue", "@effect/docgen", "@effect/doctest", + "@effect/graphql-generator", "@effect/openapi-generator", "@effect/opentelemetry", "@effect/platform-browser", diff --git a/repos/effect/.github/actions/deploy-website/action.yml b/repos/effect/.github/actions/deploy-website/action.yml deleted file mode 100644 index 436ec4944e..0000000000 --- a/repos/effect/.github/actions/deploy-website/action.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Deploy website -description: Request API reference publication and deployment from the website repository. -inputs: - channel: - description: API reference channel that was published - required: true - dispatch-token: - description: Token with permission to dispatch workflows in Effect-TS/website - required: true - revision: - description: Full Git commit SHA that was published - required: true - -runs: - using: composite - steps: - - name: Request website API reference publication - shell: bash - env: - CHANNEL: ${{ inputs.channel }} - GH_TOKEN: ${{ inputs.dispatch-token }} - REVISION: ${{ inputs.revision }} - run: | - if [[ ! "$CHANNEL" =~ ^v[34]$ || ! "$REVISION" =~ ^[a-f0-9]{40}$ ]]; then - echo "::error::Website deployment requires channel v3 or v4 and a full Git commit SHA" - exit 1 - fi - - jq -n \ - --arg channel "$CHANNEL" \ - --arg revision "$REVISION" \ - '{ - event_type: "publish-api-reference", - client_payload: { - repository: "Effect-TS/effect", - channel: $channel, - revision: $revision - } - }' | - gh api --method POST repos/Effect-TS/website/dispatches --input - diff --git a/repos/effect/.github/workflows/check.yml b/repos/effect/.github/workflows/check.yml index b52e80d53f..fbb21ced9b 100644 --- a/repos/effect/.github/workflows/check.yml +++ b/repos/effect/.github/workflows/check.yml @@ -50,7 +50,7 @@ jobs: - name: Install dependencies uses: ./.github/actions/setup with: - deno-version: v2.9.4 + deno-version: v2.9.7 - run: pnpm check env: # Leave memory headroom for the runner by collecting the Go heap earlier. @@ -130,7 +130,7 @@ jobs: bun: "" command: pnpm test --max-concurrency=10 - runtime: Deno - deno: v2.9.4 + deno: v2.9.7 bun: "" command: deno task test --max-concurrency=10 - runtime: Bun @@ -148,6 +148,7 @@ jobs: docker pull mcr.microsoft.com/mssql/server:2022-latest & docker pull vitess/vttestserver:mysql80 & docker pull redis:alpine & + docker pull coredns/coredns:1.14.7 & wait - name: Install dependencies @@ -156,7 +157,39 @@ jobs: deno-version: ${{ matrix.deno }} bun-version: ${{ matrix.bun }} - name: Test + if: matrix.runtime != 'Deno' run: ${{ matrix.command }} + - name: Test with PostgreSQL lifecycle capture + if: matrix.runtime == 'Deno' + shell: bash + env: + PG_LIFECYCLE_DIAGNOSTICS: "1" + PG_LIFECYCLE_LOG: ${{ runner.temp }}/pg-lifecycle/lifecycle.log + run: | + capture_dir="${{ runner.temp }}/pg-lifecycle" + mkdir -p "$capture_dir" + started_at=$(date --iso-8601=seconds) + docker events --since "$started_at" --format '{{json .}}' > "$capture_dir/docker-events.jsonl" 2> "$capture_dir/docker-events.stderr" & + events_pid=$! + cleanup() { + # Reap only the capture process started here; preserve the test exit code. + kill "$events_pid" 2>/dev/null || true + wait "$events_pid" 2>/dev/null || true + # The runner owns the output file; only journal access needs sudo. + # shellcheck disable=SC2024 + sudo -n journalctl -u docker.service --since "$started_at" --no-pager -o short-iso-precise > "$capture_dir/docker-journal.log" 2>&1 || true + } + trap cleanup EXIT + trap 'exit 130' INT + trap 'exit 143' TERM + ${{ matrix.command }} 2>&1 | tee "$capture_dir/tests.log" + - name: Upload PostgreSQL lifecycle diagnostics + if: always() && matrix.runtime == 'Deno' && (failure() || cancelled()) + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: deno-pg-lifecycle-${{ github.run_attempt }} + path: ${{ runner.temp }}/pg-lifecycle + if-no-files-found: warn doctest: name: Test (Documentation) diff --git a/repos/effect/.github/workflows/npm-promote.yml b/repos/effect/.github/workflows/npm-promote.yml new file mode 100644 index 0000000000..18c9ab071d --- /dev/null +++ b/repos/effect/.github/workflows/npm-promote.yml @@ -0,0 +1,67 @@ +name: npm promote +on: + schedule: + - cron: "*/10 * * * *" + workflow_run: + workflows: [Release] + types: [completed] + branches: [main] + workflow_dispatch: + inputs: + dry-run: + description: Print what would change without moving dist-tags or touching issues + type: boolean + default: false + +# Promotions never overlap. A running promotion is never cancelled; a newer +# queued run replaces an older queued one, which is safe because every run +# re-reads the registry. +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + +permissions: {} + +jobs: + promote: + name: Promote + # NPM_PROMOTE_PAUSED is the kill switch for a bad release still on `staging`. + if: >- + github.repository_owner == 'Effect-Ts' + && github.ref == 'refs/heads/main' + && vars.NPM_PROMOTE_PAUSED != 'true' + runs-on: ubuntu-latest + timeout-minutes: 15 + # The npm trusted publisher configuration for dist-tags pins this + # workflow file and environment. + environment: npm-promote + permissions: + contents: read + # Records website deploys, so a failed or interrupted deploy is retried. + deployments: write + # npm trusted publishing: dist-tag writes authenticate over OIDC. + id-token: write + issues: write + steps: + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + with: + ref: main + # The overdue check reads the commit that bumped the version. + fetch-depth: 0 + persist-credentials: false + - name: Install dependencies + uses: ./.github/actions/setup + - name: Upgrade npm for OIDC dist-tag support + run: npm install -g npm@^11.21.0 + # Promotes the release, deploys the website for it and keeps the tracking issue up to date. + - name: Promote staged release + env: + DRY_RUN: ${{ inputs.dry-run }} + GITHUB_TOKEN: ${{ github.token }} + WEBSITE_DISPATCH_TOKEN: ${{ secrets.WEBSITE_DISPATCH_TOKEN }} + run: | + args=() + if [[ "$DRY_RUN" == "true" ]]; then + args+=(--dry-run) + fi + node packages/tools/npm-promote/src/bin.ts "${args[@]}" diff --git a/repos/effect/.github/workflows/release-queue.yml b/repos/effect/.github/workflows/release-queue.yml index 1235f5adf5..c23e57485d 100644 --- a/repos/effect/.github/workflows/release-queue.yml +++ b/repos/effect/.github/workflows/release-queue.yml @@ -10,16 +10,7 @@ on: permissions: {} jobs: - approval-gate: - if: github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository - runs-on: ubuntu-latest - environment: fork - steps: - - run: echo "Fork PR approved by maintainer." - update: - needs: [approval-gate] - if: always() && (needs.approval-gate.result == 'success' || needs.approval-gate.result == 'skipped') name: Update runs-on: ubuntu-latest timeout-minutes: 10 @@ -31,6 +22,15 @@ jobs: with: fetch-depth: 0 token: ${{ secrets.EFFECT_BOT_GH }} + # Non-cone mode excludes root files too. Git preserves this restriction across gh pr checkout. + # Keep full checkouts for same-repo PRs, pushes, and comments used by release/rebase paths. + - name: Limit fork checkout to changesets + if: github.event.pull_request && github.event.pull_request.head.repo.full_name != github.repository + run: git sparse-checkout set --no-cone '/.changeset/' + # This checks out untrusted fork code with privileged bot credentials available to subsequent steps. + # Sparse checkout reduces exposed files; it is not a security boundary. + # No step may execute code from the working tree (including installs, builds, or repo scripts). + # The pinned release action only reads changeset files on the fork PR path. - run: gh pr checkout ${{ github.event.pull_request.number }} if: github.event.pull_request env: diff --git a/repos/effect/.github/workflows/release.yml b/repos/effect/.github/workflows/release.yml index 43931cad55..ee71d69125 100644 --- a/repos/effect/.github/workflows/release.yml +++ b/repos/effect/.github/workflows/release.yml @@ -41,10 +41,6 @@ jobs: # automatically to ensure workflows get triggered on the changesets # release branch. github-token: ${{ secrets.CHANGESET_GITHUB_TOKEN }} - - name: Deploy website - if: steps.changesets.outputs.published == 'true' - uses: ./.github/actions/deploy-website - with: - channel: v4 - dispatch-token: ${{ secrets.WEBSITE_DISPATCH_TOKEN }} - revision: ${{ github.sha }} + # Packages are published under the `staging` dist-tag. The npm promote + # workflow moves `latest` once npm serves every package, then deploys the + # website. diff --git a/repos/effect/.oxlintrc.json b/repos/effect/.oxlintrc.json index b75ec470da..3fcaaf516b 100644 --- a/repos/effect/.oxlintrc.json +++ b/repos/effect/.oxlintrc.json @@ -10,6 +10,7 @@ "**/CHANGELOG.md", "packages/effect/typeperf/**/*", "packages/effect/src/StandardSchema.ts", + "packages/tools/graphql-generator/test/generated/**/*.graphql.ts", "!scratchpad/**/*", "**/.*", "!.agents", diff --git a/repos/effect/LLMS.md b/repos/effect/LLMS.md index 963a7a5bd5..eaaabca6dc 100644 --- a/repos/effect/LLMS.md +++ b/repos/effect/LLMS.md @@ -370,6 +370,30 @@ Build http clients with the `HttpClient` module. Test handlers through an in-memory typed client with `HttpApiTest`, without starting an HTTP server or touching a real database. +## Typed GraphQL clients with `effect/graphql` + +Use the `effect/graphql` modules to call GraphQL APIs with typed +operations. Run `graphqlgen` from `@effect/graphql-generator` to generate +operations from `.graphql` documents, then build a client with +`GraphQLClient.make` and provide a transport from `GraphQLProtocol`. + +- **[Getting started with GraphQL clients](./ai-docs/src/52_graphql/10_basics.ts)**: + Define a query, build a typed client service over HTTP with an auth + middleware, and page through a cursor connection. +- **[Testing code that uses a GraphQL client](./ai-docs/src/52_graphql/20_testing.ts)**: + Replace a client service with `GraphQLClient.layerTest`, answering each + operation from a handler instead of a server. +- **[Batching lookups with GraphQLResolver](./ai-docs/src/52_graphql/30_batching.ts)**: + Collect concurrent lookups by id into one `nodes(ids:)` request with + `GraphQLResolver`, instead of one request per id. +- **[Batching single-item lookups with aliases](./ai-docs/src/52_graphql/40_aliased-batching.ts)**: + When an API has no field that takes a list of keys, `GraphQLResolver.aliased` + repeats a generated operation under aliases, so concurrent lookups share one + request and keep their generated types. +- **[Handling GraphQL errors, retries and rate limits](./ai-docs/src/52_graphql/50_errors-and-retries.ts)**: + Read rate-limit headers in a middleware, tell GraphQL errors apart by their + fields, and retry timeouts and rate limits with `Effect.retry`. + ## Working with child processes Use the `effect/process` modules to define child processes and run them with `ChildProcessSpawner`. diff --git a/repos/effect/MIGRATION.md b/repos/effect/MIGRATION.md index 4df8d9eafd..22d1555b5b 100644 --- a/repos/effect/MIGRATION.md +++ b/repos/effect/MIGRATION.md @@ -71,9 +71,8 @@ Moving these modules does not stabilize their APIs. ### Performance and Bundle Size The fiber runtime has been rewritten for reduced memory overhead and faster -execution. The core `effect` package supports aggressive tree-shaking — a -minimal Effect program bundles to ~6.3 KB (minified + gzipped). With Schema, -~15 KB. +execution. The core `effect` package supports aggressive tree-shaking. A +minimal Effect program bundles to 7.1 kB (minified + gzipped). --- diff --git a/repos/effect/README.md b/repos/effect/README.md index 8df9d3431d..4d9effea28 100644 --- a/repos/effect/README.md +++ b/repos/effect/README.md @@ -91,6 +91,7 @@ This monorepo contains the core `effect` package alongside integration packages | [`@effect/docgen`](packages/tools/docgen) | Documentation generator for Effect projects | [docs](https://effect.website/docs/v4/api/docgen) | | [`@effect/doctest`](packages/tools/doctest) | Runs JSDoc examples as Vitest tests | [docs](https://effect.website/docs/v4/api/doctest) | | [`@effect/openapi-generator`](packages/tools/openapi-generator) | Generate Effect code from OpenAPI specifications | [docs](https://effect.website/docs/v4/api/openapi-generator) | +| [`@effect/graphql-generator`](packages/tools/graphql-generator) | Generate Effect code from GraphQL documents | [docs](https://effect.website/docs/v4/api/graphql-generator) | ## License diff --git a/repos/effect/ai-docs/package.json b/repos/effect/ai-docs/package.json index 1c21dce107..13ef4319f8 100644 --- a/repos/effect/ai-docs/package.json +++ b/repos/effect/ai-docs/package.json @@ -27,8 +27,8 @@ "@effect/sql-sqlite-wasm": "workspace:*", "@effect/vitest": "workspace:*", "effect": "workspace:*", - "hono": "^4.13.12", - "nodemailer": "^10.0.14" + "hono": "^4.13.13", + "nodemailer": "^10.1.0" }, "devDependencies": { "@types/nodemailer": "^8.0.2" diff --git a/repos/effect/ai-docs/src/52_graphql/10_basics.ts b/repos/effect/ai-docs/src/52_graphql/10_basics.ts new file mode 100644 index 0000000000..1c4ff992df --- /dev/null +++ b/repos/effect/ai-docs/src/52_graphql/10_basics.ts @@ -0,0 +1,117 @@ +/** + * @title Getting started with GraphQL clients + * + * Define a query, build a typed client service over HTTP with an auth + * middleware, and page through a cursor connection. + */ +import { Config, Context, Effect, Layer, Redacted, Schema, Stream } from "effect" +import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLMiddleware, GraphQLProtocol } from "effect/graphql" +import { FetchHttpClient } from "effect/http" + +// Operations are usually generated: write them in `.graphql` files and run +// `graphqlgen` from `@effect/graphql-generator`, which writes a `.graphql.ts` +// module like the one below next to each document. +// +// query RepoIssues($owner: String!, $name: String!, $after: String) { +// repository(owner: $owner, name: $name) { +// issues(first: 50, after: $after) { +// pageInfo { hasNextPage endCursor } +// nodes { number title } +// } +// } +// } +// +// Each nested object selection has a Schema.Struct const and a same-named +// interface for its decoded type. The const handles decoding, encoding and +// `make`; use the interface in explicit type annotations when a named type +// is useful. Inferred types and editor hovers can expand structurally rather +// than showing the names, unlike the previous Schema.Opaque classes. +export const PageInfo = Schema.Struct({ + hasNextPage: Schema.Boolean, + endCursor: Schema.NullOr(Schema.String) +}) +export interface PageInfo extends Schema.Struct.Type {} + +export const Issue = Schema.Struct({ number: Schema.Int, title: Schema.String }) +export interface Issue extends Schema.Struct.Type {} + +export const IssueConnection = Schema.Struct({ + pageInfo: PageInfo, + nodes: Schema.NullOr(Schema.Array(Schema.NullOr(Issue))) +}) +export interface IssueConnection extends Schema.Struct.Type {} + +export const Repository = Schema.Struct({ issues: IssueConnection }) +export interface Repository extends Schema.Struct.Type {} + +export const RepoIssues = GraphQL.query("RepoIssues", { + document: + "query RepoIssues($owner:String!,$name:String!,$after:String){repository(owner:$owner,name:$name){issues(first:50,after:$after){pageInfo{hasNextPage endCursor}nodes{number title}}}}", + variables: { + owner: Schema.String, + name: Schema.String, + after: Schema.optional(Schema.NullOr(Schema.String)) + }, + result: Schema.Struct({ + repository: Schema.NullOr(Repository) + }) +}) + +// A middleware is a service that wraps every operation it is attached to. +// `mapRequest` builds one from a single request transform. +export class GitHubAuth extends GraphQLMiddleware.Service()("app/GitHubAuth") { + static readonly layer = Layer.effect( + GitHubAuth, + Effect.gen(function*() { + const token = yield* Config.Redacted("GITHUB_TOKEN") + return GraphQLMiddleware.mapRequest((request) => + Effect.succeed({ + ...request, + headers: { ...request.headers, authorization: `Bearer ${Redacted.value(token)}` } + }) + ) + }) + ) +} + +// A group is the set of operations a client exposes; the generator emits one +// per file. Attaching the middleware makes `GraphQLClient.make` require it. +export const GitHubGraphQLGroup = GraphQLGroup.make(RepoIssues).middleware(GitHubAuth) + +// The client has one method per operation, named after it. +export class GitHub extends Context.Service< + GitHub, + GraphQLClient.FromGroup +>()("app/GitHub") { + static readonly layerTest = GraphQLClient.layerTest(GitHub, GitHubGraphQLGroup) + + static readonly layer = Layer.effect(GitHub, GraphQLClient.make(GitHubGraphQLGroup)).pipe( + Layer.provide(GitHubAuth.layer), + // Queries and mutations are sent as `POST`. Subscriptions use graphql-sse + // here, or graphql-ws with `GraphQLProtocol.layerWebSocket`. + Layer.provide(GraphQLProtocol.layerHttp({ url: "https://api.github.com/graphql" })), + Layer.provide(FetchHttpClient.layer) + ) +} + +export const program = Effect.gen(function*() { + const github = yield* GitHub + + // Variables are encoded and the result decoded through the Schemas. Any + // `errors` in the response fail with a `GraphQLClientError`; pass + // `{ partial: true }` as the second argument to get them with the data. + const { repository } = yield* github.RepoIssues({ owner: "Effect-TS", name: "effect" }) + yield* Effect.log(`First page has ${repository?.issues.nodes?.length ?? 0} issues`) + + // `items` pages through the connection by driving `$after`, one request at + // a time and only as the stream is pulled. + const titles = yield* GraphQLClient.items(github.RepoIssues, { + variables: { owner: "Effect-TS", name: "effect" }, + connection: (result) => result.repository?.issues + }).pipe( + Stream.take(120), + Stream.map((issue) => issue?.title), + Stream.runCollect + ) + yield* Effect.log(`Fetched ${titles.length} issues`) +}).pipe(Effect.provide(GitHub.layer)) diff --git a/repos/effect/ai-docs/src/52_graphql/20_testing.ts b/repos/effect/ai-docs/src/52_graphql/20_testing.ts new file mode 100644 index 0000000000..0ea9c6e254 --- /dev/null +++ b/repos/effect/ai-docs/src/52_graphql/20_testing.ts @@ -0,0 +1,45 @@ +/** + * @title Testing code that uses a GraphQL client + * + * Replace a client service with `GraphQLClient.layerTest`, answering each + * operation from a handler instead of a server. + */ +import { assert, describe, it } from "@effect/vitest" +import { Effect } from "effect" +import { GitHub } from "./10_basics.ts" + +// Code under test that depends on the `GitHub` client service. +const issueTitles = (owner: string, name: string) => + GitHub.use((github) => github.RepoIssues({ owner, name })).pipe( + Effect.map(({ repository }) => repository?.issues.nodes?.map((issue) => issue?.title) ?? []) + ) + +// The service binds `GraphQLClient.layerTest(GitHub, GitHubGraphQLGroup)` once +// as a static helper. Handlers are keyed by operation name, receive the +// caller's variables and options, and return results in their decoded form. +// Nothing is encoded or decoded and no middleware runs. An operation without +// a handler dies with an `UnimplementedError` defect. +const GitHubTest = GitHub.layerTest({ + RepoIssues: ({ owner, name }) => + Effect.succeed({ + repository: { + issues: { + pageInfo: { hasNextPage: false, endCursor: null }, + nodes: [{ number: 1, title: `Hello from ${owner}/${name}` }] + } + } + }) +}) + +describe("issueTitles", () => { + it.effect("returns the titles of the first page", () => + Effect.gen(function*() { + const titles = yield* issueTitles("Effect-TS", "effect") + assert.deepStrictEqual(titles, ["Hello from Effect-TS/effect"]) + }).pipe(Effect.provide(GitHubTest))) +}) + +// `layerTest` uses `makeTest`, which skips the protocol and cannot return +// partial data together with `errors`. To test that, or the encode and decode +// path, build the real client with `GraphQLClient.make` over a scripted +// `GraphQLProtocol` layer (see `GraphQLProtocol`). diff --git a/repos/effect/ai-docs/src/52_graphql/30_batching.ts b/repos/effect/ai-docs/src/52_graphql/30_batching.ts new file mode 100644 index 0000000000..44242c1ce1 --- /dev/null +++ b/repos/effect/ai-docs/src/52_graphql/30_batching.ts @@ -0,0 +1,118 @@ +/** + * @title Batching lookups with GraphQLResolver + * + * Collect concurrent lookups by id into one `nodes(ids:)` request with + * `GraphQLResolver`, instead of one request per id. + */ +import { type Cause, Context, Effect, Layer, RequestResolver, Schema } from "effect" +import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol, GraphQLResolver } from "effect/graphql" +import { FetchHttpClient } from "effect/http" +import { GitHubAuth } from "./10_basics.ts" + +// The generator's output for `repo-nodes.graphql`: +// +// query RepoNodes($ids: [ID!]!) { +// nodes(ids: $ids) { __typename ... on Repository { nameWithOwner } } +// } +// +// Generated modules import shared codecs and the possible `__typename`s of +// each interface from the module the generator writes next to the schema +// (`import * as Shared from "../schema.graphql.ts"`); here `Shared` is +// declared inline. +const Shared = { ID: Schema.String } +declare namespace Shared { + export namespace Typename { + export type Node = "Issue" | "PullRequest" | "Repository" | "User" + } +} + +export const Repository = Schema.Struct({ + __typename: Schema.Literal("Repository"), + nameWithOwner: Schema.String +}) +export interface Repository extends Schema.Struct.Type {} + +// Unselected node types are represented by `otherTypename`. +export const NodeOther = Schema.Struct({ + __typename: GraphQL.otherTypename()(["Repository"]) +}) +export interface NodeOther extends Schema.Struct.Type {} + +/** `query RepoNodes` */ +export const RepoNodes = GraphQL.query("RepoNodes", { + document: { + variables: [ + { name: "ids", body: "[ID!]!" } + ], + selections: [ + { name: "nodes", body: ["(ids:$", "ids", "){__typename...on Repository{nameWithOwner}}"] } + ], + fragments: [] + }, + variables: { + ids: Schema.Array(Shared.ID) + }, + result: Schema.Struct({ + nodes: Schema.Array(Schema.NullOr(Schema.Union([ + Repository, + NodeOther + ]))) + }) +}) +export declare namespace RepoNodes { + export type Variables = typeof RepoNodes.variables.Type + export type Result = typeof RepoNodes.result.Type +} + +/** Every operation in repo-nodes.graphql. */ +export const RepoNodesGraphQLGroup = GraphQLGroup.make(RepoNodes) + +// Your code: attach the middleware to the generated group. +export const GitHubGraphQLGroup = RepoNodesGraphQLGroup.middleware(GitHubAuth) + +export class GitHub extends Context.Service< + GitHub, + GraphQLClient.FromGroup & { + getRepo(id: string): Effect.Effect< + Repository, + GraphQL.Error | Cause.NoSuchElementError + > + } +>()("app/GitHub") { + static readonly layer = Layer.effect( + GitHub, + Effect.gen(function*() { + const client = yield* GraphQLClient.make(GitHubGraphQLGroup) + + // Null entries and non-Repository nodes fail with NoSuchElementError. + // GitHub accepts at most 100 ids per request. + // + // GitHubAuth reads one token from config, so every lookup can share a + // batch. If a middleware `requires` a per-request service, such as the + // signed-in user, `batchKey` is required and keeps lookups for different + // users in separate calls: + // + // batchKey: (context) => Context.get(context, CurrentUser).id + const RepoById = GraphQLResolver.ordered(client.RepoNodes, { + variables: (ids: ReadonlyArray) => ({ ids }), + path: ["nodes"], + typename: "Repository" + }).pipe(RequestResolver.batchN(100)) + return { ...client, getRepo: GraphQLResolver.request(RepoById) } + }) + ).pipe( + Layer.provide(GitHubAuth.layer), + Layer.provide(GraphQLProtocol.layerHttp({ url: "https://api.github.com/graphql" })), + Layer.provide(FetchHttpClient.layer) + ) +} + +export const repoNames = Effect.fn("repoNames")(function*(ids: ReadonlyArray) { + const github = yield* GitHub + const repos = yield* Effect.forEach(ids, github.getRepo, { concurrency: "unbounded" }) + return repos.map((repo) => repo.nameWithOwner) +}) + +export const program = repoNames(["R_1", "R_2"]).pipe( + Effect.provide(GitHub.layer) +) diff --git a/repos/effect/ai-docs/src/52_graphql/40_aliased-batching.ts b/repos/effect/ai-docs/src/52_graphql/40_aliased-batching.ts new file mode 100644 index 0000000000..45e0325a91 --- /dev/null +++ b/repos/effect/ai-docs/src/52_graphql/40_aliased-batching.ts @@ -0,0 +1,124 @@ +/** + * @title Batching single-item lookups with aliases + * + * When an API has no field that takes a list of keys, `GraphQLResolver.aliased` + * repeats a generated operation under aliases, so concurrent lookups share one + * request and keep their generated types. + */ +import { Context, Effect, Layer, Schema } from "effect" +import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol, GraphQLResolver } from "effect/graphql" +import { FetchHttpClient } from "effect/http" +import { GitHubAuth } from "./10_basics.ts" + +// The generator's output for `pr.graphql`: +// +// query PullRequest($owner: String!, $name: String!, $number: Int!) { +// repository(owner: $owner, name: $name) { +// pullRequest(number: $number) { number title } +// } +// } +// +// Generated modules import shared codecs, such as `Int`, from the module the +// generator writes next to the schema (`import * as Shared from +// "../schema.graphql.ts"`); here `Shared` is declared inline. +const Shared = { Int: Schema.Number.check(Schema.isInt32()) } + +export const PullRequestPullRequest = Schema.Struct({ + number: Shared.Int, + title: Schema.String +}) +export interface PullRequestPullRequest extends Schema.Struct.Type {} + +export const Repository = Schema.Struct({ + pullRequest: Schema.NullOr(PullRequestPullRequest) +}) +export interface Repository extends Schema.Struct.Type {} + +// The generator gives queries and mutations their document as a +// `GraphQL.DocumentTemplate`. The odd entries of each `body` are the names +// `aliased` renames per slice; joined together they are the printed document. +/** `query PullRequest` */ +export const PullRequest = GraphQL.query("PullRequest", { + document: { + variables: [ + { name: "owner", body: "String!" }, + { name: "name", body: "String!" }, + { name: "number", body: "Int!" } + ], + selections: [ + { + name: "repository", + body: ["(owner:$", "owner", " name:$", "name", "){pullRequest(number:$", "number", "){number title}}"] + } + ], + fragments: [] + }, + variables: { + owner: Schema.String, + name: Schema.String, + number: Shared.Int + }, + result: Schema.Struct({ + repository: Schema.NullOr(Repository) + }) +}) +export declare namespace PullRequest { + export type Variables = typeof PullRequest.variables.Type + export type Result = typeof PullRequest.result.Type +} + +/** Every operation in pr.graphql. */ +export const PrGraphQLGroup = GraphQLGroup.make(PullRequest) + +// Your code: attach the middleware to the generated group. +export const GitHubGraphQLGroup = PrGraphQLGroup.middleware(GitHubAuth) + +export class GitHub extends Context.Service< + GitHub, + GraphQLClient.FromGroup & { + readonly getPullRequest: ( + variables: GraphQL.Variables + ) => Effect.Effect, GraphQL.Error> + } +>()("app/GitHub") { + static readonly layer = Layer.effect( + GitHub, + Effect.gen(function*() { + const client = yield* GraphQLClient.make(GitHubGraphQLGroup) + + // Concurrent calls go out as one POST whose root fields are aliased + // `_0_repository`, `_1_repository`, and so on. Each slice is decoded + // with the generated result Schema, and a GraphQL error under + // `_1_repository` fails only that call. + // + // A batch holds 10 slices by default, because GitHub's query cost and + // timeouts grow with the size of the query. Pipe + // `RequestResolver.batchN` to change it. + const PullRequests = GraphQLResolver.aliased(client.PullRequest) + + // `request` turns the resolver into a lookup by the operation's + // variables, as for `ordered` and `findById`. + return { ...client, getPullRequest: GraphQLResolver.request(PullRequests) } + }) + ).pipe( + Layer.provide(GitHubAuth.layer), + Layer.provide(GraphQLProtocol.layerHttp({ url: "https://api.github.com/graphql" })), + Layer.provide(FetchHttpClient.layer) + ) +} + +export const pullRequestTitles = Effect.fn("pullRequestTitles")(function*(numbers: ReadonlyArray) { + const github = yield* GitHub + const results = yield* Effect.forEach( + numbers, + (number) => github.getPullRequest({ owner: "Effect-TS", name: "effect", number }), + { concurrency: "unbounded" } + ) + // `repository` and `pullRequest` are nullable, so a missing pull request is + // `null` rather than an error that would fail every slice. + return results.map((result) => result.repository?.pullRequest?.title ?? null) +}) + +export const program = pullRequestTitles([1, 2, 3]).pipe( + Effect.provide(GitHub.layer) +) diff --git a/repos/effect/ai-docs/src/52_graphql/50_errors-and-retries.ts b/repos/effect/ai-docs/src/52_graphql/50_errors-and-retries.ts new file mode 100644 index 0000000000..72f6cdfa11 --- /dev/null +++ b/repos/effect/ai-docs/src/52_graphql/50_errors-and-retries.ts @@ -0,0 +1,74 @@ +/** + * @title Handling GraphQL errors, retries and rate limits + * + * Read rate-limit headers in a middleware, tell GraphQL errors apart by their + * fields, and retry timeouts and rate limits with `Effect.retry`. + */ +import { Duration, Effect, Layer, Schedule } from "effect" +import { type GraphQLClientError, GraphQLMiddleware } from "effect/graphql" +import { GitHub } from "./10_basics.ts" + +// Middleware see each response's HTTP `status` and `headers` on the result +// `next` returns, including responses with GraphQL `errors`. A failed call +// keeps them, and `GraphQLClientError` exposes them as `headers` and +// `status`. Attach it with `GraphQLGroup.make(...).middleware(RateLimit)`. +export class RateLimit extends GraphQLMiddleware.Service()("app/RateLimit") { + static readonly layer = Layer.succeed(RateLimit, { + execute: ({ next, request }) => + Effect.tap(next(request), (result) => { + const remaining = Number(result.headers?.["x-ratelimit-remaining"]) + return remaining < 500 + ? Effect.logWarning(`GitHub rate limit: ${remaining} points left`) + : Effect.void + }), + subscribe: ({ next, request }) => next(request) + }) +} + +// GraphQL errors keep fields the specification doesn't define as JSON, such +// as GitHub's top-level `type` (`NOT_FOUND`, `FORBIDDEN`, `RATE_LIMITED`). +export const hasErrorType = (error: GraphQLClientError.GraphQLClientError, type: string) => + error.reason._tag === "ResponseError" && error.reason.errors.every((entry) => entry.type === type) + +// `isRetryable` is true for network failures, for 429 or 5xx responses, and +// for any error with a `Retry-After` header, whatever its status. That covers +// GitHub's 502 and 504 query timeouts, even with a GraphQL `errors` body, and +// its secondary rate limits (403 or 429 with `retry-after`). A primary rate +// limit can come without `retry-after`, with `x-ratelimit-remaining: 0`, so +// check that header too. +const rateLimited = (error: GraphQLClientError.GraphQLClientError) => error.headers?.["x-ratelimit-remaining"] === "0" + +// Wait for `retryAfter` when it is set, and until `x-ratelimit-reset` (epoch +// seconds) on a primary rate limit. GitHub may ban an integration that keeps +// retrying while rate limited, so don't retry with a plain backoff. +const gitHubRetry = Schedule.exponential("1 second").pipe( + Schedule.setInputType(), + Schedule.modifyDelay(({ duration, input, now }) => { + if (input.retryAfter !== undefined) return Effect.succeed(input.retryAfter) + if (!rateLimited(input)) return Effect.succeed(duration) + const reset = Number(input.headers?.["x-ratelimit-reset"]) * 1000 + return Effect.succeed(Number.isFinite(reset) ? Duration.millis(Math.max(0, reset - now)) : Duration.minutes(1)) + }) +) + +// The client never retries queries or mutations on its own. Retry only +// mutations that are safe to send twice, and with `GraphQLClient.pages`, +// retry inside a middleware, because `Stream.retry` starts again from the +// first page. Subscriptions reconnect on their own after a retryable failure, +// on `GraphQLClient.defaultSubscriptionRetry`, which waits for `retryAfter`. +// A primary rate limit without `retry-after` isn't retryable, so it ends the +// subscription; wait until `x-ratelimit-reset` before subscribing again. +export const retryGitHub = (effect: Effect.Effect) => + Effect.retry(effect, { + schedule: gitHubRetry, + while: (error) => error.isRetryable || rateLimited(error), + times: 5 + }) + +export const program = Effect.gen(function*() { + const github = yield* GitHub + const result = yield* retryGitHub(github.RepoIssues({ owner: "Effect-TS", name: "missing" })).pipe( + Effect.catchIf((error) => hasErrorType(error, "NOT_FOUND"), () => Effect.succeed(null)) + ) + yield* Effect.log(result === null ? "No such repository" : `${result.repository?.issues.nodes?.length} issues`) +}).pipe(Effect.provide(GitHub.layer)) diff --git a/repos/effect/ai-docs/src/52_graphql/index.md b/repos/effect/ai-docs/src/52_graphql/index.md new file mode 100644 index 0000000000..d811a6604a --- /dev/null +++ b/repos/effect/ai-docs/src/52_graphql/index.md @@ -0,0 +1,6 @@ +## Typed GraphQL clients with `effect/graphql` + +Use the `effect/graphql` modules to call GraphQL APIs with typed +operations. Run `graphqlgen` from `@effect/graphql-generator` to generate +operations from `.graphql` documents, then build a client with +`GraphQLClient.make` and provide a transport from `GraphQLProtocol`. diff --git a/repos/effect/deno.json b/repos/effect/deno.json index 38de0651a0..3b618e5262 100644 --- a/repos/effect/deno.json +++ b/repos/effect/deno.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/denoland/deno/refs/heads/main/cli/schemas/config-file.v1.json", "nodeModulesDir": "manual", - "unstable": ["bare-node-builtins", "node-globals"], + "unstable": ["bare-node-builtins", "node-globals", "net"], "workspace": ["./packages/*", "./packages/platform/*"], "exclude": [ "**/*.mjs", diff --git a/repos/effect/dprint.json b/repos/effect/dprint.json index 7d1a121c60..0622d2e264 100644 --- a/repos/effect/dprint.json +++ b/repos/effect/dprint.json @@ -21,6 +21,7 @@ "**/*.tsbuildinfo", "**/CHANGELOG.md", "packages/effect/src/StandardSchema.ts", + "packages/tools/graphql-generator/test/generated/**/*.graphql.ts", "!scratchpad/**/*", "**/.*", "!.agents", diff --git a/repos/effect/migration/annotations/effect__Channel.yaml b/repos/effect/migration/annotations/effect__Channel.yaml index a03978a159..06cbc912bf 100644 --- a/repos/effect/migration/annotations/effect__Channel.yaml +++ b/repos/effect/migration/annotations/effect__Channel.yaml @@ -114,7 +114,7 @@ note: "Use Channel.mapInput(self, (value) => Effect.succeed(f(value))); v4 consolidated pure and effectful input mapping." "effect/Channel#mapInputInEffect": replacement: "Channel.mapInput" - note: "Renamed to mapInput; the mapper remains effectful." + note: "Renamed to mapInput; the mapper remains effectful. Both overloads retain mapper service requirements in the resulting channel, so provide those services before running it." "effect/Channel#mapOut": replacement: "Channel.map" note: "Renamed to map; the v4 mapper also receives the element index." diff --git a/repos/effect/migration/annotations/effect__DateTime.yaml b/repos/effect/migration/annotations/effect__DateTime.yaml index f6c65c930d..72dcbd320c 100644 --- a/repos/effect/migration/annotations/effect__DateTime.yaml +++ b/repos/effect/migration/annotations/effect__DateTime.yaml @@ -22,12 +22,16 @@ "effect/DateTime#DateTime.UnitSingular": replacement: "DateTime.DateTime.UnitSingular" note: "Use millisecond instead of milli; the other singular unit strings remain." +"effect/DateTime#distance": + include: true + replacement: "Duration.toMillis(DateTime.distance(self, other))" + note: "V3 returns signed milliseconds; v4 returns a signed Duration (other minus self). Convert it with Duration.toMillis when a numeric millisecond result is required." "effect/DateTime#distanceDuration": - replacement: "Duration.millis(Math.abs(DateTime.distance(self, other)))" - note: "DateTime.distance returns signed milliseconds in v4; take the absolute value and construct a Duration to preserve v3 behavior." + replacement: "Duration.abs(DateTime.distance(self, other))" + note: "V4 DateTime.distance already returns a signed Duration. Use Duration.abs to preserve the non-negative distance returned by v3; Math.abs and Duration.millis expect numbers, not Durations." "effect/DateTime#distanceDurationEither": replacement: "DateTime.distance + Result" - note: "Compute the signed millisecond distance, wrap its absolute Duration as Result.succeed when positive and Result.fail when non-positive; v4 uses Result instead of Either." + note: "Let diff = DateTime.distance(self, other), a signed Duration. Use Duration.isPositive(diff) ? Result.succeed(Duration.abs(diff)) : Result.fail(Duration.abs(diff)) to preserve v3 behavior, including equal dates producing a failure with Duration.zero. V4 uses Result instead of Either." "effect/DateTime#greaterThan": replacement: "DateTime.isGreaterThan" note: "The comparison was renamed with the is prefix." diff --git a/repos/effect/migration/annotations/effect__ExecutionPlan.yaml b/repos/effect/migration/annotations/effect__ExecutionPlan.yaml index bd73e986f7..191ccb2610 100644 --- a/repos/effect/migration/annotations/effect__ExecutionPlan.yaml +++ b/repos/effect/migration/annotations/effect__ExecutionPlan.yaml @@ -1,9 +1,9 @@ effect/ExecutionPlan#ExecutionPlan: replacement: "ExecutionPlan.ExecutionPlan" - note: "The plan type remains; withRequirements was renamed to captureRequirements." + note: "The plan type remains; withRequirements was renamed to captureRequirements. Step schedules use Schedule; captureRequirements supplies captured services to schedule initialization and execution." effect/ExecutionPlan#make: replacement: "ExecutionPlan.make" - note: "The variadic execution-plan constructor remains unchanged." + note: "The constructor remains variadic. Its inferred error channel includes failures from step layers, predicates, and schedules; requirements include services needed by all three across every step." effect/ExecutionPlan#TypesBase: replacement: "ExecutionPlan.ConfigBase" note: "The base type for execution-plan step configuration was renamed." diff --git a/repos/effect/migration/annotations/effect__Scheduler.yaml b/repos/effect/migration/annotations/effect__Scheduler.yaml index 06e3b0191a..26b764e9a7 100644 --- a/repos/effect/migration/annotations/effect__Scheduler.yaml +++ b/repos/effect/migration/annotations/effect__Scheduler.yaml @@ -18,7 +18,7 @@ effect/Scheduler#makeMatrix: note: "Matrix routing was removed; implement routing in a custom Scheduler and SchedulerDispatcher if still required." effect/Scheduler#MixedScheduler: replacement: "Scheduler.MixedScheduler" - note: "The class remains with a redesigned constructor and makeDispatcher-based task API." + note: "The class remains with a redesigned constructor and makeDispatcher-based task API. On Cloudflare Workers, request-owned scheduler timers can leave shared fibers suspended; provide new Scheduler.MixedScheduler(\"sync\") to both layers and requests and build handlers at module scope (see HttpRouter.toWebHandler). Sync mode does not yield to the event loop and does not fix request-owned Effect.sleep timers or request-bound async contexts." effect/Scheduler#PriorityBuckets: replacement: "none" note: "Priority buckets are now an internal Scheduler implementation detail." diff --git a/repos/effect/migration/annotations/effect__ai-openai__OpenAiLanguageModel.yaml b/repos/effect/migration/annotations/effect__ai-openai__OpenAiLanguageModel.yaml index 21af9e0d6e..0c8abcd159 100644 --- a/repos/effect/migration/annotations/effect__ai-openai__OpenAiLanguageModel.yaml +++ b/repos/effect/migration/annotations/effect__ai-openai__OpenAiLanguageModel.yaml @@ -1,9 +1,9 @@ "@effect/ai-openai/OpenAiLanguageModel#Config": replacement: "OpenAiLanguageModel.Config" - note: "Still exported in v4; update imports and adapt to the revised v4 service and schema types." + note: "Still exported in v4; update imports and adapt to the revised service and schema types. Unrecognized model names now default to reasoning models, sending system prompts as developer messages and requesting reasoning.encrypted_content when item references are disabled or WebSockets are used. Set reasoningModel: false in config for deployments that do not support these defaults." "@effect/ai-openai/OpenAiLanguageModel#Config.Service": replacement: "OpenAiLanguageModel.Config.Service" - note: "Still exported in v4; update imports and adapt to the revised v4 service and schema types." + note: "Still exported in v4 with revised configuration fields. Set reasoningModel: false for custom deployments that need system messages rather than developer messages and do not support automatic encrypted reasoning requests; unrecognized model names otherwise default to reasoning models. Fine-tuned ft: names follow their base model." "@effect/ai-openai/OpenAiLanguageModel#layerWithTokenizer": replacement: "OpenAiLanguageModel.layer" note: "The tokenizer-combining layer was removed; provide the language model and any Tokenizer service separately." diff --git a/repos/effect/migration/annotations/effect__ai-openai__OpenAiTelemetry.yaml b/repos/effect/migration/annotations/effect__ai-openai__OpenAiTelemetry.yaml index 0f1a0c05b3..ba310c82ba 100644 --- a/repos/effect/migration/annotations/effect__ai-openai__OpenAiTelemetry.yaml +++ b/repos/effect/migration/annotations/effect__ai-openai__OpenAiTelemetry.yaml @@ -13,3 +13,7 @@ "@effect/ai-openai/OpenAiTelemetry#WellKnownResponseFormat": replacement: "Telemetry.WellKnownOutputType" note: "The response format is no longer a telemetry option. LanguageModel records gen_ai.output.type as text or json from the requested response format." +"@effect/ai-openai/OpenAiTelemetry#OpenAiTelemetryAttributes": + include: true + replacement: "OpenAiTelemetry.OpenAiTelemetryAttributes" + note: "Use openai.request.* for request keys and openai.response.* for response keys instead of gen_ai.openai.*. The response-format attribute was removed; use gen_ai.output.type from LanguageModel instead." diff --git a/repos/effect/migration/annotations/effect__ai__McpServer.yaml b/repos/effect/migration/annotations/effect__ai__McpServer.yaml index 51598405d8..66e2f5e030 100644 --- a/repos/effect/migration/annotations/effect__ai__McpServer.yaml +++ b/repos/effect/migration/annotations/effect__ai__McpServer.yaml @@ -18,10 +18,10 @@ note: "The service is now a Context.Service. initializedClients and notificationsMailbox are no longer exposed. Registration callbacks use McpSchema.McpRequestContext; McpServerClient is only supplied for initialized stateful requests. Prefer registerToolkit, registerResource, and registerPrompt over implementing the registry shape directly." "@effect/ai/McpServer#registerToolkit": replacement: "McpServer.registerToolkit" - note: "Moved to effect/ai/McpServer. Handler requirements now exclude McpSchema.McpRequestContext instead of McpServerClient. Strict tools reject excess input properties; raw JSON Schema dynamic tools cannot use strict mode. Declared handler failures produce isError results, while parameter validation fails with InvalidParams." + note: "Moved to effect/ai/McpServer. Requirements from every tool handler are propagated, excluding McpSchema.McpRequestContext instead of McpServerClient; provide the remaining handler services. Strict tools reject excess input properties; raw JSON Schema dynamic tools cannot use strict mode. Declared handler failures produce isError results, while parameter validation fails with InvalidParams." "@effect/ai/McpServer#toolkit": replacement: "McpServer.toolkit" - note: "Moved to effect/ai/McpServer. The registration layer supplies McpSchema.McpRequestContext to handlers instead of excluding McpServerClient from requirements. Strict tools reject excess properties and require an Effect Schema rather than raw dynamic JSON Schema." + note: "Moved to effect/ai/McpServer. The registration layer supplies McpSchema.McpRequestContext to handlers instead of excluding McpServerClient from requirements. Its requirements include services from every tool handler. Strict tools reject excess properties and require an Effect Schema rather than raw dynamic JSON Schema." "@effect/ai/McpServer#registerResource": replacement: "McpServer.registerResource" note: "Moved to effect/ai/McpServer. Resource and completion handler requirements now exclude McpSchema.McpRequestContext instead of McpServerClient; use the request context for protocol-neutral client metadata." @@ -30,7 +30,7 @@ note: "Moved to effect/ai/McpServer. The registration layer excludes McpSchema.McpRequestContext from resource and completion handler requirements instead of McpServerClient." "@effect/ai/McpServer#registerPrompt": replacement: "McpServer.registerPrompt" - note: "Moved to effect/ai/McpServer. Prompt decoding and handler requirements now exclude McpSchema.McpRequestContext instead of McpServerClient; use the request context for protocol-neutral client metadata." + note: "Moved to effect/ai/McpServer. Prompt decoding, handler, and completion callback requirements now exclude McpSchema.McpRequestContext instead of McpServerClient; use the request context for protocol-neutral client metadata." "@effect/ai/McpServer#prompt": replacement: "McpServer.prompt" - note: "Moved to effect/ai/McpServer. The registration layer excludes McpSchema.McpRequestContext from prompt decoding and handler requirements instead of McpServerClient." + note: "Moved to effect/ai/McpServer. The registration layer excludes McpSchema.McpRequestContext from prompt decoding, handler, and completion callback requirements instead of McpServerClient." diff --git a/repos/effect/migration/annotations/effect__ai__Telemetry.yaml b/repos/effect/migration/annotations/effect__ai__Telemetry.yaml index f815ee141f..cd2d7b132b 100644 --- a/repos/effect/migration/annotations/effect__ai__Telemetry.yaml +++ b/repos/effect/migration/annotations/effect__ai__Telemetry.yaml @@ -13,3 +13,7 @@ "@effect/ai/Telemetry#WellKnownSystem": replacement: "Telemetry.WellKnownProviderName" note: "Values follow gen_ai.provider.name: az.ai.inference, az.ai.openai, gemini, vertex_ai and xai became azure.ai.inference, azure.ai.openai, gcp.gemini, gcp.vertex_ai and x_ai." +"@effect/ai/Telemetry#GenAITelemetryAttributes": + include: true + replacement: "Telemetry.GenAITelemetryAttributes" + note: "The flat span attribute keys changed: replace gen_ai.system with gen_ai.provider.name and remove gen_ai.token.type. gen_ai.output.type records text or json. Update code constructing or indexing this attribute type." diff --git a/repos/effect/migration/annotations/effect__platform-bun__BunTerminal.yaml b/repos/effect/migration/annotations/effect__platform-bun__BunTerminal.yaml new file mode 100644 index 0000000000..4002ba608c --- /dev/null +++ b/repos/effect/migration/annotations/effect__platform-bun__BunTerminal.yaml @@ -0,0 +1,8 @@ +"@effect/platform-bun/BunTerminal#make": + include: true + replacement: "BunTerminal.make" + note: "V4 ends key input on bare Esc as well as Ctrl+C and Ctrl+D. Pass a custom shouldQuit predicate to make if your application needs to receive Esc; the v3 default quit only on Ctrl+C and Ctrl+D." +"@effect/platform-bun/BunTerminal#layer": + include: true + replacement: "BunTerminal.layer" + note: "The default layer now ends key input on bare Esc as well as Ctrl+C and Ctrl+D. To keep Esc as input, build a layer with Layer.effect(Terminal.Terminal, BunTerminal.make(shouldQuit)) using a custom quit predicate." diff --git a/repos/effect/migration/annotations/effect__platform-node-shared__NodeTerminal.yaml b/repos/effect/migration/annotations/effect__platform-node-shared__NodeTerminal.yaml new file mode 100644 index 0000000000..08d16aa481 --- /dev/null +++ b/repos/effect/migration/annotations/effect__platform-node-shared__NodeTerminal.yaml @@ -0,0 +1,8 @@ +"@effect/platform-node-shared/NodeTerminal#make": + include: true + replacement: "NodeTerminal.make" + note: "V4 ends key input on bare Esc as well as Ctrl+C and Ctrl+D. Pass a custom shouldQuit predicate to make if your application needs to receive Esc; the v3 default quit only on Ctrl+C and Ctrl+D." +"@effect/platform-node-shared/NodeTerminal#layer": + include: true + replacement: "NodeTerminal.layer" + note: "The default layer now ends key input on bare Esc as well as Ctrl+C and Ctrl+D. To keep Esc as input, build a layer with Layer.effect(Terminal.Terminal, NodeTerminal.make(shouldQuit)) using a custom quit predicate." diff --git a/repos/effect/migration/annotations/effect__platform-node__NodeTerminal.yaml b/repos/effect/migration/annotations/effect__platform-node__NodeTerminal.yaml new file mode 100644 index 0000000000..6045db1e5a --- /dev/null +++ b/repos/effect/migration/annotations/effect__platform-node__NodeTerminal.yaml @@ -0,0 +1,8 @@ +"@effect/platform-node/NodeTerminal#make": + include: true + replacement: "NodeTerminal.make" + note: "V4 ends key input on bare Esc as well as Ctrl+C and Ctrl+D. Pass a custom shouldQuit predicate to make if your application needs to receive Esc; the v3 default quit only on Ctrl+C and Ctrl+D." +"@effect/platform-node/NodeTerminal#layer": + include: true + replacement: "NodeTerminal.layer" + note: "The default layer now ends key input on bare Esc as well as Ctrl+C and Ctrl+D. To keep Esc as input, build a layer with Layer.effect(Terminal.Terminal, NodeTerminal.make(shouldQuit)) using a custom quit predicate." diff --git a/repos/effect/migration/annotations/effect__platform__HttpApiClient.yaml b/repos/effect/migration/annotations/effect__platform__HttpApiClient.yaml index 3d0fcbe365..d323c0dbe9 100644 --- a/repos/effect/migration/annotations/effect__platform__HttpApiClient.yaml +++ b/repos/effect/migration/annotations/effect__platform__HttpApiClient.yaml @@ -1,6 +1,6 @@ "@effect/platform/HttpApiClient#Client.Method": replacement: "effect/http-api/HttpApiClient#Client.Method" - note: "The type remains without GroupError. Requests use params/query and responseMode instead of path/urlParams and withResponse." + note: "The type remains without GroupError. Requests use params/query and responseMode instead of path/urlParams and withResponse. Omitting responseMode returns the decoded value; a union-valued mode returns the corresponding union of decoded values, responses, or [value, response] tuples." "@effect/platform/HttpApiClient#endpoint": replacement: "effect/http-api/HttpApiClient#endpoint" note: "The endpoint client remains, selected by group and endpoint identifiers and using v4 request and responseMode fields." diff --git a/repos/effect/migration/annotations/effect__platform__HttpServer.yaml b/repos/effect/migration/annotations/effect__platform__HttpServer.yaml index 8f295f9d8d..200433f72f 100644 --- a/repos/effect/migration/annotations/effect__platform__HttpServer.yaml +++ b/repos/effect/migration/annotations/effect__platform__HttpServer.yaml @@ -6,7 +6,7 @@ note: "The accessor was removed; read the service and pass its Address to the callback." "@effect/platform/HttpServer#HttpServer": replacement: "HttpServer.HttpServer" - note: "The interface and tag became one Context.Service class; use its Service member for implementations." + note: "The interface and tag became one Context.Service class; use its Service member for implementations. The service-level serve method derives requirements from the middleware-transformed application, so services added by middleware must also be provided." "@effect/platform/HttpServer#layerContext": replacement: "HttpServer.layerServices" note: "Renamed; it provides the standard HTTP platform services." diff --git a/repos/effect/migration/v3-to-v4.md b/repos/effect/migration/v3-to-v4.md index d10fe28cf5..0adea8d81c 100644 --- a/repos/effect/migration/v3-to-v4.md +++ b/repos/effect/migration/v3-to-v4.md @@ -2,9 +2,9 @@ # v3 to v4 Migration Reference -Base: `origin/v3` (`e730f59d29db5f1e312be6476a95d07bcad45788`) +Base: `e730f59d29db5f1e312be6476a95d07bcad45788` (`e730f59d29db5f1e312be6476a95d07bcad45788`) -Head: `HEAD` (`79b88977582fb715494d08405c73a47a593afced`) +Head: `origin/main` (`7547a99f81fa6f7e651d52f3d42081f399bfbca8`) This file is generated from the API diff and `migration/annotations/*.yaml`. @@ -4136,9 +4136,9 @@ effect/rpc/Utils (barrel: effect/rpc) ### `@effect/ai-openai/OpenAiLanguageModel` -- `OpenAiLanguageModel.Config` -> `OpenAiLanguageModel.Config`: Still exported in v4; update imports and adapt to the revised v4 service and schema types. +- `OpenAiLanguageModel.Config` -> `OpenAiLanguageModel.Config`: Still exported in v4; update imports and adapt to the revised service and schema types. Unrecognized model names now default to reasoning models, sending system prompts as developer messages and requesting reasoning.encrypted\_content when item references are disabled or WebSockets are used. Set reasoningModel: false in config for deployments that do not support these defaults. -- `OpenAiLanguageModel.Config.Service` -> `OpenAiLanguageModel.Config.Service`: Still exported in v4; update imports and adapt to the revised v4 service and schema types. +- `OpenAiLanguageModel.Config.Service` -> `OpenAiLanguageModel.Config.Service`: Still exported in v4 with revised configuration fields. Set reasoningModel: false for custom deployments that need system messages rather than developer messages and do not support automatic encrypted reasoning requests; unrecognized model names otherwise default to reasoning models. Fine-tuned ft: names follow their base model. - `OpenAiLanguageModel.Model` -> `OpenAiLanguageModel.Model`: Still exported in v4; update imports and adapt to the revised v4 service and schema types. @@ -4156,6 +4156,8 @@ effect/rpc/Utils (barrel: effect/rpc) - `OpenAiTelemetry.OpenAiTelemetryAttributeOptions` -> `OpenAiTelemetry.OpenAiTelemetryAttributeOptions`: Still exported in v4; update imports and adapt to the revised v4 service and schema types. +- `OpenAiTelemetry.OpenAiTelemetryAttributes` -> `OpenAiTelemetry.OpenAiTelemetryAttributes`: Use openai.request.\* for request keys and openai.response.\* for response keys instead of gen\_ai.openai.\*. The response-format attribute was removed; use gen\_ai.output.type from LanguageModel instead. + - `OpenAiTelemetry.RequestAttributes` -> `OpenAiTelemetry.RequestAttributes`: Attributes are written under openai.request.\* instead of gen\_ai.openai.request.\*. responseFormat was removed; LanguageModel records gen\_ai.output.type for every provider. - `OpenAiTelemetry.WellKnownResponseFormat` -> `Telemetry.WellKnownOutputType`: The response format is no longer a telemetry option. LanguageModel records gen\_ai.output.type as text or json from the requested response format. @@ -4976,19 +4978,19 @@ effect/rpc/Utils (barrel: effect/rpc) - `McpServer.layerStdio` -> `McpServer.layerStdio`: Moved to effect/ai/McpServer. Pass a non-empty protocols array of adapters, such as [McpProtocol.v2025\_06\_18], imported with McpProtocol from effect/ai. -- `McpServer.prompt` -> `McpServer.prompt`: Moved to effect/ai/McpServer. The registration layer excludes McpSchema.McpRequestContext from prompt decoding and handler requirements instead of McpServerClient. +- `McpServer.prompt` -> `McpServer.prompt`: Moved to effect/ai/McpServer. The registration layer excludes McpSchema.McpRequestContext from prompt decoding, handler, and completion callback requirements instead of McpServerClient. -- `McpServer.registerPrompt` -> `McpServer.registerPrompt`: Moved to effect/ai/McpServer. Prompt decoding and handler requirements now exclude McpSchema.McpRequestContext instead of McpServerClient; use the request context for protocol-neutral client metadata. +- `McpServer.registerPrompt` -> `McpServer.registerPrompt`: Moved to effect/ai/McpServer. Prompt decoding, handler, and completion callback requirements now exclude McpSchema.McpRequestContext instead of McpServerClient; use the request context for protocol-neutral client metadata. - `McpServer.registerResource` -> `McpServer.registerResource`: Moved to effect/ai/McpServer. Resource and completion handler requirements now exclude McpSchema.McpRequestContext instead of McpServerClient; use the request context for protocol-neutral client metadata. -- `McpServer.registerToolkit` -> `McpServer.registerToolkit`: Moved to effect/ai/McpServer. Handler requirements now exclude McpSchema.McpRequestContext instead of McpServerClient. Strict tools reject excess input properties; raw JSON Schema dynamic tools cannot use strict mode. Declared handler failures produce isError results, while parameter validation fails with InvalidParams. +- `McpServer.registerToolkit` -> `McpServer.registerToolkit`: Moved to effect/ai/McpServer. Requirements from every tool handler are propagated, excluding McpSchema.McpRequestContext instead of McpServerClient; provide the remaining handler services. Strict tools reject excess input properties; raw JSON Schema dynamic tools cannot use strict mode. Declared handler failures produce isError results, while parameter validation fails with InvalidParams. - `McpServer.resource` -> `McpServer.resource`: Moved to effect/ai/McpServer. The registration layer excludes McpSchema.McpRequestContext from resource and completion handler requirements instead of McpServerClient. - `McpServer.run` -> `McpServer.run`: Moved to effect/ai/McpServer. Pass a non-empty protocols array of adapters, such as [McpProtocol.v2025\_06\_18], imported with McpProtocol from effect/ai; it remains the Effect-level runner over RpcServer.Protocol. -- `McpServer.toolkit` -> `McpServer.toolkit`: Moved to effect/ai/McpServer. The registration layer supplies McpSchema.McpRequestContext to handlers instead of excluding McpServerClient from requirements. Strict tools reject excess properties and require an Effect Schema rather than raw dynamic JSON Schema. +- `McpServer.toolkit` -> `McpServer.toolkit`: Moved to effect/ai/McpServer. The registration layer supplies McpSchema.McpRequestContext to handlers instead of excluding McpServerClient from requirements. Its requirements include services from every tool handler. Strict tools reject excess properties and require an Effect Schema rather than raw dynamic JSON Schema. ### `@effect/ai/Model` @@ -5076,6 +5078,8 @@ effect/rpc/Utils (barrel: effect/rpc) - `Telemetry.GenAITelemetryAttributeOptions` -> `Telemetry.GenAITelemetryAttributeOptions`: The system and token options were removed. Use provider: { name } for gen\_ai.provider.name; gen\_ai.token.type has no span replacement. The new output option writes gen\_ai.output.type. +- `Telemetry.GenAITelemetryAttributes` -> `Telemetry.GenAITelemetryAttributes`: The flat span attribute keys changed: replace gen\_ai.system with gen\_ai.provider.name and remove gen\_ai.token.type. gen\_ai.output.type records text or json. Update code constructing or indexing this attribute type. + - `Telemetry.TokenAttributes` -> `none`: Removed with the token option. gen\_ai.token.type is not a span attribute in the current OpenTelemetry GenAI conventions. - `Telemetry.WellKnownSystem` -> `Telemetry.WellKnownProviderName`: Values follow gen\_ai.provider.name: az.ai.inference, az.ai.openai, gemini, vertex\_ai and xai became azure.ai.inference, azure.ai.openai, gcp.gemini, gcp.vertex\_ai and x\_ai. @@ -6188,6 +6192,8 @@ effect/rpc/Utils (barrel: effect/rpc) ### `@effect/opentelemetry/OtlpResource` +- `OtlpResource.make` -> `OtlpResource.make`: The constructor remains in the module moved to effect/observability/OtlpResource. + - `OtlpResource.unsafeServiceName` -> `OtlpResource.serviceNameUnsafe`: Moved to effect/observability/OtlpResource and renamed to follow the v4 unsafe-suffix convention. ### `@effect/opentelemetry/OtlpTracer` @@ -6318,6 +6324,12 @@ effect/rpc/Utils (barrel: effect/rpc) - `BunStream.stdout` -> `stdio.stdout() from Stdio.Stdio`: Standard output is correctly modeled as a Sink in v4. Explicitly adapt process.stdout with BunStream.fromReadable only to preserve the old unusual read behavior. +### `@effect/platform-bun/BunTerminal` + +- `BunTerminal.layer` -> `BunTerminal.layer`: The default layer now ends key input on bare Esc as well as Ctrl+C and Ctrl+D. To keep Esc as input, build a layer with Layer.effect(Terminal.Terminal, BunTerminal.make(shouldQuit)) using a custom quit predicate. + +- `BunTerminal.make` -> `BunTerminal.make`: V4 ends key input on bare Esc as well as Ctrl+C and Ctrl+D. Pass a custom shouldQuit predicate to make if your application needs to receive Esc; the v3 default quit only on Ctrl+C and Ctrl+D. + ### `@effect/platform-bun/BunWorker` - `BunWorker.layerManager` -> `BunWorker.layerPlatform`: WorkerManager was removed. Provide WorkerPlatform directly, or use BunWorker.layer(spawn) when a Worker.Spawner is also required. @@ -6362,6 +6374,12 @@ effect/rpc/Utils (barrel: effect/rpc) - `NodeStream.stdout` -> `NodeStream.fromReadable({ evaluate: () => process.stdout, closeOnDone: false }).pipe(Stream.orDie)`: This preserves the unusual v3 read behavior; for normal output use the stdio.stdout() Sink from effect/Stdio. +### `@effect/platform-node-shared/NodeTerminal` + +- `NodeTerminal.layer` -> `NodeTerminal.layer`: The default layer now ends key input on bare Esc as well as Ctrl+C and Ctrl+D. To keep Esc as input, build a layer with Layer.effect(Terminal.Terminal, NodeTerminal.make(shouldQuit)) using a custom quit predicate. + +- `NodeTerminal.make` -> `NodeTerminal.make`: V4 ends key input on bare Esc as well as Ctrl+C and Ctrl+D. Pass a custom shouldQuit predicate to make if your application needs to receive Esc; the v3 default quit only on Ctrl+C and Ctrl+D. + ### `@effect/platform-node/NodeCommandExecutor` - `NodeCommandExecutor.layer` -> `NodeChildProcessSpawner.layer`: CommandExecutor became ChildProcessSpawner; use the @effect/platform-node/NodeChildProcessSpawner re-export. @@ -6404,6 +6422,12 @@ effect/rpc/Utils (barrel: effect/rpc) - `NodeHttpServer.layerContext` -> `NodeHttpServer.layerHttpServices`: Direct rename; it provides NodeServices, HttpPlatform, and Etag.Generator, without the removed WorkerManager. +### `@effect/platform-node/NodeTerminal` + +- `NodeTerminal.layer` -> `NodeTerminal.layer`: The default layer now ends key input on bare Esc as well as Ctrl+C and Ctrl+D. To keep Esc as input, build a layer with Layer.effect(Terminal.Terminal, NodeTerminal.make(shouldQuit)) using a custom quit predicate. + +- `NodeTerminal.make` -> `NodeTerminal.make`: V4 ends key input on bare Esc as well as Ctrl+C and Ctrl+D. Pass a custom shouldQuit predicate to make if your application needs to receive Esc; the v3 default quit only on Ctrl+C and Ctrl+D. + ### `@effect/platform-node/NodeWorker` - `NodeWorker.layerManager` -> `NodeWorker.layerPlatform`: WorkerManager was removed. Provide WorkerPlatform directly, or use NodeWorker.layer(spawn) when a Worker.Spawner is also required. @@ -6718,7 +6742,7 @@ effect/rpc/Utils (barrel: effect/rpc) ### `@effect/platform/HttpApiClient` -- `HttpApiClient.Client.Method` -> `effect/http-api/HttpApiClient#Client.Method`: The type remains without GroupError. Requests use params/query and responseMode instead of path/urlParams and withResponse. +- `HttpApiClient.Client.Method` -> `effect/http-api/HttpApiClient#Client.Method`: The type remains without GroupError. Requests use params/query and responseMode instead of path/urlParams and withResponse. Omitting responseMode returns the decoded value; a union-valued mode returns the corresponding union of decoded values, responses, or [value, response] tuples. - `HttpApiClient.endpoint` -> `effect/http-api/HttpApiClient#endpoint`: The endpoint client remains, selected by group and endpoint identifiers and using v4 request and responseMode fields. @@ -7264,7 +7288,7 @@ effect/rpc/Utils (barrel: effect/rpc) - `HttpServer.Address` -> `effect/net/NetAddress#SocketAddress`: Replaced by the shared concrete internet-or-Unix socket address union. -- `HttpServer.HttpServer` -> `HttpServer.HttpServer`: The interface and tag became one Context.Service class; use its Service member for implementations. +- `HttpServer.HttpServer` -> `HttpServer.HttpServer`: The interface and tag became one Context.Service class; use its Service member for implementations. The service-level serve method derives requirements from the middleware-transformed application, so services added by middleware must also be provided. - `HttpServer.ServeOptions` -> `none`: The unused respond option model was removed with no shared v4 counterpart. @@ -8036,6 +8060,8 @@ effect/rpc/Utils (barrel: effect/rpc) - `SqlClient.SafeIntegers` -> `effect/sql/SqlClient#SafeIntegers`: Moved and changed from a Reference subclass to a Context.Reference value; provide it as a service. +- `SqlClient.SqlClient.MakeOptions`: TODO: needs guidance + - `SqlClient.TransactionConnection` -> `effect/sql/SqlClient#TransactionConnection`: Now a factory keyed by client id, not a singleton tag. Prefer the client's transactionService; the payload type is TransactionConnection.Service. - `SqlClient.TypeId` -> `none`: The brand is private in v4; do not inspect or attach it, and obtain clients through SqlClient or SqlClient.make. @@ -9174,7 +9200,7 @@ Arbitrary.schema(schema) - `Channel.mapInputIn` -> `Channel.mapInput`: Use Channel.mapInput(self, (value) =\> Effect.succeed(f(value))); v4 consolidated pure and effectful input mapping. -- `Channel.mapInputInEffect` -> `Channel.mapInput`: Renamed to mapInput; the mapper remains effectful. +- `Channel.mapInputInEffect` -> `Channel.mapInput`: Renamed to mapInput; the mapper remains effectful. Both overloads retain mapper service requirements in the resulting channel, so provide those services before running it. - `Channel.mapOut` -> `Channel.map`: Renamed to map; the v4 mapper also receives the element index. @@ -9612,9 +9638,11 @@ Arbitrary.schema(schema) - `DateTime.Zoned` -> `DateTime.Zoned`: The model remains; rename epochMillis and adjustedEpochMillis to epochMilliseconds and adjustedEpochMilliseconds. -- `DateTime.distanceDuration` -> `Duration.millis(Math.abs(DateTime.distance(self, other)))`: DateTime.distance returns signed milliseconds in v4; take the absolute value and construct a Duration to preserve v3 behavior. +- `DateTime.distance` -> `Duration.toMillis(DateTime.distance(self, other))`: V3 returns signed milliseconds; v4 returns a signed Duration (other minus self). Convert it with Duration.toMillis when a numeric millisecond result is required. + +- `DateTime.distanceDuration` -> `Duration.abs(DateTime.distance(self, other))`: V4 DateTime.distance already returns a signed Duration. Use Duration.abs to preserve the non-negative distance returned by v3; Math.abs and Duration.millis expect numbers, not Durations. -- `DateTime.distanceDurationEither` -> `DateTime.distance + Result`: Compute the signed millisecond distance, wrap its absolute Duration as Result.succeed when positive and Result.fail when non-positive; v4 uses Result instead of Either. +- `DateTime.distanceDurationEither` -> `DateTime.distance + Result`: Let diff = DateTime.distance(self, other), a signed Duration. Use Duration.isPositive(diff) ? Result.succeed(Duration.abs(diff)) : Result.fail(Duration.abs(diff)) to preserve v3 behavior, including equal dates producing a failure with Duration.zero. V4 uses Result instead of Either. - `DateTime.greaterThan` -> `DateTime.isGreaterThan`: The comparison was renamed with the is prefix. @@ -10382,11 +10410,11 @@ Arbitrary.schema(schema) ### `effect/ExecutionPlan` -- `ExecutionPlan.ExecutionPlan` -> `ExecutionPlan.ExecutionPlan`: The plan type remains; withRequirements was renamed to captureRequirements. +- `ExecutionPlan.ExecutionPlan` -> `ExecutionPlan.ExecutionPlan`: The plan type remains; withRequirements was renamed to captureRequirements. Step schedules use Schedule\; captureRequirements supplies captured services to schedule initialization and execution. - `ExecutionPlan.TypesBase` -> `ExecutionPlan.ConfigBase`: The base type for execution-plan step configuration was renamed. -- `ExecutionPlan.make` -> `ExecutionPlan.make`: The variadic execution-plan constructor remains unchanged. +- `ExecutionPlan.make` -> `ExecutionPlan.make`: The constructor remains variadic. Its inferred error channel includes failures from step layers, predicates, and schedules; requirements include services needed by all three across every step. ### `effect/ExecutionStrategy` @@ -14103,7 +14131,7 @@ Schema.toFormatter(schema) - `Scheduler.ControlledScheduler` -> `none`: No public step-controlled scheduler remains; implement Scheduler and SchedulerDispatcher for exact controlled stepping. -- `Scheduler.MixedScheduler` -> `Scheduler.MixedScheduler`: The class remains with a redesigned constructor and makeDispatcher-based task API. +- `Scheduler.MixedScheduler` -> `Scheduler.MixedScheduler`: The class remains with a redesigned constructor and makeDispatcher-based task API. On Cloudflare Workers, request-owned scheduler timers can leave shared fibers suspended; provide new Scheduler.MixedScheduler("sync") to both layers and requests and build handlers at module scope (see HttpRouter.toWebHandler). Sync mode does not yield to the event loop and does not fix request-owned Effect.sleep timers or request-bound async contexts. - `Scheduler.PriorityBuckets` -> `none`: Priority buckets are now an internal Scheduler implementation detail. diff --git a/repos/effect/package.json b/repos/effect/package.json index 572fb0d81c..3be5cbf06f 100644 --- a/repos/effect/package.json +++ b/repos/effect/package.json @@ -31,11 +31,11 @@ "api-diff": "pnpm --dir packages/tools/api-diff exec node src/bin.ts", "test-types": "tstyche --target '>=5.9'", "changeset-version": "changeset version && node scripts/version.mjs", - "changeset-publish": "node scripts/set-strip-internal.mjs && pnpm codemod && pnpm build && changeset publish" + "changeset-publish": "node scripts/set-strip-internal.mjs && pnpm codemod && pnpm build && changeset publish --tag staging" }, "devDependencies": { "@babel/cli": "^8.0.6", - "@babel/core": "^8.0.6", + "@babel/core": "^8.0.7", "@babel/plugin-transform-export-namespace-from": "^8.0.1", "@babel/plugin-transform-modules-commonjs": "^8.0.1", "@changesets/changelog-github": "1.0.1", @@ -46,7 +46,7 @@ "@effect/doctest": "workspace:^", "@effect/jsdocs": "workspace:^", "@effect/oxc": "workspace:^", - "@effect/tsgo": "^0.51.0", + "@effect/tsgo": "^0.51.1", "@effect/utils": "workspace:^", "@effect/vitest": "workspace:^", "@faker-js/faker": "^10.6.0", @@ -54,29 +54,29 @@ "@rollup/plugin-replace": "^6.0.3", "@rollup/plugin-terser": "^1.0.0", "@types/jscodeshift": "^17.3.0", - "@types/node": "^26.6.4", + "@types/node": "^26.6.5", "@vitest/coverage-v8": "^5.0.3", "@vitest/web-worker": "^5.0.3", "ast-types": "^0.16.3", "babel-plugin-annotate-pure-calls": "^0.5.0", - "dprint": "^0.59.0", + "dprint": "^0.61.1", "fast-check": "^4.10.2", "glob": "^13.0.6", - "happy-dom": "^20.14.5", + "happy-dom": "^20.14.6", "jscodeshift": "^17.4.0", "lalph": "^0.3.139", "madge": "^8.0.0", - "oxlint": "^1.86.0", - "pkg-pr-new": "0.0.88", - "playwright": "^1.63.0", - "rollup": "^4.64.0", + "oxlint": "^1.87.0", + "pkg-pr-new": "0.0.91", + "playwright": "^1.64.0", + "rollup": "^4.64.5", "rollup-plugin-bundle-stats": "^4.22.3", "rollup-plugin-esbuild": "^6.2.1", "rollup-plugin-visualizer": "^7.1.1", "terser": "^5.51.2", "tstyche": "^7.2.5", "typescript": "^7.0.2", - "vite": "^8.3.2", + "vite": "^8.3.4", "vitest": "^5.0.3", "vitest-websocket-mock": "^0.8.0", "zod": "^4.6.5" diff --git a/repos/effect/packages/ai/anthropic/CHANGELOG.md b/repos/effect/packages/ai/anthropic/CHANGELOG.md index ccd63f7aae..d1d417677d 100644 --- a/repos/effect/packages/ai/anthropic/CHANGELOG.md +++ b/repos/effect/packages/ai/anthropic/CHANGELOG.md @@ -1,5 +1,30 @@ # @effect/ai-anthropic +## 4.0.5 + +### Patch Changes + +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- [#9008](https://github.com/Effect-TS/effect/pull/9008) [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d) Thanks @effect-bot! - Add `toolCallValidation: "deferred"` for callers using `disableToolCallResolution: true`. Model-generated tool calls return with `unknown` parameters, including invalid parameters and undeclared tool names, even without a toolkit. Supported by the Anthropic, OpenAI, and OpenAI-compatible providers. Strict validation remains the default; provider-executed calls remain validated. + +- [#9029](https://github.com/Effect-TS/effect/pull/9029) [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163) Thanks @effect-bot! - Clean up unused Anthropic bindings and make documentation-only imports type-only, preserving server-tool inputs and documentation links. +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- [#8971](https://github.com/Effect-TS/effect/pull/8971) [`1db5671`](https://github.com/Effect-TS/effect/commit/1db5671d77e70a07d65d3c8a17056a9d46e748e2) Thanks @m9tdev! - Decode streamed and non-streamed Anthropic fallback responses. Preserve fallback blocks in response metadata and model attribution in usage iterations. +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/ai/anthropic/codegen.yml b/repos/effect/packages/ai/anthropic/codegen.yml index 12e961deee..2d576c581f 100644 --- a/repos/effect/packages/ai/anthropic/codegen.yml +++ b/repos/effect/packages/ai/anthropic/codegen.yml @@ -9,6 +9,8 @@ patches: - '[{"op":"replace","path":"/components/schemas/BetaInputMessage/properties/role/enum","value":["user","assistant","system"]},{"op":"replace","path":"/components/schemas/InputMessage/properties/role/enum","value":["user","assistant","system"]}]' # Make iterations and speed optional in BetaUsage, iterations optional in BetaMessageDeltaUsage (API may omit these fields) - '[{"op":"remove","path":"/components/schemas/BetaUsage/required/9"},{"op":"remove","path":"/components/schemas/BetaUsage/required/5"},{"op":"remove","path":"/components/schemas/BetaMessageDeltaUsage/required/3"}]' + # Make model optional in BetaMessageIterationUsage (gateways and older responses may omit it) + - '[{"op":"replace","path":"/components/schemas/BetaMessageIterationUsage/required","value":["cache_creation","cache_creation_input_tokens","cache_read_input_tokens","input_tokens","output_tokens","type"]}]' header: | /** * @stability unstable diff --git a/repos/effect/packages/ai/anthropic/package.json b/repos/effect/packages/ai/anthropic/package.json index eb3b2c36ad..e38e713202 100644 --- a/repos/effect/packages/ai/anthropic/package.json +++ b/repos/effect/packages/ai/anthropic/package.json @@ -1,6 +1,6 @@ { "name": "@effect/ai-anthropic", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "An Anthropic provider integration for Effect AI SDK", diff --git a/repos/effect/packages/ai/anthropic/src/AnthropicLanguageModel.ts b/repos/effect/packages/ai/anthropic/src/AnthropicLanguageModel.ts index 3709ddec40..8f3e30f944 100644 --- a/repos/effect/packages/ai/anthropic/src/AnthropicLanguageModel.ts +++ b/repos/effect/packages/ai/anthropic/src/AnthropicLanguageModel.ts @@ -659,6 +659,24 @@ declare module "effect/ai/Response" { requestId?: string | null } | null } + + /** + * Anthropic metadata attached to response metadata parts. + * + * **Details** + * + * Fallback blocks are stored in `anthropic.fallback`; the part's `modelId` + * identifies the fallback model. + * + * @stability unstable + * @category models + * @since 4.0.3 + */ + export interface ResponseMetadataPartMetadata extends ProviderMetadata { + readonly anthropic?: { + readonly fallback?: typeof Generated.BetaResponseFallbackBlock.Encoded + } | null + } } // ============================================================================= @@ -1044,7 +1062,7 @@ const prepareMessages = Effect.fnUntraced( pendingSystem = [] } - const content: Array = [] + const content: Array = [] const mcpToolIds = new Set() for (let j = 0; j < group.messages.length; j++) { @@ -1142,7 +1160,7 @@ const prepareMessages = Effect.fnUntraced( Predicate.hasProperty(part.params, "type") && part.params.type === "programmatic-tool-call" ) { - const { type, ...params } = part.params + const { type: _type, ...params } = part.params content.push({ type: "server_tool_use", id: part.id, @@ -1651,6 +1669,15 @@ const makeResponse = Effect.fnUntraced( for (const part of rawResponse.content) { switch (part.type) { + case "fallback": { + parts.push({ + type: "response-metadata", + modelId: part.to.model, + timestamp: DateTime.formatIso(yield* DateTime.now), + metadata: { anthropic: { fallback: part } } + }) + break + } case "text": { // The response tool supplies the JSON payload. Accompanying prose // must not be concatenated with it during structured output decoding. @@ -1722,7 +1749,7 @@ const makeResponse = Effect.fnUntraced( // Map the provider wire name (e.g. "memory") back to the tool's // custom name (e.g. "AnthropicMemory") that the toolkit is keyed by const toolName = toolNameMapper.getCustomName(part.name) - const params = yield* transformToolCallParams(options.tools, toolName, part.input) + const params = yield* transformToolCallParams(options, toolName, part.input) parts.push({ type: "tool-call", @@ -2162,7 +2189,7 @@ const makeStreamResponse = Effect.fnUntraced( id: part.id }) - const params = yield* transformToolCallParams(options.tools, toolName, part.input) + const params = yield* transformToolCallParams(options, toolName, part.input) parts.push({ type: "tool-call", @@ -2602,6 +2629,17 @@ const makeStreamResponse = Effect.fnUntraced( break } + + case "fallback": { + parts.push({ + type: "response-metadata", + modelId: event.content_block.to.model, + timestamp: DateTime.formatIso(yield* DateTime.now), + metadata: { anthropic: { fallback: event.content_block } } + }) + + break + } } break @@ -2765,7 +2803,7 @@ const makeStreamResponse = Effect.fnUntraced( const params = contentBlock.providerExecuted === true ? toolParams - : yield* transformToolCallParams(options.tools, contentBlock.name, toolParams) + : yield* transformToolCallParams(options, contentBlock.name, toolParams) parts.push({ type: "tool-call", @@ -3205,20 +3243,23 @@ const getOutputFormat = Effect.fnUntraced(function*({ capabilities, options }: { return undefined }) -const transformToolCallParams = Effect.fnUntraced(function*>( - tools: Tools, +const transformToolCallParams = Effect.fnUntraced(function*( + options: LanguageModel.ProviderOptions, toolName: string, toolParams: unknown ): Effect.fn.Return { - const tool = tools.find((tool) => tool.name === toolName) + const tool = options.tools.find((tool) => tool.name === toolName) if (Predicate.isUndefined(tool)) { + if (options.toolCallValidation === "deferred") { + return toolParams + } return yield* AiError.make({ module: "AnthropicLanguageModel", method: "makeResponse", reason: new AiError.ToolNotFoundError({ toolName, - availableTools: tools.map((tool) => tool.name) + availableTools: options.tools.map((tool) => tool.name) }) }) } diff --git a/repos/effect/packages/ai/anthropic/src/Generated.ts b/repos/effect/packages/ai/anthropic/src/Generated.ts index 16969168ea..7622bc5bec 100644 --- a/repos/effect/packages/ai/anthropic/src/Generated.ts +++ b/repos/effect/packages/ai/anthropic/src/Generated.ts @@ -2915,6 +2915,52 @@ export const Model = Schema.Union([ "description": "The model that will complete your prompt.\n\nSee [models](https://docs.anthropic.com/en/docs/models-overview) for additional details and options." }) +export type BetaResponseFallbackHopInfo = { readonly "model": Model } +export const BetaResponseFallbackHopInfo = Schema.Struct({ "model": Model }).annotate({ + "title": "ResponseFallbackHopInfo", + "description": "Identifies one hop of a fallback transition." +}) +export type BetaRefusalCategory = "cyber" | "bio" | "frontier_llm" | "reasoning_extraction" | "general_harms" +export const BetaRefusalCategory = Schema.Literals([ + "cyber", + "bio", + "frontier_llm", + "reasoning_extraction", + "general_harms" +]).annotate({ "title": "RefusalCategory", "description": "The policy category that triggered a refusal." }) +export type BetaFallbackRefusalTrigger = { readonly "category": BetaRefusalCategory | null; readonly "type": "refusal" } +export const BetaFallbackRefusalTrigger = Schema.Struct({ + "category": Schema.Union([BetaRefusalCategory, Schema.Null]).annotate({ + "description": + "The policy category that triggered the `from` model's refusal at this hop. `null` when the refusal doesn't map to a named category. Same vocabulary as `stop_details.category`.", + "default": null + }), + "type": Schema.Literal("refusal").annotate({ "title": "Type", "default": "refusal" }) +}).annotate({ "title": "FallbackRefusalTrigger", "description": "The `from` model declined for policy reasons." }) +export type BetaResponseFallbackBlock = { + readonly "from": BetaResponseFallbackHopInfo + readonly "to": BetaResponseFallbackHopInfo + readonly "trigger": BetaFallbackRefusalTrigger + readonly "type": "fallback" +} +export const BetaResponseFallbackBlock = Schema.Struct({ + "from": BetaResponseFallbackHopInfo.annotate({ + "description": + "The model whose output ends at this point — the model that declined at this hop. When the declining hop is the requested model, its `model` echoes the top-level `model` string the caller sent (alias or canonical); when the declining hop is a fallback model, its `model` is that model's canonical id." + }), + "to": BetaResponseFallbackHopInfo.annotate({ + "description": + "The fallback model producing the content that follows this block. Its `model` is always the canonical id." + }), + "trigger": BetaFallbackRefusalTrigger.annotate({ + "description": "What caused the `from` model to hand over at this hop." + }), + "type": Schema.Literal("fallback").annotate({ "title": "Type", "default": "fallback" }) +}).annotate({ + "title": "ResponseFallbackBlock", + "description": + "Marks the point in `content` where one model's output gives way to the next.\n\nOne block appears per hop where a preceding model actually ran this turn and\ndeclined. A turn where no preceding model ran and declined has no such\nboundary and carries no block — the signal for whether a fallback model\nserved the response is the presence of a `fallback_message` entry in\n`usage.iterations`, not this block.\n\nThe block is treated like a server-tool content block for streaming: it\narrives via the standard `content_block_start` / `content_block_stop`\npair and carries no deltas." +}) export type BetaMemoryTool_20250818_ViewCommand = { readonly "command": "view" readonly "path": string @@ -3343,6 +3389,7 @@ export type BetaMessageIterationUsage = { readonly "cache_creation_input_tokens": number readonly "cache_read_input_tokens": number readonly "input_tokens": number + readonly "model"?: Model readonly "output_tokens": number readonly "type": "message" } @@ -3365,6 +3412,7 @@ export const BetaMessageIterationUsage = Schema.Struct({ "title": "Input Tokens", "description": "The number of input tokens which were used." }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), + "model": Schema.optionalKey(Model), "output_tokens": Schema.Number.annotate({ "title": "Output Tokens", "description": "The number of output tokens which were used." @@ -6672,9 +6720,56 @@ export const BetaRequestToolSearchToolSearchResultBlock = Schema.Struct({ "tool_references": Schema.Array(BetaRequestToolReferenceBlock).annotate({ "title": "Tool References" }), "type": Schema.Literal("tool_search_tool_search_result").annotate({ "title": "Type" }) }).annotate({ "title": "RequestToolSearchToolSearchResultBlock" }) -export type BetaIterationsUsage = ReadonlyArray | null +export type BetaFallbackMessageIterationUsage = { + readonly "cache_creation": BetaCacheCreation | null + readonly "cache_creation_input_tokens": number + readonly "cache_read_input_tokens": number + readonly "input_tokens": number + readonly "model": Model + readonly "output_tokens": number + readonly "type": "fallback_message" +} +export const BetaFallbackMessageIterationUsage = Schema.Struct({ + "cache_creation": Schema.Union([BetaCacheCreation, Schema.Null]).annotate({ + "description": "Breakdown of cached tokens by TTL", + "default": null + }), + "cache_creation_input_tokens": Schema.Number.annotate({ + "title": "Cache Creation Input Tokens", + "description": "The number of input tokens used to create the cache entry.", + "default": 0 + }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), + "cache_read_input_tokens": Schema.Number.annotate({ + "title": "Cache Read Input Tokens", + "description": "The number of input tokens read from the cache.", + "default": 0 + }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), + "input_tokens": Schema.Number.annotate({ + "title": "Input Tokens", + "description": "The number of input tokens which were used." + }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), + "model": Model, + "output_tokens": Schema.Number.annotate({ + "title": "Output Tokens", + "description": "The number of output tokens which were used." + }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), + "type": Schema.Literal("fallback_message").annotate({ + "title": "Type", + "description": "Usage for the fallback-model attempt that served the response", + "default": "fallback_message" + }) +}).annotate({ + "title": "FallbackMessageIterationUsage", + "description": + "Token usage for the fallback-model attempt of a server-side fallback request.\n\nProduced in place of a `message` entry for whichever hop served the\nresponse. A declined hop produces the existing `message` entry. Whether\na fallback model served the response is signalled by the presence of this\nentry in `usage.iterations`." +}) +export type BetaIterationsUsage = + | ReadonlyArray + | null export const BetaIterationsUsage = Schema.Union([ - Schema.Array(Schema.Union([BetaMessageIterationUsage, BetaCompactionIterationUsage])), + Schema.Array( + Schema.Union([BetaMessageIterationUsage, BetaCompactionIterationUsage, BetaFallbackMessageIterationUsage]) + ), Schema.Null ]).annotate({ "title": "Iterations", @@ -7554,6 +7649,7 @@ export type BetaContentBlockStartEvent = { | BetaResponseMCPToolResultBlock | BetaResponseContainerUploadBlock | BetaResponseCompactionBlock + | BetaResponseFallbackBlock readonly "index": number readonly "type": "content_block_start" } @@ -7573,7 +7669,8 @@ export const BetaContentBlockStartEvent = Schema.Struct({ BetaResponseMCPToolUseBlock, BetaResponseMCPToolResultBlock, BetaResponseContainerUploadBlock, - BetaResponseCompactionBlock + BetaResponseCompactionBlock, + BetaResponseFallbackBlock ], { mode: "oneOf" }).annotate({ "title": "Content Block" }), "index": Schema.Number.annotate({ "title": "Index" }).check(Schema.isInt()), "type": Schema.Literal("content_block_start").annotate({ "title": "Type", "default": "content_block_start" }) @@ -7594,6 +7691,7 @@ export type BetaContentBlock = | BetaResponseMCPToolResultBlock | BetaResponseContainerUploadBlock | BetaResponseCompactionBlock + | BetaResponseFallbackBlock export const BetaContentBlock = Schema.Union([ BetaResponseTextBlock, BetaResponseThinkingBlock, @@ -7609,7 +7707,8 @@ export const BetaContentBlock = Schema.Union([ BetaResponseMCPToolUseBlock, BetaResponseMCPToolResultBlock, BetaResponseContainerUploadBlock, - BetaResponseCompactionBlock + BetaResponseCompactionBlock, + BetaResponseFallbackBlock ], { mode: "oneOf" }) export type BetaRequestWebFetchResultBlock = { readonly "content": BetaRequestDocumentBlock diff --git a/repos/effect/packages/ai/anthropic/test/AnthropicLanguageModel.test.ts b/repos/effect/packages/ai/anthropic/test/AnthropicLanguageModel.test.ts index 5f240511d1..2d89752262 100644 --- a/repos/effect/packages/ai/anthropic/test/AnthropicLanguageModel.test.ts +++ b/repos/effect/packages/ai/anthropic/test/AnthropicLanguageModel.test.ts @@ -254,6 +254,84 @@ describe("AnthropicLanguageModel", () => { assert.deepStrictEqual(toolCall.params, toolParams) })) + it.effect("streams undeclared tool calls when tool call validation is deferred", () => + Effect.gen(function*() { + const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + makeHttpClient((request) => + Effect.succeed(sseResponse(request, [ + { + type: "message_start", + message: { + id: "msg_test_1", + type: "message", + role: "assistant", + model: "claude-sonnet-4-20250514", + content: [], + stop_reason: null, + stop_sequence: null, + usage: { + cache_creation: null, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, + inference_geo: null, + input_tokens: 10, + output_tokens: 0, + service_tier: null + } + } + }, + { + type: "content_block_start", + index: 0, + content_block: { type: "tool_use", id: "toolu_test_1", name: "Write", input: {} } + }, + { + type: "content_block_delta", + index: 0, + delta: { type: "input_json_delta", partial_json: JSON.stringify({ path: "a" }) } + }, + { type: "content_block_stop", index: 0 }, + { + type: "message_delta", + delta: { stop_reason: "tool_use", stop_sequence: null }, + usage: { + cache_creation_input_tokens: null, + cache_read_input_tokens: null, + input_tokens: null, + output_tokens: 5 + } + }, + { type: "message_stop" } + ])) + ) + )) + ) + const Read = Tool.make("Read", { + parameters: Schema.Struct({ path: Schema.String }), + success: Schema.String + }) + const toolkit = Toolkit.make(Read) + + const parts = yield* LanguageModel.streamText({ + prompt: "use the tools", + toolkit, + disableToolCallResolution: true, + toolCallValidation: "deferred" + }).pipe( + Stream.runCollect, + Effect.provide(AnthropicLanguageModel.model("claude-sonnet-4-20250514")), + Effect.provide(toolkit.toLayer({ Read: () => Effect.succeed("") })), + Effect.provide(layer) + ) + + assert.deepStrictEqual( + parts.filter((part) => part.type === "tool-call").map(({ name, params }) => ({ name, params })), + [{ name: "Write", params: { path: "a" } }] + ) + })) + for (const blockType of ["tool_use", "server_tool_use"] as const) { it.effect(`fails with AiError for malformed streamed ${blockType} JSON`, () => Effect.gen(function*() { @@ -660,6 +738,72 @@ describe("AnthropicLanguageModel", () => { assert.strictEqual(text.delta, "Hello") })) + + it.effect("emits response metadata for a fallback block", () => + Effect.gen(function*() { + const fallback = { + type: "fallback", + from: { model: "claude-opus-5-5" }, + to: { model: "claude-opus-4-8" }, + trigger: { type: "refusal", category: "cyber" } + } as const + const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + makeHttpClient((request) => + Effect.succeed(sseResponse(request, [ + { + type: "message_start", + message: { + id: "msg_test_1", + type: "message", + role: "assistant", + model: "claude-opus-4-8", + content: [], + stop_reason: null, + stop_sequence: null, + usage: { + cache_creation: null, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, + input_tokens: 10, + output_tokens: 0, + service_tier: null + } + } + }, + { type: "content_block_start", index: 0, content_block: fallback }, + { type: "content_block_stop", index: 0 }, + { + type: "message_delta", + delta: { stop_reason: "end_turn", stop_sequence: null }, + usage: { + cache_creation_input_tokens: null, + cache_read_input_tokens: null, + input_tokens: null, + output_tokens: 5 + } + }, + { type: "message_stop" } + ])) + ) + )) + ) + + const parts = yield* LanguageModel.streamText({ prompt: "Hello" }).pipe( + Stream.runCollect, + Effect.provide(AnthropicLanguageModel.model("claude-opus-5-5")), + Effect.provide(layer) + ) + const metadata = globalThis.Array.from(parts).find((part) => + part.type === "response-metadata" && part.metadata.anthropic?.fallback !== undefined + ) + assert.strictEqual(metadata?.type === "response-metadata" ? metadata.modelId : undefined, "claude-opus-4-8") + assert.deepStrictEqual( + metadata?.type === "response-metadata" ? metadata.metadata.anthropic?.fallback : undefined, + fallback + ) + })) }) describe("generateText", () => { @@ -706,6 +850,79 @@ describe("AnthropicLanguageModel", () => { })) } + it.effect("emits response metadata for a fallback block and keeps fallback usage iterations", () => + Effect.gen(function*() { + const fallback = { + type: "fallback", + from: { model: "claude-opus-5-5" }, + to: { model: "claude-opus-4-8" }, + trigger: { type: "refusal", category: "cyber" } + } as const + const iterations = [ + { + type: "message", + model: "claude-opus-5-5", + cache_creation: null, + cache_creation_input_tokens: 0, + cache_read_input_tokens: 0, + input_tokens: 10, + output_tokens: 0 + }, + { + type: "fallback_message", + model: "claude-opus-4-8", + cache_creation: null, + cache_creation_input_tokens: 0, + cache_read_input_tokens: 0, + input_tokens: 10, + output_tokens: 5 + } + ] as const + const layer = AnthropicClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + makeHttpClient((request) => + Effect.succeed(jsonResponse(request, { + id: "msg_test_1", + type: "message", + role: "assistant", + model: "claude-opus-4-8", + content: [fallback, { type: "text", text: "Hello" }], + stop_reason: "end_turn", + stop_sequence: null, + usage: { + cache_creation: null, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, + input_tokens: 10, + output_tokens: 5, + service_tier: null, + iterations + } + })) + ) + )) + ) + + const response = yield* LanguageModel.generateText({ prompt: "Hello" }).pipe( + Effect.provide(AnthropicLanguageModel.model("claude-opus-5-5")), + Effect.provide(layer) + ) + const metadata = response.content.find((part) => + part.type === "response-metadata" && part.metadata.anthropic?.fallback !== undefined + ) + assert.strictEqual(metadata?.type === "response-metadata" ? metadata.modelId : undefined, "claude-opus-4-8") + assert.deepStrictEqual( + metadata?.type === "response-metadata" ? metadata.metadata.anthropic?.fallback : undefined, + fallback + ) + const finish = response.content.find((part) => part.type === "finish") + assert.deepStrictEqual( + finish?.type === "finish" ? finish.metadata.anthropic?.usage?.iterations : undefined, + iterations + ) + })) + it.effect("reports total input tokens and cache usage on the span", () => Effect.gen(function*() { const spans: Array = [] diff --git a/repos/effect/packages/ai/cloudflare/CHANGELOG.md b/repos/effect/packages/ai/cloudflare/CHANGELOG.md index 87470785c1..8428dc82ff 100644 --- a/repos/effect/packages/ai/cloudflare/CHANGELOG.md +++ b/repos/effect/packages/ai/cloudflare/CHANGELOG.md @@ -1,5 +1,29 @@ # @effect/ai-cloudflare +## 4.0.5 + +### Patch Changes + +- [#9121](https://github.com/Effect-TS/effect/pull/9121) [`bd2c7a3`](https://github.com/Effect-TS/effect/commit/bd2c7a3b8b94859a29b1064f87713dae0b1598f9) Thanks @jem-computer! - Support images in `CloudflareDecisionModel`. Byte arrays, base64 strings, and `data:` URLs are sent to Clef. Remote URLs fail with `AiError.InvalidUserInputError`. + +- [#9124](https://github.com/Effect-TS/effect/pull/9124) [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e) Thanks @jem-computer! - Support structured decision instructions, descriptions, and score legends in TypeSafe, Cloudflare, and OpenRouter. `Decision.rate` accepts labeled descriptions; `Rate.criteria` entries are now `{ label, description }` objects instead of strings. +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/ai/cloudflare/README.md b/repos/effect/packages/ai/cloudflare/README.md index ed3b8a0260..35a9d0f27b 100644 --- a/repos/effect/packages/ai/cloudflare/README.md +++ b/repos/effect/packages/ai/cloudflare/README.md @@ -37,8 +37,23 @@ const program = DecisionModel.decide(Triage, { }).pipe(Effect.provide(Clef)) ``` +Pass `images` to include pictures with the input. Clef shows them to the model before the state: + +```ts +declare const screenshotBytes: Uint8Array + +const withScreenshot = DecisionModel.decide(Triage, { + input: "Customers report this checkout error.", + images: [{ mediaType: "image/png", data: screenshotBytes }] +}) +``` + +Image `data` may be a `Uint8Array`, a base64 string, or a `data:` URL. Remote URLs fail with `AiError.InvalidUserInputError` because Clef does not fetch them, so download the image first. The API accepts up to 4 PNG, JPEG, or WebP images, each at most 4 MiB and 16 megapixels, with 8 MiB of decoded images in total and a 13 MiB request body. + Use `"clef"` for the larger model. `CloudflareDecisionModel.model` provides a model descriptor with Cloudflare provider metadata. `CloudflareClient.layer` accepts an explicit account ID and redacted API token; `apiUrl` and `transformClient` customize HTTP access. +Instructions and descriptions can be strings, JSON objects, or JSON arrays. A rating level with a structured description takes an explicit `label`, which answers use. + The client unwraps Cloudflare's REST envelope and maps failures to `AiError`. It does not retry automatically. Rate-limit errors include `Retry-After` when provided. The decision model validates answers and rescales small probability drift from four-decimal rounding. Cloudflare limits each request to 64 questions, classification to 2–255 choices, and ratings to 2–10 levels. See the [Clef API documentation](https://developers.cloudflare.com/workers-ai/models/clef/) for request limits. diff --git a/repos/effect/packages/ai/cloudflare/package.json b/repos/effect/packages/ai/cloudflare/package.json index b7e707957a..d8c9a520aa 100644 --- a/repos/effect/packages/ai/cloudflare/package.json +++ b/repos/effect/packages/ai/cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@effect/ai-cloudflare", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "A Cloudflare Workers AI decision provider for Effect", diff --git a/repos/effect/packages/ai/cloudflare/src/CloudflareDecisionModel.ts b/repos/effect/packages/ai/cloudflare/src/CloudflareDecisionModel.ts index 769875dbb7..7b1e28e041 100644 --- a/repos/effect/packages/ai/cloudflare/src/CloudflareDecisionModel.ts +++ b/repos/effect/packages/ai/cloudflare/src/CloudflareDecisionModel.ts @@ -4,9 +4,11 @@ * @stability unstable * @since 4.0.0 */ +import * as AiError from "effect/ai/AiError" import * as DecisionModel from "effect/ai/DecisionModel" import * as AiModel from "effect/ai/Model" import * as Effect from "effect/Effect" +import * as Base64 from "effect/encoding/Base64" import * as Layer from "effect/Layer" import { CloudflareClient } from "./CloudflareClient.ts" import type * as CloudflareSchema from "./CloudflareSchema.ts" @@ -35,6 +37,16 @@ export const model = ( /** * Builds a decision service with tolerance for four-decimal probability rounding. * + * **Details** + * + * Byte arrays and base64 strings are sent as base64 with their media type. + * `data:` URLs are sent unchanged. The API enforces image limits. + * + * **Gotchas** + * + * - Remote URLs fail with `AiError.InvalidUserInputError` because Clef does + * not fetch them. + * * @stability unstable * @category constructors * @since 4.0.0 @@ -46,7 +58,8 @@ export const make = Effect.fnUntraced( const client = yield* CloudflareClient return yield* DecisionModel.make({ probabilityPrecision: 4, - decide: Effect.fnUntraced(function*({ state, decisions }) { + supportsImages: true, + decide: Effect.fnUntraced(function*({ state, decisions, images }) { const questions: Record = Object.create(null) for (const [key, decision] of Object.entries(decisions)) { switch (decision._tag) { @@ -54,14 +67,32 @@ export const make = Effect.fnUntraced( questions[key] = { type: "choice", instructions: decision.instructions, criteria: decision.criteria } break case "Rate": - questions[key] = { type: "score", instructions: decision.instructions, criteria: decision.criteria } + questions[key] = { + type: "score", + instructions: decision.instructions, + criteria: decision.criteria.map((level) => level.description) + } break case "Probability": questions[key] = { type: "noul", instructions: decision.instructions, criteria: decision.criteria } break } } - const response = yield* client.createDecisions({ model: options.model, state, questions }) + if (images?.some((image) => image.data instanceof URL && image.data.protocol !== "data:")) { + return yield* Effect.fail(AiError.make({ + module: "CloudflareDecisionModel", + method: "decide", + reason: new AiError.InvalidUserInputError({ + description: "Cloudflare Clef accepts base64 or data URL images, not remote URLs" + }) + })) + } + const response = yield* client.createDecisions({ + model: options.model, + state, + questions, + ...(images === undefined ? undefined : { images: images.map(encodeImage) }) + }) const answers: Record = Object.create(null) for (const [key, decision] of Object.entries(decisions)) { const answer = response.answers[key] @@ -79,7 +110,7 @@ export const make = Effect.fnUntraced( const probabilities: Record = Object.create(null) for (let index = 0; index < levels.length; index++) { const probability = answer.probabilities[String(index)] - if (probability !== undefined) probabilities[levels[index]] = probability + if (probability !== undefined) probabilities[levels[index].label] = probability } answers[key] = { _tag: "Rate", rating: answer.score, probabilities, confidence: answer.confidence } break @@ -98,6 +129,12 @@ export const make = Effect.fnUntraced( } ) +const encodeImage = (image: DecisionModel.Image): typeof CloudflareSchema.Image.Encoded => + image.data instanceof URL ? image.data.href : { + content_type: image.mediaType, + base64: typeof image.data === "string" ? image.data : Base64.encode(image.data) + } + /** * Provides DecisionModel using an existing CloudflareClient. * diff --git a/repos/effect/packages/ai/cloudflare/src/CloudflareSchema.ts b/repos/effect/packages/ai/cloudflare/src/CloudflareSchema.ts index 3ae972da05..d712ddf800 100644 --- a/repos/effect/packages/ai/cloudflare/src/CloudflareSchema.ts +++ b/repos/effect/packages/ai/cloudflare/src/CloudflareSchema.ts @@ -6,6 +6,8 @@ */ import * as Schema from "effect/Schema" +const Entry = Schema.Union([Schema.String, Schema.JsonObject, Schema.Array(Schema.Json)]) + /** * A classification question. * @@ -15,8 +17,8 @@ import * as Schema from "effect/Schema" */ export const ChoiceQuestion = Schema.Struct({ type: Schema.Literal("choice"), - instructions: Schema.String, - criteria: Schema.Record(Schema.String, Schema.String) + instructions: Entry, + criteria: Schema.Record(Schema.String, Schema.NullOr(Entry)) }) /** @@ -28,8 +30,8 @@ export const ChoiceQuestion = Schema.Struct({ */ export const ScoreQuestion = Schema.Struct({ type: Schema.Literal("score"), - instructions: Schema.String, - criteria: Schema.Array(Schema.String) + instructions: Entry, + criteria: Schema.Array(Schema.Json) }) /** @@ -41,12 +43,13 @@ export const ScoreQuestion = Schema.Struct({ */ export const NoulQuestion = Schema.Struct({ type: Schema.Literal("noul"), - instructions: Schema.String, - criteria: Schema.optional(Schema.Struct({ false: Schema.String, true: Schema.String })) + instructions: Entry, + criteria: Schema.optional(Schema.Struct({ false: Schema.Json, true: Schema.Json })) }) /** - * A Clef classification, rating, or probability question. + * A Clef question with string, JSON object, or JSON array instructions. + * Choice descriptions also accept `null`; Score and Noul descriptions accept any JSON value. * * @stability unstable * @category schemas @@ -55,7 +58,32 @@ export const NoulQuestion = Schema.Struct({ export const Question = Schema.Union([ChoiceQuestion, ScoreQuestion, NoulQuestion]) /** - * A batch of questions about text or JSON state. + * An image as a `data:` URL or as base64 data with its media type. Clef + * rejects remote URLs. + * + * @stability unstable + * @category schemas + * @since 4.0.5 + */ +export const Image = Schema.Union([ + Schema.String, + Schema.Struct({ + content_type: Schema.Union([ + Schema.Literals(["image/png", "image/jpeg", "image/webp"]), + Schema.StringForLiteralAutocomplete + ]), + base64: Schema.String + }) +]) + +/** + * A batch of questions about text or JSON state, with optional images shown + * to the model before the state. + * + * **Details** + * + * Clef accepts up to 4 images of at most 4 MiB and 16 megapixels each, 8 MiB + * of decoded images in total, and 13 MiB per request body. * * @stability unstable * @category schemas @@ -64,7 +92,8 @@ export const Question = Schema.Union([ChoiceQuestion, ScoreQuestion, NoulQuestio export const DecisionsRequest = Schema.Struct({ model: Schema.Union([Schema.Literals(["clef", "clef-flash"]), Schema.StringForLiteralAutocomplete]), state: Schema.Json, - questions: Schema.Record(Schema.String, Question) + questions: Schema.Record(Schema.String, Question), + images: Schema.optional(Schema.Array(Image)) }) /** @@ -82,7 +111,7 @@ export const ChoiceAnswer = Schema.Struct({ }) /** - * A zero-based rating and index-keyed distribution. + * A zero-based rating and index-keyed distribution. `legend` maps indices to descriptions. * * @stability unstable * @category schemas @@ -93,7 +122,7 @@ export const ScoreAnswer = Schema.Struct({ score: Schema.Number, probabilities: Schema.Record(Schema.String, Schema.Number), confidence: Schema.Number, - legend: Schema.Record(Schema.String, Schema.String) + legend: Schema.Record(Schema.String, Schema.Json) }) /** diff --git a/repos/effect/packages/ai/cloudflare/test/CloudflareDecisionModel.test.ts b/repos/effect/packages/ai/cloudflare/test/CloudflareDecisionModel.test.ts index ff4c27d793..ce641e22c3 100644 --- a/repos/effect/packages/ai/cloudflare/test/CloudflareDecisionModel.test.ts +++ b/repos/effect/packages/ai/cloudflare/test/CloudflareDecisionModel.test.ts @@ -72,6 +72,16 @@ const clientLayer = ( const layer = (answers: unknown) => CloudflareDecisionModel.layer({ model: "clef" }).pipe(Layer.provide(clientLayer(answers))) +const Structured = Decision.make({ + input: Schema.String, + decisions: { + severity: Decision.rate({ + instructions: ["How severe?"], + criteria: ["Minor", { label: "Critical", description: { impact: "outage" } }] + }) + } +}) + describe("CloudflareDecisionModel", () => { it.effect("sends every decision as a question and maps the answers", () => Effect.gen(function*() { @@ -104,7 +114,7 @@ describe("CloudflareDecisionModel", () => { severity: { type: "score", instructions: Triage.decisions.severity.instructions, - criteria: Triage.decisions.severity.criteria + criteria: ["Minor", "Major", "Critical"] }, urgent: { type: "noul", @@ -172,4 +182,73 @@ describe("CloudflareDecisionModel", () => { assert.strictEqual(error.reason._tag, "InvalidOutputError") }).pipe(Effect.provide(layer(invalid)))) } + + it.effect("sends byte arrays, base64 strings, and data URLs as images", () => { + const dataUrl = "data:image/webp;base64,UklGRg==" + return Effect.gen(function*() { + const result = yield* DecisionModel.decide(Triage, { + input, + images: [ + { mediaType: "image/png", data: new Uint8Array([137, 80, 78, 71]) }, + { mediaType: "image/jpeg", data: "/9j/4AAQ" }, + { mediaType: "image/webp", data: new URL(dataUrl) } + ] + }) + assert.strictEqual(result.answers.urgent.probability, 0.99) + }).pipe( + Effect.provide(CloudflareDecisionModel.layer({ model: "clef" })), + Effect.provide(clientLayer(answers, (request) => { + assert.strictEqual(request.body._tag, "Uint8Array") + if (request.body._tag === "Uint8Array") { + assert.deepStrictEqual(JSON.parse(new TextDecoder().decode(request.body.body)).images, [ + { content_type: "image/png", base64: "iVBORw==" }, + { content_type: "image/jpeg", base64: "/9j/4AAQ" }, + dataUrl + ]) + } + })) + ) + }) + + it.effect("rejects remote image URLs without sending a request", () => { + let requests = 0 + return Effect.gen(function*() { + const error = yield* Effect.flip(DecisionModel.decide(Triage, { + input, + images: [{ mediaType: "image/png", data: new URL("https://example.com/cat.png") }] + })) + assert.strictEqual(error.reason._tag, "InvalidUserInputError") + assert.strictEqual(requests, 0) + }).pipe( + Effect.provide(CloudflareDecisionModel.layer({ model: "clef" })), + Effect.provide(clientLayer(answers, () => { + requests++ + })) + ) + }) + + it.effect("sends structured descriptions and maps score indices to labels", () => + Effect.gen(function*() { + const result = yield* DecisionModel.decide(Structured, { input: "Checkout is down" }) + assert.strictEqual(result.answers.severity.label, "Critical") + assert.deepStrictEqual({ ...result.answers.severity.probabilities }, { Minor: 0.1, Critical: 0.9 }) + }).pipe( + Effect.provide(CloudflareDecisionModel.layer({ model: "clef" })), + Effect.provide(clientLayer({ + severity: { + type: "score", + score: 0.9, + probabilities: { "0": 0.1, "1": 0.9 }, + confidence: 0.9, + legend: { "0": "Minor", "1": { impact: "outage" } } + } + }, (request) => { + assert.strictEqual(request.body._tag, "Uint8Array") + if (request.body._tag === "Uint8Array") { + assert.deepStrictEqual(JSON.parse(new TextDecoder().decode(request.body.body)).questions, { + severity: { type: "score", instructions: ["How severe?"], criteria: ["Minor", { impact: "outage" }] } + }) + } + })) + )) }) diff --git a/repos/effect/packages/ai/cloudflare/typetest/CloudflareDecisionModel.tst.ts b/repos/effect/packages/ai/cloudflare/typetest/CloudflareDecisionModel.tst.ts index 880636e3ea..76ea7d0f7b 100644 --- a/repos/effect/packages/ai/cloudflare/typetest/CloudflareDecisionModel.tst.ts +++ b/repos/effect/packages/ai/cloudflare/typetest/CloudflareDecisionModel.tst.ts @@ -18,3 +18,27 @@ describe("Cloudflare model identifiers", () => { expect(CloudflareDecisionModel.model).type.toBeCallableWith("clef-flash") }) }) + +describe("Cloudflare images", () => { + it("accepts data URLs and base64 images with any media type", () => { + expect(client.createDecisions).type.toBeCallableWith({ + model, + state: "Checkout is down", + questions: {}, + images: [ + "data:image/png;base64,iVBORw==", + { content_type: "image/png", base64: "iVBORw==" }, + { content_type: model, base64: "iVBORw==" } + ] + }) + }) + + it("rejects images without base64 data", () => { + expect(client.createDecisions).type.not.toBeCallableWith({ + model, + state: "Checkout is down", + questions: {}, + images: [{ content_type: "image/png" }] + }) + }) +}) diff --git a/repos/effect/packages/ai/openai-compat/CHANGELOG.md b/repos/effect/packages/ai/openai-compat/CHANGELOG.md index d588c5c9af..915ba4c40a 100644 --- a/repos/effect/packages/ai/openai-compat/CHANGELOG.md +++ b/repos/effect/packages/ai/openai-compat/CHANGELOG.md @@ -1,5 +1,43 @@ # @effect/ai-openai-compat +## 4.0.5 + +### Patch Changes + +- [#9168](https://github.com/Effect-TS/effect/pull/9168) [`a0ad8d3`](https://github.com/Effect-TS/effect/commit/a0ad8d3a4fce6b0db1315b2787aa6dd64d227d3d) Thanks @danieljvdm! - Emit each streamed chat completion event's parts as one chunk instead of creating an inner stream per event. + +- [#9140](https://github.com/Effect-TS/effect/pull/9140) [`91f4c74`](https://github.com/Effect-TS/effect/commit/91f4c74fe8f41a9897927e9bc2c4b814924c85e0) Thanks @tim-smart! - Use `"openai-compat"` instead of `"openai"` as the provider key for error metadata, prompt part options, and response part metadata, so `@effect/ai-openai-compat` no longer shares module augmentation keys with `@effect/ai-openai`. + +- [#9167](https://github.com/Effect-TS/effect/pull/9167) [`f9f4335`](https://github.com/Effect-TS/effect/commit/f9f43352d6b718623fdc0f29e2297785a8d6a073) Thanks @danieljvdm! - Avoid creating a child stream for each SSE event when streaming chat completions. + +- [#9144](https://github.com/Effect-TS/effect/pull/9144) [`738bc87`](https://github.com/Effect-TS/effect/commit/738bc873a779179a9c9f0e675b51b2f074796598) Thanks @danieljvdm! - Avoid intermediate content allocations for single text-part user messages. +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- [#9008](https://github.com/Effect-TS/effect/pull/9008) [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d) Thanks @effect-bot! - Add `toolCallValidation: "deferred"` for callers using `disableToolCallResolution: true`. Model-generated tool calls return with `unknown` parameters, including invalid parameters and undeclared tool names, even without a toolkit. Supported by the Anthropic, OpenAI, and OpenAI-compatible providers. Strict validation remains the default; provider-executed calls remain validated. + +- [#9011](https://github.com/Effect-TS/effect/pull/9011) [`844a77b`](https://github.com/Effect-TS/effect/commit/844a77b18c03b4faa386cf04bf94908d3d37abc7) Thanks @tim-smart! - Replay assistant text, reasoning, and tool calls in Chat Completions requests even when their parts carry item IDs. Remove unused Responses API include bookkeeping and the unsupported `store` and `conversation` configuration options. Neither option is sent to the provider. + +- [#9005](https://github.com/Effect-TS/effect/pull/9005) [`42aceb9`](https://github.com/Effect-TS/effect/commit/42aceb966a558e5c3edd3ece857ef2f1ef738384) Thanks @effect-bot! - Replay assistant reasoning alongside text and tool calls in a single chat message, preserving the provider’s reasoning field (defaulting to `reasoning_content`). + +- [#9054](https://github.com/Effect-TS/effect/pull/9054) [`8aee3b9`](https://github.com/Effect-TS/effect/commit/8aee3b9caa796aa79316c82c7c83f98c89dc49f5) Thanks @danieljvdm! - Convert each tool's parameter schema once per request, instead of again for every returned tool call. +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- [#8916](https://github.com/Effect-TS/effect/pull/8916) [`950ea4e`](https://github.com/Effect-TS/effect/commit/950ea4eeb22785f437112976f399726814549ff3) Thanks @edizferit! - Preserve tool call `extra_content` from OpenAI-compatible providers, so Gemini receives its thought signatures on follow-up tool turns. It is exposed as `metadata.openai.extraContent` on tool call response parts and sent back from the `openai.extraContent` tool call prompt option. + +- [#8952](https://github.com/Effect-TS/effect/pull/8952) [`b63a4f9`](https://github.com/Effect-TS/effect/commit/b63a4f9ac75a277d53eb43eed5dfb0f793a96f6e) Thanks @jayhemnani9910! - Ignore empty `content` deltas in streamed chat completions. Providers such as Ollama send `content: ""` with every reasoning chunk, which split a single reasoning block into one part per token and opened the text part before the reasoning finished. +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/ai/openai-compat/package.json b/repos/effect/packages/ai/openai-compat/package.json index 361b19cb87..c908e4b93d 100644 --- a/repos/effect/packages/ai/openai-compat/package.json +++ b/repos/effect/packages/ai/openai-compat/package.json @@ -1,6 +1,6 @@ { "name": "@effect/ai-openai-compat", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "An OpenAI compat integration for Effect", diff --git a/repos/effect/packages/ai/openai-compat/src/OpenAiClient.ts b/repos/effect/packages/ai/openai-compat/src/OpenAiClient.ts index 8551f926ea..1c535b6daf 100644 --- a/repos/effect/packages/ai/openai-compat/src/OpenAiClient.ts +++ b/repos/effect/packages/ai/openai-compat/src/OpenAiClient.ts @@ -21,6 +21,7 @@ import * as HttpClientRequest from "effect/http/HttpClientRequest" import * as HttpClientResponse from "effect/http/HttpClientResponse" import * as Layer from "effect/Layer" import * as Redacted from "effect/Redacted" +import * as Result from "effect/Result" import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import * as Errors from "./internal/errors.ts" @@ -216,9 +217,9 @@ export const make = Effect.fnUntraced( const stream = response.stream.pipe( Stream.decodeText(), Stream.pipeThroughChannel(Sse.decode()), - Stream.flatMap((event) => { + Stream.filterMap((event) => { const data = decodeChatCompletionSseData(event.data) - return Stream.fromIterable(data !== undefined ? [data] : []) + return data !== undefined ? Result.succeed(data) : Result.failVoid }), Stream.takeUntil((event) => event === "[DONE]"), Stream.catchTags({ @@ -531,6 +532,7 @@ type FunctionCall = { readonly call_id: string readonly name: string readonly arguments: string + readonly extra_content?: JsonObject | undefined readonly status?: MessageStatus | undefined } @@ -978,6 +980,7 @@ export type ChatCompletionRequestToolCall = { readonly name: string readonly arguments: string } + readonly extra_content?: JsonObject | undefined } /** * Message shapes accepted by the chat completions endpoint. @@ -991,6 +994,15 @@ export type ChatCompletionRequestMessage = readonly role: "system" | "developer" | "user" | "assistant" readonly content: string | ReadonlyArray | null readonly tool_calls?: ReadonlyArray | undefined + /** + * Assistant reasoning replayed for providers that read it from + * `reasoning_content`. + */ + readonly reasoning_content?: string | undefined + /** + * Assistant reasoning replayed for providers that read it from `reasoning`. + */ + readonly reasoning?: string | undefined } | { readonly role: "tool" @@ -1135,6 +1147,7 @@ const ChatCompletionToolCall = Schema.Struct({ id: Schema.optionalKey(Schema.String), index: Schema.optionalKey(Schema.Int), type: Schema.optionalKey(Schema.String), + extra_content: Schema.optionalKey(Schema.NullOr(Schema.JsonObject)), function: Schema.optionalKey(ChatCompletionToolFunction) }) @@ -1143,6 +1156,7 @@ const ChatCompletionToolCallDelta = Schema.Struct({ id: Schema.optionalKey(Schema.NullOr(Schema.String)), index: Schema.optionalKey(Schema.Int), type: Schema.optionalKey(Schema.String), + extra_content: Schema.optionalKey(Schema.NullOr(Schema.JsonObject)), function: Schema.optionalKey(ChatCompletionToolFunctionDelta) }) diff --git a/repos/effect/packages/ai/openai-compat/src/OpenAiError.ts b/repos/effect/packages/ai/openai-compat/src/OpenAiError.ts index ad317c58ea..074c66765a 100644 --- a/repos/effect/packages/ai/openai-compat/src/OpenAiError.ts +++ b/repos/effect/packages/ai/openai-compat/src/OpenAiError.ts @@ -77,7 +77,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface RateLimitErrorMetadata { - readonly openai?: OpenAiRateLimitMetadata | null + readonly "openai-compat"?: OpenAiRateLimitMetadata | null } /** @@ -88,7 +88,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface QuotaExhaustedErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } /** @@ -99,7 +99,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface AuthenticationErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } /** @@ -110,7 +110,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface ContentPolicyErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } /** @@ -121,7 +121,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface InvalidRequestErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } /** @@ -132,7 +132,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface InternalProviderErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } /** @@ -143,7 +143,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface InvalidOutputErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } /** @@ -154,7 +154,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface StructuredOutputErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } /** @@ -165,7 +165,7 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface UnsupportedSchemaErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } /** @@ -176,6 +176,6 @@ declare module "effect/ai/AiError" { * @since 4.0.0 */ export interface UnknownErrorMetadata { - readonly openai?: OpenAiErrorMetadata | null + readonly "openai-compat"?: OpenAiErrorMetadata | null } } diff --git a/repos/effect/packages/ai/openai-compat/src/OpenAiLanguageModel.ts b/repos/effect/packages/ai/openai-compat/src/OpenAiLanguageModel.ts index b8ba73d309..2f73db2296 100644 --- a/repos/effect/packages/ai/openai-compat/src/OpenAiLanguageModel.ts +++ b/repos/effect/packages/ai/openai-compat/src/OpenAiLanguageModel.ts @@ -16,6 +16,7 @@ import { toCodecOpenAI } from "effect/ai/OpenAiStructuredOutput" import type * as Prompt from "effect/ai/Prompt" import type * as Response from "effect/ai/Response" import * as Tool from "effect/ai/Tool" +import * as Arr from "effect/Array" import * as Context from "effect/Context" import * as DateTime from "effect/DateTime" import * as Effect from "effect/Effect" @@ -32,23 +33,20 @@ import * as Schema from "effect/Schema" import * as AST from "effect/SchemaAST" import * as Stream from "effect/Stream" import type { Span } from "effect/Tracer" -import type { DeepMutable, Simplify } from "effect/Types" +import type { Simplify } from "effect/Types" import * as InternalUtilities from "./internal/utilities.ts" import { type Annotation, type ChatCompletionContentPart, + type ChatCompletionRequestMessage, type ChatCompletionRequestToolCall, type CreateResponse, type CreateResponse200, type CreateResponse200Sse, type CreateResponseRequestJson, - type IncludeEnum, type InputContent, - type InputItem, type MessageStatus, OpenAiClient, - type ReasoningItem, - type SummaryTextContent, type TextResponseFormatConfiguration, type Tool as OpenAiClientTool, type UnknownChatCompletionEvent @@ -66,7 +64,7 @@ type ImageDetail = "auto" | "low" | "high" type ConfigOptions = Simplify< & Partial< - Omit + Omit > & { /** @@ -137,7 +135,7 @@ declare module "effect/ai/Prompt" { /** * Provider-specific file options for OpenAI-compatible APIs. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`. */ @@ -156,7 +154,7 @@ declare module "effect/ai/Prompt" { /** * Provider-specific reasoning options for OpenAI-compatible APIs. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The ID of the item to reference. */ @@ -167,6 +165,12 @@ declare module "effect/ai/Prompt" { * parameter. */ readonly encryptedContent?: string | null + /** + * The chat message field the reasoning was returned under. Replayed + * reasoning is sent back under the same field, defaulting to + * `reasoning_content`. + */ + readonly reasoningField?: "reasoning" | "reasoning_content" | null } | null } @@ -181,7 +185,7 @@ declare module "effect/ai/Prompt" { /** * Provider-specific tool-call options for OpenAI-compatible APIs. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The ID of the item to reference. */ @@ -190,6 +194,10 @@ declare module "effect/ai/Prompt" { * The status to send for the tool-call item. */ readonly status?: MessageStatus | null + /** + * Provider-specific extra content to echo back with the tool call. + */ + readonly extraContent?: Schema.JsonObject | null } | null } @@ -204,7 +212,7 @@ declare module "effect/ai/Prompt" { /** * Provider-specific tool-result options for OpenAI-compatible APIs. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The ID of the item to reference. */ @@ -227,7 +235,7 @@ declare module "effect/ai/Prompt" { /** * Provider-specific text options for OpenAI-compatible APIs. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The ID of the item to reference. */ @@ -256,7 +264,7 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned for the text part. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The OpenAI item ID associated with the text part. */ @@ -289,7 +297,7 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned for the streamed text start. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The OpenAI item ID associated with the streamed text part. */ @@ -308,7 +316,7 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned for the streamed text end. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The OpenAI item ID associated with the streamed text part. */ @@ -331,7 +339,7 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned for the reasoning part. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The OpenAI item ID associated with the reasoning part. */ @@ -340,6 +348,10 @@ declare module "effect/ai/Response" { * Encrypted reasoning content that can be sent back in later requests. */ readonly encryptedContent?: string | null + /** + * The chat message field the provider returned the reasoning under. + */ + readonly reasoningField?: "reasoning" | "reasoning_content" | null } | null } @@ -354,7 +366,7 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned for the streamed reasoning start. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The OpenAI item ID associated with the reasoning part. */ @@ -363,6 +375,10 @@ declare module "effect/ai/Response" { * Encrypted reasoning content that can be sent back in later requests. */ readonly encryptedContent?: string | null + /** + * The chat message field the provider returned the reasoning under. + */ + readonly reasoningField?: "reasoning" | "reasoning_content" | null } | null } @@ -377,7 +393,7 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned for the streamed reasoning delta. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The OpenAI item ID associated with the reasoning part. */ @@ -396,7 +412,7 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned for the streamed reasoning end. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The OpenAI item ID associated with the reasoning part. */ @@ -419,11 +435,15 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned for the tool call. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The OpenAI item ID associated with the tool call. */ readonly itemId?: string | null + /** + * Provider-specific extra content returned with the tool call. + */ + readonly extraContent?: Schema.JsonObject | null } | null } @@ -438,7 +458,7 @@ declare module "effect/ai/Response" { /** * Provider-specific citation metadata for OpenAI-compatible APIs. */ - readonly openai?: + readonly "openai-compat"?: | { /** * Identifies a citation to an uploaded file. @@ -495,7 +515,7 @@ declare module "effect/ai/Response" { /** * Provider-specific URL citation metadata for OpenAI-compatible APIs. */ - readonly openai?: { + readonly "openai-compat"?: { /** * Identifies a citation to a URL. */ @@ -522,7 +542,7 @@ declare module "effect/ai/Response" { /** * Provider-specific metadata returned when generation finishes. */ - readonly openai?: { + readonly "openai-compat"?: { /** * The service tier reported by the OpenAI-compatible provider. */ @@ -604,17 +624,16 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig readonly config: typeof Config.Service readonly options: LanguageModel.ProviderOptions readonly toolNameMapper: Tool.NameMapper - }): Effect.fn.Return { - const include = new Set() - const capabilities = getModelCapabilities(config.model!) + }): Effect.fn.Return<{ + readonly request: CreateResponseRequestJson + readonly toolCodecs: ToolCodecs + }, AiError.AiError> { const messages = yield* prepareMessages({ config, options, - capabilities, - include, toolNameMapper }) - const { toolChoice, tools } = yield* prepareTools({ + const { toolChoice, toolCodecs, tools } = yield* prepareTools({ config, options, toolNameMapper @@ -626,8 +645,6 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig const { fileIdPrefixes: _fip, strictJsonSchema: _sjs, ...apiConfig } = config const request: CreateResponse = { ...apiConfig, - input: messages, - include: include.size > 0 ? Array.from(include) : null, text: { verbosity: config.text?.verbosity ?? null, format: responseFormat @@ -635,7 +652,7 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig ...(tools !== undefined ? { tools } : undefined), ...(toolChoice !== undefined ? { tool_choice: toolChoice } : undefined) } - return toChatCompletionsRequest(request) + return { request: toChatCompletionsRequest(request, messages), toolCodecs } } ) @@ -645,7 +662,7 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig function*(options) { const config = yield* makeConfig const toolNameMapper = new Tool.NameMapper(options.tools) - const request = yield* makeRequest({ config, options, toolNameMapper }) + const { request, toolCodecs } = yield* makeRequest({ config, options, toolNameMapper }) annotateRequest(options.span, request) const [rawResponse, response] = yield* client.createResponse(request) annotateResponse(options.span, rawResponse) @@ -653,7 +670,8 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig options, rawResponse, response, - toolNameMapper + toolNameMapper, + toolCodecs }) } ), @@ -661,14 +679,15 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig function*(options) { const config = yield* makeConfig const toolNameMapper = new Tool.NameMapper(options.tools) - const request = yield* makeRequest({ config, options, toolNameMapper }) + const { request, toolCodecs } = yield* makeRequest({ config, options, toolNameMapper }) annotateRequest(options.span, request) const [response, stream] = yield* client.createResponseStream(request) return yield* makeStreamResponse({ options, stream, response, - toolNameMapper + toolNameMapper, + toolCodecs }) }, (effect, options) => @@ -758,27 +777,13 @@ const prepareMessages = Effect.fnUntraced( function*>({ config, options, - capabilities, - include, toolNameMapper }: { readonly config: typeof Config.Service readonly options: LanguageModel.ProviderOptions - readonly include: Set - readonly capabilities: ModelCapabilities readonly toolNameMapper: Tool.NameMapper - }): Effect.fn.Return, AiError.AiError> { - const hasConversation = Predicate.isNotNullish(config.conversation) - - // Handle Included Features - if (config.top_logprobs !== undefined) { - include.add("message.output_text.logprobs") - } - if (config.store === false && capabilities.isReasoningModel) { - include.add("reasoning.encrypted_content") - } - - const messages: Array = [] + }): Effect.fn.Return, AiError.AiError> { + const messages: Array = [] for (const message of options.prompt.content) { switch (message.role) { @@ -847,155 +852,62 @@ const prepareMessages = Effect.fnUntraced( } } - messages.push({ role: "user", content }) + messages.push({ role: "user", content: toChatMessageContent(content) }) break } case "assistant": { - const reasoningMessages: Record> = Object.create(null) + let content: string | null = null + let reasoning = "" + let reasoningField: ReasoningField | undefined + const toolCalls: Array = [] for (const part of message.content) { switch (part.type) { case "text": { - const id = getItemId(part) - - // When in conversation mode, skip items that already exist in the - // conversation context to avoid "Duplicate item found" errors - if (hasConversation && Predicate.isNotNull(id)) { - break - } - - if (config.store === true && Predicate.isNotNull(id)) { - messages.push({ type: "item_reference", id }) - break - } - - messages.push({ - id: id!, - type: "message", - role: "assistant", - status: part.options.openai?.status ?? "completed", - content: [{ - type: "output_text", - text: part.text, - annotations: part.options.openai?.annotations ?? [], - logprobs: [] - }] - }) - + content = (content ?? "") + part.text break } case "reasoning": { - const id = getItemId(part) - const encryptedContent = getEncryptedContent(part) - - if (hasConversation && Predicate.isNotNull(id)) { - break - } - - if (Predicate.isNotNull(id)) { - const message = reasoningMessages[id] - - if (config.store === true) { - // Use item references to refer to reasoning (single reference) - // when the first part is encountered - if (Predicate.isUndefined(message)) { - messages.push({ type: "item_reference", id }) - - // Store unused reasoning message to mark its id as used - reasoningMessages[id] = { - type: "reasoning", - id, - summary: [] - } - } - } else { - const summaryParts: Array = [] - - if (part.text.length > 0) { - summaryParts.push({ type: "summary_text", text: part.text }) - } - - if (Predicate.isUndefined(message)) { - reasoningMessages[id] = { - type: "reasoning", - id, - summary: summaryParts, - encrypted_content: encryptedContent ?? null - } - - messages.push(reasoningMessages[id]) - } else { - message.summary.push(...summaryParts) - - // Update encrypted content to enable setting it in the - // last summary part - if (Predicate.isNotNull(encryptedContent)) { - message.encrypted_content = encryptedContent - } - } - } - } - + reasoning += part.text + reasoningField ??= part.options["openai-compat"]?.reasoningField ?? undefined break } case "tool-call": { - const id = getItemId(part) - const status = getStatus(part) - - if (hasConversation && Predicate.isNotNull(id)) { - break - } - - if (config.store && Predicate.isNotNull(id)) { - messages.push({ type: "item_reference", id }) - break - } - if (part.providerExecuted) { break } - const toolName = toolNameMapper.getProviderName(part.name) + const extraContent = getExtraContent(part) - messages.push({ - type: "function_call", - name: toolName, - call_id: part.id, - arguments: JSON.stringify(part.params), - ...(Predicate.isNotNull(id) ? { id } : {}), - ...(Predicate.isNotNull(status) ? { status } : {}) + toolCalls.push({ + id: part.id, + type: "function", + function: { + name: toolNameMapper.getProviderName(part.name), + arguments: JSON.stringify(part.params) + }, + ...(Predicate.isNotNull(extraContent) ? { extra_content: extraContent } : undefined) }) - break } - - // Assistant tool-result parts are always provider executed - case "tool-result": { - // Skip execution denied results - these have no corresponding - // item in OpenAI's store - if ( - Predicate.hasProperty(part.result, "type") && - part.result.type === "execution-denied" - ) { - break - } - - if (hasConversation) { - break - } - - if (config.store === true) { - const id = getItemId(part) ?? part.id - messages.push({ type: "item_reference", id }) - } - } } } + // Text, reasoning and tool calls from one prompt message are sent as a + // single chat message so reasoning stays attached to its tool calls + if (content !== null || toolCalls.length > 0) { + messages.push({ + role: "assistant", + content, + ...(reasoning.length > 0 ? { [reasoningField ?? "reasoning_content"]: reasoning } : undefined), + ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : undefined) + }) + } + break } @@ -1005,13 +917,10 @@ const prepareMessages = Effect.fnUntraced( continue } - const status = getStatus(part) - messages.push({ - type: "function_call_output", - call_id: part.id, - output: typeof part.result === "string" ? part.result : JSON.stringify(part.result), - ...(Predicate.isNotNull(status) ? { status } : {}) + role: "tool", + tool_call_id: part.id, + content: typeof part.result === "string" ? part.result : JSON.stringify(part.result) }) } @@ -1060,6 +969,7 @@ type ActiveToolCall = { readonly id: string name: string arguments: string + extraContent: Schema.JsonObject | undefined } const makeResponse = Effect.fnUntraced( @@ -1067,12 +977,14 @@ const makeResponse = Effect.fnUntraced( options, rawResponse, response, - toolNameMapper + toolNameMapper, + toolCodecs }: { readonly options: LanguageModel.ProviderOptions readonly rawResponse: CreateResponse200 readonly response: HttpClientResponse.HttpClientResponse readonly toolNameMapper: Tool.NameMapper + readonly toolCodecs: ToolCodecs }): Effect.fn.Return< Array, AiError.AiError @@ -1093,9 +1005,10 @@ const makeResponse = Effect.fnUntraced( const message = choice?.message if (message !== undefined) { - const reasoning = message.reasoning ?? message.reasoning_content - if (Predicate.isNotNullish(reasoning) && reasoning.length > 0) { - parts.push({ type: "reasoning", text: reasoning }) + const reasoningField = getResponseReasoningField(message) + const reasoning = reasoningField !== undefined ? message[reasoningField] : undefined + if (reasoningField !== undefined && Predicate.isNotNullish(reasoning) && reasoning.length > 0) { + parts.push({ type: "reasoning", text: reasoning, metadata: { "openai-compat": { reasoningField } } }) } if ( @@ -1121,14 +1034,19 @@ const makeResponse = Effect.fnUntraced( }) }) }) - const params = yield* transformToolCallParams(options.tools, toolName, toolParams) + const params = yield* transformToolCallParams(options, toolName, toolParams, toolCodecs) hasToolCalls = true parts.push({ type: "tool-call", id: toolId, name: toolName, params, - metadata: { openai: { ...makeItemIdMetadata(toolCall.id) } } + metadata: { + "openai-compat": { + ...makeItemIdMetadata(toolCall.id), + ...makeExtraContentMetadata(toolCall.extra_content ?? undefined) + } + } }) } } @@ -1145,7 +1063,7 @@ const makeResponse = Effect.fnUntraced( reason: finishReason, usage: getUsage(rawResponse.usage), response: buildHttpResponseDetails(response), - ...(serviceTier !== undefined && { metadata: { openai: { serviceTier } } }) + ...(serviceTier !== undefined && { metadata: { "openai-compat": { serviceTier } } }) }) return parts @@ -1157,12 +1075,14 @@ const makeStreamResponse = Effect.fnUntraced( options, stream, response, - toolNameMapper + toolNameMapper, + toolCodecs }: { readonly options: LanguageModel.ProviderOptions readonly stream: Stream.Stream readonly response: HttpClientResponse.HttpClientResponse readonly toolNameMapper: Tool.NameMapper + readonly toolCodecs: ToolCodecs }): Effect.fn.Return< Stream.Stream, AiError.AiError @@ -1187,7 +1107,7 @@ const makeStreamResponse = Effect.fnUntraced( parts.push({ type: "reasoning-end", id: reasoningId, - metadata: { openai: { ...makeItemIdMetadata(reasoningId) } } + metadata: { "openai-compat": { ...makeItemIdMetadata(reasoningId) } } }) } @@ -1195,7 +1115,7 @@ const makeStreamResponse = Effect.fnUntraced( parts.push({ type: "text-end", id: textId, - metadata: { openai: { ...makeItemIdMetadata(textId) } } + metadata: { "openai-compat": { ...makeItemIdMetadata(textId) } } }) } @@ -1213,14 +1133,19 @@ const makeStreamResponse = Effect.fnUntraced( }) }) }) - const params = yield* transformToolCallParams(options.tools, toolCall.name, parsedParams) + const params = yield* transformToolCallParams(options, toolCall.name, parsedParams, toolCodecs) parts.push({ type: "tool-params-end", id: toolCall.id }) parts.push({ type: "tool-call", id: toolCall.id, name: toolCall.name, params, - metadata: { openai: { ...makeItemIdMetadata(toolCall.id) } } + metadata: { + "openai-compat": { + ...makeItemIdMetadata(toolCall.id), + ...makeExtraContentMetadata(toolCall.extraContent) + } + } }) hasToolCalls = true } @@ -1232,7 +1157,7 @@ const makeStreamResponse = Effect.fnUntraced( usage: getUsage(usage), response: buildHttpResponseDetails(response), ...(normalizedServiceTier !== undefined - ? { metadata: { openai: { serviceTier: normalizedServiceTier } } } + ? { metadata: { "openai-compat": { serviceTier: normalizedServiceTier } } } : undefined) }) return parts @@ -1269,26 +1194,29 @@ const makeStreamResponse = Effect.fnUntraced( return parts } - const reasoningDelta = choice.delta?.reasoning ?? choice.delta?.reasoning_content - if (Predicate.isNotNullish(reasoningDelta) && reasoningDelta.length > 0) { + const reasoningField = Predicate.isNotNullish(choice.delta) + ? getResponseReasoningField(choice.delta) + : undefined + const reasoningDelta = reasoningField !== undefined ? choice.delta?.[reasoningField] : undefined + if (reasoningField !== undefined && Predicate.isNotNullish(reasoningDelta) && reasoningDelta.length > 0) { if (!reasoningStarted) { reasoningStarted = true parts.push({ type: "reasoning-start", id: reasoningId, - metadata: { openai: { ...makeItemIdMetadata(reasoningId) } } + metadata: { "openai-compat": { ...makeItemIdMetadata(reasoningId), reasoningField } } }) } parts.push({ type: "reasoning-delta", id: reasoningId, delta: reasoningDelta }) } - if (choice.delta?.content !== undefined && Predicate.isNotNull(choice.delta.content)) { + if (Predicate.isNotNullish(choice.delta?.content) && choice.delta.content.length > 0) { if (reasoningStarted) { reasoningStarted = false parts.push({ type: "reasoning-end", id: reasoningId, - metadata: { openai: { ...makeItemIdMetadata(reasoningId) } } + metadata: { "openai-compat": { ...makeItemIdMetadata(reasoningId) } } }) } @@ -1297,7 +1225,7 @@ const makeStreamResponse = Effect.fnUntraced( parts.push({ type: "text-start", id: textId, - metadata: { openai: { ...makeItemIdMetadata(textId) } } + metadata: { "openai-compat": { ...makeItemIdMetadata(textId) } } }) } parts.push({ type: "text-delta", id: textId, delta: choice.delta.content }) @@ -1319,12 +1247,16 @@ const makeStreamResponse = Effect.fnUntraced( activeToolCalls[toolIndex] = { id: toolId, name: toolName, - arguments: argumentsDelta + arguments: argumentsDelta, + extraContent: deltaTool.extra_content ?? undefined } parts.push({ type: "tool-params-start", id: toolId, name: toolName }) } else { activeToolCall.name = toolName activeToolCall.arguments = `${activeToolCall.arguments}${argumentsDelta}` + if (Predicate.isNotNullish(deltaTool.extra_content)) { + activeToolCall.extraContent = deltaTool.extra_content + } } if (argumentsDelta.length > 0) { @@ -1339,7 +1271,8 @@ const makeStreamResponse = Effect.fnUntraced( return parts })), - Stream.flattenIterable + Stream.filter(Arr.isArrayNonEmpty), + Stream.flattenArray ) } ) @@ -1399,7 +1332,7 @@ const annotateStreamResponse = (span: Span, part: Response.StreamPartEncoded) => }) } if (part.type === "finish") { - const serviceTier = (part.metadata as any)?.openai?.serviceTier as string | undefined + const serviceTier = (part.metadata as any)?.["openai-compat"]?.serviceTier as string | undefined addGenAIAnnotations(span, { response: { finishReasons: [part.reason] @@ -1442,26 +1375,27 @@ const tryJsonSchema = (schema: S, method: string) = catch: (error) => unsupportedSchemaError(error, method) }) -const tryToolJsonSchema = (tool: T, method: string) => - Effect.try({ - try: () => Tool.getJsonSchema(tool, { transformer: toCodecOpenAI }), - catch: (error) => unsupportedSchemaError(error, method) - }) +type ToolCodec = ReturnType["codec"] +type ToolCodecs = ReadonlyMap -const transformToolCallParams = Effect.fnUntraced(function*>( - tools: Tools, +const transformToolCallParams = Effect.fnUntraced(function*( + options: LanguageModel.ProviderOptions, toolName: string, - toolParams: unknown + toolParams: unknown, + toolCodecs: ToolCodecs ): Effect.fn.Return { - const tool = tools.find((tool) => tool.name === toolName) + const tool = options.tools.find((tool) => tool.name === toolName) if (Predicate.isUndefined(tool)) { + if (options.toolCallValidation === "deferred") { + return toolParams + } return yield* AiError.make({ module: "OpenAiLanguageModel", method: "makeResponse", reason: new AiError.ToolNotFoundError({ toolName, - availableTools: tools.map((tool) => tool.name) + availableTools: options.tools.map((tool) => tool.name) }) }) } @@ -1470,7 +1404,7 @@ const transformToolCallParams = Effect.fnUntraced(function* | undefined readonly toolChoice: OpenAiToolChoice | undefined + readonly toolCodecs: ToolCodecs }, AiError.AiError> { + const toolCodecs = new Map() + // Return immediately if no tools are in the toolkit if (options.tools.length === 0) { - return { tools: undefined, toolChoice: undefined } + return { tools: undefined, toolChoice: undefined, toolCodecs } } const tools: Array = [] @@ -1518,7 +1455,15 @@ const prepareTools = Effect.fnUntraced(function* + if (Tool.isDynamic(tool) && tool.jsonSchema !== undefined) { + parameters = tool.jsonSchema + } else { + const prepared = yield* tryCodecTransform(tool.parametersSchema, "prepareTools") + parameters = prepared.jsonSchema + // Reused to normalize this tool's calls in the response. + toolCodecs.set(tool, prepared.codec) + } tools.push({ type: "function", name: tool.name, @@ -1553,11 +1498,13 @@ const prepareTools = Effect.fnUntraced(function* { - const messages = toChatMessages(payload.input) +const toChatCompletionsRequest = ( + payload: CreateResponse, + messages: ReadonlyArray +): CreateResponseRequestJson => { const responseFormat = toChatResponseFormat(payload.text?.format) const tools = payload.tools !== undefined ? payload.tools.map(toChatTool).filter((tool): tool is NonNullable> => @@ -1719,112 +1666,6 @@ const toChatTool = ( return undefined } -const toChatMessages = ( - input: CreateResponse["input"] -): Array => { - if (Predicate.isUndefined(input)) { - return [] - } - - if (typeof input === "string") { - return [{ role: "user", content: input }] - } - - const messages: Array = [] - - for (const item of input) { - if (Predicate.hasProperty(item, "type") && item.type === "function_call") { - const previous = messages.at(-1) - const toolCall = toChatToolCall(item) - if (previous?.role === "assistant" && previous.tool_calls !== undefined) { - messages[messages.length - 1] = { - ...previous, - tool_calls: [...previous.tool_calls, toolCall] - } - } else { - messages.push({ - role: "assistant", - content: null, - tool_calls: [toolCall] - }) - } - } else { - messages.push(...toChatMessagesFromItem(item)) - } - } - - return messages -} - -const toChatMessagesFromItem = ( - item: InputItem -): Array => { - if (Predicate.hasProperty(item, "type") && item.type === "message") { - return [{ - role: item.role, - content: toAssistantChatMessageContent(item.content) - }] - } - - if (Predicate.hasProperty(item, "role")) { - return [{ - role: item.role, - content: toChatMessageContent(item.content) - }] - } - - switch (item.type) { - case "function_call": { - return [{ - role: "assistant", - content: null, - tool_calls: [toChatToolCall(item)] - }] - } - - case "function_call_output": { - return [{ - role: "tool", - tool_call_id: item.call_id, - content: stringifyJson(item.output) - }] - } - - default: { - return [] - } - } -} - -const toChatToolCall = ( - item: Extract -): ChatCompletionRequestToolCall => ({ - id: item.call_id, - type: "function", - function: { - name: item.name, - arguments: item.arguments - } -}) - -const toAssistantChatMessageContent = ( - content: ReadonlyArray<{ - readonly type: string - readonly [x: string]: unknown - }> -): string => { - let text = "" - for (const part of content) { - if (part.type === "output_text" && typeof part.text === "string") { - text += part.text - } - if (part.type === "refusal" && typeof part.refusal === "string") { - text += part.refusal - } - } - return text -} - const toChatMessageContent = ( content: string | ReadonlyArray ): string | ReadonlyArray => { @@ -1832,6 +1673,10 @@ const toChatMessageContent = ( return content } + if (content.length === 1 && content[0].type === "input_text") { + return content[0].text + } + const parts: Array = [] for (const part of content) { @@ -1882,11 +1727,6 @@ const toChatMessageContent = ( return parts } -const stringifyJson = (value: unknown): string => - typeof value === "string" - ? value - : JSON.stringify(value) - // ============================================================================= // Utilities // ============================================================================= @@ -1894,27 +1734,34 @@ const stringifyJson = (value: unknown): string => const isFileId = (data: string, config: typeof Config.Service): boolean => config.fileIdPrefixes != null && config.fileIdPrefixes.some((prefix) => data.startsWith(prefix)) -const getItemId = ( - part: - | Prompt.TextPart - | Prompt.ReasoningPart - | Prompt.ToolCallPart - | Prompt.ToolResultPart -): string | null => part.options.openai?.itemId ?? null -const getStatus = ( - part: - | Prompt.TextPart - | Prompt.ToolCallPart - | Prompt.ToolResultPart -): MessageStatus | null => part.options.openai?.status ?? null -const getEncryptedContent = ( - part: Prompt.ReasoningPart -): string | null => part.options.openai?.encryptedContent ?? null - -const getImageDetail = (part: Prompt.FilePart): ImageDetail => part.options.openai?.imageDetail ?? "auto" +const getExtraContent = ( + part: Prompt.ToolCallPart +): Schema.JsonObject | null => part.options["openai-compat"]?.extraContent ?? null + +/** + * The chat message field carrying reasoning text. Providers differ: DeepSeek, + * Kimi and GLM use `reasoning_content`, while Groq uses `reasoning` and + * rejects `reasoning_content` on request messages. + */ +type ReasoningField = "reasoning" | "reasoning_content" + +const getResponseReasoningField = (message: { + readonly reasoning?: string | null | undefined + readonly reasoning_content?: string | null | undefined +}): ReasoningField | undefined => + Predicate.isNotNullish(message.reasoning) + ? "reasoning" + : Predicate.isNotNullish(message.reasoning_content) + ? "reasoning_content" + : undefined + +const getImageDetail = (part: Prompt.FilePart): ImageDetail => part.options["openai-compat"]?.imageDetail ?? "auto" const makeItemIdMetadata = (itemId: string | undefined) => itemId !== undefined ? { itemId } : undefined +const makeExtraContentMetadata = (extraContent: Schema.JsonObject | undefined) => + extraContent !== undefined ? { extraContent } : undefined + const normalizeServiceTier = ( serviceTier: string | undefined ): "default" | "auto" | "flex" | "scale" | "priority" | null | undefined => { @@ -1951,54 +1798,6 @@ const prepareResponseFormat = Effect.fnUntraced(function*({ config, options }: { return { type: "text" } }) -interface ModelCapabilities { - readonly isReasoningModel: boolean - readonly systemMessageMode: "remove" | "system" | "developer" - readonly supportsFlexProcessing: boolean - readonly supportsPriorityProcessing: boolean - /** - * Allow temperature, topP, logProbs when reasoningEffort is none. - */ - readonly supportsNonReasoningParameters: boolean -} - -const getModelCapabilities = (modelId: string): ModelCapabilities => { - const supportsFlexProcessing = modelId.startsWith("o3") || - modelId.startsWith("o4-mini") || - (modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat")) - - const supportsPriorityProcessing = modelId.startsWith("gpt-4") || - modelId.startsWith("gpt-5-mini") || - (modelId.startsWith("gpt-5") && - !modelId.startsWith("gpt-5-nano") && - !modelId.startsWith("gpt-5-chat")) || - modelId.startsWith("o3") || - modelId.startsWith("o4-mini") - - // Use allowlist approach: only known reasoning models should use 'developer' role - // This prevents issues with fine-tuned models, third-party models, and custom models - const isReasoningModel = modelId.startsWith("o1") || - modelId.startsWith("o3") || - modelId.startsWith("o4-mini") || - modelId.startsWith("codex-mini") || - modelId.startsWith("computer-use-preview") || - (modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat")) - - // https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility - // GPT-5.1 and GPT-5.2 support temperature, topP, logProbs when reasoningEffort is none - const supportsNonReasoningParameters = modelId.startsWith("gpt-5.1") || modelId.startsWith("gpt-5.2") - - const systemMessageMode = isReasoningModel ? "developer" : "system" - - return { - supportsFlexProcessing, - supportsPriorityProcessing, - isReasoningModel, - systemMessageMode, - supportsNonReasoningParameters - } -} - const getUsage = (usage: CreateResponse200["usage"]): Response.Usage => { if (Predicate.isNullish(usage)) { return { diff --git a/repos/effect/packages/ai/openai-compat/src/internal/errors.ts b/repos/effect/packages/ai/openai-compat/src/internal/errors.ts index 4fef55b9d2..b80a6b413b 100644 --- a/repos/effect/packages/ai/openai-compat/src/internal/errors.ts +++ b/repos/effect/packages/ai/openai-compat/src/internal/errors.ts @@ -230,7 +230,7 @@ export const mapStatusCodeToReason = ({ status, headers, message, metadata, http case 400: return new AiError.InvalidRequestError({ description: errorDescription, - metadata: { openai: metadata }, + metadata: { "openai-compat": metadata }, http }) case 401: @@ -250,14 +250,14 @@ export const mapStatusCodeToReason = ({ status, headers, message, metadata, http case 404: return new AiError.InvalidRequestError({ description: errorDescription, - metadata: { openai: metadata }, + metadata: { "openai-compat": metadata }, http }) case 409: case 422: return new AiError.InvalidRequestError({ description: errorDescription, - metadata: { openai: metadata }, + metadata: { "openai-compat": metadata }, http }) case 429: { @@ -268,7 +268,7 @@ export const mapStatusCodeToReason = ({ status, headers, message, metadata, http metadata.errorType?.includes("exhausted") ) { return new AiError.QuotaExhaustedError({ - metadata: { openai: metadata }, + metadata: { "openai-compat": metadata }, http }) } @@ -276,7 +276,7 @@ export const mapStatusCodeToReason = ({ status, headers, message, metadata, http return new AiError.RateLimitError({ retryAfter, metadata: { - openai: { + "openai-compat": { ...metadata, ...rateLimitMetadata } diff --git a/repos/effect/packages/ai/openai-compat/test/OpenAiClient.test.ts b/repos/effect/packages/ai/openai-compat/test/OpenAiClient.test.ts index ac3e031b83..8cbd49581c 100644 --- a/repos/effect/packages/ai/openai-compat/test/OpenAiClient.test.ts +++ b/repos/effect/packages/ai/openai-compat/test/OpenAiClient.test.ts @@ -184,7 +184,7 @@ describe("OpenAiClient", () => { ] })))) - it.effect("drops invalid JSON and continues streaming", () => + it.effect("drops invalid JSON and streams valid events until [DONE]", () => Effect.gen(function*() { const client = yield* OpenAiClient.OpenAiClient @@ -215,7 +215,8 @@ describe("OpenAiClient", () => { }] }) }\n\n`, - "data: [DONE]\n\n" + "data: [DONE]\n\n", + "data: {\"ignored\":\"after completion\"}\n\n" ].join("") })))) diff --git a/repos/effect/packages/ai/openai-compat/test/OpenAiLanguageModel.test.ts b/repos/effect/packages/ai/openai-compat/test/OpenAiLanguageModel.test.ts index 43a2dc4ae7..c1ae663ba7 100644 --- a/repos/effect/packages/ai/openai-compat/test/OpenAiLanguageModel.test.ts +++ b/repos/effect/packages/ai/openai-compat/test/OpenAiLanguageModel.test.ts @@ -5,8 +5,102 @@ import { type AiError, LanguageModel, Prompt, Tool, Toolkit } from "effect/ai" import { HttpClient, type HttpClientError, type HttpClientRequest, HttpClientResponse } from "effect/http" describe("OpenAiLanguageModel", () => { + for (const mode of ["complete", "stream"] as const) { + it.effect(`prepares selected tool codecs once per ${mode} request and normalizes repeated calls`, () => + Effect.gen(function*() { + let conversions = 0 + const Env = Schema.Record(Schema.String, Schema.String).check( + Schema.makeFilter(() => true, { + representation: { id: "test/compat/toolCodec", payload: null }, + toJsonSchema: () => { + conversions++ + return { minItems: 1 } + } + }) + ) + const ReadEnv = Tool.make("ReadEnv", { parameters: Schema.Struct({ env: Env }) }) + const Unselected = Tool.make("Unselected", { + parameters: Schema.Struct({ opaque: Schema.declare((input): input is string => typeof input === "string") }) + }) + const toolkit = Toolkit.make(ReadEnv, Unselected) + const toolkitLayer = toolkit.toLayer({ + ReadEnv: () => Effect.void, + Unselected: () => Effect.void + }) + const calls = ["call_1", "call_2"].map((id) => ({ + id, + type: "function" as const, + function: { name: "ReadEnv", arguments: JSON.stringify({ env: [{ 0: "PATH", 1: "/usr/bin" }] }) } + })) + const layer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + makeHttpClient((request) => + Effect.gen(function*() { + const body = yield* getRequestBody(request) + assert.deepStrictEqual(body.tools.map((tool: any) => tool.function.name), ["ReadEnv"]) + assert.strictEqual(body.tools[0].function.parameters.properties.env.type, "array") + return mode === "complete" + ? jsonResponse( + request, + makeChatCompletion({ + choices: [{ + index: 0, + finish_reason: "tool_calls", + message: { role: "assistant", content: null, tool_calls: calls } + }] + }) + ) + : sseResponse(request, [{ + id: "chatcmpl_env", + object: "chat.completion.chunk", + model: "gpt-4o-mini", + created: 1, + choices: [{ + index: 0, + delta: { tool_calls: calls.map((call, index) => ({ ...call, index })) }, + finish_reason: "tool_calls" + }] + }, "[DONE]"]) + }) + ) + )) + ) + for (let request = 1; request <= 2; request++) { + const options = { + prompt: "read the environment", + toolkit, + toolChoice: { oneOf: ["ReadEnv"] as Array<"ReadEnv"> }, + disableToolCallResolution: true + } + const calls = yield* (mode === "complete" + ? LanguageModel.generateText(options).pipe( + Effect.map((result) => result.toolCalls.map((part) => ({ id: part.id, params: part.params }))) + ) + : LanguageModel.streamText(options).pipe( + Stream.runCollect, + Effect.map((parts) => + parts.filter((part) => part.type === "tool-call").map((part) => ({ id: part.id, params: part.params })) + ) + )).pipe( + Effect.provide(OpenAiLanguageModel.model("gpt-4o-mini")), + Effect.provide(toolkitLayer), + Effect.provide(layer) + ) + assert.deepStrictEqual( + calls, + [ + { id: "call_1", params: { env: { PATH: "/usr/bin" } } }, + { id: "call_2", params: { env: { PATH: "/usr/bin" } } } + ] + ) + assert.strictEqual(conversions, request) + } + })) + } + describe("generateText", () => { - it.effect("sends model in request and decodes text output", () => + it.effect("serializes text-only user messages and decodes text output", () => Effect.gen(function*() { let capturedRequest: HttpClientRequest.HttpClientRequest | undefined @@ -32,7 +126,15 @@ describe("OpenAiLanguageModel", () => { )) ) - const result = yield* LanguageModel.generateText({ prompt: "hello" }).pipe( + const result = yield* LanguageModel.generateText({ + prompt: Prompt.make([ + { role: "user", content: [Prompt.textPart({ text: "hello" })] }, + { role: "user", content: [Prompt.textPart({ text: "" })] }, + { role: "user", content: [Prompt.textPart({ text: " Hello, 世界!\nGoodbye. " })] }, + { role: "user", content: [Prompt.textPart({ text: "first" }), Prompt.textPart({ text: "second" })] }, + { role: "user", content: [] } + ]) + }).pipe( Effect.provide(OpenAiLanguageModel.model("gpt-4o-mini")), Effect.provide(layer) ) @@ -45,7 +147,13 @@ describe("OpenAiLanguageModel", () => { const requestBody = yield* getRequestBody(capturedRequest) assert.strictEqual(requestBody.model, "gpt-4o-mini") - assert.strictEqual(requestBody.messages[0]?.content, "hello") + assert.deepStrictEqual(requestBody.messages, [ + { role: "user", content: "hello" }, + { role: "user", content: "" }, + { role: "user", content: " Hello, 世界!\nGoodbye. " }, + { role: "user", content: "first\nsecond" }, + { role: "user", content: "" } + ]) })) it.effect("routes invalid tool call params through failureMode: return without failing the effect", () => @@ -633,6 +741,53 @@ describe("OpenAiLanguageModel", () => { ]) })) + it.effect("echoes tool call extra_content in follow-up requests", () => + Effect.gen(function*() { + const extraContent = { google: { thought_signature: "signature-1" } } + const requests: Array = [] + + const layer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + makeHttpClient((request) => { + requests.push(request) + return Effect.succeed(jsonResponse( + request, + requests.length > 1 ? makeChatCompletion() : makeChatCompletion({ + choices: [{ + index: 0, + finish_reason: "tool_calls", + message: { + role: "assistant", + content: null, + tool_calls: [{ + id: "call_1", + type: "function", + extra_content: extraContent, + function: { name: "TestTool", arguments: JSON.stringify({ input: "hello" }) } + }] + } + }] + }) + )) + }) + )) + ) + + const generate = (prompt: Prompt.Prompt) => + LanguageModel.generateText({ prompt, toolkit: TestToolkit, disableToolCallResolution: true }).pipe( + Effect.provide(OpenAiLanguageModel.model("gpt-4o-mini")), + Effect.provide(layer) + ) + + const prompt = Prompt.make("use the tool") + const first = yield* generate(prompt) + yield* generate(Prompt.concat(prompt, Prompt.fromResponseParts(first.content))) + + const followUpBody = yield* getRequestBody(requests[1]) + assert.deepStrictEqual(followUpBody.messages[1].tool_calls[0].extra_content, extraContent) + })) + it.effect("converts dynamic tools to function type", () => Effect.gen(function*() { let capturedRequest: HttpClientRequest.HttpClientRequest | undefined @@ -918,6 +1073,168 @@ describe("OpenAiLanguageModel", () => { assert.strictEqual(reasoning.text, "I should greet the user.") assert.strictEqual(result.text, "Hello!") })) + + it.effect("returns invalid and undeclared tool calls when tool call validation is deferred", () => + Effect.gen(function*() { + const client = makeHttpClient((request) => + Effect.succeed(jsonResponse( + request, + makeChatCompletion({ + choices: [{ + index: 0, + finish_reason: "tool_calls", + message: { + role: "assistant", + content: null, + tool_calls: [ + { id: "call_1", type: "function", function: { name: "TestTool", arguments: "{\"input\":42}" } }, + { id: "call_2", type: "function", function: { name: "Write", arguments: "{\"path\":\"a\"}" } } + ] + } + }] + }) + )) + ) + + const result = yield* LanguageModel.generateText({ + prompt: "use the tools", + toolkit: TestToolkit, + disableToolCallResolution: true, + toolCallValidation: "deferred" + }).pipe( + Effect.provide(OpenAiLanguageModel.model("gpt-4o-mini")), + Effect.provide(TestToolkitLayer), + Effect.provide(OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") })), + Effect.provideService(HttpClient.HttpClient, client) + ) + + assert.deepStrictEqual(result.toolCalls.map(({ name, params }) => ({ name, params })), [ + { name: "TestTool", params: { input: 42 } }, + { name: "Write", params: { path: "a" } } + ]) + })) + + it.effect("replays reasoning alongside assistant text and tool calls", () => + Effect.gen(function*() { + let capturedRequest: HttpClientRequest.HttpClientRequest | undefined + + const layer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + makeHttpClient((request) => { + capturedRequest = request + return Effect.succeed(jsonResponse(request, makeChatCompletion())) + }) + )) + ) + + const prompt = Prompt.make([ + { role: "user", content: "What is in a.txt?" }, + { + role: "assistant", + content: [ + { type: "reasoning", text: "The user wants a.txt; I should read it." }, + { type: "text", text: "Let me read it." }, + { type: "tool-call", id: "call_1", name: "TestTool", params: { input: "a.txt" } } + ] + }, + { + role: "tool", + content: [{ type: "tool-result", id: "call_1", name: "TestTool", isFailure: false, result: "hello" }] + } + ]) + + yield* LanguageModel.generateText({ prompt, toolkit: TestToolkit, disableToolCallResolution: true }).pipe( + Effect.provide(OpenAiLanguageModel.model("deepseek-reasoner")), + Effect.provide(layer) + ) + + assert.isDefined(capturedRequest) + if (capturedRequest === undefined) { + return + } + + const requestBody = yield* getRequestBody(capturedRequest) + assert.deepStrictEqual(requestBody.messages, [ + { role: "user", content: "What is in a.txt?" }, + { + role: "assistant", + content: "Let me read it.", + reasoning_content: "The user wants a.txt; I should read it.", + tool_calls: [{ + id: "call_1", + type: "function", + function: { name: "TestTool", arguments: JSON.stringify({ input: "a.txt" }) } + }] + }, + { role: "tool", tool_call_id: "call_1", content: "hello" } + ]) + })) + + it.effect("replays decoded Groq reasoning under its original field alongside text and tool calls", () => + Effect.gen(function*() { + const requests: Array = [] + + const layer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + makeHttpClient((request) => { + requests.push(request) + return Effect.succeed(jsonResponse( + request, + requests.length > 1 ? makeChatCompletion() : makeChatCompletion({ + choices: [{ + index: 0, + finish_reason: "tool_calls", + message: { + role: "assistant", + reasoning: "Need the file", + content: "Let me read it.", + tool_calls: [{ + id: "call_1", + type: "function", + function: { name: "TestTool", arguments: JSON.stringify({ input: "a.txt" }) } + }] + } + }] + }) + )) + }) + )) + ) + + const generate = (prompt: Prompt.Prompt) => + LanguageModel.generateText({ prompt, toolkit: TestToolkit, disableToolCallResolution: true }).pipe( + Effect.provide(OpenAiLanguageModel.model("openai/gpt-oss-120b")), + Effect.provide(layer) + ) + + const prompt = Prompt.make("What is in a.txt?") + const first = yield* generate(prompt) + yield* generate(Prompt.concat( + Prompt.concat(prompt, Prompt.fromResponseParts(first.content)), + Prompt.make([{ + role: "tool", + content: [{ type: "tool-result", id: "call_1", name: "TestTool", isFailure: false, result: "hello" }] + }]) + )) + + const followUpBody = yield* getRequestBody(requests[1]) + assert.deepStrictEqual(followUpBody.messages, [ + { role: "user", content: "What is in a.txt?" }, + { + role: "assistant", + content: "Let me read it.", + reasoning: "Need the file", + tool_calls: [{ + id: "call_1", + type: "function", + function: { name: "TestTool", arguments: JSON.stringify({ input: "a.txt" }) } + }] + }, + { role: "tool", tool_call_id: "call_1", content: "hello" } + ]) + })) }) describe("generateObject", () => { @@ -1025,6 +1342,88 @@ describe("OpenAiLanguageModel", () => { }) describe("streamText", () => { + it.effect("replays streamed assistant text and tool calls with store enabled", () => + Effect.gen(function*() { + const requests: Array = [] + + const layer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + makeHttpClient((request) => { + requests.push(request) + return Effect.succeed( + requests.length > 1 + ? jsonResponse(request, makeChatCompletion()) + : sseResponse(request, [ + { + id: "chatcmpl_store_1", + object: "chat.completion.chunk", + model: "gpt-4o-mini", + created: 1, + choices: [{ + index: 0, + delta: { + content: "Let me read it.", + tool_calls: [{ + index: 0, + id: "call_1", + type: "function", + function: { name: "TestTool", arguments: JSON.stringify({ input: "a.txt" }) } + }] + }, + finish_reason: "tool_calls" + }] + }, + "[DONE]" + ]) + ) + }) + )) + ) + + const model = OpenAiLanguageModel.model("gpt-4o-mini", { store: true }) + const prompt = Prompt.make("What is in a.txt?") + const parts = yield* LanguageModel.streamText({ + prompt, + toolkit: TestToolkit, + disableToolCallResolution: true + }).pipe( + Stream.runCollect, + Effect.provide(model), + Effect.provide(layer) + ) + + yield* LanguageModel.generateText({ + prompt: Prompt.concat( + Prompt.concat(prompt, Prompt.fromResponseParts(parts)), + Prompt.make([{ + role: "tool", + content: [{ type: "tool-result", id: "call_1", name: "TestTool", isFailure: false, result: "hello" }] + }]) + ), + toolkit: TestToolkit, + disableToolCallResolution: true + }).pipe( + Effect.provide(model), + Effect.provide(layer) + ) + + const followUpBody = yield* getRequestBody(requests[1]) + assert.deepStrictEqual(followUpBody.messages, [ + { role: "user", content: "What is in a.txt?" }, + { + role: "assistant", + content: "Let me read it.", + tool_calls: [{ + id: "call_1", + type: "function", + function: { name: "TestTool", arguments: JSON.stringify({ input: "a.txt" }) } + }] + }, + { role: "tool", tool_call_id: "call_1", content: "hello" } + ]) + })) + it.effect("handles chat completion stream chunks", () => Effect.gen(function*() { const layer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( @@ -1066,6 +1465,51 @@ describe("OpenAiLanguageModel", () => { } })) + it.effect("streams undeclared tool calls when tool call validation is deferred", () => + Effect.gen(function*() { + const client = makeHttpClient((request) => + Effect.succeed(sseResponse(request, [ + { + id: "chatcmpl_undeclared", + object: "chat.completion.chunk", + model: "gpt-4o-mini", + created: 1, + choices: [{ + index: 0, + delta: { + tool_calls: [{ + index: 0, + id: "call_1", + type: "function", + function: { name: "Write", arguments: JSON.stringify({ path: "a" }) } + }] + }, + finish_reason: "tool_calls" + }] + }, + "[DONE]" + ])) + ) + + const parts = yield* LanguageModel.streamText({ + prompt: "use the tools", + toolkit: TestToolkit, + disableToolCallResolution: true, + toolCallValidation: "deferred" + }).pipe( + Stream.runCollect, + Effect.provide(OpenAiLanguageModel.model("gpt-4o-mini")), + Effect.provide(TestToolkitLayer), + Effect.provide(OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") })), + Effect.provideService(HttpClient.HttpClient, client) + ) + + assert.deepStrictEqual( + parts.filter((part) => part.type === "tool-call").map(({ name, params }) => ({ name, params })), + [{ name: "Write", params: { path: "a" } }] + ) + })) + it.effect("emits text when streamed tool_calls is null", () => Effect.gen(function*() { const layer = OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( @@ -1110,6 +1554,7 @@ describe("OpenAiLanguageModel", () => { it.effect("preserves streamed text and tool args with nullable delta fields", () => Effect.gen(function*() { + const extraContent = { google: { thought_signature: "signature-1" } } const chunk = (delta: Record) => ({ id: "chatcmpl_nullable_delta_fields", object: "chat.completion.chunk", @@ -1129,11 +1574,17 @@ describe("OpenAiLanguageModel", () => { index: 0, id: "call_1", type: "function", + extra_content: extraContent, function: { name: "TestTool", arguments: "" } }] }), chunk({ - tool_calls: [{ index: 0, id: null, function: { name: null, arguments: "{\"in" } }] + tool_calls: [{ + index: 0, + id: null, + extra_content: null, + function: { name: null, arguments: "{\"in" } + }] }), chunk({ tool_calls: [{ index: 0, id: null, function: { name: null, arguments: "put\":\"hel" } }] @@ -1179,6 +1630,7 @@ describe("OpenAiLanguageModel", () => { } assert.strictEqual(toolCall.id, "call_1") assert.deepStrictEqual(toolCall.params, { input: "hello" }) + assert.deepStrictEqual(toolCall.metadata["openai-compat"] as unknown, { itemId: "call_1", extraContent }) })) it.effect("decodes streamed tool call params with the OpenAI codec", () => @@ -1294,7 +1746,7 @@ describe("OpenAiLanguageModel", () => { params: { action: localShellAction }, providerExecuted: false, options: { - openai: { + "openai-compat": { itemId: "ls_call_1" } } @@ -1712,10 +2164,11 @@ describe("OpenAiLanguageModel", () => { HttpClient.HttpClient, makeHttpClient((request) => Effect.succeed(sseResponse(request, [ - chunk({ reasoning: "Let me think" }), - chunk({ reasoning: " about this." }), + chunk({ content: "", reasoning: "Let me think" }), + chunk({ content: "", reasoning: " about this." }), chunk({ content: "Hello" }), - chunk({ content: " there" }, "stop"), + chunk({ content: " there" }), + chunk({ content: "" }, "stop"), "[DONE]" ])) ) diff --git a/repos/effect/packages/ai/openai/CHANGELOG.md b/repos/effect/packages/ai/openai/CHANGELOG.md index e7637f1745..1ed5bd3f26 100644 --- a/repos/effect/packages/ai/openai/CHANGELOG.md +++ b/repos/effect/packages/ai/openai/CHANGELOG.md @@ -1,5 +1,52 @@ # @effect/ai-openai +## 4.0.5 + +### Patch Changes + +- [#9140](https://github.com/Effect-TS/effect/pull/9140) [`91f4c74`](https://github.com/Effect-TS/effect/commit/91f4c74fe8f41a9897927e9bc2c4b814924c85e0) Thanks @tim-smart! - Add `OpenAiDecisionModel`, a `DecisionModel` backed by OpenAI's Decisions API (`gpt-6-luna`), and `OpenAiClient.createDecisions`. Refused decisions fail the call with `AiError.ContentPolicyError`, and remote image URLs fail with `AiError.InvalidUserInputError`. + +- [#9097](https://github.com/Effect-TS/effect/pull/9097) [`68caf1d`](https://github.com/Effect-TS/effect/commit/68caf1d642e882d2882624d9227b7d6414a1065f) Thanks @adam-r-kowalski! - Stop Responses streams at the `data: [DONE]` sentinel sent by some OpenAI-compatible servers instead of failing to decode it. + +- [#9115](https://github.com/Effect-TS/effect/pull/9115) [`5d018e1`](https://github.com/Effect-TS/effect/commit/5d018e1fb171d9a2e8658305ee6cb232d67b0ae5) Thanks @danieljvdm! - Preserve the `ultrafast` service tier in finish metadata. + +- [#9124](https://github.com/Effect-TS/effect/pull/9124) [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e) Thanks @jem-computer! - Support structured decision instructions, descriptions, and score legends in TypeSafe, Cloudflare, and OpenRouter. `Decision.rate` accepts labeled descriptions; `Rate.criteria` entries are now `{ label, description }` objects instead of strings. + +- [#9100](https://github.com/Effect-TS/effect/pull/9100) [`51c079b`](https://github.com/Effect-TS/effect/commit/51c079b90b6d4453601efc2d0402cdfc6b7533f2) Thanks @tim-smart! - Accept omitted `pattern` fields in OpenAI `find_in_page` web-search actions so streams do not fail validation. The public `WebSearchActionFind.pattern` property is now optional (`string | undefined` when read); explicit null and non-string values remain invalid. +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- [#9008](https://github.com/Effect-TS/effect/pull/9008) [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d) Thanks @effect-bot! - Add `toolCallValidation: "deferred"` for callers using `disableToolCallResolution: true`. Model-generated tool calls return with `unknown` parameters, including invalid parameters and undeclared tool names, even without a toolkit. Supported by the Anthropic, OpenAI, and OpenAI-compatible providers. Strict validation remains the default; provider-executed calls remain validated. + +- [#9067](https://github.com/Effect-TS/effect/pull/9067) [`984b4ab`](https://github.com/Effect-TS/effect/commit/984b4abfb2a804659e63b72f345ead0c1e511caa) Thanks @tim-smart! - Regenerate the OpenAI client from a pinned canonical specification. Fix composed schemas that collapsed to `Schema.Never` and preserve keys in maps and free-form objects. + + Public type changes in `Generated`: + + - Remove Realtime WebSocket event exports no longer referenced by HTTP operations. Rename multipart request bodies to `*Multipart` or `*FormData`. + - Require fields specified upstream, including `CreateImageRequest.model`, `AdminApiKey.expires_at`, `ProjectApiKey.owner_project_access`, `AssignedRoleDetails.assignment_sources` and `VoiceResource.type`. + - Type maps and free-form objects as records instead of `{}`. `Metadata` is now `{ readonly [x: string]: string } | null`. + - Make `FineTuningJob` a union of `dpo`, `reinforcement` and `hyperparameters` variants. Use `WebSearchCallStatus` for `WebSearchToolCall.status`. + +- [#9075](https://github.com/Effect-TS/effect/pull/9075) [`de38e53`](https://github.com/Effect-TS/effect/commit/de38e53651c8f6b36573ee038d0292e199e231b7) Thanks @tim-smart! - Accept OpenAI web search `find_in_page` actions without a URL while still requiring the search pattern. +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- [`43bb382`](https://github.com/Effect-TS/effect/commit/43bb382f68a62d759fca7b26f14a82bcaa49be0d) Thanks @tim-smart! - Preserve explicit `include` values and default unknown OpenAI models to reasoning. + + - Merge explicit and automatic includes without duplicates. + - Treat models as reasoning except for `gpt-3*`, `gpt-4*`, `chatgpt-*`, `chat-latest`, and `gpt--chat*`. Fine-tunes follow their base model. Reasoning models use the `developer` role and request encrypted reasoning when item references are disabled or WebSockets are used. OpenAI returns encrypted reasoning by default with `store: false`; the include is retained for compatibility. + - Add `reasoningModel` to override detection. Use `reasoningModel: false` for incompatible custom deployments to select the `system` role and disable the automatic encrypted reasoning include. Explicit includes are still preserved. +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/ai/openai/codegen.yaml b/repos/effect/packages/ai/openai/codegen.yaml index 4c9ed89bfc..c8265791b9 100644 --- a/repos/effect/packages/ai/openai/codegen.yaml +++ b/repos/effect/packages/ai/openai/codegen.yaml @@ -1,5 +1,7 @@ # yaml-language-server: $schema=../../tools/ai-codegen/codegen.schema.json -spec: https://app.stainless.com/api/spec/documented/openai/openapi.documented.yml +# To update, pin the latest openai/openai-openapi commit and regenerate from the repo root: +# nix develop -c node packages/tools/ai-codegen/src/bin.ts generate --provider openai +spec: https://raw.githubusercontent.com/openai/openai-openapi/e95c0fe615f45a19e8878af923a729948445a6bd/openapi.yaml output: src/Generated.ts name: OpenAiClient header: | @@ -8,20 +10,20 @@ header: | * @since 1.0.0 */ patches: - - '[{"op":"replace","path":"/openapi","value":"3.0.0"}]' - - '[{"op":"add","path":"/components/schemas/ModelResponseProperties/properties/user/nullable","value":true}]' - - '[{"op":"add","path":"/components/schemas/ModelResponseProperties/properties/safety_identifier/nullable","value":true}]' - - '[{"op":"add","path":"/components/schemas/ModelResponseProperties/properties/prompt_cache_key/nullable","value":true}]' - - '[{"op":"add","path":"/components/schemas/Response/allOf/2/properties/usage/nullable","value":true}]' - - '[{"op":"remove","path":"/components/schemas/ResponseFunctionCallArgumentsDoneEvent/required/2"}]' - - '[{"op":"add","path":"/components/schemas/ModelResponseProperties/properties/prompt_cache_retention/anyOf/0/enum/1","value":"in_memory"}]' + # Preserve the optional `name` field removed upstream. + - '[{"op":"add","path":"/components/schemas/ResponseFunctionCallArgumentsDoneEvent/properties/name","value":{"type":"string","description":"The name of the function that was called."}}]' + # Keep cache_write_tokens and access_programs optional for older and OpenAI-compatible servers. + - '[{"op":"replace","path":"/components/schemas/ResponseUsage/properties/input_tokens_details/required","value":["cached_tokens"]}]' + - '[{"op":"replace","path":"/components/schemas/Response/allOf/2/required","value":["id","object","created_at","error","incomplete_details","instructions","model","tools","output","parallel_tool_calls","metadata","tool_choice","temperature","top_p"]}]' + # Also accept the legacy `in-memory` spelling - '[{"op":"add","path":"/components/schemas/PromptCacheRetentionEnum/enum/1","value":"in-memory"}]' - '[{"op":"replace","path":"/components/schemas/OpenAIFile/properties/expires_at","value":{"anyOf":[{"type":"integer","format":"unixtime","description":"The Unix timestamp (in seconds) for when the file will expire."},{"type":"null"}]}}]' - - '[{"op":"add","path":"/components/schemas/OpenAIFile/properties/status_details/nullable","value":true}]' + - '[{"op":"replace","path":"/components/schemas/OpenAIFile/properties/status_details/type","value":["string","null"]}]' # Remove when the upstream schema includes named API sources: https://github.com/openai/openai-openapi/issues/573 - '[{"op":"replace","path":"/components/schemas/WebSearchActionSearch/properties/sources/items","value":{"anyOf":[{"type":"object","title":"Web search source","description":"A source used in the search.\n","properties":{"type":{"type":"string","enum":["url"],"description":"The type of source. Always `url`.\n","x-stainless-const":true},"url":{"type":"string","format":"uri","description":"The URL of the source.\n"}},"required":["type","url"]},{"type":"object","title":"Web search API source","description":"An API source used in the search.\n","properties":{"type":{"type":"string","enum":["api"],"description":"The type of source. Always `api`.\n","x-stainless-const":true},"name":{"type":"string","description":"The name of the API source, such as `oai-weather`, `oai-sports`, or `oai-finance`.\n"}},"required":["type","name"]}]}}]' - # OpenAI may omit action (https://github.com/openai/openai-openapi/issues/572) or report incomplete. - - '[{"op":"replace","path":"/components/schemas/WebSearchToolCall/required","value":["id","type","status"]},{"op":"replace","path":"/components/schemas/WebSearchToolCall/properties/status","value":{"type":"string","enum":["in_progress","searching","completed","failed","incomplete"],"description":"The status of the web search tool call.\n"}}]' + # OpenAI may omit the find-in-page URL: https://github.com/openai/openai-openapi/issues/571 + # Also tolerate omitted patterns without substituting a value. + - '[{"op":"replace","path":"/components/schemas/WebSearchActionFind/required","value":["type"]}]' # Add missing keepalive stream event support - '[{"op":"add","path":"/components/schemas/ResponseKeepAliveEvent","value":{"type":"object","title":"Keep alive","description":"A keepalive event emitted during long-running response streams.","properties":{"type":{"type":"string","enum":["keepalive"],"description":"The type of the keepalive event. Always `keepalive`.","default":"keepalive","x-stainless-const":true},"sequence_number":{"type":"integer","description":"The sequence number of this keepalive event."}},"required":["type","sequence_number"]}}]' - '[{"op":"add","path":"/components/schemas/ResponseStreamEvent/anyOf/-","value":{"$ref":"#/components/schemas/ResponseKeepAliveEvent"}}]' diff --git a/repos/effect/packages/ai/openai/package.json b/repos/effect/packages/ai/openai/package.json index c041c153bc..f9a91a928c 100644 --- a/repos/effect/packages/ai/openai/package.json +++ b/repos/effect/packages/ai/openai/package.json @@ -1,6 +1,6 @@ { "name": "@effect/ai-openai", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "An OpenAI provider integration for Effect AI SDK", diff --git a/repos/effect/packages/ai/openai/src/Generated.ts b/repos/effect/packages/ai/openai/src/Generated.ts index 4d5918bba1..fc81ebddd5 100644 --- a/repos/effect/packages/ai/openai/src/Generated.ts +++ b/repos/effect/packages/ai/openai/src/Generated.ts @@ -13,161 +13,94 @@ import * as HttpClientResponse from "effect/http/HttpClientResponse" import type { SchemaError } from "effect/Schema" import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" +// recursive declarations +export type CompoundFilter = { + readonly "type": "and" | "or" + readonly "filters": ReadonlyArray +} +export const CompoundFilter = Schema.suspend((): Schema.Codec => __recursive_CompoundFilter) +export type BetaCompoundFilter = { + readonly "type": "and" | "or" + readonly "filters": ReadonlyArray +} +export const BetaCompoundFilter = Schema.suspend((): Schema.Codec => __recursive_BetaCompoundFilter) // non-recursive definitions -export type AddUploadPartRequest = { readonly "data": string } -export const AddUploadPartRequest = Schema.Struct({ - "data": Schema.String.annotate({ "description": "The chunk of bytes for this Part.\n", "format": "binary" }) +export type AssistantToolsCode = { readonly "type": "code_interpreter" } +export const AssistantToolsCode = Schema.Struct({ + "type": Schema.Literal("code_interpreter").annotate({ + "description": "The type of tool being defined: `code_interpreter`" + }) +}).annotate({ "title": "Code interpreter tool", "identifier": "AssistantToolsCode" }) +export type FileSearchRanker = "auto" | "default_2024_08_21" +export const FileSearchRanker = Schema.Literals(["auto", "default_2024_08_21"]).annotate({ + "description": "The ranker to use for the file search. If not specified will use the `auto` ranker.", + "identifier": "FileSearchRanker" }) -export type AdminApiKey = { - readonly "object": "organization.admin_api_key" - readonly "id": string - readonly "name"?: string | null - readonly "redacted_value": string - readonly "created_at": number - readonly "last_used_at"?: number | null - readonly "owner": { - readonly "type"?: string - readonly "object"?: string - readonly "id"?: string - readonly "name"?: string - readonly "created_at"?: number - readonly "role"?: string - } -} -export const AdminApiKey = Schema.Struct({ - "object": Schema.Literal("organization.admin_api_key").annotate({ - "description": "The object type, which is always `organization.admin_api_key`" - }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the API key" }) - ), - "redacted_value": Schema.String.annotate({ "description": "The redacted value of the API key" }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the API key was created", - "format": "unixtime" - }).check(Schema.isInt()), - "last_used_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the API key was last used", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "owner": Schema.Struct({ - "type": Schema.optionalKey(Schema.String.annotate({ "description": "Always `user`" })), - "object": Schema.optionalKey( - Schema.String.annotate({ "description": "The object type, which is always organization.user" }) - ), - "id": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }) - ), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the user" })), - "created_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the user was created", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "role": Schema.optionalKey(Schema.String.annotate({ "description": "Always `owner`" })) +export type FunctionParameters = { readonly [x: string]: Schema.Json } +export const FunctionParameters = Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) + .annotate({ + "description": + "The parameters the functions accepts, described as a JSON Schema object. See the [guide](https://developers.openai.com/api/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format.\n\nOmitting `parameters` defines a function with an empty parameter list.", + "identifier": "FunctionParameters" }) -}).annotate({ "description": "Represents an individual Admin API key in an org." }) -export type AdminApiKeyCreateResponse = { - readonly "object": "organization.admin_api_key" - readonly "id": string - readonly "name"?: string | null - readonly "redacted_value": string - readonly "created_at": number - readonly "last_used_at"?: number | null - readonly "owner": { - readonly "type"?: string - readonly "object"?: string - readonly "id"?: string - readonly "name"?: string - readonly "created_at"?: number - readonly "role"?: string - } - readonly "value": string -} -export const AdminApiKeyCreateResponse = Schema.Struct({ - "object": Schema.Literal("organization.admin_api_key").annotate({ - "description": "The object type, which is always `organization.admin_api_key`" - }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the API key" }) - ), - "redacted_value": Schema.String.annotate({ "description": "The redacted value of the API key" }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the API key was created", - "format": "unixtime" - }).check(Schema.isInt()), - "last_used_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the API key was last used", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "owner": Schema.Struct({ - "type": Schema.optionalKey(Schema.String.annotate({ "description": "Always `user`" })), - "object": Schema.optionalKey( - Schema.String.annotate({ "description": "The object type, which is always organization.user" }) - ), - "id": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }) - ), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the user" })), - "created_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the user was created", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "role": Schema.optionalKey(Schema.String.annotate({ "description": "Always `owner`" })) +export type Metadata = { readonly [x: string]: string } | null +export const Metadata = Schema.Union([ + Schema.Record(Schema.String, Schema.String).annotate({ + "description": + "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" }), - "value": Schema.String.annotate({ "description": "The value of the API key. Only shown on create." }) + Schema.Null +]).annotate({ "identifier": "Metadata" }) +export type ResponseFormatText = { readonly "type": "text" } +export const ResponseFormatText = Schema.Struct({ + "type": Schema.Literal("text").annotate({ + "description": "The type of response format being defined. Always `text`." + }) }).annotate({ - "description": "The newly created admin API key. The `value` field is only returned once, when the key is created." + "title": "Text", + "description": "Default response format. Used to generate text responses.\n", + "identifier": "ResponseFormatText" }) -export type AssignedRoleDetails = { - readonly "id": string - readonly "name": string - readonly "permissions": ReadonlyArray - readonly "resource_type": string - readonly "predefined_role": boolean - readonly "description": string | null - readonly "created_at": number | null - readonly "updated_at": number | null - readonly "created_by": string | null - readonly "created_by_user_obj": {} | null - readonly "metadata": {} | null -} -export const AssignedRoleDetails = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier for the role." }), - "name": Schema.String.annotate({ "description": "Name of the role." }), - "permissions": Schema.Array(Schema.String).annotate({ "description": "Permissions associated with the role." }), - "resource_type": Schema.String.annotate({ "description": "Resource type the role applies to." }), - "predefined_role": Schema.Boolean.annotate({ "description": "Whether the role is predefined by OpenAI." }), - "description": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Description of the role." }), - "created_at": Schema.Union([Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt()), Schema.Null]) - .annotate({ "description": "When the role was created." }), - "updated_at": Schema.Union([Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt()), Schema.Null]) - .annotate({ "description": "When the role was last updated." }), - "created_by": Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "Identifier of the actor who created the role." - }), - "created_by_user_obj": Schema.Union([Schema.Struct({}), Schema.Null]).annotate({ - "description": "User details for the actor that created the role, when available." - }), - "metadata": Schema.Union([Schema.Struct({}), Schema.Null]).annotate({ - "description": "Arbitrary metadata stored on the role." +export type ResponseFormatJsonObject = { readonly "type": "json_object" } +export const ResponseFormatJsonObject = Schema.Struct({ + "type": Schema.Literal("json_object").annotate({ + "description": "The type of response format being defined. Always `json_object`." }) -}).annotate({ "description": "Detailed information about a role assignment entry returned when listing assignments." }) +}).annotate({ + "title": "JSON object", + "description": + "JSON object response format. An older method of generating JSON responses.\nUsing `json_schema` is recommended for models that support it. Note that the\nmodel will not generate JSON without a system or user message instructing it\nto do so.\n", + "identifier": "ResponseFormatJsonObject" +}) +export type ResponseFormatJsonSchemaSchema = { readonly [x: string]: Schema.Json } +export const ResponseFormatJsonSchemaSchema = Schema.Record( + Schema.String, + Schema.Json.annotate({ "expected": "JSON value" }) +).annotate({ + "title": "JSON schema", + "description": + "The schema for the response format, described as a JSON Schema object.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n", + "identifier": "ResponseFormatJsonSchemaSchema" +}) +export type _MisalignmentErrorType = + | string + | "potentially_unintended_data_transfer" + | "potentially_unintended_data_access" + | "potentially_unintended_destructive_activity" + | "other" +export const _MisalignmentErrorType = Schema.Union([ + Schema.String, + Schema.Literals([ + "potentially_unintended_data_transfer", + "potentially_unintended_data_access", + "potentially_unintended_destructive_activity", + "other" + ]) +]).annotate({ "identifier": "_MisalignmentErrorType" }) +export type _MisalignmentSteer = { readonly "message": string } +export const _MisalignmentSteer = Schema.Struct({ + "message": Schema.String.annotate({ "description": "The public continuation instruction." }) +}).annotate({ "identifier": "_MisalignmentSteer" }) export type AssistantSupportedModels = | "gpt-5" | "gpt-5-mini" @@ -254,427 +187,487 @@ export const AssistantSupportedModels = Schema.Literals([ "gpt-3.5-turbo-1106", "gpt-3.5-turbo-0125", "gpt-3.5-turbo-16k-0613" -]) -export type AssistantToolsCode = { readonly "type": "code_interpreter" } -export const AssistantToolsCode = Schema.Struct({ - "type": Schema.Literal("code_interpreter").annotate({ - "description": "The type of tool being defined: `code_interpreter`" - }) -}).annotate({ "title": "Code interpreter tool" }) -export type AssistantToolsFileSearchTypeOnly = { readonly "type": "file_search" } -export const AssistantToolsFileSearchTypeOnly = Schema.Struct({ - "type": Schema.Literal("file_search").annotate({ "description": "The type of tool being defined: `file_search`" }) -}).annotate({ "title": "FileSearch tool" }) -export type AssistantsNamedToolChoice = { - readonly "type": "function" | "code_interpreter" | "file_search" - readonly "function"?: { readonly "name": string } +]).annotate({ "identifier": "AssistantSupportedModels" }) +export type ReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | null +export const ReasoningEffort = Schema.Union([ + Schema.Literals(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).annotate({ + "description": + "Constrains effort on reasoning for reasoning models. Currently supported\nvalues are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.\nReducing reasoning effort can result in faster responses and fewer tokens\nused on reasoning in a response. Not all reasoning models support every\nvalue. See the\n[reasoning guide](https://developers.openai.com/api/docs/guides/reasoning)\nfor model-specific support.\n" + }), + Schema.Null +]).annotate({ "identifier": "ReasoningEffort" }) +export type DeleteAssistantResponse = { + readonly "id": string + readonly "deleted": boolean + readonly "object": "assistant.deleted" } -export const AssistantsNamedToolChoice = Schema.Struct({ - "type": Schema.Literals(["function", "code_interpreter", "file_search"]).annotate({ - "description": "The type of the tool. If type is `function`, the function name must be set" +export const DeleteAssistantResponse = Schema.Struct({ + "id": Schema.String, + "deleted": Schema.Boolean, + "object": Schema.Literal("assistant.deleted") +}).annotate({ "identifier": "DeleteAssistantResponse" }) +export type VoiceIdsShared = + | string + | "alloy" + | "ash" + | "ballad" + | "coral" + | "echo" + | "sage" + | "shimmer" + | "verse" + | "marin" + | "cedar" +export const VoiceIdsShared = Schema.Union([ + Schema.String, + Schema.Literals(["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"]) +]).annotate({ "identifier": "VoiceIdsShared" }) +export type SpeechAudioDeltaEvent = { readonly "type": "speech.audio.delta"; readonly "audio": string } +export const SpeechAudioDeltaEvent = Schema.Struct({ + "type": Schema.Literal("speech.audio.delta").annotate({ + "description": "The type of the event. Always `speech.audio.delta`.\n" }), - "function": Schema.optionalKey( - Schema.Struct({ "name": Schema.String.annotate({ "description": "The name of the function to call." }) }) - ) -}).annotate({ "description": "Specifies a tool the model should use. Use to force the model to call a specific tool." }) + "audio": Schema.String.annotate({ "description": "A chunk of Base64-encoded audio data.\n" }) +}).annotate({ + "description": "Emitted for each chunk of audio data generated during speech synthesis.", + "identifier": "SpeechAudioDeltaEvent" +}) +export type SpeechAudioDoneEvent = { + readonly "type": "speech.audio.done" + readonly "usage": { + readonly "input_tokens": number + readonly "output_tokens": number + readonly "total_tokens": number + } +} +export const SpeechAudioDoneEvent = Schema.Struct({ + "type": Schema.Literal("speech.audio.done").annotate({ + "description": "The type of the event. Always `speech.audio.done`.\n" + }), + "usage": Schema.Struct({ + "input_tokens": Schema.Number.annotate({ "description": "Number of input tokens in the prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "output_tokens": Schema.Number.annotate({ "description": "Number of output tokens generated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (input + output)." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "Token usage statistics for the request.\n" }) +}).annotate({ + "description": "Emitted when the speech synthesis is complete and all audio has been streamed.", + "identifier": "SpeechAudioDoneEvent" +}) +export type __ClientMultipartFile = globalThis.File | globalThis.Blob +export const __ClientMultipartFile = Schema.instanceOf(globalThis.Blob, { expected: "File | Blob" }) export type AudioResponseFormat = "json" | "text" | "srt" | "verbose_json" | "vtt" | "diarized_json" export const AudioResponseFormat = Schema.Literals(["json", "text", "srt", "verbose_json", "vtt", "diarized_json"]) .annotate({ "description": - "The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, `vtt`, or `diarized_json`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. For `gpt-4o-transcribe-diarize`, the supported formats are `json`, `text`, and `diarized_json`, with `diarized_json` required to receive speaker annotations.\n" + "The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, `vtt`, or `diarized_json`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, the only supported format is `json`. For `gpt-4o-transcribe-diarize`, the supported formats are `json`, `text`, and `diarized_json`, with `diarized_json` required to receive speaker annotations.\n", + "identifier": "AudioResponseFormat" }) -export type AuditLogActorServiceAccount = { readonly "id"?: string } -export const AuditLogActorServiceAccount = Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The service account id." })) -}).annotate({ "description": "The service account that performed the audit logged action." }) -export type AuditLogActorUser = { readonly "id"?: string; readonly "email"?: string } -export const AuditLogActorUser = Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The user id." })), - "email": Schema.optionalKey(Schema.String.annotate({ "description": "The user email." })) -}).annotate({ "description": "The user who performed the audit logged action." }) -export type AuditLogEventType = - | "api_key.created" - | "api_key.updated" - | "api_key.deleted" - | "certificate.created" - | "certificate.updated" - | "certificate.deleted" - | "certificates.activated" - | "certificates.deactivated" - | "checkpoint.permission.created" - | "checkpoint.permission.deleted" - | "external_key.registered" - | "external_key.removed" - | "group.created" - | "group.updated" - | "group.deleted" - | "invite.sent" - | "invite.accepted" - | "invite.deleted" - | "ip_allowlist.created" - | "ip_allowlist.updated" - | "ip_allowlist.deleted" - | "ip_allowlist.config.activated" - | "ip_allowlist.config.deactivated" - | "login.succeeded" - | "login.failed" - | "logout.succeeded" - | "logout.failed" - | "organization.updated" - | "project.created" - | "project.updated" - | "project.archived" - | "project.deleted" - | "rate_limit.updated" - | "rate_limit.deleted" - | "resource.deleted" - | "tunnel.created" - | "tunnel.updated" - | "tunnel.deleted" - | "role.created" - | "role.updated" - | "role.deleted" - | "role.assignment.created" - | "role.assignment.deleted" - | "scim.enabled" - | "scim.disabled" - | "service_account.created" - | "service_account.updated" - | "service_account.deleted" - | "user.added" - | "user.updated" - | "user.deleted" -export const AuditLogEventType = Schema.Literals([ - "api_key.created", - "api_key.updated", - "api_key.deleted", - "certificate.created", - "certificate.updated", - "certificate.deleted", - "certificates.activated", - "certificates.deactivated", - "checkpoint.permission.created", - "checkpoint.permission.deleted", - "external_key.registered", - "external_key.removed", - "group.created", - "group.updated", - "group.deleted", - "invite.sent", - "invite.accepted", - "invite.deleted", - "ip_allowlist.created", - "ip_allowlist.updated", - "ip_allowlist.deleted", - "ip_allowlist.config.activated", - "ip_allowlist.config.deactivated", - "login.succeeded", - "login.failed", - "logout.succeeded", - "logout.failed", - "organization.updated", - "project.created", - "project.updated", - "project.archived", - "project.deleted", - "rate_limit.updated", - "rate_limit.deleted", - "resource.deleted", - "tunnel.created", - "tunnel.updated", - "tunnel.deleted", - "role.created", - "role.updated", - "role.deleted", - "role.assignment.created", - "role.assignment.deleted", - "scim.enabled", - "scim.disabled", - "service_account.created", - "service_account.updated", - "service_account.deleted", - "user.added", - "user.updated", - "user.deleted" -]).annotate({ "description": "The event type." }) -export type BatchFileExpirationAfter = { readonly "anchor": "created_at"; readonly "seconds": number } -export const BatchFileExpirationAfter = Schema.Struct({ - "anchor": Schema.Literal("created_at").annotate({ - "description": - "Anchor timestamp after which the expiration policy applies. Supported anchors: `created_at`. Note that the anchor is the file creation time, not the time the batch is created." - }), - "seconds": Schema.Number.annotate({ - "description": - "The number of seconds after the anchor time that the file will expire. Must be between 3600 (1 hour) and 2592000 (30 days).", - "format": "int64" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(3600)).check(Schema.isLessThanOrEqualTo(2592000)) -}).annotate({ - "title": "File expiration policy", - "description": "The expiration policy for the output and/or error file that are generated for a batch." -}) -export type Certificate = { - readonly "object": "certificate" | "organization.certificate" | "organization.project.certificate" - readonly "id": string - readonly "name": string | null - readonly "created_at": number - readonly "certificate_details": { - readonly "valid_at"?: number - readonly "expires_at"?: number - readonly "content"?: string - } - readonly "active"?: boolean +export type TranscriptionInclude = "logprobs" +export const TranscriptionInclude = Schema.Literal("logprobs").annotate({ "identifier": "TranscriptionInclude" }) +export type VadConfig = { + readonly "type": "server_vad" + readonly "prefix_padding_ms"?: number + readonly "silence_duration_ms"?: number + readonly "threshold"?: number } -export const Certificate = Schema.Struct({ - "object": Schema.Literals(["certificate", "organization.certificate", "organization.project.certificate"]).annotate({ - "description": - "The object type.\n\n- If creating, updating, or getting a specific certificate, the object type is `certificate`.\n- If listing, activating, or deactivating certificates for the organization, the object type is `organization.certificate`.\n- If listing, activating, or deactivating certificates for a project, the object type is `organization.project.certificate`.\n" - }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the certificate." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate was uploaded.", - "format": "unixtime" - }).check(Schema.isInt()), - "certificate_details": Schema.Struct({ - "valid_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate becomes valid.", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "expires_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate expires.", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "content": Schema.optionalKey( - Schema.String.annotate({ "description": "The content of the certificate in PEM format." }) - ) +export const VadConfig = Schema.Struct({ + "type": Schema.Literal("server_vad").annotate({ + "description": "Must be set to `server_vad` to enable manual chunking using server side VAD." }), - "active": Schema.optionalKey( - Schema.Boolean.annotate({ + "prefix_padding_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Amount of audio to include before the VAD detected speech (in \nmilliseconds).\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "silence_duration_ms": Schema.optionalKey( + Schema.Number.annotate({ "description": - "Whether the certificate is currently active at the specified scope. Not returned when getting details for a specific certificate." - }) + "Duration of silence to detect speech stop (in milliseconds).\nWith shorter values the model will respond more quickly, \nbut may jump in on short pauses from the user.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "threshold": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Sensitivity threshold (0.0 to 1.0) for voice activity detection. A \nhigher threshold will require louder audio to activate the model, and \nthus might perform better in noisy environments.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) ) -}).annotate({ "description": "Represents an individual `certificate` uploaded to the organization." }) -export type ChatCompletionAllowedTools = { readonly "mode": "auto" | "required"; readonly "tools": ReadonlyArray<{}> } -export const ChatCompletionAllowedTools = Schema.Struct({ - "mode": Schema.Literals(["auto", "required"]).annotate({ - "description": - "Constrains the tools available to the model to a pre-defined set.\n\n`auto` allows the model to pick from among the allowed tools and generate a\nmessage.\n\n`required` requires the model to call one or more of the allowed tools.\n" +}).annotate({ "identifier": "VadConfig" }) +export type TranscriptionLanguage = { readonly "code": string } +export const TranscriptionLanguage = Schema.Struct({ + "code": Schema.String.annotate({ "description": "The code of a language detected in the audio." }) +}).annotate({ "description": "A language detected in transcribed audio.", "identifier": "TranscriptionLanguage" }) +export type TranscriptTextUsageTokens = { + readonly "type": "tokens" + readonly "input_tokens": number + readonly "input_token_details"?: { readonly "text_tokens"?: number; readonly "audio_tokens"?: number } + readonly "output_tokens": number + readonly "total_tokens": number +} +export const TranscriptTextUsageTokens = Schema.Struct({ + "type": Schema.Literal("tokens").annotate({ + "description": "The type of the usage object. Always `tokens` for this variant." }), - "tools": Schema.Array( - Schema.Struct({}).annotate({ "description": "A tool definition that the model should be allowed to call.\n" }) - ).annotate({ - "description": - "A list of tool definitions that the model should be allowed to call.\n\nFor the Chat Completions API, the list of tool definitions might look like:\n```json\n[\n { \"type\": \"function\", \"function\": { \"name\": \"get_weather\" } },\n { \"type\": \"function\", \"function\": { \"name\": \"get_time\" } }\n]\n```\n" - }) + "input_tokens": Schema.Number.annotate({ "description": "Number of input tokens billed for this request." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "input_token_details": Schema.optionalKey( + Schema.Struct({ + "text_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "Number of text tokens billed for this request." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "audio_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "Number of audio tokens billed for this request." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ) + }).annotate({ "description": "Details about the input tokens billed for this request." }) + ), + "output_tokens": Schema.Number.annotate({ "description": "Number of output tokens generated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (input + output)." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) }).annotate({ - "title": "Allowed tools", - "description": "Constrains the tools available to the model to a pre-defined set.\n" -}) -export type ChatCompletionDeleted = { - readonly "object": "chat.completion.deleted" - readonly "id": string - readonly "deleted": boolean -} -export const ChatCompletionDeleted = Schema.Struct({ - "object": Schema.Literal("chat.completion.deleted").annotate({ "description": "The type of object being deleted." }), - "id": Schema.String.annotate({ "description": "The ID of the chat completion that was deleted." }), - "deleted": Schema.Boolean.annotate({ "description": "Whether the chat completion was deleted." }) + "title": "Token Usage", + "description": "Usage statistics for models billed by token usage.", + "identifier": "TranscriptTextUsageTokens" }) -export type ChatCompletionFunctionCallOption = { readonly "name": string } -export const ChatCompletionFunctionCallOption = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the function to call." }) +export type TranscriptTextUsageDuration = { readonly "type": "duration"; readonly "seconds": number } +export const TranscriptTextUsageDuration = Schema.Struct({ + "type": Schema.Literal("duration").annotate({ + "description": "The type of the usage object. Always `duration` for this variant." + }), + "seconds": Schema.Number.annotate({ "description": "Duration of the input audio in seconds.", "format": "double" }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })) }).annotate({ - "description": - "Specifying a particular function via `{\"name\": \"my_function\"}` forces the model to call that function.\n" + "title": "Duration Usage", + "description": "Usage statistics for models billed by audio input duration.", + "identifier": "TranscriptTextUsageDuration" }) -export type ChatCompletionMessageCustomToolCall = { - readonly "id": string - readonly "type": "custom" - readonly "custom": { readonly "name": string; readonly "input": string } -} -export const ChatCompletionMessageCustomToolCall = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The ID of the tool call." }), - "type": Schema.Literal("custom").annotate({ "description": "The type of the tool. Always `custom`." }), - "custom": Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the custom tool to call." }), - "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model." }) - }).annotate({ "description": "The custom tool that the model called." }) -}).annotate({ "title": "Custom tool call", "description": "A call to a custom tool created by the model.\n" }) -export type ChatCompletionMessageToolCall = { +export type TranscriptionDiarizedSegment = { + readonly "type": "transcript.text.segment" readonly "id": string - readonly "type": "function" - readonly "function": { readonly "name": string; readonly "arguments": string } + readonly "start": number + readonly "end": number + readonly "text": string + readonly "speaker": string } -export const ChatCompletionMessageToolCall = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The ID of the tool call." }), - "type": Schema.Literal("function").annotate({ - "description": "The type of the tool. Currently, only `function` is supported." +export const TranscriptionDiarizedSegment = Schema.Struct({ + "type": Schema.Literal("transcript.text.segment").annotate({ + "description": "The type of the segment. Always `transcript.text.segment`.\n" }), - "function": Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the function to call." }), - "arguments": Schema.String.annotate({ - "description": - "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - }) - }).annotate({ "description": "The function that the model called." }) -}).annotate({ "title": "Function tool call", "description": "A call to a function tool created by the model.\n" }) -export type ChatCompletionMessageToolCallChunk = { - readonly "index": number - readonly "id"?: string - readonly "type"?: "function" - readonly "function"?: { readonly "name"?: string; readonly "arguments"?: string } + "id": Schema.String.annotate({ "description": "Unique identifier for the segment." }), + "start": Schema.Number.annotate({ "description": "Start timestamp of the segment in seconds.", "format": "double" }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "end": Schema.Number.annotate({ "description": "End timestamp of the segment in seconds.", "format": "double" }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "text": Schema.String.annotate({ "description": "Transcript text for this segment." }), + "speaker": Schema.String.annotate({ + "description": + "Speaker label for this segment. When known speakers are provided, the label matches `known_speaker_names[]`. Otherwise speakers are labeled sequentially using capital letters (`A`, `B`, ...).\n" + }) +}).annotate({ + "description": "A segment of diarized transcript text with speaker metadata.", + "identifier": "TranscriptionDiarizedSegment" +}) +export type TranscriptionWord = { readonly "word": string; readonly "start": number; readonly "end": number } +export const TranscriptionWord = Schema.Struct({ + "word": Schema.String.annotate({ "description": "The text content of the word." }), + "start": Schema.Number.annotate({ "description": "Start time of the word in seconds.", "format": "double" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "end": Schema.Number.annotate({ "description": "End time of the word in seconds.", "format": "double" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) +}).annotate({ "identifier": "TranscriptionWord" }) +export type TranscriptionSegment = { + readonly "id": number + readonly "seek": number + readonly "start": number + readonly "end": number + readonly "text": string + readonly "tokens": ReadonlyArray + readonly "temperature": number + readonly "avg_logprob": number + readonly "compression_ratio": number + readonly "no_speech_prob": number } -export const ChatCompletionMessageToolCallChunk = Schema.Struct({ - "index": Schema.Number.check(Schema.isInt()), - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the tool call." })), - "type": Schema.optionalKey( - Schema.Literal("function").annotate({ - "description": "The type of the tool. Currently, only `function` is supported." - }) +export const TranscriptionSegment = Schema.Struct({ + "id": Schema.Number.annotate({ "description": "Unique identifier of the segment." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "function": Schema.optionalKey(Schema.Struct({ - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function to call." })), - "arguments": Schema.optionalKey(Schema.String.annotate({ - "description": - "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - })) - })) -}) -export type ChatCompletionNamedToolChoice = { - readonly "type": "function" - readonly "function": { readonly "name": string } + "seek": Schema.Number.annotate({ "description": "Seek offset of the segment." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "start": Schema.Number.annotate({ "description": "Start time of the segment in seconds.", "format": "double" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "end": Schema.Number.annotate({ "description": "End time of the segment in seconds.", "format": "double" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "text": Schema.String.annotate({ "description": "Text content of the segment." }), + "tokens": Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).annotate({ + "description": "Array of token IDs for the text content." + }), + "temperature": Schema.Number.annotate({ + "description": "Temperature parameter used for generating the segment.", + "format": "float" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "avg_logprob": Schema.Number.annotate({ + "description": "Average logprob of the segment. If the value is lower than -1, consider the logprobs failed.", + "format": "float" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "compression_ratio": Schema.Number.annotate({ + "description": + "Compression ratio of the segment. If the value is greater than 2.4, consider the compression failed.", + "format": "float" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "no_speech_prob": Schema.Number.annotate({ + "description": + "Probability of no speech in the segment. If the value is higher than 1.0 and the `avg_logprob` is below -1, consider this segment silent.", + "format": "float" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) +}).annotate({ "identifier": "TranscriptionSegment" }) +export type TranscriptTextSegmentEvent = { + readonly "type": "transcript.text.segment" + readonly "id": string + readonly "start": number + readonly "end": number + readonly "text": string + readonly "speaker": string } -export const ChatCompletionNamedToolChoice = Schema.Struct({ - "type": Schema.Literal("function").annotate({ - "description": "For function calling, the type is always `function`." +export const TranscriptTextSegmentEvent = Schema.Struct({ + "type": Schema.Literal("transcript.text.segment").annotate({ + "description": "The type of the event. Always `transcript.text.segment`." }), - "function": Schema.Struct({ "name": Schema.String.annotate({ "description": "The name of the function to call." }) }) + "id": Schema.String.annotate({ "description": "Unique identifier for the segment." }), + "start": Schema.Number.annotate({ "description": "Start timestamp of the segment in seconds.", "format": "double" }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "end": Schema.Number.annotate({ "description": "End timestamp of the segment in seconds.", "format": "double" }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "text": Schema.String.annotate({ "description": "Transcript text for this segment." }), + "speaker": Schema.String.annotate({ "description": "Speaker label for this segment." }) }).annotate({ - "title": "Function tool choice", - "description": "Specifies a tool the model should use. Use to force the model to call a specific function." + "description": + "Emitted when a diarized transcription returns a completed segment with speaker information. Only emitted when you [create a transcription](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create) with `stream` set to `true` and `response_format` set to `diarized_json`.\n", + "identifier": "TranscriptTextSegmentEvent" }) -export type ChatCompletionNamedToolChoiceCustom = { - readonly "type": "custom" - readonly "custom": { readonly "name": string } +export type TranscriptTextDeltaEvent = { + readonly "type": "transcript.text.delta" + readonly "delta": string + readonly "logprobs"?: ReadonlyArray< + { readonly "token"?: string; readonly "logprob"?: number; readonly "bytes"?: ReadonlyArray } + > + readonly "segment_id"?: string } -export const ChatCompletionNamedToolChoiceCustom = Schema.Struct({ - "type": Schema.Literal("custom").annotate({ "description": "For custom tool calling, the type is always `custom`." }), - "custom": Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the custom tool to call." }) - }) +export const TranscriptTextDeltaEvent = Schema.Struct({ + "type": Schema.Literal("transcript.text.delta").annotate({ + "description": "The type of the event. Always `transcript.text.delta`.\n" + }), + "delta": Schema.String.annotate({ "description": "The text delta that was additionally transcribed.\n" }), + "logprobs": Schema.optionalKey( + Schema.Array(Schema.Struct({ + "token": Schema.optionalKey( + Schema.String.annotate({ "description": "The token that was used to generate the log probability.\n" }) + ), + "logprob": Schema.optionalKey( + Schema.Number.annotate({ "description": "The log probability of the token.\n" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) + ), + "bytes": Schema.optionalKey( + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).annotate({ + "description": "The bytes that were used to generate the log probability.\n" + }) + ) + })).annotate({ + "description": + "The log probabilities of the delta. Only included if you [create a transcription](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create) with the `include[]` parameter set to `logprobs`.\n" + }) + ), + "segment_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "Identifier of the diarized segment that this delta belongs to. Only present when using `gpt-4o-transcribe-diarize`.\n" + }) + ) }).annotate({ - "title": "Custom tool choice", - "description": "Specifies a tool the model should use. Use to force the model to call a specific custom tool." + "description": + "Emitted when there is an additional text delta. This is also the first event emitted when the transcription starts. Only emitted when you [create a transcription](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create) with the `Stream` parameter set to `true`.", + "identifier": "TranscriptTextDeltaEvent" }) -export type ChatCompletionRequestFunctionMessage = { - readonly "role": "function" - readonly "content": string | null +export type CreateTranslationResponseJson = { readonly "text": string } +export const CreateTranslationResponseJson = Schema.Struct({ "text": Schema.String }).annotate({ + "identifier": "CreateTranslationResponseJson" +}) +export type VoiceConsentResource = { + readonly "object": "audio.voice_consent" + readonly "id": string readonly "name": string + readonly "language": string + readonly "created_at": number } -export const ChatCompletionRequestFunctionMessage = Schema.Struct({ - "role": Schema.Literal("function").annotate({ - "description": "The role of the messages author, in this case `function`." +export const VoiceConsentResource = Schema.Struct({ + "object": Schema.Literal("audio.voice_consent").annotate({ + "description": "The object type, which is always `audio.voice_consent`." }), - "content": Schema.Union([ - Schema.String.annotate({ "description": "The contents of the function message." }), - Schema.Null - ]), - "name": Schema.String.annotate({ "description": "The name of the function to call." }) -}).annotate({ "title": "Function message" }) -export type ChatCompletionRequestMessageContentPartAudio = { - readonly "type": "input_audio" - readonly "input_audio": { readonly "data": string; readonly "format": "wav" | "mp3" } -} -export const ChatCompletionRequestMessageContentPartAudio = Schema.Struct({ - "type": Schema.Literal("input_audio").annotate({ - "description": "The type of the content part. Always `input_audio`." + "id": Schema.String.annotate({ "description": "The consent recording identifier." }), + "name": Schema.String.annotate({ "description": "The label provided when the consent recording was uploaded." }), + "language": Schema.String.annotate({ + "description": "The BCP 47 language tag for the consent phrase (for example, `en-US`)." }), - "input_audio": Schema.Struct({ - "data": Schema.String.annotate({ "description": "Base64 encoded audio data." }), - "format": Schema.Literals(["wav", "mp3"]).annotate({ - "description": "The format of the encoded audio data. Currently supports \"wav\" and \"mp3\".\n" - }) - }) -}).annotate({ "title": "Audio content part", "description": "Learn about [audio inputs](/docs/guides/audio).\n" }) -export type ChatCompletionRequestMessageContentPartFile = { - readonly "type": "file" - readonly "file": { readonly "filename"?: string; readonly "file_data"?: string; readonly "file_id"?: string } -} -export const ChatCompletionRequestMessageContentPartFile = Schema.Struct({ - "type": Schema.Literal("file").annotate({ "description": "The type of the content part. Always `file`." }), - "file": Schema.Struct({ - "filename": Schema.optionalKey( - Schema.String.annotate({ - "description": "The name of the file, used when passing the file to the model as a \nstring.\n" - }) - ), - "file_data": Schema.optionalKey( - Schema.String.annotate({ - "description": "The base64 encoded file data, used when passing the file to the model \nas a string.\n" - }) - ), - "file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of an uploaded file to use as input.\n" }) - ) - }) + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the consent recording was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) }).annotate({ - "title": "File content part", - "description": "Learn about [file inputs](/docs/guides/text) for text generation.\n" + "title": "Voice consent", + "description": "A consent recording used to authorize creation of a custom voice.", + "identifier": "VoiceConsentResource" }) -export type ChatCompletionRequestMessageContentPartImage = { - readonly "type": "image_url" - readonly "image_url": { readonly "url": string; readonly "detail"?: "auto" | "low" | "high" } +export type UpdateVoiceConsentRequest = { readonly "name": string } +export const UpdateVoiceConsentRequest = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The updated label for this consent recording." }) +}).annotate({ "identifier": "UpdateVoiceConsentRequest" }) +export type VoiceConsentDeletedResource = { + readonly "id": string + readonly "object": "audio.voice_consent" + readonly "deleted": boolean } -export const ChatCompletionRequestMessageContentPartImage = Schema.Struct({ - "type": Schema.Literal("image_url").annotate({ "description": "The type of the content part." }), - "image_url": Schema.Struct({ - "url": Schema.String.annotate({ - "description": "Either a URL of the image or the base64 encoded image data.", - "format": "uri" - }), - "detail": Schema.optionalKey( - Schema.Literals(["auto", "low", "high"]).annotate({ - "description": - "Specifies the detail level of the image. Learn more in the [Vision guide](/docs/guides/vision#low-or-high-fidelity-image-understanding)." - }) - ) - }) -}).annotate({ "title": "Image content part", "description": "Learn about [image inputs](/docs/guides/vision).\n" }) -export type ChatCompletionRequestMessageContentPartRefusal = { readonly "type": "refusal"; readonly "refusal": string } -export const ChatCompletionRequestMessageContentPartRefusal = Schema.Struct({ - "type": Schema.Literal("refusal").annotate({ "description": "The type of the content part." }), - "refusal": Schema.String.annotate({ "description": "The refusal message generated by the model." }) -}).annotate({ "title": "Refusal content part" }) -export type ChatCompletionRequestMessageContentPartText = { readonly "type": "text"; readonly "text": string } -export const ChatCompletionRequestMessageContentPartText = Schema.Struct({ - "type": Schema.Literal("text").annotate({ "description": "The type of the content part." }), - "text": Schema.String.annotate({ "description": "The text content." }) +export const VoiceConsentDeletedResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The consent recording identifier." }), + "object": Schema.Literal("audio.voice_consent"), + "deleted": Schema.Boolean +}).annotate({ "identifier": "VoiceConsentDeletedResource" }) +export type VoiceResource = { + readonly "object": "audio.voice" + readonly "id": string + readonly "type": "audio_sample" + readonly "name": string + readonly "created_at": number +} +export const VoiceResource = Schema.Struct({ + "object": Schema.Literal("audio.voice").annotate({ + "description": "The object type, which is always `audio.voice`." + }), + "id": Schema.String.annotate({ "description": "The voice identifier, which can be referenced in API endpoints." }), + "type": Schema.Literal("audio_sample").annotate({ "description": "How the voice was created." }), + "name": Schema.String.annotate({ "description": "The name of the voice." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the voice was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) }).annotate({ - "title": "Text content part", - "description": "Learn about [text inputs](/docs/guides/text-generation).\n" + "title": "Voice", + "description": "A custom voice that can be used for audio output.", + "identifier": "VoiceResource" }) -export type ChatCompletionStreamOptions = { - readonly "include_usage"?: boolean - readonly "include_obfuscation"?: boolean -} | null -export const ChatCompletionStreamOptions = Schema.Union([ - Schema.Struct({ - "include_usage": Schema.optionalKey(Schema.Boolean.annotate({ - "description": - "If set, an additional chunk will be streamed before the `data: [DONE]`\nmessage. The `usage` field on this chunk shows the token usage statistics\nfor the entire request, and the `choices` field will always be an empty\narray.\n\nAll other chunks will also include a `usage` field, but with a null\nvalue. **NOTE:** If the stream is interrupted, you may not receive the\nfinal usage chunk which contains the total token usage for the request.\n" - })), - "include_obfuscation": Schema.optionalKey(Schema.Boolean.annotate({ +export type BatchError = { + readonly "code"?: string + readonly "message"?: string + readonly "param"?: string | null + readonly "line"?: number | null +} +export const BatchError = Schema.Struct({ + "code": Schema.optionalKey(Schema.String.annotate({ "description": "An error code identifying the error type." })), + "message": Schema.optionalKey( + Schema.String.annotate({ "description": "A human-readable message providing more details about the error." }) + ), + "param": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The name of the parameter that caused the error, if applicable." }), + Schema.Null + ]) + ), + "line": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The line number of the input file where the error occurred, if applicable." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ) +}).annotate({ "identifier": "BatchError" }) +export type BatchRequestCounts = { readonly "total": number; readonly "completed": number; readonly "failed": number } +export const BatchRequestCounts = Schema.Struct({ + "total": Schema.Number.annotate({ "description": "Total number of requests in the batch." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "completed": Schema.Number.annotate({ "description": "Number of requests that have been completed successfully." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "failed": Schema.Number.annotate({ "description": "Number of requests that have failed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "The request counts for different statuses within the batch.", + "identifier": "BatchRequestCounts" +}) +export type BatchFileExpirationAfter = { readonly "anchor": "created_at"; readonly "seconds": number } +export const BatchFileExpirationAfter = Schema.Struct({ + "anchor": Schema.Literal("created_at").annotate({ + "description": + "Anchor timestamp after which the expiration policy applies. Supported anchors: `created_at`. Note that the anchor is the file creation time, not the time the batch is created." + }), + "seconds": Schema.Number.annotate({ + "description": + "The number of seconds after the anchor time that the file will expire. Must be between 3600 (1 hour) and 2592000 (30 days).", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(3600).annotate({ "expected": "a value greater than or equal to 3600" }) + ).check(Schema.isLessThanOrEqualTo(2592000).annotate({ "expected": "a value less than or equal to 2592000" })) +}).annotate({ + "title": "File expiration policy", + "description": "The expiration policy for the output and/or error file that are generated for a batch.", + "identifier": "BatchFileExpirationAfter" +}) +export type ChatCompletionMessageToolCall = { + readonly "id": string + readonly "type": "function" + readonly "function": { readonly "name": string; readonly "arguments": string } +} +export const ChatCompletionMessageToolCall = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the tool call." }), + "type": Schema.Literal("function").annotate({ + "description": "The type of the tool. Currently, only `function` is supported." + }), + "function": Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the function to call." }), + "arguments": Schema.String.annotate({ "description": - "When true, stream obfuscation will be enabled. Stream obfuscation adds\nrandom characters to an `obfuscation` field on streaming delta events to\nnormalize payload sizes as a mitigation to certain side-channel attacks.\nThese obfuscation fields are included by default, but add a small amount\nof overhead to the data stream. You can set `include_obfuscation` to\nfalse to optimize for bandwidth if you trust the network links between\nyour application and the OpenAI API.\n" - })) - }).annotate({ "description": "Options for streaming response. Only set this when you set `stream: true`.\n" }), - Schema.Null -]) + "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." + }) + }).annotate({ "description": "The function that the model called." }) +}).annotate({ + "title": "Function tool call", + "description": "A call to a function tool created by the model.\n", + "identifier": "ChatCompletionMessageToolCall" +}) +export type ChatCompletionMessageCustomToolCall = { + readonly "id": string + readonly "type": "custom" + readonly "custom": { readonly "name": string; readonly "input": string } +} +export const ChatCompletionMessageCustomToolCall = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the tool call." }), + "type": Schema.Literal("custom").annotate({ "description": "The type of the tool. Always `custom`." }), + "custom": Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the custom tool to call." }), + "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model." }) + }).annotate({ "description": "The custom tool that the model called." }) +}).annotate({ + "title": "Custom tool call", + "description": "A call to a custom tool created by the model.\n", + "identifier": "ChatCompletionMessageCustomToolCall" +}) export type ChatCompletionTokenLogprob = { readonly "token": string readonly "logprob": number @@ -688,9 +681,9 @@ export const ChatCompletionTokenLogprob = Schema.Struct({ "logprob": Schema.Number.annotate({ "description": "The log probability of this token, if it is within the top 20 most likely tokens. Otherwise, the value `-9999.0` is used to signify that the token is very unlikely." - }).check(Schema.isFinite()), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), "bytes": Schema.Union([ - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).annotate({ "description": "A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token." }), @@ -701,9 +694,9 @@ export const ChatCompletionTokenLogprob = Schema.Struct({ "logprob": Schema.Number.annotate({ "description": "The log probability of this token, if it is within the top 20 most likely tokens. Otherwise, the value `-9999.0` is used to signify that the token is very unlikely." - }).check(Schema.isFinite()), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), "bytes": Schema.Union([ - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).annotate({ "description": "A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token." }), @@ -713,41 +706,15 @@ export const ChatCompletionTokenLogprob = Schema.Struct({ "description": "List of the most likely tokens and their log probability, at this token position. The number of entries may be fewer than the requested `top_logprobs`." }) -}) -export type ComparisonFilter = { - readonly "type": "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" - readonly "key": string - readonly "value": string | number | boolean | ReadonlyArray -} -export const ComparisonFilter = Schema.Struct({ - "type": Schema.Literals(["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"]).annotate({ +}).annotate({ "identifier": "ChatCompletionTokenLogprob" }) +export type ServiceTier = "auto" | "default" | "flex" | "scale" | "priority" | "fast" | null +export const ServiceTier = Schema.Union([ + Schema.Literals(["auto", "default", "flex", "scale", "priority", "fast"]).annotate({ "description": - "Specifies the comparison operator: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`.\n- `eq`: equals\n- `ne`: not equal\n- `gt`: greater than\n- `gte`: greater than or equal\n- `lt`: less than\n- `lte`: less than or equal\n- `in`: in\n- `nin`: not in\n" + "Specifies the processing type used for serving the request.\n - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'.\n - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model.\n - If set to '[flex](https://developers.openai.com/api/docs/guides/flex-processing)', then the request will be processed with the Flex Processing service tier.\n - To opt-in to [Fast mode](https://developers.openai.com/api/docs/guides/fast-mode) at the request level, include the `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat Completions. The response will show `service_tier=priority` regardless of if you specify `service_tier=fast` or `priority` in your request.\n - When not set, the default behavior is 'auto'.\n\n When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter.\n" }), - "key": Schema.String.annotate({ "description": "The key to compare against the value." }), - "value": Schema.Union([ - Schema.String, - Schema.Number.check(Schema.isFinite()), - Schema.Boolean, - Schema.Array(Schema.Union([Schema.String, Schema.Number.check(Schema.isFinite())], { mode: "oneOf" })) - ], { mode: "oneOf" }).annotate({ - "description": "The value to compare against the attribute key; supports string, number, or boolean types." - }) -}).annotate({ - "title": "Comparison Filter", - "description": - "A filter used to compare a specified attribute key to a given value using a defined comparison operation.\n" -}) -export type CompleteUploadRequest = { readonly "part_ids": ReadonlyArray; readonly "md5"?: string } -export const CompleteUploadRequest = Schema.Struct({ - "part_ids": Schema.Array(Schema.String).annotate({ "description": "The ordered list of Part IDs.\n" }), - "md5": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The optional md5 checksum for the file contents to verify if the bytes uploaded matches what you expect.\n" - }) - ) -}) + Schema.Null +]).annotate({ "identifier": "ServiceTier" }) export type CompletionUsage = { readonly "completion_tokens": number readonly "prompt_tokens": number @@ -756,1932 +723,2153 @@ export type CompletionUsage = { readonly "accepted_prediction_tokens"?: number readonly "audio_tokens"?: number readonly "reasoning_tokens"?: number + readonly "text_tokens"?: number readonly "rejected_prediction_tokens"?: number } - readonly "prompt_tokens_details"?: { readonly "audio_tokens"?: number; readonly "cached_tokens"?: number } + readonly "prompt_tokens_details"?: { + readonly "audio_tokens"?: number + readonly "cached_tokens"?: number + readonly "text_tokens"?: number + readonly "image_tokens"?: number + readonly "cache_write_tokens"?: number + } } export const CompletionUsage = Schema.Struct({ "completion_tokens": Schema.Number.annotate({ "description": "Number of tokens in the generated completion." }).check( - Schema.isInt() + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "prompt_tokens": Schema.Number.annotate({ "description": "Number of tokens in the prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "prompt_tokens": Schema.Number.annotate({ "description": "Number of tokens in the prompt." }).check(Schema.isInt()), "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used in the request (prompt + completion)." - }).check(Schema.isInt()), + }).check(Schema.isInt().annotate({ "expected": "an integer" })), "completion_tokens_details": Schema.optionalKey( Schema.Struct({ "accepted_prediction_tokens": Schema.optionalKey( Schema.Number.annotate({ "description": "When using Predicted Outputs, the number of tokens in the\nprediction that appeared in the completion.\n" - }).check(Schema.isInt()) + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Audio input tokens generated by the model." }).check(Schema.isInt()) + Schema.Number.annotate({ "description": "Audio input tokens generated by the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), "reasoning_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Tokens generated by the model for reasoning." }).check(Schema.isInt()) + Schema.Number.annotate({ "description": "Tokens generated by the model for reasoning." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "text_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "Text output tokens generated by the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), "rejected_prediction_tokens": Schema.optionalKey( Schema.Number.annotate({ "description": "When using Predicted Outputs, the number of tokens in the\nprediction that did not appear in the completion. However, like\nreasoning tokens, these tokens are still counted in the total\ncompletion tokens for purposes of billing, output, and context window\nlimits.\n" - }).check(Schema.isInt()) + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ) }).annotate({ "description": "Breakdown of tokens used in a completion." }) ), "prompt_tokens_details": Schema.optionalKey( Schema.Struct({ "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Audio input tokens present in the prompt." }).check(Schema.isInt()) + Schema.Number.annotate({ "description": "Audio input tokens present in the prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), "cached_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Cached tokens present in the prompt." }).check(Schema.isInt()) + Schema.Number.annotate({ "description": "Cached tokens present in the prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "text_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "Text input tokens present in the prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "image_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "Image input tokens present in the prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "cache_write_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The unadjusted number of prompt tokens written to cache." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ) }).annotate({ "description": "Breakdown of tokens used in the prompt." }) ) -}).annotate({ "description": "Usage statistics for the completion request." }) -export type ComputerScreenshotImage = { - readonly "type": "computer_screenshot" - readonly "image_url"?: string - readonly "file_id"?: string -} -export const ComputerScreenshotImage = Schema.Struct({ - "type": Schema.Literal("computer_screenshot").annotate({ - "description": - "Specifies the event type. For a computer screenshot, this property is \nalways set to `computer_screenshot`.\n" - }), - "image_url": Schema.optionalKey( - Schema.String.annotate({ "description": "The URL of the screenshot image.", "format": "uri" }) - ), - "file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of an uploaded file that contains the screenshot." }) - ) -}).annotate({ "description": "A computer screenshot image used with the computer use tool.\n" }) -export type ContainerFileResource = { - readonly "id": string - readonly "object": string - readonly "container_id": string - readonly "created_at": number - readonly "bytes": number - readonly "path": string - readonly "source": string +}).annotate({ "description": "Usage statistics for the completion request.", "identifier": "CompletionUsage" }) +export type ModerationInputType = "text" | "image" +export const ModerationInputType = Schema.Literals(["text", "image"]).annotate({ "identifier": "ModerationInputType" }) +export type ChatCompletionModerationError = { + readonly "type": "error" + readonly "code": string + readonly "message": string } -export const ContainerFileResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Unique identifier for the file." }), - "object": Schema.String.annotate({ "description": "The type of this object (`container.file`)." }), - "container_id": Schema.String.annotate({ "description": "The container this file belongs to." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the file was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "bytes": Schema.Number.annotate({ "description": "Size of the file in bytes." }).check(Schema.isInt()), - "path": Schema.String.annotate({ "description": "Path of the file in the container." }), - "source": Schema.String.annotate({ "description": "Source of the file (e.g., `user`, `assistant`)." }) -}).annotate({ "title": "The container file object" }) -export type ContainerResource = { - readonly "id": string - readonly "object": string +export const ChatCompletionModerationError = Schema.Struct({ + "type": Schema.Literal("error").annotate({ "description": "The object type, which is always `error`." }), + "code": Schema.String.annotate({ "description": "The error code." }), + "message": Schema.String.annotate({ "description": "The error message." }) +}).annotate({ + "description": "An error produced while attempting moderation.", + "identifier": "ChatCompletionModerationError" +}) +export type PromptCacheTTLEnum = "30m" +export const PromptCacheTTLEnum = Schema.Literal("30m").annotate({ "identifier": "PromptCacheTTLEnum" }) +export type PromptCacheModeEnum = "implicit" | "explicit" +export const PromptCacheModeEnum = Schema.Literals(["implicit", "explicit"]).annotate({ + "identifier": "PromptCacheModeEnum" +}) +export type PromptCacheBreakpointParam = { readonly "mode": "explicit" } +export const PromptCacheBreakpointParam = Schema.Struct({ + "mode": Schema.Literal("explicit").annotate({ "description": "The breakpoint mode. Always `explicit`." }) +}).annotate({ + "title": "Prompt cache breakpoint", + "description": + "Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.", + "identifier": "PromptCacheBreakpointParam" +}) +export type ChatCompletionRequestMessageContentPartRefusal = { readonly "type": "refusal"; readonly "refusal": string } +export const ChatCompletionRequestMessageContentPartRefusal = Schema.Struct({ + "type": Schema.Literal("refusal").annotate({ "description": "The type of the content part." }), + "refusal": Schema.String.annotate({ "description": "The refusal message generated by the model." }) +}).annotate({ "title": "Refusal content part", "identifier": "ChatCompletionRequestMessageContentPartRefusal" }) +export type ChatCompletionRequestFunctionMessage = { + readonly "role": "function" + readonly "content": string | null readonly "name": string - readonly "created_at": number - readonly "status": string - readonly "last_active_at"?: number - readonly "expires_after"?: { readonly "anchor"?: "last_active_at"; readonly "minutes"?: number } - readonly "memory_limit"?: "1g" | "4g" | "16g" | "64g" - readonly "network_policy"?: { - readonly "type": "allowlist" | "disabled" - readonly "allowed_domains"?: ReadonlyArray - } -} -export const ContainerResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Unique identifier for the container." }), - "object": Schema.String.annotate({ "description": "The type of this object." }), - "name": Schema.String.annotate({ "description": "Name of the container." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the container was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "status": Schema.String.annotate({ "description": "Status of the container (e.g., active, deleted)." }), - "last_active_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the container was last active.", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "expires_after": Schema.optionalKey( - Schema.Struct({ - "anchor": Schema.optionalKey( - Schema.Literal("last_active_at").annotate({ "description": "The reference point for the expiration." }) - ), - "minutes": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of minutes after the anchor before the container expires." - }).check(Schema.isInt()) - ) - }).annotate({ - "description": - "The container will expire after this time period.\nThe anchor is the reference point for the expiration.\nThe minutes is the number of minutes after the anchor before the container expires.\n" - }) - ), - "memory_limit": Schema.optionalKey( - Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ - "description": "The memory limit configured for the container." - }) - ), - "network_policy": Schema.optionalKey( - Schema.Struct({ - "type": Schema.Literals(["allowlist", "disabled"]).annotate({ "description": "The network policy mode." }), - "allowed_domains": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ "description": "Allowed outbound domains when `type` is `allowlist`." }) - ) - }).annotate({ "description": "Network access policy for the container." }) - ) -}).annotate({ "title": "The container object" }) -export type CostsResult = { - readonly "object": "organization.costs.result" - readonly "amount"?: { readonly "value"?: number; readonly "currency"?: string } - readonly "line_item"?: string | null - readonly "project_id"?: string | null - readonly "api_key_id"?: string | null - readonly "quantity"?: number | null } -export const CostsResult = Schema.Struct({ - "object": Schema.Literal("organization.costs.result"), - "amount": Schema.optionalKey( - Schema.Struct({ - "value": Schema.optionalKey( - Schema.Number.annotate({ "description": "The numeric value of the cost." }).check(Schema.isFinite()) - ), - "currency": Schema.optionalKey( - Schema.String.annotate({ "description": "Lowercase ISO-4217 currency e.g. \"usd\"" }) - ) - }).annotate({ "description": "The monetary value in its associated currency." }) - ), - "line_item": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=line_item`, this field provides the line item of the grouped costs result." - }), - Schema.Null - ]) - ), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped costs result." - }), - Schema.Null - ]) - ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API Key ID of the grouped costs result." - }), - Schema.Null - ]) - ), - "quantity": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "When `group_by=line_item`, this field provides the quantity of the grouped costs result." - }).check(Schema.isFinite()), - Schema.Null - ]) - ) -}).annotate({ "description": "The aggregated costs details of the specific time bucket." }) -export type CreateContainerFileBody = { readonly "file_id"?: string; readonly "file"?: string } -export const CreateContainerFileBody = Schema.Struct({ - "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "Name of the file to create." })), - "file": Schema.optionalKey( - Schema.String.annotate({ "description": "The File object (not file name) to be uploaded.\n", "format": "binary" }) - ) -}) -export type CreateEmbeddingRequest = { - readonly "input": string | ReadonlyArray | ReadonlyArray | ReadonlyArray> - readonly "model": string | "text-embedding-ada-002" | "text-embedding-3-small" | "text-embedding-3-large" - readonly "encoding_format"?: "float" | "base64" - readonly "dimensions"?: number - readonly "user"?: string -} -export const CreateEmbeddingRequest = Schema.Struct({ - "input": Schema.Union([ - Schema.String.annotate({ "title": "string", "description": "The string that will be turned into an embedding." }), - Schema.Array(Schema.String).annotate({ - "title": "array", - "description": "The array of strings that will be turned into an embedding." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(2048)), - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "title": "array", - "description": "The array of integers that will be turned into an embedding." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(2048)), - Schema.Array(Schema.Array(Schema.Number.check(Schema.isInt())).check(Schema.isMinLength(1))).annotate({ - "title": "array", - "description": "The array of arrays containing integers that will be turned into an embedding." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(2048)) - ], { mode: "oneOf" }).annotate({ +export const ChatCompletionRequestFunctionMessage = Schema.Struct({ + "role": Schema.Literal("function").annotate({ + "description": "The role of the messages author, in this case `function`." + }), + "content": Schema.Union([ + Schema.String.annotate({ "description": "The contents of the function message." }), + Schema.Null + ]), + "name": Schema.String.annotate({ "description": "The name of the function to call." }) +}).annotate({ "title": "Function message", "identifier": "ChatCompletionRequestFunctionMessage" }) +export type ModelIdsShared = + | string + | "gpt-6-astra" + | "gpt-6.1-sol" + | "gpt-6-sol" + | "gpt-6-luna" + | "gpt-5.6-sol" + | "gpt-5.6-terra" + | "gpt-5.6-luna" + | "gpt-5.5" + | "gpt-5.5-2026-04-23" + | "gpt-5.4" + | "gpt-5.4-mini" + | "gpt-5.4-nano" + | "gpt-5.4-mini-2026-03-17" + | "gpt-5.4-nano-2026-03-17" + | "gpt-5.3-chat-latest" + | "gpt-5.2" + | "gpt-5.2-2025-12-11" + | "gpt-5.2-chat-latest" + | "gpt-5.2-pro" + | "gpt-5.2-pro-2025-12-11" + | "gpt-5.1" + | "gpt-5.1-2025-11-13" + | "gpt-5.1-codex" + | "gpt-5.1-mini" + | "gpt-5.1-chat-latest" + | "gpt-5" + | "gpt-5-mini" + | "gpt-5-nano" + | "gpt-5-2025-08-07" + | "gpt-5-mini-2025-08-07" + | "gpt-5-nano-2025-08-07" + | "gpt-5-chat-latest" + | "gpt-4.1" + | "gpt-4.1-mini" + | "gpt-4.1-nano" + | "gpt-4.1-2025-04-14" + | "gpt-4.1-mini-2025-04-14" + | "gpt-4.1-nano-2025-04-14" + | "o4-mini" + | "o4-mini-2025-04-16" + | "o3" + | "o3-2025-04-16" + | "o3-mini" + | "o3-mini-2025-01-31" + | "o1" + | "o1-2024-12-17" + | "o1-preview" + | "o1-preview-2024-09-12" + | "o1-mini" + | "o1-mini-2024-09-12" + | "gpt-4o" + | "gpt-4o-2024-11-20" + | "gpt-4o-2024-08-06" + | "gpt-4o-2024-05-13" + | "gpt-audio-mini" + | "gpt-audio-mini-2025-12-15" + | "gpt-4o-audio-preview" + | "gpt-4o-audio-preview-2024-10-01" + | "gpt-4o-audio-preview-2024-12-17" + | "gpt-4o-audio-preview-2025-06-03" + | "gpt-4o-mini-audio-preview" + | "gpt-4o-mini-audio-preview-2024-12-17" + | "gpt-4o-search-preview" + | "gpt-4o-mini-search-preview" + | "gpt-4o-search-preview-2025-03-11" + | "gpt-4o-mini-search-preview-2025-03-11" + | "chatgpt-4o-latest" + | "codex-mini-latest" + | "gpt-4o-mini" + | "gpt-4o-mini-2024-07-18" + | "gpt-4-turbo" + | "gpt-4-turbo-2024-04-09" + | "gpt-4-0125-preview" + | "gpt-4-turbo-preview" + | "gpt-4-1106-preview" + | "gpt-4-vision-preview" + | "gpt-4" + | "gpt-4-0314" + | "gpt-4-0613" + | "gpt-4-32k" + | "gpt-4-32k-0314" + | "gpt-4-32k-0613" + | "gpt-3.5-turbo" + | "gpt-3.5-turbo-16k" + | "gpt-3.5-turbo-0301" + | "gpt-3.5-turbo-0613" + | "gpt-3.5-turbo-1106" + | "gpt-3.5-turbo-0125" + | "gpt-3.5-turbo-16k-0613" +export const ModelIdsShared = Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-6-astra", + "gpt-6.1-sol", + "gpt-6-sol", + "gpt-6-luna", + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", + "gpt-5.5", + "gpt-5.5-2026-04-23", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.4-mini-2026-03-17", + "gpt-5.4-nano-2026-03-17", + "gpt-5.3-chat-latest", + "gpt-5.2", + "gpt-5.2-2025-12-11", + "gpt-5.2-chat-latest", + "gpt-5.2-pro", + "gpt-5.2-pro-2025-12-11", + "gpt-5.1", + "gpt-5.1-2025-11-13", + "gpt-5.1-codex", + "gpt-5.1-mini", + "gpt-5.1-chat-latest", + "gpt-5", + "gpt-5-mini", + "gpt-5-nano", + "gpt-5-2025-08-07", + "gpt-5-mini-2025-08-07", + "gpt-5-nano-2025-08-07", + "gpt-5-chat-latest", + "gpt-4.1", + "gpt-4.1-mini", + "gpt-4.1-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "o4-mini", + "o4-mini-2025-04-16", + "o3", + "o3-2025-04-16", + "o3-mini", + "o3-mini-2025-01-31", + "o1", + "o1-2024-12-17", + "o1-preview", + "o1-preview-2024-09-12", + "o1-mini", + "o1-mini-2024-09-12", + "gpt-4o", + "gpt-4o-2024-11-20", + "gpt-4o-2024-08-06", + "gpt-4o-2024-05-13", + "gpt-audio-mini", + "gpt-audio-mini-2025-12-15", + "gpt-4o-audio-preview", + "gpt-4o-audio-preview-2024-10-01", + "gpt-4o-audio-preview-2024-12-17", + "gpt-4o-audio-preview-2025-06-03", + "gpt-4o-mini-audio-preview", + "gpt-4o-mini-audio-preview-2024-12-17", + "gpt-4o-search-preview", + "gpt-4o-mini-search-preview", + "gpt-4o-search-preview-2025-03-11", + "gpt-4o-mini-search-preview-2025-03-11", + "chatgpt-4o-latest", + "codex-mini-latest", + "gpt-4o-mini", + "gpt-4o-mini-2024-07-18", + "gpt-4-turbo", + "gpt-4-turbo-2024-04-09", + "gpt-4-0125-preview", + "gpt-4-turbo-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-4", + "gpt-4-0314", + "gpt-4-0613", + "gpt-4-32k", + "gpt-4-32k-0314", + "gpt-4-32k-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k", + "gpt-3.5-turbo-0301", + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo-1106", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-16k-0613" + ]) +]).annotate({ "identifier": "ModelIdsShared" }) +export type ResponseModalities = ReadonlyArray<"text" | "audio"> | null +export const ResponseModalities = Schema.Union([ + Schema.Array(Schema.Literals(["text", "audio"])).annotate({ "description": - "Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for all embedding models), cannot be an empty string, and any array must be 2048 dimensions or less. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. In addition to the per-input token limit, all embedding models enforce a maximum of 300,000 tokens summed across all inputs in a single request.\n" + "Output types that you would like the model to generate.\nMost models are capable of generating text, which is the default:\n\n`[\"text\"]`\n\nThe `gpt-4o-audio-preview` model can also be used to\n[generate audio](https://developers.openai.com/api/docs/guides/audio). To request that this model generate\nboth text and audio responses, you can use:\n\n`[\"text\", \"audio\"]`\n" }), - "model": Schema.Union([ - Schema.String, - Schema.Literals(["text-embedding-ada-002", "text-embedding-3-small", "text-embedding-3-large"]) - ]).annotate({ + Schema.Null +]).annotate({ "identifier": "ResponseModalities" }) +export type Verbosity = "low" | "medium" | "high" | null +export const Verbosity = Schema.Union([ + Schema.Literals(["low", "medium", "high"]).annotate({ "description": - "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models) for descriptions of them.\n" + "Constrains the verbosity of the model's response. Lower values will result in\nmore concise responses, while higher values will result in more verbose responses.\nCurrently supported values are `low`, `medium`, and `high`. The default is\n`medium`.\n" }), - "encoding_format": Schema.optionalKey( - Schema.Literals(["float", "base64"]).annotate({ + Schema.Null +]).annotate({ "identifier": "Verbosity" }) +export type WebSearchLocation = { + readonly "country"?: string + readonly "region"?: string + readonly "city"?: string + readonly "timezone"?: string +} +export const WebSearchLocation = Schema.Struct({ + "country": Schema.optionalKey( + Schema.String.annotate({ "description": - "The format to return the embeddings in. Can be either `float` or [`base64`](https://pypi.org/project/pybase64/)." + "The two-letter \n[ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user,\ne.g. `US`.\n" }) ), - "dimensions": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)) + "region": Schema.optionalKey( + Schema.String.annotate({ "description": "Free text input for the region of the user, e.g. `California`.\n" }) ), - "user": Schema.optionalKey( + "city": Schema.optionalKey( + Schema.String.annotate({ "description": "Free text input for the city of the user, e.g. `San Francisco`.\n" }) + ), + "timezone": Schema.optionalKey( Schema.String.annotate({ "description": - "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices#end-user-ids).\n" + "The [IANA timezone](https://timeapi.io/documentation/iana-timezones) \nof the user, e.g. `America/Los_Angeles`.\n" }) ) +}).annotate({ + "title": "Web search location", + "description": "Approximate location parameters for the search.", + "identifier": "WebSearchLocation" }) -export type CreateFineTuningCheckpointPermissionRequest = { readonly "project_ids": ReadonlyArray } -export const CreateFineTuningCheckpointPermissionRequest = Schema.Struct({ - "project_ids": Schema.Array(Schema.String).annotate({ "description": "The project identifiers to grant access to." }) +export type WebSearchContextSize = "low" | "medium" | "high" +export const WebSearchContextSize = Schema.Literals(["low", "medium", "high"]).annotate({ + "description": + "High level guidance for the amount of context window space to use for the \nsearch. One of `low`, `medium`, or `high`. `medium` is the default.\n", + "identifier": "WebSearchContextSize" }) -export type CreateGroupBody = { readonly "name": string } -export const CreateGroupBody = Schema.Struct({ - "name": Schema.String.annotate({ "description": "Human readable name for the group." }).check(Schema.isMinLength(1)) - .check(Schema.isMaxLength(255)) -}).annotate({ "description": "Request payload for creating a new group in the organization." }) -export type CreateGroupUserBody = { readonly "user_id": string } -export const CreateGroupUserBody = Schema.Struct({ - "user_id": Schema.String.annotate({ "description": "Identifier of the user to add to the group." }) -}).annotate({ "description": "Request payload for adding a user to a group." }) -export type CreateImageVariationRequest = { - readonly "image": string - readonly "model"?: string | "dall-e-2" | null - readonly "n"?: number - readonly "response_format"?: "url" | "b64_json" | null - readonly "size"?: "256x256" | "512x512" | "1024x1024" | null - readonly "user"?: string +export type ModerationMode = "score" | "block" +export const ModerationMode = Schema.Literals(["score", "block"]).annotate({ "identifier": "ModerationMode" }) +export type StopConfiguration = string | ReadonlyArray | null +export const StopConfiguration = Schema.Union([ + Schema.String, + Schema.Array(Schema.String).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxLength(4).annotate({ "expected": "a value with a length of at most 4" })), + Schema.Null +], { mode: "oneOf" }).annotate({ + "description": + "Not supported with latest reasoning models `o3` and `o4-mini`.\n\nUp to 4 sequences where the API will stop generating further tokens. The\nreturned text will not contain the stop sequence.\n", + "identifier": "StopConfiguration" +}) +export type ChatCompletionStreamOptions = { + readonly "include_usage"?: boolean + readonly "include_obfuscation"?: boolean +} | null +export const ChatCompletionStreamOptions = Schema.Union([ + Schema.Struct({ + "include_usage": Schema.optionalKey(Schema.Boolean.annotate({ + "description": + "If set, an additional chunk will be streamed before the `data: [DONE]`\nmessage. The `usage` field on this chunk shows the token usage statistics\nfor the entire request, and the `choices` field will always be an empty\narray.\n\nAll other chunks will also include a `usage` field, but with a null\nvalue. **NOTE:** If the stream is interrupted, you may not receive the\nfinal usage chunk which contains the total token usage for the request.\n" + })), + "include_obfuscation": Schema.optionalKey(Schema.Boolean.annotate({ + "description": + "When true, stream obfuscation will be enabled. Stream obfuscation adds\nrandom characters to an `obfuscation` field on streaming delta events to\nnormalize payload sizes as a mitigation to certain side-channel attacks.\nThese obfuscation fields are included by default, but add a small amount\nof overhead to the data stream. You can set `include_obfuscation` to\nfalse to optimize for bandwidth if you trust the network links between\nyour application and the OpenAI API.\n" + })) + }).annotate({ "description": "Options for streaming response. Only set this when you set `stream: true`.\n" }), + Schema.Null +]).annotate({ "identifier": "ChatCompletionStreamOptions" }) +export type CustomToolChatCompletions = { + readonly "type": "custom" + readonly "custom": { + readonly "name": string + readonly "description"?: string + readonly "format"?: { readonly "type": "text" } | { + readonly "type": "grammar" + readonly "grammar": { readonly "definition": string; readonly "syntax": "lark" | "regex" } + } + } } -export const CreateImageVariationRequest = Schema.Struct({ - "image": Schema.String.annotate({ - "description": - "The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square.", - "format": "binary" - }), - "model": Schema.optionalKey( - Schema.Union([ - Schema.Union([Schema.String, Schema.Literal("dall-e-2")]).annotate({ - "description": "The model to use for image generation. Only `dall-e-2` is supported at this time." - }), - Schema.Null - ]) - ), - "n": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(10)], { - "description": "The number of images to generate. Must be between 1 and 10." - }) - ) - ]) - ), - "response_format": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["url", "b64_json"]).annotate({ - "description": - "The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated." - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated." +export const CustomToolChatCompletions = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "The type of the custom tool. Always `custom`." }), + "custom": Schema.Struct({ + "name": Schema.String.annotate({ + "description": "The name of the custom tool, used to identify it in tool calls." + }), + "description": Schema.optionalKey( + Schema.String.annotate({ + "description": "Optional description of the custom tool, used to provide more context.\n" }) - ]) - ), - "size": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["256x256", "512x512", "1024x1024"]).annotate({ - "description": "The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`." - }), - Schema.Union([Schema.Null]).annotate({ - "description": "The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`." + ), + "format": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "Unconstrained text format. Always `text`." }) + }).annotate({ "title": "Text format", "description": "Unconstrained free-form text." }), + Schema.Struct({ + "type": Schema.Literal("grammar").annotate({ "description": "Grammar format. Always `grammar`." }), + "grammar": Schema.Struct({ + "definition": Schema.String.annotate({ "description": "The grammar definition." }), + "syntax": Schema.Literals(["lark", "regex"]).annotate({ + "description": "The syntax of the grammar definition. One of `lark` or `regex`." + }) + }).annotate({ "title": "Grammar format", "description": "Your chosen grammar." }) + }).annotate({ "title": "Grammar format", "description": "A grammar defined by the user." }) + ], { mode: "oneOf" }).annotate({ + "description": "The input format for the custom tool. Default is unconstrained text.\n" }) - ]) - ), - "user": Schema.optionalKey( - Schema.String.annotate({ - "description": - "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices#end-user-ids).\n" - }) - ) + ) + }).annotate({ "title": "Custom tool properties", "description": "Properties of the custom tool.\n" }) +}).annotate({ + "title": "Custom tool", + "description": "A custom tool that processes input using a specified format.\n", + "identifier": "CustomToolChatCompletions" }) -export type CreateModerationRequest = { - readonly "input": - | string - | ReadonlyArray - | ReadonlyArray< - { readonly "type": "image_url"; readonly "image_url": { readonly "url": string } } | { - readonly "type": "text" - readonly "text": string - } - > - readonly "model"?: - | string - | "omni-moderation-latest" - | "omni-moderation-2024-09-26" - | "text-moderation-latest" - | "text-moderation-stable" +export type ChatCompletionAllowedTools = { + readonly "mode": "auto" | "required" + readonly "tools": ReadonlyArray<{ readonly [x: string]: Schema.Json }> } -export const CreateModerationRequest = Schema.Struct({ - "input": Schema.Union([ - Schema.String.annotate({ "description": "A string of text to classify for moderation." }), - Schema.Array(Schema.String).annotate({ "description": "An array of strings to classify for moderation." }), - Schema.Array(Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("image_url").annotate({ "description": "Always `image_url`." }), - "image_url": Schema.Struct({ - "url": Schema.String.annotate({ - "description": "Either a URL of the image or the base64 encoded image data.", - "format": "uri" - }) - }).annotate({ "description": "Contains either an image URL or a data URL for a base64 encoded image." }) - }).annotate({ "description": "An object describing an image to classify." }), - Schema.Struct({ - "type": Schema.Literal("text").annotate({ "description": "Always `text`." }), - "text": Schema.String.annotate({ "description": "A string of text to classify." }) - }).annotate({ "description": "An object describing text to classify." }) - ], { mode: "oneOf" })).annotate({ "description": "An array of multi-modal inputs to the moderation model." }) - ], { mode: "oneOf" }).annotate({ +export const ChatCompletionAllowedTools = Schema.Struct({ + "mode": Schema.Literals(["auto", "required"]).annotate({ "description": - "Input (or inputs) to classify. Can be a single string, an array of strings, or\nan array of multi-modal input objects similar to other models.\n" + "Constrains the tools available to the model to a pre-defined set.\n\n`auto` allows the model to pick from among the allowed tools and generate a\nmessage.\n\n`required` requires the model to call one or more of the allowed tools.\n" }), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "omni-moderation-latest", - "omni-moderation-2024-09-26", - "text-moderation-latest", - "text-moderation-stable" - ]) - ]).annotate({ - "description": - "The content moderation model you would like to use. Learn more in\n[the moderation guide](/docs/guides/moderation), and learn about\navailable models [here](/docs/models#moderation).\n" + "tools": Schema.Array( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A tool definition that the model should be allowed to call.\n" }) - ) + ).annotate({ + "description": + "A list of tool definitions that the model should be allowed to call.\n\nFor the Chat Completions API, the list of tool definitions might look like:\n```json\n[\n { \"type\": \"function\", \"function\": { \"name\": \"get_weather\" } },\n { \"type\": \"function\", \"function\": { \"name\": \"get_time\" } }\n]\n```\n" + }) +}).annotate({ + "title": "Allowed tools", + "description": "Constrains the tools available to the model to a pre-defined set.\n", + "identifier": "ChatCompletionAllowedTools" }) -export type CreateModerationResponse = { +export type ChatCompletionNamedToolChoice = { + readonly "type": "function" + readonly "function": { readonly "name": string } +} +export const ChatCompletionNamedToolChoice = Schema.Struct({ + "type": Schema.Literal("function").annotate({ + "description": "For function calling, the type is always `function`." + }), + "function": Schema.Struct({ "name": Schema.String.annotate({ "description": "The name of the function to call." }) }) +}).annotate({ + "title": "Function tool choice", + "description": "Specifies a tool the model should use. Use to force the model to call a specific function.", + "identifier": "ChatCompletionNamedToolChoice" +}) +export type ChatCompletionNamedToolChoiceCustom = { + readonly "type": "custom" + readonly "custom": { readonly "name": string } +} +export const ChatCompletionNamedToolChoiceCustom = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "For custom tool calling, the type is always `custom`." }), + "custom": Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the custom tool to call." }) + }) +}).annotate({ + "title": "Custom tool choice", + "description": "Specifies a tool the model should use. Use to force the model to call a specific custom tool.", + "identifier": "ChatCompletionNamedToolChoiceCustom" +}) +export type ParallelToolCalls = boolean +export const ParallelToolCalls = Schema.Boolean.annotate({ + "description": + "Whether to enable [parallel function calling](https://developers.openai.com/api/docs/guides/function-calling#parallel-function-calling) during tool use.", + "identifier": "ParallelToolCalls" +}) +export type ChatCompletionFunctionCallOption = { readonly "name": string } +export const ChatCompletionFunctionCallOption = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the function to call." }) +}).annotate({ + "description": + "Specifying a particular function via `{\"name\": \"my_function\"}` forces the model to call that function.\n", + "identifier": "ChatCompletionFunctionCallOption" +}) +export type ChatCompletionMessageToolCallChunk = { + readonly "index": number + readonly "id"?: string + readonly "type"?: "function" + readonly "function"?: { readonly "name"?: string; readonly "arguments"?: string } +} +export const ChatCompletionMessageToolCallChunk = Schema.Struct({ + "index": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the tool call." })), + "type": Schema.optionalKey( + Schema.Literal("function").annotate({ + "description": "The type of the tool. Currently, only `function` is supported." + }) + ), + "function": Schema.optionalKey(Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function to call." })), + "arguments": Schema.optionalKey(Schema.String.annotate({ + "description": + "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." + })) + })) +}).annotate({ "identifier": "ChatCompletionMessageToolCallChunk" }) +export type ChatCompletionDeleted = { + readonly "object": "chat.completion.deleted" readonly "id": string - readonly "model": string - readonly "results": ReadonlyArray< + readonly "deleted": boolean +} +export const ChatCompletionDeleted = Schema.Struct({ + "object": Schema.Literal("chat.completion.deleted").annotate({ "description": "The type of object being deleted." }), + "id": Schema.String.annotate({ "description": "The ID of the chat completion that was deleted." }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the chat completion was deleted." }) +}).annotate({ "identifier": "ChatCompletionDeleted" }) +export type ChatCompletionMessageList = { + readonly "object": "list" + readonly "data": ReadonlyArray< { - readonly "flagged": boolean - readonly "categories": { - readonly "hate": boolean - readonly "hate/threatening": boolean - readonly "harassment": boolean - readonly "harassment/threatening": boolean - readonly "illicit": boolean | null - readonly "illicit/violent": boolean | null - readonly "self-harm": boolean - readonly "self-harm/intent": boolean - readonly "self-harm/instructions": boolean - readonly "sexual": boolean - readonly "sexual/minors": boolean - readonly "violence": boolean - readonly "violence/graphic": boolean - } - readonly "category_scores": { - readonly "hate": number - readonly "hate/threatening": number - readonly "harassment": number - readonly "harassment/threatening": number - readonly "illicit": number - readonly "illicit/violent": number - readonly "self-harm": number - readonly "self-harm/intent": number - readonly "self-harm/instructions": number - readonly "sexual": number - readonly "sexual/minors": number - readonly "violence": number - readonly "violence/graphic": number - } - readonly "category_applied_input_types": { - readonly "hate": ReadonlyArray<"text"> - readonly "hate/threatening": ReadonlyArray<"text"> - readonly "harassment": ReadonlyArray<"text"> - readonly "harassment/threatening": ReadonlyArray<"text"> - readonly "illicit": ReadonlyArray<"text"> - readonly "illicit/violent": ReadonlyArray<"text"> - readonly "self-harm": ReadonlyArray<"text" | "image"> - readonly "self-harm/intent": ReadonlyArray<"text" | "image"> - readonly "self-harm/instructions": ReadonlyArray<"text" | "image"> - readonly "sexual": ReadonlyArray<"text" | "image"> - readonly "sexual/minors": ReadonlyArray<"text"> - readonly "violence": ReadonlyArray<"text" | "image"> - readonly "violence/graphic": ReadonlyArray<"text" | "image"> - } + readonly "id": string + readonly "role": "user" | "assistant" | "tool" | "system" | "function" | "developer" + readonly "content": string | null + readonly "content_parts": + | ReadonlyArray< + { + readonly "type": "text" | "image_url" | "input_audio" | "file" + readonly "text"?: string | null + readonly "image_url"?: { readonly "url": string; readonly "detail"?: string | null } | null + readonly "input_audio"?: { readonly "data": string; readonly "format": string } | null + readonly "file"?: { + readonly "file_data"?: string | null + readonly "filename"?: string | null + readonly "file_id"?: string | null + } | null + } + > + | null + readonly "name"?: string | null } > + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean } -export const CreateModerationResponse = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique identifier for the moderation request." }), - "model": Schema.String.annotate({ "description": "The model used to generate the moderation results." }), - "results": Schema.Array(Schema.Struct({ - "flagged": Schema.Boolean.annotate({ "description": "Whether any of the below categories are flagged." }), - "categories": Schema.Struct({ - "hate": Schema.Boolean.annotate({ - "description": - "Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harassment." - }), - "hate/threatening": Schema.Boolean.annotate({ - "description": - "Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste." - }), - "harassment": Schema.Boolean.annotate({ - "description": "Content that expresses, incites, or promotes harassing language towards any target." - }), - "harassment/threatening": Schema.Boolean.annotate({ - "description": "Harassment content that also includes violence or serious harm towards any target." - }), - "illicit": Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Content that includes instructions or advice that facilitate the planning or execution of wrongdoing, or that gives advice or instruction on how to commit illicit acts. For example, \"how to shoplift\" would fit this category." - }), - Schema.Null - ]), - "illicit/violent": Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Content that includes instructions or advice that facilitate the planning or execution of wrongdoing that also includes violence, or that gives advice or instruction on the procurement of any weapon." - }), - Schema.Null - ]), - "self-harm": Schema.Boolean.annotate({ - "description": - "Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders." - }), - "self-harm/intent": Schema.Boolean.annotate({ - "description": - "Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders." - }), - "self-harm/instructions": Schema.Boolean.annotate({ - "description": - "Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts." - }), - "sexual": Schema.Boolean.annotate({ - "description": - "Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness)." - }), - "sexual/minors": Schema.Boolean.annotate({ - "description": "Sexual content that includes an individual who is under 18 years old." - }), - "violence": Schema.Boolean.annotate({ - "description": "Content that depicts death, violence, or physical injury." - }), - "violence/graphic": Schema.Boolean.annotate({ - "description": "Content that depicts death, violence, or physical injury in graphic detail." - }) - }).annotate({ "description": "A list of the categories, and whether they are flagged or not." }), - "category_scores": Schema.Struct({ - "hate": Schema.Number.annotate({ "description": "The score for the category 'hate'." }).check(Schema.isFinite()), - "hate/threatening": Schema.Number.annotate({ "description": "The score for the category 'hate/threatening'." }) - .check(Schema.isFinite()), - "harassment": Schema.Number.annotate({ "description": "The score for the category 'harassment'." }).check( - Schema.isFinite() - ), - "harassment/threatening": Schema.Number.annotate({ - "description": "The score for the category 'harassment/threatening'." - }).check(Schema.isFinite()), - "illicit": Schema.Number.annotate({ "description": "The score for the category 'illicit'." }).check( - Schema.isFinite() - ), - "illicit/violent": Schema.Number.annotate({ "description": "The score for the category 'illicit/violent'." }) - .check(Schema.isFinite()), - "self-harm": Schema.Number.annotate({ "description": "The score for the category 'self-harm'." }).check( - Schema.isFinite() - ), - "self-harm/intent": Schema.Number.annotate({ "description": "The score for the category 'self-harm/intent'." }) - .check(Schema.isFinite()), - "self-harm/instructions": Schema.Number.annotate({ - "description": "The score for the category 'self-harm/instructions'." - }).check(Schema.isFinite()), - "sexual": Schema.Number.annotate({ "description": "The score for the category 'sexual'." }).check( - Schema.isFinite() - ), - "sexual/minors": Schema.Number.annotate({ "description": "The score for the category 'sexual/minors'." }).check( - Schema.isFinite() - ), - "violence": Schema.Number.annotate({ "description": "The score for the category 'violence'." }).check( - Schema.isFinite() - ), - "violence/graphic": Schema.Number.annotate({ "description": "The score for the category 'violence/graphic'." }) - .check(Schema.isFinite()) - }).annotate({ "description": "A list of the categories along with their scores as predicted by model." }), - "category_applied_input_types": Schema.Struct({ - "hate": Schema.Array(Schema.Literal("text")).annotate({ - "description": "The applied input type(s) for the category 'hate'." - }), - "hate/threatening": Schema.Array(Schema.Literal("text")).annotate({ - "description": "The applied input type(s) for the category 'hate/threatening'." - }), - "harassment": Schema.Array(Schema.Literal("text")).annotate({ - "description": "The applied input type(s) for the category 'harassment'." - }), - "harassment/threatening": Schema.Array(Schema.Literal("text")).annotate({ - "description": "The applied input type(s) for the category 'harassment/threatening'." - }), - "illicit": Schema.Array(Schema.Literal("text")).annotate({ - "description": "The applied input type(s) for the category 'illicit'." - }), - "illicit/violent": Schema.Array(Schema.Literal("text")).annotate({ - "description": "The applied input type(s) for the category 'illicit/violent'." - }), - "self-harm": Schema.Array(Schema.Literals(["text", "image"])).annotate({ - "description": "The applied input type(s) for the category 'self-harm'." - }), - "self-harm/intent": Schema.Array(Schema.Literals(["text", "image"])).annotate({ - "description": "The applied input type(s) for the category 'self-harm/intent'." - }), - "self-harm/instructions": Schema.Array(Schema.Literals(["text", "image"])).annotate({ - "description": "The applied input type(s) for the category 'self-harm/instructions'." - }), - "sexual": Schema.Array(Schema.Literals(["text", "image"])).annotate({ - "description": "The applied input type(s) for the category 'sexual'." - }), - "sexual/minors": Schema.Array(Schema.Literal("text")).annotate({ - "description": "The applied input type(s) for the category 'sexual/minors'." - }), - "violence": Schema.Array(Schema.Literals(["text", "image"])).annotate({ - "description": "The applied input type(s) for the category 'violence'." - }), - "violence/graphic": Schema.Array(Schema.Literals(["text", "image"])).annotate({ - "description": "The applied input type(s) for the category 'violence/graphic'." - }) - }).annotate({ "description": "A list of the categories along with the input type(s) that the score applies to." }) - })).annotate({ "description": "A list of moderation objects." }) -}).annotate({ "description": "Represents if a given text input is potentially harmful." }) -export type CreateTranscriptionResponseJson = { - readonly "text": string - readonly "logprobs"?: ReadonlyArray< - { readonly "token"?: string; readonly "logprob"?: number; readonly "bytes"?: ReadonlyArray } - > - readonly "usage"?: { - readonly "type": "tokens" - readonly "input_tokens": number - readonly "input_token_details"?: { readonly "text_tokens"?: number; readonly "audio_tokens"?: number } - readonly "output_tokens": number - readonly "total_tokens": number - } | { readonly "type": "duration"; readonly "seconds": number } +export const ChatCompletionMessageList = Schema.Struct({ + "object": Schema.Literal("list").annotate({ + "description": "The type of this object. It is always set to \"list\".\n" + }), + "data": Schema.Array(Schema.Struct({ + "id": Schema.String, + "role": Schema.Literals(["user", "assistant", "tool", "system", "function", "developer"]), + "content": Schema.Union([Schema.String, Schema.Null]), + "content_parts": Schema.Union([ + Schema.Array(Schema.Struct({ + "type": Schema.Literals(["text", "image_url", "input_audio", "file"]), + "text": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "image_url": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ + "url": Schema.String, + "detail": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])) + }), + Schema.Null + ]) + ), + "input_audio": Schema.optionalKey( + Schema.Union([Schema.Struct({ "data": Schema.String, "format": Schema.String }), Schema.Null]) + ), + "file": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ + "file_data": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "filename": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "file_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])) + }), + Schema.Null + ]) + ) + })), + Schema.Null + ]), + "name": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])) + })).annotate({ "description": "An array of chat completion message objects.\n" }), + "first_id": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The identifier of the first chat message in the data array." + }), + "last_id": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The identifier of the last chat message in the data array." + }), + "has_more": Schema.Boolean.annotate({ "description": "Indicates whether there are more chat messages available." }) +}).annotate({ + "title": "ChatCompletionMessageList", + "description": "An object representing a list of chat completion messages.\n", + "identifier": "ChatCompletionMessageList" +}) +export type ContainerResource = { + readonly "id": string + readonly "object": string + readonly "name": string + readonly "created_at": number + readonly "status": string + readonly "last_active_at"?: number + readonly "expires_after"?: { readonly "anchor"?: "last_active_at"; readonly "minutes"?: number } + readonly "memory_limit"?: "1g" | "4g" | "16g" | "64g" + readonly "network_policy"?: { + readonly "type": "allowlist" | "disabled" + readonly "allowed_domains"?: ReadonlyArray + } } -export const CreateTranscriptionResponseJson = Schema.Struct({ - "text": Schema.String.annotate({ "description": "The transcribed text." }), - "logprobs": Schema.optionalKey( - Schema.Array(Schema.Struct({ - "token": Schema.optionalKey(Schema.String.annotate({ "description": "The token in the transcription." })), - "logprob": Schema.optionalKey( - Schema.Number.annotate({ "description": "The log probability of the token." }).check(Schema.isFinite()) +export const ContainerResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Unique identifier for the container." }), + "object": Schema.String.annotate({ "description": "The type of this object." }), + "name": Schema.String.annotate({ "description": "Name of the container." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the container was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "status": Schema.String.annotate({ "description": "Status of the container (e.g., active, deleted)." }), + "last_active_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the container was last active.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "expires_after": Schema.optionalKey( + Schema.Struct({ + "anchor": Schema.optionalKey( + Schema.Literal("last_active_at").annotate({ "description": "The reference point for the expiration." }) ), - "bytes": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isFinite())).annotate({ "description": "The bytes of the token." }) + "minutes": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The number of minutes after the anchor before the container expires." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ) - })).annotate({ + }).annotate({ "description": - "The log probabilities of the tokens in the transcription. Only returned with the models `gpt-4o-transcribe` and `gpt-4o-mini-transcribe` if `logprobs` is added to the `include` array.\n" + "The container will expire after this time period.\nThe anchor is the reference point for the expiration.\nThe minutes is the number of minutes after the anchor before the container expires.\n" + }) + ), + "memory_limit": Schema.optionalKey( + Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ + "description": "The memory limit configured for the container." }) ), - "usage": Schema.optionalKey(Schema.Union([ + "network_policy": Schema.optionalKey( Schema.Struct({ - "type": Schema.Literal("tokens").annotate({ - "description": "The type of the usage object. Always `tokens` for this variant." - }), - "input_tokens": Schema.Number.annotate({ "description": "Number of input tokens billed for this request." }) - .check(Schema.isInt()), - "input_token_details": Schema.optionalKey( - Schema.Struct({ - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of text tokens billed for this request." }).check( - Schema.isInt() - ) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of audio tokens billed for this request." }).check( - Schema.isInt() - ) - ) - }).annotate({ "description": "Details about the input tokens billed for this request." }) - ), - "output_tokens": Schema.Number.annotate({ "description": "Number of output tokens generated." }).check( - Schema.isInt() - ), - "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (input + output)." }).check( - Schema.isInt() + "type": Schema.Literals(["allowlist", "disabled"]).annotate({ "description": "The network policy mode." }), + "allowed_domains": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ "description": "Allowed outbound domains when `type` is `allowlist`." }) ) - }).annotate({ "title": "Token Usage", "description": "Token usage statistics for the request." }), - Schema.Struct({ - "type": Schema.Literal("duration").annotate({ - "description": "The type of the usage object. Always `duration` for this variant." - }), - "seconds": Schema.Number.annotate({ - "description": "Duration of the input audio in seconds.", - "format": "double" - }).check(Schema.isFinite()) - }).annotate({ "title": "Duration Usage", "description": "Token usage statistics for the request." }) - ], { mode: "oneOf" })) -}).annotate({ "description": "Represents a transcription response returned by model, based on the provided input." }) -export type CreateTranslationRequest = { - readonly "file": string - readonly "model": string | "whisper-1" - readonly "prompt"?: string - readonly "response_format"?: "json" | "text" | "srt" | "verbose_json" | "vtt" - readonly "temperature"?: number + }).annotate({ "description": "Network access policy for the container." }) + ) +}).annotate({ "title": "The container object", "identifier": "ContainerResource" }) +export type SkillReferenceParam = { + readonly "type": "skill_reference" + readonly "skill_id": string + readonly "version"?: string } -export const CreateTranslationRequest = Schema.Struct({ - "file": Schema.String.annotate({ - "description": - "The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.\n", - "format": "binary" - }), - "model": Schema.Union([Schema.String, Schema.Literal("whisper-1")]).annotate({ - "description": - "ID of the model to use. Only `whisper-1` (which is powered by our open source Whisper V2 model) is currently available.\n" +export const SkillReferenceParam = Schema.Struct({ + "type": Schema.Literal("skill_reference").annotate({ + "description": "References a skill created with the /v1/skills endpoint." }), - "prompt": Schema.optionalKey( + "skill_id": Schema.String.annotate({ "description": "The ID of the referenced skill." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "version": Schema.optionalKey( Schema.String.annotate({ - "description": - "An optional text to guide the model's style or continue a previous audio segment. The [prompt](/docs/guides/speech-to-text#prompting) should be in English.\n" - }) - ), - "response_format": Schema.optionalKey( - Schema.Literals(["json", "text", "srt", "verbose_json", "vtt"]).annotate({ - "description": - "The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`.\n" + "description": "Optional skill version. Use a positive integer or 'latest'. Omit for default." }) - ), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit.\n" - }).check(Schema.isFinite()) ) -}) -export type CreateTranslationResponseJson = { readonly "text": string } -export const CreateTranslationResponseJson = Schema.Struct({ "text": Schema.String }) -export type CreateVoiceConsentRequest = { - readonly "name": string - readonly "recording": string - readonly "language": string -} -export const CreateVoiceConsentRequest = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The label to use for this consent recording." }), - "recording": Schema.String.annotate({ - "description": - "The consent audio recording file. Maximum size is 10 MiB.\n\nSupported MIME types:\n`audio/mpeg`, `audio/wav`, `audio/x-wav`, `audio/ogg`, `audio/aac`, `audio/flac`, `audio/webm`, `audio/mp4`.\n", - "format": "binary" - }), - "language": Schema.String.annotate({ - "description": "The BCP 47 language tag for the consent phrase (for example, `en-US`)." - }) -}) -export type CreateVoiceRequest = { - readonly "name": string - readonly "audio_sample": string - readonly "consent": string -} -export const CreateVoiceRequest = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the new voice." }), - "audio_sample": Schema.String.annotate({ - "description": - "The sample audio recording file. Maximum size is 10 MiB.\n\nSupported MIME types:\n`audio/mpeg`, `audio/wav`, `audio/x-wav`, `audio/ogg`, `audio/aac`, `audio/flac`, `audio/webm`, `audio/mp4`.\n", - "format": "binary" - }), - "consent": Schema.String.annotate({ "description": "The consent recording ID (for example, `cons_1234`)." }) -}) -export type CustomToolCall = { - readonly "type": "custom_tool_call" - readonly "id"?: string - readonly "call_id": string - readonly "namespace"?: string +}).annotate({ "identifier": "SkillReferenceParam" }) +export type InlineSkillSourceParam = { + readonly "type": "base64" + readonly "media_type": "application/zip" + readonly "data": string +} +export const InlineSkillSourceParam = Schema.Struct({ + "type": Schema.Literal("base64").annotate({ + "description": "The type of the inline skill source. Must be `base64`." + }), + "media_type": Schema.Literal("application/zip").annotate({ + "description": "The media type of the inline skill payload. Must be `application/zip`." + }), + "data": Schema.String.annotate({ "description": "Base64-encoded skill zip bundle." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(70254592).annotate({ "expected": "a string with at most 70254592 code points" })) +}).annotate({ "description": "Inline skill payload", "identifier": "InlineSkillSourceParam" }) +export type ContainerNetworkPolicyDisabledParam = { readonly "type": "disabled" } +export const ContainerNetworkPolicyDisabledParam = Schema.Struct({ + "type": Schema.Literal("disabled").annotate({ "description": "Disable outbound network access. Always `disabled`." }) +}).annotate({ "identifier": "ContainerNetworkPolicyDisabledParam" }) +export type ContainerNetworkPolicyDomainSecretParam = { + readonly "domain": string readonly "name": string - readonly "input": string + readonly "value": string } -export const CustomToolCall = Schema.Struct({ - "type": Schema.Literal("custom_tool_call").annotate({ - "description": "The type of the custom tool call. Always `custom_tool_call`.\n" - }), - "id": Schema.optionalKey( - Schema.String.annotate({ "description": "The unique ID of the custom tool call in the OpenAI platform.\n" }) +export const ContainerNetworkPolicyDomainSecretParam = Schema.Struct({ + "domain": Schema.String.annotate({ "description": "The domain associated with the secret." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) ), - "call_id": Schema.String.annotate({ - "description": "An identifier used to map this custom tool call to a tool call output.\n" - }), - "namespace": Schema.optionalKey( - Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) + "name": Schema.String.annotate({ "description": "The name of the secret to inject for the domain." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) ), - "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), - "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model.\n" }) -}).annotate({ "title": "Custom tool call", "description": "A call to a custom tool created by the model.\n" }) -export type CustomToolCallResource = { - readonly "type": "custom_tool_call" + "value": Schema.String.annotate({ "description": "The secret value to inject for the domain." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" })) +}).annotate({ "identifier": "ContainerNetworkPolicyDomainSecretParam" }) +export type ContainerFileResource = { readonly "id": string - readonly "call_id": string - readonly "namespace"?: string - readonly "name": string - readonly "input": string - readonly "status": "in_progress" | "completed" | "incomplete" - readonly "created_by"?: string + readonly "object": string + readonly "container_id": string + readonly "created_at": number + readonly "bytes": number + readonly "path": string + readonly "source": string } -export const CustomToolCallResource = Schema.Struct({ - "type": Schema.Literal("custom_tool_call").annotate({ - "description": "The type of the custom tool call. Always `custom_tool_call`.\n" - }), - "id": Schema.String.annotate({ "description": "The unique ID of the custom tool call item.\n" }), - "call_id": Schema.String.annotate({ - "description": "An identifier used to map this custom tool call to a tool call output.\n" - }), - "namespace": Schema.optionalKey( - Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) +export const ContainerFileResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Unique identifier for the file." }), + "object": Schema.String.annotate({ "description": "The type of this object (`container.file`)." }), + "container_id": Schema.String.annotate({ "description": "The container this file belongs to." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the file was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "bytes": Schema.Number.annotate({ "description": "Size of the file in bytes." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), - "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model.\n" }), - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + "path": Schema.String.annotate({ "description": "Path of the file in the container." }), + "source": Schema.String.annotate({ "description": "Source of the file (e.g., `user`, `assistant`)." }) +}).annotate({ "title": "The container file object", "identifier": "ContainerFileResource" }) +export type CreateContainerFileBody = { readonly "file_id"?: string; readonly "file"?: string } +export const CreateContainerFileBody = Schema.Struct({ + "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "Name of the file to create." })), + "file": Schema.optionalKey( + Schema.String.annotate({ "description": "The File object (not file name) to be uploaded.\n", "format": "binary" }) ) -}).annotate({ "title": "Custom tool call", "description": "A call to a custom tool created by the model.\n" }) -export type CustomToolChatCompletions = { - readonly "type": "custom" - readonly "custom": { - readonly "name": string - readonly "description"?: string - readonly "format"?: { readonly "type": "text" } | { - readonly "type": "grammar" - readonly "grammar": { readonly "definition": string; readonly "syntax": "lark" | "regex" } - } - } -} -export const CustomToolChatCompletions = Schema.Struct({ - "type": Schema.Literal("custom").annotate({ "description": "The type of the custom tool. Always `custom`." }), - "custom": Schema.Struct({ - "name": Schema.String.annotate({ - "description": "The name of the custom tool, used to identify it in tool calls." - }), - "description": Schema.optionalKey( - Schema.String.annotate({ - "description": "Optional description of the custom tool, used to provide more context.\n" - }) - ), - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("text").annotate({ "description": "Unconstrained text format. Always `text`." }) - }).annotate({ "title": "Text format", "description": "Unconstrained free-form text." }), - Schema.Struct({ - "type": Schema.Literal("grammar").annotate({ "description": "Grammar format. Always `grammar`." }), - "grammar": Schema.Struct({ - "definition": Schema.String.annotate({ "description": "The grammar definition." }), - "syntax": Schema.Literals(["lark", "regex"]).annotate({ - "description": "The syntax of the grammar definition. One of `lark` or `regex`." - }) - }).annotate({ "title": "Grammar format", "description": "Your chosen grammar." }) - }).annotate({ "title": "Grammar format", "description": "A grammar defined by the user." }) - ], { mode: "oneOf" }).annotate({ - "description": "The input format for the custom tool. Default is unconstrained text.\n" - }) - ) - }).annotate({ "title": "Custom tool properties", "description": "Properties of the custom tool.\n" }) -}).annotate({ "title": "Custom tool", "description": "A custom tool that processes input using a specified format.\n" }) -export type DeleteAssistantResponse = { - readonly "id": string - readonly "deleted": boolean - readonly "object": "assistant.deleted" -} -export const DeleteAssistantResponse = Schema.Struct({ - "id": Schema.String, - "deleted": Schema.Boolean, - "object": Schema.Literal("assistant.deleted") +}).annotate({ "identifier": "CreateContainerFileBody" }) +export type IncludeEnum = + | "file_search_call.results" + | "web_search_call.results" + | "web_search_call.action.sources" + | "message.input_image.image_url" + | "computer_call_output.output.image_url" + | "code_interpreter_call.outputs" + | "reasoning.encrypted_content" + | "message.output_text.logprobs" +export const IncludeEnum = Schema.Literals([ + "file_search_call.results", + "web_search_call.results", + "web_search_call.action.sources", + "message.input_image.image_url", + "computer_call_output.output.image_url", + "code_interpreter_call.outputs", + "reasoning.encrypted_content", + "message.output_text.logprobs" +]).annotate({ + "description": + "Specify additional output data to include in the model response. Currently supported values are:\n- `web_search_call.results`: Include the search results of the web search tool call.\n- `web_search_call.action.sources`: Include the sources of the web search tool call.\n- `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items.\n- `computer_call_output.output.image_url`: Include image urls from the computer call output.\n- `file_search_call.results`: Include the search results of the file search tool call.\n- `message.input_image.image_url`: Include image urls from the input message.\n- `message.output_text.logprobs`: Include logprobs with assistant messages.\n- `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program).", + "identifier": "IncludeEnum" }) -export type DeleteCertificateResponse = { readonly "object": "certificate.deleted"; readonly "id": string } -export const DeleteCertificateResponse = Schema.Struct({ - "object": Schema.Literal("certificate.deleted").annotate({ - "description": "The object type, must be `certificate.deleted`." - }), - "id": Schema.String.annotate({ "description": "The ID of the certificate that was deleted." }) +export type MessageStatus = "in_progress" | "completed" | "incomplete" +export const MessageStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "MessageStatus" }) -export type DeleteFileResponse = { readonly "id": string; readonly "object": "file"; readonly "deleted": boolean } -export const DeleteFileResponse = Schema.Struct({ - "id": Schema.String, - "object": Schema.Literal("file"), - "deleted": Schema.Boolean +export type MessageRole = + | "unknown" + | "user" + | "assistant" + | "system" + | "critic" + | "discriminator" + | "developer" + | "tool" +export const MessageRole = Schema.Literals([ + "unknown", + "user", + "assistant", + "system", + "critic", + "discriminator", + "developer", + "tool" +]).annotate({ "identifier": "MessageRole" }) +export type PromptCacheBreakpointConfig = { readonly "mode": "explicit" } +export const PromptCacheBreakpointConfig = Schema.Struct({ + "mode": Schema.Literal("explicit").annotate({ "description": "The breakpoint mode. Always `explicit`." }) +}).annotate({ + "title": "Prompt cache breakpoint", + "description": + "Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.", + "identifier": "PromptCacheBreakpointConfig" }) -export type DeleteFineTuningCheckpointPermissionResponse = { - readonly "id": string - readonly "object": "checkpoint.permission" - readonly "deleted": boolean +export type FileCitationBody = { + readonly "type": "file_citation" + readonly "file_id": string + readonly "index": number + readonly "filename": string } -export const DeleteFineTuningCheckpointPermissionResponse = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The ID of the fine-tuned model checkpoint permission that was deleted." +export const FileCitationBody = Schema.Struct({ + "type": Schema.Literal("file_citation").annotate({ + "description": "The type of the file citation. Always `file_citation`." }), - "object": Schema.Literal("checkpoint.permission").annotate({ - "description": "The object type, which is always \"checkpoint.permission\"." + "file_id": Schema.String.annotate({ "description": "The ID of the file." }), + "index": Schema.Number.annotate({ + "description": "The index in the output text at which to insert the file citation." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "filename": Schema.String.annotate({ "description": "The filename of the file cited." }) +}).annotate({ "title": "File citation", "description": "A citation to a file.", "identifier": "FileCitationBody" }) +export type UrlCitationBody = { + readonly "type": "url_citation" + readonly "url": string + readonly "start_index": number + readonly "end_index": number + readonly "title": string +} +export const UrlCitationBody = Schema.Struct({ + "type": Schema.Literal("url_citation").annotate({ + "description": "The type of the URL citation. Always `url_citation`." }), - "deleted": Schema.Boolean.annotate({ - "description": "Whether the fine-tuned model checkpoint permission was successfully deleted." - }) + "url": Schema.String.annotate({ "description": "The URL of the web resource.", "format": "uri" }), + "start_index": Schema.Number.annotate({ + "description": "The index of the first character of the URL citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_index": Schema.Number.annotate({ + "description": "The index of the last character of the URL citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "title": Schema.String.annotate({ "description": "The title of the web resource." }) +}).annotate({ + "title": "URL citation", + "description": "A citation for a web resource used to generate a model response.", + "identifier": "UrlCitationBody" }) -export type DeleteMessageResponse = { - readonly "id": string - readonly "deleted": boolean - readonly "object": "thread.message.deleted" -} -export const DeleteMessageResponse = Schema.Struct({ - "id": Schema.String, - "deleted": Schema.Boolean, - "object": Schema.Literal("thread.message.deleted") -}) -export type DeleteModelResponse = { readonly "id": string; readonly "deleted": boolean; readonly "object": string } -export const DeleteModelResponse = Schema.Struct({ - "id": Schema.String, - "deleted": Schema.Boolean, - "object": Schema.String -}) -export type DeleteThreadResponse = { - readonly "id": string - readonly "deleted": boolean - readonly "object": "thread.deleted" +export type ContainerFileCitationBody = { + readonly "type": "container_file_citation" + readonly "container_id": string + readonly "file_id": string + readonly "start_index": number + readonly "end_index": number + readonly "filename": string } -export const DeleteThreadResponse = Schema.Struct({ - "id": Schema.String, - "deleted": Schema.Boolean, - "object": Schema.Literal("thread.deleted") +export const ContainerFileCitationBody = Schema.Struct({ + "type": Schema.Literal("container_file_citation").annotate({ + "description": "The type of the container file citation. Always `container_file_citation`." + }), + "container_id": Schema.String.annotate({ "description": "The ID of the container file." }), + "file_id": Schema.String.annotate({ "description": "The ID of the file." }), + "start_index": Schema.Number.annotate({ + "description": "The index of the first character of the container file citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_index": Schema.Number.annotate({ + "description": "The index of the last character of the container file citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "filename": Schema.String.annotate({ "description": "The filename of the container file cited." }) +}).annotate({ + "title": "Container file citation", + "description": "A citation for a container file used to generate a model response.", + "identifier": "ContainerFileCitationBody" }) -export type DeleteVectorStoreFileResponse = { - readonly "id": string - readonly "deleted": boolean - readonly "object": "vector_store.file.deleted" +export type FilePath = { readonly "type": "file_path"; readonly "file_id": string; readonly "index": number } +export const FilePath = Schema.Struct({ + "type": Schema.Literal("file_path").annotate({ "description": "The type of the file path. Always `file_path`.\n" }), + "file_id": Schema.String.annotate({ "description": "The ID of the file.\n" }), + "index": Schema.Number.annotate({ "description": "The index of the file in the list of files.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ "title": "File path", "description": "A path to a file.\n", "identifier": "FilePath" }) +export type TopLogProb = { + readonly "token": string + readonly "logprob": number + readonly "bytes": ReadonlyArray } -export const DeleteVectorStoreFileResponse = Schema.Struct({ - "id": Schema.String, - "deleted": Schema.Boolean, - "object": Schema.Literal("vector_store.file.deleted") +export const TopLogProb = Schema.Struct({ + "token": Schema.String, + "logprob": Schema.Finite, + "bytes": Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))) +}).annotate({ + "title": "Top log probability", + "description": "The top log probability of a token.", + "identifier": "TopLogProb" }) -export type DeleteVectorStoreResponse = { - readonly "id": string - readonly "deleted": boolean - readonly "object": "vector_store.deleted" -} -export const DeleteVectorStoreResponse = Schema.Struct({ - "id": Schema.String, - "deleted": Schema.Boolean, - "object": Schema.Literal("vector_store.deleted") +export type TextContent = { readonly "type": "text"; readonly "text": string } +export const TextContent = Schema.Struct({ "type": Schema.Literal("text"), "text": Schema.String }).annotate({ + "title": "Text Content", + "description": "A text content.", + "identifier": "TextContent" }) -export type DeletedRoleAssignmentResource = { readonly "object": string; readonly "deleted": boolean } -export const DeletedRoleAssignmentResource = Schema.Struct({ - "object": Schema.String.annotate({ - "description": "Identifier for the deleted assignment, such as `group.role.deleted` or `user.role.deleted`." +export type SummaryTextContent = { readonly "type": "summary_text"; readonly "text": string } +export const SummaryTextContent = Schema.Struct({ + "type": Schema.Literal("summary_text").annotate({ "description": "The type of the object. Always `summary_text`." }), + "text": Schema.String.annotate({ "description": "A summary of the reasoning output from the model so far." }) +}).annotate({ + "title": "Summary text", + "description": "A summary text from the model.", + "identifier": "SummaryTextContent" +}) +export type ReasoningTextContent = { readonly "type": "reasoning_text"; readonly "text": string } +export const ReasoningTextContent = Schema.Struct({ + "type": Schema.Literal("reasoning_text").annotate({ + "description": "The type of the reasoning text. Always `reasoning_text`." }), - "deleted": Schema.Boolean.annotate({ "description": "Whether the assignment was removed." }) -}).annotate({ "description": "Confirmation payload returned after unassigning a role." }) -export type DoneEvent = { readonly "event": "done"; readonly "data": "[DONE]" } -export const DoneEvent = Schema.Struct({ "event": Schema.Literal("done"), "data": Schema.Literal("[DONE]") }).annotate({ - "description": "Occurs when a stream ends." + "text": Schema.String.annotate({ "description": "The reasoning text from the model." }) +}).annotate({ + "title": "Reasoning text", + "description": "Reasoning text from the model.", + "identifier": "ReasoningTextContent" }) -export type Embedding = { - readonly "index": number - readonly "embedding": ReadonlyArray - readonly "object": "embedding" -} -export const Embedding = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the embedding in the list of embeddings." }).check( - Schema.isInt() - ), - "embedding": Schema.Array(Schema.Number.annotate({ "format": "float" }).check(Schema.isFinite())).annotate({ +export type RefusalContent = { readonly "type": "refusal"; readonly "refusal": string } +export const RefusalContent = Schema.Struct({ + "type": Schema.Literal("refusal").annotate({ "description": "The type of the refusal. Always `refusal`." }), + "refusal": Schema.String.annotate({ "description": "The refusal explanation from the model." }) +}).annotate({ "title": "Refusal", "description": "A refusal from the model.", "identifier": "RefusalContent" }) +export type ImageDetail = "low" | "high" | "auto" | "original" +export const ImageDetail = Schema.Literals(["low", "high", "auto", "original"]).annotate({ + "identifier": "ImageDetail" +}) +export type FileInputDetail = "auto" | "low" | "high" +export const FileInputDetail = Schema.Literals(["auto", "low", "high"]).annotate({ "identifier": "FileInputDetail" }) +export type MessagePhase_2 = "commentary" | "final_answer" +export const MessagePhase_2 = Schema.Literals(["commentary", "final_answer"]).annotate({ + "identifier": "MessagePhase-2" +}) +export type DirectToolCallCaller = { readonly "type": "direct" } +export const DirectToolCallCaller = Schema.Struct({ "type": Schema.Literal("direct") }).annotate({ + "identifier": "DirectToolCallCaller" +}) +export type ProgramToolCallCaller = { readonly "type": "program"; readonly "caller_id": string } +export const ProgramToolCallCaller = Schema.Struct({ + "type": Schema.Literal("program"), + "caller_id": Schema.String.annotate({ + "description": "The call ID of the program item that produced this tool call." + }) +}).annotate({ "identifier": "ProgramToolCallCaller" }) +export type DirectToolCallCallerParam = { readonly "type": "direct" } +export const DirectToolCallCallerParam = Schema.Struct({ + "type": Schema.Literal("direct").annotate({ "description": "The caller type. Always `direct`." }) +}).annotate({ "identifier": "DirectToolCallCallerParam" }) +export type ProgramToolCallCallerParam = { readonly "type": "program"; readonly "caller_id": string } +export const ProgramToolCallCallerParam = Schema.Struct({ + "type": Schema.Literal("program").annotate({ "description": "The caller type. Always `program`." }), + "caller_id": Schema.String.annotate({ + "description": "The call ID of the program item that produced this tool call." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ) +}).annotate({ "identifier": "ProgramToolCallCallerParam" }) +export type VectorStoreFileAttributes = { readonly [x: string]: string | number | boolean } | null +export const VectorStoreFileAttributes = Schema.Union([ + Schema.Record( + Schema.String, + Schema.Union([ + Schema.String.check( + Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" }) + ), + Schema.Finite, + Schema.Boolean + ], { mode: "oneOf" }) + ).annotate({ "description": - "The embedding vector, which is a list of floats. The length of vector depends on the model as listed in the [embedding guide](/docs/guides/embeddings).\n" - }), - "object": Schema.Literal("embedding").annotate({ "description": "The object type, which is always \"embedding\"." }) -}).annotate({ "description": "Represents an embedding vector returned by embedding endpoint.\n" }) -export type Error = { - readonly "code": string | null - readonly "message": string - readonly "param": string | null - readonly "type": string + "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard. Keys are strings\nwith a maximum length of 64 characters. Values are strings with a maximum\nlength of 512 characters, booleans, or numbers.\n" + }).check(Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null +]).annotate({ "identifier": "VectorStoreFileAttributes" }) +export type WebSearchCallStatus = "in_progress" | "searching" | "completed" | "failed" | "incomplete" +export const WebSearchCallStatus = Schema.Literals(["in_progress", "searching", "completed", "failed", "incomplete"]) + .annotate({ "identifier": "WebSearchCallStatus" }) +export type WebSearchActionSearch = { + readonly "type": "search" + readonly "query"?: string + readonly "queries"?: ReadonlyArray + readonly "sources"?: ReadonlyArray< + { readonly "type": "url"; readonly "url": string } | { readonly "type": "api"; readonly "name": string } + > } -export const Error = Schema.Struct({ - "code": Schema.Union([Schema.String, Schema.Null]), - "message": Schema.String, - "param": Schema.Union([Schema.String, Schema.Null]), - "type": Schema.String +export const WebSearchActionSearch = Schema.Struct({ + "type": Schema.Literal("search").annotate({ "description": "The action type.\n" }), + "query": Schema.optionalKey(Schema.String.annotate({ "description": "The search query.\n" })), + "queries": Schema.optionalKey( + Schema.Array(Schema.String.annotate({ "description": "A search query.\n" })).annotate({ + "title": "Search queries", + "description": "The search queries.\n" + }) + ), + "sources": Schema.optionalKey( + Schema.Array( + Schema.Union([ + Schema.Struct({ + "type": Schema.Literal("url").annotate({ "description": "The type of source. Always `url`.\n" }), + "url": Schema.String.annotate({ "description": "The URL of the source.\n", "format": "uri" }) + }).annotate({ "title": "Web search source", "description": "A source used in the search.\n" }), + Schema.Struct({ + "type": Schema.Literal("api").annotate({ "description": "The type of source. Always `api`.\n" }), + "name": Schema.String.annotate({ + "description": "The name of the API source, such as `oai-weather`, `oai-sports`, or `oai-finance`.\n" + }) + }).annotate({ "title": "Web search API source", "description": "An API source used in the search.\n" }) + ]) + ).annotate({ "title": "Web search sources", "description": "The sources used in the search.\n" }) + ) +}).annotate({ + "title": "Search action", + "description": "Action type \"search\" - Performs a web search query.\n", + "identifier": "WebSearchActionSearch" }) -export type EvalApiError = { readonly "code": string; readonly "message": string } -export const EvalApiError = Schema.Struct({ - "code": Schema.String.annotate({ "description": "The error code." }), - "message": Schema.String.annotate({ "description": "The error message." }) -}).annotate({ "title": "EvalApiError", "description": "An object representing an error response from the Eval API.\n" }) -export type EvalGraderPython = { - readonly "type": "python" - readonly "name": string - readonly "source": string - readonly "image_tag"?: string - readonly "pass_threshold"?: number +export type WebSearchActionOpenPage = { readonly "type": "open_page"; readonly "url"?: string | null } +export const WebSearchActionOpenPage = Schema.Struct({ + "type": Schema.Literal("open_page").annotate({ "description": "The action type.\n" }), + "url": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "format": "uri" }), Schema.Null]).annotate({ + "description": "The URL opened by the model.\n" + }) + ) +}).annotate({ + "title": "Open page action", + "description": "Action type \"open_page\" - Opens a specific URL from search results.\n", + "identifier": "WebSearchActionOpenPage" +}) +export type WebSearchActionFind = { + readonly "type": "find_in_page" + readonly "url"?: string + readonly "pattern"?: string } -export const EvalGraderPython = Schema.Struct({ - "type": Schema.Literal("python").annotate({ "description": "The object type, which is always `python`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "source": Schema.String.annotate({ "description": "The source code of the python script." }), - "image_tag": Schema.optionalKey( - Schema.String.annotate({ "description": "The image tag to use for the python script." }) +export const WebSearchActionFind = Schema.Struct({ + "type": Schema.Literal("find_in_page").annotate({ "description": "The action type.\n" }), + "url": Schema.optionalKey( + Schema.String.annotate({ "description": "The URL of the page searched for the pattern.\n", "format": "uri" }) ), - "pass_threshold": Schema.optionalKey( - Schema.Number.annotate({ "description": "The threshold for the score." }).check(Schema.isFinite()) + "pattern": Schema.optionalKey( + Schema.String.annotate({ "description": "The pattern or text to search for within the page.\n" }) ) }).annotate({ - "title": "PythonGrader", - "description": "A PythonGrader object that runs a python script on the input.\n" + "title": "Find action", + "description": "Action type \"find_in_page\": Searches for a pattern within a loaded page.\n", + "identifier": "WebSearchActionFind" }) -export type EvalGraderStringCheck = { - readonly "type": "string_check" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "operation": "eq" | "ne" | "like" | "ilike" +export type ImageGenActionEnum = "generate" | "edit" | "auto" +export const ImageGenActionEnum = Schema.Literals(["generate", "edit", "auto"]).annotate({ + "identifier": "ImageGenActionEnum" +}) +export type ImageBackground = "transparent" | "opaque" | "auto" +export const ImageBackground = Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "identifier": "ImageBackground" +}) +export type ImageOutputFormat = "png" | "webp" | "jpeg" +export const ImageOutputFormat = Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "identifier": "ImageOutputFormat" +}) +export type ClickButtonType = "left" | "right" | "wheel" | "back" | "forward" +export const ClickButtonType = Schema.Literals(["left", "right", "wheel", "back", "forward"]).annotate({ + "identifier": "ClickButtonType" +}) +export type DoubleClickAction = { + readonly "type": "double_click" + readonly "x": number + readonly "y": number + readonly "keys": ReadonlyArray | null } -export const EvalGraderStringCheck = Schema.Struct({ - "type": Schema.Literal("string_check").annotate({ - "description": "The object type, which is always `string_check`." +export const DoubleClickAction = Schema.Struct({ + "type": Schema.Literal("double_click").annotate({ + "description": "Specifies the event type. For a double click action, this property is always set to `double_click`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The input text. This may include template strings." }), - "reference": Schema.String.annotate({ "description": "The reference text. This may include template strings." }), - "operation": Schema.Literals(["eq", "ne", "like", "ilike"]).annotate({ - "description": "The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`." - }) + "x": Schema.Number.annotate({ "description": "The x-coordinate where the double click occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "y": Schema.Number.annotate({ "description": "The y-coordinate where the double click occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "keys": Schema.Union([ + Schema.Array(Schema.String).annotate({ "description": "The keys being held while double-clicking." }), + Schema.Null + ]) +}).annotate({ "title": "DoubleClick", "description": "A double click action.", "identifier": "DoubleClickAction" }) +export type CoordParam = { readonly "x": number; readonly "y": number } +export const CoordParam = Schema.Struct({ + "x": Schema.Number.annotate({ "description": "The x-coordinate." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "y": Schema.Number.annotate({ "description": "The y-coordinate." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) }).annotate({ - "title": "StringCheckGrader", - "description": - "A StringCheckGrader object that performs a string comparison between input and reference using a specified operation.\n" + "title": "Coordinate", + "description": "An x/y coordinate pair, e.g. `{ x: 100, y: 200 }`.", + "identifier": "CoordParam" }) -export type EvalGraderTextSimilarity = { - readonly "type": "text_similarity" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "evaluation_metric": - | "cosine" - | "fuzzy_match" - | "bleu" - | "gleu" - | "meteor" - | "rouge_1" - | "rouge_2" - | "rouge_3" - | "rouge_4" - | "rouge_5" - | "rouge_l" - readonly "pass_threshold": number -} -export const EvalGraderTextSimilarity = Schema.Struct({ - "type": Schema.Literal("text_similarity").annotate({ "description": "The type of grader." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The text being graded." }), - "reference": Schema.String.annotate({ "description": "The text being graded against." }), - "evaluation_metric": Schema.Literals([ - "cosine", - "fuzzy_match", - "bleu", - "gleu", - "meteor", - "rouge_1", - "rouge_2", - "rouge_3", - "rouge_4", - "rouge_5", - "rouge_l" - ]).annotate({ - "description": - "The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, \n`gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, \nor `rouge_l`.\n" +export type KeyPressAction = { readonly "type": "keypress"; readonly "keys": ReadonlyArray } +export const KeyPressAction = Schema.Struct({ + "type": Schema.Literal("keypress").annotate({ + "description": "Specifies the event type. For a keypress action, this property is always set to `keypress`." }), - "pass_threshold": Schema.Number.annotate({ "description": "The threshold for the score." }).check(Schema.isFinite()) + "keys": Schema.Array( + Schema.String.annotate({ "description": "One of the keys the model is requesting to be pressed." }) + ).annotate({ + "description": + "The combination of keys the model is requesting to be pressed. This is an array of strings, each representing a key." + }) }).annotate({ - "title": "TextSimilarityGrader", - "description": "A TextSimilarityGrader object which grades text based on similarity metrics.\n" + "title": "KeyPress", + "description": "A collection of keypresses the model would like to perform.", + "identifier": "KeyPressAction" }) -export type EvalItemContentOutputText = { readonly "type": "output_text"; readonly "text": string } -export const EvalItemContentOutputText = Schema.Struct({ - "type": Schema.Literal("output_text").annotate({ - "description": "The type of the output text. Always `output_text`.\n" - }), - "text": Schema.String.annotate({ "description": "The text output from the model.\n" }) -}).annotate({ "title": "Output text", "description": "A text output from the model.\n" }) -export type EvalItemContentText = string -export const EvalItemContentText = Schema.String.annotate({ - "title": "Text input", - "description": "A text input to the model.\n" -}) -export type EvalItemInputImage = { - readonly "type": "input_image" - readonly "image_url": string - readonly "detail"?: string -} -export const EvalItemInputImage = Schema.Struct({ - "type": Schema.Literal("input_image").annotate({ - "description": "The type of the image input. Always `input_image`.\n" - }), - "image_url": Schema.String.annotate({ "description": "The URL of the image input.\n", "format": "uri" }), - "detail": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`.\n" - }) - ) -}).annotate({ "title": "Input image", "description": "An image input block used within EvalItem content arrays." }) -export type EvalJsonlFileContentSource = { - readonly "type": "file_content" - readonly "content": ReadonlyArray<{ readonly "item": {}; readonly "sample"?: {} }> +export type MoveParam = { + readonly "type": "move" + readonly "x": number + readonly "y": number + readonly "keys"?: ReadonlyArray | null } -export const EvalJsonlFileContentSource = Schema.Struct({ - "type": Schema.Literal("file_content").annotate({ - "description": "The type of jsonl source. Always `file_content`." +export const MoveParam = Schema.Struct({ + "type": Schema.Literal("move").annotate({ + "description": "Specifies the event type. For a move action, this property is always set to `move`." }), - "content": Schema.Array(Schema.Struct({ "item": Schema.Struct({}), "sample": Schema.optionalKey(Schema.Struct({})) })) - .annotate({ "description": "The content of the jsonl file." }) -}).annotate({ "title": "EvalJsonlFileContentSource" }) -export type EvalJsonlFileIdSource = { readonly "type": "file_id"; readonly "id": string } -export const EvalJsonlFileIdSource = Schema.Struct({ - "type": Schema.Literal("file_id").annotate({ "description": "The type of jsonl source. Always `file_id`." }), - "id": Schema.String.annotate({ "description": "The identifier of the file." }) -}).annotate({ "title": "EvalJsonlFileIdSource" }) -export type EvalResponsesSource = { - readonly "type": "responses" - readonly "metadata"?: {} | null - readonly "model"?: string | null - readonly "instructions_search"?: string | null - readonly "created_after"?: number | null - readonly "created_before"?: number | null - readonly "reasoning_effort"?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | null | null - readonly "temperature"?: number | null - readonly "top_p"?: number | null - readonly "users"?: ReadonlyArray | null - readonly "tools"?: ReadonlyArray | null -} -export const EvalResponsesSource = Schema.Struct({ - "type": Schema.Literal("responses").annotate({ "description": "The type of run data source. Always `responses`." }), - "metadata": Schema.optionalKey( - Schema.Union([ - Schema.Struct({}).annotate({ - "description": "Metadata filter for the responses. This is a query parameter used to select responses." - }), - Schema.Null - ]) - ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The name of the model to find responses for. This is a query parameter used to select responses." - }), - Schema.Null - ]) - ), - "instructions_search": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "Optional string to search the 'instructions' field. This is a query parameter used to select responses." - }), - Schema.Null - ]) + "x": Schema.Number.annotate({ "description": "The x-coordinate to move to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "created_after": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "Only include items created after this timestamp (inclusive). This is a query parameter used to select responses." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), - Schema.Null - ]) + "y": Schema.Number.annotate({ "description": "The y-coordinate to move to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "created_before": Schema.optionalKey( + "keys": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ - "description": - "Only include items created before this timestamp (inclusive). This is a query parameter used to select responses." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), + Schema.Array(Schema.String).annotate({ "description": "The keys being held while moving the mouse." }), Schema.Null ]) + ) +}).annotate({ "title": "Move", "description": "A mouse move action.", "identifier": "MoveParam" }) +export type ScreenshotParam = { readonly "type": "screenshot" } +export const ScreenshotParam = Schema.Struct({ + "type": Schema.Literal("screenshot").annotate({ + "description": "Specifies the event type. For a screenshot action, this property is always set to `screenshot`." + }) +}).annotate({ "title": "Screenshot", "description": "A screenshot action.", "identifier": "ScreenshotParam" }) +export type ScrollParam = { + readonly "type": "scroll" + readonly "x": number + readonly "y": number + readonly "scroll_x": number + readonly "scroll_y": number + readonly "keys"?: ReadonlyArray | null +} +export const ScrollParam = Schema.Struct({ + "type": Schema.Literal("scroll").annotate({ + "description": "Specifies the event type. For a scroll action, this property is always set to `scroll`." + }), + "x": Schema.Number.annotate({ "description": "The x-coordinate where the scroll occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "reasoning_effort": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.Literals(["none", "minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": - "Constrains effort on reasoning for\n[reasoning models](https://platform.openai.com/docs/guides/reasoning).\nCurrently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing\nreasoning effort can result in faster responses and fewer tokens used\non reasoning in a response.\n\n- `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1.\n- All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`.\n- The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort.\n- `xhigh` is supported for all models after `gpt-5.1-codex-max`.\n" - }), - Schema.Null - ]).annotate({ - "description": "Optional reasoning effort parameter. This is a query parameter used to select responses." - }), - Schema.Null - ]) + "y": Schema.Number.annotate({ "description": "The y-coordinate where the scroll occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "Sampling temperature. This is a query parameter used to select responses." - }).check(Schema.isFinite()), - Schema.Null - ]) + "scroll_x": Schema.Number.annotate({ "description": "The horizontal scroll distance." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "top_p": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "Nucleus sampling parameter. This is a query parameter used to select responses." - }).check(Schema.isFinite()), - Schema.Null - ]) + "scroll_y": Schema.Number.annotate({ "description": "The vertical scroll distance." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "users": Schema.optionalKey( + "keys": Schema.optionalKey( Schema.Union([ - Schema.Array(Schema.String).annotate({ - "description": "List of user identifiers. This is a query parameter used to select responses." - }), + Schema.Array(Schema.String).annotate({ "description": "The keys being held while scrolling." }), Schema.Null ]) + ) +}).annotate({ "title": "Scroll", "description": "A scroll action.", "identifier": "ScrollParam" }) +export type TypeParam = { readonly "type": "type"; readonly "text": string } +export const TypeParam = Schema.Struct({ + "type": Schema.Literal("type").annotate({ + "description": "Specifies the event type. For a type action, this property is always set to `type`." + }), + "text": Schema.String.annotate({ "description": "The text to type." }) +}).annotate({ "title": "Type", "description": "An action to type in text.", "identifier": "TypeParam" }) +export type WaitParam = { readonly "type": "wait" } +export const WaitParam = Schema.Struct({ + "type": Schema.Literal("wait").annotate({ + "description": "Specifies the event type. For a wait action, this property is always set to `wait`." + }) +}).annotate({ "title": "Wait", "description": "A wait action.", "identifier": "WaitParam" }) +export type ComputerCallSafetyCheckParam = { + readonly "id": string + readonly "code"?: string | null + readonly "message"?: string | null +} +export const ComputerCallSafetyCheckParam = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the pending safety check." }), + "code": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The type of the pending safety check." }), Schema.Null]) ), - "tools": Schema.optionalKey( - Schema.Union([ - Schema.Array(Schema.String).annotate({ - "description": "List of tool names. This is a query parameter used to select responses." - }), - Schema.Null - ]) + "message": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Details about the pending safety check." }), Schema.Null]) ) }).annotate({ - "title": "EvalResponsesSource", - "description": "A EvalResponsesSource object describing a run data source configuration.\n" + "description": "A pending safety check for the computer call.", + "identifier": "ComputerCallSafetyCheckParam" }) -export type EvalRunOutputItemResult = { - readonly "name": string - readonly "type"?: string - readonly "score": number - readonly "passed": boolean - readonly "sample"?: {} | null +export type ComputerScreenshotImage = { + readonly "type": "computer_screenshot" + readonly "image_url"?: string + readonly "file_id"?: string } -export const EvalRunOutputItemResult = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "type": Schema.optionalKey( - Schema.String.annotate({ "description": "The grader type (for example, \"string-check-grader\")." }) - ), - "score": Schema.Number.annotate({ "description": "The numeric score produced by the grader." }).check( - Schema.isFinite() +export const ComputerScreenshotImage = Schema.Struct({ + "type": Schema.Literal("computer_screenshot").annotate({ + "description": + "Specifies the event type. For a computer screenshot, this property is \nalways set to `computer_screenshot`.\n" + }), + "image_url": Schema.optionalKey( + Schema.String.annotate({ "description": "The URL of the screenshot image.", "format": "uri" }) ), - "passed": Schema.Boolean.annotate({ "description": "Whether the grader considered the output a pass." }), - "sample": Schema.optionalKey( - Schema.Union([Schema.Struct({}), Schema.Null]).annotate({ - "description": "Optional sample or intermediate data produced by the grader." - }) + "file_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of an uploaded file that contains the screenshot." }) ) }).annotate({ - "title": "EvalRunOutputItemResult", - "description": "A single grader result for an evaluation run output item.\n" + "description": "A computer screenshot image used with the computer use tool.\n", + "identifier": "ComputerScreenshotImage" }) -export type FileExpirationAfter = { readonly "anchor": "created_at"; readonly "seconds": number } -export const FileExpirationAfter = Schema.Struct({ - "anchor": Schema.Literal("created_at").annotate({ - "description": "Anchor timestamp after which the expiration policy applies. Supported anchors: `created_at`." - }), - "seconds": Schema.Number.annotate({ +export type ToolSearchExecutionType = "server" | "client" +export const ToolSearchExecutionType = Schema.Literals(["server", "client"]).annotate({ + "identifier": "ToolSearchExecutionType" +}) +export type FunctionCallStatus = "in_progress" | "completed" | "incomplete" +export const FunctionCallStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "FunctionCallStatus" +}) +export type CallableToolAllowedCaller = "direct" | "programmatic" +export const CallableToolAllowedCaller = Schema.Literals(["direct", "programmatic"]).annotate({ + "identifier": "CallableToolAllowedCaller" +}) +export type RankerVersionType = "auto" | "default-2024-11-15" +export const RankerVersionType = Schema.Literals(["auto", "default-2024-11-15"]).annotate({ + "identifier": "RankerVersionType" +}) +export type HybridSearchOptions = { readonly "embedding_weight": number; readonly "text_weight": number } +export const HybridSearchOptions = Schema.Struct({ + "embedding_weight": Schema.Number.annotate({ + "description": "The weight of the embedding in the reciprocal ranking fusion." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "text_weight": Schema.Number.annotate({ "description": "The weight of the text in the reciprocal ranking fusion." }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })) +}).annotate({ "identifier": "HybridSearchOptions" }) +export type ComparisonFilter = { + readonly "type": "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" + readonly "key": string + readonly "value": string | number | boolean | ReadonlyArray +} +export const ComparisonFilter = Schema.Struct({ + "type": Schema.Literals(["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"]).annotate({ "description": - "The number of seconds after the anchor time that the file will expire. Must be between 3600 (1 hour) and 2592000 (30 days).", - "format": "int64" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(3600)).check(Schema.isLessThanOrEqualTo(2592000)) + "Specifies the comparison operator: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`.\n- `eq`: equals\n- `ne`: not equal\n- `gt`: greater than\n- `gte`: greater than or equal\n- `lt`: less than\n- `lte`: less than or equal\n- `in`: in\n- `nin`: not in\n" + }), + "key": Schema.String.annotate({ "description": "The key to compare against the value." }), + "value": Schema.Union([ + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.Array(Schema.Union([Schema.String, Schema.Finite], { mode: "oneOf" })) + ], { mode: "oneOf" }).annotate({ + "description": "The value to compare against the attribute key; supports string, number, or boolean types." + }) }).annotate({ - "title": "File expiration policy", + "title": "Comparison Filter", "description": - "The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted." + "A filter used to compare a specified attribute key to a given value using a defined comparison operation.\n", + "identifier": "ComparisonFilter" }) -export type FilePath = { readonly "type": "file_path"; readonly "file_id": string; readonly "index": number } -export const FilePath = Schema.Struct({ - "type": Schema.Literal("file_path").annotate({ "description": "The type of the file path. Always `file_path`.\n" }), - "file_id": Schema.String.annotate({ "description": "The ID of the file.\n" }), - "index": Schema.Number.annotate({ "description": "The index of the file in the list of files.\n" }).check( - Schema.isInt() - ) -}).annotate({ "title": "File path", "description": "A path to a file.\n" }) -export type FileSearchRanker = "auto" | "default_2024_08_21" -export const FileSearchRanker = Schema.Literals(["auto", "default_2024_08_21"]).annotate({ - "description": "The ranker to use for the file search. If not specified will use the `auto` ranker." +export type ComputerTool = { readonly "type": "computer" } +export const ComputerTool = Schema.Struct({ + "type": Schema.Literal("computer").annotate({ "description": "The type of the computer tool. Always `computer`." }) +}).annotate({ + "title": "Computer", + "description": + "A tool that controls a virtual computer. Learn more about the [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use).", + "identifier": "ComputerTool" }) -export type FineTuneDPOHyperparameters = { - readonly "beta"?: "auto" | number - readonly "batch_size"?: "auto" | number - readonly "learning_rate_multiplier"?: "auto" | number - readonly "n_epochs"?: "auto" | number -} -export const FineTuneDPOHyperparameters = Schema.Struct({ - "beta": Schema.optionalKey( - Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isFinite()).check(Schema.isLessThanOrEqualTo(2)).check(Schema.isGreaterThan(0)) - ], { mode: "oneOf" }).annotate({ - "description": - "The beta value for the DPO method. A higher beta value will increase the weight of the penalty between the policy and reference model.\n" - }) - ), - "batch_size": Schema.optionalKey( - Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(256)) - ], { mode: "oneOf" }).annotate({ - "description": - "Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance.\n" - }) - ), - "learning_rate_multiplier": Schema.optionalKey( - Schema.Union([Schema.Literal("auto"), Schema.Number.check(Schema.isFinite()).check(Schema.isGreaterThan(0))], { - mode: "oneOf" - }).annotate({ - "description": - "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting.\n" - }) +export type ComputerEnvironment = "windows" | "mac" | "linux" | "ubuntu" | "browser" +export const ComputerEnvironment = Schema.Literals(["windows", "mac", "linux", "ubuntu", "browser"]).annotate({ + "identifier": "ComputerEnvironment" +}) +export type WebSearchApproximateLocation = { + readonly "type"?: "approximate" + readonly "country"?: string | null + readonly "region"?: string | null + readonly "city"?: string | null + readonly "timezone"?: string | null +} | null +export const WebSearchApproximateLocation = Schema.Union([ + Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("approximate").annotate({ + "description": "The type of location approximation. Always `approximate`." + }) + ), + "country": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`." + }), + Schema.Null + ]) + ), + "region": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Free text input for the region of the user, e.g. `California`." }), + Schema.Null + ]) + ), + "city": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Free text input for the city of the user, e.g. `San Francisco`." }), + Schema.Null + ]) + ), + "timezone": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`." + }), + Schema.Null + ]) + ) + }).annotate({ "title": "Web search approximate location", "description": "The approximate location of the user.\n" }), + Schema.Null +]).annotate({ "identifier": "WebSearchApproximateLocation" }) +export type MCPToolFilter = { readonly "tool_names"?: ReadonlyArray; readonly "read_only"?: boolean } +export const MCPToolFilter = Schema.Struct({ + "tool_names": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ "title": "MCP allowed tools", "description": "List of allowed tool names." }) ), - "n_epochs": Schema.optionalKey( - Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(50)) - ], { mode: "oneOf" }).annotate({ + "read_only": Schema.optionalKey( + Schema.Boolean.annotate({ "description": - "The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.\n" + "Indicates whether or not a tool modifies data or is read-only. If an\nMCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint),\nit will match this filter.\n" }) ) -}).annotate({ "description": "The hyperparameters used for the DPO fine-tuning job." }) -export type FineTuneReinforcementHyperparameters = { - readonly "batch_size"?: "auto" | number - readonly "learning_rate_multiplier"?: "auto" | number - readonly "n_epochs"?: "auto" | number - readonly "reasoning_effort"?: "default" | "low" | "medium" | "high" - readonly "compute_multiplier"?: "auto" | number - readonly "eval_interval"?: "auto" | number - readonly "eval_samples"?: "auto" | number +}).annotate({ + "title": "MCP tool filter", + "description": "A filter object to specify which tools are allowed.\n", + "identifier": "MCPToolFilter" +}) +export type ContainerMemoryLimit = "1g" | "4g" | "16g" | "64g" +export const ContainerMemoryLimit = Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ + "identifier": "ContainerMemoryLimit" +}) +export type ProgrammaticToolCallingParam = { readonly "type": "programmatic_tool_calling" } +export const ProgrammaticToolCallingParam = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The type of the tool. Always `programmatic_tool_calling`." + }) +}).annotate({ "identifier": "ProgrammaticToolCallingParam" }) +export type InputFidelity = "high" | "low" +export const InputFidelity = Schema.Literals(["high", "low"]).annotate({ + "description": + "Control how much effort the model will exert to match the style and features, especially facial features, of input images. Supports `high` and `low` on `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For `gpt-image-2`, omit this parameter. Defaults to `low` on supported models.", + "identifier": "InputFidelity" +}) +export type LocalShellToolParam = { readonly "type": "local_shell" } +export const LocalShellToolParam = Schema.Struct({ + "type": Schema.Literal("local_shell").annotate({ + "description": "The type of the local shell tool. Always `local_shell`." + }) +}).annotate({ + "title": "Local shell tool", + "description": "A tool that allows the model to execute shell commands in a local environment.", + "identifier": "LocalShellToolParam" +}) +export type LocalSkillParam = { readonly "name": string; readonly "description": string; readonly "path": string } +export const LocalSkillParam = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the skill." }), + "description": Schema.String.annotate({ "description": "The description of the skill." }), + "path": Schema.String.annotate({ "description": "The path to the directory containing the skill." }) +}).annotate({ "identifier": "LocalSkillParam" }) +export type ContainerReferenceParam = { readonly "type": "container_reference"; readonly "container_id": string } +export const ContainerReferenceParam = Schema.Struct({ + "type": Schema.Literal("container_reference").annotate({ + "description": "References a container created with the /v1/containers endpoint" + }), + "container_id": Schema.String.annotate({ "description": "The ID of the referenced container." }) +}).annotate({ "identifier": "ContainerReferenceParam" }) +export type CustomTextFormatParam = { readonly "type": "text" } +export const CustomTextFormatParam = Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "Unconstrained text format. Always `text`." }) +}).annotate({ + "title": "Text format", + "description": "Unconstrained free-form text.", + "identifier": "CustomTextFormatParam" +}) +export type GrammarSyntax1 = "lark" | "regex" +export const GrammarSyntax1 = Schema.Literals(["lark", "regex"]).annotate({ "identifier": "GrammarSyntax1" }) +export type EmptyModelParam = { readonly [x: string]: Schema.Json } +export const EmptyModelParam = Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) + .annotate({ "identifier": "EmptyModelParam" }) +export type ApproximateLocation = { + readonly "type": "approximate" + readonly "country"?: string | null + readonly "region"?: string | null + readonly "city"?: string | null + readonly "timezone"?: string | null } -export const FineTuneReinforcementHyperparameters = Schema.Struct({ - "batch_size": Schema.optionalKey( - Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(256)) - ], { mode: "oneOf" }).annotate({ - "description": - "Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance.\n" - }) - ), - "learning_rate_multiplier": Schema.optionalKey( - Schema.Union([Schema.Literal("auto"), Schema.Number.check(Schema.isFinite()).check(Schema.isGreaterThan(0))], { - mode: "oneOf" - }).annotate({ - "description": - "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting.\n" - }) - ), - "n_epochs": Schema.optionalKey( +export const ApproximateLocation = Schema.Struct({ + "type": Schema.Literal("approximate").annotate({ + "description": "The type of location approximation. Always `approximate`." + }), + "country": Schema.optionalKey( Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(50)) - ], { mode: "oneOf" }).annotate({ - "description": - "The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.\n" - }) - ), - "reasoning_effort": Schema.optionalKey( - Schema.Literals(["default", "low", "medium", "high"]).annotate({ "description": "Level of reasoning effort.\n" }) + Schema.String.annotate({ + "description": + "The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`." + }), + Schema.Null + ]) ), - "compute_multiplier": Schema.optionalKey( + "region": Schema.optionalKey( Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isFinite()).check(Schema.isLessThanOrEqualTo(10)).check(Schema.isGreaterThan(0.00001)) - ], { mode: "oneOf" }).annotate({ - "description": "Multiplier on amount of compute used for exploring search space during training.\n" - }) - ), - "eval_interval": Schema.optionalKey( - Schema.Union( - [Schema.Literal("auto"), Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1))], - { mode: "oneOf" } - ).annotate({ "description": "The number of training steps between evaluation runs.\n" }) + Schema.String.annotate({ "description": "Free text input for the region of the user, e.g. `California`." }), + Schema.Null + ]) ), - "eval_samples": Schema.optionalKey( - Schema.Union( - [Schema.Literal("auto"), Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1))], - { mode: "oneOf" } - ).annotate({ "description": "Number of evaluation samples to generate per training step.\n" }) - ) -}).annotate({ "description": "The hyperparameters used for the reinforcement fine-tuning job." }) -export type FineTuneSupervisedHyperparameters = { - readonly "batch_size"?: "auto" | number - readonly "learning_rate_multiplier"?: "auto" | number - readonly "n_epochs"?: "auto" | number -} -export const FineTuneSupervisedHyperparameters = Schema.Struct({ - "batch_size": Schema.optionalKey( + "city": Schema.optionalKey( Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(256)) - ], { mode: "oneOf" }).annotate({ - "description": - "Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance.\n" - }) - ), - "learning_rate_multiplier": Schema.optionalKey( - Schema.Union([Schema.Literal("auto"), Schema.Number.check(Schema.isFinite()).check(Schema.isGreaterThan(0))], { - mode: "oneOf" - }).annotate({ - "description": - "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting.\n" - }) + Schema.String.annotate({ "description": "Free text input for the city of the user, e.g. `San Francisco`." }), + Schema.Null + ]) ), - "n_epochs": Schema.optionalKey( + "timezone": Schema.optionalKey( Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(50)) - ], { mode: "oneOf" }).annotate({ - "description": - "The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.\n" - }) + Schema.String.annotate({ + "description": + "The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`." + }), + Schema.Null + ]) ) -}).annotate({ "description": "The hyperparameters used for the fine-tuning job." }) -export type FineTuningCheckpointPermission = { +}).annotate({ "identifier": "ApproximateLocation" }) +export type SearchContextSize = "low" | "medium" | "high" +export const SearchContextSize = Schema.Literals(["low", "medium", "high"]).annotate({ + "identifier": "SearchContextSize" +}) +export type SearchContentType = "text" | "image" +export const SearchContentType = Schema.Literals(["text", "image"]).annotate({ "identifier": "SearchContentType" }) +export type FunctionCallOutputStatusEnum = "in_progress" | "completed" | "incomplete" +export const FunctionCallOutputStatusEnum = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "FunctionCallOutputStatusEnum" +}) +export type Program = { + readonly "type": "program" readonly "id": string - readonly "created_at": number - readonly "project_id": string - readonly "object": "checkpoint.permission" + readonly "call_id": string + readonly "code": string + readonly "fingerprint": string +} +export const Program = Schema.Struct({ + "type": Schema.Literal("program").annotate({ "description": "The type of the item. Always `program`." }), + "id": Schema.String.annotate({ "description": "The unique ID of the program item." }), + "call_id": Schema.String.annotate({ "description": "The stable call ID of the program item." }), + "code": Schema.String.annotate({ "description": "The JavaScript source executed by programmatic tool calling." }), + "fingerprint": Schema.String.annotate({ + "description": "Opaque program replay fingerprint that must be round-tripped." + }) +}).annotate({ "identifier": "Program" }) +export type ProgramOutputStatus = "completed" | "incomplete" +export const ProgramOutputStatus = Schema.Literals(["completed", "incomplete"]).annotate({ + "identifier": "ProgramOutputStatus" +}) +export type CompactionBody = { + readonly "type": "compaction" + readonly "id": string + readonly "encrypted_content": string + readonly "created_by"?: string } -export const FineTuningCheckpointPermission = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The permission identifier, which can be referenced in the API endpoints." +export const CompactionBody = Schema.Struct({ + "type": Schema.Literal("compaction").annotate({ "description": "The type of the item. Always `compaction`." }), + "id": Schema.String.annotate({ "description": "The unique ID of the compaction item." }), + "encrypted_content": Schema.String.annotate({ + "description": "The encrypted content that was produced by compaction." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the permission was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "project_id": Schema.String.annotate({ "description": "The project identifier that the permission is for." }), - "object": Schema.Literal("checkpoint.permission").annotate({ - "description": "The object type, which is always \"checkpoint.permission\"." + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ + "title": "Compaction item", + "description": + "A compaction item generated by the [`v1/responses/compact` API](https://developers.openai.com/api/reference/resources/responses/methods/compact).", + "identifier": "CompactionBody" +}) +export type CodeInterpreterOutputLogs = { readonly "type": "logs"; readonly "logs": string } +export const CodeInterpreterOutputLogs = Schema.Struct({ + "type": Schema.Literal("logs").annotate({ "description": "The type of the output. Always `logs`." }), + "logs": Schema.String.annotate({ "description": "The logs output from the code interpreter." }) +}).annotate({ + "title": "Code interpreter output logs", + "description": "The logs output from the code interpreter.", + "identifier": "CodeInterpreterOutputLogs" +}) +export type CodeInterpreterOutputImage = { readonly "type": "image"; readonly "url": string } +export const CodeInterpreterOutputImage = Schema.Struct({ + "type": Schema.Literal("image").annotate({ "description": "The type of the output. Always `image`." }), + "url": Schema.String.annotate({ + "description": "The URL of the image output from the code interpreter.", + "format": "uri" }) }).annotate({ - "title": "FineTuningCheckpointPermission", - "description": "The `checkpoint.permission` object represents a permission for a fine-tuned model checkpoint.\n" + "title": "Code interpreter output image", + "description": "The image output from the code interpreter.", + "identifier": "CodeInterpreterOutputImage" }) -export type FineTuningIntegration = { - readonly "type": "wandb" - readonly "wandb": { - readonly "project": string - readonly "name"?: string | null - readonly "entity"?: string | null - readonly "tags"?: ReadonlyArray - } +export type LocalShellExecAction = { + readonly "type": "exec" + readonly "command": ReadonlyArray + readonly "timeout_ms"?: number | null + readonly "working_directory"?: string | null + readonly "env": { readonly [x: string]: string } + readonly "user"?: string | null } -export const FineTuningIntegration = Schema.Struct({ - "type": Schema.Literal("wandb").annotate({ - "description": "The type of the integration being enabled for the fine-tuning job" - }), - "wandb": Schema.Struct({ - "project": Schema.String.annotate({ - "description": "The name of the project that the new run will be created under.\n" - }), - "name": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "A display name to set for the run. If not set, we will use the Job ID as the name.\n" - }), - Schema.Null - ]) - ), - "entity": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The entity to use for the run. This allows you to set the team or username of the WandB user that you would\nlike associated with the run. If not set, the default entity for the registered WandB API key is used.\n" - }), - Schema.Null - ]) - ), - "tags": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of tags to be attached to the newly created run. These tags are passed through directly to WandB. Some\ndefault tags are generated by OpenAI: \"openai/finetune\", \"openai/{base-model}\", \"openai/{ftjob-abcdef}\".\n" - }) - ) - }).annotate({ - "description": - "The settings for your integration with Weights and Biases. This payload specifies the project that\nmetrics will be sent to. Optionally, you can set an explicit display name for your run, add tags\nto your run, and set a default entity (team, username, etc) to be associated with your run.\n" - }) -}).annotate({ "title": "Fine-Tuning Job Integration" }) -export type FineTuningJobCheckpoint = { +export const LocalShellExecAction = Schema.Struct({ + "type": Schema.Literal("exec").annotate({ "description": "The type of the local shell action. Always `exec`." }), + "command": Schema.Array(Schema.String).annotate({ "description": "The command to run." }), + "timeout_ms": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "Optional timeout in milliseconds for the command." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null + ]) + ), + "working_directory": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Optional working directory to run the command in." }), + Schema.Null + ]) + ), + "env": Schema.Record(Schema.String, Schema.String).annotate({ + "description": "Environment variables to set for the command." + }), + "user": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Optional user to run the command as." }), Schema.Null]) + ) +}).annotate({ + "title": "Local shell exec action", + "description": "Execute a shell command on the server.", + "identifier": "LocalShellExecAction" +}) +export type LocalShellToolCallOutput = { + readonly "type": "local_shell_call_output" readonly "id": string - readonly "created_at": number - readonly "fine_tuned_model_checkpoint": string - readonly "step_number": number - readonly "metrics": { - readonly "step"?: number - readonly "train_loss"?: number - readonly "train_mean_token_accuracy"?: number - readonly "valid_loss"?: number - readonly "valid_mean_token_accuracy"?: number - readonly "full_valid_loss"?: number - readonly "full_valid_mean_token_accuracy"?: number - } - readonly "fine_tuning_job_id": string - readonly "object": "fine_tuning.job.checkpoint" + readonly "output": string + readonly "status"?: "in_progress" | "completed" | "incomplete" | null + readonly "call_id": Schema.Json } -export const FineTuningJobCheckpoint = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The checkpoint identifier, which can be referenced in the API endpoints." +export const LocalShellToolCallOutput = Schema.Struct({ + "type": Schema.Literal("local_shell_call_output").annotate({ + "description": "The type of the local shell tool call output. Always `local_shell_call_output`.\n" }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the checkpoint was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "fine_tuned_model_checkpoint": Schema.String.annotate({ - "description": "The name of the fine-tuned checkpoint model that is created." + "id": Schema.String.annotate({ + "description": "The unique ID of the local shell tool call generated by the model.\n" }), - "step_number": Schema.Number.annotate({ "description": "The step number that the checkpoint was created at." }).check( - Schema.isInt() + "output": Schema.String.annotate({ "description": "A JSON string of the output of the local shell tool call.\n" }), + "status": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": "The status of the item. One of `in_progress`, `completed`, or `incomplete`.\n" + }), + Schema.Null + ]) ), - "metrics": Schema.Struct({ - "step": Schema.optionalKey(Schema.Number.check(Schema.isFinite())), - "train_loss": Schema.optionalKey(Schema.Number.check(Schema.isFinite())), - "train_mean_token_accuracy": Schema.optionalKey(Schema.Number.check(Schema.isFinite())), - "valid_loss": Schema.optionalKey(Schema.Number.check(Schema.isFinite())), - "valid_mean_token_accuracy": Schema.optionalKey(Schema.Number.check(Schema.isFinite())), - "full_valid_loss": Schema.optionalKey(Schema.Number.check(Schema.isFinite())), - "full_valid_mean_token_accuracy": Schema.optionalKey(Schema.Number.check(Schema.isFinite())) - }).annotate({ "description": "Metrics at the step number during the fine-tuning job." }), - "fine_tuning_job_id": Schema.String.annotate({ - "description": "The name of the fine-tuning job that this checkpoint was created from." - }), - "object": Schema.Literal("fine_tuning.job.checkpoint").annotate({ - "description": "The object type, which is always \"fine_tuning.job.checkpoint\"." - }) + "call_id": Schema.Json.annotate({ "expected": "JSON value" }) }).annotate({ - "title": "FineTuningJobCheckpoint", - "description": - "The `fine_tuning.job.checkpoint` object represents a model checkpoint for a fine-tuning job that is ready to use.\n" + "title": "Local shell call output", + "description": "The output of a local shell tool call.\n", + "identifier": "LocalShellToolCallOutput" }) -export type FineTuningJobEvent = { - readonly "object": "fine_tuning.job.event" - readonly "id": string - readonly "created_at": number - readonly "level": "info" | "warn" | "error" - readonly "message": string - readonly "type"?: "message" | "metrics" - readonly "data"?: {} +export type FunctionShellAction = { + readonly "commands": ReadonlyArray + readonly "timeout_ms": number | null + readonly "max_output_length": number | null } -export const FineTuningJobEvent = Schema.Struct({ - "object": Schema.Literal("fine_tuning.job.event").annotate({ - "description": "The object type, which is always \"fine_tuning.job.event\"." +export const FunctionShellAction = Schema.Struct({ + "commands": Schema.Array(Schema.String.annotate({ "description": "A list of commands to run." })), + "timeout_ms": Schema.Union([ + Schema.Number.annotate({ "description": "Optional timeout in milliseconds for the commands." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null + ]), + "max_output_length": Schema.Union([ + Schema.Number.annotate({ "description": "Optional maximum number of characters to return from each command." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) +}).annotate({ + "title": "Shell exec action", + "description": "Execute a shell command.", + "identifier": "FunctionShellAction" +}) +export type FunctionShellCallStatus = "in_progress" | "completed" | "incomplete" +export const FunctionShellCallStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "FunctionShellCallStatus" +}) +export type LocalEnvironmentResource = { readonly "type": "local" } +export const LocalEnvironmentResource = Schema.Struct({ + "type": Schema.Literal("local").annotate({ "description": "The environment type. Always `local`." }) +}).annotate({ + "title": "Local Environment", + "description": "Represents the use of a local environment to perform shell actions.", + "identifier": "LocalEnvironmentResource" +}) +export type ContainerReferenceResource = { readonly "type": "container_reference"; readonly "container_id": string } +export const ContainerReferenceResource = Schema.Struct({ + "type": Schema.Literal("container_reference").annotate({ + "description": "The environment type. Always `container_reference`." }), - "id": Schema.String.annotate({ "description": "The object identifier." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the fine-tuning job was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "level": Schema.Literals(["info", "warn", "error"]).annotate({ "description": "The log level of the event." }), - "message": Schema.String.annotate({ "description": "The message of the event." }), - "type": Schema.optionalKey(Schema.Literals(["message", "metrics"]).annotate({ "description": "The type of event." })), - "data": Schema.optionalKey(Schema.Struct({}).annotate({ "description": "The data associated with the event." })) -}).annotate({ "description": "Fine-tuning job event object" }) -export type FunctionParameters = {} -export const FunctionParameters = Schema.Struct({}).annotate({ - "description": - "The parameters the functions accepts, described as a JSON Schema object. See the [guide](/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format. \n\nOmitting `parameters` defines a function with an empty parameter list." + "container_id": Schema.String +}).annotate({ + "title": "Container Reference", + "description": "Represents a container created with /v1/containers.", + "identifier": "ContainerReferenceResource" }) -export type FunctionToolCall = { - readonly "id"?: string - readonly "type": "function_call" - readonly "call_id": string - readonly "namespace"?: string +export type FunctionShellCallOutputStatusEnum = "in_progress" | "completed" | "incomplete" +export const FunctionShellCallOutputStatusEnum = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "FunctionShellCallOutputStatusEnum" +}) +export type FunctionShellCallOutputTimeoutOutcome = { readonly "type": "timeout" } +export const FunctionShellCallOutputTimeoutOutcome = Schema.Struct({ + "type": Schema.Literal("timeout").annotate({ "description": "The outcome type. Always `timeout`." }) +}).annotate({ + "title": "Shell call timeout outcome", + "description": "Indicates that the shell call exceeded its configured time limit.", + "identifier": "FunctionShellCallOutputTimeoutOutcome" +}) +export type FunctionShellCallOutputExitOutcome = { readonly "type": "exit"; readonly "exit_code": number } +export const FunctionShellCallOutputExitOutcome = Schema.Struct({ + "type": Schema.Literal("exit").annotate({ "description": "The outcome type. Always `exit`." }), + "exit_code": Schema.Number.annotate({ "description": "Exit code from the shell process." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "Shell call exit outcome", + "description": "Indicates that the shell commands finished and returned an exit code.", + "identifier": "FunctionShellCallOutputExitOutcome" +}) +export type ApplyPatchCallStatus = "in_progress" | "completed" +export const ApplyPatchCallStatus = Schema.Literals(["in_progress", "completed"]).annotate({ + "identifier": "ApplyPatchCallStatus" +}) +export type ApplyPatchCreateFileOperation = { + readonly "type": "create_file" + readonly "path": string + readonly "diff": string +} +export const ApplyPatchCreateFileOperation = Schema.Struct({ + "type": Schema.Literal("create_file").annotate({ "description": "Create a new file with the provided diff." }), + "path": Schema.String.annotate({ "description": "Path of the file to create." }), + "diff": Schema.String.annotate({ "description": "Diff to apply." }) +}).annotate({ + "title": "Apply patch create file operation", + "description": "Instruction describing how to create a file via the apply_patch tool.", + "identifier": "ApplyPatchCreateFileOperation" +}) +export type ApplyPatchDeleteFileOperation = { readonly "type": "delete_file"; readonly "path": string } +export const ApplyPatchDeleteFileOperation = Schema.Struct({ + "type": Schema.Literal("delete_file").annotate({ "description": "Delete the specified file." }), + "path": Schema.String.annotate({ "description": "Path of the file to delete." }) +}).annotate({ + "title": "Apply patch delete file operation", + "description": "Instruction describing how to delete a file via the apply_patch tool.", + "identifier": "ApplyPatchDeleteFileOperation" +}) +export type ApplyPatchUpdateFileOperation = { + readonly "type": "update_file" + readonly "path": string + readonly "diff": string +} +export const ApplyPatchUpdateFileOperation = Schema.Struct({ + "type": Schema.Literal("update_file").annotate({ "description": "Update an existing file with the provided diff." }), + "path": Schema.String.annotate({ "description": "Path of the file to update." }), + "diff": Schema.String.annotate({ "description": "Diff to apply." }) +}).annotate({ + "title": "Apply patch update file operation", + "description": "Instruction describing how to update a file via the apply_patch tool.", + "identifier": "ApplyPatchUpdateFileOperation" +}) +export type ApplyPatchCallOutputStatus = "completed" | "failed" +export const ApplyPatchCallOutputStatus = Schema.Literals(["completed", "failed"]).annotate({ + "identifier": "ApplyPatchCallOutputStatus" +}) +export type MCPListToolsTool = { readonly "name": string - readonly "arguments": string - readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "description"?: string | null + readonly "input_schema": { readonly [x: string]: Schema.Json } + readonly "annotations"?: { readonly [x: string]: Schema.Json } | null } -export const FunctionToolCall = Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the function tool call.\n" })), - "type": Schema.Literal("function_call").annotate({ - "description": "The type of the function tool call. Always `function_call`.\n" - }), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the function tool call generated by the model.\n" +export const MCPListToolsTool = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the tool.\n" }), + "description": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The description of the tool.\n" }), Schema.Null]) + ), + "input_schema": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The JSON schema describing the tool's input.\n" }), - "namespace": Schema.optionalKey(Schema.String.annotate({ "description": "The namespace of the function to run.\n" })), - "name": Schema.String.annotate({ "description": "The name of the function to run.\n" }), - "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments to pass to the function.\n" }), - "status": Schema.optionalKey( - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }) + "annotations": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Additional annotations about the tool.\n" + }), + Schema.Null + ]) ) }).annotate({ - "title": "Function tool call", - "description": - "A tool call to run a function. See the \n[function calling guide](/docs/guides/function-calling) for more information.\n" + "title": "MCP list tools tool", + "description": "A tool available on an MCP server.\n", + "identifier": "MCPListToolsTool" }) -export type FunctionToolCallResource = { +export type MCPApprovalRequest = { + readonly "type": "mcp_approval_request" readonly "id": string - readonly "type": "function_call" - readonly "call_id": string - readonly "namespace"?: string + readonly "server_label": string readonly "name": string readonly "arguments": string - readonly "status": "in_progress" | "completed" | "incomplete" - readonly "created_by"?: string } -export const FunctionToolCallResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique ID of the function tool call.\n" }), - "type": Schema.Literal("function_call").annotate({ - "description": "The type of the function tool call. Always `function_call`.\n" - }), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the function tool call generated by the model.\n" +export const MCPApprovalRequest = Schema.Struct({ + "type": Schema.Literal("mcp_approval_request").annotate({ + "description": "The type of the item. Always `mcp_approval_request`.\n" }), - "namespace": Schema.optionalKey(Schema.String.annotate({ "description": "The namespace of the function to run.\n" })), - "name": Schema.String.annotate({ "description": "The name of the function to run.\n" }), - "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments to pass to the function.\n" }), - "status": Schema.Union([ - Schema.Literal("in_progress").annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }), - Schema.Literal("completed").annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }), - Schema.Literal("incomplete").annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }) - ]).annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + "id": Schema.String.annotate({ "description": "The unique ID of the approval request.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server making the request.\n" }), + "name": Schema.String.annotate({ "description": "The name of the tool to run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of arguments for the tool.\n" }) +}).annotate({ + "title": "MCP approval request", + "description": "A request for human approval of a tool invocation.\n", + "identifier": "MCPApprovalRequest" +}) +export type MCPApprovalResponseResource = { + readonly "type": "mcp_approval_response" + readonly "id": string + readonly "approval_request_id": string + readonly "approve": boolean + readonly "reason"?: string | null + readonly "request_id": Schema.Json +} +export const MCPApprovalResponseResource = Schema.Struct({ + "type": Schema.Literal("mcp_approval_response").annotate({ + "description": "The type of the item. Always `mcp_approval_response`.\n" }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) - ) + "id": Schema.String.annotate({ "description": "The unique ID of the approval response\n" }), + "approval_request_id": Schema.String.annotate({ "description": "The ID of the approval request being answered.\n" }), + "approve": Schema.Boolean.annotate({ "description": "Whether the request was approved.\n" }), + "reason": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Optional reason for the decision.\n" }), Schema.Null]) + ), + "request_id": Schema.Json.annotate({ "expected": "JSON value" }) }).annotate({ - "title": "Function tool call", + "title": "MCP approval response", + "description": "A response to an MCP approval request.\n", + "identifier": "MCPApprovalResponseResource" +}) +export type MCPProtocolError = { + readonly "type": "mcp_protocol_error" + readonly "code": number + readonly "message": string +} +export const MCPProtocolError = Schema.Struct({ + "type": Schema.Literal("mcp_protocol_error"), + "code": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "message": Schema.String +}).annotate({ "identifier": "MCPProtocolError" }) +export type MCPToolExecutionError = { readonly "type": "mcp_tool_execution_error"; readonly "content": Schema.Json } +export const MCPToolExecutionError = Schema.Struct({ + "type": Schema.Literal("mcp_tool_execution_error"), + "content": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ "identifier": "MCPToolExecutionError" }) +export type HTTPError = { readonly "type": "http_error"; readonly "code": number; readonly "message": string } +export const HTTPError = Schema.Struct({ + "type": Schema.Literal("http_error"), + "code": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "message": Schema.String +}).annotate({ "identifier": "HTTPError" }) +export type MCPToolCallStatus = "in_progress" | "completed" | "incomplete" | "calling" | "failed" +export const MCPToolCallStatus = Schema.Literals(["in_progress", "completed", "incomplete", "calling", "failed"]) + .annotate({ "identifier": "MCPToolCallStatus" }) +export type MessagePhase = "commentary" | "final_answer" +export const MessagePhase = Schema.Literals(["commentary", "final_answer"]).annotate({ "description": - "A tool call to run a function. See the \n[function calling guide](/docs/guides/function-calling) for more information.\n" + "Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`).\nFor models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend\nphase on all assistant messages — dropping it can degrade performance. Not used for user messages.\n", + "identifier": "MessagePhase" }) -export type GraderPython = { - readonly "type": "python" - readonly "name": string - readonly "source": string - readonly "image_tag"?: string +export type FunctionCallItemStatus = "in_progress" | "completed" | "incomplete" +export const FunctionCallItemStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "FunctionCallItemStatus" +}) +export type DetailEnum = "low" | "high" | "auto" | "original" +export const DetailEnum = Schema.Literals(["low", "high", "auto", "original"]).annotate({ "identifier": "DetailEnum" }) +export type FileDetailEnum = "auto" | "low" | "high" +export const FileDetailEnum = Schema.Literals(["auto", "low", "high"]).annotate({ "identifier": "FileDetailEnum" }) +export type FunctionShellActionParam = { + readonly "commands": ReadonlyArray + readonly "timeout_ms"?: number | null + readonly "max_output_length"?: number | null } -export const GraderPython = Schema.Struct({ - "type": Schema.Literal("python").annotate({ "description": "The object type, which is always `python`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "source": Schema.String.annotate({ "description": "The source code of the python script." }), - "image_tag": Schema.optionalKey( - Schema.String.annotate({ "description": "The image tag to use for the python script." }) +export const FunctionShellActionParam = Schema.Struct({ + "commands": Schema.Array(Schema.String).annotate({ + "description": "Ordered shell commands for the execution environment to run." + }), + "timeout_ms": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "Maximum wall-clock time in milliseconds to allow the shell commands to run." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ), + "max_output_length": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "Maximum number of UTF-8 characters to capture from combined stdout and stderr output." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) ) }).annotate({ - "title": "PythonGrader", - "description": "A PythonGrader object that runs a python script on the input.\n" + "title": "Shell action", + "description": "Commands and limits describing how to run the shell tool call.", + "identifier": "FunctionShellActionParam" }) -export type GraderStringCheck = { - readonly "type": "string_check" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "operation": "eq" | "ne" | "like" | "ilike" +export type FunctionShellCallItemStatus = "in_progress" | "completed" | "incomplete" +export const FunctionShellCallItemStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "title": "Shell call status", + "description": "Status values reported for shell tool calls.", + "identifier": "FunctionShellCallItemStatus" +}) +export type FunctionShellCallOutputTimeoutOutcomeParam = { readonly "type": "timeout" } +export const FunctionShellCallOutputTimeoutOutcomeParam = Schema.Struct({ + "type": Schema.Literal("timeout").annotate({ "description": "The outcome type. Always `timeout`." }) +}).annotate({ + "title": "Shell call timeout outcome", + "description": "Indicates that the shell call exceeded its configured time limit.", + "identifier": "FunctionShellCallOutputTimeoutOutcomeParam" +}) +export type FunctionShellCallOutputExitOutcomeParam = { readonly "type": "exit"; readonly "exit_code": number } +export const FunctionShellCallOutputExitOutcomeParam = Schema.Struct({ + "type": Schema.Literal("exit").annotate({ "description": "The outcome type. Always `exit`." }), + "exit_code": Schema.Number.annotate({ "description": "The exit code returned by the shell process." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "Shell call exit outcome", + "description": "Indicates that the shell commands finished and returned an exit code.", + "identifier": "FunctionShellCallOutputExitOutcomeParam" +}) +export type ApplyPatchCallStatusParam = "in_progress" | "completed" +export const ApplyPatchCallStatusParam = Schema.Literals(["in_progress", "completed"]).annotate({ + "title": "Apply patch call status", + "description": "Status values reported for apply_patch tool calls.", + "identifier": "ApplyPatchCallStatusParam" +}) +export type ApplyPatchCreateFileOperationParam = { + readonly "type": "create_file" + readonly "path": string + readonly "diff": string } -export const GraderStringCheck = Schema.Struct({ - "type": Schema.Literal("string_check").annotate({ - "description": "The object type, which is always `string_check`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The input text. This may include template strings." }), - "reference": Schema.String.annotate({ "description": "The reference text. This may include template strings." }), - "operation": Schema.Literals(["eq", "ne", "like", "ilike"]).annotate({ - "description": "The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`." - }) +export const ApplyPatchCreateFileOperationParam = Schema.Struct({ + "type": Schema.Literal("create_file").annotate({ "description": "The operation type. Always `create_file`." }), + "path": Schema.String.annotate({ "description": "Path of the file to create relative to the workspace root." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + "diff": Schema.String.annotate({ "description": "Unified diff content to apply when creating the file." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ) }).annotate({ - "title": "StringCheckGrader", - "description": - "A StringCheckGrader object that performs a string comparison between input and reference using a specified operation.\n" + "title": "Apply patch create file operation", + "description": "Instruction for creating a new file via the apply_patch tool.", + "identifier": "ApplyPatchCreateFileOperationParam" }) -export type GraderTextSimilarity = { - readonly "type": "text_similarity" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "evaluation_metric": - | "cosine" - | "fuzzy_match" - | "bleu" - | "gleu" - | "meteor" - | "rouge_1" - | "rouge_2" - | "rouge_3" - | "rouge_4" - | "rouge_5" - | "rouge_l" +export type ApplyPatchDeleteFileOperationParam = { readonly "type": "delete_file"; readonly "path": string } +export const ApplyPatchDeleteFileOperationParam = Schema.Struct({ + "type": Schema.Literal("delete_file").annotate({ "description": "The operation type. Always `delete_file`." }), + "path": Schema.String.annotate({ "description": "Path of the file to delete relative to the workspace root." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ) +}).annotate({ + "title": "Apply patch delete file operation", + "description": "Instruction for deleting an existing file via the apply_patch tool.", + "identifier": "ApplyPatchDeleteFileOperationParam" +}) +export type ApplyPatchUpdateFileOperationParam = { + readonly "type": "update_file" + readonly "path": string + readonly "diff": string } -export const GraderTextSimilarity = Schema.Struct({ - "type": Schema.Literal("text_similarity").annotate({ "description": "The type of grader." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The text being graded." }), - "reference": Schema.String.annotate({ "description": "The text being graded against." }), - "evaluation_metric": Schema.Literals([ - "cosine", - "fuzzy_match", - "bleu", - "gleu", - "meteor", - "rouge_1", - "rouge_2", - "rouge_3", - "rouge_4", - "rouge_5", - "rouge_l" - ]).annotate({ - "description": - "The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, \n`gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, \nor `rouge_l`.\n" +export const ApplyPatchUpdateFileOperationParam = Schema.Struct({ + "type": Schema.Literal("update_file").annotate({ "description": "The operation type. Always `update_file`." }), + "path": Schema.String.annotate({ "description": "Path of the file to update relative to the workspace root." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + "diff": Schema.String.annotate({ "description": "Unified diff content to apply to the existing file." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ) +}).annotate({ + "title": "Apply patch update file operation", + "description": "Instruction for updating an existing file via the apply_patch tool.", + "identifier": "ApplyPatchUpdateFileOperationParam" +}) +export type ApplyPatchCallOutputStatusParam = "completed" | "failed" +export const ApplyPatchCallOutputStatusParam = Schema.Literals(["completed", "failed"]).annotate({ + "title": "Apply patch call output status", + "description": "Outcome values reported for apply_patch tool call outputs.", + "identifier": "ApplyPatchCallOutputStatusParam" +}) +export type CompactionTriggerItemParam = { readonly "id"?: string | null; readonly "type": "compaction_trigger" } +export const CompactionTriggerItemParam = Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The unique ID of this compaction trigger." }), Schema.Null]) + ), + "type": Schema.Literal("compaction_trigger").annotate({ + "description": "The type of the item. Always `compaction_trigger`." }) }).annotate({ - "title": "TextSimilarityGrader", - "description": "A TextSimilarityGrader object which grades text based on similarity metrics.\n" + "title": "Compaction trigger", + "description": "Compacts the current context. Must be the final input item.", + "identifier": "CompactionTriggerItemParam" }) -export type Group = { - readonly "object": "group" - readonly "id": string - readonly "name": string - readonly "created_at": number - readonly "scim_managed": boolean -} -export const Group = Schema.Struct({ - "object": Schema.Literal("group").annotate({ "description": "Always `group`." }), - "id": Schema.String.annotate({ "description": "Identifier for the group." }), - "name": Schema.String.annotate({ "description": "Display name of the group." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the group was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "scim_managed": Schema.Boolean.annotate({ "description": "Whether the group is managed through SCIM." }) -}).annotate({ "description": "Summary information about a group returned in role assignment responses." }) -export type GroupDeletedResource = { - readonly "object": "group.deleted" +export type ItemReferenceParam = { readonly "type"?: "item_reference" | null; readonly "id": string } +export const ItemReferenceParam = Schema.Struct({ + "type": Schema.optionalKey( + Schema.Union([ + Schema.Literal("item_reference").annotate({ + "description": "The type of item to reference. Always `item_reference`." + }), + Schema.Null + ]) + ), + "id": Schema.String.annotate({ "description": "The ID of the item to reference." }) +}).annotate({ + "title": "Item reference", + "description": "An internal identifier for an item to reference.", + "identifier": "ItemReferenceParam" +}) +export type ProgramItemParam = { readonly "id": string - readonly "deleted": boolean -} -export const GroupDeletedResource = Schema.Struct({ - "object": Schema.Literal("group.deleted").annotate({ "description": "Always `group.deleted`." }), - "id": Schema.String.annotate({ "description": "Identifier of the deleted group." }), - "deleted": Schema.Boolean.annotate({ "description": "Whether the group was deleted." }) -}).annotate({ "description": "Confirmation payload returned after deleting a group." }) -export type GroupResourceWithSuccess = { + readonly "type": "program" + readonly "call_id": string + readonly "code": string + readonly "fingerprint": string +} +export const ProgramItemParam = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of this program item." }), + "type": Schema.Literal("program").annotate({ "description": "The item type. Always `program`." }), + "call_id": Schema.String.annotate({ "description": "The stable call ID of the program item." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "code": Schema.String.annotate({ "description": "The JavaScript source executed by programmatic tool calling." }) + .check(Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" })), + "fingerprint": Schema.String.annotate({ + "description": "Opaque program replay fingerprint that must be round-tripped." + }).check(Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" })) +}).annotate({ "identifier": "ProgramItemParam" }) +export type ProgramOutputItemStatus = "completed" | "incomplete" +export const ProgramOutputItemStatus = Schema.Literals(["completed", "incomplete"]).annotate({ + "identifier": "ProgramOutputItemStatus" +}) +export type ConversationResource = { readonly "id": string - readonly "name": string + readonly "object": "conversation" + readonly "metadata": { readonly [x: string]: string } readonly "created_at": number - readonly "is_scim_managed": boolean } -export const GroupResourceWithSuccess = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier for the group." }), - "name": Schema.String.annotate({ "description": "Updated display name for the group." }), +export const ConversationResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the conversation." }), + "object": Schema.Literal("conversation").annotate({ + "description": "The object type, which is always `conversation`." + }), + "metadata": Schema.Record(Schema.String, Schema.String).annotate({ + "description": + "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard.\n Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters." + }), "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the group was created.", + "description": "The time at which the conversation was created, measured in seconds since the Unix epoch.", "format": "unixtime" - }).check(Schema.isInt()), - "is_scim_managed": Schema.Boolean.annotate({ - "description": "Whether the group is managed through SCIM and controlled by your identity provider." - }) -}).annotate({ "description": "Response returned after updating a group." }) -export type GroupResponse = { - readonly "id": string - readonly "name": string - readonly "created_at": number - readonly "is_scim_managed": boolean - readonly "group_type": string + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ "identifier": "ConversationResource" }) +export type CreateEmbeddingRequest = { + readonly "input": string | ReadonlyArray | ReadonlyArray | ReadonlyArray> + readonly "model": string | "text-embedding-ada-002" | "text-embedding-3-small" | "text-embedding-3-large" + readonly "encoding_format"?: "float" | "base64" + readonly "dimensions"?: number + readonly "user"?: string } -export const GroupResponse = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier for the group." }), - "name": Schema.String.annotate({ "description": "Display name of the group." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the group was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "is_scim_managed": Schema.Boolean.annotate({ - "description": "Whether the group is managed through SCIM and controlled by your identity provider." +export const CreateEmbeddingRequest = Schema.Struct({ + "input": Schema.Union([ + Schema.String.annotate({ "title": "string", "description": "The string that will be turned into an embedding." }), + Schema.Array(Schema.String).annotate({ + "title": "array", + "description": "The array of strings that will be turned into an embedding." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(2048).annotate({ "expected": "a value with a length of at most 2048" }) + ), + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).annotate({ + "title": "array", + "description": "The array of integers that will be turned into an embedding." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(2048).annotate({ "expected": "a value with a length of at most 2048" }) + ), + Schema.Array( + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ) + ).annotate({ + "title": "array", + "description": "The array of arrays containing integers that will be turned into an embedding." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(2048).annotate({ "expected": "a value with a length of at most 2048" }) + ) + ], { mode: "oneOf" }).annotate({ + "description": + "Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for all embedding models), cannot be an empty string, and any array must be 2048 dimensions or less. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. In addition to the per-input token limit, all embedding models enforce a maximum of 300,000 tokens summed across all inputs in a single request.\n" }), - "group_type": Schema.String.annotate({ "description": "The type of the group." }) -}).annotate({ "description": "Details about an organization group." }) -export type GroupUser = { readonly "id": string; readonly "name": string; readonly "email": string | null } -export const GroupUser = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.String.annotate({ "description": "The name of the user." }), - "email": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The email address of the user." }) -}).annotate({ "description": "Represents an individual user returned when inspecting group membership." }) -export type GroupUserAssignment = { - readonly "object": "group.user" - readonly "user_id": string - readonly "group_id": string -} -export const GroupUserAssignment = Schema.Struct({ - "object": Schema.Literal("group.user").annotate({ "description": "Always `group.user`." }), - "user_id": Schema.String.annotate({ "description": "Identifier of the user that was added." }), - "group_id": Schema.String.annotate({ "description": "Identifier of the group the user was added to." }) -}).annotate({ "description": "Confirmation payload returned after adding a user to a group." }) -export type GroupUserDeletedResource = { readonly "object": "group.user.deleted"; readonly "deleted": boolean } -export const GroupUserDeletedResource = Schema.Struct({ - "object": Schema.Literal("group.user.deleted").annotate({ "description": "Always `group.user.deleted`." }), - "deleted": Schema.Boolean.annotate({ "description": "Whether the group membership was removed." }) -}).annotate({ "description": "Confirmation payload returned after removing a user from a group." }) -export type HostedToolPermission = { readonly "enabled": boolean } -export const HostedToolPermission = Schema.Struct({ - "enabled": Schema.Boolean.annotate({ "description": "Whether the hosted tool is enabled for the project." }) -}).annotate({ "description": "Permission state for a single hosted tool on a project." }) -export type HostedToolPermissionUpdate = { readonly "enabled": boolean } -export const HostedToolPermissionUpdate = Schema.Struct({ - "enabled": Schema.Boolean.annotate({ "description": "Whether to enable the hosted tool for the project." }) -}) -export type Image = { readonly "b64_json"?: string; readonly "url"?: string; readonly "revised_prompt"?: string } -export const Image = Schema.Struct({ - "b64_json": Schema.optionalKey( - Schema.String.annotate({ + "model": Schema.Union([ + Schema.String, + Schema.Literals(["text-embedding-ada-002", "text-embedding-3-small", "text-embedding-3-large"]) + ]).annotate({ + "description": + "ID of the model to use. You can use the [List models](https://developers.openai.com/api/reference/resources/models/methods/list) API to see all of your available models, or see our [Model overview](https://developers.openai.com/api/docs/models) for descriptions of them.\n" + }), + "encoding_format": Schema.optionalKey( + Schema.Literals(["float", "base64"]).annotate({ "description": - "The base64-encoded JSON of the generated image. Returned by default for the GPT image models, and only present if `response_format` is set to `b64_json` for `dall-e-2` and `dall-e-3`." + "The format to return the embeddings in. Can be either `float` or [`base64`](https://pypi.org/project/pybase64/)." }) ), - "url": Schema.optionalKey( - Schema.String.annotate({ + "dimensions": Schema.optionalKey( + Schema.Number.annotate({ "description": - "When using `dall-e-2` or `dall-e-3`, the URL of the generated image if `response_format` is set to `url` (default value). Unsupported for the GPT image models.", - "format": "uri" - }) + "The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ) ), - "revised_prompt": Schema.optionalKey( + "user": Schema.optionalKey( Schema.String.annotate({ - "description": "For `dall-e-3` only, the revised prompt that was used to generate the image." + "description": + "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" }) ) -}).annotate({ "description": "Represents the content or the URL of an image generated by the OpenAI API." }) -export type ImageEditPartialImageEvent = { - readonly "type": "image_edit.partial_image" - readonly "b64_json": string - readonly "created_at": number - readonly "size": "1024x1024" | "1024x1536" | "1536x1024" | "auto" - readonly "quality": "low" | "medium" | "high" | "auto" - readonly "background": "transparent" | "opaque" | "auto" - readonly "output_format": "png" | "webp" | "jpeg" - readonly "partial_image_index": number -} -export const ImageEditPartialImageEvent = Schema.Struct({ - "type": Schema.Literal("image_edit.partial_image").annotate({ - "description": "The type of the event. Always `image_edit.partial_image`.\n" - }), - "b64_json": Schema.String.annotate({ - "description": "Base64-encoded partial image data, suitable for rendering as an image.\n" - }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp when the event was created.\n", - "format": "unixtime" - }).check(Schema.isInt()), - "size": Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"]).annotate({ - "description": "The size of the requested edited image.\n" - }), - "quality": Schema.Literals(["low", "medium", "high", "auto"]).annotate({ - "description": "The quality setting for the requested edited image.\n" - }), - "background": Schema.Literals(["transparent", "opaque", "auto"]).annotate({ - "description": "The background setting for the requested edited image.\n" - }), - "output_format": Schema.Literals(["png", "webp", "jpeg"]).annotate({ - "description": "The output format for the requested edited image.\n" - }), - "partial_image_index": Schema.Number.annotate({ "description": "0-based index for the partial image (streaming).\n" }) - .check(Schema.isInt()) -}).annotate({ "description": "Emitted when a partial image is available during image editing streaming.\n" }) -export type ImageGenPartialImageEvent = { - readonly "type": "image_generation.partial_image" - readonly "b64_json": string - readonly "created_at": number - readonly "size": "1024x1024" | "1024x1536" | "1536x1024" | "auto" - readonly "quality": "low" | "medium" | "high" | "auto" - readonly "background": "transparent" | "opaque" | "auto" - readonly "output_format": "png" | "webp" | "jpeg" - readonly "partial_image_index": number -} -export const ImageGenPartialImageEvent = Schema.Struct({ - "type": Schema.Literal("image_generation.partial_image").annotate({ - "description": "The type of the event. Always `image_generation.partial_image`.\n" - }), - "b64_json": Schema.String.annotate({ - "description": "Base64-encoded partial image data, suitable for rendering as an image.\n" - }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp when the event was created.\n", - "format": "unixtime" - }).check(Schema.isInt()), - "size": Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"]).annotate({ - "description": "The size of the requested image.\n" - }), - "quality": Schema.Literals(["low", "medium", "high", "auto"]).annotate({ - "description": "The quality setting for the requested image.\n" - }), - "background": Schema.Literals(["transparent", "opaque", "auto"]).annotate({ - "description": "The background setting for the requested image.\n" - }), - "output_format": Schema.Literals(["png", "webp", "jpeg"]).annotate({ - "description": "The output format for the requested image.\n" - }), - "partial_image_index": Schema.Number.annotate({ "description": "0-based index for the partial image (streaming).\n" }) - .check(Schema.isInt()) -}).annotate({ "description": "Emitted when a partial image is available during image generation streaming.\n" }) -export type ImageGenToolCall = { - readonly "type": "image_generation_call" - readonly "id": string - readonly "status": "in_progress" | "completed" | "generating" | "failed" - readonly "result": string | null -} -export const ImageGenToolCall = Schema.Struct({ - "type": Schema.Literal("image_generation_call").annotate({ - "description": "The type of the image generation call. Always `image_generation_call`.\n" - }), - "id": Schema.String.annotate({ "description": "The unique ID of the image generation call.\n" }), - "status": Schema.Literals(["in_progress", "completed", "generating", "failed"]).annotate({ - "description": "The status of the image generation call.\n" - }), - "result": Schema.Union([ - Schema.String.annotate({ "description": "The generated image encoded in base64.\n" }), - Schema.Null - ]) -}).annotate({ "title": "Image generation call", "description": "An image generation request made by the model.\n" }) -export type ImageRefParam = { readonly "image_url": string; readonly "file_id"?: string } | { - readonly "file_id": string - readonly "image_url"?: string +}).annotate({ "identifier": "CreateEmbeddingRequest" }) +export type Embedding = { + readonly "index": number + readonly "embedding": ReadonlyArray | string + readonly "object": "embedding" } -export const ImageRefParam = Schema.Union([ - Schema.Struct({ - "image_url": Schema.String.annotate({ - "description": "A fully qualified URL or base64-encoded data URL.", - "format": "uri" - }).check(Schema.isMaxLength(20971520)), - "file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The File API ID of an uploaded image to use as input." }) - ) - }).annotate({ +export const Embedding = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the embedding in the list of embeddings." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "embedding": Schema.Union([ + Schema.Array( + Schema.Number.annotate({ "format": "float" }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + Schema.String.annotate({ "contentEncoding": "base64" }) + ]).annotate({ "description": - "Reference an input image by either URL or uploaded file ID.\nProvide exactly one of `image_url` or `file_id`.\n" + "The embedding vector, returned as a list of floats when `encoding_format` is `float` (the default), or as a base64-encoded string when `encoding_format` is `base64`. The length of the vector depends on the model as listed in the [embedding guide](https://developers.openai.com/api/docs/guides/embeddings).\n" }), - Schema.Struct({ - "file_id": Schema.String.annotate({ "description": "The File API ID of an uploaded image to use as input." }), - "image_url": Schema.optionalKey( - Schema.String.annotate({ "description": "A fully qualified URL or base64-encoded data URL.", "format": "uri" }) - .check(Schema.isMaxLength(20971520)) - ) - }).annotate({ + "object": Schema.Literal("embedding").annotate({ "description": "The object type, which is always \"embedding\"." }) +}).annotate({ + "description": "Represents an embedding vector returned by embedding endpoint.\n", + "identifier": "Embedding" +}) +export type EvalCustomDataSourceConfig = { + readonly "type": "custom" + readonly "schema": { readonly [x: string]: Schema.Json } +} +export const EvalCustomDataSourceConfig = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "The type of data source. Always `custom`." }), + "schema": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ "description": - "Reference an input image by either URL or uploaded file ID.\nProvide exactly one of `image_url` or `file_id`.\n" + "The json schema for the run data source items.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n" }) -]) -export type ImagesUsage = { - readonly "total_tokens": number - readonly "input_tokens": number - readonly "output_tokens": number - readonly "input_tokens_details": { readonly "text_tokens": number; readonly "image_tokens": number } +}).annotate({ + "title": "CustomDataSourceConfig", + "description": + "A CustomDataSourceConfig which specifies the schema of your `item` and optionally `sample` namespaces.\nThe response schema defines the shape of the data that will be:\n- Used to define your testing criteria and\n- What data is required when creating a run\n", + "identifier": "EvalCustomDataSourceConfig" +}) +export type EvalItemContentText = string +export const EvalItemContentText = Schema.String.annotate({ + "title": "Text input", + "description": "A text input to the model.\n", + "identifier": "EvalItemContentText" +}) +export type EvalItemContentOutputText = { readonly "type": "output_text"; readonly "text": string } +export const EvalItemContentOutputText = Schema.Struct({ + "type": Schema.Literal("output_text").annotate({ + "description": "The type of the output text. Always `output_text`.\n" + }), + "text": Schema.String.annotate({ "description": "The text output from the model.\n" }) +}).annotate({ + "title": "Output text", + "description": "A text output from the model.\n", + "identifier": "EvalItemContentOutputText" +}) +export type EvalItemInputImage = { + readonly "type": "input_image" + readonly "image_url": string + readonly "detail"?: string } -export const ImagesUsage = Schema.Struct({ - "total_tokens": Schema.Number.annotate({ - "description": "The total number of tokens (images and text) used for the image generation.\n" - }).check(Schema.isInt()), - "input_tokens": Schema.Number.annotate({ - "description": "The number of tokens (images and text) in the input prompt." - }).check(Schema.isInt()), - "output_tokens": Schema.Number.annotate({ "description": "The number of image tokens in the output image." }).check( - Schema.isInt() - ), - "input_tokens_details": Schema.Struct({ - "text_tokens": Schema.Number.annotate({ "description": "The number of text tokens in the input prompt." }).check( - Schema.isInt() - ), - "image_tokens": Schema.Number.annotate({ "description": "The number of image tokens in the input prompt." }).check( - Schema.isInt() - ) - }).annotate({ "description": "The input tokens detailed information for the image generation." }) -}).annotate({ "description": "For the GPT image models only, the token usage information for the image generation.\n" }) +export const EvalItemInputImage = Schema.Struct({ + "type": Schema.Literal("input_image").annotate({ + "description": "The type of the image input. Always `input_image`.\n" + }), + "image_url": Schema.String.annotate({ "description": "The URL of the image input.\n", "format": "uri" }), + "detail": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`.\n" + }) + ) +}).annotate({ + "title": "Input image", + "description": "An image input block used within EvalItem content arrays.", + "identifier": "EvalItemInputImage" +}) export type InputAudio = { readonly "type": "input_audio" readonly "input_audio": { readonly "data": string; readonly "format": "mp3" | "wav" } @@ -2696,3951 +2884,3987 @@ export const InputAudio = Schema.Struct({ "description": "The format of the audio data. Currently supported formats are `mp3` and\n`wav`.\n" }) }) -}).annotate({ "title": "Input audio", "description": "An audio input to the model.\n" }) -export type Invite = { - readonly "object": "organization.invite" - readonly "id": string - readonly "email": string - readonly "role": "owner" | "reader" - readonly "status": "accepted" | "expired" | "pending" - readonly "created_at": number - readonly "expires_at"?: number | null - readonly "accepted_at"?: number | null - readonly "projects": ReadonlyArray<{ readonly "id": string; readonly "role": "member" | "owner" }> +}).annotate({ "title": "Input audio", "description": "An audio input to the model.\n", "identifier": "InputAudio" }) +export type EvalGraderStringCheck = { + readonly "type": "string_check" + readonly "name": string + readonly "input": string + readonly "reference": string + readonly "operation": "eq" | "ne" | "like" | "ilike" } -export const Invite = Schema.Struct({ - "object": Schema.Literal("organization.invite").annotate({ - "description": "The object type, which is always `organization.invite`" - }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "email": Schema.String.annotate({ "description": "The email address of the individual to whom the invite was sent" }), - "role": Schema.Literals(["owner", "reader"]).annotate({ "description": "`owner` or `reader`" }), - "status": Schema.Literals(["accepted", "expired", "pending"]).annotate({ - "description": "`accepted`,`expired`, or `pending`" +export const EvalGraderStringCheck = Schema.Struct({ + "type": Schema.Literal("string_check").annotate({ + "description": "The object type, which is always `string_check`." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the invite was sent.", - "format": "unixtime" - }).check(Schema.isInt()), - "expires_at": Schema.optionalKey( - Schema.Union([Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt()), Schema.Null]).annotate({ - "description": "The Unix timestamp (in seconds) of when the invite expires." - }) - ), - "accepted_at": Schema.optionalKey( - Schema.Union([Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt()), Schema.Null]).annotate({ - "description": "The Unix timestamp (in seconds) of when the invite was accepted." - }) - ), - "projects": Schema.Array( - Schema.Struct({ - "id": Schema.String.annotate({ "description": "Project's public ID" }), - "role": Schema.Literals(["member", "owner"]).annotate({ "description": "Project membership role" }) - }) - ).annotate({ "description": "The projects that were granted membership upon acceptance of the invite." }) -}).annotate({ "description": "Represents an individual `invite` to the organization." }) -export type InviteDeleteResponse = { - readonly "object": "organization.invite.deleted" - readonly "id": string - readonly "deleted": boolean -} -export const InviteDeleteResponse = Schema.Struct({ - "object": Schema.Literal("organization.invite.deleted").annotate({ - "description": "The object type, which is always `organization.invite.deleted`" - }), - "id": Schema.String, - "deleted": Schema.Boolean -}) -export type InviteProjectGroupBody = { readonly "group_id": string; readonly "role": string } -export const InviteProjectGroupBody = Schema.Struct({ - "group_id": Schema.String.annotate({ "description": "Identifier of the group to add to the project." }), - "role": Schema.String.annotate({ "description": "Identifier of the project role to grant to the group." }) -}).annotate({ "description": "Request payload for granting a group access to a project." }) -export type InviteRequest = { - readonly "email": string - readonly "role": "reader" | "owner" - readonly "projects"?: ReadonlyArray<{ readonly "id": string; readonly "role": "member" | "owner" }> -} -export const InviteRequest = Schema.Struct({ - "email": Schema.String.annotate({ "description": "Send an email to this address" }), - "role": Schema.Literals(["reader", "owner"]).annotate({ "description": "`owner` or `reader`" }), - "projects": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "id": Schema.String.annotate({ "description": "Project's public ID" }), - "role": Schema.Literals(["member", "owner"]).annotate({ "description": "Project membership role" }) - }) - ).annotate({ - "description": - "An array of projects to which membership is granted at the same time the org invite is accepted. If omitted, the user will be invited to the default project for compatibility with legacy behavior. If empty list is passed, the user will not be invited to any projects, including the default one." - }) - ) -}) -export type LocalShellToolCallOutput = { - readonly "type": "local_shell_call_output" - readonly "id": string - readonly "output": string - readonly "status"?: "in_progress" | "completed" | "incomplete" | null - readonly "call_id": unknown -} -export const LocalShellToolCallOutput = Schema.Struct({ - "type": Schema.Literal("local_shell_call_output").annotate({ - "description": "The type of the local shell tool call output. Always `local_shell_call_output`.\n" - }), - "id": Schema.String.annotate({ - "description": "The unique ID of the local shell tool call generated by the model.\n" - }), - "output": Schema.String.annotate({ "description": "A JSON string of the output of the local shell tool call.\n" }), - "status": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": "The status of the item. One of `in_progress`, `completed`, or `incomplete`.\n" - }), - Schema.Null - ]) - ), - "call_id": Schema.Unknown -}).annotate({ "title": "Local shell call output", "description": "The output of a local shell tool call.\n" }) -export type LogProbProperties = { - readonly "token": string - readonly "logprob": number - readonly "bytes": ReadonlyArray -} -export const LogProbProperties = Schema.Struct({ - "token": Schema.String.annotate({ "description": "The token that was used to generate the log probability.\n" }), - "logprob": Schema.Number.annotate({ "description": "The log probability of the token.\n" }).check(Schema.isFinite()), - "bytes": Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "description": "The bytes that were used to generate the log probability.\n" + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "input": Schema.String.annotate({ "description": "The input text. This may include template strings." }), + "reference": Schema.String.annotate({ "description": "The reference text. This may include template strings." }), + "operation": Schema.Literals(["eq", "ne", "like", "ilike"]).annotate({ + "description": "The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`." }) -}).annotate({ "description": "A log probability object.\n" }) -export type MCPApprovalRequest = { - readonly "type": "mcp_approval_request" - readonly "id": string - readonly "server_label": string +}).annotate({ + "title": "StringCheckGrader", + "description": + "A StringCheckGrader object that performs a string comparison between input and reference using a specified operation.\n", + "identifier": "EvalGraderStringCheck" +}) +export type EvalGraderTextSimilarity = { + readonly "type": "text_similarity" readonly "name": string - readonly "arguments": string -} -export const MCPApprovalRequest = Schema.Struct({ - "type": Schema.Literal("mcp_approval_request").annotate({ - "description": "The type of the item. Always `mcp_approval_request`.\n" - }), - "id": Schema.String.annotate({ "description": "The unique ID of the approval request.\n" }), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server making the request.\n" }), - "name": Schema.String.annotate({ "description": "The name of the tool to run.\n" }), - "arguments": Schema.String.annotate({ "description": "A JSON string of arguments for the tool.\n" }) -}).annotate({ "title": "MCP approval request", "description": "A request for human approval of a tool invocation.\n" }) -export type MCPApprovalResponseResource = { - readonly "type": "mcp_approval_response" - readonly "id": string - readonly "approval_request_id": string - readonly "approve": boolean - readonly "reason"?: string | null - readonly "request_id": unknown + readonly "input": string + readonly "reference": string + readonly "evaluation_metric": + | "cosine" + | "fuzzy_match" + | "bleu" + | "gleu" + | "meteor" + | "rouge_1" + | "rouge_2" + | "rouge_3" + | "rouge_4" + | "rouge_5" + | "rouge_l" + readonly "pass_threshold": number } -export const MCPApprovalResponseResource = Schema.Struct({ - "type": Schema.Literal("mcp_approval_response").annotate({ - "description": "The type of the item. Always `mcp_approval_response`.\n" +export const EvalGraderTextSimilarity = Schema.Struct({ + "type": Schema.Literal("text_similarity").annotate({ "description": "The type of grader." }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "input": Schema.String.annotate({ "description": "The text being graded." }), + "reference": Schema.String.annotate({ "description": "The text being graded against." }), + "evaluation_metric": Schema.Literals([ + "cosine", + "fuzzy_match", + "bleu", + "gleu", + "meteor", + "rouge_1", + "rouge_2", + "rouge_3", + "rouge_4", + "rouge_5", + "rouge_l" + ]).annotate({ + "description": + "The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, \n`gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, \nor `rouge_l`.\n" }), - "id": Schema.String.annotate({ "description": "The unique ID of the approval response\n" }), - "approval_request_id": Schema.String.annotate({ "description": "The ID of the approval request being answered.\n" }), - "approve": Schema.Boolean.annotate({ "description": "Whether the request was approved.\n" }), - "reason": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "Optional reason for the decision.\n" }), Schema.Null]) - ), - "request_id": Schema.Unknown -}).annotate({ "title": "MCP approval response", "description": "A response to an MCP approval request.\n" }) -export type MCPListToolsTool = { + "pass_threshold": Schema.Number.annotate({ "description": "The threshold for the score." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) +}).annotate({ "title": "TextSimilarityGrader", "identifier": "EvalGraderTextSimilarity" }) +export type EvalGraderPython = { + readonly "type": "python" readonly "name": string - readonly "description"?: string | null - readonly "input_schema": {} - readonly "annotations"?: {} | null + readonly "source": string + readonly "image_tag"?: string + readonly "pass_threshold"?: number } -export const MCPListToolsTool = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the tool.\n" }), - "description": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "The description of the tool.\n" }), Schema.Null]) +export const EvalGraderPython = Schema.Struct({ + "type": Schema.Literal("python").annotate({ "description": "The object type, which is always `python`." }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "source": Schema.String.annotate({ "description": "The source code of the python script." }), + "image_tag": Schema.optionalKey( + Schema.String.annotate({ "description": "The image tag to use for the python script." }) ), - "input_schema": Schema.Struct({}).annotate({ "description": "The JSON schema describing the tool's input.\n" }), - "annotations": Schema.optionalKey( - Schema.Union([ - Schema.Struct({}).annotate({ "description": "Additional annotations about the tool.\n" }), - Schema.Null - ]) + "pass_threshold": Schema.optionalKey( + Schema.Number.annotate({ "description": "The threshold for the score." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) ) -}).annotate({ "title": "MCP list tools tool", "description": "A tool available on an MCP server.\n" }) -export type MCPToolCall = { - readonly "type": "mcp_call" - readonly "id": string - readonly "server_label": string - readonly "name": string - readonly "arguments": string - readonly "output"?: string | null - readonly "error"?: string | null - readonly "status"?: "in_progress" | "completed" | "incomplete" | "calling" | "failed" - readonly "approval_request_id"?: string | null +}).annotate({ "title": "PythonGrader", "identifier": "EvalGraderPython" }) +export type CreateEvalCustomDataSourceConfig = { + readonly "type": "custom" + readonly "item_schema": { readonly [x: string]: Schema.Json } + readonly "include_sample_schema"?: boolean } -export const MCPToolCall = Schema.Struct({ - "type": Schema.Literal("mcp_call").annotate({ "description": "The type of the item. Always `mcp_call`.\n" }), - "id": Schema.String.annotate({ "description": "The unique ID of the tool call.\n" }), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server running the tool.\n" }), - "name": Schema.String.annotate({ "description": "The name of the tool that was run.\n" }), - "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments passed to the tool.\n" }), - "output": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "The output from the tool call.\n" }), Schema.Null]) - ), - "error": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "The error from the tool call, if any.\n" }), Schema.Null]) - ), - "status": Schema.optionalKey( - Schema.Literals(["in_progress", "completed", "incomplete", "calling", "failed"]).annotate({ +export const CreateEvalCustomDataSourceConfig = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "The type of data source. Always `custom`." }), + "item_schema": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The json schema for each row in the data source." + }), + "include_sample_schema": Schema.optionalKey( + Schema.Boolean.annotate({ "description": - "The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`.\n" + "Whether the eval should expect you to populate the sample namespace (ie, by generating responses off of your data source)" }) - ), - "approval_request_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "Unique identifier for the MCP tool call approval request.\nInclude this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call.\n" - }), - Schema.Null - ]) ) -}).annotate({ "title": "MCP tool call", "description": "An invocation of a tool on an MCP server.\n" }) -export type MCPToolFilter = { readonly "tool_names"?: ReadonlyArray; readonly "read_only"?: boolean } -export const MCPToolFilter = Schema.Struct({ - "tool_names": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ "title": "MCP allowed tools", "description": "List of allowed tool names." }) - ), - "read_only": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": - "Indicates whether or not a tool modifies data or is read-only. If an\nMCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint),\nit will match this filter.\n" +}).annotate({ + "title": "CustomDataSourceConfig", + "description": + "A CustomDataSourceConfig object that defines the schema for the data source used for the evaluation runs.\nThis schema is used to define the shape of the data that will be:\n- Used to define your testing criteria and\n- What data is required when creating a run\n", + "identifier": "CreateEvalCustomDataSourceConfig" +}) +export type CreateEvalLogsDataSourceConfig = { + readonly "type": "logs" + readonly "metadata"?: { readonly [x: string]: Schema.Json } +} +export const CreateEvalLogsDataSourceConfig = Schema.Struct({ + "type": Schema.Literal("logs").annotate({ "description": "The type of data source. Always `logs`." }), + "metadata": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Metadata filters for the logs data source." }) ) -}).annotate({ "title": "MCP tool filter", "description": "A filter object to specify which tools are allowed.\n" }) -export type MessageContentImageFileObject = { - readonly "type": "image_file" - readonly "image_file": { readonly "file_id": string; readonly "detail"?: "auto" | "low" | "high" } +}).annotate({ + "title": "LogsDataSourceConfig", + "description": + "A data source config which specifies the metadata property of your logs query.\nThis is usually metadata like `usecase=chatbot` or `prompt-version=v2`, etc.\n", + "identifier": "CreateEvalLogsDataSourceConfig" +}) +export type CreateEvalStoredCompletionsDataSourceConfig = { + readonly "type": "stored_completions" + readonly "metadata"?: { readonly [x: string]: Schema.Json } } -export const MessageContentImageFileObject = Schema.Struct({ - "type": Schema.Literal("image_file").annotate({ "description": "Always `image_file`." }), - "image_file": Schema.Struct({ - "file_id": Schema.String.annotate({ - "description": - "The [File](/docs/api-reference/files) ID of the image in the message content. Set `purpose=\"vision\"` when uploading the File if you need to later display the file content." - }), - "detail": Schema.optionalKey( - Schema.Literals(["auto", "low", "high"]).annotate({ - "description": - "Specifies the detail level of the image if specified by the user. `low` uses fewer tokens, you can opt in to high resolution using `high`." - }) - ) - }) +export const CreateEvalStoredCompletionsDataSourceConfig = Schema.Struct({ + "type": Schema.Literal("stored_completions").annotate({ + "description": "The type of data source. Always `stored_completions`." + }), + "metadata": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Metadata filters for the stored completions data source." + }) + ) }).annotate({ - "title": "Image file", - "description": "References an image [File](/docs/api-reference/files) in the content of a message." + "title": "StoredCompletionsDataSourceConfig", + "description": "Deprecated in favor of LogsDataSourceConfig.\n", + "identifier": "CreateEvalStoredCompletionsDataSourceConfig" }) -export type MessageContentImageUrlObject = { - readonly "type": "image_url" - readonly "image_url": { readonly "url": string; readonly "detail"?: "auto" | "low" | "high" } +export type EvalJsonlFileContentSource = { + readonly "type": "file_content" + readonly "content": ReadonlyArray< + { + readonly "item": { readonly [x: string]: Schema.Json } + readonly "sample"?: { readonly [x: string]: Schema.Json } + } + > } -export const MessageContentImageUrlObject = Schema.Struct({ - "type": Schema.Literal("image_url").annotate({ "description": "The type of the content part." }), - "image_url": Schema.Struct({ - "url": Schema.String.annotate({ - "description": "The external URL of the image, must be a supported image types: jpeg, jpg, png, gif, webp.", - "format": "uri" - }), - "detail": Schema.optionalKey( - Schema.Literals(["auto", "low", "high"]).annotate({ - "description": - "Specifies the detail level of the image. `low` uses fewer tokens, you can opt in to high resolution using `high`. Default value is `auto`" - }) - ) - }) -}).annotate({ "title": "Image URL", "description": "References an image URL in the content of a message." }) -export type MessageContentRefusalObject = { readonly "type": "refusal"; readonly "refusal": string } -export const MessageContentRefusalObject = Schema.Struct({ - "type": Schema.Literal("refusal").annotate({ "description": "Always `refusal`." }), - "refusal": Schema.String -}).annotate({ "title": "Refusal", "description": "The refusal content generated by the assistant." }) -export type MessageContentTextAnnotationsFileCitationObject = { - readonly "type": "file_citation" - readonly "text": string - readonly "file_citation": { readonly "file_id": string } - readonly "start_index": number - readonly "end_index": number -} -export const MessageContentTextAnnotationsFileCitationObject = Schema.Struct({ - "type": Schema.Literal("file_citation").annotate({ "description": "Always `file_citation`." }), - "text": Schema.String.annotate({ "description": "The text in the message content that needs to be replaced." }), - "file_citation": Schema.Struct({ - "file_id": Schema.String.annotate({ "description": "The ID of the specific File the citation is from." }) - }), - "start_index": Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), - "end_index": Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)) -}).annotate({ - "title": "File citation", - "description": - "A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the \"file_search\" tool to search files." -}) -export type MessageContentTextAnnotationsFilePathObject = { - readonly "type": "file_path" - readonly "text": string - readonly "file_path": { readonly "file_id": string } - readonly "start_index": number - readonly "end_index": number -} -export const MessageContentTextAnnotationsFilePathObject = Schema.Struct({ - "type": Schema.Literal("file_path").annotate({ "description": "Always `file_path`." }), - "text": Schema.String.annotate({ "description": "The text in the message content that needs to be replaced." }), - "file_path": Schema.Struct({ - "file_id": Schema.String.annotate({ "description": "The ID of the file that was generated." }) +export const EvalJsonlFileContentSource = Schema.Struct({ + "type": Schema.Literal("file_content").annotate({ + "description": "The type of jsonl source. Always `file_content`." }), - "start_index": Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)), - "end_index": Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)) + "content": Schema.Array( + Schema.Struct({ + "item": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), + "sample": Schema.optionalKey(Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))) + }) + ).annotate({ "description": "The content of the jsonl file." }) +}).annotate({ "title": "EvalJsonlFileContentSource", "identifier": "EvalJsonlFileContentSource" }) +export type EvalJsonlFileIdSource = { readonly "type": "file_id"; readonly "id": string } +export const EvalJsonlFileIdSource = Schema.Struct({ + "type": Schema.Literal("file_id").annotate({ "description": "The type of jsonl source. Always `file_id`." }), + "id": Schema.String.annotate({ "description": "The identifier of the file." }) +}).annotate({ "title": "EvalJsonlFileIdSource", "identifier": "EvalJsonlFileIdSource" }) +export type EvalApiError = { readonly "code": string; readonly "message": string } +export const EvalApiError = Schema.Struct({ + "code": Schema.String.annotate({ "description": "The error code." }), + "message": Schema.String.annotate({ "description": "The error message." }) }).annotate({ - "title": "File path", - "description": - "A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file." + "title": "EvalApiError", + "description": "An object representing an error response from the Eval API.\n", + "identifier": "EvalApiError" }) -export type MessageDeltaContentImageFileObject = { - readonly "index": number - readonly "type": "image_file" - readonly "image_file"?: { readonly "file_id"?: string; readonly "detail"?: "auto" | "low" | "high" } -} -export const MessageDeltaContentImageFileObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the content part in the message." }).check( - Schema.isInt() - ), - "type": Schema.Literal("image_file").annotate({ "description": "Always `image_file`." }), - "image_file": Schema.optionalKey(Schema.Struct({ - "file_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The [File](/docs/api-reference/files) ID of the image in the message content. Set `purpose=\"vision\"` when uploading the File if you need to later display the file content." - }) +export type EvalRunOutputItemResult = { + readonly "name": string + readonly "type"?: string + readonly "score": number + readonly "passed": boolean + readonly "sample"?: { readonly [x: string]: Schema.Json } | null +} & { readonly [x: string]: Schema.Json } +export const EvalRunOutputItemResult = Schema.StructWithRest( + Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "type": Schema.optionalKey( + Schema.String.annotate({ "description": "The grader type (for example, \"string-check-grader\")." }) ), - "detail": Schema.optionalKey( - Schema.Literals(["auto", "low", "high"]).annotate({ - "description": - "Specifies the detail level of the image if specified by the user. `low` uses fewer tokens, you can opt in to high resolution using `high`." - }) - ) - })) -}).annotate({ - "title": "Image file", - "description": "References an image [File](/docs/api-reference/files) in the content of a message." -}) -export type MessageDeltaContentImageUrlObject = { - readonly "index": number - readonly "type": "image_url" - readonly "image_url"?: { readonly "url"?: string; readonly "detail"?: "auto" | "low" | "high" } -} -export const MessageDeltaContentImageUrlObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the content part in the message." }).check( - Schema.isInt() - ), - "type": Schema.Literal("image_url").annotate({ "description": "Always `image_url`." }), - "image_url": Schema.optionalKey(Schema.Struct({ - "url": Schema.optionalKey( - Schema.String.annotate({ - "description": "The URL of the image, must be a supported image types: jpeg, jpg, png, gif, webp.", - "format": "uri" - }) + "score": Schema.Number.annotate({ "description": "The numeric score produced by the grader." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) ), - "detail": Schema.optionalKey( - Schema.Literals(["auto", "low", "high"]).annotate({ - "description": - "Specifies the detail level of the image. `low` uses fewer tokens, you can opt in to high resolution using `high`." - }) + "passed": Schema.Boolean.annotate({ "description": "Whether the grader considered the output a pass." }), + "sample": Schema.optionalKey( + Schema.Union([Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), Schema.Null]) + .annotate({ "description": "Optional sample or intermediate data produced by the grader." }) ) - })) -}).annotate({ "title": "Image URL", "description": "References an image URL in the content of a message." }) -export type MessageDeltaContentRefusalObject = { - readonly "index": number - readonly "type": "refusal" - readonly "refusal"?: string -} -export const MessageDeltaContentRefusalObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the refusal part in the message." }).check( - Schema.isInt() - ), - "type": Schema.Literal("refusal").annotate({ "description": "Always `refusal`." }), - "refusal": Schema.optionalKey(Schema.String) -}).annotate({ "title": "Refusal", "description": "The refusal content that is part of a message." }) -export type MessageDeltaContentTextAnnotationsFileCitationObject = { - readonly "index": number - readonly "type": "file_citation" - readonly "text"?: string - readonly "file_citation"?: { readonly "file_id"?: string; readonly "quote"?: string } - readonly "start_index"?: number - readonly "end_index"?: number -} -export const MessageDeltaContentTextAnnotationsFileCitationObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the annotation in the text content part." }).check( - Schema.isInt() - ), - "type": Schema.Literal("file_citation").annotate({ "description": "Always `file_citation`." }), - "text": Schema.optionalKey( - Schema.String.annotate({ "description": "The text in the message content that needs to be replaced." }) - ), - "file_citation": Schema.optionalKey( + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] +).annotate({ + "title": "EvalRunOutputItemResult", + "description": "A single grader result for an evaluation run output item.\n", + "identifier": "EvalRunOutputItemResult" +}) +export type OpenAIFile = + | null + | string + | number + | boolean + | { + readonly "id": string + readonly "bytes": number | null + readonly "created_at": number + readonly "expires_at"?: number | null + readonly "filename": string + readonly "object": "file" + readonly "purpose": + | "assistants" + | "assistants_output" + | "batch" + | "batch_output" + | "fine-tune" + | "fine-tune-results" + | "vision" + | "user_data" + readonly "status": "uploaded" | "processed" | "error" + readonly "status_details"?: string | null + } & { readonly [x: string]: Schema.Json } + | ReadonlyArray +export const OpenAIFile = Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.StructWithRest( Schema.Struct({ - "file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the specific File the citation is from." }) + "id": Schema.String.annotate({ + "description": "The file identifier, which can be referenced in the API endpoints." + }), + "bytes": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ + "description": + "The size of the file, in bytes. In a completed file upload response, this can\nbe null when the file size is not yet available.\n" + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the file was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "expires_at": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the file will expire.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) ), - "quote": Schema.optionalKey(Schema.String.annotate({ "description": "The specific quote in the file." })) - }) + "filename": Schema.String.annotate({ "description": "The name of the file." }), + "object": Schema.Literal("file").annotate({ "description": "The object type, which is always `file`." }), + "purpose": Schema.Literals([ + "assistants", + "assistants_output", + "batch", + "batch_output", + "fine-tune", + "fine-tune-results", + "vision", + "user_data" + ]).annotate({ + "description": + "The intended purpose of the file. Supported values are `assistants`, `assistants_output`, `batch`, `batch_output`, `fine-tune`, `fine-tune-results`, `vision`, and `user_data`." + }), + "status": Schema.Literals(["uploaded", "processed", "error"]).annotate({ + "description": + "Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or `error`." + }), + "status_details": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "Deprecated. For details on why a fine-tuning training file failed validation, see the `error` field on `fine_tuning.job`. Completed file upload responses can return null when these details are unset." + }) + ) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] ), - "start_index": Schema.optionalKey(Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0))), - "end_index": Schema.optionalKey(Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0))) + Schema.Array(Schema.Json.annotate({ "expected": "JSON value" })) +]).annotate({ + "title": "OpenAIFile", + "description": "The `File` object represents a document that has been uploaded to OpenAI.", + "identifier": "OpenAIFile" +}) +export type FileExpirationAfter = { readonly "anchor": "created_at"; readonly "seconds": number } +export const FileExpirationAfter = Schema.Struct({ + "anchor": Schema.Literal("created_at").annotate({ + "description": "Anchor timestamp after which the expiration policy applies. Supported anchors: `created_at`." + }), + "seconds": Schema.Number.annotate({ + "description": + "The number of seconds after the anchor time that the file will expire. Must be between 3600 (1 hour) and 2592000 (30 days).", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(3600).annotate({ "expected": "a value greater than or equal to 3600" }) + ).check(Schema.isLessThanOrEqualTo(2592000).annotate({ "expected": "a value less than or equal to 2592000" })) }).annotate({ - "title": "File citation", + "title": "File expiration policy", "description": - "A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the \"file_search\" tool to search files." + "The expiration policy for a file. By default, files with `purpose=batch` expire after 30 days and all other files are persisted until they are manually deleted.", + "identifier": "FileExpirationAfter" }) -export type MessageDeltaContentTextAnnotationsFilePathObject = { - readonly "index": number - readonly "type": "file_path" - readonly "text"?: string - readonly "file_path"?: { readonly "file_id"?: string } - readonly "start_index"?: number - readonly "end_index"?: number +export type DeleteFileResponse = { readonly "id": string; readonly "object": "file"; readonly "deleted": boolean } +export const DeleteFileResponse = Schema.Struct({ + "id": Schema.String, + "object": Schema.Literal("file"), + "deleted": Schema.Boolean +}).annotate({ "identifier": "DeleteFileResponse" }) +export type GraderStringCheck = { + readonly "type": "string_check" + readonly "name": string + readonly "input": string + readonly "reference": string + readonly "operation": "eq" | "ne" | "like" | "ilike" } -export const MessageDeltaContentTextAnnotationsFilePathObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the annotation in the text content part." }).check( - Schema.isInt() - ), - "type": Schema.Literal("file_path").annotate({ "description": "Always `file_path`." }), - "text": Schema.optionalKey( - Schema.String.annotate({ "description": "The text in the message content that needs to be replaced." }) - ), - "file_path": Schema.optionalKey( - Schema.Struct({ - "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the file that was generated." })) - }) - ), - "start_index": Schema.optionalKey(Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0))), - "end_index": Schema.optionalKey(Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0))) +export const GraderStringCheck = Schema.Struct({ + "type": Schema.Literal("string_check").annotate({ + "description": "The object type, which is always `string_check`." + }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "input": Schema.String.annotate({ "description": "The input text. This may include template strings." }), + "reference": Schema.String.annotate({ "description": "The reference text. This may include template strings." }), + "operation": Schema.Literals(["eq", "ne", "like", "ilike"]).annotate({ + "description": "The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`." + }) }).annotate({ - "title": "File path", - "description": - "A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file." -}) -export type MessagePhase = "commentary" | "final_answer" -export const MessagePhase = Schema.Literals(["commentary", "final_answer"]).annotate({ + "title": "StringCheckGrader", "description": - "Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`).\nFor models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend\nphase on all assistant messages — dropping it can degrade performance. Not used for user messages.\n" + "A StringCheckGrader object that performs a string comparison between input and reference using a specified operation.\n", + "identifier": "GraderStringCheck" }) -export type MessageRequestContentTextObject = { readonly "type": "text"; readonly "text": string } -export const MessageRequestContentTextObject = Schema.Struct({ - "type": Schema.Literal("text").annotate({ "description": "Always `text`." }), - "text": Schema.String.annotate({ "description": "Text content to be sent to the model" }) -}).annotate({ "title": "Text", "description": "The text content that is part of a message." }) -export type Metadata = {} | null -export const Metadata = Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null -]) -export type Model = { - readonly "id": string - readonly "created": number - readonly "object": "model" - readonly "owned_by": string - readonly [x: string]: unknown -} -export const Model = Schema.StructWithRest( - Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The model identifier, which can be referenced in the API endpoints." - }), - "created": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) when the model was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "object": Schema.Literal("model").annotate({ "description": "The object type, which is always \"model\"." }), - "owned_by": Schema.String.annotate({ "description": "The organization that owns the model." }) - }), - [Schema.Record(Schema.String, Schema.Json)] -).annotate({ "title": "Model", "description": "Describes an OpenAI model offering that can be used with the API." }) -export type ModelIdsShared = - | string - | "gpt-5.4" - | "gpt-5.4-mini" - | "gpt-5.4-nano" - | "gpt-5.4-mini-2026-03-17" - | "gpt-5.4-nano-2026-03-17" - | "gpt-5.3-chat-latest" - | "gpt-5.2" - | "gpt-5.2-2025-12-11" - | "gpt-5.2-chat-latest" - | "gpt-5.2-pro" - | "gpt-5.2-pro-2025-12-11" - | "gpt-5.1" - | "gpt-5.1-2025-11-13" - | "gpt-5.1-codex" - | "gpt-5.1-mini" - | "gpt-5.1-chat-latest" - | "gpt-5" - | "gpt-5-mini" - | "gpt-5-nano" - | "gpt-5-2025-08-07" - | "gpt-5-mini-2025-08-07" - | "gpt-5-nano-2025-08-07" - | "gpt-5-chat-latest" - | "gpt-4.1" - | "gpt-4.1-mini" - | "gpt-4.1-nano" - | "gpt-4.1-2025-04-14" - | "gpt-4.1-mini-2025-04-14" - | "gpt-4.1-nano-2025-04-14" - | "o4-mini" - | "o4-mini-2025-04-16" - | "o3" - | "o3-2025-04-16" - | "o3-mini" - | "o3-mini-2025-01-31" - | "o1" - | "o1-2024-12-17" - | "o1-preview" - | "o1-preview-2024-09-12" - | "o1-mini" - | "o1-mini-2024-09-12" - | "gpt-4o" - | "gpt-4o-2024-11-20" - | "gpt-4o-2024-08-06" - | "gpt-4o-2024-05-13" - | "gpt-4o-audio-preview" - | "gpt-4o-audio-preview-2024-10-01" - | "gpt-4o-audio-preview-2024-12-17" - | "gpt-4o-audio-preview-2025-06-03" - | "gpt-4o-mini-audio-preview" - | "gpt-4o-mini-audio-preview-2024-12-17" - | "gpt-4o-search-preview" - | "gpt-4o-mini-search-preview" - | "gpt-4o-search-preview-2025-03-11" - | "gpt-4o-mini-search-preview-2025-03-11" - | "chatgpt-4o-latest" - | "codex-mini-latest" - | "gpt-4o-mini" - | "gpt-4o-mini-2024-07-18" - | "gpt-4-turbo" - | "gpt-4-turbo-2024-04-09" - | "gpt-4-0125-preview" - | "gpt-4-turbo-preview" - | "gpt-4-1106-preview" - | "gpt-4-vision-preview" - | "gpt-4" - | "gpt-4-0314" - | "gpt-4-0613" - | "gpt-4-32k" - | "gpt-4-32k-0314" - | "gpt-4-32k-0613" - | "gpt-3.5-turbo" - | "gpt-3.5-turbo-16k" - | "gpt-3.5-turbo-0301" - | "gpt-3.5-turbo-0613" - | "gpt-3.5-turbo-1106" - | "gpt-3.5-turbo-0125" - | "gpt-3.5-turbo-16k-0613" -export const ModelIdsShared = Schema.Union([ - Schema.String, - Schema.Literals([ - "gpt-5.4", - "gpt-5.4-mini", - "gpt-5.4-nano", - "gpt-5.4-mini-2026-03-17", - "gpt-5.4-nano-2026-03-17", - "gpt-5.3-chat-latest", - "gpt-5.2", - "gpt-5.2-2025-12-11", - "gpt-5.2-chat-latest", - "gpt-5.2-pro", - "gpt-5.2-pro-2025-12-11", - "gpt-5.1", - "gpt-5.1-2025-11-13", - "gpt-5.1-codex", - "gpt-5.1-mini", - "gpt-5.1-chat-latest", - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-5-2025-08-07", - "gpt-5-mini-2025-08-07", - "gpt-5-nano-2025-08-07", - "gpt-5-chat-latest", - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4.1-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "o4-mini", - "o4-mini-2025-04-16", - "o3", - "o3-2025-04-16", - "o3-mini", - "o3-mini-2025-01-31", - "o1", - "o1-2024-12-17", - "o1-preview", - "o1-preview-2024-09-12", - "o1-mini", - "o1-mini-2024-09-12", - "gpt-4o", - "gpt-4o-2024-11-20", - "gpt-4o-2024-08-06", - "gpt-4o-2024-05-13", - "gpt-4o-audio-preview", - "gpt-4o-audio-preview-2024-10-01", - "gpt-4o-audio-preview-2024-12-17", - "gpt-4o-audio-preview-2025-06-03", - "gpt-4o-mini-audio-preview", - "gpt-4o-mini-audio-preview-2024-12-17", - "gpt-4o-search-preview", - "gpt-4o-mini-search-preview", - "gpt-4o-search-preview-2025-03-11", - "gpt-4o-mini-search-preview-2025-03-11", - "chatgpt-4o-latest", - "codex-mini-latest", - "gpt-4o-mini", - "gpt-4o-mini-2024-07-18", - "gpt-4-turbo", - "gpt-4-turbo-2024-04-09", - "gpt-4-0125-preview", - "gpt-4-turbo-preview", - "gpt-4-1106-preview", - "gpt-4-vision-preview", - "gpt-4", - "gpt-4-0314", - "gpt-4-0613", - "gpt-4-32k", - "gpt-4-32k-0314", - "gpt-4-32k-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0301", - "gpt-3.5-turbo-0613", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-0125", - "gpt-3.5-turbo-16k-0613" - ]) -]) -export type ModifyCertificateRequest = { readonly "name"?: string } -export const ModifyCertificateRequest = Schema.Struct({ - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The updated name for the certificate" })) -}) -export type NoiseReductionType = "near_field" | "far_field" -export const NoiseReductionType = Schema.Literals(["near_field", "far_field"]).annotate({ - "description": - "Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones.\n" -}) -export type OpenAIFile = { - readonly "id": string - readonly "bytes": number - readonly "created_at": number - readonly "expires_at"?: number | null - readonly "filename": string - readonly "object": "file" - readonly "purpose": - | "assistants" - | "assistants_output" - | "batch" - | "batch_output" - | "fine-tune" - | "fine-tune-results" - | "vision" - | "user_data" - readonly "status": "uploaded" | "processed" | "error" - readonly "status_details"?: string | null - readonly [x: string]: unknown -} -export const OpenAIFile = Schema.StructWithRest( - Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The file identifier, which can be referenced in the API endpoints." - }), - "bytes": Schema.Number.annotate({ "description": "The size of the file, in bytes." }).check(Schema.isInt()), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the file was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "expires_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the file will expire.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "filename": Schema.String.annotate({ "description": "The name of the file." }), - "object": Schema.Literal("file").annotate({ "description": "The object type, which is always `file`." }), - "purpose": Schema.Literals([ - "assistants", - "assistants_output", - "batch", - "batch_output", - "fine-tune", - "fine-tune-results", - "vision", - "user_data" - ]).annotate({ - "description": - "The intended purpose of the file. Supported values are `assistants`, `assistants_output`, `batch`, `batch_output`, `fine-tune`, `fine-tune-results`, `vision`, and `user_data`." - }), - "status": Schema.Literals(["uploaded", "processed", "error"]).annotate({ - "description": - "Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or `error`." - }), - "status_details": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Deprecated. For details on why a fine-tuning training file failed validation, see the `error` field on `fine_tuning.job`." - }) - ) - }), - [Schema.Record(Schema.String, Schema.Json)] -).annotate({ - "title": "OpenAIFile", - "description": "The `File` object represents a document that has been uploaded to OpenAI." +export type GraderTextSimilarity = { + readonly "type": "text_similarity" + readonly "name": string + readonly "input": string + readonly "reference": string + readonly "evaluation_metric": + | "cosine" + | "fuzzy_match" + | "bleu" + | "gleu" + | "meteor" + | "rouge_1" + | "rouge_2" + | "rouge_3" + | "rouge_4" + | "rouge_5" + | "rouge_l" +} +export const GraderTextSimilarity = Schema.Struct({ + "type": Schema.Literal("text_similarity").annotate({ "description": "The type of grader." }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "input": Schema.String.annotate({ "description": "The text being graded." }), + "reference": Schema.String.annotate({ "description": "The text being graded against." }), + "evaluation_metric": Schema.Literals([ + "cosine", + "fuzzy_match", + "bleu", + "gleu", + "meteor", + "rouge_1", + "rouge_2", + "rouge_3", + "rouge_4", + "rouge_5", + "rouge_l" + ]).annotate({ + "description": + "The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, \n`gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, \nor `rouge_l`.\n" + }) +}).annotate({ + "title": "TextSimilarityGrader", + "description": "A TextSimilarityGrader object which grades text based on similarity metrics.\n", + "identifier": "GraderTextSimilarity" }) -export type OrganizationCertificate = { - readonly "object": "organization.certificate" - readonly "id": string - readonly "name": string | null - readonly "created_at": number - readonly "certificate_details": { readonly "valid_at"?: number; readonly "expires_at"?: number } - readonly "active": boolean +export type GraderPython = { + readonly "type": "python" + readonly "name": string + readonly "source": string + readonly "image_tag"?: string } -export const OrganizationCertificate = Schema.Struct({ - "object": Schema.Literal("organization.certificate").annotate({ - "description": "The object type, which is always `organization.certificate`." - }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the certificate." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate was uploaded.", - "format": "unixtime" - }).check(Schema.isInt()), - "certificate_details": Schema.Struct({ - "valid_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate becomes valid.", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "expires_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate expires.", - "format": "unixtime" - }).check(Schema.isInt()) - ) +export const GraderPython = Schema.Struct({ + "type": Schema.Literal("python").annotate({ "description": "The object type, which is always `python`." }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "source": Schema.String.annotate({ "description": "The source code of the python script." }), + "image_tag": Schema.optionalKey( + Schema.String.annotate({ "description": "The image tag to use for the python script." }) + ) +}).annotate({ + "title": "PythonGrader", + "description": "A PythonGrader object that runs a python script on the input.\n", + "identifier": "GraderPython" +}) +export type RunGraderResponse = { + readonly "reward": number + readonly "metadata": { + readonly "name": string + readonly "type": string + readonly "errors": { + readonly "formula_parse_error": boolean + readonly "sample_parse_error": boolean + readonly "truncated_observation_error": boolean + readonly "unresponsive_reward_error": boolean + readonly "invalid_variable_error": boolean + readonly "other_error": boolean + readonly "python_grader_server_error": boolean + readonly "python_grader_server_error_type": string | null + readonly "python_grader_runtime_error": boolean + readonly "python_grader_runtime_error_details": string | null + readonly "model_grader_server_error": boolean + readonly "model_grader_refusal_error": boolean + readonly "model_grader_parse_error": boolean + readonly "model_grader_server_error_details": string | null + } + readonly "execution_time": number + readonly "scores": { readonly [x: string]: Schema.Json } + readonly "token_usage": { + readonly "prompt_tokens": number + readonly "total_tokens": number + readonly "completion_tokens"?: number | null + readonly "cached_tokens"?: number | null + } | null + readonly "sampled_model_name": string | null + } + readonly "sub_rewards": { readonly [x: string]: Schema.Json } + readonly "model_grader_token_usage_per_model": { readonly [x: string]: Schema.Json } +} +export const RunGraderResponse = Schema.Struct({ + "reward": Schema.Finite, + "metadata": Schema.Struct({ + "name": Schema.String, + "type": Schema.String, + "errors": Schema.Struct({ + "formula_parse_error": Schema.Boolean, + "sample_parse_error": Schema.Boolean, + "truncated_observation_error": Schema.Boolean, + "unresponsive_reward_error": Schema.Boolean, + "invalid_variable_error": Schema.Boolean, + "other_error": Schema.Boolean, + "python_grader_server_error": Schema.Boolean, + "python_grader_server_error_type": Schema.Union([Schema.String, Schema.Null]), + "python_grader_runtime_error": Schema.Boolean, + "python_grader_runtime_error_details": Schema.Union([Schema.String, Schema.Null]), + "model_grader_server_error": Schema.Boolean, + "model_grader_refusal_error": Schema.Boolean, + "model_grader_parse_error": Schema.Boolean, + "model_grader_server_error_details": Schema.Union([Schema.String, Schema.Null]) + }), + "execution_time": Schema.Finite, + "scores": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), + "token_usage": Schema.Union([ + Schema.Struct({ + "prompt_tokens": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "total_tokens": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "completion_tokens": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + ), + "cached_tokens": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + ) + }), + Schema.Null + ]), + "sampled_model_name": Schema.Union([Schema.String, Schema.Null]) }), - "active": Schema.Boolean.annotate({ - "description": "Whether the certificate is currently active at the organization level." - }) -}).annotate({ "description": "Represents an individual certificate configured at the organization level." }) -export type OrganizationProjectCertificate = { - readonly "object": "organization.project.certificate" + "sub_rewards": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), + "model_grader_token_usage_per_model": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) +}).annotate({ "identifier": "RunGraderResponse" }) +export type FineTuningCheckpointPermission = { readonly "id": string - readonly "name": string | null readonly "created_at": number - readonly "certificate_details": { readonly "valid_at"?: number; readonly "expires_at"?: number } - readonly "active": boolean + readonly "project_id": string + readonly "object": "checkpoint.permission" } -export const OrganizationProjectCertificate = Schema.Struct({ - "object": Schema.Literal("organization.project.certificate").annotate({ - "description": "The object type, which is always `organization.project.certificate`." +export const FineTuningCheckpointPermission = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The permission identifier, which can be referenced in the API endpoints." }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the certificate." }), "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate was uploaded.", + "description": "The Unix timestamp (in seconds) for when the permission was created.", "format": "unixtime" - }).check(Schema.isInt()), - "certificate_details": Schema.Struct({ - "valid_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate becomes valid.", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "expires_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the certificate expires.", - "format": "unixtime" - }).check(Schema.isInt()) - ) - }), - "active": Schema.Boolean.annotate({ - "description": "Whether the certificate is currently active at the project level." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "project_id": Schema.String.annotate({ "description": "The project identifier that the permission is for." }), + "object": Schema.Literal("checkpoint.permission").annotate({ + "description": "The object type, which is always \"checkpoint.permission\"." }) -}).annotate({ "description": "Represents an individual certificate configured at the project level." }) -export type ParallelToolCalls = boolean -export const ParallelToolCalls = Schema.Boolean.annotate({ - "description": - "Whether to enable [parallel function calling](/docs/guides/function-calling#configuring-parallel-function-calling) during tool use." +}).annotate({ + "title": "FineTuningCheckpointPermission", + "description": "The `checkpoint.permission` object represents a permission for a fine-tuned model checkpoint.\n", + "identifier": "FineTuningCheckpointPermission" }) -export type PartialImages = number | null -export const PartialImages = Schema.Union([ - Schema.Number.annotate({ - "description": - "The number of partial images to generate. This parameter is used for\nstreaming responses that return partial images. Value must be between 0 and 3.\nWhen set to 0, the response will be a single image sent in one streaming event.\n\nNote that the final image may be sent before the full number of partial images\nare generated if the full image is generated more quickly.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(3)), - Schema.Null -]) -export type Project = { +export type CreateFineTuningCheckpointPermissionRequest = { readonly "project_ids": ReadonlyArray } +export const CreateFineTuningCheckpointPermissionRequest = Schema.Struct({ + "project_ids": Schema.Array(Schema.String).annotate({ "description": "The project identifiers to grant access to." }) +}).annotate({ "identifier": "CreateFineTuningCheckpointPermissionRequest" }) +export type DeleteFineTuningCheckpointPermissionResponse = { readonly "id": string - readonly "object": "organization.project" - readonly "name"?: string | null - readonly "created_at": number - readonly "archived_at"?: number | null - readonly "status"?: string | null - readonly "external_key_id"?: string | null + readonly "object": "checkpoint.permission" + readonly "deleted": boolean } -export const Project = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "object": Schema.Literal("organization.project").annotate({ - "description": "The object type, which is always `organization.project`" +export const DeleteFineTuningCheckpointPermissionResponse = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The ID of the fine-tuned model checkpoint permission that was deleted." }), - "name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "The name of the project. This appears in reporting." + "object": Schema.Literal("checkpoint.permission").annotate({ + "description": "The object type, which is always \"checkpoint.permission\"." + }), + "deleted": Schema.Boolean.annotate({ + "description": "Whether the fine-tuned model checkpoint permission was successfully deleted." + }) +}).annotate({ "identifier": "DeleteFineTuningCheckpointPermissionResponse" }) +export type FineTuningIntegration = { + readonly "type": "wandb" + readonly "wandb": { + readonly "project": string + readonly "name"?: string | null + readonly "entity"?: string | null + readonly "tags"?: ReadonlyArray + } +} +export const FineTuningIntegration = Schema.Struct({ + "type": Schema.Literal("wandb").annotate({ + "description": "The type of the integration being enabled for the fine-tuning job" + }), + "wandb": Schema.Struct({ + "project": Schema.String.annotate({ + "description": "The name of the project that the new run will be created under.\n" + }), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "A display name to set for the run. If not set, we will use the Job ID as the name.\n" + }), + Schema.Null + ]) + ), + "entity": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The entity to use for the run. This allows you to set the team or username of the WandB user that you would\nlike associated with the run. If not set, the default entity for the registered WandB API key is used.\n" + }), + Schema.Null + ]) + ), + "tags": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of tags to be attached to the newly created run. These tags are passed through directly to WandB. Some\ndefault tags are generated by OpenAI: \"openai/finetune\", \"openai/{base-model}\", \"openai/{ftjob-abcdef}\".\n" + }) + ) + }).annotate({ + "description": + "The settings for your integration with Weights and Biases. This payload specifies the project that\nmetrics will be sent to. Optionally, you can set an explicit display name for your run, add tags\nto your run, and set a default entity (team, username, etc) to be associated with your run.\n" + }) +}).annotate({ "title": "Fine-Tuning Job Integration", "identifier": "FineTuningIntegration" }) +export type FineTuneSupervisedHyperparameters = { + readonly "batch_size"?: "auto" | number + readonly "learning_rate_multiplier"?: "auto" | number + readonly "n_epochs"?: "auto" | number +} +export const FineTuneSupervisedHyperparameters = Schema.Struct({ + "batch_size": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(256).annotate({ "expected": "a value less than or equal to 256" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance.\n" }) ), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the project was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "archived_at": Schema.optionalKey( + "learning_rate_multiplier": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the project was archived or `null`.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "status": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "`active` or `archived`" }) + Schema.Literal("auto"), + Schema.Finite.check(Schema.isGreaterThan(0).annotate({ "expected": "a value greater than 0" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting.\n" + }) ), - "external_key_id": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "The external key associated with the project." + "n_epochs": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(50).annotate({ "expected": "a value less than or equal to 50" })) + ], { mode: "oneOf" }).annotate({ + "description": + "The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.\n" }) ) -}).annotate({ "description": "Represents an individual project." }) -export type ProjectApiKeyDeleteResponse = { - readonly "object": "organization.project.api_key.deleted" - readonly "id": string - readonly "deleted": boolean -} -export const ProjectApiKeyDeleteResponse = Schema.Struct({ - "object": Schema.Literal("organization.project.api_key.deleted"), - "id": Schema.String, - "deleted": Schema.Boolean +}).annotate({ + "description": "The hyperparameters used for the fine-tuning job.", + "identifier": "FineTuneSupervisedHyperparameters" }) -export type ProjectApiKeyOwnerServiceAccount = { - readonly "id": string - readonly "name": string - readonly "created_at": number - readonly "role": string -} -export const ProjectApiKeyOwnerServiceAccount = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.String.annotate({ "description": "The name of the service account." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the service account was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "role": Schema.String.annotate({ "description": "The service account's project role." }) -}).annotate({ "description": "The service account that owns a project API key." }) -export type ProjectApiKeyOwnerUser = { - readonly "id": string - readonly "email": string - readonly "name": string - readonly "created_at": number - readonly "role": string +export type FineTuneDPOHyperparameters = { + readonly "beta"?: "auto" | number + readonly "batch_size"?: "auto" | number + readonly "learning_rate_multiplier"?: "auto" | number + readonly "n_epochs"?: "auto" | number } -export const ProjectApiKeyOwnerUser = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "email": Schema.String.annotate({ "description": "The email address of the user." }), - "name": Schema.String.annotate({ "description": "The name of the user." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the user was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "role": Schema.String.annotate({ "description": "The user's project role." }) -}).annotate({ "description": "The user that owns a project API key." }) -export type ProjectCreateRequest = { - readonly "name": string - readonly "geography"?: string | null - readonly "external_key_id"?: string | null +export const FineTuneDPOHyperparameters = Schema.Struct({ + "beta": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Finite.check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })) + .check(Schema.isGreaterThan(0).annotate({ "expected": "a value greater than 0" })) + ], { mode: "oneOf" }).annotate({ + "description": + "The beta value for the DPO method. A higher beta value will increase the weight of the penalty between the policy and reference model.\n" + }) + ), + "batch_size": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(256).annotate({ "expected": "a value less than or equal to 256" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance.\n" + }) + ), + "learning_rate_multiplier": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Finite.check(Schema.isGreaterThan(0).annotate({ "expected": "a value greater than 0" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting.\n" + }) + ), + "n_epochs": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(50).annotate({ "expected": "a value less than or equal to 50" })) + ], { mode: "oneOf" }).annotate({ + "description": + "The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.\n" + }) + ) +}).annotate({ + "description": "The hyperparameters used for the DPO fine-tuning job.", + "identifier": "FineTuneDPOHyperparameters" +}) +export type FineTuneReinforcementHyperparameters = { + readonly "batch_size"?: "auto" | number + readonly "learning_rate_multiplier"?: "auto" | number + readonly "n_epochs"?: "auto" | number + readonly "reasoning_effort"?: "default" | "low" | "medium" | "high" + readonly "compute_multiplier"?: "auto" | number + readonly "eval_interval"?: "auto" | number + readonly "eval_samples"?: "auto" | number } -export const ProjectCreateRequest = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The friendly name of the project, this name appears in reports." }), - "geography": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ +export const FineTuneReinforcementHyperparameters = Schema.Struct({ + "batch_size": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(256).annotate({ "expected": "a value less than or equal to 256" })) + ], { mode: "oneOf" }).annotate({ "description": - "Create the project with the specified data residency region. Your organization must have access to Data residency functionality in order to use. See [data residency controls](/docs/guides/your-data#data-residency-controls) to review the functionality and limitations of setting this field." + "Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance.\n" }) ), - "external_key_id": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "External key ID to associate with the project." + "learning_rate_multiplier": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Finite.check(Schema.isGreaterThan(0).annotate({ "expected": "a value greater than 0" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting.\n" + }) + ), + "n_epochs": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(50).annotate({ "expected": "a value less than or equal to 50" })) + ], { mode: "oneOf" }).annotate({ + "description": + "The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.\n" + }) + ), + "reasoning_effort": Schema.optionalKey( + Schema.Literals(["default", "low", "medium", "high"]).annotate({ "description": "Level of reasoning effort.\n" }) + ), + "compute_multiplier": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Finite.check(Schema.isLessThanOrEqualTo(10).annotate({ "expected": "a value less than or equal to 10" })) + .check(Schema.isGreaterThan(0.00001).annotate({ "expected": "a value greater than 0.00001" })) + ], { mode: "oneOf" }).annotate({ + "description": "Multiplier on amount of compute used for exploring search space during training.\n" }) + ), + "eval_interval": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ) + ], { mode: "oneOf" }).annotate({ "description": "The number of training steps between evaluation runs.\n" }) + ), + "eval_samples": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ) + ], { mode: "oneOf" }).annotate({ "description": "Number of evaluation samples to generate per training step.\n" }) ) +}).annotate({ + "description": "The hyperparameters used for the reinforcement fine-tuning job.", + "identifier": "FineTuneReinforcementHyperparameters" }) -export type ProjectGroup = { - readonly "object": "project.group" - readonly "project_id": string - readonly "group_id": string - readonly "group_name": string - readonly "group_type": string +export type FineTuningJobCheckpoint = { + readonly "id": string readonly "created_at": number + readonly "fine_tuned_model_checkpoint": string + readonly "step_number": number + readonly "metrics": { + readonly "step"?: number + readonly "train_loss"?: number + readonly "train_mean_token_accuracy"?: number + readonly "valid_loss"?: number + readonly "valid_mean_token_accuracy"?: number + readonly "full_valid_loss"?: number + readonly "full_valid_mean_token_accuracy"?: number + } + readonly "fine_tuning_job_id": string + readonly "object": "fine_tuning.job.checkpoint" } -export const ProjectGroup = Schema.Struct({ - "object": Schema.Literal("project.group").annotate({ "description": "Always `project.group`." }), - "project_id": Schema.String.annotate({ "description": "Identifier of the project." }), - "group_id": Schema.String.annotate({ "description": "Identifier of the group that has access to the project." }), - "group_name": Schema.String.annotate({ "description": "Display name of the group." }), - "group_type": Schema.String.annotate({ "description": "The type of the group." }), +export const FineTuningJobCheckpoint = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The checkpoint identifier, which can be referenced in the API endpoints." + }), "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the group was granted project access.", + "description": "The Unix timestamp (in seconds) for when the checkpoint was created.", "format": "unixtime" - }).check(Schema.isInt()) -}).annotate({ "description": "Details about a group's membership in a project." }) -export type ProjectGroupDeletedResource = { readonly "object": "project.group.deleted"; readonly "deleted": boolean } -export const ProjectGroupDeletedResource = Schema.Struct({ - "object": Schema.Literal("project.group.deleted").annotate({ "description": "Always `project.group.deleted`." }), - "deleted": Schema.Boolean.annotate({ "description": "Whether the group membership in the project was removed." }) -}).annotate({ "description": "Confirmation payload returned after removing a group from a project." }) -export type ProjectModelPermissions = { - readonly "object": "project.model_permissions" - readonly "mode": "allow_list" | "deny_list" - readonly "model_ids": ReadonlyArray -} -export const ProjectModelPermissions = Schema.Struct({ - "object": Schema.Literal("project.model_permissions").annotate({ - "description": "The object type, which is always `project.model_permissions`." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "fine_tuned_model_checkpoint": Schema.String.annotate({ + "description": "The name of the fine-tuned checkpoint model that is created." }), - "mode": Schema.Literals(["allow_list", "deny_list"]).annotate({ - "description": "Whether the project uses an allowlist or a denylist." + "step_number": Schema.Number.annotate({ "description": "The step number that the checkpoint was created at." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "metrics": Schema.Struct({ + "step": Schema.optionalKey(Schema.Finite), + "train_loss": Schema.optionalKey(Schema.Finite), + "train_mean_token_accuracy": Schema.optionalKey(Schema.Finite), + "valid_loss": Schema.optionalKey(Schema.Finite), + "valid_mean_token_accuracy": Schema.optionalKey(Schema.Finite), + "full_valid_loss": Schema.optionalKey(Schema.Finite), + "full_valid_mean_token_accuracy": Schema.optionalKey(Schema.Finite) + }).annotate({ "description": "Metrics at the step number during the fine-tuning job." }), + "fine_tuning_job_id": Schema.String.annotate({ + "description": "The name of the fine-tuning job that this checkpoint was created from." }), - "model_ids": Schema.Array(Schema.String).annotate({ - "description": "The model IDs included in the model permissions policy." + "object": Schema.Literal("fine_tuning.job.checkpoint").annotate({ + "description": "The object type, which is always \"fine_tuning.job.checkpoint\"." }) -}).annotate({ "description": "Represents the model allowlist or denylist policy for a project." }) -export type ProjectModelPermissionsDeleteResponse = { - readonly "object": "project.model_permissions.deleted" - readonly "deleted": boolean +}).annotate({ + "title": "FineTuningJobCheckpoint", + "description": + "The `fine_tuning.job.checkpoint` object represents a model checkpoint for a fine-tuning job that is ready to use.\n", + "identifier": "FineTuningJobCheckpoint" +}) +export type FineTuningJobEvent = { + readonly "object": "fine_tuning.job.event" + readonly "id": string + readonly "created_at": number + readonly "level": "info" | "warn" | "error" + readonly "message": string + readonly "type"?: "message" | "metrics" + readonly "data"?: { readonly [x: string]: Schema.Json } | null } -export const ProjectModelPermissionsDeleteResponse = Schema.Struct({ - "object": Schema.Literal("project.model_permissions.deleted").annotate({ - "description": "The object type, which is always `project.model_permissions.deleted`." +export const FineTuningJobEvent = Schema.Struct({ + "object": Schema.Literal("fine_tuning.job.event").annotate({ + "description": "The object type, which is always \"fine_tuning.job.event\"." }), - "deleted": Schema.Boolean.annotate({ "description": "Whether the project model permissions were deleted." }) -}).annotate({ "description": "Confirmation payload returned after deleting project model permissions." }) -export type ProjectModelPermissionsUpdateRequest = { - readonly "mode": "allow_list" | "deny_list" - readonly "model_ids": ReadonlyArray + "id": Schema.String.annotate({ "description": "The object identifier." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the fine-tuning job was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "level": Schema.Literals(["info", "warn", "error"]).annotate({ "description": "The log level of the event." }), + "message": Schema.String.annotate({ "description": "The message of the event." }), + "type": Schema.optionalKey(Schema.Literals(["message", "metrics"]).annotate({ "description": "The type of event." })), + "data": Schema.optionalKey( + Schema.Union([Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), Schema.Null]) + .annotate({ "description": "The data associated with the event." }) + ) +}).annotate({ "description": "Fine-tuning job event object", "identifier": "FineTuningJobEvent" }) +export type ImageRefParam = { readonly "image_url": string; readonly "file_id"?: string } | { + readonly "image_url"?: string + readonly "file_id": string } -export const ProjectModelPermissionsUpdateRequest = Schema.Struct({ - "mode": Schema.Literals(["allow_list", "deny_list"]).annotate({ - "description": "The model permissions mode to apply." +export const ImageRefParam = Schema.Union([ + Schema.Struct({ + "image_url": Schema.String.annotate({ + "description": "A fully qualified URL or base64-encoded data URL.", + "format": "uri" + }).check(Schema.isMaxCodePoints(20971520).annotate({ "expected": "a string with at most 20971520 code points" })), + "file_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The File API ID of an uploaded image to use as input." }) + ) }), - "model_ids": Schema.Array(Schema.String).annotate({ - "description": "The model IDs included in this permissions policy." + Schema.Struct({ + "image_url": Schema.optionalKey( + Schema.String.annotate({ "description": "A fully qualified URL or base64-encoded data URL.", "format": "uri" }) + .check(Schema.isMaxCodePoints(20971520).annotate({ "expected": "a string with at most 20971520 code points" })) + ), + "file_id": Schema.String.annotate({ "description": "The File API ID of an uploaded image to use as input." }) }) +], { mode: "oneOf" }).annotate({ + "description": + "Reference an input image by either URL or uploaded file ID.\nProvide exactly one of `image_url` or `file_id`.\n", + "identifier": "ImageRefParam" }) -export type ProjectRateLimit = { - readonly "object": "project.rate_limit" - readonly "id": string - readonly "model": string - readonly "max_requests_per_1_minute": number - readonly "max_tokens_per_1_minute": number - readonly "max_images_per_1_minute"?: number - readonly "max_audio_megabytes_per_1_minute"?: number - readonly "max_requests_per_1_day"?: number - readonly "batch_1_day_max_input_tokens"?: number -} -export const ProjectRateLimit = Schema.Struct({ - "object": Schema.Literal("project.rate_limit").annotate({ - "description": "The object type, which is always `project.rate_limit`" - }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), - "model": Schema.String.annotate({ "description": "The model this rate limit applies to." }), - "max_requests_per_1_minute": Schema.Number.annotate({ "description": "The maximum requests per minute." }).check( - Schema.isInt() - ), - "max_tokens_per_1_minute": Schema.Number.annotate({ "description": "The maximum tokens per minute." }).check( - Schema.isInt() - ), - "max_images_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum images per minute. Only present for relevant models." }).check( - Schema.isInt() - ) - ), - "max_audio_megabytes_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum audio megabytes per minute. Only present for relevant models." - }).check(Schema.isInt()) +export type PartialImages = number | null +export const PartialImages = Schema.Union([ + Schema.Number.annotate({ + "description": + "The number of partial images to generate. This parameter is used for\nstreaming responses that return partial images. Value must be between 0 and 3.\nWhen set to 0, the response will be a single image sent in one streaming event.\n\nNote that the final image may be sent before the full number of partial images\nare generated if the full image is generated more quickly.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(3).annotate({ "expected": "a value less than or equal to 3" })), + Schema.Null +]).annotate({ "identifier": "PartialImages" }) +export type Image = { readonly "b64_json"?: string; readonly "url"?: string; readonly "revised_prompt"?: string } +export const Image = Schema.Struct({ + "b64_json": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The base64-encoded JSON of the generated image. Returned by default for GPT image models, or when `response_format` is set to `b64_json` for models that support that parameter." + }) ), - "max_requests_per_1_day": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum requests per day. Only present for relevant models." }).check( - Schema.isInt() - ) + "url": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The URL of the generated image when `response_format` is set to `url` for models that support that parameter. Unsupported for GPT image models.", + "format": "uri" + }) ), - "batch_1_day_max_input_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum batch input tokens per day. Only present for relevant models." - }).check(Schema.isInt()) + "revised_prompt": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The revised prompt used to generate the image, for models that support prompt revision. Not returned by GPT image models." + }) ) -}).annotate({ "description": "Represents a project rate limit config." }) -export type ProjectRateLimitUpdateRequest = { - readonly "max_requests_per_1_minute"?: number - readonly "max_tokens_per_1_minute"?: number - readonly "max_images_per_1_minute"?: number - readonly "max_audio_megabytes_per_1_minute"?: number - readonly "max_requests_per_1_day"?: number - readonly "batch_1_day_max_input_tokens"?: number -} -export const ProjectRateLimitUpdateRequest = Schema.Struct({ - "max_requests_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum requests per minute." }).check(Schema.isInt()) - ), - "max_tokens_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum tokens per minute." }).check(Schema.isInt()) - ), - "max_images_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum images per minute. Only relevant for certain models." }).check( - Schema.isInt() - ) - ), - "max_audio_megabytes_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum audio megabytes per minute. Only relevant for certain models." - }).check(Schema.isInt()) - ), - "max_requests_per_1_day": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum requests per day. Only relevant for certain models." }).check( - Schema.isInt() - ) +}).annotate({ + "description": "Represents the content or the URL of an image generated by the OpenAI API.", + "identifier": "Image" +}) +export type ImageGenOutputTokensDetails = { readonly "image_tokens": number; readonly "text_tokens": number } +export const ImageGenOutputTokensDetails = Schema.Struct({ + "image_tokens": Schema.Number.annotate({ "description": "The number of image output tokens generated by the model." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "text_tokens": Schema.Number.annotate({ "description": "The number of text output tokens generated by the model." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "title": "Image generation output token details", + "description": "The output token details for the image generation.", + "identifier": "ImageGenOutputTokensDetails" +}) +export type ImageGenInputUsageDetails = { readonly "text_tokens": number; readonly "image_tokens": number } +export const ImageGenInputUsageDetails = Schema.Struct({ + "text_tokens": Schema.Number.annotate({ "description": "The number of text tokens in the input prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "batch_1_day_max_input_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum batch input tokens per day. Only relevant for certain models." - }).check(Schema.isInt()) + "image_tokens": Schema.Number.annotate({ "description": "The number of image tokens in the input prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) +}).annotate({ + "title": "Input usage details", + "description": "The input tokens detailed information for the image generation.", + "identifier": "ImageGenInputUsageDetails" }) -export type ProjectServiceAccount = { - readonly "object": "organization.project.service_account" - readonly "id": string - readonly "name": string - readonly "role": "owner" | "member" +export type ImageEditPartialImageEvent = { + readonly "type": "image_edit.partial_image" + readonly "b64_json": string readonly "created_at": number + readonly "size": string | "1024x1024" | "1024x1536" | "1536x1024" | "auto" + readonly "quality": "low" | "medium" | "high" | "xhigh" | "max" | "auto" + readonly "background": "transparent" | "opaque" | "auto" + readonly "output_format": "png" | "webp" | "jpeg" + readonly "partial_image_index": number } -export const ProjectServiceAccount = Schema.Struct({ - "object": Schema.Literal("organization.project.service_account").annotate({ - "description": "The object type, which is always `organization.project.service_account`" +export const ImageEditPartialImageEvent = Schema.Struct({ + "type": Schema.Literal("image_edit.partial_image").annotate({ + "description": "The type of the event. Always `image_edit.partial_image`.\n" + }), + "b64_json": Schema.String.annotate({ + "description": "Base64-encoded partial image data, suitable for rendering as an image.\n" }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.String.annotate({ "description": "The name of the service account" }), - "role": Schema.Literals(["owner", "member"]).annotate({ "description": "`owner` or `member`" }), "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the service account was created", + "description": "The Unix timestamp when the event was created.\n", "format": "unixtime" - }).check(Schema.isInt()) -}).annotate({ "description": "Represents an individual service account in a project." }) -export type ProjectServiceAccountApiKey = { - readonly "object": "organization.project.service_account.api_key" - readonly "value": string - readonly "name": string + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "size": Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." + }), + "quality": Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": "The quality setting for the requested edited image.\n" + }), + "background": Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "description": "The background setting for the requested edited image.\n" + }), + "output_format": Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "description": "The output format for the requested edited image.\n" + }), + "partial_image_index": Schema.Number.annotate({ "description": "0-based index for the partial image (streaming).\n" }) + .check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a partial image is available during image editing streaming.\n", + "identifier": "ImageEditPartialImageEvent" +}) +export type ImagesUsage = { + readonly "total_tokens": number + readonly "input_tokens": number + readonly "output_tokens": number + readonly "input_tokens_details": { readonly "text_tokens": number; readonly "image_tokens": number } +} +export const ImagesUsage = Schema.Struct({ + "total_tokens": Schema.Number.annotate({ + "description": "The total number of tokens (images and text) used for the image generation.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "input_tokens": Schema.Number.annotate({ + "description": "The number of tokens (images and text) in the input prompt." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "output_tokens": Schema.Number.annotate({ "description": "The number of image tokens in the output image." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "input_tokens_details": Schema.Struct({ + "text_tokens": Schema.Number.annotate({ "description": "The number of text tokens in the input prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "image_tokens": Schema.Number.annotate({ "description": "The number of image tokens in the input prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "The input tokens detailed information for the image generation." }) +}).annotate({ + "description": "For the GPT image models only, the token usage information for the image generation.\n", + "identifier": "ImagesUsage" +}) +export type ImageGenPartialImageEvent = { + readonly "type": "image_generation.partial_image" + readonly "b64_json": string readonly "created_at": number - readonly "id": string + readonly "size": string | "1024x1024" | "1024x1536" | "1536x1024" | "auto" + readonly "quality": "low" | "medium" | "high" | "xhigh" | "max" | "auto" + readonly "background": "transparent" | "opaque" | "auto" + readonly "output_format": "png" | "webp" | "jpeg" + readonly "partial_image_index": number } -export const ProjectServiceAccountApiKey = Schema.Struct({ - "object": Schema.Literal("organization.project.service_account.api_key").annotate({ - "description": "The object type, which is always `organization.project.service_account.api_key`" +export const ImageGenPartialImageEvent = Schema.Struct({ + "type": Schema.Literal("image_generation.partial_image").annotate({ + "description": "The type of the event. Always `image_generation.partial_image`.\n" }), - "value": Schema.String, - "name": Schema.String, - "created_at": Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt()), - "id": Schema.String + "b64_json": Schema.String.annotate({ + "description": "Base64-encoded partial image data, suitable for rendering as an image.\n" + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp when the event was created.\n", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "size": Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." + }), + "quality": Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": "The quality setting for the requested image.\n" + }), + "background": Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "description": "The background setting for the requested image.\n" + }), + "output_format": Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "description": "The output format for the requested image.\n" + }), + "partial_image_index": Schema.Number.annotate({ "description": "0-based index for the partial image (streaming).\n" }) + .check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a partial image is available during image generation streaming.\n", + "identifier": "ImageGenPartialImageEvent" }) -export type ProjectServiceAccountCreateRequest = { readonly "name": string } -export const ProjectServiceAccountCreateRequest = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the service account being created." }) +export type ModelIdsLive = string | "gpt-live-1" +export const ModelIdsLive = Schema.Union([ + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + Schema.Literal("gpt-live-1") +]).annotate({ + "description": + "The Live model. Required in the session configuration for every transport; do not pass it as a URL query parameter.", + "identifier": "ModelIdsLive" }) -export type ProjectServiceAccountDeleteResponse = { - readonly "object": "organization.project.service_account.deleted" - readonly "id": string - readonly "deleted": boolean -} -export const ProjectServiceAccountDeleteResponse = Schema.Struct({ - "object": Schema.Literal("organization.project.service_account.deleted"), - "id": Schema.String, - "deleted": Schema.Boolean +export type Instructions = string | null +export const Instructions = Schema.Union([ + Schema.String.annotate({ + "description": + "Frontend instructions for voice, conversation, interruptions, and when to delegate. Start with the [Live prompting guide](https://developers.openai.com/api/docs/guides/live-prompting); put business rules and tool workflows in a separate [backend prompt](https://developers.openai.com/api/docs/guides/live-delegation#start-with-your-existing-backend-prompt). Limited to 16,384 client-supplied tokens. Omitted or blank instructions use server defaults. Immutable after startup." + }), + Schema.Null +]).annotate({ "identifier": "instructions" }) +export type LiveCustomVoiceParam = { readonly "id": string } +export const LiveCustomVoiceParam = Schema.Struct({ + "id": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })) +}).annotate({ "identifier": "LiveCustomVoiceParam" }) +export type LiveClientDelegationParam = { readonly "type": "client" } +export const LiveClientDelegationParam = Schema.Struct({ + "type": Schema.Literal("client").annotate({ + "description": "The delegation owner. Always `client` for tasks handled by your application." + }) +}).annotate({ + "description": + "Delegate tasks to your application. The Live session emits delegation events that your backend handles.", + "identifier": "LiveClientDelegationParam" }) -export type ProjectUpdateRequest = { - readonly "name"?: string | null - readonly "external_key_id"?: string | null - readonly "geography"?: string | null +export type LiveResponsesServiceTier = "auto" | "default" | "fast_tier_temp_pilot" | "flex" | "priority" | "ultrafast" +export const LiveResponsesServiceTier = Schema.Literals([ + "auto", + "default", + "fast_tier_temp_pilot", + "flex", + "priority", + "ultrafast" +]).annotate({ "identifier": "LiveResponsesServiceTier" }) +export type LiveReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" +export const LiveReasoningEffort = Schema.Literals(["none", "minimal", "low", "medium", "high", "xhigh"]).annotate({ + "identifier": "LiveReasoningEffort" +}) +export type LiveReasoningSummary = "concise" | "detailed" | "auto" +export const LiveReasoningSummary = Schema.Literals(["concise", "detailed", "auto"]).annotate({ + "identifier": "LiveReasoningSummary" +}) +export type LiveTextVerbosity = "low" | "medium" | "high" +export const LiveTextVerbosity = Schema.Literals(["low", "medium", "high"]).annotate({ + "identifier": "LiveTextVerbosity" +}) +export type LiveFunctionToolInputParam = { + readonly "type": "function" + readonly "name": string + readonly "description"?: string | null + readonly "parameters"?: { readonly [x: string]: Schema.Json } | null + readonly "strict"?: boolean | null } -export const ProjectUpdateRequest = Schema.Struct({ - "name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "The updated name of the project, this name appears in reports." - }) +export const LiveFunctionToolInputParam = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The tool type. Always `function`." }), + "name": Schema.String.annotate({ + "description": "The name the delegated Responses model uses when calling this function." + }), + "description": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "What the function does and when the delegated Responses model should call it." + }), + Schema.Null + ]) ), - "external_key_id": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "External key ID to associate with the project." - }) + "parameters": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON Schema object describing the arguments accepted by the function." + }), + Schema.Null + ]) ), - "geography": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Geography for the project." }) + "strict": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": "Whether the delegated Responses model must follow the function’s parameter schema exactly." + }), + Schema.Null + ]) ) +}).annotate({ + "description": "A function tool available to the Responses backend when the Live model delegates a task.", + "identifier": "LiveFunctionToolInputParam" }) -export type ProjectUser = { - readonly "object": "organization.project.user" - readonly "id": string - readonly "name"?: string | null - readonly "email"?: string | null - readonly "role": string - readonly "added_at": number +export type LiveWebSearchToolInputParam = { readonly "type": "web_search" } +export const LiveWebSearchToolInputParam = Schema.Struct({ + "type": Schema.Literal("web_search").annotate({ "description": "The tool type. Always `web_search`." }) +}).annotate({ + "description": "A web search tool available to the Live session’s Responses backend.", + "identifier": "LiveWebSearchToolInputParam" +}) +export type LiveFileSearchToolInputParam = { readonly "type": "file_search" } +export const LiveFileSearchToolInputParam = Schema.Struct({ "type": Schema.Literal("file_search") }).annotate({ + "identifier": "LiveFileSearchToolInputParam" +}) +export type LiveCodeInterpreterToolInputParam = { readonly "type": "code_interpreter" } +export const LiveCodeInterpreterToolInputParam = Schema.Struct({ "type": Schema.Literal("code_interpreter") }).annotate( + { "identifier": "LiveCodeInterpreterToolInputParam" } +) +export type LiveContainerMemoryLimit = "1g" | "4g" | "16g" | "64g" +export const LiveContainerMemoryLimit = Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ + "identifier": "LiveContainerMemoryLimit" +}) +export type LiveContainerNetworkPolicyDisabledParam = { readonly "type": "disabled" } +export const LiveContainerNetworkPolicyDisabledParam = Schema.Struct({ + "type": Schema.Literal("disabled").annotate({ "description": "Disable outbound network access. Always `disabled`." }) +}).annotate({ "identifier": "LiveContainerNetworkPolicyDisabledParam" }) +export type LiveHostedShellNetworkPolicyAllowlistParam = { + readonly "type": "allowlist" + readonly "allowed_domains": ReadonlyArray } -export const ProjectUser = Schema.Struct({ - "object": Schema.Literal("organization.project.user").annotate({ - "description": "The object type, which is always `organization.project.user`" +export const LiveHostedShellNetworkPolicyAllowlistParam = Schema.Struct({ + "type": Schema.Literal("allowlist").annotate({ + "description": "Allow outbound network access only to specified domains. Always `allowlist`." }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the user" }) - ), - "email": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The email address of the user" }) - ), - "role": Schema.String.annotate({ "description": "`owner` or `member`" }), - "added_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the project was added.", - "format": "unixtime" - }).check(Schema.isInt()) -}).annotate({ "description": "Represents an individual user in a project." }) -export type ProjectUserCreateRequest = { - readonly "user_id"?: string | null - readonly "email"?: string | null - readonly "role": string + "allowed_domains": Schema.Array(Schema.String).annotate({ + "description": "A list of allowed domains when type is `allowlist`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) +}).annotate({ "identifier": "LiveHostedShellNetworkPolicyAllowlistParam" }) +export type LiveSkillReferenceParam = { + readonly "type": "skill_reference" + readonly "skill_id": string + readonly "version"?: string | null } -export const ProjectUserCreateRequest = Schema.Struct({ - "user_id": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The ID of the user." }) - ), - "email": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Email of the user to add." }) - ), - "role": Schema.String.annotate({ "description": "`owner` or `member`" }) +export const LiveSkillReferenceParam = Schema.Struct({ + "type": Schema.Literal("skill_reference").annotate({ + "description": "References a skill created with the /v1/skills endpoint." + }), + "skill_id": Schema.String.annotate({ "description": "The ID of the referenced skill." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "version": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "Optional skill version. Use a positive integer or 'latest'. Omit for default." + }), + Schema.Null + ]) + ) +}).annotate({ "identifier": "LiveSkillReferenceParam" }) +export type LiveInlineSkillSourceParam = { + readonly "type": "base64" + readonly "media_type": "application/zip" + readonly "data": string +} +export const LiveInlineSkillSourceParam = Schema.Struct({ + "type": Schema.Literal("base64").annotate({ + "description": "The type of the inline skill source. Must be `base64`." + }), + "media_type": Schema.Literal("application/zip").annotate({ + "description": "The media type of the inline skill payload. Must be `application/zip`." + }), + "data": Schema.String.annotate({ "description": "Base64-encoded skill zip bundle." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(70254592).annotate({ "expected": "a string with at most 70254592 code points" })) +}).annotate({ "description": "Inline skill payload", "identifier": "LiveInlineSkillSourceParam" }) +export type LiveContainerReferenceParam = { readonly "type": "container_reference"; readonly "container_id": string } +export const LiveContainerReferenceParam = Schema.Struct({ + "type": Schema.Literal("container_reference").annotate({ + "description": "References a container created with the /v1/containers endpoint" + }), + "container_id": Schema.String.annotate({ "description": "The ID of the referenced container." }) +}).annotate({ "identifier": "LiveContainerReferenceParam" }) +export type LiveLocalSkillParam = { readonly "name": string; readonly "description": string; readonly "path": string } +export const LiveLocalSkillParam = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the skill." }), + "description": Schema.String.annotate({ "description": "The description of the skill." }), + "path": Schema.String.annotate({ "description": "The path to the directory containing the skill." }) +}).annotate({ "identifier": "LiveLocalSkillParam" }) +export type LiveImageGenerationToolInputParam = { readonly "type": "image_generation" } +export const LiveImageGenerationToolInputParam = Schema.Struct({ "type": Schema.Literal("image_generation") }).annotate( + { "identifier": "LiveImageGenerationToolInputParam" } +) +export type LiveMCPToolInputParam = { readonly "type": "mcp" } +export const LiveMCPToolInputParam = Schema.Struct({ "type": Schema.Literal("mcp") }).annotate({ + "identifier": "LiveMCPToolInputParam" }) -export type ProjectUserDeleteResponse = { - readonly "object": "organization.project.user.deleted" - readonly "id": string - readonly "deleted": boolean -} -export const ProjectUserDeleteResponse = Schema.Struct({ - "object": Schema.Literal("organization.project.user.deleted"), - "id": Schema.String, - "deleted": Schema.Boolean +export type LiveCustomToolInputParam = { readonly "type": "custom" } +export const LiveCustomToolInputParam = Schema.Struct({ "type": Schema.Literal("custom") }).annotate({ + "identifier": "LiveCustomToolInputParam" }) -export type ProjectUserUpdateRequest = { readonly "role"?: string | null } -export const ProjectUserUpdateRequest = Schema.Struct({ - "role": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "`owner` or `member`" }) - ) +export type LiveNamespaceToolInputParam = { readonly "type": "namespace" } +export const LiveNamespaceToolInputParam = Schema.Struct({ "type": Schema.Literal("namespace") }).annotate({ + "identifier": "LiveNamespaceToolInputParam" }) -export type PublicAssignOrganizationGroupRoleBody = { readonly "role_id": string } -export const PublicAssignOrganizationGroupRoleBody = Schema.Struct({ - "role_id": Schema.String.annotate({ "description": "Identifier of the role to assign." }) -}).annotate({ "description": "Request payload for assigning a role to a group or user." }) -export type PublicCreateOrganizationRoleBody = { - readonly "role_name": string - readonly "permissions": ReadonlyArray - readonly "description"?: string | null -} -export const PublicCreateOrganizationRoleBody = Schema.Struct({ - "role_name": Schema.String.annotate({ "description": "Unique name for the role." }), - "permissions": Schema.Array(Schema.String).annotate({ "description": "Permissions to grant to the role." }), - "description": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Optional description of the role." }) - ) -}).annotate({ "description": "Request payload for creating a custom role." }) -export type PublicUpdateOrganizationRoleBody = { - readonly "permissions"?: ReadonlyArray | null - readonly "description"?: string | null - readonly "role_name"?: string | null +export type LiveToolSearchToolInputParam = { readonly "type": "tool_search" } +export const LiveToolSearchToolInputParam = Schema.Struct({ "type": Schema.Literal("tool_search") }).annotate({ + "identifier": "LiveToolSearchToolInputParam" +}) +export type LiveProgrammaticToolInputParam = { readonly "type": "programmatic_tool_calling" } +export const LiveProgrammaticToolInputParam = Schema.Struct({ "type": Schema.Literal("programmatic_tool_calling") }) + .annotate({ "identifier": "LiveProgrammaticToolInputParam" }) +export type LiveComputerToolInputParam = { readonly "type": "computer" } +export const LiveComputerToolInputParam = Schema.Struct({ "type": Schema.Literal("computer") }).annotate({ + "identifier": "LiveComputerToolInputParam" +}) +export type LiveApplyPatchToolInputParam = { readonly "type": "apply_patch" } +export const LiveApplyPatchToolInputParam = Schema.Struct({ "type": Schema.Literal("apply_patch") }).annotate({ + "identifier": "LiveApplyPatchToolInputParam" +}) +export type LiveToolChoiceEnum = "auto" | "none" | "required" +export const LiveToolChoiceEnum = Schema.Literals(["auto", "none", "required"]).annotate({ + "identifier": "LiveToolChoiceEnum" +}) +export type LiveFunctionToolChoiceParam = { readonly "type": "function"; readonly "name": string } +export const LiveFunctionToolChoiceParam = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The tool to call. Always `function`." }), + "name": Schema.String.annotate({ "description": "The name of the function tool to call." }) +}).annotate({ "identifier": "LiveFunctionToolChoiceParam" }) +export type LiveMCPToolChoiceParam = { + readonly "type": "mcp" + readonly "server_label": string + readonly "name"?: string | null } -export const PublicUpdateOrganizationRoleBody = Schema.Struct({ - "permissions": Schema.optionalKey( - Schema.Union([Schema.Array(Schema.String), Schema.Null]).annotate({ - "description": "Updated set of permissions for the role." - }) - ), - "description": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "New description for the role." }) - ), - "role_name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "New name for the role." }) +export const LiveMCPToolChoiceParam = Schema.Struct({ + "type": Schema.Literal("mcp").annotate({ "description": "The tool to call. Always `mcp`." }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server to call." }), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "The name of the MCP tool to call. If omitted, the server may choose a default." + }), + Schema.Null + ]) ) -}).annotate({ "description": "Request payload for updating an existing role." }) -export type RealtimeAudioFormats = { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" -} | { readonly "type"?: "audio/pcma" } -export const RealtimeAudioFormats = Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) -]) -export type RealtimeCallReferRequest = { readonly "target_uri": string } -export const RealtimeCallReferRequest = Schema.Struct({ - "target_uri": Schema.String.annotate({ - "description": - "URI that should appear in the SIP Refer-To header. Supports values like\n`tel:+14155550123` or `sip:agent@example.com`." +}).annotate({ "identifier": "LiveMCPToolChoiceParam" }) +export type LiveSpecificFileSearchParam = { readonly "type": "file_search" } +export const LiveSpecificFileSearchParam = Schema.Struct({ + "type": Schema.Literal("file_search").annotate({ "description": "The tool to call. Always `file_search`." }) +}).annotate({ "identifier": "LiveSpecificFileSearchParam" }) +export type LiveSpecificWebSearchParam = { readonly "type": "web_search" } +export const LiveSpecificWebSearchParam = Schema.Struct({ + "type": Schema.Literal("web_search").annotate({ "description": "The tool to call. Always `web_search`." }) +}).annotate({ "identifier": "LiveSpecificWebSearchParam" }) +export type LiveSpecificWebSearchPreviewParam = { readonly "type": "web_search_preview" } +export const LiveSpecificWebSearchPreviewParam = Schema.Struct({ + "type": Schema.Literal("web_search_preview").annotate({ + "description": "The tool to call. Always `web_search_preview`." }) +}).annotate({ "identifier": "LiveSpecificWebSearchPreviewParam" }) +export type LiveSpecificImageGenParam = { readonly "type": "image_generation" } +export const LiveSpecificImageGenParam = Schema.Struct({ + "type": Schema.Literal("image_generation").annotate({ "description": "The tool to call. Always `image_generation`." }) +}).annotate({ "identifier": "LiveSpecificImageGenParam" }) +export type LiveSpecificComputerParam = { readonly "type": "computer" } +export const LiveSpecificComputerParam = Schema.Struct({ + "type": Schema.Literal("computer").annotate({ "description": "The tool to call. Always `computer`." }) +}).annotate({ "identifier": "LiveSpecificComputerParam" }) +export type LiveSpecificCodeInterpreterParam = { readonly "type": "code_interpreter" } +export const LiveSpecificCodeInterpreterParam = Schema.Struct({ + "type": Schema.Literal("code_interpreter").annotate({ "description": "The tool to call. Always `code_interpreter`." }) +}).annotate({ "identifier": "LiveSpecificCodeInterpreterParam" }) +export type LiveSpecificProgrammaticToolCallingParam = { readonly "type": "programmatic_tool_calling" } +export const LiveSpecificProgrammaticToolCallingParam = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The tool to call. Always `programmatic_tool_calling`." + }) +}).annotate({ "identifier": "LiveSpecificProgrammaticToolCallingParam" }) +export type LiveSpecificFunctionShellParam = { readonly "type": "shell" } +export const LiveSpecificFunctionShellParam = Schema.Struct({ + "type": Schema.Literal("shell").annotate({ "description": "The tool to call. Always `shell`." }) }).annotate({ - "title": "Realtime call refer request", - "description": "Parameters required to transfer a SIP call to a new destination using the\nRealtime API." -}) -export type RealtimeCallRejectRequest = { readonly "status_code"?: number } -export const RealtimeCallRejectRequest = Schema.Struct({ - "status_code": Schema.optionalKey( - Schema.Number.annotate({ - "description": "SIP response code to send back to the caller. Defaults to `603` (Decline)\nwhen omitted." - }).check(Schema.isInt()) - ) -}).annotate({ - "title": "Realtime call reject request", - "description": "Parameters used to decline an incoming SIP call handled by the Realtime API." + "title": "Specific shell tool choice", + "description": "Forces the model to call the shell tool when a tool call is required.", + "identifier": "LiveSpecificFunctionShellParam" }) -export type RealtimeClientEventConversationItemDelete = { - readonly "event_id"?: string - readonly "type": "conversation.item.delete" - readonly "item_id": string -} -export const RealtimeClientEventConversationItemDelete = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) - ), - "type": Schema.Literal("conversation.item.delete").annotate({ - "description": "The event type, must be `conversation.item.delete`." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the item to delete." }) +export type LiveSpecificCustomToolParam = { readonly "type": "custom"; readonly "name": string } +export const LiveSpecificCustomToolParam = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "The tool to call. Always `custom`." }), + "name": Schema.String.annotate({ "description": "The name of the custom tool to call." }) +}).annotate({ "identifier": "LiveSpecificCustomToolParam" }) +export type LiveSpecificApplyPatchParam = { readonly "type": "apply_patch" } +export const LiveSpecificApplyPatchParam = Schema.Struct({ + "type": Schema.Literal("apply_patch").annotate({ "description": "The tool to call. Always `apply_patch`." }) }).annotate({ - "description": - "Send this event when you want to remove any item from the conversation \nhistory. The server will respond with a `conversation.item.deleted` event, \nunless the item does not exist in the conversation history, in which case the \nserver will respond with an error.\n" + "title": "Specific apply patch tool choice", + "description": "Forces the model to call the apply_patch tool when executing a tool call.", + "identifier": "LiveSpecificApplyPatchParam" }) -export type RealtimeClientEventConversationItemRetrieve = { - readonly "event_id"?: string - readonly "type": "conversation.item.retrieve" - readonly "item_id": string -} -export const RealtimeClientEventConversationItemRetrieve = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) - ), - "type": Schema.Literal("conversation.item.retrieve").annotate({ - "description": "The event type, must be `conversation.item.retrieve`." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the item to retrieve." }) -}).annotate({ - "description": - "Send this event when you want to retrieve the server's representation of a specific item in the conversation history. This is useful, for example, to inspect user audio after noise cancellation and VAD.\nThe server will respond with a `conversation.item.retrieved` event, \nunless the item does not exist in the conversation history, in which case the \nserver will respond with an error.\n" +export type LiveToolChoiceValueEnum = "none" | "auto" | "required" +export const LiveToolChoiceValueEnum = Schema.Literals(["none", "auto", "required"]).annotate({ + "identifier": "LiveToolChoiceValueEnum" }) -export type RealtimeClientEventConversationItemTruncate = { - readonly "event_id"?: string - readonly "type": "conversation.item.truncate" - readonly "item_id": string - readonly "content_index": number - readonly "audio_end_ms": number -} -export const RealtimeClientEventConversationItemTruncate = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) - ), - "type": Schema.Literal("conversation.item.truncate").annotate({ - "description": "The event type, must be `conversation.item.truncate`." - }), - "item_id": Schema.String.annotate({ - "description": - "The ID of the assistant message item to truncate. Only assistant message \nitems can be truncated.\n" - }), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part to truncate. Set this to `0`." - }).check(Schema.isInt()), - "audio_end_ms": Schema.Number.annotate({ - "description": - "Inclusive duration up to which audio is truncated, in milliseconds. If \nthe audio_end_ms is greater than the actual audio duration, the server \nwill respond with an error.\n" - }).check(Schema.isInt()) -}).annotate({ +export type Store = boolean +export const Store = Schema.Boolean.annotate({ "description": - "Send this event to truncate a previous assistant message’s audio. The server \nwill produce audio faster than realtime, so this event is useful when the user \ninterrupts to truncate audio that has already been sent to the client but not \nyet played. This will synchronize the server's understanding of the audio with \nthe client's playback.\n\nTruncating audio will delete the server-side text transcript to ensure there \nis not text in the context that hasn't been heard by the user.\n\nIf successful, the server will respond with a `conversation.item.truncated` \nevent. \n" + "Whether to store the session for later forking and recording download. Defaults to false for new sessions.", + "identifier": "store" }) -export type RealtimeClientEventInputAudioBufferAppend = { - readonly "event_id"?: string - readonly "type": "input_audio_buffer.append" - readonly "audio": string -} -export const RealtimeClientEventInputAudioBufferAppend = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) - ), - "type": Schema.Literal("input_audio_buffer.append").annotate({ - "description": "The event type, must be `input_audio_buffer.append`." - }), - "audio": Schema.String.annotate({ - "description": - "Base64-encoded audio bytes. This must be in the format specified by the \n`input_audio_format` field in the session configuration.\n" - }) -}).annotate({ - "description": - "Send this event to append audio bytes to the input audio buffer. The audio \nbuffer is temporary storage you can write to and later commit. A \"commit\" will create a new\nuser message item in the conversation history from the buffer content and clear the buffer.\nInput audio transcription (if enabled) will be generated when the buffer is committed.\n\nIf VAD is enabled the audio buffer is used to detect speech and the server will decide \nwhen to commit. When Server VAD is disabled, you must commit the audio buffer\nmanually. Input audio noise reduction operates on writes to the audio buffer.\n\nThe client may choose how much audio to place in each event up to a maximum \nof 15 MiB, for example streaming smaller chunks from the client may allow the \nVAD to be more responsive. Unlike most other client events, the server will \nnot send a confirmation response to this event.\n" +export type LiveInitialMessageStatus = "incomplete" | "completed" +export const LiveInitialMessageStatus = Schema.Literals(["incomplete", "completed"]).annotate({ + "identifier": "LiveInitialMessageStatus" }) -export type RealtimeClientEventInputAudioBufferClear = { - readonly "event_id"?: string - readonly "type": "input_audio_buffer.clear" -} -export const RealtimeClientEventInputAudioBufferClear = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) +export type LiveInitialInputTextContentPartParam = { readonly "type"?: "input_text"; readonly "text": string } +export const LiveInitialInputTextContentPartParam = Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("input_text").annotate({ "description": "The text content type. Always `input_text`." }) ), - "type": Schema.Literal("input_audio_buffer.clear").annotate({ - "description": "The event type, must be `input_audio_buffer.clear`." + "text": Schema.String.annotate({ + "description": "The message text to include in the Live session’s initial conversation history." }) }).annotate({ - "description": - "Send this event to clear the audio bytes in the buffer. The server will \nrespond with an `input_audio_buffer.cleared` event.\n" + "description": "Text supplied in a developer or user message when starting a Live session.", + "identifier": "LiveInitialInputTextContentPartParam" }) -export type RealtimeClientEventInputAudioBufferCommit = { - readonly "event_id"?: string - readonly "type": "input_audio_buffer.commit" -} -export const RealtimeClientEventInputAudioBufferCommit = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) +export type LiveInitialTextContentPartParam = { readonly "type"?: "text"; readonly "text": string } +export const LiveInitialTextContentPartParam = Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("text").annotate({ "description": "The text content type. Always `text`." }) ), - "type": Schema.Literal("input_audio_buffer.commit").annotate({ - "description": "The event type, must be `input_audio_buffer.commit`." + "text": Schema.String.annotate({ + "description": "The message text to include in the Live session’s initial conversation history." }) }).annotate({ - "description": - "Send this event to commit the user input audio buffer, which will create a new user message item in the conversation. This event will produce an error if the input audio buffer is empty. When in Server VAD mode, the client does not need to send this event, the server will commit the audio buffer automatically.\n\nCommitting the input audio buffer will trigger input audio transcription (if enabled in session configuration), but it will not create a response from the model. The server will respond with an `input_audio_buffer.committed` event.\n" + "description": "Assistant text supplied as conversation history when starting a Live session.", + "identifier": "LiveInitialTextContentPartParam" }) -export type RealtimeClientEventOutputAudioBufferClear = { - readonly "event_id"?: string - readonly "type": "output_audio_buffer.clear" -} -export const RealtimeClientEventOutputAudioBufferClear = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The unique ID of the client event used for error handling." }) - ), - "type": Schema.Literal("output_audio_buffer.clear").annotate({ - "description": "The event type, must be `output_audio_buffer.clear`." +export type LiveInitialOutputTextContentPartParam = { readonly "type": "output_text"; readonly "text": string } +export const LiveInitialOutputTextContentPartParam = Schema.Struct({ + "type": Schema.Literal("output_text").annotate({ "description": "The text content type. Always `output_text`." }), + "text": Schema.String.annotate({ + "description": "The message text to include in the Live session’s initial conversation history." }) }).annotate({ - "description": - "**WebRTC/SIP Only:** Emit to cut off the current audio response. This will trigger the server to\nstop generating audio and emit a `output_audio_buffer.cleared` event. This\nevent should be preceded by a `response.cancel` client event to stop the\ngeneration of the current response.\n[Learn more](/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc).\n" + "description": "Assistant output text supplied as conversation history when starting a Live session.", + "identifier": "LiveInitialOutputTextContentPartParam" }) -export type RealtimeClientEventResponseCancel = { - readonly "event_id"?: string - readonly "type": "response.cancel" - readonly "response_id"?: string -} -export const RealtimeClientEventResponseCancel = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) +export type LiveAllowedServerEventParam = { readonly "type": string; readonly "response_event"?: string } +export const LiveAllowedServerEventParam = Schema.Struct({ + "type": Schema.String.annotate({ + "description": "The outer Live server event type. Use 'response.event' for Responses events." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) ), - "type": Schema.Literal("response.cancel").annotate({ "description": "The event type, must be `response.cancel`." }), - "response_id": Schema.optionalKey( + "response_event": Schema.optionalKey( Schema.String.annotate({ "description": - "A specific response ID to cancel - if not provided, will cancel an \nin-progress response in the default conversation.\n" - }) + "The nested Responses event type. Required when type is 'response.event'; forbidden for other event types." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ) ) }).annotate({ - "description": - "Send this event to cancel an in-progress response. The server will respond \nwith a `response.done` event with a status of `response.status=cancelled`. If \nthere is no response to cancel, the server will respond with an error. It's safe\nto call `response.cancel` even if no response is in progress, an error will be\nreturned the session will remain unaffected.\n" + "description": "A Live server event selector for the WebRTC frontend data channel.", + "identifier": "LiveAllowedServerEventParam" }) -export type RealtimeConversationItemFunctionCall = { - readonly "id"?: string - readonly "object"?: "realtime.item" - readonly "type": "function_call" - readonly "status"?: "completed" | "incomplete" | "in_progress" - readonly "call_id"?: string - readonly "name": string - readonly "arguments": string -} -export const RealtimeConversationItemFunctionCall = Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The unique ID of the item. This may be provided by the client or generated by the server." - }) - ), - "object": Schema.optionalKey( - Schema.Literal("realtime.item").annotate({ - "description": - "Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item." - }) - ), - "type": Schema.Literal("function_call").annotate({ "description": "The type of the item. Always `function_call`." }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "incomplete", "in_progress"]).annotate({ - "description": "The status of the item. Has no effect on the conversation." - }) - ), - "call_id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the function call." })), - "name": Schema.String.annotate({ "description": "The name of the function being called." }), - "arguments": Schema.String.annotate({ - "description": - "The arguments of the function call. This is a JSON-encoded string representing the arguments passed to the function, for example `{\"arg1\": \"value1\", \"arg2\": 42}`." - }) +export type LiveWebRTCTransport = { readonly "type": "webrtc"; readonly "sdp": string } +export const LiveWebRTCTransport = Schema.Struct({ + "type": Schema.Literal("webrtc").annotate({ + "description": "The transport used for the Live session. Always `webrtc`." + }), + "sdp": Schema.String.annotate({ "description": "Session Description Protocol message for the WebRTC connection." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ - "title": "Realtime function call item", - "description": "A function call item in a Realtime conversation." + "description": "WebRTC transport carrying the offer SDP in a creation request or answer SDP in its response.", + "identifier": "LiveWebRTCTransport" }) -export type RealtimeConversationItemFunctionCallOutput = { - readonly "id"?: string - readonly "object"?: "realtime.item" - readonly "type": "function_call_output" - readonly "status"?: "completed" | "incomplete" | "in_progress" - readonly "call_id": string - readonly "output": string -} -export const RealtimeConversationItemFunctionCallOutput = Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The unique ID of the item. This may be provided by the client or generated by the server." - }) - ), - "object": Schema.optionalKey( - Schema.Literal("realtime.item").annotate({ - "description": - "Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item." - }) - ), - "type": Schema.Literal("function_call_output").annotate({ - "description": "The type of the item. Always `function_call_output`." +export type LiveSIPTrunkAuth = { readonly "type": "digest"; readonly "username": string; readonly "password": string } +export const LiveSIPTrunkAuth = Schema.Struct({ + "type": Schema.Literal("digest").annotate({ + "description": "Use `digest` for SIP Digest authentication. Handles 401 and 407 challenges." }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "incomplete", "in_progress"]).annotate({ - "description": "The status of the item. Has no effect on the conversation." - }) - ), - "call_id": Schema.String.annotate({ "description": "The ID of the function call this output is for." }), - "output": Schema.String.annotate({ + "username": Schema.String.annotate({ "description": - "The output of the function call, this is free text and can contain any information or simply be empty." + "Provider username. Must contain a non-whitespace character, be at most 256 bytes, and contain no CR, LF, or NUL." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "password": Schema.String.annotate({ + "description": "Provider password. Must be at most 4096 bytes and contain no CR, LF, or NUL.", + "writeOnly": true + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) +}).annotate({ + "description": "Credentials for SIP Digest authentication with your trunk provider.", + "identifier": "LiveSIPTrunkAuth" +}) +export type Session = { readonly "id": string } +export const Session = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "Opaque session identifier. Preserve the returned value unchanged, including its prefix." }) }).annotate({ - "title": "Realtime function call output item", - "description": "A function call output item in a Realtime conversation." + "description": "The newly created Live session. Use its ID for session controls and sideband connections.", + "identifier": "session" }) -export type RealtimeConversationItemMessageAssistant = { - readonly "id"?: string - readonly "object"?: "realtime.item" - readonly "type": "message" - readonly "status"?: "completed" | "incomplete" | "in_progress" - readonly "role": "assistant" - readonly "content": ReadonlyArray< - { - readonly "type"?: "output_text" | "output_audio" - readonly "text"?: string - readonly "audio"?: string - readonly "transcript"?: string - } - > -} -export const RealtimeConversationItemMessageAssistant = Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The unique ID of the item. This may be provided by the client or generated by the server." - }) - ), - "object": Schema.optionalKey( - Schema.Literal("realtime.item").annotate({ - "description": - "Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item." - }) - ), - "type": Schema.Literal("message").annotate({ "description": "The type of the item. Always `message`." }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "incomplete", "in_progress"]).annotate({ - "description": "The status of the item. Has no effect on the conversation." - }) - ), - "role": Schema.Literal("assistant").annotate({ - "description": "The role of the message sender. Always `assistant`." - }), - "content": Schema.Array(Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literals(["output_text", "output_audio"]).annotate({ - "description": - "The content type, `output_text` or `output_audio` depending on the session `output_modalities` configuration." - }) - ), - "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content." })), - "audio": Schema.optionalKey( - Schema.String.annotate({ - "description": - "Base64-encoded audio bytes, these will be parsed as the format specified in the session output audio type configuration. This defaults to PCM 16-bit 24kHz mono if not specified." - }) - ), - "transcript": Schema.optionalKey( - Schema.String.annotate({ - "description": "The transcript of the audio content, this will always be present if the output type is `audio`." - }) - ) - })).annotate({ "description": "The content of the message." }) +export type Properties_store = boolean +export const Properties_store = Schema.Boolean.annotate({ + "description": "Whether to store the forked session. Omission inherits the stored session's setting.", + "identifier": "properties-store" +}) +export type LiveCallReferRequest = { readonly "target_uri": string } +export const LiveCallReferRequest = Schema.Struct({ + "target_uri": Schema.String.annotate({ + "description": "Nonblank URI for the SIP Refer-To header, such as tel:+14155550123 or sip:agent@example.com." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isPattern(new RegExp("\\S", "u")).annotate({ "expected": "a string matching the RegExp \\S" }) + ) }).annotate({ - "title": "Realtime assistant message item", - "description": "An assistant message item in a Realtime conversation." + "description": "Parameters used to transfer a Live SIP call to another destination.", + "identifier": "LiveCallReferRequest" }) -export type RealtimeConversationItemMessageSystem = { - readonly "id"?: string - readonly "object"?: "realtime.item" - readonly "type": "message" - readonly "status"?: "completed" | "incomplete" | "in_progress" - readonly "role": "system" - readonly "content": ReadonlyArray<{ readonly "type"?: "input_text"; readonly "text"?: string }> -} -export const RealtimeConversationItemMessageSystem = Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The unique ID of the item. This may be provided by the client or generated by the server." - }) - ), - "object": Schema.optionalKey( - Schema.Literal("realtime.item").annotate({ - "description": - "Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item." - }) - ), - "type": Schema.Literal("message").annotate({ "description": "The type of the item. Always `message`." }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "incomplete", "in_progress"]).annotate({ - "description": "The status of the item. Has no effect on the conversation." - }) - ), - "role": Schema.Literal("system").annotate({ "description": "The role of the message sender. Always `system`." }), - "content": Schema.Array( +export type LiveCallRejectRequest = { readonly "status_code": number } +export const LiveCallRejectRequest = Schema.Struct({ + "status_code": Schema.Number.annotate({ + "description": "SIP rejection status sent to the caller. This field is required." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(300).annotate({ "expected": "a value greater than or equal to 300" }) + ).check(Schema.isLessThanOrEqualTo(699).annotate({ "expected": "a value less than or equal to 699" })) +}).annotate({ + "description": "Parameters used to reject an incoming Live SIP call.", + "identifier": "LiveCallRejectRequest" +}) +export type Model = + | null + | string + | number + | boolean + | { + readonly "id": string + readonly "created": number + readonly "object": "model" + readonly "owned_by": string + readonly "shutdown_date"?: string | null + } & { readonly [x: string]: Schema.Json } + | ReadonlyArray +export const Model = Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.StructWithRest( Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("input_text").annotate({ - "description": "The content type. Always `input_text` for system messages." + "id": Schema.String.annotate({ + "description": "The model identifier, which can be referenced in the API endpoints." + }), + "created": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) when the model was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "object": Schema.Literal("model").annotate({ "description": "The object type, which is always \"model\"." }), + "owned_by": Schema.String.annotate({ "description": "The organization that owns the model." }), + "shutdown_date": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "format": "date" }), Schema.Null]).annotate({ + "description": "The date when the model will shut down, or null if not announced." }) - ), - "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content." })) - }) - ).annotate({ "description": "The content of the message." }) -}).annotate({ - "title": "Realtime system message item", - "description": - "A system message in a Realtime conversation can be used to provide additional context or instructions to the model. This is similar but distinct from the instruction prompt provided at the start of a conversation, as system messages can be added at any point in the conversation. For major changes to the conversation's behavior, use instructions, but for smaller updates (e.g. \"the user is now asking about a different topic\"), use system messages." + ) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Array(Schema.Json.annotate({ "expected": "JSON value" })) +]).annotate({ + "title": "Model", + "description": "Describes an OpenAI model offering that can be used with the API.", + "identifier": "Model" }) -export type RealtimeConversationItemMessageUser = { - readonly "id"?: string - readonly "object"?: "realtime.item" - readonly "type": "message" - readonly "status"?: "completed" | "incomplete" | "in_progress" - readonly "role": "user" - readonly "content": ReadonlyArray< +export type DeleteModelResponse = { readonly "id": string; readonly "deleted": boolean; readonly "object": string } +export const DeleteModelResponse = Schema.Struct({ + "id": Schema.String, + "deleted": Schema.Boolean, + "object": Schema.String +}).annotate({ "identifier": "DeleteModelResponse" }) +export type CreateModerationRequest = { + readonly "input": + | string + | ReadonlyArray + | ReadonlyArray< + { readonly "type": "image_url"; readonly "image_url": { readonly "url": string } } | { + readonly "type": "text" + readonly "text": string + } + > + readonly "model"?: + | string + | "omni-moderation-latest" + | "omni-moderation-2024-09-26" + | "text-moderation-latest" + | "text-moderation-stable" +} +export const CreateModerationRequest = Schema.Struct({ + "input": Schema.Union([ + Schema.String.annotate({ "description": "A string of text to classify for moderation." }), + Schema.Array(Schema.String).annotate({ "description": "An array of strings to classify for moderation." }), + Schema.Array(Schema.Union([ + Schema.Struct({ + "type": Schema.Literal("image_url").annotate({ "description": "Always `image_url`." }), + "image_url": Schema.Struct({ + "url": Schema.String.annotate({ + "description": "Either a URL of the image or the base64 encoded image data.", + "format": "uri" + }) + }).annotate({ "description": "Contains either an image URL or a data URL for a base64 encoded image." }) + }).annotate({ "description": "An object describing an image to classify." }), + Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "Always `text`." }), + "text": Schema.String.annotate({ "description": "A string of text to classify." }) + }).annotate({ "description": "An object describing text to classify." }) + ], { mode: "oneOf" })).annotate({ "description": "An array of multi-modal inputs to the moderation model." }) + ], { mode: "oneOf" }).annotate({ + "description": + "Input (or inputs) to classify. Can be a single string, an array of strings, or\nan array of multi-modal input objects similar to other models.\n" + }), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "omni-moderation-latest", + "omni-moderation-2024-09-26", + "text-moderation-latest", + "text-moderation-stable" + ]) + ]).annotate({ + "description": + "The content moderation model you would like to use. Learn more in\n[the moderation guide](https://developers.openai.com/api/docs/guides/moderation), and learn about\navailable models [here](https://developers.openai.com/api/docs/guides/moderation).\n" + }) + ) +}).annotate({ "identifier": "CreateModerationRequest" }) +export type CreateModerationResponse = { + readonly "id": string + readonly "model": string + readonly "results": ReadonlyArray< { - readonly "type"?: "input_text" | "input_audio" | "input_image" - readonly "text"?: string - readonly "audio"?: string - readonly "image_url"?: string - readonly "detail"?: "auto" | "low" | "high" - readonly "transcript"?: string + readonly "flagged": boolean + readonly "categories": { + readonly "hate": boolean + readonly "hate/threatening": boolean + readonly "harassment": boolean + readonly "harassment/threatening": boolean + readonly "illicit": boolean | null + readonly "illicit/violent": boolean | null + readonly "self-harm": boolean + readonly "self-harm/intent": boolean + readonly "self-harm/instructions": boolean + readonly "sexual": boolean + readonly "sexual/minors": boolean + readonly "violence": boolean + readonly "violence/graphic": boolean + } + readonly "category_scores": { + readonly "hate": number + readonly "hate/threatening": number + readonly "harassment": number + readonly "harassment/threatening": number + readonly "illicit": number + readonly "illicit/violent": number + readonly "self-harm": number + readonly "self-harm/intent": number + readonly "self-harm/instructions": number + readonly "sexual": number + readonly "sexual/minors": number + readonly "violence": number + readonly "violence/graphic": number + } + readonly "category_applied_input_types": { + readonly "hate": ReadonlyArray<"text"> + readonly "hate/threatening": ReadonlyArray<"text"> + readonly "harassment": ReadonlyArray<"text"> + readonly "harassment/threatening": ReadonlyArray<"text"> + readonly "illicit": ReadonlyArray<"text"> + readonly "illicit/violent": ReadonlyArray<"text"> + readonly "self-harm": ReadonlyArray<"text" | "image"> + readonly "self-harm/intent": ReadonlyArray<"text" | "image"> + readonly "self-harm/instructions": ReadonlyArray<"text" | "image"> + readonly "sexual": ReadonlyArray<"text" | "image"> + readonly "sexual/minors": ReadonlyArray<"text"> + readonly "violence": ReadonlyArray<"text" | "image"> + readonly "violence/graphic": ReadonlyArray<"text" | "image"> + } } > } -export const RealtimeConversationItemMessageUser = Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The unique ID of the item. This may be provided by the client or generated by the server." - }) - ), - "object": Schema.optionalKey( - Schema.Literal("realtime.item").annotate({ - "description": - "Identifier for the API object being returned - always `realtime.item`. Optional when creating a new item." - }) - ), - "type": Schema.Literal("message").annotate({ "description": "The type of the item. Always `message`." }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "incomplete", "in_progress"]).annotate({ - "description": "The status of the item. Has no effect on the conversation." - }) - ), - "role": Schema.Literal("user").annotate({ "description": "The role of the message sender. Always `user`." }), - "content": Schema.Array(Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literals(["input_text", "input_audio", "input_image"]).annotate({ - "description": "The content type (`input_text`, `input_audio`, or `input_image`)." - }) - ), - "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content (for `input_text`)." })), - "audio": Schema.optionalKey( - Schema.String.annotate({ +export const CreateModerationResponse = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique identifier for the moderation request." }), + "model": Schema.String.annotate({ "description": "The model used to generate the moderation results." }), + "results": Schema.Array(Schema.Struct({ + "flagged": Schema.Boolean.annotate({ "description": "Whether any of the below categories are flagged." }), + "categories": Schema.Struct({ + "hate": Schema.Boolean.annotate({ "description": - "Base64-encoded audio bytes (for `input_audio`), these will be parsed as the format specified in the session input audio type configuration. This defaults to PCM 16-bit 24kHz mono if not specified." - }) - ), - "image_url": Schema.optionalKey( - Schema.String.annotate({ + "Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harassment." + }), + "hate/threatening": Schema.Boolean.annotate({ "description": - "Base64-encoded image bytes (for `input_image`) as a data URI. For example `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...`. Supported formats are PNG and JPEG.", - "format": "uri" - }) - ), - "detail": Schema.optionalKey( - Schema.Literals(["auto", "low", "high"]).annotate({ - "description": "The detail level of the image (for `input_image`). `auto` will default to `high`." - }) - ), - "transcript": Schema.optionalKey( - Schema.String.annotate({ + "Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste." + }), + "harassment": Schema.Boolean.annotate({ + "description": "Content that expresses, incites, or promotes harassing language towards any target." + }), + "harassment/threatening": Schema.Boolean.annotate({ + "description": "Harassment content that also includes violence or serious harm towards any target." + }), + "illicit": Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Content that includes instructions or advice that facilitate the planning or execution of wrongdoing, or that gives advice or instruction on how to commit illicit acts. For example, \"how to shoplift\" would fit this category." + }), + Schema.Null + ]), + "illicit/violent": Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Content that includes instructions or advice that facilitate the planning or execution of wrongdoing that also includes violence, or that gives advice or instruction on the procurement of any weapon." + }), + Schema.Null + ]), + "self-harm": Schema.Boolean.annotate({ + "description": + "Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders." + }), + "self-harm/intent": Schema.Boolean.annotate({ + "description": + "Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders." + }), + "self-harm/instructions": Schema.Boolean.annotate({ + "description": + "Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts." + }), + "sexual": Schema.Boolean.annotate({ "description": - "Transcript of the audio (for `input_audio`). This is not sent to the model, but will be attached to the message item for reference." + "Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness)." + }), + "sexual/minors": Schema.Boolean.annotate({ + "description": "Sexual content that includes an individual who is under 18 years old." + }), + "violence": Schema.Boolean.annotate({ + "description": "Content that depicts death, violence, or physical injury." + }), + "violence/graphic": Schema.Boolean.annotate({ + "description": "Content that depicts death, violence, or physical injury in graphic detail." }) - ) - })).annotate({ "description": "The content of the message." }) -}).annotate({ "title": "Realtime user message item", "description": "A user message item in a Realtime conversation." }) -export type RealtimeFunctionTool = { - readonly "type"?: "function" - readonly "name"?: string - readonly "description"?: string - readonly "parameters"?: {} -} -export const RealtimeFunctionTool = Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("function").annotate({ "description": "The type of the tool, i.e. `function`." }) - ), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function." })), - "description": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The description of the function, including guidance on when and how\nto call it, and guidance about what to tell the user when calling\n(if anything).\n" - }) - ), - "parameters": Schema.optionalKey( - Schema.Struct({}).annotate({ "description": "Parameters of the function in JSON Schema." }) - ) -}).annotate({ "title": "Function tool" }) -export type RealtimeMCPApprovalRequest = { - readonly "type": "mcp_approval_request" - readonly "id": string - readonly "server_label": string - readonly "name": string - readonly "arguments": string -} -export const RealtimeMCPApprovalRequest = Schema.Struct({ - "type": Schema.Literal("mcp_approval_request").annotate({ - "description": "The type of the item. Always `mcp_approval_request`." - }), - "id": Schema.String.annotate({ "description": "The unique ID of the approval request." }), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server making the request." }), - "name": Schema.String.annotate({ "description": "The name of the tool to run." }), - "arguments": Schema.String.annotate({ "description": "A JSON string of arguments for the tool." }) + }).annotate({ "description": "A list of the categories, and whether they are flagged or not." }), + "category_scores": Schema.Struct({ + "hate": Schema.Number.annotate({ "description": "The score for the category 'hate'." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "hate/threatening": Schema.Number.annotate({ "description": "The score for the category 'hate/threatening'." }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "harassment": Schema.Number.annotate({ "description": "The score for the category 'harassment'." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "harassment/threatening": Schema.Number.annotate({ + "description": "The score for the category 'harassment/threatening'." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "illicit": Schema.Number.annotate({ "description": "The score for the category 'illicit'." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "illicit/violent": Schema.Number.annotate({ "description": "The score for the category 'illicit/violent'." }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "self-harm": Schema.Number.annotate({ "description": "The score for the category 'self-harm'." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "self-harm/intent": Schema.Number.annotate({ "description": "The score for the category 'self-harm/intent'." }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "self-harm/instructions": Schema.Number.annotate({ + "description": "The score for the category 'self-harm/instructions'." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "sexual": Schema.Number.annotate({ "description": "The score for the category 'sexual'." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "sexual/minors": Schema.Number.annotate({ "description": "The score for the category 'sexual/minors'." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "violence": Schema.Number.annotate({ "description": "The score for the category 'violence'." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "violence/graphic": Schema.Number.annotate({ "description": "The score for the category 'violence/graphic'." }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })) + }).annotate({ "description": "A list of the categories along with their scores as predicted by model." }), + "category_applied_input_types": Schema.Struct({ + "hate": Schema.Array(Schema.Literal("text")).annotate({ + "description": "The applied input type(s) for the category 'hate'." + }), + "hate/threatening": Schema.Array(Schema.Literal("text")).annotate({ + "description": "The applied input type(s) for the category 'hate/threatening'." + }), + "harassment": Schema.Array(Schema.Literal("text")).annotate({ + "description": "The applied input type(s) for the category 'harassment'." + }), + "harassment/threatening": Schema.Array(Schema.Literal("text")).annotate({ + "description": "The applied input type(s) for the category 'harassment/threatening'." + }), + "illicit": Schema.Array(Schema.Literal("text")).annotate({ + "description": "The applied input type(s) for the category 'illicit'." + }), + "illicit/violent": Schema.Array(Schema.Literal("text")).annotate({ + "description": "The applied input type(s) for the category 'illicit/violent'." + }), + "self-harm": Schema.Array(Schema.Literals(["text", "image"])).annotate({ + "description": "The applied input type(s) for the category 'self-harm'." + }), + "self-harm/intent": Schema.Array(Schema.Literals(["text", "image"])).annotate({ + "description": "The applied input type(s) for the category 'self-harm/intent'." + }), + "self-harm/instructions": Schema.Array(Schema.Literals(["text", "image"])).annotate({ + "description": "The applied input type(s) for the category 'self-harm/instructions'." + }), + "sexual": Schema.Array(Schema.Literals(["text", "image"])).annotate({ + "description": "The applied input type(s) for the category 'sexual'." + }), + "sexual/minors": Schema.Array(Schema.Literal("text")).annotate({ + "description": "The applied input type(s) for the category 'sexual/minors'." + }), + "violence": Schema.Array(Schema.Literals(["text", "image"])).annotate({ + "description": "The applied input type(s) for the category 'violence'." + }), + "violence/graphic": Schema.Array(Schema.Literals(["text", "image"])).annotate({ + "description": "The applied input type(s) for the category 'violence/graphic'." + }) + }).annotate({ "description": "A list of the categories along with the input type(s) that the score applies to." }) + })).annotate({ "description": "A list of moderation objects." }) }).annotate({ - "title": "Realtime MCP approval request", - "description": "A Realtime item requesting human approval of a tool invocation.\n" + "description": "Represents if a given text input is potentially harmful.", + "identifier": "CreateModerationResponse" }) -export type RealtimeMCPApprovalResponse = { - readonly "type": "mcp_approval_response" +export type AdminApiKey = { + readonly "object": "organization.admin_api_key" readonly "id": string - readonly "approval_request_id": string - readonly "approve": boolean - readonly "reason"?: string | null -} -export const RealtimeMCPApprovalResponse = Schema.Struct({ - "type": Schema.Literal("mcp_approval_response").annotate({ - "description": "The type of the item. Always `mcp_approval_response`." - }), - "id": Schema.String.annotate({ "description": "The unique ID of the approval response." }), - "approval_request_id": Schema.String.annotate({ "description": "The ID of the approval request being answered." }), - "approve": Schema.Boolean.annotate({ "description": "Whether the request was approved." }), - "reason": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "Optional reason for the decision." }), Schema.Null]) - ) -}).annotate({ - "title": "Realtime MCP approval response", - "description": "A Realtime item responding to an MCP approval request.\n" -}) -export type RealtimeMCPHTTPError = { - readonly "type": "http_error" - readonly "code": number - readonly "message": string -} -export const RealtimeMCPHTTPError = Schema.Struct({ - "type": Schema.Literal("http_error"), - "code": Schema.Number.check(Schema.isInt()), - "message": Schema.String -}).annotate({ "title": "Realtime MCP HTTP error" }) -export type RealtimeMCPProtocolError = { - readonly "type": "protocol_error" - readonly "code": number - readonly "message": string -} -export const RealtimeMCPProtocolError = Schema.Struct({ - "type": Schema.Literal("protocol_error"), - "code": Schema.Number.check(Schema.isInt()), - "message": Schema.String -}).annotate({ "title": "Realtime MCP protocol error" }) -export type RealtimeMCPToolExecutionError = { readonly "type": "tool_execution_error"; readonly "message": string } -export const RealtimeMCPToolExecutionError = Schema.Struct({ - "type": Schema.Literal("tool_execution_error"), - "message": Schema.String -}).annotate({ "title": "Realtime MCP tool execution error" }) -export type RealtimeReasoningEffort = "minimal" | "low" | "medium" | "high" | "xhigh" -export const RealtimeReasoningEffort = Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": "Constrains effort on reasoning for reasoning-capable Realtime models such as\n`gpt-realtime-2`.\n" -}) -export type RealtimeServerEventConversationCreated = { - readonly "event_id": string - readonly "type": "conversation.created" - readonly "conversation": { readonly "id"?: string; readonly "object"?: string } -} -export const RealtimeServerEventConversationCreated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.created").annotate({ - "description": "The event type, must be `conversation.created`." - }), - "conversation": Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the conversation." })), - "object": Schema.optionalKey( - Schema.String.annotate({ "description": "The object type, must be `realtime.conversation`." }) - ) - }).annotate({ "description": "The conversation resource." }) -}).annotate({ "description": "Returned when a conversation is created. Emitted right after session creation.\n" }) -export type RealtimeServerEventConversationItemDeleted = { - readonly "event_id": string - readonly "type": "conversation.item.deleted" - readonly "item_id": string -} -export const RealtimeServerEventConversationItemDeleted = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.deleted").annotate({ - "description": "The event type, must be `conversation.item.deleted`." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the item that was deleted." }) -}).annotate({ - "description": - "Returned when an item in the conversation is deleted by the client with a \n`conversation.item.delete` event. This event is used to synchronize the \nserver's understanding of the conversation history with the client's view.\n" -}) -export type RealtimeServerEventConversationItemInputAudioTranscriptionFailed = { - readonly "event_id": string - readonly "type": "conversation.item.input_audio_transcription.failed" - readonly "item_id": string - readonly "content_index": number - readonly "error": { + readonly "name"?: string | null + readonly "redacted_value": string + readonly "created_at": number + readonly "expires_at": number | null + readonly "last_used_at"?: number | null + readonly "owner": { readonly "type"?: string - readonly "code"?: string - readonly "message"?: string - readonly "param"?: string - } -} -export const RealtimeServerEventConversationItemInputAudioTranscriptionFailed = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.input_audio_transcription.failed").annotate({ - "description": "The event type, must be\n`conversation.item.input_audio_transcription.failed`.\n" - }), - "item_id": Schema.String.annotate({ "description": "The ID of the user message item." }), - "content_index": Schema.Number.annotate({ "description": "The index of the content part containing the audio." }) - .check(Schema.isInt()), - "error": Schema.Struct({ - "type": Schema.optionalKey(Schema.String.annotate({ "description": "The type of error." })), - "code": Schema.optionalKey(Schema.String.annotate({ "description": "Error code, if any." })), - "message": Schema.optionalKey(Schema.String.annotate({ "description": "A human-readable error message." })), - "param": Schema.optionalKey(Schema.String.annotate({ "description": "Parameter related to the error, if any." })) - }).annotate({ "description": "Details of the transcription error." }) -}).annotate({ - "description": - "Returned when input audio transcription is configured, and a transcription \nrequest for a user message failed. These events are separate from other \n`error` events so that the client can identify the related Item.\n" -}) -export type RealtimeServerEventConversationItemInputAudioTranscriptionSegment = { - readonly "event_id": string - readonly "type": "conversation.item.input_audio_transcription.segment" - readonly "item_id": string - readonly "content_index": number - readonly "text": string - readonly "id": string - readonly "speaker": string - readonly "start": number - readonly "end": number + readonly "object"?: string + readonly "id"?: string + readonly "name"?: string + readonly "created_at"?: number + readonly "role"?: string + } } -export const RealtimeServerEventConversationItemInputAudioTranscriptionSegment = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.input_audio_transcription.segment").annotate({ - "description": "The event type, must be `conversation.item.input_audio_transcription.segment`." +export const AdminApiKey = Schema.Struct({ + "object": Schema.Literal("organization.admin_api_key").annotate({ + "description": "The object type, which is always `organization.admin_api_key`" }), - "item_id": Schema.String.annotate({ "description": "The ID of the item containing the input audio content." }), - "content_index": Schema.Number.annotate({ - "description": "The index of the input audio content part within the item." - }).check(Schema.isInt()), - "text": Schema.String.annotate({ "description": "The text for this segment." }), - "id": Schema.String.annotate({ "description": "The segment identifier." }), - "speaker": Schema.String.annotate({ "description": "The detected speaker label for this segment." }), - "start": Schema.Number.annotate({ "description": "Start time of the segment in seconds.", "format": "double" }).check( - Schema.isFinite() + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the API key" }) ), - "end": Schema.Number.annotate({ "description": "End time of the segment in seconds.", "format": "double" }).check( - Schema.isFinite() - ) -}).annotate({ "description": "Returned when an input audio transcription segment is identified for an item." }) -export type RealtimeServerEventConversationItemTruncated = { - readonly "event_id": string - readonly "type": "conversation.item.truncated" - readonly "item_id": string - readonly "content_index": number - readonly "audio_end_ms": number -} -export const RealtimeServerEventConversationItemTruncated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.truncated").annotate({ - "description": "The event type, must be `conversation.item.truncated`." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the assistant message item that was truncated." }), - "content_index": Schema.Number.annotate({ "description": "The index of the content part that was truncated." }).check( - Schema.isInt() + "redacted_value": Schema.String.annotate({ "description": "The redacted value of the API key" }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the API key was created", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "expires_at": Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the API key expires", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "last_used_at": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the API key was last used", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) ), - "audio_end_ms": Schema.Number.annotate({ - "description": "The duration up to which the audio was truncated, in milliseconds.\n" - }).check(Schema.isInt()) -}).annotate({ - "description": - "Returned when an earlier assistant audio message item is truncated by the \nclient with a `conversation.item.truncate` event. This event is used to \nsynchronize the server's understanding of the audio with the client's playback.\n\nThis action will truncate the audio and remove the server-side text transcript \nto ensure there is no text in the context that hasn't been heard by the user.\n" -}) -export type RealtimeServerEventError = { - readonly "event_id": string - readonly "type": "error" - readonly "error": { - readonly "type": string - readonly "code"?: string | null - readonly "message": string - readonly "param"?: string | null - readonly "event_id"?: string | null - } -} -export const RealtimeServerEventError = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("error").annotate({ "description": "The event type, must be `error`." }), - "error": Schema.Struct({ - "type": Schema.String.annotate({ - "description": "The type of error (e.g., \"invalid_request_error\", \"server_error\").\n" - }), - "code": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "Error code, if any." }), Schema.Null]) + "owner": Schema.Struct({ + "type": Schema.optionalKey(Schema.String.annotate({ "description": "Always `user`" })), + "object": Schema.optionalKey( + Schema.String.annotate({ "description": "The object type, which is always organization.user" }) ), - "message": Schema.String.annotate({ "description": "A human-readable error message." }), - "param": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "Parameter related to the error, if any." }), Schema.Null]) + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }) ), - "event_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "The event_id of the client event that caused the error, if applicable.\n" - }), - Schema.Null - ]) - ) - }).annotate({ "description": "Details of the error." }) -}).annotate({ - "description": - "Returned when an error occurs, which could be a client problem or a server\nproblem. Most errors are recoverable and the session will stay open, we\nrecommend to implementors to monitor and log error messages by default.\n" -}) -export type RealtimeServerEventInputAudioBufferCleared = { - readonly "event_id": string - readonly "type": "input_audio_buffer.cleared" -} -export const RealtimeServerEventInputAudioBufferCleared = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("input_audio_buffer.cleared").annotate({ - "description": "The event type, must be `input_audio_buffer.cleared`." + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the user" })), + "created_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the user was created", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "role": Schema.optionalKey(Schema.String.annotate({ "description": "Always `owner`" })) }) -}).annotate({ - "description": - "Returned when the input audio buffer is cleared by the client with a \n`input_audio_buffer.clear` event.\n" -}) -export type RealtimeServerEventInputAudioBufferCommitted = { - readonly "event_id": string - readonly "type": "input_audio_buffer.committed" - readonly "previous_item_id"?: string | null - readonly "item_id": string +}).annotate({ "description": "Represents an individual Admin API key in an org.", "identifier": "AdminApiKey" }) +export type AdminApiKeyCreateResponse = { + readonly "object": "organization.admin_api_key" + readonly "id": string + readonly "name"?: string | null + readonly "redacted_value": string + readonly "created_at": number + readonly "expires_at": number | null + readonly "last_used_at"?: number | null + readonly "owner": { + readonly "type"?: string + readonly "object"?: string + readonly "id"?: string + readonly "name"?: string + readonly "created_at"?: number + readonly "role"?: string + } + readonly "value": string } -export const RealtimeServerEventInputAudioBufferCommitted = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("input_audio_buffer.committed").annotate({ - "description": "The event type, must be `input_audio_buffer.committed`." +export const AdminApiKeyCreateResponse = Schema.Struct({ + "object": Schema.Literal("organization.admin_api_key").annotate({ + "description": "The object type, which is always `organization.admin_api_key`" }), - "previous_item_id": Schema.optionalKey( + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the API key" }) + ), + "redacted_value": Schema.String.annotate({ "description": "The redacted value of the API key" }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the API key was created", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "expires_at": Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the API key expires", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "last_used_at": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ - "description": - "The ID of the preceding item after which the new item will be inserted.\nCan be `null` if the item has no predecessor.\n" - }), + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the API key was last used", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ), - "item_id": Schema.String.annotate({ "description": "The ID of the user message item that will be created." }) -}).annotate({ - "description": - "Returned when an input audio buffer is committed, either by the client or\nautomatically in server VAD mode. The `item_id` property is the ID of the user\nmessage item that will be created, thus a `conversation.item.created` event\nwill also be sent to the client.\n" -}) -export type RealtimeServerEventInputAudioBufferDtmfEventReceived = { - readonly "type": "input_audio_buffer.dtmf_event_received" - readonly "event": string - readonly "received_at": number -} -export const RealtimeServerEventInputAudioBufferDtmfEventReceived = Schema.Struct({ - "type": Schema.Literal("input_audio_buffer.dtmf_event_received").annotate({ - "description": "The event type, must be `input_audio_buffer.dtmf_event_received`." + "owner": Schema.Struct({ + "type": Schema.optionalKey(Schema.String.annotate({ "description": "Always `user`" })), + "object": Schema.optionalKey( + Schema.String.annotate({ "description": "The object type, which is always organization.user" }) + ), + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }) + ), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the user" })), + "created_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the user was created", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "role": Schema.optionalKey(Schema.String.annotate({ "description": "Always `owner`" })) }), - "event": Schema.String.annotate({ "description": "The telephone keypad that was pressed by the user." }), - "received_at": Schema.Number.annotate({ - "description": "UTC Unix Timestamp when DTMF Event was received by server.\n" - }).check(Schema.isInt()) + "value": Schema.String.annotate({ "description": "The value of the API key. Only shown on create." }) +}).annotate({ "identifier": "AdminApiKeyCreateResponse" }) +export type AuditLogEventType = + | "api_key.created" + | "api_key.updated" + | "api_key.deleted" + | "certificate.created" + | "certificate.updated" + | "certificate.deleted" + | "certificates.activated" + | "certificates.deactivated" + | "checkpoint.permission.created" + | "checkpoint.permission.deleted" + | "external_key.registered" + | "external_key.removed" + | "external_storage.registered" + | "external_storage.removed" + | "group.created" + | "group.updated" + | "group.deleted" + | "invite.sent" + | "invite.accepted" + | "invite.deleted" + | "ip_allowlist.created" + | "ip_allowlist.updated" + | "ip_allowlist.deleted" + | "ip_allowlist.config.activated" + | "ip_allowlist.config.deactivated" + | "login.succeeded" + | "login.failed" + | "logout.succeeded" + | "logout.failed" + | "organization.updated" + | "project.created" + | "project.updated" + | "project.archived" + | "project.deleted" + | "rate_limit.updated" + | "rate_limit.deleted" + | "resource.deleted" + | "tunnel.created" + | "tunnel.updated" + | "tunnel.deleted" + | "workload_identity_provider.created" + | "workload_identity_provider.updated" + | "workload_identity_provider.deleted" + | "workload_identity_provider_mapping.created" + | "workload_identity_provider_mapping.updated" + | "workload_identity_provider_mapping.deleted" + | "role.created" + | "role.updated" + | "role.deleted" + | "role.assignment.created" + | "role.assignment.deleted" + | "role.bound_to_resource" + | "role.unbound_from_resource" + | "scim.enabled" + | "scim.disabled" + | "service_account.created" + | "service_account.updated" + | "service_account.deleted" + | "user.added" + | "user.updated" + | "user.deleted" + | "tenant.metadata.updated" + | "tenant.microsoft_entra_mapping.upserted" + | "tenant.microsoft_entra_mapping.deleted" + | "tenant.workload_identity.provider.created" + | "tenant.workload_identity.provider.updated" + | "tenant.workload_identity.provider.archived" + | "tenant.workload_identity.mapping.created" + | "tenant.workload_identity.mapping.updated" + | "tenant.workload_identity.mapping.archived" + | "tenant.workload_identity.binding.created" + | "tenant.workload_identity.principal.provisioned" + | "tenant.workload_identity.access_token.issued" + | "tenant.admin_api_key.created" + | "tenant.admin_api_key.updated" + | "tenant.admin_api_key.deleted" + | "tenant.project_api_key.created" + | "tenant.trusted_access.business_verification.started" + | "tenant.trusted_access.application.submitted" + | "tenant.chatgpt_access_token.revoked" + | "tenant.migration.completed" + | "tenant.sso.migrated" + | "tenant.domains.migrated" + | "tenant.sso_connection.created" + | "tenant.sso_connection.updated" + | "tenant.sso_connection.deleted" + | "tenant.sso_connection.setup.started" + | "tenant.policy.created" + | "tenant.policy.updated" + | "tenant.policy.deleted" + | "tenant.policy.attached" + | "tenant.policy.detached" + | "tenant.principal_authentication_policy.resolved" + | "tenant.scim.setup.started" + | "tenant.scim.deletion.requested" + | "tenant.scim.directory.created" + | "tenant.product_access_policy.updated" + | "tenant.resource_share_grant.created" + | "tenant.resource_share_grant.updated" + | "tenant.resource_share_grant.accepted" + | "tenant.resource_share_grant.declined" + | "tenant.resource_share_grant.revoked" + | "tenant.resource_share_grant.deleted" + | "tenant.service_account.updated" + | "tenant.service_account.deleted" + | "tenant.service_account.token.revoked" + | "tenant.billing.overage_limit.updated" + | "tenant.billing.alerts.updated" + | "tenant.billing.info.updated" + | "tenant.usage_limit.workspace.updated" + | "tenant.usage_limit.group.updated" + | "tenant.usage_limit.user.updated" + | "tenant.usage_limit.increase_request.updated" + | "tenant.usage_limit.increase_request.resolved" + | "tenant.group.created" + | "tenant.group.updated" + | "tenant.group.deleted" + | "tenant.group.member.added" + | "tenant.group.member.removed" + | "tenant.migration_rollout.status.updated" + | "tenant.migration_rollout.tier.updated" + | "tenant.role.metadata.updated" + | "tenant.custom_role.created" + | "tenant.custom_role.updated" + | "tenant.custom_role.deleted" + | "tenant.role_assignment.created" + | "tenant.role_assignment.deleted" + | "tenant.resource_role_assignment.created" + | "tenant.resource_role_assignment.deleted" + | "tenant.resource_access.updated" + | "tenant.resource_access.deleted" + | "tenant.ads_account.onboarding.redemption" + | "tenant.session_policy.created" + | "tenant.session_policy.updated" + | "tenant.session_policy.deleted" + | "tenant.session_revocation.started" + | "tenant.third_party_app_policy.updated" + | "tenant.user.added" + | "tenant.user.updated" + | "tenant.user.removed" + | "tenant.user.looked_up" + | "tenant.user.invited" + | "tenant.membership.revoked" + | "tenant.api_organization_invite.upserted" + | "tenant.api_organization_invite.deleted" + | "tenant.chatgpt_workspace_invite.upserted" + | "tenant.membership.accepted" + | "tenant.membership.declined" + | "tenant.workspace_invite_email_settings.updated" +export const AuditLogEventType = Schema.Literals([ + "api_key.created", + "api_key.updated", + "api_key.deleted", + "certificate.created", + "certificate.updated", + "certificate.deleted", + "certificates.activated", + "certificates.deactivated", + "checkpoint.permission.created", + "checkpoint.permission.deleted", + "external_key.registered", + "external_key.removed", + "external_storage.registered", + "external_storage.removed", + "group.created", + "group.updated", + "group.deleted", + "invite.sent", + "invite.accepted", + "invite.deleted", + "ip_allowlist.created", + "ip_allowlist.updated", + "ip_allowlist.deleted", + "ip_allowlist.config.activated", + "ip_allowlist.config.deactivated", + "login.succeeded", + "login.failed", + "logout.succeeded", + "logout.failed", + "organization.updated", + "project.created", + "project.updated", + "project.archived", + "project.deleted", + "rate_limit.updated", + "rate_limit.deleted", + "resource.deleted", + "tunnel.created", + "tunnel.updated", + "tunnel.deleted", + "workload_identity_provider.created", + "workload_identity_provider.updated", + "workload_identity_provider.deleted", + "workload_identity_provider_mapping.created", + "workload_identity_provider_mapping.updated", + "workload_identity_provider_mapping.deleted", + "role.created", + "role.updated", + "role.deleted", + "role.assignment.created", + "role.assignment.deleted", + "role.bound_to_resource", + "role.unbound_from_resource", + "scim.enabled", + "scim.disabled", + "service_account.created", + "service_account.updated", + "service_account.deleted", + "user.added", + "user.updated", + "user.deleted", + "tenant.metadata.updated", + "tenant.microsoft_entra_mapping.upserted", + "tenant.microsoft_entra_mapping.deleted", + "tenant.workload_identity.provider.created", + "tenant.workload_identity.provider.updated", + "tenant.workload_identity.provider.archived", + "tenant.workload_identity.mapping.created", + "tenant.workload_identity.mapping.updated", + "tenant.workload_identity.mapping.archived", + "tenant.workload_identity.binding.created", + "tenant.workload_identity.principal.provisioned", + "tenant.workload_identity.access_token.issued", + "tenant.admin_api_key.created", + "tenant.admin_api_key.updated", + "tenant.admin_api_key.deleted", + "tenant.project_api_key.created", + "tenant.trusted_access.business_verification.started", + "tenant.trusted_access.application.submitted", + "tenant.chatgpt_access_token.revoked", + "tenant.migration.completed", + "tenant.sso.migrated", + "tenant.domains.migrated", + "tenant.sso_connection.created", + "tenant.sso_connection.updated", + "tenant.sso_connection.deleted", + "tenant.sso_connection.setup.started", + "tenant.policy.created", + "tenant.policy.updated", + "tenant.policy.deleted", + "tenant.policy.attached", + "tenant.policy.detached", + "tenant.principal_authentication_policy.resolved", + "tenant.scim.setup.started", + "tenant.scim.deletion.requested", + "tenant.scim.directory.created", + "tenant.product_access_policy.updated", + "tenant.resource_share_grant.created", + "tenant.resource_share_grant.updated", + "tenant.resource_share_grant.accepted", + "tenant.resource_share_grant.declined", + "tenant.resource_share_grant.revoked", + "tenant.resource_share_grant.deleted", + "tenant.service_account.updated", + "tenant.service_account.deleted", + "tenant.service_account.token.revoked", + "tenant.billing.overage_limit.updated", + "tenant.billing.alerts.updated", + "tenant.billing.info.updated", + "tenant.usage_limit.workspace.updated", + "tenant.usage_limit.group.updated", + "tenant.usage_limit.user.updated", + "tenant.usage_limit.increase_request.updated", + "tenant.usage_limit.increase_request.resolved", + "tenant.group.created", + "tenant.group.updated", + "tenant.group.deleted", + "tenant.group.member.added", + "tenant.group.member.removed", + "tenant.migration_rollout.status.updated", + "tenant.migration_rollout.tier.updated", + "tenant.role.metadata.updated", + "tenant.custom_role.created", + "tenant.custom_role.updated", + "tenant.custom_role.deleted", + "tenant.role_assignment.created", + "tenant.role_assignment.deleted", + "tenant.resource_role_assignment.created", + "tenant.resource_role_assignment.deleted", + "tenant.resource_access.updated", + "tenant.resource_access.deleted", + "tenant.ads_account.onboarding.redemption", + "tenant.session_policy.created", + "tenant.session_policy.updated", + "tenant.session_policy.deleted", + "tenant.session_revocation.started", + "tenant.third_party_app_policy.updated", + "tenant.user.added", + "tenant.user.updated", + "tenant.user.removed", + "tenant.user.looked_up", + "tenant.user.invited", + "tenant.membership.revoked", + "tenant.api_organization_invite.upserted", + "tenant.api_organization_invite.deleted", + "tenant.chatgpt_workspace_invite.upserted", + "tenant.membership.accepted", + "tenant.membership.declined", + "tenant.workspace_invite_email_settings.updated" +]).annotate({ "description": "The event type.", "identifier": "AuditLogEventType" }) +export type AuditLogActorUser = { readonly "id"?: string; readonly "email"?: string } +export const AuditLogActorUser = Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The user id." })), + "email": Schema.optionalKey(Schema.String.annotate({ "description": "The user email." })) +}).annotate({ "description": "The user who performed the audit logged action.", "identifier": "AuditLogActorUser" }) +export type AuditLogActorServiceAccount = { readonly "id"?: string } +export const AuditLogActorServiceAccount = Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The service account id." })) }).annotate({ - "description": - "**SIP Only:** Returned when an DTMF event is received. A DTMF event is a message that\nrepresents a telephone keypad press (0–9, *, #, A–D). The `event` property\nis the keypad that the user press. The `received_at` is the UTC Unix Timestamp\nthat the server received the event.\n" + "description": "The service account that performed the audit logged action.", + "identifier": "AuditLogActorServiceAccount" }) -export type RealtimeServerEventInputAudioBufferSpeechStarted = { - readonly "event_id": string - readonly "type": "input_audio_buffer.speech_started" - readonly "audio_start_ms": number - readonly "item_id": string +export type AwsExternalStorageProviderResponse = { + readonly "type": "aws" + readonly "account_id": string + readonly "region": string + readonly "bucket": string + readonly "role_arn": string + readonly "external_id": string +} +export const AwsExternalStorageProviderResponse = Schema.Struct({ + "type": Schema.Literal("aws"), + "account_id": Schema.String, + "region": Schema.String, + "bucket": Schema.String, + "role_arn": Schema.String, + "external_id": Schema.String +}).annotate({ "identifier": "AwsExternalStorageProviderResponse" }) +export type AzureExternalStorageProviderResponse = { + readonly "type": "azure" + readonly "tenant_id": string + readonly "subscription_id": string + readonly "resource_group": string + readonly "account_name": string + readonly "container": string + readonly "region": string +} +export const AzureExternalStorageProviderResponse = Schema.Struct({ + "type": Schema.Literal("azure"), + "tenant_id": Schema.String, + "subscription_id": Schema.String, + "resource_group": Schema.String, + "account_name": Schema.String, + "container": Schema.String, + "region": Schema.String +}).annotate({ "identifier": "AzureExternalStorageProviderResponse" }) +export type GcpExternalStorageProviderResponse = { + readonly "type": "gcp" + readonly "bucket": string + readonly "workload_identity_project_number": string + readonly "workload_identity_pool_id": string + readonly "workload_identity_provider_id": string + readonly "region": string + readonly "audience": string +} +export const GcpExternalStorageProviderResponse = Schema.Struct({ + "type": Schema.Literal("gcp"), + "bucket": Schema.String, + "workload_identity_project_number": Schema.String, + "workload_identity_pool_id": Schema.String, + "workload_identity_provider_id": Schema.String, + "region": Schema.String, + "audience": Schema.String +}).annotate({ "identifier": "GcpExternalStorageProviderResponse" }) +export type OciExternalStorageProviderResponse = { + readonly "type": "oci" + readonly "tenancy_ocid": string + readonly "region": string + readonly "bucket": string +} +export const OciExternalStorageProviderResponse = Schema.Struct({ + "type": Schema.Literal("oci"), + "tenancy_ocid": Schema.String, + "region": Schema.String, + "bucket": Schema.String +}).annotate({ "identifier": "OciExternalStorageProviderResponse" }) +export type OrganizationCertificate = { + readonly "object": "organization.certificate" + readonly "id": string + readonly "name": string | null + readonly "created_at": number + readonly "certificate_details": { readonly "valid_at"?: number; readonly "expires_at"?: number } + readonly "active": boolean } -export const RealtimeServerEventInputAudioBufferSpeechStarted = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("input_audio_buffer.speech_started").annotate({ - "description": "The event type, must be `input_audio_buffer.speech_started`." +export const OrganizationCertificate = Schema.Struct({ + "object": Schema.Literal("organization.certificate").annotate({ + "description": "The object type, which is always `organization.certificate`." }), - "audio_start_ms": Schema.Number.annotate({ - "description": - "Milliseconds from the start of all audio written to the buffer during the \nsession when speech was first detected. This will correspond to the \nbeginning of audio sent to the model, and thus includes the \n`prefix_padding_ms` configured in the Session.\n" - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The ID of the user message item that will be created when speech stops.\n" - }) -}).annotate({ - "description": - "Sent by the server when in `server_vad` mode to indicate that speech has been \ndetected in the audio buffer. This can happen any time audio is added to the \nbuffer (unless speech is already detected). The client may want to use this \nevent to interrupt audio playback or provide visual feedback to the user. \n\nThe client should expect to receive a `input_audio_buffer.speech_stopped` event \nwhen speech stops. The `item_id` property is the ID of the user message item \nthat will be created when speech stops and will also be included in the \n`input_audio_buffer.speech_stopped` event (unless the client manually commits \nthe audio buffer during VAD activation).\n" -}) -export type RealtimeServerEventInputAudioBufferSpeechStopped = { - readonly "event_id": string - readonly "type": "input_audio_buffer.speech_stopped" - readonly "audio_end_ms": number - readonly "item_id": string -} -export const RealtimeServerEventInputAudioBufferSpeechStopped = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("input_audio_buffer.speech_stopped").annotate({ - "description": "The event type, must be `input_audio_buffer.speech_stopped`." + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the certificate." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate was uploaded.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "certificate_details": Schema.Struct({ + "valid_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate becomes valid.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "expires_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate expires.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ) }), - "audio_end_ms": Schema.Number.annotate({ - "description": - "Milliseconds since the session started when speech stopped. This will \ncorrespond to the end of audio sent to the model, and thus includes the \n`min_silence_duration_ms` configured in the Session.\n" - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ "description": "The ID of the user message item that will be created." }) + "active": Schema.Boolean.annotate({ + "description": "Whether the certificate is currently active at the organization level." + }) }).annotate({ - "description": - "Returned in `server_vad` mode when the server detects the end of speech in \nthe audio buffer. The server will also send an `conversation.item.created` \nevent with the user message item that is created from the audio buffer.\n" + "description": "Represents an individual certificate configured at the organization level.", + "identifier": "OrganizationCertificate" }) -export type RealtimeServerEventInputAudioBufferTimeoutTriggered = { - readonly "event_id": string - readonly "type": "input_audio_buffer.timeout_triggered" - readonly "audio_start_ms": number - readonly "audio_end_ms": number - readonly "item_id": string +export type UploadCertificateRequest = { readonly "name"?: string; readonly "certificate": string } +export const UploadCertificateRequest = Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "An optional name for the certificate" })), + "certificate": Schema.String.annotate({ "description": "The certificate content in PEM format" }) +}).annotate({ "identifier": "UploadCertificateRequest" }) +export type Certificate = { + readonly "object": "certificate" | "organization.certificate" | "organization.project.certificate" + readonly "id": string + readonly "name": string | null + readonly "created_at": number + readonly "certificate_details": { + readonly "valid_at"?: number + readonly "expires_at"?: number + readonly "content"?: string + } + readonly "active"?: boolean } -export const RealtimeServerEventInputAudioBufferTimeoutTriggered = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("input_audio_buffer.timeout_triggered").annotate({ - "description": "The event type, must be `input_audio_buffer.timeout_triggered`." - }), - "audio_start_ms": Schema.Number.annotate({ - "description": - "Millisecond offset of audio written to the input audio buffer that was after the playback time of the last model response." - }).check(Schema.isInt()), - "audio_end_ms": Schema.Number.annotate({ +export const Certificate = Schema.Struct({ + "object": Schema.Literals(["certificate", "organization.certificate", "organization.project.certificate"]).annotate({ "description": - "Millisecond offset of audio written to the input audio buffer at the time the timeout was triggered." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ "description": "The ID of the item associated with this segment." }) -}).annotate({ - "description": - "Returned when the Server VAD timeout is triggered for the input audio buffer. This is configured\nwith `idle_timeout_ms` in the `turn_detection` settings of the session, and it indicates that\nthere hasn't been any speech detected for the configured duration.\n\nThe `audio_start_ms` and `audio_end_ms` fields indicate the segment of audio after the last\nmodel response up to the triggering time, as an offset from the beginning of audio written\nto the input audio buffer. This means it demarcates the segment of audio that was silent and\nthe difference between the start and end values will roughly match the configured timeout.\n\nThe empty audio will be committed to the conversation as an `input_audio` item (there will be a\n`input_audio_buffer.committed` event) and a model response will be generated. There may be speech\nthat didn't trigger VAD but is still detected by the model, so the model may respond with\nsomething relevant to the conversation or a prompt to continue speaking.\n" -}) -export type RealtimeServerEventMCPListToolsCompleted = { - readonly "event_id": string - readonly "type": "mcp_list_tools.completed" - readonly "item_id": string -} -export const RealtimeServerEventMCPListToolsCompleted = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("mcp_list_tools.completed").annotate({ - "description": "The event type, must be `mcp_list_tools.completed`." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP list tools item." }) -}).annotate({ "description": "Returned when listing MCP tools has completed for an item." }) -export type RealtimeServerEventMCPListToolsFailed = { - readonly "event_id": string - readonly "type": "mcp_list_tools.failed" - readonly "item_id": string -} -export const RealtimeServerEventMCPListToolsFailed = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("mcp_list_tools.failed").annotate({ - "description": "The event type, must be `mcp_list_tools.failed`." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP list tools item." }) -}).annotate({ "description": "Returned when listing MCP tools has failed for an item." }) -export type RealtimeServerEventMCPListToolsInProgress = { - readonly "event_id": string - readonly "type": "mcp_list_tools.in_progress" - readonly "item_id": string -} -export const RealtimeServerEventMCPListToolsInProgress = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("mcp_list_tools.in_progress").annotate({ - "description": "The event type, must be `mcp_list_tools.in_progress`." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP list tools item." }) -}).annotate({ "description": "Returned when listing MCP tools is in progress for an item." }) -export type RealtimeServerEventOutputAudioBufferCleared = { - readonly "event_id": string - readonly "type": "output_audio_buffer.cleared" - readonly "response_id": string -} -export const RealtimeServerEventOutputAudioBufferCleared = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("output_audio_buffer.cleared").annotate({ - "description": "The event type, must be `output_audio_buffer.cleared`." + "The object type.\n\n- If creating, updating, or getting a specific certificate, the object type is `certificate`.\n- If listing, activating, or deactivating certificates for the organization, the object type is `organization.certificate`.\n- If listing, activating, or deactivating certificates for a project, the object type is `organization.project.certificate`.\n" }), - "response_id": Schema.String.annotate({ "description": "The unique ID of the response that produced the audio." }) -}).annotate({ - "description": - "**WebRTC/SIP Only:** Emitted when the output audio buffer is cleared. This happens either in VAD\nmode when the user has interrupted (`input_audio_buffer.speech_started`),\nor when the client has emitted the `output_audio_buffer.clear` event to manually\ncut off the current audio response.\n[Learn more](/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc).\n" -}) -export type RealtimeServerEventOutputAudioBufferStarted = { - readonly "event_id": string - readonly "type": "output_audio_buffer.started" - readonly "response_id": string -} -export const RealtimeServerEventOutputAudioBufferStarted = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("output_audio_buffer.started").annotate({ - "description": "The event type, must be `output_audio_buffer.started`." + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the certificate." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate was uploaded.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "certificate_details": Schema.Struct({ + "valid_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate becomes valid.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "expires_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate expires.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "content": Schema.optionalKey( + Schema.String.annotate({ "description": "The content of the certificate in PEM format." }) + ) }), - "response_id": Schema.String.annotate({ "description": "The unique ID of the response that produced the audio." }) + "active": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Whether the certificate is currently active at the specified scope. Not returned when getting details for a specific certificate." + }) + ) }).annotate({ - "description": - "**WebRTC/SIP Only:** Emitted when the server begins streaming audio to the client. This event is\nemitted after an audio content part has been added (`response.content_part.added`)\nto the response.\n[Learn more](/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc).\n" + "description": "Represents an individual `certificate` uploaded to the organization.", + "identifier": "Certificate" }) -export type RealtimeServerEventOutputAudioBufferStopped = { - readonly "event_id": string - readonly "type": "output_audio_buffer.stopped" - readonly "response_id": string -} -export const RealtimeServerEventOutputAudioBufferStopped = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("output_audio_buffer.stopped").annotate({ - "description": "The event type, must be `output_audio_buffer.stopped`." +export type ToggleCertificatesRequest = { readonly "certificate_ids": ReadonlyArray } +export const ToggleCertificatesRequest = Schema.Struct({ + "certificate_ids": Schema.Array(Schema.String).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxLength(10).annotate({ "expected": "a value with a length of at most 10" })) +}).annotate({ "identifier": "ToggleCertificatesRequest" }) +export type ModifyCertificateRequest = { readonly "name"?: string } +export const ModifyCertificateRequest = Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The updated name for the certificate" })) +}).annotate({ "identifier": "ModifyCertificateRequest" }) +export type DeleteCertificateResponse = { readonly "object": "certificate.deleted"; readonly "id": string } +export const DeleteCertificateResponse = Schema.Struct({ + "object": Schema.Literal("certificate.deleted").annotate({ + "description": "The object type, must be `certificate.deleted`." }), - "response_id": Schema.String.annotate({ "description": "The unique ID of the response that produced the audio." }) -}).annotate({ - "description": - "**WebRTC/SIP Only:** Emitted when the output audio buffer has been completely drained on the server,\nand no more audio is forthcoming. This event is emitted after the full response\ndata has been sent to the client (`response.done`).\n[Learn more](/docs/guides/realtime-conversations#client-and-server-events-for-audio-in-webrtc).\n" -}) -export type RealtimeServerEventRateLimitsUpdated = { - readonly "event_id": string - readonly "type": "rate_limits.updated" - readonly "rate_limits": ReadonlyArray< - { - readonly "name"?: "requests" | "tokens" - readonly "limit"?: number - readonly "remaining"?: number - readonly "reset_seconds"?: number - } - > + "id": Schema.String.annotate({ "description": "The ID of the certificate that was deleted." }) +}).annotate({ "identifier": "DeleteCertificateResponse" }) +export type UsageCompletionsResult = { + readonly "api_source"?: "agents_api" | "unlabeled" | null + readonly "object": "organization.usage.completions.result" + readonly "input_tokens": number + readonly "input_cached_tokens"?: number + readonly "input_cache_write_tokens"?: number + readonly "input_cache_write_12h_tokens"?: number + readonly "input_uncached_tokens"?: number + readonly "output_tokens": number + readonly "input_text_tokens"?: number + readonly "output_text_tokens"?: number + readonly "input_cached_text_tokens"?: number + readonly "input_audio_tokens"?: number + readonly "input_cached_audio_tokens"?: number + readonly "output_audio_tokens"?: number + readonly "input_image_tokens"?: number + readonly "input_cached_image_tokens"?: number + readonly "output_image_tokens"?: number + readonly "num_model_requests": number + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "model"?: string | null + readonly "batch"?: boolean | null + readonly "service_tier"?: string | null } -export const RealtimeServerEventRateLimitsUpdated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("rate_limits.updated").annotate({ - "description": "The event type, must be `rate_limits.updated`." - }), - "rate_limits": Schema.Array(Schema.Struct({ - "name": Schema.optionalKey( - Schema.Literals(["requests", "tokens"]).annotate({ - "description": "The name of the rate limit (`requests`, `tokens`).\n" - }) - ), - "limit": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum allowed value for the rate limit." }).check(Schema.isInt()) - ), - "remaining": Schema.optionalKey( - Schema.Number.annotate({ "description": "The remaining value before the limit is reached." }).check( - Schema.isInt() - ) - ), - "reset_seconds": Schema.optionalKey( - Schema.Number.annotate({ "description": "Seconds until the rate limit resets." }).check(Schema.isFinite()) +export const UsageCompletionsResult = Schema.Struct({ + "api_source": Schema.optionalKey( + Schema.Union([Schema.Literals(["agents_api", "unlabeled"]), Schema.Null]).annotate({ + "description": + "When grouped by `api_source`, `agents_api` identifies attributed Agents API activity and `unlabeled` includes all records without published source attribution, including historical and unknown origins. Unlabeled does not imply direct API usage. Without source grouping, this field is null." + }) + ), + "object": Schema.Literal("organization.usage.completions.result"), + "input_tokens": Schema.Number.annotate({ + "description": + "The aggregated number of input tokens used, including cached and cache-write tokens. This includes text, audio, and image tokens. For customers subscribed to Scale Tier, this includes Scale Tier tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "input_cached_tokens": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The aggregated number of cached input tokens used across text, audio, and image inputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "input_cache_write_tokens": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The aggregated number of input tokens written to the cache with a 30-minute retention period." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "input_cache_write_12h_tokens": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The aggregated number of input tokens written to the cache with a 12-hour retention period." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "input_uncached_tokens": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The aggregated number of uncached input tokens used across text, audio, and image inputs, excluding cache-write tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "output_tokens": Schema.Number.annotate({ + "description": + "The aggregated number of output tokens used across text, audio, and image outputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "input_text_tokens": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The aggregated number of uncached text input tokens used, excluding cache-write tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "output_text_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The aggregated number of text output tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) - })).annotate({ "description": "List of rate limit information." }) -}).annotate({ - "description": - "Emitted at the beginning of a Response to indicate the updated rate limits. \nWhen a Response is created some tokens will be \"reserved\" for the output \ntokens, the rate limits shown here reflect that reservation, which is then \nadjusted accordingly once the Response is completed.\n" -}) -export type RealtimeServerEventResponseAudioDelta = { - readonly "event_id": string - readonly "type": "response.output_audio.delta" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "delta": string -} -export const RealtimeServerEventResponseAudioDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.output_audio.delta").annotate({ - "description": "The event type, must be `response.output_audio.delta`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() ), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part in the item's content array." - }).check(Schema.isInt()), - "delta": Schema.String.annotate({ "description": "Base64-encoded audio data delta." }) -}).annotate({ "description": "Returned when the model-generated audio is updated." }) -export type RealtimeServerEventResponseAudioDone = { - readonly "event_id": string - readonly "type": "response.output_audio.done" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number -} -export const RealtimeServerEventResponseAudioDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.output_audio.done").annotate({ - "description": "The event type, must be `response.output_audio.done`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "input_cached_text_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The aggregated number of cached text input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part in the item's content array." - }).check(Schema.isInt()) -}).annotate({ - "description": - "Returned when the model-generated audio is done. Also emitted when a Response\nis interrupted, incomplete, or cancelled.\n" -}) -export type RealtimeServerEventResponseAudioTranscriptDelta = { - readonly "event_id": string - readonly "type": "response.output_audio_transcript.delta" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "delta": string -} -export const RealtimeServerEventResponseAudioTranscriptDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.output_audio_transcript.delta").annotate({ - "description": "The event type, must be `response.output_audio_transcript.delta`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "input_audio_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The aggregated number of uncached audio input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part in the item's content array." - }).check(Schema.isInt()), - "delta": Schema.String.annotate({ "description": "The transcript delta." }) -}).annotate({ "description": "Returned when the model-generated transcription of audio output is updated.\n" }) -export type RealtimeServerEventResponseAudioTranscriptDone = { - readonly "event_id": string - readonly "type": "response.output_audio_transcript.done" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "transcript": string -} -export const RealtimeServerEventResponseAudioTranscriptDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.output_audio_transcript.done").annotate({ - "description": "The event type, must be `response.output_audio_transcript.done`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "input_cached_audio_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The aggregated number of cached audio input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part in the item's content array." - }).check(Schema.isInt()), - "transcript": Schema.String.annotate({ "description": "The final transcript of the audio." }) -}).annotate({ - "description": - "Returned when the model-generated transcription of audio output is done\nstreaming. Also emitted when a Response is interrupted, incomplete, or\ncancelled.\n" -}) -export type RealtimeServerEventResponseContentPartAdded = { - readonly "event_id": string - readonly "type": "response.content_part.added" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "part": { - readonly "type"?: "audio" | "text" - readonly "text"?: string - readonly "audio"?: string - readonly "transcript"?: string - } -} -export const RealtimeServerEventResponseContentPartAdded = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.content_part.added").annotate({ - "description": "The event type, must be `response.content_part.added`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item to which the content part was added." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "output_audio_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The aggregated number of audio output tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part in the item's content array." - }).check(Schema.isInt()), - "part": Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literals(["audio", "text"]).annotate({ "description": "The content type (\"text\", \"audio\")." }) - ), - "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content (if type is \"text\")." })), - "audio": Schema.optionalKey( - Schema.String.annotate({ "description": "Base64-encoded audio data (if type is \"audio\")." }) - ), - "transcript": Schema.optionalKey( - Schema.String.annotate({ "description": "The transcript of the audio (if type is \"audio\")." }) + "input_image_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The aggregated number of uncached image input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) - }).annotate({ "description": "The content part that was added." }) -}).annotate({ - "description": "Returned when a new content part is added to an assistant message item during\nresponse generation.\n" -}) -export type RealtimeServerEventResponseContentPartDone = { - readonly "event_id": string - readonly "type": "response.content_part.done" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "part": { - readonly "type"?: "audio" | "text" - readonly "text"?: string - readonly "audio"?: string - readonly "transcript"?: string - } -} -export const RealtimeServerEventResponseContentPartDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.content_part.done").annotate({ - "description": "The event type, must be `response.content_part.done`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() ), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part in the item's content array." - }).check(Schema.isInt()), - "part": Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literals(["audio", "text"]).annotate({ "description": "The content type (\"text\", \"audio\")." }) - ), - "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content (if type is \"text\")." })), - "audio": Schema.optionalKey( - Schema.String.annotate({ "description": "Base64-encoded audio data (if type is \"audio\")." }) - ), - "transcript": Schema.optionalKey( - Schema.String.annotate({ "description": "The transcript of the audio (if type is \"audio\")." }) + "input_cached_image_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The aggregated number of cached image input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) - }).annotate({ "description": "The content part that is done." }) -}).annotate({ - "description": - "Returned when a content part is done streaming in an assistant message item.\nAlso emitted when a Response is interrupted, incomplete, or cancelled.\n" -}) -export type RealtimeServerEventResponseFunctionCallArgumentsDelta = { - readonly "event_id": string - readonly "type": "response.function_call_arguments.delta" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "call_id": string - readonly "delta": string -} -export const RealtimeServerEventResponseFunctionCallArgumentsDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.function_call_arguments.delta").annotate({ - "description": "The event type, must be `response.function_call_arguments.delta`.\n" - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the function call item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() ), - "call_id": Schema.String.annotate({ "description": "The ID of the function call." }), - "delta": Schema.String.annotate({ "description": "The arguments delta as a JSON string." }) -}).annotate({ "description": "Returned when the model-generated function call arguments are updated.\n" }) -export type RealtimeServerEventResponseFunctionCallArgumentsDone = { - readonly "event_id": string - readonly "type": "response.function_call_arguments.done" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "call_id": string - readonly "name": string - readonly "arguments": string -} -export const RealtimeServerEventResponseFunctionCallArgumentsDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.function_call_arguments.done").annotate({ - "description": "The event type, must be `response.function_call_arguments.done`.\n" - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the function call item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "output_image_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The aggregated number of image output tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), - "call_id": Schema.String.annotate({ "description": "The ID of the function call." }), - "name": Schema.String.annotate({ "description": "The name of the function that was called." }), - "arguments": Schema.String.annotate({ "description": "The final arguments as a JSON string." }) -}).annotate({ - "description": - "Returned when the model-generated function call arguments are done streaming.\nAlso emitted when a Response is interrupted, incomplete, or cancelled.\n" -}) -export type RealtimeServerEventResponseMCPCallArgumentsDelta = { - readonly "event_id": string - readonly "type": "response.mcp_call_arguments.delta" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "delta": string - readonly "obfuscation"?: string | null -} -export const RealtimeServerEventResponseMCPCallArgumentsDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.mcp_call_arguments.delta").annotate({ - "description": "The event type, must be `response.mcp_call_arguments.delta`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "delta": Schema.String.annotate({ "description": "The JSON-encoded arguments delta." }), - "obfuscation": Schema.optionalKey( + "project_id": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ "description": "If present, indicates the delta text was obfuscated." }), + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), Schema.Null ]) - ) -}).annotate({ "description": "Returned when MCP tool call arguments are updated during response generation." }) -export type RealtimeServerEventResponseMCPCallArgumentsDone = { - readonly "event_id": string - readonly "type": "response.mcp_call_arguments.done" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "arguments": string -} -export const RealtimeServerEventResponseMCPCallArgumentsDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.mcp_call_arguments.done").annotate({ - "description": "The event type, must be `response.mcp_call_arguments.done`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() ), - "arguments": Schema.String.annotate({ "description": "The final JSON-encoded arguments string." }) -}).annotate({ "description": "Returned when MCP tool call arguments are finalized during response generation." }) -export type RealtimeServerEventResponseMCPCallCompleted = { - readonly "event_id": string - readonly "type": "response.mcp_call.completed" - readonly "output_index": number - readonly "item_id": string -} -export const RealtimeServerEventResponseMCPCallCompleted = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.mcp_call.completed").annotate({ - "description": "The event type, must be `response.mcp_call.completed`." - }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null + ]) ), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item." }) -}).annotate({ "description": "Returned when an MCP tool call has completed successfully." }) -export type RealtimeServerEventResponseMCPCallFailed = { - readonly "event_id": string - readonly "type": "response.mcp_call.failed" - readonly "output_index": number - readonly "item_id": string -} -export const RealtimeServerEventResponseMCPCallFailed = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.mcp_call.failed").annotate({ - "description": "The event type, must be `response.mcp_call.failed`." - }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) ), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item." }) -}).annotate({ "description": "Returned when an MCP tool call has failed." }) -export type RealtimeServerEventResponseMCPCallInProgress = { - readonly "event_id": string - readonly "type": "response.mcp_call.in_progress" - readonly "output_index": number - readonly "item_id": string -} -export const RealtimeServerEventResponseMCPCallInProgress = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.mcp_call.in_progress").annotate({ - "description": "The event type, must be `response.mcp_call.in_progress`." - }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "model": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=model`, this field provides the model name of the grouped usage result." + }), + Schema.Null + ]) ), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item." }) -}).annotate({ "description": "Returned when an MCP tool call has started and is in progress." }) -export type RealtimeServerEventResponseTextDelta = { - readonly "event_id": string - readonly "type": "response.output_text.delta" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "delta": string -} -export const RealtimeServerEventResponseTextDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.output_text.delta").annotate({ - "description": "The event type, must be `response.output_text.delta`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() + "batch": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": "When `group_by=batch`, this field tells whether the grouped usage result is batch or not." + }), + Schema.Null + ]) ), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part in the item's content array." - }).check(Schema.isInt()), - "delta": Schema.String.annotate({ "description": "The text delta." }) -}).annotate({ "description": "Returned when the text value of an \"output_text\" content part is updated." }) -export type RealtimeServerEventResponseTextDone = { - readonly "event_id": string - readonly "type": "response.output_text.done" - readonly "response_id": string - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "text": string -} -export const RealtimeServerEventResponseTextDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.output_text.done").annotate({ - "description": "The event type, must be `response.output_text.done`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the response." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the response." }).check( - Schema.isInt() - ), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part in the item's content array." - }).check(Schema.isInt()), - "text": Schema.String.annotate({ "description": "The final text content." }) + "service_tier": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=service_tier`, this field provides the service tier of the grouped usage result." + }), + Schema.Null + ]) + ) }).annotate({ - "description": - "Returned when the text value of an \"output_text\" content part is done streaming. Also\nemitted when a Response is interrupted, incomplete, or cancelled.\n" + "description": "The aggregated completions usage details of the specific time bucket.", + "identifier": "UsageCompletionsResult" }) -export type RealtimeTranscriptionSessionCreateResponse = { - readonly "client_secret": { readonly "value": string; readonly "expires_at": number } - readonly "modalities"?: ReadonlyArray<"text" | "audio"> - readonly "input_audio_format"?: string - readonly "input_audio_transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - } - readonly "turn_detection"?: { - readonly "type"?: string - readonly "threshold"?: number - readonly "prefix_padding_ms"?: number - readonly "silence_duration_ms"?: number - } +export type UsageEmbeddingsResult = { + readonly "object": "organization.usage.embeddings.result" + readonly "input_tokens": number + readonly "num_model_requests": number + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "model"?: string | null } -export const RealtimeTranscriptionSessionCreateResponse = Schema.Struct({ - "client_secret": Schema.Struct({ - "value": Schema.String.annotate({ - "description": - "Ephemeral key usable in client environments to authenticate connections\nto the Realtime API. Use this in client-side environments rather than\na standard API token, which should only be used server-side.\n" - }), - "expires_at": Schema.Number.annotate({ - "description": "Timestamp for when the token expires. Currently, all tokens expire\nafter one minute.\n", - "format": "unixtime" - }).check(Schema.isInt()) - }).annotate({ - "description": - "Ephemeral key returned by the API. Only present when the session is\ncreated on the server via REST API.\n" - }), - "modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": "The set of modalities the model can respond with. To disable audio,\nset this to [\"text\"].\n" - }) +export const UsageEmbeddingsResult = Schema.Struct({ + "object": Schema.Literal("organization.usage.embeddings.result"), + "input_tokens": Schema.Number.annotate({ "description": "The aggregated number of input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "input_audio_format": Schema.optionalKey( - Schema.String.annotate({ - "description": "The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\n" - }) + "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "input_audio_transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model used for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`.\n" - }) - ), - "language": Schema.optionalKey(Schema.String.annotate({ "description": "The language of the input audio.\n" })), - "prompt": Schema.optionalKey( - Schema.String.annotate({ - "description": "The prompt configured for input audio transcription, when present.\n" - }) - ) - }).annotate({ "description": "Configuration of the transcription model.\n" }) + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null + ]) ), - "turn_detection": Schema.optionalKey( - Schema.Struct({ - "type": Schema.optionalKey( - Schema.String.annotate({ "description": "Type of turn detection, only `server_vad` is currently supported.\n" }) - ), - "threshold": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" - }).check(Schema.isFinite()) - ), - "prefix_padding_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" - }).check(Schema.isInt()) - ), - "silence_duration_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" - }).check(Schema.isInt()) - ) - }).annotate({ - "description": - "Configuration for turn detection. Can be set to `null` to turn off. Server\nVAD means that the model will detect the start and end of speech based on\naudio volume and respond at the end of user speech.\n" - }) + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=model`, this field provides the model name of the grouped usage result." + }), + Schema.Null + ]) ) }).annotate({ - "description": - "A new Realtime transcription session configuration.\n\nWhen a session is created on the server via REST API, the session object\nalso contains an ephemeral key. Default TTL for keys is 10 minutes. This\nproperty is not present when a session is updated via the WebSocket API.\n" + "description": "The aggregated embeddings usage details of the specific time bucket.", + "identifier": "UsageEmbeddingsResult" }) -export type RealtimeTranslationClientEventInputAudioBufferAppend = { - readonly "event_id"?: string - readonly "type": "session.input_audio_buffer.append" - readonly "audio": string +export type UsageModerationsResult = { + readonly "object": "organization.usage.moderations.result" + readonly "input_tokens": number + readonly "num_model_requests": number + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "model"?: string | null } -export const RealtimeTranslationClientEventInputAudioBufferAppend = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) +export const UsageModerationsResult = Schema.Struct({ + "object": Schema.Literal("organization.usage.moderations.result"), + "input_tokens": Schema.Number.annotate({ "description": "The aggregated number of input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "type": Schema.Literal("session.input_audio_buffer.append").annotate({ - "description": "The event type, must be `session.input_audio_buffer.append`." - }), - "audio": Schema.String.annotate({ "description": "Base64-encoded 24 kHz PCM16 mono audio bytes." }) -}).annotate({ - "description": - "Send this event to append audio bytes to the translation session input audio buffer.\n\nWebSocket translation sessions accept base64-encoded 24 kHz PCM16 mono\nlittle-endian raw audio bytes. Unsupported websocket audio formats return a\nvalidation error because lower-quality audio materially degrades translation\nquality.\n\nTranslation consumes 200 ms engine frames. For best realtime behavior, append\naudio in 200 ms chunks. If a chunk is shorter, the server buffers it until it\nhas enough audio for one frame. If a chunk is longer, the server splits it into\n200 ms frames and enqueues them back-to-back.\n\nKeep appending silence while the session is active. If a client stops sending\naudio and later resumes, model time treats the resumed audio as contiguous with\nthe previous audio rather than as a real-world pause.\n" -}) -export type RealtimeTranslationClientEventSessionClose = { - readonly "event_id"?: string - readonly "type": "session.close" -} -export const RealtimeTranslationClientEventSessionClose = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) + "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "type": Schema.Literal("session.close").annotate({ "description": "The event type, must be `session.close`." }) -}).annotate({ - "description": - "Gracefully close the realtime translation session. The server flushes pending\ninput audio and emits any remaining translated output before closing the\nsession.\n" -}) -export type RealtimeTranslationServerEventSessionClosed = { - readonly "event_id": string - readonly "type": "session.closed" -} -export const RealtimeTranslationServerEventSessionClosed = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("session.closed").annotate({ "description": "The event type, must be `session.closed`." }) -}).annotate({ "description": "Returned when a realtime translation session is closed.\n" }) -export type RealtimeTranslationServerEventSessionInputTranscriptDelta = { - readonly "event_id": string - readonly "type": "session.input_transcript.delta" - readonly "delta": string - readonly "elapsed_ms"?: number | null -} -export const RealtimeTranslationServerEventSessionInputTranscriptDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("session.input_transcript.delta").annotate({ - "description": "The event type, must be `session.input_transcript.delta`." - }), - "delta": Schema.String.annotate({ "description": "Append-only source-language transcript text." }), - "elapsed_ms": Schema.optionalKey(Schema.Union([ - Schema.Number.annotate({ - "description": - "Timing metadata for stream alignment, derived from the translation frame\nwhen available. It advances in 200 ms increments, but multiple transcript\ndeltas may share the same `elapsed_ms`. Treat it as alignment metadata,\nnot a unique transcript-delta identifier.\n" - }).check(Schema.isInt()), - Schema.Null - ])) + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=model`, this field provides the model name of the grouped usage result." + }), + Schema.Null + ]) + ) }).annotate({ - "description": - "Returned when optional source-language transcript text is available. This event\nis emitted only when `audio.input.transcription` is configured.\n\nTranscript deltas are append-only text fragments. Clients should not insert\nunconditional spaces between deltas.\n" + "description": "The aggregated moderations usage details of the specific time bucket.", + "identifier": "UsageModerationsResult" }) -export type RealtimeTranslationServerEventSessionOutputAudioDelta = { - readonly "event_id": string - readonly "type": "session.output_audio.delta" - readonly "delta": string - readonly "sample_rate"?: number - readonly "channels"?: number - readonly "format"?: "pcm16" - readonly "elapsed_ms"?: number | null +export type UsageImagesResult = { + readonly "object": "organization.usage.images.result" + readonly "images": number + readonly "num_model_requests": number + readonly "source"?: string | null + readonly "size"?: string | null + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "model"?: string | null } -export const RealtimeTranslationServerEventSessionOutputAudioDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("session.output_audio.delta").annotate({ - "description": "The event type, must be `session.output_audio.delta`." - }), - "delta": Schema.String.annotate({ "description": "Base64-encoded translated audio data." }), - "sample_rate": Schema.optionalKey( - Schema.Number.annotate({ "description": "Sample rate of the audio delta." }).check(Schema.isInt()) +export const UsageImagesResult = Schema.Struct({ + "object": Schema.Literal("organization.usage.images.result"), + "images": Schema.Number.annotate({ "description": "The number of images processed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "channels": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of audio channels." }).check(Schema.isInt()) + "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "format": Schema.optionalKey(Schema.Literal("pcm16").annotate({ "description": "Audio encoding for `delta`." })), - "elapsed_ms": Schema.optionalKey( + "source": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ + Schema.String.annotate({ "description": - "Timing metadata for stream alignment, derived from the translation frame\nwhen available. Treat `elapsed_ms` as alignment metadata, not a unique\nevent identifier.\n" - }).check(Schema.isInt()), + "When `group_by=source`, this field provides the source of the grouped usage result, possible values are `image.generation`, `image.edit`, `image.variation`." + }), + Schema.Null + ]) + ), + "size": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=size`, this field provides the image size of the grouped usage result." + }), + Schema.Null + ]) + ), + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=model`, this field provides the model name of the grouped usage result." + }), Schema.Null ]) ) }).annotate({ - "description": - "Returned when translated output audio is available. Output audio deltas are\n200 ms frames of PCM16 audio.\n" + "description": "The aggregated images usage details of the specific time bucket.", + "identifier": "UsageImagesResult" }) -export type RealtimeTranslationServerEventSessionOutputTranscriptDelta = { - readonly "event_id": string - readonly "type": "session.output_transcript.delta" - readonly "delta": string - readonly "elapsed_ms"?: number | null +export type UsageAudioSpeechesResult = { + readonly "object": "organization.usage.audio_speeches.result" + readonly "characters": number + readonly "num_model_requests": number + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "model"?: string | null } -export const RealtimeTranslationServerEventSessionOutputTranscriptDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("session.output_transcript.delta").annotate({ - "description": "The event type, must be `session.output_transcript.delta`." - }), - "delta": Schema.String.annotate({ "description": "Append-only transcript text for the translated output audio." }), - "elapsed_ms": Schema.optionalKey(Schema.Union([ - Schema.Number.annotate({ - "description": - "Timing metadata for stream alignment, derived from the translation frame\nwhen available. It advances in 200 ms increments, but multiple transcript\ndeltas may share the same `elapsed_ms`. Treat it as alignment metadata,\nnot a unique transcript-delta identifier.\n" - }).check(Schema.isInt()), - Schema.Null - ])) +export const UsageAudioSpeechesResult = Schema.Struct({ + "object": Schema.Literal("organization.usage.audio_speeches.result"), + "characters": Schema.Number.annotate({ "description": "The number of characters processed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=model`, this field provides the model name of the grouped usage result." + }), + Schema.Null + ]) + ) }).annotate({ - "description": - "Returned when translated transcript text is available.\n\nTranscript deltas are append-only text fragments. Clients should not insert\nunconditional spaces between deltas.\n" + "description": "The aggregated audio speeches usage details of the specific time bucket.", + "identifier": "UsageAudioSpeechesResult" }) -export type RealtimeTruncation = "auto" | "disabled" | { - readonly "type": "retention_ratio" - readonly "retention_ratio": number - readonly "token_limits"?: { readonly "post_instructions"?: number } +export type UsageAudioTranscriptionsResult = { + readonly "object": "organization.usage.audio_transcriptions.result" + readonly "seconds": number + readonly "num_model_requests": number + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "model"?: string | null } -export const RealtimeTruncation = Schema.Union([ - Schema.Literals(["auto", "disabled"]).annotate({ - "description": - "The truncation strategy to use for the session. `auto` is the default truncation strategy. `disabled` will disable truncation and emit errors when the conversation exceeds the input token limit." - }), - Schema.Struct({ - "type": Schema.Literal("retention_ratio").annotate({ "description": "Use retention ratio truncation." }), - "retention_ratio": Schema.Number.annotate({ - "description": - "Fraction of post-instruction conversation tokens to retain (`0.0` - `1.0`) when the conversation exceeds the input token limit. Setting this to `0.8` means that messages will be dropped until 80% of the maximum allowed tokens are used. This helps reduce the frequency of truncations and improve cache rates.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - "token_limits": Schema.optionalKey( - Schema.Struct({ - "post_instructions": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Maximum tokens allowed in the conversation after instructions (which including tool definitions). For example, setting this to 5,000 would mean that truncation would occur when the conversation exceeds 5,000 tokens after instructions. This cannot be higher than the model's context window size minus the maximum output tokens." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)) - ) - }).annotate({ - "description": - "Optional custom token limits for this truncation strategy. If not provided, the model's default token limits will be used." - }) - ) - }).annotate({ - "title": "Retention ratio truncation", - "description": - "Retain a fraction of the conversation tokens when the conversation exceeds the input token limit. This allows you to amortize truncations across multiple turns, which can help improve cached token usage." - }) -], { mode: "oneOf" }).annotate({ - "title": "Realtime Truncation Controls", - "description": - "When the number of tokens in a conversation exceeds the model's input token limit, the conversation be truncated, meaning messages (starting from the oldest) will not be included in the model's context. A 32k context model with 4,096 max output tokens can only include 28,224 tokens in the context before truncation occurs.\n\nClients can configure truncation behavior to truncate with a lower max token limit, which is an effective way to control token usage and cost.\n\nTruncation will reduce the number of cached tokens on the next turn (busting the cache), since messages are dropped from the beginning of the context. However, clients can also configure truncation to retain messages up to a fraction of the maximum context size, which will reduce the need for future truncations and thus improve the cache rate.\n\nTruncation can be disabled entirely, which means the server will never truncate but would instead return an error if the conversation exceeds the model's input token limit.\n" -}) -export type RealtimeTurnDetection = { - readonly "type": "server_vad" - readonly "threshold"?: number - readonly "prefix_padding_ms"?: number - readonly "silence_duration_ms"?: number - readonly "create_response"?: boolean - readonly "interrupt_response"?: boolean - readonly "idle_timeout_ms"?: number | null -} | { - readonly "type": "semantic_vad" - readonly "eagerness"?: "low" | "medium" | "high" | "auto" - readonly "create_response"?: boolean - readonly "interrupt_response"?: boolean -} | null -export const RealtimeTurnDetection = Schema.Union([ - Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("server_vad").annotate({ - "description": "Type of turn detection, `server_vad` to turn on simple Server VAD.\n" - }), - "threshold": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" - }).check(Schema.isFinite()) - ), - "prefix_padding_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" - }).check(Schema.isInt()) - ), - "silence_duration_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" - }).check(Schema.isInt()) - ), - "create_response": Schema.optionalKey(Schema.Boolean.annotate({ - "description": - "Whether or not to automatically generate a response when a VAD stop event occurs. If `interrupt_response` is set to `false` this may fail to create a response if the model is already responding.\n\nIf both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted.\n" - })), - "interrupt_response": Schema.optionalKey(Schema.Boolean.annotate({ - "description": - "Whether or not to automatically interrupt (cancel) any ongoing response with output to the default\nconversation (i.e. `conversation` of `auto`) when a VAD start event occurs. If `true` then the response will be cancelled, otherwise it will continue until complete.\n\nIf both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted.\n" - })), - "idle_timeout_ms": Schema.optionalKey(Schema.Union([ - Schema.Number.annotate({ - "description": - "Optional timeout after which a model response will be triggered automatically. This is\nuseful for situations in which a long pause from the user is unexpected, such as a phone\ncall. The model will effectively prompt the user to continue the conversation based\non the current context.\n\nThe timeout value will be applied after the last model response's audio has finished playing,\ni.e. it's set to the `response.done` time plus audio playback duration.\n\nAn `input_audio_buffer.timeout_triggered` event (plus events\nassociated with the Response) will be emitted when the timeout is reached.\nIdle timeout is currently only supported for `server_vad` mode.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(5000)).check(Schema.isLessThanOrEqualTo(30000)), - Schema.Null - ])) - }).annotate({ - "title": "Server VAD", - "description": - "Server-side voice activity detection (VAD) which flips on when user speech is detected and off after a period of silence." - }), - Schema.Struct({ - "type": Schema.Literal("semantic_vad").annotate({ - "description": "Type of turn detection, `semantic_vad` to turn on Semantic VAD.\n" +export const UsageAudioTranscriptionsResult = Schema.Struct({ + "object": Schema.Literal("organization.usage.audio_transcriptions.result"), + "seconds": Schema.Number.annotate({ "description": "The number of seconds processed.", "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." }), - "eagerness": Schema.optionalKey( - Schema.Literals(["low", "medium", "high", "auto"]).annotate({ - "description": - "Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. `low`, `medium`, and `high` have max timeouts of 8s, 4s, and 2s respectively.\n" - }) - ), - "create_response": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": "Whether or not to automatically generate a response when a VAD stop event occurs.\n" - }) - ), - "interrupt_response": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": - "Whether or not to automatically interrupt any ongoing response with output to the default\nconversation (i.e. `conversation` of `auto`) when a VAD start event occurs.\n" - }) - ) - }).annotate({ - "title": "Semantic VAD", - "description": - "Server-side semantic turn detection which uses a model to determine when the user has finished speaking." - }) - ], { mode: "oneOf" }).annotate({ - "title": "Realtime Turn Detection", - "description": - "Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response.\n\nServer VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech.\n\nSemantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with \"uhhm\", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency.\n\nFor `gpt-realtime-whisper` transcription sessions, turn detection must be\nset to `null`; VAD is not supported.\n" - }), - Schema.Null -]) -export type ReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | null -export const ReasoningEffort = Schema.Union([ - Schema.Literals(["none", "minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": - "Constrains effort on reasoning for\n[reasoning models](https://platform.openai.com/docs/guides/reasoning).\nCurrently supported values are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`. Reducing\nreasoning effort can result in faster responses and fewer tokens used\non reasoning in a response.\n\n- `gpt-5.1` defaults to `none`, which does not perform reasoning. The supported reasoning values for `gpt-5.1` are `none`, `low`, `medium`, and `high`. Tool calls are supported for all reasoning values in gpt-5.1.\n- All models before `gpt-5.1` default to `medium` reasoning effort, and do not support `none`.\n- The `gpt-5-pro` model defaults to (and only supports) `high` reasoning effort.\n- `xhigh` is supported for all models after `gpt-5.1-codex-max`.\n" - }), - Schema.Null -]) -export type ResponseAudioDeltaEvent = { - readonly "type": "response.audio.delta" - readonly "sequence_number": number - readonly "delta": string -} -export const ResponseAudioDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.audio.delta").annotate({ - "description": "The type of the event. Always `response.audio.delta`.\n" - }), - "sequence_number": Schema.Number.annotate({ - "description": "A sequence number for this chunk of the stream response.\n" - }).check(Schema.isInt()), - "delta": Schema.String.annotate({ "description": "A chunk of Base64 encoded response audio bytes.\n" }) -}).annotate({ "description": "Emitted when there is a partial audio response." }) -export type ResponseAudioDoneEvent = { - readonly "type": "response.audio.done" - readonly "sequence_number": number - readonly "response_id": unknown -} -export const ResponseAudioDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.audio.done").annotate({ - "description": "The type of the event. Always `response.audio.done`.\n" - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the delta.\n" }).check( - Schema.isInt() + Schema.Null + ]) ), - "response_id": Schema.Unknown -}).annotate({ "description": "Emitted when the audio response is complete." }) -export type ResponseAudioTranscriptDeltaEvent = { - readonly "type": "response.audio.transcript.delta" - readonly "delta": string - readonly "sequence_number": number - readonly "response_id": unknown -} -export const ResponseAudioTranscriptDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.audio.transcript.delta").annotate({ - "description": "The type of the event. Always `response.audio.transcript.delta`.\n" - }), - "delta": Schema.String.annotate({ "description": "The partial transcript of the audio response.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null + ]) ), - "response_id": Schema.Unknown -}).annotate({ "description": "Emitted when there is a partial transcript of audio." }) -export type ResponseAudioTranscriptDoneEvent = { - readonly "type": "response.audio.transcript.done" - readonly "sequence_number": number - readonly "response_id": unknown -} -export const ResponseAudioTranscriptDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.audio.transcript.done").annotate({ - "description": "The type of the event. Always `response.audio.transcript.done`.\n" - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) ), - "response_id": Schema.Unknown -}).annotate({ "description": "Emitted when the full audio transcript is completed." }) -export type ResponseCodeInterpreterCallCodeDeltaEvent = { - readonly "type": "response.code_interpreter_call_code.delta" - readonly "output_index": number - readonly "item_id": string - readonly "delta": string - readonly "sequence_number": number -} -export const ResponseCodeInterpreterCallCodeDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.code_interpreter_call_code.delta").annotate({ - "description": "The type of the event. Always `response.code_interpreter_call_code.delta`." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response for which the code is being streamed." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), - "delta": Schema.String.annotate({ - "description": "The partial code snippet being streamed by the code interpreter." - }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of this event, used to order streaming events." - }).check(Schema.isInt()) -}).annotate({ "description": "Emitted when a partial code snippet is streamed by the code interpreter." }) -export type ResponseCodeInterpreterCallCodeDoneEvent = { - readonly "type": "response.code_interpreter_call_code.done" - readonly "output_index": number - readonly "item_id": string - readonly "code": string - readonly "sequence_number": number -} -export const ResponseCodeInterpreterCallCodeDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.code_interpreter_call_code.done").annotate({ - "description": "The type of the event. Always `response.code_interpreter_call_code.done`." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response for which the code is finalized." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), - "code": Schema.String.annotate({ "description": "The final code snippet output by the code interpreter." }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of this event, used to order streaming events." - }).check(Schema.isInt()) -}).annotate({ "description": "Emitted when the code snippet is finalized by the code interpreter." }) -export type ResponseCodeInterpreterCallCompletedEvent = { - readonly "type": "response.code_interpreter_call.completed" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number -} -export const ResponseCodeInterpreterCallCompletedEvent = Schema.Struct({ - "type": Schema.Literal("response.code_interpreter_call.completed").annotate({ - "description": "The type of the event. Always `response.code_interpreter_call.completed`." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response for which the code interpreter call is completed." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of this event, used to order streaming events." - }).check(Schema.isInt()) -}).annotate({ "description": "Emitted when the code interpreter call is completed." }) -export type ResponseCodeInterpreterCallInProgressEvent = { - readonly "type": "response.code_interpreter_call.in_progress" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number + "model": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=model`, this field provides the model name of the grouped usage result." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "The aggregated audio transcriptions usage details of the specific time bucket.", + "identifier": "UsageAudioTranscriptionsResult" +}) +export type UsageVectorStoresResult = { + readonly "object": "organization.usage.vector_stores.result" + readonly "usage_bytes": number + readonly "project_id"?: string | null } -export const ResponseCodeInterpreterCallInProgressEvent = Schema.Struct({ - "type": Schema.Literal("response.code_interpreter_call.in_progress").annotate({ - "description": "The type of the event. Always `response.code_interpreter_call.in_progress`." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response for which the code interpreter call is in progress." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of this event, used to order streaming events." - }).check(Schema.isInt()) -}).annotate({ "description": "Emitted when a code interpreter call is in progress." }) -export type ResponseCodeInterpreterCallInterpretingEvent = { - readonly "type": "response.code_interpreter_call.interpreting" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number +export const UsageVectorStoresResult = Schema.Struct({ + "object": Schema.Literal("organization.usage.vector_stores.result"), + "usage_bytes": Schema.Number.annotate({ "description": "The vector stores usage in bytes." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "The aggregated vector stores usage details of the specific time bucket.", + "identifier": "UsageVectorStoresResult" +}) +export type UsageCodeInterpreterSessionsResult = { + readonly "object": "organization.usage.code_interpreter_sessions.result" + readonly "num_sessions": number + readonly "project_id"?: string | null } -export const ResponseCodeInterpreterCallInterpretingEvent = Schema.Struct({ - "type": Schema.Literal("response.code_interpreter_call.interpreting").annotate({ - "description": "The type of the event. Always `response.code_interpreter_call.interpreting`." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response for which the code interpreter is interpreting code." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of this event, used to order streaming events." - }).check(Schema.isInt()) -}).annotate({ "description": "Emitted when the code interpreter is actively interpreting the code snippet." }) -export type ResponseCustomToolCallInputDeltaEvent = { - readonly "type": "response.custom_tool_call_input.delta" - readonly "sequence_number": number - readonly "output_index": number - readonly "item_id": string - readonly "delta": string +export const UsageCodeInterpreterSessionsResult = Schema.Struct({ + "object": Schema.Literal("organization.usage.code_interpreter_sessions.result"), + "num_sessions": Schema.Number.annotate({ "description": "The number of code interpreter sessions." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "The aggregated code interpreter sessions usage details of the specific time bucket.", + "identifier": "UsageCodeInterpreterSessionsResult" +}) +export type UsageFileSearchCallsResult = { + readonly "object": "organization.usage.file_searches.result" + readonly "num_requests": number + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "vector_store_id"?: string | null } -export const ResponseCustomToolCallInputDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.custom_tool_call_input.delta").annotate({ - "description": "The event type identifier." - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() +export const UsageFileSearchCallsResult = Schema.Struct({ + "object": Schema.Literal("organization.usage.file_searches.result"), + "num_requests": Schema.Number.annotate({ "description": "The count of file search calls." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "output_index": Schema.Number.annotate({ "description": "The index of the output this delta applies to." }).check( - Schema.isInt() + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null + ]) ), - "item_id": Schema.String.annotate({ - "description": "Unique identifier for the API item associated with this event." - }), - "delta": Schema.String.annotate({ "description": "The incremental input data (delta) for the custom tool call." }) + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "vector_store_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "When `group_by=vector_store_id`, this field provides the vector store ID of the grouped usage result." + }), + Schema.Null + ]) + ) }).annotate({ - "title": "ResponseCustomToolCallInputDelta", - "description": "Event representing a delta (partial update) to the input of a custom tool call.\n" + "description": "The aggregated file search calls usage details of the specific time bucket.", + "identifier": "UsageFileSearchCallsResult" }) -export type ResponseCustomToolCallInputDoneEvent = { - readonly "type": "response.custom_tool_call_input.done" - readonly "sequence_number": number - readonly "output_index": number - readonly "item_id": string - readonly "input": string +export type UsageWebSearchCallsResult = { + readonly "api_source"?: "agents_api" | "unlabeled" | null + readonly "object": "organization.usage.web_searches.result" + readonly "num_model_requests": number + readonly "num_requests": number + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "model"?: string | null + readonly "context_level"?: string | null } -export const ResponseCustomToolCallInputDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.custom_tool_call_input.done").annotate({ - "description": "The event type identifier." - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() +export const UsageWebSearchCallsResult = Schema.Struct({ + "api_source": Schema.optionalKey( + Schema.Union([Schema.Literals(["agents_api", "unlabeled"]), Schema.Null]).annotate({ + "description": + "When grouped by `api_source`, `agents_api` identifies attributed Agents API activity and `unlabeled` includes all records without published source attribution, including historical and unknown origins. Unlabeled does not imply direct API usage. Without source grouping, this field is null." + }) ), - "output_index": Schema.Number.annotate({ "description": "The index of the output this event applies to." }).check( - Schema.isInt() + "object": Schema.Literal("organization.usage.web_searches.result"), + "num_model_requests": Schema.Number.annotate({ "description": "The count of model requests." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "item_id": Schema.String.annotate({ - "description": "Unique identifier for the API item associated with this event." - }), - "input": Schema.String.annotate({ "description": "The complete input data for the custom tool call." }) + "num_requests": Schema.Number.annotate({ "description": "The count of web search calls." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) + ), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=model`, this field provides the model name of the grouped usage result." + }), + Schema.Null + ]) + ), + "context_level": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "When `group_by=context_level`, this field provides the search context size of the grouped usage result." + }), + Schema.Null + ]) + ) }).annotate({ - "title": "ResponseCustomToolCallInputDone", - "description": "Event indicating that input for a custom tool call is complete.\n" + "description": "The aggregated web search calls usage details of the specific time bucket.", + "identifier": "UsageWebSearchCallsResult" }) -export type ResponseErrorCode = - | "server_error" - | "rate_limit_exceeded" - | "invalid_prompt" - | "vector_store_timeout" - | "invalid_image" - | "invalid_image_format" - | "invalid_base64_image" - | "invalid_image_url" - | "image_too_large" - | "image_too_small" - | "image_parse_error" - | "image_content_policy_violation" - | "invalid_image_mode" - | "image_file_too_large" - | "unsupported_image_media_type" - | "empty_image_file" - | "failed_to_download_image" - | "image_file_not_found" -export const ResponseErrorCode = Schema.Literals([ - "server_error", - "rate_limit_exceeded", - "invalid_prompt", - "vector_store_timeout", - "invalid_image", - "invalid_image_format", - "invalid_base64_image", - "invalid_image_url", - "image_too_large", - "image_too_small", - "image_parse_error", - "image_content_policy_violation", - "invalid_image_mode", - "image_file_too_large", - "unsupported_image_media_type", - "empty_image_file", - "failed_to_download_image", - "image_file_not_found" -]).annotate({ "description": "The error code for the response.\n" }) -export type ResponseErrorEvent = { - readonly "type": "error" - readonly "code": string | null - readonly "message": string - readonly "param": string | null - readonly "sequence_number": number -} -export const ResponseErrorEvent = Schema.Struct({ - "type": Schema.Literal("error").annotate({ "description": "The type of the event. Always `error`.\n" }), - "code": Schema.Union([Schema.String.annotate({ "description": "The error code.\n" }), Schema.Null]), - "message": Schema.String.annotate({ "description": "The error message.\n" }), - "param": Schema.Union([Schema.String.annotate({ "description": "The error parameter.\n" }), Schema.Null]), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) -}).annotate({ "description": "Emitted when an error occurs." }) -export type ResponseFileSearchCallCompletedEvent = { - readonly "type": "response.file_search_call.completed" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number -} -export const ResponseFileSearchCallCompletedEvent = Schema.Struct({ - "type": Schema.Literal("response.file_search_call.completed").annotate({ - "description": "The type of the event. Always `response.file_search_call.completed`.\n" - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the file search call is initiated.\n" - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the file search call is initiated.\n" - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) -}).annotate({ "description": "Emitted when a file search call is completed (results found)." }) -export type ResponseFileSearchCallInProgressEvent = { - readonly "type": "response.file_search_call.in_progress" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number +export type CostsResult = { + readonly "api_source"?: "agents_api" | "unlabeled" | null + readonly "object": "organization.costs.result" + readonly "amount"?: { readonly "value"?: number; readonly "currency"?: string } + readonly "line_item"?: string | null + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "quantity"?: number | null + readonly "quantity_unit"?: + | string + | "tokens" + | "1000_tokens" + | "duration_seconds" + | "duration_minutes" + | "duration_hours" + | "gibibyte_hours" + | "images" + | "characters" + | null } -export const ResponseFileSearchCallInProgressEvent = Schema.Struct({ - "type": Schema.Literal("response.file_search_call.in_progress").annotate({ - "description": "The type of the event. Always `response.file_search_call.in_progress`.\n" - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the file search call is initiated.\n" - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the file search call is initiated.\n" - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() +export const CostsResult = Schema.Struct({ + "api_source": Schema.optionalKey( + Schema.Union([Schema.Literals(["agents_api", "unlabeled"]), Schema.Null]).annotate({ + "description": + "When grouped by `api_source`, `agents_api` identifies attributed Agents API activity and `unlabeled` includes all records without published source attribution, including historical and unknown origins. Unlabeled does not imply direct API usage. Without source grouping, this field is null." + }) + ), + "object": Schema.Literal("organization.costs.result"), + "amount": Schema.optionalKey( + Schema.Struct({ + "value": Schema.optionalKey( + Schema.Number.annotate({ "description": "The numeric value of the cost." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) + ), + "currency": Schema.optionalKey( + Schema.String.annotate({ "description": "Lowercase ISO-4217 currency e.g. \"usd\"" }) + ) + }).annotate({ "description": "The monetary value in its associated currency." }) + ), + "line_item": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=line_item`, this field provides the line item of the grouped costs result." + }), + Schema.Null + ]) + ), + "project_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped costs result." + }), + Schema.Null + ]) + ), + "user_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped costs result." + }), + Schema.Null + ]) + ), + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API Key ID of the grouped costs result." + }), + Schema.Null + ]) + ), + "quantity": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "When `group_by=line_item`, this field provides the quantity of the grouped costs result." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + Schema.Null + ]) + ), + "quantity_unit": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "tokens", + "1000_tokens", + "duration_seconds", + "duration_minutes", + "duration_hours", + "gibibyte_hours", + "images", + "characters" + ]), + Schema.Null + ]).annotate({ + "description": + "The unit of the `quantity` value. If no single supported unit applies to the result, this field is `null`." + }) ) -}).annotate({ "description": "Emitted when a file search call is initiated." }) -export type ResponseFileSearchCallSearchingEvent = { - readonly "type": "response.file_search_call.searching" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number +}).annotate({ "description": "The aggregated costs details of the specific time bucket.", "identifier": "CostsResult" }) +export type OrganizationDataRetention = { + readonly "object": "organization.data_retention" + readonly "type": + | "zero_data_retention" + | "modified_abuse_monitoring" + | "enhanced_zero_data_retention" + | "enhanced_modified_abuse_monitoring" } -export const ResponseFileSearchCallSearchingEvent = Schema.Struct({ - "type": Schema.Literal("response.file_search_call.searching").annotate({ - "description": "The type of the event. Always `response.file_search_call.searching`.\n" +export const OrganizationDataRetention = Schema.Struct({ + "object": Schema.Literal("organization.data_retention").annotate({ + "description": "The object type, which is always `organization.data_retention`." }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the file search call is searching.\n" - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the file search call is initiated.\n" - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) -}).annotate({ "description": "Emitted when a file search is currently searching." }) -export type ResponseFormatJsonObject = { readonly "type": "json_object" } -export const ResponseFormatJsonObject = Schema.Struct({ - "type": Schema.Literal("json_object").annotate({ - "description": "The type of response format being defined. Always `json_object`." - }) + "type": Schema.Literals([ + "zero_data_retention", + "modified_abuse_monitoring", + "enhanced_zero_data_retention", + "enhanced_modified_abuse_monitoring" + ]).annotate({ "description": "The configured organization data retention type." }) }).annotate({ - "title": "JSON object", - "description": - "JSON object response format. An older method of generating JSON responses.\nUsing `json_schema` is recommended for models that support it. Note that the\nmodel will not generate JSON without a system or user message instructing it\nto do so.\n" + "description": "Represents the organization's data retention control setting.", + "identifier": "OrganizationDataRetention" }) -export type ResponseFormatJsonSchemaSchema = {} -export const ResponseFormatJsonSchemaSchema = Schema.Struct({}).annotate({ - "title": "JSON schema", - "description": - "The schema for the response format, described as a JSON Schema object.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n" +export type UpdateOrganizationDataRetentionBody = { + readonly "retention_type": + | "zero_data_retention" + | "modified_abuse_monitoring" + | "enhanced_zero_data_retention" + | "enhanced_modified_abuse_monitoring" +} +export const UpdateOrganizationDataRetentionBody = Schema.Struct({ + "retention_type": Schema.Literals([ + "zero_data_retention", + "modified_abuse_monitoring", + "enhanced_zero_data_retention", + "enhanced_modified_abuse_monitoring" + ]).annotate({ "description": "The desired organization data retention type." }) +}).annotate({ + "description": "Parameters for updating organization data retention controls.", + "identifier": "UpdateOrganizationDataRetentionBody" }) -export type ResponseFormatText = { readonly "type": "text" } -export const ResponseFormatText = Schema.Struct({ - "type": Schema.Literal("text").annotate({ - "description": "The type of response format being defined. Always `text`." - }) -}).annotate({ "title": "Text", "description": "Default response format. Used to generate text responses.\n" }) -export type ResponseFunctionCallArgumentsDeltaEvent = { - readonly "type": "response.function_call_arguments.delta" - readonly "item_id": string - readonly "output_index": number - readonly "sequence_number": number - readonly "delta": string -} -export const ResponseFunctionCallArgumentsDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.function_call_arguments.delta").annotate({ - "description": "The type of the event. Always `response.function_call_arguments.delta`.\n" - }), - "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the function-call arguments delta is added to.\n" - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the function-call arguments delta is added to.\n" - }).check(Schema.isInt()), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ), - "delta": Schema.String.annotate({ "description": "The function-call arguments delta that is added.\n" }) -}).annotate({ "description": "Emitted when there is a partial function-call arguments delta." }) -export type ResponseFunctionCallArgumentsDoneEvent = { - readonly "type": "response.function_call_arguments.done" - readonly "item_id": string - readonly "name"?: string - readonly "output_index": number - readonly "sequence_number": number - readonly "arguments": string -} -export const ResponseFunctionCallArgumentsDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.function_call_arguments.done"), - "item_id": Schema.String.annotate({ "description": "The ID of the item." }), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function that was called." })), - "output_index": Schema.Number.annotate({ "description": "The index of the output item." }).check(Schema.isInt()), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ), - "arguments": Schema.String.annotate({ "description": "The function-call arguments." }) -}).annotate({ "description": "Emitted when function-call arguments are finalized." }) -export type ResponseImageGenCallCompletedEvent = { - readonly "type": "response.image_generation_call.completed" - readonly "output_index": number - readonly "sequence_number": number - readonly "item_id": string +export type GroupResponse = { + readonly "id": string + readonly "name": string + readonly "created_at": number + readonly "is_scim_managed": boolean + readonly "group_type": "group" | "tenant_group" } -export const ResponseImageGenCallCompletedEvent = Schema.Struct({ - "type": Schema.Literal("response.image_generation_call.completed").annotate({ - "description": "The type of the event. Always 'response.image_generation_call.completed'." +export const GroupResponse = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier for the group." }), + "name": Schema.String.annotate({ "description": "Display name of the group." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the group was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "is_scim_managed": Schema.Boolean.annotate({ + "description": "Whether the group is managed through SCIM and controlled by your identity provider." }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response's output array." - }).check(Schema.isInt()), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ), - "item_id": Schema.String.annotate({ - "description": "The unique identifier of the image generation item being processed." - }) + "group_type": Schema.Literals(["group", "tenant_group"]).annotate({ "description": "The type of the group." }) +}).annotate({ "description": "Details about an organization group.", "identifier": "GroupResponse" }) +export type CreateGroupBody = { readonly "name": string } +export const CreateGroupBody = Schema.Struct({ + "name": Schema.String.annotate({ "description": "Human readable name for the group." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(255).annotate({ "expected": "a string with at most 255 code points" })) }).annotate({ - "title": "ResponseImageGenCallCompletedEvent", - "description": "Emitted when an image generation tool call has completed and the final image is available.\n" + "description": "Request payload for creating a new group in the organization.", + "identifier": "CreateGroupBody" }) -export type ResponseImageGenCallGeneratingEvent = { - readonly "type": "response.image_generation_call.generating" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number -} -export const ResponseImageGenCallGeneratingEvent = Schema.Struct({ - "type": Schema.Literal("response.image_generation_call.generating").annotate({ - "description": "The type of the event. Always 'response.image_generation_call.generating'." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response's output array." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The unique identifier of the image generation item being processed." - }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of the image generation item being processed." - }).check(Schema.isInt()) +export type UpdateGroupBody = { readonly "name": string } +export const UpdateGroupBody = Schema.Struct({ + "name": Schema.String.annotate({ "description": "New display name for the group." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(255).annotate({ "expected": "a string with at most 255 code points" })) }).annotate({ - "title": "ResponseImageGenCallGeneratingEvent", - "description": "Emitted when an image generation tool call is actively generating an image (intermediate state).\n" + "description": "Request payload for updating the details of an existing group.", + "identifier": "UpdateGroupBody" }) -export type ResponseImageGenCallInProgressEvent = { - readonly "type": "response.image_generation_call.in_progress" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number +export type GroupResourceWithSuccess = { + readonly "id": string + readonly "name": string + readonly "created_at": number + readonly "is_scim_managed": boolean } -export const ResponseImageGenCallInProgressEvent = Schema.Struct({ - "type": Schema.Literal("response.image_generation_call.in_progress").annotate({ - "description": "The type of the event. Always 'response.image_generation_call.in_progress'." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response's output array." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The unique identifier of the image generation item being processed." - }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of the image generation item being processed." - }).check(Schema.isInt()) +export const GroupResourceWithSuccess = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier for the group." }), + "name": Schema.String.annotate({ "description": "Updated display name for the group." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the group was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "is_scim_managed": Schema.Boolean.annotate({ + "description": "Whether the group is managed through SCIM and controlled by your identity provider." + }) +}).annotate({ "description": "Response returned after updating a group.", "identifier": "GroupResourceWithSuccess" }) +export type GroupDeletedResource = { + readonly "object": "group.deleted" + readonly "id": string + readonly "deleted": boolean +} +export const GroupDeletedResource = Schema.Struct({ + "object": Schema.Literal("group.deleted").annotate({ "description": "Always `group.deleted`." }), + "id": Schema.String.annotate({ "description": "Identifier of the deleted group." }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the group was deleted." }) }).annotate({ - "title": "ResponseImageGenCallInProgressEvent", - "description": "Emitted when an image generation tool call is in progress.\n" + "description": "Confirmation payload returned after deleting a group.", + "identifier": "GroupDeletedResource" }) -export type ResponseImageGenCallPartialImageEvent = { - readonly "type": "response.image_generation_call.partial_image" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number - readonly "partial_image_index": number - readonly "partial_image_b64": string +export type AssignedRoleDetails = { + readonly "id": string + readonly "name": string + readonly "permissions": ReadonlyArray + readonly "resource_type": string + readonly "predefined_role": boolean + readonly "description": string | null + readonly "created_at": number | null + readonly "updated_at": number | null + readonly "created_by": string | null + readonly "created_by_user_obj": { readonly [x: string]: Schema.Json } | null + readonly "metadata": { readonly [x: string]: Schema.Json } | null + readonly "assignment_sources": + | ReadonlyArray<{ readonly "principal_id": string; readonly "principal_type": string }> + | null } -export const ResponseImageGenCallPartialImageEvent = Schema.Struct({ - "type": Schema.Literal("response.image_generation_call.partial_image").annotate({ - "description": "The type of the event. Always 'response.image_generation_call.partial_image'." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response's output array." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The unique identifier of the image generation item being processed." +export const AssignedRoleDetails = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier for the role." }), + "name": Schema.String.annotate({ "description": "Name of the role." }), + "permissions": Schema.Array(Schema.String).annotate({ "description": "Permissions associated with the role." }), + "resource_type": Schema.String.annotate({ "description": "Resource type the role applies to." }), + "predefined_role": Schema.Boolean.annotate({ "description": "Whether the role is predefined by OpenAI." }), + "description": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Description of the role." }), + "created_at": Schema.Union([ + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ "description": "When the role was created." }), + "updated_at": Schema.Union([ + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ "description": "When the role was last updated." }), + "created_by": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "Identifier of the actor who created the role." }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of the image generation item being processed." - }).check(Schema.isInt()), - "partial_image_index": Schema.Number.annotate({ - "description": "0-based index for the partial image (backend is 1-based, but this is 0-based for the user)." - }).check(Schema.isInt()), - "partial_image_b64": Schema.String.annotate({ - "description": "Base64-encoded partial image data, suitable for rendering as an image." - }) + "created_by_user_obj": Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), + Schema.Null + ]).annotate({ "description": "User details for the actor that created the role, when available." }), + "metadata": Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), + Schema.Null + ]).annotate({ "description": "Arbitrary metadata stored on the role." }), + "assignment_sources": Schema.Union([ + Schema.Array(Schema.Struct({ "principal_id": Schema.String, "principal_type": Schema.String })), + Schema.Null + ]).annotate({ "description": "Principals from which the role assignment is inherited, when available." }) }).annotate({ - "title": "ResponseImageGenCallPartialImageEvent", - "description": "Emitted when a partial image is available during image generation streaming.\n" + "description": "Detailed information about a role assignment entry returned when listing assignments.", + "identifier": "AssignedRoleDetails" }) -export type ResponseLogProb = { - readonly "token": string - readonly "logprob": number - readonly "top_logprobs"?: ReadonlyArray<{ readonly "token"?: string; readonly "logprob"?: number }> +export type PublicAssignOrganizationGroupRoleBody = { readonly "role_id": string } +export const PublicAssignOrganizationGroupRoleBody = Schema.Struct({ + "role_id": Schema.String.annotate({ "description": "Identifier of the role to assign." }) +}).annotate({ + "description": "Request payload for assigning a role to a group or user.", + "identifier": "PublicAssignOrganizationGroupRoleBody" +}) +export type Group = { + readonly "object": "group" + readonly "id": string + readonly "name": string + readonly "created_at": number + readonly "scim_managed": boolean } -export const ResponseLogProb = Schema.Struct({ - "token": Schema.String.annotate({ "description": "A possible text token." }), - "logprob": Schema.Number.annotate({ "description": "The log probability of this token.\n" }).check(Schema.isFinite()), - "top_logprobs": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "token": Schema.optionalKey(Schema.String.annotate({ "description": "A possible text token." })), - "logprob": Schema.optionalKey( - Schema.Number.annotate({ "description": "The log probability of this token." }).check(Schema.isFinite()) - ) - }) - ).annotate({ "description": "The log probabilities of up to 20 of the most likely tokens.\n" }) - ) +export const Group = Schema.Struct({ + "object": Schema.Literal("group").annotate({ "description": "Always `group`." }), + "id": Schema.String.annotate({ "description": "Identifier for the group." }), + "name": Schema.String.annotate({ "description": "Display name of the group." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the group was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "scim_managed": Schema.Boolean.annotate({ "description": "Whether the group is managed through SCIM." }) }).annotate({ - "description": - "A logprob is the logarithmic probability that the model assigns to producing \na particular token at a given position in the sequence. Less-negative (higher) \nlogprob values indicate greater model confidence in that token choice.\n" + "description": "Summary information about a group returned in role assignment responses.", + "identifier": "Group" }) -export type ResponseMCPCallArgumentsDeltaEvent = { - readonly "type": "response.mcp_call_arguments.delta" - readonly "output_index": number - readonly "item_id": string - readonly "delta": string - readonly "sequence_number": number +export type Role = { + readonly "object": "role" + readonly "id": string + readonly "name": string + readonly "description": string | null + readonly "permissions": ReadonlyArray + readonly "resource_type": string + readonly "predefined_role": boolean } -export const ResponseMCPCallArgumentsDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.mcp_call_arguments.delta").annotate({ - "description": "The type of the event. Always 'response.mcp_call_arguments.delta'." +export const Role = Schema.Struct({ + "object": Schema.Literal("role").annotate({ "description": "Always `role`." }), + "id": Schema.String.annotate({ "description": "Identifier for the role." }), + "name": Schema.String.annotate({ "description": "Unique name for the role." }), + "description": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "Optional description of the role." }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response's output array." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The unique identifier of the MCP tool call item being processed." + "permissions": Schema.Array(Schema.String).annotate({ "description": "Permissions granted by the role." }), + "resource_type": Schema.String.annotate({ + "description": "Resource type the role is bound to (for example `api.organization` or `api.project`)." }), - "delta": Schema.String.annotate({ - "description": "A JSON string containing the partial update to the arguments for the MCP tool call.\n" + "predefined_role": Schema.Boolean.annotate({ "description": "Whether the role is predefined and managed by OpenAI." }) +}).annotate({ + "description": "Details about a role that can be assigned through the public Roles API.", + "identifier": "Role" +}) +export type DeletedRoleAssignmentResource = { readonly "object": string; readonly "deleted": boolean } +export const DeletedRoleAssignmentResource = Schema.Struct({ + "object": Schema.String.annotate({ + "description": "Identifier for the deleted assignment, such as `group.role.deleted` or `user.role.deleted`." }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) + "deleted": Schema.Boolean.annotate({ "description": "Whether the assignment was removed." }) }).annotate({ - "title": "ResponseMCPCallArgumentsDeltaEvent", - "description": "Emitted when there is a delta (partial update) to the arguments of an MCP tool call.\n" + "description": "Confirmation payload returned after unassigning a role.", + "identifier": "DeletedRoleAssignmentResource" }) -export type ResponseMCPCallArgumentsDoneEvent = { - readonly "type": "response.mcp_call_arguments.done" - readonly "output_index": number - readonly "item_id": string - readonly "arguments": string - readonly "sequence_number": number +export type GroupUser = { readonly "id": string; readonly "name": string; readonly "email": string | null } +export const GroupUser = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.String.annotate({ "description": "The name of the user." }), + "email": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The email address of the user." }) +}).annotate({ + "description": "Represents an individual user returned when inspecting group membership.", + "identifier": "GroupUser" +}) +export type CreateGroupUserBody = { readonly "user_id": string } +export const CreateGroupUserBody = Schema.Struct({ + "user_id": Schema.String.annotate({ "description": "Identifier of the user to add to the group." }) +}).annotate({ "description": "Request payload for adding a user to a group.", "identifier": "CreateGroupUserBody" }) +export type GroupUserAssignment = { + readonly "object": "group.user" + readonly "user_id": string + readonly "group_id": string } -export const ResponseMCPCallArgumentsDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.mcp_call_arguments.done").annotate({ - "description": "The type of the event. Always 'response.mcp_call_arguments.done'." +export const GroupUserAssignment = Schema.Struct({ + "object": Schema.Literal("group.user").annotate({ "description": "Always `group.user`." }), + "user_id": Schema.String.annotate({ "description": "Identifier of the user that was added." }), + "group_id": Schema.String.annotate({ "description": "Identifier of the group the user was added to." }) +}).annotate({ + "description": "Confirmation payload returned after adding a user to a group.", + "identifier": "GroupUserAssignment" +}) +export type GroupMemberUser = { + readonly "id": string + readonly "name": string + readonly "email": string | null + readonly "picture": string | null + readonly "is_service_account": boolean | null + readonly "user_type": "user" | "tenant_user" +} +export const GroupMemberUser = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier for the user." }), + "name": Schema.String.annotate({ "description": "Display name of the user." }), + "email": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "Email address of the user, or `null` for users without an email." }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response's output array." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The unique identifier of the MCP tool call item being processed." + "picture": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "URL of the user's profile picture, if available." }), - "arguments": Schema.String.annotate({ - "description": "A JSON string containing the finalized arguments for the MCP tool call.\n" + "is_service_account": Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": "Whether the user is a service account." }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) + "user_type": Schema.Literals(["user", "tenant_user"]).annotate({ "description": "The type of user." }) }).annotate({ - "title": "ResponseMCPCallArgumentsDoneEvent", - "description": "Emitted when the arguments for an MCP tool call are finalized.\n" + "description": "Details about a user returned from an organization group membership lookup.", + "identifier": "GroupMemberUser" }) -export type ResponseMCPCallCompletedEvent = { - readonly "type": "response.mcp_call.completed" - readonly "item_id": string - readonly "output_index": number - readonly "sequence_number": number -} -export const ResponseMCPCallCompletedEvent = Schema.Struct({ - "type": Schema.Literal("response.mcp_call.completed").annotate({ - "description": "The type of the event. Always 'response.mcp_call.completed'." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that completed." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item that completed." }).check( - Schema.isInt() - ), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) +export type GroupUserDeletedResource = { readonly "object": "group.user.deleted"; readonly "deleted": boolean } +export const GroupUserDeletedResource = Schema.Struct({ + "object": Schema.Literal("group.user.deleted").annotate({ "description": "Always `group.user.deleted`." }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the group membership was removed." }) }).annotate({ - "title": "ResponseMCPCallCompletedEvent", - "description": "Emitted when an MCP tool call has completed successfully.\n" + "description": "Confirmation payload returned after removing a user from a group.", + "identifier": "GroupUserDeletedResource" }) -export type ResponseMCPCallFailedEvent = { - readonly "type": "response.mcp_call.failed" - readonly "item_id": string - readonly "output_index": number - readonly "sequence_number": number +export type Invite = { + readonly "object": "organization.invite" + readonly "id": string + readonly "email": string + readonly "role": "owner" | "reader" + readonly "status": "accepted" | "expired" | "pending" + readonly "created_at": number + readonly "expires_at"?: number | null + readonly "accepted_at"?: number | null + readonly "projects": ReadonlyArray<{ readonly "id": string; readonly "role": "member" | "owner" }> } -export const ResponseMCPCallFailedEvent = Schema.Struct({ - "type": Schema.Literal("response.mcp_call.failed").annotate({ - "description": "The type of the event. Always 'response.mcp_call.failed'." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that failed." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item that failed." }).check( - Schema.isInt() +export const Invite = Schema.Struct({ + "object": Schema.Literal("organization.invite").annotate({ + "description": "The object type, which is always `organization.invite`" + }), + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "email": Schema.String.annotate({ "description": "The email address of the individual to whom the invite was sent" }), + "role": Schema.Literals(["owner", "reader"]).annotate({ "description": "`owner` or `reader`" }), + "status": Schema.Literals(["accepted", "expired", "pending"]).annotate({ + "description": "`accepted`,`expired`, or `pending`" + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the invite was sent.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "expires_at": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ "description": "The Unix timestamp (in seconds) of when the invite expires." }) ), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + "accepted_at": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ "description": "The Unix timestamp (in seconds) of when the invite was accepted." }) + ), + "projects": Schema.Array( + Schema.Struct({ + "id": Schema.String.annotate({ "description": "Project's public ID" }), + "role": Schema.Literals(["member", "owner"]).annotate({ "description": "Project membership role" }) + }) + ).annotate({ "description": "The projects that were granted membership upon acceptance of the invite." }) +}).annotate({ "description": "Represents an individual `invite` to the organization.", "identifier": "Invite" }) +export type InviteRequest = { + readonly "email": string + readonly "role": "reader" | "owner" + readonly "projects"?: ReadonlyArray<{ readonly "id": string; readonly "role": "member" | "owner" }> +} +export const InviteRequest = Schema.Struct({ + "email": Schema.String.annotate({ "description": "Send an email to this address" }), + "role": Schema.Literals(["reader", "owner"]).annotate({ "description": "`owner` or `reader`" }), + "projects": Schema.optionalKey( + Schema.Array( + Schema.Struct({ + "id": Schema.String.annotate({ "description": "Project's public ID" }), + "role": Schema.Literals(["member", "owner"]).annotate({ "description": "Project membership role" }) + }) + ).annotate({ + "description": + "An array of projects to which membership is granted at the same time the org invite is accepted. If omitted, the user will be invited to the default project for compatibility with legacy behavior. If empty list is passed, the user will not be invited to any projects, including the default one." + }) ) -}).annotate({ "title": "ResponseMCPCallFailedEvent", "description": "Emitted when an MCP tool call has failed.\n" }) -export type ResponseMCPCallInProgressEvent = { - readonly "type": "response.mcp_call.in_progress" - readonly "sequence_number": number - readonly "output_index": number - readonly "item_id": string +}).annotate({ "identifier": "InviteRequest" }) +export type InviteDeleteResponse = { + readonly "object": "organization.invite.deleted" + readonly "id": string + readonly "deleted": boolean } -export const ResponseMCPCallInProgressEvent = Schema.Struct({ - "type": Schema.Literal("response.mcp_call.in_progress").annotate({ - "description": "The type of the event. Always 'response.mcp_call.in_progress'." +export const InviteDeleteResponse = Schema.Struct({ + "object": Schema.Literal("organization.invite.deleted").annotate({ + "description": "The object type, which is always `organization.invite.deleted`" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response's output array." - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "The unique identifier of the MCP tool call item being processed." - }) -}).annotate({ - "title": "ResponseMCPCallInProgressEvent", - "description": "Emitted when an MCP tool call is in progress.\n" -}) -export type ResponseMCPListToolsCompletedEvent = { - readonly "type": "response.mcp_list_tools.completed" - readonly "item_id": string - readonly "output_index": number - readonly "sequence_number": number + "id": Schema.String, + "deleted": Schema.Boolean +}).annotate({ "identifier": "InviteDeleteResponse" }) +export type PublicProjectResidency = + | "GLOBAL" + | "US_STORAGE_PROCESSING" + | "EU_STORAGE_PROCESSING" + | "JP_STORAGE" + | "KR_STORAGE" + | "CA_STORAGE" + | "SG_STORAGE" + | "IN_STORAGE" + | "AU_STORAGE" + | "GB_STORAGE" + | "AE_STORAGE" + | "AE_STORAGE_PROCESSING" +export const PublicProjectResidency = Schema.Literals([ + "GLOBAL", + "US_STORAGE_PROCESSING", + "EU_STORAGE_PROCESSING", + "JP_STORAGE", + "KR_STORAGE", + "CA_STORAGE", + "SG_STORAGE", + "IN_STORAGE", + "AU_STORAGE", + "GB_STORAGE", + "AE_STORAGE", + "AE_STORAGE_PROCESSING" +]).annotate({ "identifier": "PublicProjectResidency" }) +export type ProjectUpdateRequest = { + readonly "name"?: string | null + readonly "external_key_id"?: string | null + readonly "geography"?: string | null } -export const ResponseMCPListToolsCompletedEvent = Schema.Struct({ - "type": Schema.Literal("response.mcp_list_tools.completed").annotate({ - "description": "The type of the event. Always 'response.mcp_list_tools.completed'." - }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that produced this output." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item that was processed." }).check( - Schema.isInt() +export const ProjectUpdateRequest = Schema.Struct({ + "name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The updated name of the project, this name appears in reports." + }) ), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + "external_key_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "External key ID to associate with the project." + }) + ), + "geography": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "Geography for the project.\nDeprecated: use `residency` when creating a project to configure data residency. This field is retained for backward compatibility." + }) ) +}).annotate({ "identifier": "ProjectUpdateRequest" }) +export type ProjectApiKeyOwnerUser = { + readonly "id": string + readonly "email": string + readonly "name": string + readonly "created_at": number + readonly "role": string +} +export const ProjectApiKeyOwnerUser = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "email": Schema.String.annotate({ "description": "The email address of the user." }), + "name": Schema.String.annotate({ "description": "The name of the user." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the user was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "role": Schema.String.annotate({ "description": "The user's project role." }) +}).annotate({ "description": "The user that owns a project API key.", "identifier": "ProjectApiKeyOwnerUser" }) +export type ProjectApiKeyOwnerServiceAccount = { + readonly "id": string + readonly "name": string + readonly "created_at": number + readonly "role": string +} +export const ProjectApiKeyOwnerServiceAccount = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.String.annotate({ "description": "The name of the service account." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the service account was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "role": Schema.String.annotate({ "description": "The service account's project role." }) }).annotate({ - "title": "ResponseMCPListToolsCompletedEvent", - "description": "Emitted when the list of available MCP tools has been successfully retrieved.\n" + "description": "The service account that owns a project API key.", + "identifier": "ProjectApiKeyOwnerServiceAccount" }) -export type ResponseMCPListToolsFailedEvent = { - readonly "type": "response.mcp_list_tools.failed" - readonly "item_id": string - readonly "output_index": number - readonly "sequence_number": number +export type ProjectApiKeyDeleteResponse = { + readonly "object": "organization.project.api_key.deleted" + readonly "id": string + readonly "deleted": boolean } -export const ResponseMCPListToolsFailedEvent = Schema.Struct({ - "type": Schema.Literal("response.mcp_list_tools.failed").annotate({ - "description": "The type of the event. Always 'response.mcp_list_tools.failed'." +export const ProjectApiKeyDeleteResponse = Schema.Struct({ + "object": Schema.Literal("organization.project.api_key.deleted"), + "id": Schema.String, + "deleted": Schema.Boolean +}).annotate({ "identifier": "ProjectApiKeyDeleteResponse" }) +export type OrganizationProjectCertificate = { + readonly "object": "organization.project.certificate" + readonly "id": string + readonly "name": string | null + readonly "created_at": number + readonly "certificate_details": { readonly "valid_at"?: number; readonly "expires_at"?: number } + readonly "active": boolean +} +export const OrganizationProjectCertificate = Schema.Struct({ + "object": Schema.Literal("organization.project.certificate").annotate({ + "description": "The object type, which is always `organization.project.certificate`." }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that failed." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item that failed." }).check( - Schema.isInt() - ), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the certificate." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate was uploaded.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "certificate_details": Schema.Struct({ + "valid_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate becomes valid.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "expires_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the certificate expires.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ) + }), + "active": Schema.Boolean.annotate({ + "description": "Whether the certificate is currently active at the project level." + }) }).annotate({ - "title": "ResponseMCPListToolsFailedEvent", - "description": "Emitted when the attempt to list available MCP tools has failed.\n" + "description": "Represents an individual certificate configured at the project level.", + "identifier": "OrganizationProjectCertificate" }) -export type ResponseMCPListToolsInProgressEvent = { - readonly "type": "response.mcp_list_tools.in_progress" - readonly "item_id": string - readonly "output_index": number - readonly "sequence_number": number +export type ProjectDataRetention = { + readonly "object": "project.data_retention" + readonly "type": + | "organization_default" + | "none" + | "zero_data_retention" + | "modified_abuse_monitoring" + | "enhanced_zero_data_retention" + | "enhanced_modified_abuse_monitoring" } -export const ResponseMCPListToolsInProgressEvent = Schema.Struct({ - "type": Schema.Literal("response.mcp_list_tools.in_progress").annotate({ - "description": "The type of the event. Always 'response.mcp_list_tools.in_progress'." +export const ProjectDataRetention = Schema.Struct({ + "object": Schema.Literal("project.data_retention").annotate({ + "description": "The object type, which is always `project.data_retention`." }), - "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that is being processed." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item that is being processed." }) - .check(Schema.isInt()), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) + "type": Schema.Literals([ + "organization_default", + "none", + "zero_data_retention", + "modified_abuse_monitoring", + "enhanced_zero_data_retention", + "enhanced_modified_abuse_monitoring" + ]).annotate({ "description": "The configured project data retention type." }) }).annotate({ - "title": "ResponseMCPListToolsInProgressEvent", - "description": "Emitted when the system is in the process of retrieving the list of available MCP tools.\n" + "description": "Represents a project's data retention control setting.", + "identifier": "ProjectDataRetention" }) -export type ResponseModalities = ReadonlyArray<"text" | "audio"> | null -export const ResponseModalities = Schema.Union([ - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": - "Output types that you would like the model to generate.\nMost models are capable of generating text, which is the default:\n\n`[\"text\"]`\n\nThe `gpt-4o-audio-preview` model can also be used to\n[generate audio](/docs/guides/audio). To request that this model generate\nboth text and audio responses, you can use:\n\n`[\"text\", \"audio\"]`\n" - }), - Schema.Null -]) -export type ResponseOutputTextAnnotationAddedEvent = { - readonly "type": "response.output_text.annotation.added" - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "annotation_index": number - readonly "sequence_number": number - readonly "annotation": {} -} -export const ResponseOutputTextAnnotationAddedEvent = Schema.Struct({ - "type": Schema.Literal("response.output_text.annotation.added").annotate({ - "description": "The type of the event. Always 'response.output_text.annotation.added'." - }), - "item_id": Schema.String.annotate({ - "description": "The unique identifier of the item to which the annotation is being added." - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item in the response's output array." - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ "description": "The index of the content part within the output item." }) - .check(Schema.isInt()), - "annotation_index": Schema.Number.annotate({ "description": "The index of the annotation within the content part." }) - .check(Schema.isInt()), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ), - "annotation": Schema.Struct({}).annotate({ - "description": "The annotation object being added. (See annotation schema for details.)" - }) +export type UpdateProjectDataRetentionBody = { + readonly "retention_type": + | "organization_default" + | "none" + | "zero_data_retention" + | "modified_abuse_monitoring" + | "enhanced_zero_data_retention" + | "enhanced_modified_abuse_monitoring" +} +export const UpdateProjectDataRetentionBody = Schema.Struct({ + "retention_type": Schema.Literals([ + "organization_default", + "none", + "zero_data_retention", + "modified_abuse_monitoring", + "enhanced_zero_data_retention", + "enhanced_modified_abuse_monitoring" + ]).annotate({ "description": "The desired project data retention type." }) }).annotate({ - "title": "ResponseOutputTextAnnotationAddedEvent", - "description": "Emitted when an annotation is added to output text content.\n" + "description": "Parameters for updating project data retention controls.", + "identifier": "UpdateProjectDataRetentionBody" }) -export type ResponsePromptVariables = {} | null -export const ResponsePromptVariables = Schema.Union([ - Schema.Struct({}).annotate({ - "title": "Prompt Variables", - "description": - "Optional map of values to substitute in for variables in your\nprompt. The substitution values can either be strings, or other\nResponse input types like images or files.\n" - }), - Schema.Null -]) -export type ResponseReasoningSummaryPartAddedEvent = { - readonly "type": "response.reasoning_summary_part.added" - readonly "item_id": string - readonly "output_index": number - readonly "summary_index": number - readonly "sequence_number": number - readonly "part": { readonly "type": "summary_text"; readonly "text": string } +export type ProjectGroup = { + readonly "object": "project.group" + readonly "project_id": string + readonly "group_id": string + readonly "group_name": string + readonly "group_type": "group" | "tenant_group" + readonly "created_at": number } -export const ResponseReasoningSummaryPartAddedEvent = Schema.Struct({ - "type": Schema.Literal("response.reasoning_summary_part.added").annotate({ - "description": "The type of the event. Always `response.reasoning_summary_part.added`.\n" - }), - "item_id": Schema.String.annotate({ "description": "The ID of the item this summary part is associated with.\n" }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item this summary part is associated with.\n" - }).check(Schema.isInt()), - "summary_index": Schema.Number.annotate({ - "description": "The index of the summary part within the reasoning summary.\n" - }).check(Schema.isInt()), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() - ), - "part": Schema.Struct({ - "type": Schema.Literal("summary_text").annotate({ - "description": "The type of the summary part. Always `summary_text`." - }), - "text": Schema.String.annotate({ "description": "The text of the summary part." }) - }).annotate({ "description": "The summary part that was added.\n" }) -}).annotate({ "description": "Emitted when a new reasoning summary part is added." }) -export type ResponseReasoningSummaryPartDoneEvent = { - readonly "type": "response.reasoning_summary_part.done" - readonly "item_id": string - readonly "output_index": number - readonly "summary_index": number - readonly "sequence_number": number - readonly "part": { readonly "type": "summary_text"; readonly "text": string } -} -export const ResponseReasoningSummaryPartDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.reasoning_summary_part.done").annotate({ - "description": "The type of the event. Always `response.reasoning_summary_part.done`.\n" - }), - "item_id": Schema.String.annotate({ "description": "The ID of the item this summary part is associated with.\n" }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item this summary part is associated with.\n" - }).check(Schema.isInt()), - "summary_index": Schema.Number.annotate({ - "description": "The index of the summary part within the reasoning summary.\n" - }).check(Schema.isInt()), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() - ), - "part": Schema.Struct({ - "type": Schema.Literal("summary_text").annotate({ - "description": "The type of the summary part. Always `summary_text`." - }), - "text": Schema.String.annotate({ "description": "The text of the summary part." }) - }).annotate({ "description": "The completed summary part.\n" }) -}).annotate({ "description": "Emitted when a reasoning summary part is completed." }) -export type ResponseReasoningSummaryTextDeltaEvent = { - readonly "type": "response.reasoning_summary_text.delta" - readonly "item_id": string - readonly "output_index": number - readonly "summary_index": number - readonly "delta": string - readonly "sequence_number": number +export const ProjectGroup = Schema.Struct({ + "object": Schema.Literal("project.group").annotate({ "description": "Always `project.group`." }), + "project_id": Schema.String.annotate({ "description": "Identifier of the project." }), + "group_id": Schema.String.annotate({ "description": "Identifier of the group that has access to the project." }), + "group_name": Schema.String.annotate({ "description": "Display name of the group." }), + "group_type": Schema.Literals(["group", "tenant_group"]).annotate({ "description": "The type of the group." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the group was granted project access.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ "description": "Details about a group's membership in a project.", "identifier": "ProjectGroup" }) +export type InviteProjectGroupBody = { readonly "group_id": string; readonly "role": string } +export const InviteProjectGroupBody = Schema.Struct({ + "group_id": Schema.String.annotate({ "description": "Identifier of the group to add to the project." }), + "role": Schema.String.annotate({ "description": "Identifier of the project role to grant to the group." }) +}).annotate({ + "description": "Request payload for granting a group access to a project.", + "identifier": "InviteProjectGroupBody" +}) +export type ProjectGroupDeletedResource = { readonly "object": "project.group.deleted"; readonly "deleted": boolean } +export const ProjectGroupDeletedResource = Schema.Struct({ + "object": Schema.Literal("project.group.deleted").annotate({ "description": "Always `project.group.deleted`." }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the group membership in the project was removed." }) +}).annotate({ + "description": "Confirmation payload returned after removing a group from a project.", + "identifier": "ProjectGroupDeletedResource" +}) +export type HostedToolPermission = { readonly "enabled": boolean } +export const HostedToolPermission = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Whether the hosted tool is enabled for the project." }) +}).annotate({ + "description": "Permission state for a single hosted tool on a project.", + "identifier": "HostedToolPermission" +}) +export type HostedToolPermissionUpdate = { readonly "enabled": boolean } +export const HostedToolPermissionUpdate = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Whether to enable the hosted tool for the project." }) +}).annotate({ "identifier": "HostedToolPermissionUpdate" }) +export type ProjectModelPermissions = { + readonly "object": "project.model_permissions" + readonly "mode": "allow_list" | "deny_list" + readonly "model_ids": ReadonlyArray } -export const ResponseReasoningSummaryTextDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.reasoning_summary_text.delta").annotate({ - "description": "The type of the event. Always `response.reasoning_summary_text.delta`.\n" +export const ProjectModelPermissions = Schema.Struct({ + "object": Schema.Literal("project.model_permissions").annotate({ + "description": "The object type, which is always `project.model_permissions`." }), - "item_id": Schema.String.annotate({ - "description": "The ID of the item this summary text delta is associated with.\n" + "mode": Schema.Literals(["allow_list", "deny_list"]).annotate({ + "description": "Whether the project uses an allowlist or a denylist." }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item this summary text delta is associated with.\n" - }).check(Schema.isInt()), - "summary_index": Schema.Number.annotate({ - "description": "The index of the summary part within the reasoning summary.\n" - }).check(Schema.isInt()), - "delta": Schema.String.annotate({ "description": "The text delta that was added to the summary.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() - ) -}).annotate({ "description": "Emitted when a delta is added to a reasoning summary text." }) -export type ResponseReasoningSummaryTextDoneEvent = { - readonly "type": "response.reasoning_summary_text.done" - readonly "item_id": string - readonly "output_index": number - readonly "summary_index": number - readonly "text": string - readonly "sequence_number": number + "model_ids": Schema.Array(Schema.String).annotate({ + "description": "The model IDs included in the model permissions policy." + }) +}).annotate({ + "description": "Represents the model allowlist or denylist policy for a project.", + "identifier": "ProjectModelPermissions" +}) +export type ProjectModelPermissionsUpdateRequest = { + readonly "mode": "allow_list" | "deny_list" + readonly "model_ids": ReadonlyArray } -export const ResponseReasoningSummaryTextDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.reasoning_summary_text.done").annotate({ - "description": "The type of the event. Always `response.reasoning_summary_text.done`.\n" +export const ProjectModelPermissionsUpdateRequest = Schema.Struct({ + "mode": Schema.Literals(["allow_list", "deny_list"]).annotate({ + "description": "The model permissions mode to apply." }), - "item_id": Schema.String.annotate({ "description": "The ID of the item this summary text is associated with.\n" }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item this summary text is associated with.\n" - }).check(Schema.isInt()), - "summary_index": Schema.Number.annotate({ - "description": "The index of the summary part within the reasoning summary.\n" - }).check(Schema.isInt()), - "text": Schema.String.annotate({ "description": "The full text of the completed reasoning summary.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() - ) -}).annotate({ "description": "Emitted when a reasoning summary text is completed." }) -export type ResponseReasoningTextDeltaEvent = { - readonly "type": "response.reasoning_text.delta" - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "delta": string - readonly "sequence_number": number + "model_ids": Schema.Array(Schema.String).annotate({ + "description": "The model IDs included in this permissions policy." + }) +}).annotate({ "identifier": "ProjectModelPermissionsUpdateRequest" }) +export type ProjectModelPermissionsDeleteResponse = { + readonly "object": "project.model_permissions.deleted" + readonly "deleted": boolean } -export const ResponseReasoningTextDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.reasoning_text.delta").annotate({ - "description": "The type of the event. Always `response.reasoning_text.delta`.\n" +export const ProjectModelPermissionsDeleteResponse = Schema.Struct({ + "object": Schema.Literal("project.model_permissions.deleted").annotate({ + "description": "The object type, which is always `project.model_permissions.deleted`." }), - "item_id": Schema.String.annotate({ - "description": "The ID of the item this reasoning text delta is associated with.\n" + "deleted": Schema.Boolean.annotate({ "description": "Whether the project model permissions were deleted." }) +}).annotate({ + "description": "Confirmation payload returned after deleting project model permissions.", + "identifier": "ProjectModelPermissionsDeleteResponse" +}) +export type ProjectRateLimit = { + readonly "object": "project.rate_limit" + readonly "id": string + readonly "model": string + readonly "max_requests_per_1_minute": number + readonly "max_tokens_per_1_minute": number + readonly "max_images_per_1_minute"?: number + readonly "max_audio_megabytes_per_1_minute"?: number + readonly "max_requests_per_1_day"?: number + readonly "batch_1_day_max_input_tokens"?: number +} +export const ProjectRateLimit = Schema.Struct({ + "object": Schema.Literal("project.rate_limit").annotate({ + "description": "The object type, which is always `project.rate_limit`" }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item this reasoning text delta is associated with.\n" - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ - "description": "The index of the reasoning content part this delta is associated with.\n" - }).check(Schema.isInt()), - "delta": Schema.String.annotate({ "description": "The text delta that was added to the reasoning content.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "model": Schema.String.annotate({ "description": "The model this rate limit applies to." }), + "max_requests_per_1_minute": Schema.Number.annotate({ "description": "The maximum requests per minute." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "max_tokens_per_1_minute": Schema.Number.annotate({ "description": "The maximum tokens per minute." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "max_images_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum images per minute. Only present for relevant models." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "max_audio_megabytes_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum audio megabytes per minute. Only present for relevant models." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "max_requests_per_1_day": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum requests per day. Only present for relevant models." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "batch_1_day_max_input_tokens": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum batch input tokens per day. Only present for relevant models." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ) -}).annotate({ "description": "Emitted when a delta is added to a reasoning text." }) -export type ResponseReasoningTextDoneEvent = { - readonly "type": "response.reasoning_text.done" - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "text": string - readonly "sequence_number": number +}).annotate({ "description": "Represents a project rate limit config.", "identifier": "ProjectRateLimit" }) +export type ProjectRateLimitUpdateRequest = { + readonly "max_requests_per_1_minute"?: number + readonly "max_tokens_per_1_minute"?: number + readonly "max_images_per_1_minute"?: number + readonly "max_audio_megabytes_per_1_minute"?: number + readonly "max_requests_per_1_day"?: number + readonly "batch_1_day_max_input_tokens"?: number } -export const ResponseReasoningTextDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.reasoning_text.done").annotate({ - "description": "The type of the event. Always `response.reasoning_text.done`.\n" - }), - "item_id": Schema.String.annotate({ "description": "The ID of the item this reasoning text is associated with.\n" }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item this reasoning text is associated with.\n" - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ "description": "The index of the reasoning content part.\n" }).check( - Schema.isInt() +export const ProjectRateLimitUpdateRequest = Schema.Struct({ + "max_requests_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum requests per minute." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ), - "text": Schema.String.annotate({ "description": "The full text of the completed reasoning content.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() + "max_tokens_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum tokens per minute." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "max_images_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum images per minute. Only relevant for certain models." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "max_audio_megabytes_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum audio megabytes per minute. Only relevant for certain models." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "max_requests_per_1_day": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum requests per day. Only relevant for certain models." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "batch_1_day_max_input_tokens": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum batch input tokens per day. Only relevant for certain models." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ) -}).annotate({ "description": "Emitted when a reasoning text is completed." }) -export type ResponseRefusalDeltaEvent = { - readonly "type": "response.refusal.delta" - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "delta": string - readonly "sequence_number": number +}).annotate({ "identifier": "ProjectRateLimitUpdateRequest" }) +export type ProjectServiceAccount = { + readonly "object": "organization.project.service_account" + readonly "id": string + readonly "name": string + readonly "role": "owner" | "member" | "none" + readonly "created_at": number } -export const ResponseRefusalDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.refusal.delta").annotate({ - "description": "The type of the event. Always `response.refusal.delta`.\n" - }), - "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the refusal text is added to.\n" +export const ProjectServiceAccount = Schema.Struct({ + "object": Schema.Literal("organization.project.service_account").annotate({ + "description": "The object type, which is always `organization.project.service_account`" }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the refusal text is added to.\n" - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part that the refusal text is added to.\n" - }).check(Schema.isInt()), - "delta": Schema.String.annotate({ "description": "The refusal text that is added.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.String.annotate({ "description": "The name of the service account" }), + "role": Schema.Literals(["owner", "member", "none"]).annotate({ "description": "`owner`, `member`, or `none`" }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the service account was created", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Represents an individual service account in a project.", + "identifier": "ProjectServiceAccount" +}) +export type ProjectServiceAccountCreateRequest = { + readonly "name": string + readonly "create_service_account_only"?: boolean | null + readonly "expires_in_seconds"?: number | null +} +export const ProjectServiceAccountCreateRequest = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the service account being created." }), + "create_service_account_only": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ "description": "Create the service account without default roles or an API key." }), + Schema.Null + ]) + ), + "expires_in_seconds": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(31536000).annotate({ "expected": "a value less than or equal to 31536000" })), + Schema.Null + ]).annotate({ + "description": + "Number of seconds until the initial API key expires. If omitted or null, the key does not expire unless the effective organization or project policy requires an expiration. When a policy sets a maximum lifetime, this value must be provided and must not exceed that limit. A non-null value cannot be used when `create_service_account_only` is true." + }) ) -}).annotate({ "description": "Emitted when there is a partial refusal text." }) -export type ResponseRefusalDoneEvent = { - readonly "type": "response.refusal.done" - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "refusal": string - readonly "sequence_number": number +}).annotate({ "identifier": "ProjectServiceAccountCreateRequest" }) +export type ProjectServiceAccountApiKey = { + readonly "object": "organization.project.service_account.api_key" + readonly "value": string + readonly "name": string + readonly "created_at": number + readonly "expires_at"?: number | null + readonly "id": string } -export const ResponseRefusalDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.refusal.done").annotate({ - "description": "The type of the event. Always `response.refusal.done`.\n" - }), - "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the refusal text is finalized.\n" +export const ProjectServiceAccountApiKey = Schema.Struct({ + "object": Schema.Literal("organization.project.service_account.api_key").annotate({ + "description": "The object type, which is always `organization.project.service_account.api_key`" }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the refusal text is finalized.\n" - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part that the refusal text is finalized.\n" - }).check(Schema.isInt()), - "refusal": Schema.String.annotate({ "description": "The refusal text that is finalized.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() + "value": Schema.String, + "name": Schema.String, + "created_at": Schema.Number.annotate({ "format": "unixtime" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "expires_at": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ + "description": "The Unix timestamp (in seconds) when the API key expires, or null if it does not expire." + }) + ), + "id": Schema.String +}).annotate({ "identifier": "ProjectServiceAccountApiKey" }) +export type UpdateProjectServiceAccountBody = { readonly "name"?: string; readonly "role"?: "member" | "owner" } +export const UpdateProjectServiceAccountBody = Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The updated service account name." })), + "role": Schema.optionalKey( + Schema.Literals(["member", "owner"]).annotate({ "description": "The updated service account role." }) ) -}).annotate({ "description": "Emitted when refusal text is finalized." }) -export type ResponseStreamOptions = { readonly "include_obfuscation"?: boolean } | null -export const ResponseStreamOptions = Schema.Union([ - Schema.Struct({ - "include_obfuscation": Schema.optionalKey(Schema.Boolean.annotate({ - "description": - "When true, stream obfuscation will be enabled. Stream obfuscation adds\nrandom characters to an `obfuscation` field on streaming delta events to\nnormalize payload sizes as a mitigation to certain side-channel attacks.\nThese obfuscation fields are included by default, but add a small amount\nof overhead to the data stream. You can set `include_obfuscation` to\nfalse to optimize for bandwidth if you trust the network links between\nyour application and the OpenAI API.\n" - })) - }).annotate({ "description": "Options for streaming responses. Only set this when you set `stream: true`.\n" }), - Schema.Null -]) -export type ResponseUsage = { - readonly "input_tokens": number - readonly "input_tokens_details": { readonly "cached_tokens": number } - readonly "output_tokens": number - readonly "output_tokens_details": { readonly "reasoning_tokens": number } - readonly "total_tokens": number -} -export const ResponseUsage = Schema.Struct({ - "input_tokens": Schema.Number.annotate({ "description": "The number of input tokens." }).check(Schema.isInt()), - "input_tokens_details": Schema.Struct({ - "cached_tokens": Schema.Number.annotate({ - "description": - "The number of tokens that were retrieved from the cache. \n[More on prompt caching](/docs/guides/prompt-caching).\n" - }).check(Schema.isInt()) - }).annotate({ "description": "A detailed breakdown of the input tokens." }), - "output_tokens": Schema.Number.annotate({ "description": "The number of output tokens." }).check(Schema.isInt()), - "output_tokens_details": Schema.Struct({ - "reasoning_tokens": Schema.Number.annotate({ "description": "The number of reasoning tokens." }).check( - Schema.isInt() - ) - }).annotate({ "description": "A detailed breakdown of the output tokens." }), - "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check(Schema.isInt()) }).annotate({ - "description": - "Represents token usage details including input tokens, output tokens,\na breakdown of output tokens, and the total tokens used.\n" + "description": "Parameters for updating a project service account.", + "identifier": "UpdateProjectServiceAccountBody" }) -export type ResponseWebSearchCallCompletedEvent = { - readonly "type": "response.web_search_call.completed" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number +export type ProjectServiceAccountDeleteResponse = { + readonly "object": "organization.project.service_account.deleted" + readonly "id": string + readonly "deleted": boolean } -export const ResponseWebSearchCallCompletedEvent = Schema.Struct({ - "type": Schema.Literal("response.web_search_call.completed").annotate({ - "description": "The type of the event. Always `response.web_search_call.completed`.\n" - }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the web search call is associated with.\n" - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "Unique ID for the output item associated with the web search call.\n" - }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of the web search call being processed." - }).check(Schema.isInt()) -}).annotate({ "description": "Emitted when a web search call is completed." }) -export type ResponseWebSearchCallInProgressEvent = { - readonly "type": "response.web_search_call.in_progress" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number +export const ProjectServiceAccountDeleteResponse = Schema.Struct({ + "object": Schema.Literal("organization.project.service_account.deleted"), + "id": Schema.String, + "deleted": Schema.Boolean +}).annotate({ "identifier": "ProjectServiceAccountDeleteResponse" }) +export type SpendAlertNotificationChannel = { + readonly "type": "email" + readonly "recipients": ReadonlyArray + readonly "subject_prefix"?: string | null } -export const ResponseWebSearchCallInProgressEvent = Schema.Struct({ - "type": Schema.Literal("response.web_search_call.in_progress").annotate({ - "description": "The type of the event. Always `response.web_search_call.in_progress`.\n" +export const SpendAlertNotificationChannel = Schema.Struct({ + "type": Schema.Literal("email").annotate({ + "description": "The notification channel type. Currently only `email` is supported." }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the web search call is associated with.\n" - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "Unique ID for the output item associated with the web search call.\n" + "recipients": Schema.Array(Schema.String).annotate({ + "description": "Email addresses that receive the spend alert notification." }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of the web search call being processed." - }).check(Schema.isInt()) -}).annotate({ "description": "Emitted when a web search call is initiated." }) -export type ResponseWebSearchCallSearchingEvent = { - readonly "type": "response.web_search_call.searching" - readonly "output_index": number - readonly "item_id": string - readonly "sequence_number": number + "subject_prefix": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Optional subject prefix for alert emails." }) + ) +}).annotate({ + "description": "Email notification settings for a spend alert.", + "identifier": "SpendAlertNotificationChannel" +}) +export type ProjectSpendAlertDeletedResource = { + readonly "id": string + readonly "object": "project.spend_alert.deleted" + readonly "deleted": boolean } -export const ResponseWebSearchCallSearchingEvent = Schema.Struct({ - "type": Schema.Literal("response.web_search_call.searching").annotate({ - "description": "The type of the event. Always `response.web_search_call.searching`.\n" +export const ProjectSpendAlertDeletedResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The deleted spend alert ID." }), + "object": Schema.Literal("project.spend_alert.deleted").annotate({ + "description": "Always `project.spend_alert.deleted`." }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the web search call is associated with.\n" - }).check(Schema.isInt()), - "item_id": Schema.String.annotate({ - "description": "Unique ID for the output item associated with the web search call.\n" + "deleted": Schema.Boolean.annotate({ "description": "Whether the spend alert was deleted." }) +}).annotate({ + "description": "Confirmation payload returned after deleting a project spend alert.", + "identifier": "ProjectSpendAlertDeletedResource" +}) +export type ProjectUser = { + readonly "object": "organization.project.user" + readonly "id": string + readonly "name"?: string | null + readonly "email"?: string | null + readonly "role": string + readonly "added_at": number +} +export const ProjectUser = Schema.Struct({ + "object": Schema.Literal("organization.project.user").annotate({ + "description": "The object type, which is always `organization.project.user`" }), - "sequence_number": Schema.Number.annotate({ - "description": "The sequence number of the web search call being processed." - }).check(Schema.isInt()) -}).annotate({ "description": "Emitted when a web search call is executing." }) -export type Role = { - readonly "object": "role" + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the user" }) + ), + "email": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The email address of the user" }) + ), + "role": Schema.String.annotate({ "description": "`owner` or `member`" }), + "added_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the project was added.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ "description": "Represents an individual user in a project.", "identifier": "ProjectUser" }) +export type ProjectUserCreateRequest = { + readonly "user_id"?: string | null + readonly "email"?: string | null + readonly "role": string +} +export const ProjectUserCreateRequest = Schema.Struct({ + "user_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The ID of the user." }) + ), + "email": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Email of the user to add." }) + ), + "role": Schema.String.annotate({ "description": "`owner` or `member`" }) +}).annotate({ "identifier": "ProjectUserCreateRequest" }) +export type ProjectUserUpdateRequest = { readonly "role"?: string | null } +export const ProjectUserUpdateRequest = Schema.Struct({ + "role": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "`owner` or `member`" }) + ) +}).annotate({ "identifier": "ProjectUserUpdateRequest" }) +export type ProjectUserDeleteResponse = { + readonly "object": "organization.project.user.deleted" readonly "id": string - readonly "name": string - readonly "description": string | null + readonly "deleted": boolean +} +export const ProjectUserDeleteResponse = Schema.Struct({ + "object": Schema.Literal("organization.project.user.deleted"), + "id": Schema.String, + "deleted": Schema.Boolean +}).annotate({ "identifier": "ProjectUserDeleteResponse" }) +export type PublicCreateOrganizationRoleBody = { + readonly "role_name": string readonly "permissions": ReadonlyArray - readonly "resource_type": string - readonly "predefined_role": boolean + readonly "description"?: string | null } -export const Role = Schema.Struct({ - "object": Schema.Literal("role").annotate({ "description": "Always `role`." }), - "id": Schema.String.annotate({ "description": "Identifier for the role." }), - "name": Schema.String.annotate({ "description": "Unique name for the role." }), - "description": Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "Optional description of the role." - }), - "permissions": Schema.Array(Schema.String).annotate({ "description": "Permissions granted by the role." }), - "resource_type": Schema.String.annotate({ - "description": "Resource type the role is bound to (for example `api.organization` or `api.project`)." - }), - "predefined_role": Schema.Boolean.annotate({ "description": "Whether the role is predefined and managed by OpenAI." }) -}).annotate({ "description": "Details about a role that can be assigned through the public Roles API." }) +export const PublicCreateOrganizationRoleBody = Schema.Struct({ + "role_name": Schema.String.annotate({ "description": "Unique name for the role." }), + "permissions": Schema.Array(Schema.String).annotate({ "description": "Permissions to grant to the role." }), + "description": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Optional description of the role." }) + ) +}).annotate({ + "description": "Request payload for creating a custom role.", + "identifier": "PublicCreateOrganizationRoleBody" +}) +export type PublicUpdateOrganizationRoleBody = { + readonly "permissions"?: ReadonlyArray | null + readonly "description"?: string | null + readonly "role_name"?: string | null +} +export const PublicUpdateOrganizationRoleBody = Schema.Struct({ + "permissions": Schema.optionalKey( + Schema.Union([Schema.Array(Schema.String), Schema.Null]).annotate({ + "description": "Updated set of permissions for the role." + }) + ), + "description": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "New description for the role." }) + ), + "role_name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "New name for the role." }) + ) +}).annotate({ + "description": "Request payload for updating an existing role.", + "identifier": "PublicUpdateOrganizationRoleBody" +}) export type RoleDeletedResource = { readonly "object": "role.deleted" readonly "id": string @@ -6650,458 +6874,391 @@ export const RoleDeletedResource = Schema.Struct({ "object": Schema.Literal("role.deleted").annotate({ "description": "Always `role.deleted`." }), "id": Schema.String.annotate({ "description": "Identifier of the deleted role." }), "deleted": Schema.Boolean.annotate({ "description": "Whether the role was deleted." }) -}).annotate({ "description": "Confirmation payload returned after deleting a role." }) -export type RunCompletionUsage = { - readonly "completion_tokens": number - readonly "prompt_tokens": number - readonly "total_tokens": number -} | null -export const RunCompletionUsage = Schema.Union([ - Schema.Struct({ - "completion_tokens": Schema.Number.annotate({ - "description": "Number of completion tokens used over the course of the run." - }).check(Schema.isInt()), - "prompt_tokens": Schema.Number.annotate({ - "description": "Number of prompt tokens used over the course of the run." - }).check(Schema.isInt()), - "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (prompt + completion)." }) - .check(Schema.isInt()) - }).annotate({ - "description": - "Usage statistics related to the run. This value will be `null` if the run is not in a terminal state (i.e. `in_progress`, `queued`, etc.)." - }), - Schema.Null -]) -export type RunGraderResponse = { - readonly "reward": number - readonly "metadata": { - readonly "name": string - readonly "type": string - readonly "errors": { - readonly "formula_parse_error": boolean - readonly "sample_parse_error": boolean - readonly "truncated_observation_error": boolean - readonly "unresponsive_reward_error": boolean - readonly "invalid_variable_error": boolean - readonly "other_error": boolean - readonly "python_grader_server_error": boolean - readonly "python_grader_server_error_type": string | null - readonly "python_grader_runtime_error": boolean - readonly "python_grader_runtime_error_details": string | null - readonly "model_grader_server_error": boolean - readonly "model_grader_refusal_error": boolean - readonly "model_grader_parse_error": boolean - readonly "model_grader_server_error_details": string | null - } - readonly "execution_time": number - readonly "scores": {} - readonly "token_usage": number | null - readonly "sampled_model_name": string | null - } - readonly "sub_rewards": {} - readonly "model_grader_token_usage_per_model": {} -} -export const RunGraderResponse = Schema.Struct({ - "reward": Schema.Number.check(Schema.isFinite()), - "metadata": Schema.Struct({ - "name": Schema.String, - "type": Schema.String, - "errors": Schema.Struct({ - "formula_parse_error": Schema.Boolean, - "sample_parse_error": Schema.Boolean, - "truncated_observation_error": Schema.Boolean, - "unresponsive_reward_error": Schema.Boolean, - "invalid_variable_error": Schema.Boolean, - "other_error": Schema.Boolean, - "python_grader_server_error": Schema.Boolean, - "python_grader_server_error_type": Schema.Union([Schema.String, Schema.Null]), - "python_grader_runtime_error": Schema.Boolean, - "python_grader_runtime_error_details": Schema.Union([Schema.String, Schema.Null]), - "model_grader_server_error": Schema.Boolean, - "model_grader_refusal_error": Schema.Boolean, - "model_grader_parse_error": Schema.Boolean, - "model_grader_server_error_details": Schema.Union([Schema.String, Schema.Null]) - }), - "execution_time": Schema.Number.check(Schema.isFinite()), - "scores": Schema.Struct({}), - "token_usage": Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Null]), - "sampled_model_name": Schema.Union([Schema.String, Schema.Null]) - }), - "sub_rewards": Schema.Struct({}), - "model_grader_token_usage_per_model": Schema.Struct({}) +}).annotate({ + "description": "Confirmation payload returned after deleting a role.", + "identifier": "RoleDeletedResource" }) -export type RunStepCompletionUsage = { - readonly "completion_tokens": number - readonly "prompt_tokens": number - readonly "total_tokens": number -} | null -export const RunStepCompletionUsage = Schema.Union([ - Schema.Struct({ - "completion_tokens": Schema.Number.annotate({ - "description": "Number of completion tokens used over the course of the run step." - }).check(Schema.isInt()), - "prompt_tokens": Schema.Number.annotate({ - "description": "Number of prompt tokens used over the course of the run step." - }).check(Schema.isInt()), - "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (prompt + completion)." }) - .check(Schema.isInt()) - }).annotate({ - "description": - "Usage statistics related to the run step. This value will be `null` while the run step's status is `in_progress`." - }), - Schema.Null -]) -export type RunStepDeltaStepDetailsToolCallsCodeObject = { - readonly "index": number - readonly "id"?: string - readonly "type": "code_interpreter" - readonly "code_interpreter"?: { - readonly "input"?: string - readonly "outputs"?: ReadonlyArray< - { readonly "index": number; readonly "type": "logs"; readonly "logs"?: string } | { - readonly "index": number - readonly "type": "image" - readonly "image"?: { readonly "file_id"?: string } - } - > - } +export type OrganizationSpendAlertDeletedResource = { + readonly "id": string + readonly "object": "organization.spend_alert.deleted" + readonly "deleted": boolean } -export const RunStepDeltaStepDetailsToolCallsCodeObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the tool call in the tool calls array." }).check( - Schema.isInt() - ), - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the tool call." })), - "type": Schema.Literal("code_interpreter").annotate({ - "description": "The type of tool call. This is always going to be `code_interpreter` for this type of tool call." +export const OrganizationSpendAlertDeletedResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The deleted spend alert ID." }), + "object": Schema.Literal("organization.spend_alert.deleted").annotate({ + "description": "Always `organization.spend_alert.deleted`." }), - "code_interpreter": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey( - Schema.String.annotate({ "description": "The input to the Code Interpreter tool call." }) - ), - "outputs": Schema.optionalKey( - Schema.Array(Schema.Union([ - Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the output in the outputs array." }).check( - Schema.isInt() - ), - "type": Schema.Literal("logs").annotate({ "description": "Always `logs`." }), - "logs": Schema.optionalKey( - Schema.String.annotate({ "description": "The text output from the Code Interpreter tool call." }) - ) - }).annotate({ - "title": "Code interpreter log output", - "description": "Text output from the Code Interpreter tool call as part of a run step." - }), - Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the output in the outputs array." }).check( - Schema.isInt() - ), - "type": Schema.Literal("image").annotate({ "description": "Always `image`." }), - "image": Schema.optionalKey( - Schema.Struct({ - "file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The [file](/docs/api-reference/files) ID of the image." }) - ) - }) - ) - }).annotate({ "title": "Code interpreter image output" }) - ], { mode: "oneOf" })).annotate({ - "description": - "The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a different object type." - }) - ) - }).annotate({ "description": "The Code Interpreter tool call definition." }) - ) + "deleted": Schema.Boolean.annotate({ "description": "Whether the spend alert was deleted." }) }).annotate({ - "title": "Code interpreter tool call", - "description": "Details of the Code Interpreter tool call the run step was involved in." + "description": "Confirmation payload returned after deleting an organization spend alert.", + "identifier": "OrganizationSpendAlertDeletedResource" }) -export type RunStepDeltaStepDetailsToolCallsFileSearchObject = { - readonly "index": number - readonly "id"?: string - readonly "type": "file_search" - readonly "file_search": {} +export type User = { + readonly "object": "organization.user" + readonly "id": string + readonly "name"?: string | null + readonly "email"?: string | null + readonly "role"?: string | null + readonly "added_at": number + readonly "is_default"?: boolean + readonly "created"?: number + readonly "user"?: { + readonly "object": "user" + readonly "id": string + readonly "email"?: string | null + readonly "name"?: string | null + readonly "picture"?: string | null + readonly "enabled"?: boolean | null + readonly "banned"?: boolean | null + readonly "banned_at"?: number | null + } + readonly "is_service_account"?: boolean + readonly "is_scale_tier_authorized_purchaser"?: boolean | null + readonly "is_scim_managed"?: boolean + readonly "api_key_last_used_at"?: number | null + readonly "technical_level"?: string | null + readonly "developer_persona"?: string | null + readonly "projects"?: { + readonly "object": "list" + readonly "data": ReadonlyArray< + { readonly "id"?: string | null; readonly "name"?: string | null; readonly "role"?: string | null } + > + } | null } -export const RunStepDeltaStepDetailsToolCallsFileSearchObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the tool call in the tool calls array." }).check( - Schema.isInt() - ), - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the tool call object." })), - "type": Schema.Literal("file_search").annotate({ - "description": "The type of tool call. This is always going to be `file_search` for this type of tool call." +export const User = Schema.Struct({ + "object": Schema.Literal("organization.user").annotate({ + "description": "The object type, which is always `organization.user`" }), - "file_search": Schema.Struct({}).annotate({ "description": "For now, this is always going to be an empty object." }) -}).annotate({ "title": "File search tool call" }) -export type RunStepDeltaStepDetailsToolCallsFunctionObject = { - readonly "index": number - readonly "id"?: string - readonly "type": "function" - readonly "function"?: { readonly "name"?: string; readonly "arguments"?: string; readonly "output"?: string | null } -} -export const RunStepDeltaStepDetailsToolCallsFunctionObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the tool call in the tool calls array." }).check( - Schema.isInt() + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the user" }) ), - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the tool call object." })), - "type": Schema.Literal("function").annotate({ - "description": "The type of tool call. This is always going to be `function` for this type of tool call." - }), - "function": Schema.optionalKey( + "email": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The email address of the user" }) + ), + "role": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "`owner` or `reader`" }) + ), + "added_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the user was added.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "is_default": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether this is the organization's default user." }) + ), + "created": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the user was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "user": Schema.optionalKey( Schema.Struct({ - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function." })), - "arguments": Schema.optionalKey( - Schema.String.annotate({ "description": "The arguments passed to the function." }) - ), - "output": Schema.optionalKey( + "object": Schema.Literal("user"), + "id": Schema.String, + "email": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "name": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "picture": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "enabled": Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + "banned": Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), + "banned_at": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ - "description": - "The output of the function. This will be `null` if the outputs have not been [submitted](/docs/api-reference/runs/submitToolOutputs) yet." - }), + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ) - }).annotate({ "description": "The definition of the function that was called." }) - ) -}).annotate({ "title": "Function tool call" }) -export type RunStepDetailsToolCallsCodeObject = { - readonly "id": string - readonly "type": "code_interpreter" - readonly "code_interpreter": { - readonly "input": string - readonly "outputs": ReadonlyArray< - { readonly "type": "logs"; readonly "logs": string } | { - readonly "type": "image" - readonly "image": { readonly "file_id": string } - } - > - } -} -export const RunStepDetailsToolCallsCodeObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The ID of the tool call." }), - "type": Schema.Literal("code_interpreter").annotate({ - "description": "The type of tool call. This is always going to be `code_interpreter` for this type of tool call." - }), - "code_interpreter": Schema.Struct({ - "input": Schema.String.annotate({ "description": "The input to the Code Interpreter tool call." }), - "outputs": Schema.Array( - Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("logs").annotate({ "description": "Always `logs`." }), - "logs": Schema.String.annotate({ "description": "The text output from the Code Interpreter tool call." }) - }).annotate({ - "title": "Code Interpreter log output", - "description": "Text output from the Code Interpreter tool call as part of a run step." - }), - Schema.Struct({ - "type": Schema.Literal("image").annotate({ "description": "Always `image`." }), - "image": Schema.Struct({ - "file_id": Schema.String.annotate({ - "description": "The [file](/docs/api-reference/files) ID of the image." - }) - }) - }).annotate({ "title": "Code Interpreter image output" }) - ], { mode: "oneOf" }) - ).annotate({ - "description": - "The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a different object type." + }).annotate({ "description": "Nested user details." }) + ), + "is_service_account": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the user is a service account." }) + ), + "is_scale_tier_authorized_purchaser": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": "Whether the user is an authorized purchaser for Scale Tier." }) - }).annotate({ "description": "The Code Interpreter tool call definition." }) -}).annotate({ - "title": "Code Interpreter tool call", - "description": "Details of the Code Interpreter tool call the run step was involved in." -}) -export type RunStepDetailsToolCallsFileSearchResultObject = { - readonly "file_id": string - readonly "file_name": string - readonly "score": number - readonly "content"?: ReadonlyArray<{ readonly "type"?: "text"; readonly "text"?: string }> -} -export const RunStepDetailsToolCallsFileSearchResultObject = Schema.Struct({ - "file_id": Schema.String.annotate({ "description": "The ID of the file that result was found in." }), - "file_name": Schema.String.annotate({ "description": "The name of the file that result was found in." }), - "score": Schema.Number.annotate({ - "description": "The score of the result. All values must be a floating point number between 0 and 1." - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - "content": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "type": Schema.optionalKey(Schema.Literal("text").annotate({ "description": "The type of the content." })), - "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content of the file." })) - }) - ).annotate({ - "description": - "The content of the result that was found. The content is only included if requested via the include query parameter." + ), + "is_scim_managed": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the user is managed through SCIM." }) + ), + "api_key_last_used_at": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ "description": "The Unix timestamp (in seconds) of the user's last API key usage." }) + ), + "technical_level": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The technical level metadata for the user." }) + ), + "developer_persona": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The developer persona metadata for the user." }) - ) -}).annotate({ "title": "File search tool call result", "description": "A result instance of the file search." }) -export type RunStepDetailsToolCallsFunctionObject = { - readonly "id": string - readonly "type": "function" - readonly "function": { readonly "name": string; readonly "arguments": string; readonly "output": string | null } -} -export const RunStepDetailsToolCallsFunctionObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The ID of the tool call object." }), - "type": Schema.Literal("function").annotate({ - "description": "The type of tool call. This is always going to be `function` for this type of tool call." - }), - "function": Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the function." }), - "arguments": Schema.String.annotate({ "description": "The arguments passed to the function." }), - "output": Schema.Union([ - Schema.String.annotate({ - "description": - "The output of the function. This will be `null` if the outputs have not been [submitted](/docs/api-reference/runs/submitToolOutputs) yet." + ), + "projects": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array( + Schema.Struct({ + "id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "name": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "role": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])) + }) + ) }), Schema.Null - ]) - }).annotate({ "description": "The definition of the function that was called." }) -}).annotate({ "title": "Function tool call" }) -export type RunToolCallObject = { - readonly "id": string - readonly "type": "function" - readonly "function": { readonly "name": string; readonly "arguments": string } + ]).annotate({ "description": "Projects associated with the user, if included." }) + ) +}).annotate({ "description": "Represents an individual `user` within an organization.", "identifier": "User" }) +export type UserRoleUpdateRequest = { + readonly "role"?: string | null + readonly "role_id"?: string | null + readonly "technical_level"?: string | null + readonly "developer_persona"?: string | null } -export const RunToolCallObject = Schema.Struct({ - "id": Schema.String.annotate({ - "description": - "The ID of the tool call. This ID must be referenced when you submit the tool outputs in using the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint." - }), - "type": Schema.Literal("function").annotate({ - "description": "The type of tool call the output is required for. For now, this is always `function`." - }), - "function": Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the function." }), - "arguments": Schema.String.annotate({ - "description": "The arguments that the model expects you to pass to the function." - }) - }).annotate({ "description": "The function definition." }) -}).annotate({ "description": "Tool call objects" }) -export type ServiceTier = "auto" | "default" | "flex" | "scale" | "priority" | null -export const ServiceTier = Schema.Union([ - Schema.Literals(["auto", "default", "flex", "scale", "priority"]).annotate({ - "description": - "Specifies the processing type used for serving the request.\n - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'.\n - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model.\n - If set to '[flex](/docs/guides/flex-processing)' or '[priority](https://openai.com/api-priority-processing/)', then the request will be processed with the corresponding service tier.\n - When not set, the default behavior is 'auto'.\n\n When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter.\n" - }), - Schema.Null -]) -export type SpeechAudioDeltaEvent = { readonly "type": "speech.audio.delta"; readonly "audio": string } -export const SpeechAudioDeltaEvent = Schema.Struct({ - "type": Schema.Literal("speech.audio.delta").annotate({ - "description": "The type of the event. Always `speech.audio.delta`.\n" - }), - "audio": Schema.String.annotate({ "description": "A chunk of Base64-encoded audio data.\n" }) -}).annotate({ "description": "Emitted for each chunk of audio data generated during speech synthesis." }) -export type SpeechAudioDoneEvent = { - readonly "type": "speech.audio.done" - readonly "usage": { - readonly "input_tokens": number - readonly "output_tokens": number - readonly "total_tokens": number - } +export const UserRoleUpdateRequest = Schema.Struct({ + "role": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "`owner` or `reader`" }) + ), + "role_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Role ID to assign to the user." }) + ), + "technical_level": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Technical level metadata." }) + ), + "developer_persona": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Developer persona metadata." }) + ) +}).annotate({ "identifier": "UserRoleUpdateRequest" }) +export type UserDeleteResponse = { + readonly "object": "organization.user.deleted" + readonly "id": string + readonly "deleted": boolean } -export const SpeechAudioDoneEvent = Schema.Struct({ - "type": Schema.Literal("speech.audio.done").annotate({ - "description": "The type of the event. Always `speech.audio.done`.\n" - }), - "usage": Schema.Struct({ - "input_tokens": Schema.Number.annotate({ "description": "Number of input tokens in the prompt." }).check( - Schema.isInt() - ), - "output_tokens": Schema.Number.annotate({ "description": "Number of output tokens generated." }).check( - Schema.isInt() +export const UserDeleteResponse = Schema.Struct({ + "object": Schema.Literal("organization.user.deleted"), + "id": Schema.String, + "deleted": Schema.Boolean +}).annotate({ "identifier": "UserDeleteResponse" }) +export type RealtimeAudioFormats = { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { + readonly "type"?: "audio/pcmu" +} | { readonly "type"?: "audio/pcma" } +export const RealtimeAudioFormats = Schema.Union([ + Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) ), - "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (input + output)." }).check( - Schema.isInt() + "rate": Schema.optionalKey( + Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) ) - }).annotate({ "description": "Token usage statistics for the request.\n" }) -}).annotate({ "description": "Emitted when the speech synthesis is complete and all audio has been streamed." }) -export type StaticChunkingStrategy = { - readonly "max_chunk_size_tokens": number - readonly "chunk_overlap_tokens": number -} -export const StaticChunkingStrategy = Schema.Struct({ - "max_chunk_size_tokens": Schema.Number.annotate({ - "description": - "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(100)).check(Schema.isLessThanOrEqualTo(4096)), - "chunk_overlap_tokens": Schema.Number.annotate({ - "description": - "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" - }).check(Schema.isInt()) -}) -export type StopConfiguration = string | null | ReadonlyArray | null -export const StopConfiguration = Schema.Union([ - Schema.Union([ - Schema.Union([Schema.String, Schema.Null]), - Schema.Array(Schema.String).check(Schema.isMinLength(1)).check(Schema.isMaxLength(4)) - ], { mode: "oneOf" }).annotate({ - "description": - "Not supported with latest reasoning models `o3` and `o4-mini`.\n\nUp to 4 sequences where the API will stop generating further tokens. The\nreturned text will not contain the stop sequence.\n" + }).annotate({ + "title": "PCM audio format", + "description": "The PCM audio format. Only a 24kHz sample rate is supported." }), - Schema.Null -]) -export type SubmitToolOutputsRunRequest = { - readonly "tool_outputs": ReadonlyArray<{ readonly "tool_call_id"?: string; readonly "output"?: string }> - readonly "stream"?: boolean | null -} -export const SubmitToolOutputsRunRequest = Schema.Struct({ - "tool_outputs": Schema.Array(Schema.Struct({ - "tool_call_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The ID of the tool call in the `required_action` object within the run object the output is being submitted for." - }) - ), - "output": Schema.optionalKey( - Schema.String.annotate({ "description": "The output of the tool call to be submitted to continue the run." }) + Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) ) - })).annotate({ "description": "A list of tools for which the outputs are being submitted." }), - "stream": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": - "If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message.\n" - }), - Schema.Null - ]) - ) -}) -export type ToggleCertificatesRequest = { readonly "certificate_ids": ReadonlyArray } -export const ToggleCertificatesRequest = Schema.Struct({ - "certificate_ids": Schema.Array(Schema.String).check(Schema.isMinLength(1)).check(Schema.isMaxLength(10)) -}) -export type ToolChoiceAllowed = { - readonly "type": "allowed_tools" - readonly "mode": "auto" | "required" - readonly "tools": ReadonlyArray<{}> + }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), + Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) + ) + }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) +]).annotate({ "identifier": "RealtimeAudioFormats" }) +export type AudioTranscription = { + readonly "model"?: + | string + | "whisper-1" + | "gpt-transcribe" + | "gpt-live-transcribe" + | "gpt-4o-mini-transcribe" + | "gpt-4o-mini-transcribe-2025-12-15" + | "gpt-4o-transcribe" + | "gpt-4o-transcribe-diarize" + | "gpt-realtime-whisper" + readonly "language"?: string + readonly "languages"?: ReadonlyArray + readonly "keywords"?: ReadonlyArray + readonly "prompt"?: string + readonly "delay"?: "minimal" | "low" | "medium" | "high" | "xhigh" } -export const ToolChoiceAllowed = Schema.Struct({ - "type": Schema.Literal("allowed_tools").annotate({ - "description": "Allowed tool configuration type. Always `allowed_tools`." - }), - "mode": Schema.Literals(["auto", "required"]).annotate({ - "description": - "Constrains the tools available to the model to a pre-defined set.\n\n`auto` allows the model to pick from among the allowed tools and generate a\nmessage.\n\n`required` requires the model to call one or more of the allowed tools.\n" - }), - "tools": Schema.Array( - Schema.Struct({}).annotate({ "description": "A tool definition that the model should be allowed to call.\n" }) - ).annotate({ +export const AudioTranscription = Schema.Struct({ + "model": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "whisper-1", + "gpt-transcribe", + "gpt-live-transcribe", + "gpt-4o-mini-transcribe", + "gpt-4o-mini-transcribe-2025-12-15", + "gpt-4o-transcribe", + "gpt-4o-transcribe-diarize", + "gpt-realtime-whisper" + ]) + ]).annotate({ + "description": + "The model to use for transcription. Current options are `whisper-1`, `gpt-transcribe`, `gpt-live-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels.\n" + }) + ), + "language": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The language of the input audio. Supplying the input language in\n[ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format\nwill improve accuracy and latency.\n" + }) + ), + "languages": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "Possible languages of the input audio, in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format. Supported by `gpt-transcribe` and `gpt-live-transcribe`.\n" + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ), + "keywords": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "Words or phrases to guide transcription of the input audio. Supported by `gpt-transcribe` and `gpt-live-transcribe`.\n" + }) + ), + "prompt": Schema.optionalKey(Schema.String.annotate({ "description": - "A list of tool definitions that the model should be allowed to call.\n\nFor the Responses API, the list of tool definitions might look like:\n```json\n[\n { \"type\": \"function\", \"name\": \"get_weather\" },\n { \"type\": \"mcp\", \"server_label\": \"deepwiki\" },\n { \"type\": \"image_generation\" }\n]\n```\n" - }) -}).annotate({ - "title": "Allowed tools", - "description": "Constrains the tools available to the model to a pre-defined set.\n" + "An optional text to guide the model's style or continue a previous audio\nsegment.\nFor `whisper-1`, the [prompt is a list of keywords](https://developers.openai.com/api/docs/guides/speech-to-text#prompting).\nFor `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example \"expect words related to technology\".\nPrompt is not supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" + })), + "delay": Schema.optionalKey( + Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ + "description": + "Controls how long the model waits before emitting transcription text.\nHigher values can improve transcription accuracy at the cost of latency.\nOnly supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" + }) + ) +}).annotate({ "identifier": "AudioTranscription" }) +export type NoiseReductionType = "near_field" | "far_field" +export const NoiseReductionType = Schema.Literals(["near_field", "far_field"]).annotate({ + "description": + "Type of noise reduction. `near_field` is for close-talking microphones such as headphones, `far_field` is for far-field microphones such as laptop or conference room microphones.\n", + "identifier": "NoiseReductionType" }) -export type ToolChoiceCustom = { readonly "type": "custom"; readonly "name": string } -export const ToolChoiceCustom = Schema.Struct({ - "type": Schema.Literal("custom").annotate({ "description": "For custom tool calling, the type is always `custom`." }), - "name": Schema.String.annotate({ "description": "The name of the custom tool to call." }) -}).annotate({ - "title": "Custom tool", - "description": "Use this option to force the model to call a specific custom tool.\n" +export type RealtimeTurnDetection = { + readonly "type": "server_vad" + readonly "threshold"?: number + readonly "prefix_padding_ms"?: number + readonly "silence_duration_ms"?: number + readonly "create_response"?: boolean + readonly "interrupt_response"?: boolean + readonly "idle_timeout_ms"?: number | null +} | { + readonly "type": "semantic_vad" + readonly "eagerness"?: "low" | "medium" | "high" | "auto" + readonly "create_response"?: boolean + readonly "interrupt_response"?: boolean +} | null +export const RealtimeTurnDetection = Schema.Union([ + Schema.Union([ + Schema.Struct({ + "type": Schema.Literal("server_vad").annotate({ + "description": "Type of turn detection, `server_vad` to turn on simple Server VAD.\n" + }), + "threshold": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Used only for `server_vad` mode. Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "prefix_padding_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Used only for `server_vad` mode. Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "silence_duration_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Used only for `server_vad` mode. Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "create_response": Schema.optionalKey(Schema.Boolean.annotate({ + "description": + "Whether or not to automatically generate a response when a VAD stop event occurs. If `interrupt_response` is set to `false` this may fail to create a response if the model is already responding.\n\nIf both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted.\n" + })), + "interrupt_response": Schema.optionalKey(Schema.Boolean.annotate({ + "description": + "Whether or not to automatically interrupt (cancel) any ongoing response with output to the default\nconversation (i.e. `conversation` of `auto`) when a VAD start event occurs. If `true` then the response will be cancelled, otherwise it will continue until complete.\n\nIf both `create_response` and `interrupt_response` are set to `false`, the model will never respond automatically but VAD events will still be emitted.\n" + })), + "idle_timeout_ms": Schema.optionalKey(Schema.Union([ + Schema.Number.annotate({ + "description": + "Optional timeout after which a model response will be triggered automatically. This is\nuseful for situations in which a long pause from the user is unexpected, such as a phone\ncall. The model will effectively prompt the user to continue the conversation based\non the current context.\n\nThe timeout value will be applied after the last model response's audio has finished playing,\ni.e. it's set to the `response.done` time plus audio playback duration.\n\nAn `input_audio_buffer.timeout_triggered` event (plus events\nassociated with the Response) will be emitted when the timeout is reached.\nIdle timeout is currently only supported for `server_vad` mode.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(5000).annotate({ "expected": "a value greater than or equal to 5000" }) + ).check(Schema.isLessThanOrEqualTo(30000).annotate({ "expected": "a value less than or equal to 30000" })), + Schema.Null + ])) + }).annotate({ + "title": "Server VAD", + "description": + "Server-side voice activity detection (VAD) which flips on when user speech is detected and off after a period of silence." + }), + Schema.Struct({ + "type": Schema.Literal("semantic_vad").annotate({ + "description": "Type of turn detection, `semantic_vad` to turn on Semantic VAD.\n" + }), + "eagerness": Schema.optionalKey( + Schema.Literals(["low", "medium", "high", "auto"]).annotate({ + "description": + "Used only for `semantic_vad` mode. The eagerness of the model to respond. `low` will wait longer for the user to continue speaking, `high` will respond more quickly. `auto` is the default and is equivalent to `medium`. `low`, `medium`, and `high` have max timeouts of 8s, 4s, and 2s respectively.\n" + }) + ), + "create_response": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether or not to automatically generate a response when a VAD stop event occurs.\n" + }) + ), + "interrupt_response": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Whether or not to automatically interrupt any ongoing response with output to the default\nconversation (i.e. `conversation` of `auto`) when a VAD start event occurs.\n" + }) + ) + }).annotate({ + "title": "Semantic VAD", + "description": + "Server-side semantic turn detection which uses a model to determine when the user has finished speaking." + }) + ], { mode: "oneOf" }).annotate({ + "title": "Realtime Turn Detection", + "description": + "Configuration for turn detection, ether Server VAD or Semantic VAD. This can be set to `null` to turn off, in which case the client must manually trigger model response.\n\nServer VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech.\n\nSemantic VAD is more advanced and uses a turn detection model (in conjunction with VAD) to semantically estimate whether the user has finished speaking, then dynamically sets a timeout based on this probability. For example, if user audio trails off with \"uhhm\", the model will score a low probability of turn end and wait longer for the user to continue speaking. This can be useful for more natural conversations, but may have a higher latency.\n\nFor `gpt-realtime-whisper` transcription sessions, turn detection must be\nset to `null`; VAD is not supported.\n" + }), + Schema.Null +]).annotate({ "identifier": "RealtimeTurnDetection" }) +export type RealtimeFunctionTool = { + readonly "type"?: "function" + readonly "name"?: string + readonly "description"?: string + readonly "parameters"?: { readonly [x: string]: Schema.Json } +} +export const RealtimeFunctionTool = Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("function").annotate({ "description": "The type of the tool, i.e. `function`." }) + ), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function." })), + "description": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The description of the function, including guidance on when and how\nto call it, and guidance about what to tell the user when calling\n(if anything).\n" + }) + ), + "parameters": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Parameters of the function in JSON Schema." + }) + ) +}).annotate({ "title": "Function tool", "identifier": "RealtimeFunctionTool" }) +export type ToolChoiceOptions = "none" | "auto" | "required" +export const ToolChoiceOptions = Schema.Literals(["none", "auto", "required"]).annotate({ + "title": "Tool choice mode", + "description": + "Controls which (if any) tool is called by the model.\n\n`none` means the model will not call any tool and instead generates a message.\n\n`auto` means the model can pick between generating a message or calling one or\nmore tools.\n\n`required` means the model must call one or more tools.\n", + "identifier": "ToolChoiceOptions" }) export type ToolChoiceFunction = { readonly "type": "function"; readonly "name": string } export const ToolChoiceFunction = Schema.Struct({ @@ -7111,7 +7268,8 @@ export const ToolChoiceFunction = Schema.Struct({ "name": Schema.String.annotate({ "description": "The name of the function to call." }) }).annotate({ "title": "Function tool", - "description": "Use this option to force the model to call a specific function.\n" + "description": "Use this option to force the model to call a specific function.\n", + "identifier": "ToolChoiceFunction" }) export type ToolChoiceMCP = { readonly "type": "mcp"; readonly "server_label": string; readonly "name"?: string | null } export const ToolChoiceMCP = Schema.Struct({ @@ -7125,13 +7283,153 @@ export const ToolChoiceMCP = Schema.Struct({ ) }).annotate({ "title": "MCP tool", - "description": "Use this option to force the model to call a specific tool on a remote MCP server.\n" + "description": "Use this option to force the model to call a specific tool on a remote MCP server.\n", + "identifier": "ToolChoiceMCP" }) -export type ToolChoiceOptions = "none" | "auto" | "required" -export const ToolChoiceOptions = Schema.Literals(["none", "auto", "required"]).annotate({ - "title": "Tool choice mode", +export type RealtimeReasoningEffort = "minimal" | "low" | "medium" | "high" | "xhigh" +export const RealtimeReasoningEffort = Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ + "description": "Constrains effort on reasoning for reasoning-capable Realtime models such as\n`gpt-realtime-2`.\n", + "identifier": "RealtimeReasoningEffort" +}) +export type RealtimeTruncation = "auto" | "disabled" | { + readonly "type": "retention_ratio" + readonly "retention_ratio": number + readonly "token_limits"?: { readonly "post_instructions"?: number } +} +export const RealtimeTruncation = Schema.Union([ + Schema.Literals(["auto", "disabled"]).annotate({ + "description": + "The truncation strategy to use for the session. `auto` is the default truncation strategy. `disabled` will disable truncation and emit errors when the conversation exceeds the input token limit." + }), + Schema.Struct({ + "type": Schema.Literal("retention_ratio").annotate({ "description": "Use retention ratio truncation." }), + "retention_ratio": Schema.Number.annotate({ + "description": + "Fraction of post-instruction conversation tokens to retain (`0.0` - `1.0`) when the conversation exceeds the input token limit. Setting this to `0.8` means that messages will be dropped until 80% of the maximum allowed tokens are used. This helps reduce the frequency of truncations and improve cache rates.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + "token_limits": Schema.optionalKey( + Schema.Struct({ + "post_instructions": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Maximum tokens allowed in the conversation after instructions (which including tool definitions). For example, setting this to 5,000 would mean that truncation would occur when the conversation exceeds 5,000 tokens after instructions. This cannot be higher than the model's context window size minus the maximum output tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ) + ) + }).annotate({ + "description": + "Optional custom token limits for this truncation strategy. If not provided, the model's default token limits will be used." + }) + ) + }).annotate({ + "title": "Retention ratio truncation", + "description": + "Retain a fraction of the conversation tokens when the conversation exceeds the input token limit. This allows you to amortize truncations across multiple turns, which can help improve cached token usage." + }) +], { mode: "oneOf" }).annotate({ + "title": "Realtime Truncation Controls", "description": - "Controls which (if any) tool is called by the model.\n\n`none` means the model will not call any tool and instead generates a message.\n\n`auto` means the model can pick between generating a message or calling one or\nmore tools.\n\n`required` means the model must call one or more tools.\n" + "When the number of tokens in a conversation exceeds the model's input token limit, the conversation be truncated, meaning messages (starting from the oldest) will not be included in the model's context. A 32k context model with 4,096 max output tokens can only include 28,224 tokens in the context before truncation occurs.\n\nClients can configure truncation behavior to truncate with a lower max token limit, which is an effective way to control token usage and cost.\n\nTruncation will reduce the number of cached tokens on the next turn (busting the cache), since messages are dropped from the beginning of the context. However, clients can also configure truncation to retain messages up to a fraction of the maximum context size, which will reduce the need for future truncations and thus improve the cache rate.\n\nTruncation can be disabled entirely, which means the server will never truncate but would instead return an error if the conversation exceeds the model's input token limit.\n", + "identifier": "RealtimeTruncation" +}) +export type RealtimeCallReferRequest = { readonly "target_uri": string } +export const RealtimeCallReferRequest = Schema.Struct({ + "target_uri": Schema.String.annotate({ + "description": + "URI that should appear in the SIP Refer-To header. Supports values like\n`tel:+14155550123` or `sip:agent@example.com`." + }) +}).annotate({ + "title": "Realtime call refer request", + "description": "Parameters required to transfer a SIP call to a new destination using the\nRealtime API.", + "identifier": "RealtimeCallReferRequest" +}) +export type RealtimeCallRejectRequest = { readonly "status_code"?: number } +export const RealtimeCallRejectRequest = Schema.Struct({ + "status_code": Schema.optionalKey( + Schema.Number.annotate({ + "description": "SIP response code to send back to the caller. Defaults to `603` (Decline)\nwhen omitted." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ) +}).annotate({ + "title": "Realtime call reject request", + "description": "Parameters used to decline an incoming SIP call handled by the Realtime API.", + "identifier": "RealtimeCallRejectRequest" +}) +export type AudioTranscriptionResponse = { + readonly "model"?: + | string + | "whisper-1" + | "gpt-transcribe" + | "gpt-live-transcribe" + | "gpt-4o-mini-transcribe" + | "gpt-4o-mini-transcribe-2025-12-15" + | "gpt-4o-transcribe" + | "gpt-4o-transcribe-diarize" + | "gpt-realtime-whisper" + readonly "language"?: string | null + readonly "languages"?: ReadonlyArray + readonly "prompt"?: string +} +export const AudioTranscriptionResponse = Schema.Struct({ + "model": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "whisper-1", + "gpt-transcribe", + "gpt-live-transcribe", + "gpt-4o-mini-transcribe", + "gpt-4o-mini-transcribe-2025-12-15", + "gpt-4o-transcribe", + "gpt-4o-transcribe-diarize", + "gpt-realtime-whisper" + ]) + ]).annotate({ + "description": + "The model used for transcription. Current options are `whisper-1`, `gpt-transcribe`, `gpt-live-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`.\n" + }) + ), + "language": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The language of the input audio.\n" }) + ), + "languages": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "The possible input audio languages configured for transcription, in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format.\n" + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ), + "prompt": Schema.optionalKey( + Schema.String.annotate({ "description": "The prompt configured for input audio transcription, when present.\n" }) + ) +}).annotate({ "identifier": "AudioTranscriptionResponse" }) +export type ToolChoiceAllowed = { + readonly "type": "allowed_tools" + readonly "mode": "auto" | "required" + readonly "tools": ReadonlyArray<{ readonly [x: string]: Schema.Json }> +} +export const ToolChoiceAllowed = Schema.Struct({ + "type": Schema.Literal("allowed_tools").annotate({ + "description": "Allowed tool configuration type. Always `allowed_tools`." + }), + "mode": Schema.Literals(["auto", "required"]).annotate({ + "description": + "Constrains the tools available to the model to a pre-defined set.\n\n`auto` allows the model to pick from among the allowed tools and generate a\nmessage.\n\n`required` requires the model to call one or more of the allowed tools.\n" + }), + "tools": Schema.Array( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A tool definition that the model should be allowed to call.\n" + }) + ).annotate({ + "description": + "A list of tool definitions that the model should be allowed to call.\n\nFor the Responses API, the list of tool definitions might look like:\n```json\n[\n { \"type\": \"function\", \"name\": \"get_weather\" },\n { \"type\": \"mcp\", \"server_label\": \"deepwiki\" },\n { \"type\": \"image_generation\" }\n]\n```\n" + }) +}).annotate({ + "title": "Allowed tools", + "description": "Constrains the tools available to the model to a pre-defined set.\n", + "identifier": "ToolChoiceAllowed" }) export type ToolChoiceTypes = { readonly "type": @@ -7156,2513 +7454,2509 @@ export const ToolChoiceTypes = Schema.Struct({ "code_interpreter" ]).annotate({ "description": - "The type of hosted tool the model should to use. Learn more about\n[built-in tools](/docs/guides/tools).\n\nAllowed values are:\n- `file_search`\n- `web_search_preview`\n- `computer`\n- `computer_use_preview`\n- `computer_use`\n- `code_interpreter`\n- `image_generation`\n" + "The type of hosted tool the model should to use. Learn more about\n[built-in tools](https://developers.openai.com/api/docs/guides/tools).\n\nAllowed values are:\n- `file_search`\n- `web_search_preview`\n- `computer`\n- `computer_use_preview`\n- `computer_use`\n- `code_interpreter`\n- `image_generation`\n" }) }).annotate({ "title": "Hosted tool", "description": - "Indicates that the model should use a built-in tool to generate a response.\n[Learn more about built-in tools](/docs/guides/tools).\n" + "Indicates that the model should use a built-in tool to generate a response.\n[Learn more about built-in tools](https://developers.openai.com/api/docs/guides/tools).\n", + "identifier": "ToolChoiceTypes" }) -export type TranscriptTextDeltaEvent = { - readonly "type": "transcript.text.delta" - readonly "delta": string - readonly "logprobs"?: ReadonlyArray< - { readonly "token"?: string; readonly "logprob"?: number; readonly "bytes"?: ReadonlyArray } - > - readonly "segment_id"?: string -} -export const TranscriptTextDeltaEvent = Schema.Struct({ - "type": Schema.Literal("transcript.text.delta").annotate({ - "description": "The type of the event. Always `transcript.text.delta`.\n" - }), - "delta": Schema.String.annotate({ "description": "The text delta that was additionally transcribed.\n" }), - "logprobs": Schema.optionalKey( - Schema.Array(Schema.Struct({ - "token": Schema.optionalKey( - Schema.String.annotate({ "description": "The token that was used to generate the log probability.\n" }) - ), - "logprob": Schema.optionalKey( - Schema.Number.annotate({ "description": "The log probability of the token.\n" }).check(Schema.isFinite()) - ), - "bytes": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "description": "The bytes that were used to generate the log probability.\n" - }) - ) - })).annotate({ - "description": - "The log probabilities of the delta. Only included if you [create a transcription](/docs/api-reference/audio/create-transcription) with the `include[]` parameter set to `logprobs`.\n" - }) - ), - "segment_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "Identifier of the diarized segment that this delta belongs to. Only present when using `gpt-4o-transcribe-diarize`.\n" - }) - ) +export type ToolChoiceCustom = { readonly "type": "custom"; readonly "name": string } +export const ToolChoiceCustom = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "For custom tool calling, the type is always `custom`." }), + "name": Schema.String.annotate({ "description": "The name of the custom tool to call." }) }).annotate({ - "description": - "Emitted when there is an additional text delta. This is also the first event emitted when the transcription starts. Only emitted when you [create a transcription](/docs/api-reference/audio/create-transcription) with the `Stream` parameter set to `true`." + "title": "Custom tool", + "description": "Use this option to force the model to call a specific custom tool.\n", + "identifier": "ToolChoiceCustom" }) -export type TranscriptTextSegmentEvent = { - readonly "type": "transcript.text.segment" - readonly "id": string - readonly "start": number - readonly "end": number - readonly "text": string - readonly "speaker": string -} -export const TranscriptTextSegmentEvent = Schema.Struct({ - "type": Schema.Literal("transcript.text.segment").annotate({ - "description": "The type of the event. Always `transcript.text.segment`." +export type SpecificProgrammaticToolCallingParam = { readonly "type": "programmatic_tool_calling" } +export const SpecificProgrammaticToolCallingParam = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The tool to call. Always `programmatic_tool_calling`." + }) +}).annotate({ "identifier": "SpecificProgrammaticToolCallingParam" }) +export type SpecificApplyPatchParam = { readonly "type": "apply_patch" } +export const SpecificApplyPatchParam = Schema.Struct({ + "type": Schema.Literal("apply_patch").annotate({ "description": "The tool to call. Always `apply_patch`." }) +}).annotate({ + "title": "Specific apply patch tool choice", + "description": "Forces the model to call the apply_patch tool when executing a tool call.", + "identifier": "SpecificApplyPatchParam" +}) +export type SpecificFunctionShellParam = { readonly "type": "shell" } +export const SpecificFunctionShellParam = Schema.Struct({ + "type": Schema.Literal("shell").annotate({ "description": "The tool to call. Always `shell`." }) +}).annotate({ + "title": "Specific shell tool choice", + "description": "Forces the model to call the shell tool when a tool call is required.", + "identifier": "SpecificFunctionShellParam" +}) +export type CyberAccessProgramEnum = "standard" | "daybreak_blue" | "daybreak_red" +export const CyberAccessProgramEnum = Schema.Literals(["standard", "daybreak_blue", "daybreak_red"]).annotate({ + "identifier": "CyberAccessProgramEnum" +}) +export type ServiceTierResponses = "auto" | "default" | "flex" | "scale" | "priority" | "fast" | "ultrafast" | null +export const ServiceTierResponses = Schema.Union([ + Schema.Literals(["auto", "default", "flex", "scale", "priority", "fast", "ultrafast"]).annotate({ + "description": + "Specifies the processing type used for serving the request.\n - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'.\n - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model.\n - If set to '[flex](https://developers.openai.com/api/docs/guides/flex-processing)', then the request will be processed with the Flex Processing service tier.\n - To opt-in to [Fast mode](https://developers.openai.com/api/docs/guides/fast-mode) at the request level, include the `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat Completions. The response will show `service_tier=priority` regardless of if you specify `service_tier=fast` or `priority` in your request.\n - If set to 'ultrafast', then the request will be processed with the access-controlled Ultrafast Processing service tier. This tier is currently available for `gpt-5.6-sol`; a response served through it will show `service_tier=ultrafast`.\n - When not set, the default behavior is 'auto'.\n\n When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter.\n" }), - "id": Schema.String.annotate({ "description": "Unique identifier for the segment." }), - "start": Schema.Number.annotate({ "description": "Start timestamp of the segment in seconds.", "format": "double" }) - .check(Schema.isFinite()), - "end": Schema.Number.annotate({ "description": "End timestamp of the segment in seconds.", "format": "double" }) - .check(Schema.isFinite()), - "text": Schema.String.annotate({ "description": "Transcript text for this segment." }), - "speaker": Schema.String.annotate({ "description": "Speaker label for this segment." }) + Schema.Null +]).annotate({ "identifier": "ServiceTierResponses" }) +export type ReasoningModeEnum = string | "standard" | "pro" +export const ReasoningModeEnum = Schema.Union([Schema.String, Schema.Literals(["standard", "pro"])]).annotate({ + "identifier": "ReasoningModeEnum" +}) +export type ResponseStreamOptions = { readonly "include_obfuscation"?: boolean } | null +export const ResponseStreamOptions = Schema.Union([ + Schema.Struct({ + "include_obfuscation": Schema.optionalKey(Schema.Boolean.annotate({ + "description": + "When true, stream obfuscation will be enabled. Stream obfuscation adds\nrandom characters to an `obfuscation` field on streaming delta events to\nnormalize payload sizes as a mitigation to certain side-channel attacks.\nThese obfuscation fields are included by default, but add a small amount\nof overhead to the data stream. You can set `include_obfuscation` to\nfalse to optimize for bandwidth if you trust the network links between\nyour application and the OpenAI API.\n" + })) + }).annotate({ "description": "Options for streaming responses. Only set this when you set `stream: true`.\n" }), + Schema.Null +]).annotate({ "identifier": "ResponseStreamOptions" }) +export type ConversationParam_2 = { readonly "id": string } +export const ConversationParam_2 = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the conversation." }) }).annotate({ - "description": - "Emitted when a diarized transcription returns a completed segment with speaker information. Only emitted when you [create a transcription](/docs/api-reference/audio/create-transcription) with `stream` set to `true` and `response_format` set to `diarized_json`.\n" + "title": "Conversation object", + "description": "The conversation that this response belongs to.", + "identifier": "ConversationParam-2" }) -export type TranscriptTextUsageDuration = { readonly "type": "duration"; readonly "seconds": number } -export const TranscriptTextUsageDuration = Schema.Struct({ - "type": Schema.Literal("duration").annotate({ - "description": "The type of the usage object. Always `duration` for this variant." +export type ContextManagementParam = { readonly "type": string; readonly "compact_threshold"?: number | null } +export const ContextManagementParam = Schema.Struct({ + "type": Schema.String.annotate({ + "description": "The context management entry type. Currently only 'compaction' is supported." }), - "seconds": Schema.Number.annotate({ "description": "Duration of the input audio in seconds.", "format": "double" }) - .check(Schema.isFinite()) -}).annotate({ "title": "Duration Usage", "description": "Usage statistics for models billed by audio input duration." }) -export type TranscriptTextUsageTokens = { - readonly "type": "tokens" + "compact_threshold": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "Token threshold at which compaction should be triggered for this entry." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1000).annotate({ "expected": "a value greater than or equal to 1000" }) + ), + Schema.Null + ]) + ) +}).annotate({ "identifier": "ContextManagementParam" }) +export type ResponseErrorCode = + | "server_error" + | "rate_limit_exceeded" + | "invalid_prompt" + | "data_residency_mismatch" + | "bio_policy" + | "misalignment_policy_violation" + | "vector_store_timeout" + | "invalid_image" + | "invalid_image_format" + | "invalid_base64_image" + | "invalid_image_url" + | "image_too_large" + | "image_too_small" + | "image_parse_error" + | "image_content_policy_violation" + | "invalid_image_mode" + | "image_file_too_large" + | "unsupported_image_media_type" + | "empty_image_file" + | "failed_to_download_image" + | "image_file_not_found" +export const ResponseErrorCode = Schema.Literals([ + "server_error", + "rate_limit_exceeded", + "invalid_prompt", + "data_residency_mismatch", + "bio_policy", + "misalignment_policy_violation", + "vector_store_timeout", + "invalid_image", + "invalid_image_format", + "invalid_base64_image", + "invalid_image_url", + "image_too_large", + "image_too_small", + "image_parse_error", + "image_content_policy_violation", + "invalid_image_mode", + "image_file_too_large", + "unsupported_image_media_type", + "empty_image_file", + "failed_to_download_image", + "image_file_not_found" +]).annotate({ "description": "The error code for the response.\n", "identifier": "ResponseErrorCode" }) +export type ResponseUsage = { readonly "input_tokens": number - readonly "input_token_details"?: { readonly "text_tokens"?: number; readonly "audio_tokens"?: number } + readonly "input_tokens_details": { readonly "cached_tokens": number; readonly "cache_write_tokens"?: number } readonly "output_tokens": number + readonly "output_tokens_details": { readonly "reasoning_tokens": number } readonly "total_tokens": number } -export const TranscriptTextUsageTokens = Schema.Struct({ - "type": Schema.Literal("tokens").annotate({ - "description": "The type of the usage object. Always `tokens` for this variant." - }), - "input_tokens": Schema.Number.annotate({ "description": "Number of input tokens billed for this request." }).check( - Schema.isInt() +export const ResponseUsage = Schema.Struct({ + "input_tokens": Schema.Number.annotate({ "description": "The number of input tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "input_token_details": Schema.optionalKey( - Schema.Struct({ - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of text tokens billed for this request." }).check( - Schema.isInt() - ) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of audio tokens billed for this request." }).check( - Schema.isInt() - ) + "input_tokens_details": Schema.Struct({ + "cached_tokens": Schema.Number.annotate({ + "description": + "The number of tokens that were retrieved from the cache.\n[More on prompt caching](https://developers.openai.com/api/docs/guides/prompt-caching).\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "cache_write_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The number of input tokens that were written to the cache." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) - }).annotate({ "description": "Details about the input tokens billed for this request." }) - ), - "output_tokens": Schema.Number.annotate({ "description": "Number of output tokens generated." }).check( - Schema.isInt() + ) + }).annotate({ "description": "A detailed breakdown of the input tokens." }), + "output_tokens": Schema.Number.annotate({ "description": "The number of output tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (input + output)." }).check( - Schema.isInt() + "output_tokens_details": Schema.Struct({ + "reasoning_tokens": Schema.Number.annotate({ "description": "The number of reasoning tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "A detailed breakdown of the output tokens." }), + "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "title": "Token Usage", "description": "Usage statistics for models billed by token usage." }) -export type TranscriptionDiarizedSegment = { - readonly "type": "transcript.text.segment" - readonly "id": string - readonly "start": number - readonly "end": number - readonly "text": string - readonly "speaker": string -} -export const TranscriptionDiarizedSegment = Schema.Struct({ - "type": Schema.Literal("transcript.text.segment").annotate({ - "description": "The type of the segment. Always `transcript.text.segment`.\n" +}).annotate({ + "description": + "Represents token usage details including input tokens, output tokens,\na breakdown of output tokens, and the total tokens used.\n", + "identifier": "ResponseUsage" +}) +export type CacheMissReasonTypeEnum = + | "model_changed" + | "prompt_cache_key_changed" + | "tools_changed" + | "text_format_changed" + | "reasoning_effort_changed" + | "verbosity_changed" + | "context_compacted" + | "input_changed" + | "service_tier_changed" +export const CacheMissReasonTypeEnum = Schema.Literals([ + "model_changed", + "prompt_cache_key_changed", + "tools_changed", + "text_format_changed", + "reasoning_effort_changed", + "verbosity_changed", + "context_compacted", + "input_changed", + "service_tier_changed" +]).annotate({ "identifier": "CacheMissReasonTypeEnum" }) +export type PromptCacheHitDiagnosticsBody = { readonly "type": "cache_hit" } +export const PromptCacheHitDiagnosticsBody = Schema.Struct({ "type": Schema.Literal("cache_hit") }).annotate({ + "identifier": "PromptCacheHitDiagnosticsBody" +}) +export type PromptCacheComparisonResponseNotFoundDiagnosticsBody = { readonly "type": "comparison_response_not_found" } +export const PromptCacheComparisonResponseNotFoundDiagnosticsBody = Schema.Struct({ + "type": Schema.Literal("comparison_response_not_found") +}).annotate({ "identifier": "PromptCacheComparisonResponseNotFoundDiagnosticsBody" }) +export type PromptCacheUnavailableDiagnosticsBody = { readonly "type": "unavailable" } +export const PromptCacheUnavailableDiagnosticsBody = Schema.Struct({ "type": Schema.Literal("unavailable") }).annotate({ + "identifier": "PromptCacheUnavailableDiagnosticsBody" +}) +export type ModerationErrorBody = { readonly "type": "error"; readonly "code": string; readonly "message": string } +export const ModerationErrorBody = Schema.Struct({ + "type": Schema.Literal("error").annotate({ + "description": "The object type, which was always `error` for moderation failures." }), - "id": Schema.String.annotate({ "description": "Unique identifier for the segment." }), - "start": Schema.Number.annotate({ "description": "Start timestamp of the segment in seconds.", "format": "double" }) - .check(Schema.isFinite()), - "end": Schema.Number.annotate({ "description": "End timestamp of the segment in seconds.", "format": "double" }) - .check(Schema.isFinite()), - "text": Schema.String.annotate({ "description": "Transcript text for this segment." }), - "speaker": Schema.String.annotate({ - "description": - "Speaker label for this segment. When known speakers are provided, the label matches `known_speaker_names[]`. Otherwise speakers are labeled sequentially using capital letters (`A`, `B`, ...).\n" + "code": Schema.String.annotate({ "description": "The error code." }), + "message": Schema.String.annotate({ "description": "The error message." }) +}).annotate({ + "title": "Moderation error", + "description": "An error produced while attempting moderation for the response input or output.", + "identifier": "ModerationErrorBody" +}) +export type ResponseConversation = { readonly "id": string } +export const ResponseConversation = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The unique ID of the conversation that this response was associated with." }) -}).annotate({ "description": "A segment of diarized transcript text with speaker metadata." }) -export type TranscriptionInclude = "logprobs" -export const TranscriptionInclude = Schema.Literal("logprobs") -export type TranscriptionSegment = { - readonly "id": number - readonly "seek": number - readonly "start": number - readonly "end": number - readonly "text": string - readonly "tokens": ReadonlyArray - readonly "temperature": number - readonly "avg_logprob": number - readonly "compression_ratio": number - readonly "no_speech_prob": number +}).annotate({ + "title": "Conversation", + "description": + "The conversation that this response belonged to. Input items and output items from this response were automatically added to this conversation.", + "identifier": "ResponseConversation" +}) +export type ResponseAudioDeltaEvent = { + readonly "type": "response.audio.delta" + readonly "sequence_number": number + readonly "delta": string } -export const TranscriptionSegment = Schema.Struct({ - "id": Schema.Number.annotate({ "description": "Unique identifier of the segment." }).check(Schema.isInt()), - "seek": Schema.Number.annotate({ "description": "Seek offset of the segment." }).check(Schema.isInt()), - "start": Schema.Number.annotate({ "description": "Start time of the segment in seconds.", "format": "double" }).check( - Schema.isFinite() - ), - "end": Schema.Number.annotate({ "description": "End time of the segment in seconds.", "format": "double" }).check( - Schema.isFinite() - ), - "text": Schema.String.annotate({ "description": "Text content of the segment." }), - "tokens": Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "description": "Array of token IDs for the text content." +export const ResponseAudioDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.audio.delta").annotate({ + "description": "The type of the event. Always `response.audio.delta`.\n" }), - "temperature": Schema.Number.annotate({ - "description": "Temperature parameter used for generating the segment.", - "format": "float" - }).check(Schema.isFinite()), - "avg_logprob": Schema.Number.annotate({ - "description": "Average logprob of the segment. If the value is lower than -1, consider the logprobs failed.", - "format": "float" - }).check(Schema.isFinite()), - "compression_ratio": Schema.Number.annotate({ - "description": - "Compression ratio of the segment. If the value is greater than 2.4, consider the compression failed.", - "format": "float" - }).check(Schema.isFinite()), - "no_speech_prob": Schema.Number.annotate({ - "description": - "Probability of no speech in the segment. If the value is higher than 1.0 and the `avg_logprob` is below -1, consider this segment silent.", - "format": "float" - }).check(Schema.isFinite()) + "sequence_number": Schema.Number.annotate({ + "description": "A sequence number for this chunk of the stream response.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "A chunk of Base64 encoded response audio bytes.\n" }) +}).annotate({ + "description": "Emitted when there is a partial audio response.", + "identifier": "ResponseAudioDeltaEvent" }) -export type TranscriptionWord = { readonly "word": string; readonly "start": number; readonly "end": number } -export const TranscriptionWord = Schema.Struct({ - "word": Schema.String.annotate({ "description": "The text content of the word." }), - "start": Schema.Number.annotate({ "description": "Start time of the word in seconds.", "format": "double" }).check( - Schema.isFinite() +export type ResponseAudioDoneEvent = { + readonly "type": "response.audio.done" + readonly "sequence_number": number + readonly "response_id": Schema.Json +} +export const ResponseAudioDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.audio.done").annotate({ + "description": "The type of the event. Always `response.audio.done`.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the delta.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "end": Schema.Number.annotate({ "description": "End time of the word in seconds.", "format": "double" }).check( - Schema.isFinite() - ) + "response_id": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ "description": "Emitted when the audio response is complete.", "identifier": "ResponseAudioDoneEvent" }) +export type ResponseAudioTranscriptDeltaEvent = { + readonly "type": "response.audio.transcript.delta" + readonly "delta": string + readonly "sequence_number": number + readonly "response_id": Schema.Json +} +export const ResponseAudioTranscriptDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.audio.transcript.delta").annotate({ + "description": "The type of the event. Always `response.audio.transcript.delta`.\n" + }), + "delta": Schema.String.annotate({ "description": "The partial transcript of the audio response.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "response_id": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ + "description": "Emitted when there is a partial transcript of audio.", + "identifier": "ResponseAudioTranscriptDeltaEvent" }) -export type UpdateGroupBody = { readonly "name": string } -export const UpdateGroupBody = Schema.Struct({ - "name": Schema.String.annotate({ "description": "New display name for the group." }).check(Schema.isMinLength(1)) - .check(Schema.isMaxLength(255)) -}).annotate({ "description": "Request payload for updating the details of an existing group." }) -export type UpdateVoiceConsentRequest = { readonly "name": string } -export const UpdateVoiceConsentRequest = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The updated label for this consent recording." }) +export type ResponseAudioTranscriptDoneEvent = { + readonly "type": "response.audio.transcript.done" + readonly "sequence_number": number + readonly "response_id": Schema.Json +} +export const ResponseAudioTranscriptDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.audio.transcript.done").annotate({ + "description": "The type of the event. Always `response.audio.transcript.done`.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "response_id": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ + "description": "Emitted when the full audio transcript is completed.", + "identifier": "ResponseAudioTranscriptDoneEvent" }) -export type Upload = { - readonly "id": string - readonly "created_at": number - readonly "filename": string - readonly "bytes": number - readonly "purpose": string - readonly "status": "pending" | "completed" | "cancelled" | "expired" - readonly "expires_at": number - readonly "object"?: "upload" - readonly "file"?: { - readonly "id": string - readonly "bytes": number - readonly "created_at": number - readonly "expires_at"?: number | null - readonly "filename": string - readonly "object": "file" - readonly "purpose": - | "assistants" - | "assistants_output" - | "batch" - | "batch_output" - | "fine-tune" - | "fine-tune-results" - | "vision" - | "user_data" - readonly "status": "uploaded" | "processed" | "error" - readonly "status_details"?: string | null - readonly [x: string]: unknown - } +export type ResponseCodeInterpreterCallCodeDeltaEvent = { + readonly "type": "response.code_interpreter_call_code.delta" + readonly "output_index": number + readonly "item_id": string + readonly "delta": string + readonly "sequence_number": number } -export const Upload = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The Upload unique identifier, which can be referenced in API endpoints." +export const ResponseCodeInterpreterCallCodeDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.code_interpreter_call_code.delta").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call_code.delta`." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the Upload was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "filename": Schema.String.annotate({ "description": "The name of the file to be uploaded." }), - "bytes": Schema.Number.annotate({ "description": "The intended number of bytes to be uploaded." }).check( - Schema.isInt() - ), - "purpose": Schema.String.annotate({ - "description": - "The intended purpose of the file. [Please refer here](/docs/api-reference/files/object#files/object-purpose) for acceptable values." + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code is being streamed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "delta": Schema.String.annotate({ + "description": "The partial code snippet being streamed by the code interpreter." }), - "status": Schema.Literals(["pending", "completed", "cancelled", "expired"]).annotate({ - "description": "The status of the Upload." + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a partial code snippet is streamed by the code interpreter.", + "identifier": "ResponseCodeInterpreterCallCodeDeltaEvent" +}) +export type ResponseCodeInterpreterCallCodeDoneEvent = { + readonly "type": "response.code_interpreter_call_code.done" + readonly "output_index": number + readonly "item_id": string + readonly "code": string + readonly "sequence_number": number +} +export const ResponseCodeInterpreterCallCodeDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.code_interpreter_call_code.done").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call_code.done`." }), - "expires_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the Upload will expire.", - "format": "unixtime" - }).check(Schema.isInt()), - "object": Schema.optionalKey( - Schema.Literal("upload").annotate({ "description": "The object type, which is always \"upload\"." }) - ), - "file": Schema.optionalKey(Schema.Union([ - Schema.StructWithRest( - Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The file identifier, which can be referenced in the API endpoints." - }), - "bytes": Schema.Number.annotate({ "description": "The size of the file, in bytes." }).check(Schema.isInt()), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the file was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "expires_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the file will expire.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "filename": Schema.String.annotate({ "description": "The name of the file." }), - "object": Schema.Literal("file").annotate({ "description": "The object type, which is always `file`." }), - "purpose": Schema.Literals([ - "assistants", - "assistants_output", - "batch", - "batch_output", - "fine-tune", - "fine-tune-results", - "vision", - "user_data" - ]).annotate({ - "description": - "The intended purpose of the file. Supported values are `assistants`, `assistants_output`, `batch`, `batch_output`, `fine-tune`, `fine-tune-results`, `vision`, and `user_data`." - }), - "status": Schema.Literals(["uploaded", "processed", "error"]).annotate({ - "description": - "Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or `error`." - }), - "status_details": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Deprecated. For details on why a fine-tuning training file failed validation, see the `error` field on `fine_tuning.job`." - }) - ) - }), - [Schema.Record(Schema.String, Schema.Json)] - ).annotate({ - "description": "The `File` object represents a document that has been uploaded to OpenAI.", - "title": "OpenAIFile" - }) - ])) -}).annotate({ "title": "Upload", "description": "The Upload object can accept byte chunks in the form of Parts.\n" }) -export type UploadCertificateRequest = { readonly "name"?: string; readonly "certificate": string } -export const UploadCertificateRequest = Schema.Struct({ - "name": Schema.optionalKey(Schema.String.annotate({ "description": "An optional name for the certificate" })), - "certificate": Schema.String.annotate({ "description": "The certificate content in PEM format" }) + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code is finalized." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "code": Schema.String.annotate({ "description": "The final code snippet output by the code interpreter." }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when the code snippet is finalized by the code interpreter.", + "identifier": "ResponseCodeInterpreterCallCodeDoneEvent" }) -export type UploadPart = { - readonly "id": string - readonly "created_at": number - readonly "upload_id": string - readonly "object": "upload.part" +export type ResponseCodeInterpreterCallCompletedEvent = { + readonly "type": "response.code_interpreter_call.completed" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const UploadPart = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The upload Part unique identifier, which can be referenced in API endpoints." +export const ResponseCodeInterpreterCallCompletedEvent = Schema.Struct({ + "type": Schema.Literal("response.code_interpreter_call.completed").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call.completed`." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the Part was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "upload_id": Schema.String.annotate({ "description": "The ID of the Upload object that this Part was added to." }), - "object": Schema.Literal("upload.part").annotate({ "description": "The object type, which is always `upload.part`." }) + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code interpreter call is completed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) }).annotate({ - "title": "UploadPart", - "description": "The upload Part represents a chunk of bytes we can add to an Upload object.\n" + "description": "Emitted when the code interpreter call is completed.", + "identifier": "ResponseCodeInterpreterCallCompletedEvent" }) -export type UsageAudioSpeechesResult = { - readonly "object": "organization.usage.audio_speeches.result" - readonly "characters": number - readonly "num_model_requests": number - readonly "project_id"?: string | null - readonly "user_id"?: string | null - readonly "api_key_id"?: string | null - readonly "model"?: string | null +export type ResponseCodeInterpreterCallInProgressEvent = { + readonly "type": "response.code_interpreter_call.in_progress" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const UsageAudioSpeechesResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.audio_speeches.result"), - "characters": Schema.Number.annotate({ "description": "The number of characters processed." }).check(Schema.isInt()), - "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( - Schema.isInt() - ), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "user_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." - }), - Schema.Null - ]) +export const ResponseCodeInterpreterCallInProgressEvent = Schema.Struct({ + "type": Schema.Literal("response.code_interpreter_call.in_progress").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call.in_progress`." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code interpreter call is in progress." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a code interpreter call is in progress.", + "identifier": "ResponseCodeInterpreterCallInProgressEvent" +}) +export type ResponseCodeInterpreterCallInterpretingEvent = { + readonly "type": "response.code_interpreter_call.interpreting" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const ResponseCodeInterpreterCallInterpretingEvent = Schema.Struct({ + "type": Schema.Literal("response.code_interpreter_call.interpreting").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call.interpreting`." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code interpreter is interpreting code." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when the code interpreter is actively interpreting the code snippet.", + "identifier": "ResponseCodeInterpreterCallInterpretingEvent" +}) +export type ResponseCompactionCompactingStreamingEvent = { + readonly "type": "response.compaction.compacting" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string +} +export const ResponseCompactionCompactingStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.compaction.compacting").annotate({ + "description": "The type of the event, always `response.compaction.compacting`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "output_index": Schema.Number.annotate({ "description": "The index of the compaction output item." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=model`, this field provides the model name of the grouped usage result." - }), - Schema.Null - ]) + "item_id": Schema.String.annotate({ "description": "The ID of the compaction output item." }) +}).annotate({ + "title": "Response compaction compacting event", + "description": "Emitted when new summary content is sampled for a compaction trigger. Contains no summary content.", + "identifier": "ResponseCompactionCompactingStreamingEvent" +}) +export type ResponseErrorEvent = { + readonly "type": "error" + readonly "code": string | null + readonly "message": string + readonly "param": string | null + readonly "sequence_number": number +} +export const ResponseErrorEvent = Schema.Struct({ + "type": Schema.Literal("error").annotate({ "description": "The type of the event. Always `error`.\n" }), + "code": Schema.Union([Schema.String.annotate({ "description": "The error code.\n" }), Schema.Null]), + "message": Schema.String.annotate({ "description": "The error message.\n" }), + "param": Schema.Union([Schema.String.annotate({ "description": "The error parameter.\n" }), Schema.Null]), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated audio speeches usage details of the specific time bucket." }) -export type UsageAudioTranscriptionsResult = { - readonly "object": "organization.usage.audio_transcriptions.result" - readonly "seconds": number - readonly "num_model_requests": number - readonly "project_id"?: string | null - readonly "user_id"?: string | null - readonly "api_key_id"?: string | null - readonly "model"?: string | null +}).annotate({ "description": "Emitted when an error occurs.", "identifier": "ResponseErrorEvent" }) +export type ResponseFileSearchCallCompletedEvent = { + readonly "type": "response.file_search_call.completed" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const UsageAudioTranscriptionsResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.audio_transcriptions.result"), - "seconds": Schema.Number.annotate({ "description": "The number of seconds processed.", "format": "int64" }).check( - Schema.isInt() - ), - "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( - Schema.isInt() - ), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "user_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=model`, this field provides the model name of the grouped usage result." - }), - Schema.Null - ]) +export const ResponseFileSearchCallCompletedEvent = Schema.Struct({ + "type": Schema.Literal("response.file_search_call.completed").annotate({ + "description": "The type of the event. Always `response.file_search_call.completed`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the file search call is initiated.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the file search call is initiated.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated audio transcriptions usage details of the specific time bucket." }) -export type UsageCodeInterpreterSessionsResult = { - readonly "object": "organization.usage.code_interpreter_sessions.result" - readonly "num_sessions": number - readonly "project_id"?: string | null +}).annotate({ + "description": "Emitted when a file search call is completed (results found).", + "identifier": "ResponseFileSearchCallCompletedEvent" +}) +export type ResponseFileSearchCallInProgressEvent = { + readonly "type": "response.file_search_call.in_progress" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const UsageCodeInterpreterSessionsResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.code_interpreter_sessions.result"), - "num_sessions": Schema.Number.annotate({ "description": "The number of code interpreter sessions." }).check( - Schema.isInt() - ), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) +export const ResponseFileSearchCallInProgressEvent = Schema.Struct({ + "type": Schema.Literal("response.file_search_call.in_progress").annotate({ + "description": "The type of the event. Always `response.file_search_call.in_progress`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the file search call is initiated.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the file search call is initiated.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated code interpreter sessions usage details of the specific time bucket." }) -export type UsageCompletionsResult = { - readonly "object": "organization.usage.completions.result" - readonly "input_tokens": number - readonly "input_cached_tokens"?: number - readonly "output_tokens": number - readonly "input_audio_tokens"?: number - readonly "output_audio_tokens"?: number - readonly "num_model_requests": number - readonly "project_id"?: string | null - readonly "user_id"?: string | null - readonly "api_key_id"?: string | null - readonly "model"?: string | null - readonly "batch"?: boolean | null - readonly "service_tier"?: string | null +}).annotate({ + "description": "Emitted when a file search call is initiated.", + "identifier": "ResponseFileSearchCallInProgressEvent" +}) +export type ResponseFileSearchCallSearchingEvent = { + readonly "type": "response.file_search_call.searching" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const UsageCompletionsResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.completions.result"), - "input_tokens": Schema.Number.annotate({ - "description": - "The aggregated number of text input tokens used, including cached tokens. For customers subscribe to scale tier, this includes scale tier tokens." - }).check(Schema.isInt()), - "input_cached_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The aggregated number of text input tokens that has been cached from previous requests. For customers subscribe to scale tier, this includes scale tier tokens." - }).check(Schema.isInt()) - ), - "output_tokens": Schema.Number.annotate({ - "description": - "The aggregated number of text output tokens used. For customers subscribe to scale tier, this includes scale tier tokens." - }).check(Schema.isInt()), - "input_audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The aggregated number of audio input tokens used, including cached tokens." - }).check(Schema.isInt()) - ), - "output_audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The aggregated number of audio output tokens used." }).check( - Schema.isInt() - ) +export const ResponseFileSearchCallSearchingEvent = Schema.Struct({ + "type": Schema.Literal("response.file_search_call.searching").annotate({ + "description": "The type of the event. Always `response.file_search_call.searching`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the file search call is searching.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the file search call is initiated.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a file search is currently searching.", + "identifier": "ResponseFileSearchCallSearchingEvent" +}) +export type ResponseFunctionCallArgumentsDeltaEvent = { + readonly "type": "response.function_call_arguments.delta" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number + readonly "delta": string +} +export const ResponseFunctionCallArgumentsDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.function_call_arguments.delta").annotate({ + "description": "The type of the event. Always `response.function_call_arguments.delta`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the function-call arguments delta is added to.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the function-call arguments delta is added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( - Schema.isInt() + "delta": Schema.String.annotate({ "description": "The function-call arguments delta that is added.\n" }) +}).annotate({ + "description": "Emitted when there is a partial function-call arguments delta.", + "identifier": "ResponseFunctionCallArgumentsDeltaEvent" +}) +export type ResponseFunctionCallArgumentsDoneEvent = { + readonly "type": "response.function_call_arguments.done" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number + readonly "arguments": string + readonly "name"?: string +} +export const ResponseFunctionCallArgumentsDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.function_call_arguments.done"), + "item_id": Schema.String.annotate({ "description": "The ID of the item." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "user_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." - }), - Schema.Null - ]) + "arguments": Schema.String.annotate({ "description": "The function-call arguments." }), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function that was called." })) +}).annotate({ + "description": "Emitted when function-call arguments are finalized.", + "identifier": "ResponseFunctionCallArgumentsDoneEvent" +}) +export type ResponseShellCallCommandAddedStreamingEvent = { + readonly "type": "response.shell_call_command.added" + readonly "sequence_number": number + readonly "output_index": number + readonly "command_index": number + readonly "command": string +} +export const ResponseShellCallCommandAddedStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_command.added").annotate({ + "description": "The type of the event, always `response.shell_call_command.added`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." - }), - Schema.Null - ]) + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that was added." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=model`, this field provides the model name of the grouped usage result." - }), - Schema.Null - ]) + "command": Schema.String.annotate({ "description": "The shell command that was added." }) +}).annotate({ + "title": "Response shell command added event", + "description": "A streaming event that indicated a shell command was added to a tool call.", + "identifier": "ResponseShellCallCommandAddedStreamingEvent" +}) +export type ResponseShellCallCommandDeltaStreamingEvent = { + readonly "type": "response.shell_call_command.delta" + readonly "sequence_number": number + readonly "output_index": number + readonly "command_index": number + readonly "delta": string + readonly "obfuscation"?: string +} +export const ResponseShellCallCommandDeltaStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_command.delta").annotate({ + "description": "The type of the event, always `response.shell_call_command.delta`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "batch": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": "When `group_by=batch`, this field tells whether the grouped usage result is batch or not." - }), - Schema.Null - ]) + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "service_tier": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=service_tier`, this field provides the service tier of the grouped usage result." - }), - Schema.Null - ]) + "delta": Schema.String.annotate({ "description": "The shell command delta that was appended." }), + "obfuscation": Schema.optionalKey( + Schema.String.annotate({ "description": "An obfuscation string that was added to pad the event payload." }) ) -}).annotate({ "description": "The aggregated completions usage details of the specific time bucket." }) -export type UsageEmbeddingsResult = { - readonly "object": "organization.usage.embeddings.result" - readonly "input_tokens": number - readonly "num_model_requests": number - readonly "project_id"?: string | null - readonly "user_id"?: string | null - readonly "api_key_id"?: string | null - readonly "model"?: string | null +}).annotate({ + "title": "Response shell command delta event", + "description": "A streaming event that indicated a shell command was incrementally updated.", + "identifier": "ResponseShellCallCommandDeltaStreamingEvent" +}) +export type ResponseShellCallCommandDoneStreamingEvent = { + readonly "type": "response.shell_call_command.done" + readonly "sequence_number": number + readonly "output_index": number + readonly "command_index": number + readonly "command": string } -export const UsageEmbeddingsResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.embeddings.result"), - "input_tokens": Schema.Number.annotate({ "description": "The aggregated number of input tokens used." }).check( - Schema.isInt() - ), - "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( - Schema.isInt() +export const ResponseShellCallCommandDoneStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_command.done").annotate({ + "description": "The type of the event, always `response.shell_call_command.done`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that was completed." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "command": Schema.String.annotate({ "description": "The final shell command that was emitted." }) +}).annotate({ + "title": "Response shell command done event", + "description": "A streaming event that indicated a shell command was completed.", + "identifier": "ResponseShellCallCommandDoneStreamingEvent" +}) +export type ShellCallOutputDelta = { readonly "stdout"?: string; readonly "stderr"?: string } +export const ShellCallOutputDelta = Schema.Struct({ + "stdout": Schema.optionalKey(Schema.String.annotate({ "description": "The stdout delta that was emitted." })), + "stderr": Schema.optionalKey(Schema.String.annotate({ "description": "The stderr delta that was emitted." })) +}).annotate({ + "title": "Shell call output delta", + "description": "A delta of stdout/stderr emitted while a shell call was running.", + "identifier": "ShellCallOutputDelta" +}) +export type ResponseReasoningSummaryPartAddedEvent = { + readonly "type": "response.reasoning_summary_part.added" + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "sequence_number": number + readonly "part": { readonly "type": "summary_text"; readonly "text": string } +} +export const ResponseReasoningSummaryPartAddedEvent = Schema.Struct({ + "type": Schema.Literal("response.reasoning_summary_part.added").annotate({ + "description": "The type of the event. Always `response.reasoning_summary_part.added`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the item this summary part is associated with.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this summary part is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary part within the reasoning summary.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "user_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." - }), - Schema.Null - ]) + "part": Schema.Struct({ + "type": Schema.Literal("summary_text").annotate({ + "description": "The type of the summary part. Always `summary_text`." + }), + "text": Schema.String.annotate({ "description": "The text of the summary part." }) + }).annotate({ "description": "The summary part that was added.\n" }) +}).annotate({ + "description": "Emitted when a new reasoning summary part is added.", + "identifier": "ResponseReasoningSummaryPartAddedEvent" +}) +export type ResponseReasoningSummaryPartDoneEvent = { + readonly "type": "response.reasoning_summary_part.done" + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "status"?: "incomplete" + readonly "sequence_number": number + readonly "part": { readonly "type": "summary_text"; readonly "text": string } +} +export const ResponseReasoningSummaryPartDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.reasoning_summary_part.done").annotate({ + "description": "The type of the event. Always `response.reasoning_summary_part.done`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the item this summary part is associated with.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this summary part is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary part within the reasoning summary.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "status": Schema.optionalKey( + Schema.Literal("incomplete").annotate({ + "description": + "The completion status of the summary part. Omitted when the part completed\nnormally and set to `incomplete` when generation was interrupted.\n" + }) ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." - }), - Schema.Null - ]) + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=model`, this field provides the model name of the grouped usage result." - }), - Schema.Null - ]) + "part": Schema.Struct({ + "type": Schema.Literal("summary_text").annotate({ + "description": "The type of the summary part. Always `summary_text`." + }), + "text": Schema.String.annotate({ "description": "The text of the summary part." }) + }).annotate({ "description": "The completed summary part.\n" }) +}).annotate({ + "description": "Emitted when a reasoning summary part is completed.", + "identifier": "ResponseReasoningSummaryPartDoneEvent" +}) +export type ResponseReasoningSummaryTextDeltaEvent = { + readonly "type": "response.reasoning_summary_text.delta" + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "delta": string + readonly "sequence_number": number +} +export const ResponseReasoningSummaryTextDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.reasoning_summary_text.delta").annotate({ + "description": "The type of the event. Always `response.reasoning_summary_text.delta`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the item this summary text delta is associated with.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this summary text delta is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary part within the reasoning summary.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "The text delta that was added to the summary.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated embeddings usage details of the specific time bucket." }) -export type UsageFileSearchCallsResult = { - readonly "object": "organization.usage.file_searches.result" - readonly "num_requests": number - readonly "project_id"?: string | null - readonly "user_id"?: string | null - readonly "api_key_id"?: string | null - readonly "vector_store_id"?: string | null +}).annotate({ + "description": "Emitted when a delta is added to a reasoning summary text.", + "identifier": "ResponseReasoningSummaryTextDeltaEvent" +}) +export type ResponseReasoningSummaryTextDoneEvent = { + readonly "type": "response.reasoning_summary_text.done" + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "text": string + readonly "sequence_number": number } -export const UsageFileSearchCallsResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.file_searches.result"), - "num_requests": Schema.Number.annotate({ "description": "The count of file search calls." }).check(Schema.isInt()), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "user_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "vector_store_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "When `group_by=vector_store_id`, this field provides the vector store ID of the grouped usage result." - }), - Schema.Null - ]) +export const ResponseReasoningSummaryTextDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.reasoning_summary_text.done").annotate({ + "description": "The type of the event. Always `response.reasoning_summary_text.done`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the item this summary text is associated with.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this summary text is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary part within the reasoning summary.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "text": Schema.String.annotate({ "description": "The full text of the completed reasoning summary.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated file search calls usage details of the specific time bucket." }) -export type UsageImagesResult = { - readonly "object": "organization.usage.images.result" - readonly "images": number - readonly "num_model_requests": number - readonly "source"?: string | null - readonly "size"?: string | null - readonly "project_id"?: string | null - readonly "user_id"?: string | null - readonly "api_key_id"?: string | null - readonly "model"?: string | null +}).annotate({ + "description": "Emitted when a reasoning summary text is completed.", + "identifier": "ResponseReasoningSummaryTextDoneEvent" +}) +export type ResponseReasoningTextDeltaEvent = { + readonly "type": "response.reasoning_text.delta" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "delta": string + readonly "sequence_number": number } -export const UsageImagesResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.images.result"), - "images": Schema.Number.annotate({ "description": "The number of images processed." }).check(Schema.isInt()), - "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( - Schema.isInt() - ), - "source": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "When `group_by=source`, this field provides the source of the grouped usage result, possible values are `image.generation`, `image.edit`, `image.variation`." - }), - Schema.Null - ]) - ), - "size": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=size`, this field provides the image size of the grouped usage result." - }), - Schema.Null - ]) - ), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "user_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=model`, this field provides the model name of the grouped usage result." - }), - Schema.Null - ]) +export const ResponseReasoningTextDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.reasoning_text.delta").annotate({ + "description": "The type of the event. Always `response.reasoning_text.delta`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the item this reasoning text delta is associated with.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this reasoning text delta is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the reasoning content part this delta is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "The text delta that was added to the reasoning content.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated images usage details of the specific time bucket." }) -export type UsageModerationsResult = { - readonly "object": "organization.usage.moderations.result" - readonly "input_tokens": number - readonly "num_model_requests": number - readonly "project_id"?: string | null - readonly "user_id"?: string | null - readonly "api_key_id"?: string | null - readonly "model"?: string | null +}).annotate({ + "description": "Emitted when a delta is added to a reasoning text.", + "identifier": "ResponseReasoningTextDeltaEvent" +}) +export type ResponseReasoningTextDoneEvent = { + readonly "type": "response.reasoning_text.done" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "text": string + readonly "sequence_number": number } -export const UsageModerationsResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.moderations.result"), - "input_tokens": Schema.Number.annotate({ "description": "The aggregated number of input tokens used." }).check( - Schema.isInt() - ), - "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( - Schema.isInt() - ), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) +export const ResponseReasoningTextDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.reasoning_text.done").annotate({ + "description": "The type of the event. Always `response.reasoning_text.done`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the item this reasoning text is associated with.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this reasoning text is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ "description": "The index of the reasoning content part.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "user_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=model`, this field provides the model name of the grouped usage result." - }), - Schema.Null - ]) + "text": Schema.String.annotate({ "description": "The full text of the completed reasoning content.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated moderations usage details of the specific time bucket." }) -export type UsageVectorStoresResult = { - readonly "object": "organization.usage.vector_stores.result" - readonly "usage_bytes": number - readonly "project_id"?: string | null +}).annotate({ + "description": "Emitted when a reasoning text is completed.", + "identifier": "ResponseReasoningTextDoneEvent" +}) +export type ResponseRefusalDeltaEvent = { + readonly "type": "response.refusal.delta" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "delta": string + readonly "sequence_number": number } -export const UsageVectorStoresResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.vector_stores.result"), - "usage_bytes": Schema.Number.annotate({ "description": "The vector stores usage in bytes." }).check(Schema.isInt()), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) +export const ResponseRefusalDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.refusal.delta").annotate({ + "description": "The type of the event. Always `response.refusal.delta`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the refusal text is added to.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the refusal text is added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part that the refusal text is added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "The refusal text that is added.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated vector stores usage details of the specific time bucket." }) -export type UsageWebSearchCallsResult = { - readonly "object": "organization.usage.web_searches.result" - readonly "num_model_requests": number - readonly "num_requests": number - readonly "project_id"?: string | null - readonly "user_id"?: string | null - readonly "api_key_id"?: string | null - readonly "model"?: string | null - readonly "context_level"?: string | null +}).annotate({ + "description": "Emitted when there is a partial refusal text.", + "identifier": "ResponseRefusalDeltaEvent" +}) +export type ResponseRefusalDoneEvent = { + readonly "type": "response.refusal.done" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "refusal": string + readonly "sequence_number": number } -export const UsageWebSearchCallsResult = Schema.Struct({ - "object": Schema.Literal("organization.usage.web_searches.result"), - "num_model_requests": Schema.Number.annotate({ "description": "The count of model requests." }).check(Schema.isInt()), - "num_requests": Schema.Number.annotate({ "description": "The count of web search calls." }).check(Schema.isInt()), - "project_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "user_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "api_key_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." - }), - Schema.Null - ]) - ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "When `group_by=model`, this field provides the model name of the grouped usage result." - }), - Schema.Null - ]) - ), - "context_level": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "When `group_by=context_level`, this field provides the search context size of the grouped usage result." - }), - Schema.Null - ]) +export const ResponseRefusalDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.refusal.done").annotate({ + "description": "The type of the event. Always `response.refusal.done`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the refusal text is finalized.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the refusal text is finalized.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part that the refusal text is finalized.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "refusal": Schema.String.annotate({ "description": "The refusal text that is finalized.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "The aggregated web search calls usage details of the specific time bucket." }) -export type User = { - readonly "object": "organization.user" - readonly "id": string - readonly "name"?: string | null - readonly "email"?: string | null - readonly "role"?: string | null - readonly "added_at": number - readonly "is_default"?: boolean - readonly "created"?: number - readonly "user"?: { - readonly "object": "user" - readonly "id": string - readonly "email"?: string | null - readonly "name"?: string | null - readonly "picture"?: string | null - readonly "enabled"?: boolean | null - readonly "banned"?: boolean | null - readonly "banned_at"?: number | null - } - readonly "is_service_account"?: boolean - readonly "is_scale_tier_authorized_purchaser"?: boolean | null - readonly "is_scim_managed"?: boolean - readonly "api_key_last_used_at"?: number | null - readonly "technical_level"?: string | null - readonly "developer_persona"?: string | null - readonly "projects"?: { - readonly "object": "list" - readonly "data": ReadonlyArray< - { readonly "id"?: string | null; readonly "name"?: string | null; readonly "role"?: string | null } - > - } | null +}).annotate({ "description": "Emitted when refusal text is finalized.", "identifier": "ResponseRefusalDoneEvent" }) +export type ResponseLogProb = { + readonly "token": string + readonly "logprob": number + readonly "top_logprobs"?: ReadonlyArray<{ readonly "token"?: string; readonly "logprob"?: number }> } -export const User = Schema.Struct({ - "object": Schema.Literal("organization.user").annotate({ - "description": "The object type, which is always `organization.user`" - }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the user" }) - ), - "email": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The email address of the user" }) - ), - "role": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "`owner` or `reader`" }) - ), - "added_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the user was added.", - "format": "unixtime" - }).check(Schema.isInt()), - "is_default": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether this is the organization's default user." }) - ), - "created": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the user was created.", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "user": Schema.optionalKey( - Schema.Struct({ - "object": Schema.Literal("user"), - "id": Schema.String, - "email": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "name": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "picture": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "enabled": Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), - "banned": Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), - "banned_at": Schema.optionalKey( - Schema.Union([Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt()), Schema.Null]) - ) - }).annotate({ "description": "Nested user details." }) - ), - "is_service_account": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether the user is a service account." }) - ), - "is_scale_tier_authorized_purchaser": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": "Whether the user is an authorized purchaser for Scale Tier." - }) - ), - "is_scim_managed": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether the user is managed through SCIM." }) - ), - "api_key_last_used_at": Schema.optionalKey( - Schema.Union([Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt()), Schema.Null]).annotate({ - "description": "The Unix timestamp (in seconds) of the user's last API key usage." - }) - ), - "technical_level": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The technical level metadata for the user." }) - ), - "developer_persona": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "The developer persona metadata for the user." - }) +export const ResponseLogProb = Schema.Struct({ + "token": Schema.String.annotate({ "description": "A possible text token." }), + "logprob": Schema.Number.annotate({ "description": "The log probability of this token.\n" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) ), - "projects": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array( - Schema.Struct({ - "id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "name": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "role": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])) - }) + "top_logprobs": Schema.optionalKey( + Schema.Array(Schema.Struct({ + "token": Schema.optionalKey(Schema.String.annotate({ "description": "A possible text token." })), + "logprob": Schema.optionalKey( + Schema.Number.annotate({ "description": "The log probability of this token." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) ) - }), - Schema.Null - ]).annotate({ "description": "Projects associated with the user, if included." }) - ) -}).annotate({ "description": "Represents an individual `user` within an organization." }) -export type UserDeleteResponse = { - readonly "object": "organization.user.deleted" - readonly "id": string - readonly "deleted": boolean -} -export const UserDeleteResponse = Schema.Struct({ - "object": Schema.Literal("organization.user.deleted"), - "id": Schema.String, - "deleted": Schema.Boolean -}) -export type UserRoleUpdateRequest = { - readonly "role"?: string | null - readonly "role_id"?: string | null - readonly "technical_level"?: string | null - readonly "developer_persona"?: string | null -} -export const UserRoleUpdateRequest = Schema.Struct({ - "role": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "`owner` or `reader`" }) - ), - "role_id": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Role ID to assign to the user." }) - ), - "technical_level": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Technical level metadata." }) - ), - "developer_persona": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "Developer persona metadata." }) + ) + })).annotate({ "description": "The log probabilities of up to 20 of the most likely tokens.\n" }) ) +}).annotate({ + "description": + "A logprob is the logarithmic probability that the model assigns to producing \na particular token at a given position in the sequence. Less-negative (higher) \nlogprob values indicate greater model confidence in that token choice.\n", + "identifier": "ResponseLogProb" }) -export type VadConfig = { - readonly "type": "server_vad" - readonly "prefix_padding_ms"?: number - readonly "silence_duration_ms"?: number - readonly "threshold"?: number +export type ResponseWebSearchCallCompletedEvent = { + readonly "type": "response.web_search_call.completed" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const VadConfig = Schema.Struct({ - "type": Schema.Literal("server_vad").annotate({ - "description": "Must be set to `server_vad` to enable manual chunking using server side VAD." +export const ResponseWebSearchCallCompletedEvent = Schema.Struct({ + "type": Schema.Literal("response.web_search_call.completed").annotate({ + "description": "The type of the event. Always `response.web_search_call.completed`.\n" }), - "prefix_padding_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Amount of audio to include before the VAD detected speech (in \nmilliseconds).\n" - }).check(Schema.isInt()) - ), - "silence_duration_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Duration of silence to detect speech stop (in milliseconds).\nWith shorter values the model will respond more quickly, \nbut may jump in on short pauses from the user.\n" - }).check(Schema.isInt()) - ), - "threshold": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Sensitivity threshold (0.0 to 1.0) for voice activity detection. A \nhigher threshold will require louder audio to activate the model, and \nthus might perform better in noisy environments.\n" - }).check(Schema.isFinite()) - ) + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the web search call is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "Unique ID for the output item associated with the web search call.\n" + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the web search call being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a web search call is completed.", + "identifier": "ResponseWebSearchCallCompletedEvent" }) -export type VectorStoreExpirationAfter = { readonly "anchor": "last_active_at"; readonly "days": number } -export const VectorStoreExpirationAfter = Schema.Struct({ - "anchor": Schema.Literal("last_active_at").annotate({ - "description": "Anchor timestamp after which the expiration policy applies. Supported anchors: `last_active_at`." +export type ResponseWebSearchCallInProgressEvent = { + readonly "type": "response.web_search_call.in_progress" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const ResponseWebSearchCallInProgressEvent = Schema.Struct({ + "type": Schema.Literal("response.web_search_call.in_progress").annotate({ + "description": "The type of the event. Always `response.web_search_call.in_progress`.\n" }), - "days": Schema.Number.annotate({ - "description": "The number of days after the anchor time that the vector store will expire." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(365)) -}).annotate({ "title": "Vector store expiration policy", "description": "The expiration policy for a vector store." }) -export type VectorStoreFileAttributes = {} | null -export const VectorStoreFileAttributes = Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard. Keys are strings\nwith a maximum length of 64 characters. Values are strings with a maximum\nlength of 512 characters, booleans, or numbers.\n" - }).check(Schema.isMaxProperties(16)).check(Schema.isPropertyNames(Schema.String.check(Schema.isMaxLength(64)))), - Schema.Null -]) -export type VectorStoreFileBatchObject = { - readonly "id": string - readonly "object": "vector_store.files_batch" - readonly "created_at": number - readonly "vector_store_id": string - readonly "status": "in_progress" | "completed" | "cancelled" | "failed" - readonly "file_counts": { - readonly "in_progress": number - readonly "completed": number - readonly "failed": number - readonly "cancelled": number - readonly "total": number - } + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the web search call is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "Unique ID for the output item associated with the web search call.\n" + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the web search call being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a web search call is initiated.", + "identifier": "ResponseWebSearchCallInProgressEvent" +}) +export type ResponseWebSearchCallSearchingEvent = { + readonly "type": "response.web_search_call.searching" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const VectorStoreFileBatchObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), - "object": Schema.Literal("vector_store.files_batch").annotate({ - "description": "The object type, which is always `vector_store.file_batch`." +export const ResponseWebSearchCallSearchingEvent = Schema.Struct({ + "type": Schema.Literal("response.web_search_call.searching").annotate({ + "description": "The type of the event. Always `response.web_search_call.searching`.\n" }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the vector store files batch was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "vector_store_id": Schema.String.annotate({ - "description": - "The ID of the [vector store](/docs/api-reference/vector-stores/object) that the [File](/docs/api-reference/files) is attached to." + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the web search call is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "Unique ID for the output item associated with the web search call.\n" }), - "status": Schema.Literals(["in_progress", "completed", "cancelled", "failed"]).annotate({ - "description": - "The status of the vector store files batch, which can be either `in_progress`, `completed`, `cancelled` or `failed`." + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the web search call being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a web search call is executing.", + "identifier": "ResponseWebSearchCallSearchingEvent" +}) +export type ResponseImageGenCallCompletedEvent = { + readonly "type": "response.image_generation_call.completed" + readonly "output_index": number + readonly "sequence_number": number + readonly "item_id": string +} +export const ResponseImageGenCallCompletedEvent = Schema.Struct({ + "type": Schema.Literal("response.image_generation_call.completed").annotate({ + "description": "The type of the event. Always 'response.image_generation_call.completed'." }), - "file_counts": Schema.Struct({ - "in_progress": Schema.Number.annotate({ "description": "The number of files that are currently being processed." }) - .check(Schema.isInt()), - "completed": Schema.Number.annotate({ "description": "The number of files that have been processed." }).check( - Schema.isInt() - ), - "failed": Schema.Number.annotate({ "description": "The number of files that have failed to process." }).check( - Schema.isInt() - ), - "cancelled": Schema.Number.annotate({ "description": "The number of files that where cancelled." }).check( - Schema.isInt() - ), - "total": Schema.Number.annotate({ "description": "The total number of files." }).check(Schema.isInt()) + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the image generation item being processed." }) -}).annotate({ "title": "Vector store file batch", "description": "A batch of files attached to a vector store." }) -export type VectorStoreFileContentResponse = { - readonly "object": "vector_store.file_content.page" - readonly "data": ReadonlyArray<{ readonly "type"?: string; readonly "text"?: string }> - readonly "has_more": boolean - readonly "next_page": string | null +}).annotate({ + "title": "ResponseImageGenCallCompletedEvent", + "description": "Emitted when an image generation tool call has completed and the final image is available.\n", + "identifier": "ResponseImageGenCallCompletedEvent" +}) +export type ResponseImageGenCallGeneratingEvent = { + readonly "type": "response.image_generation_call.generating" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const VectorStoreFileContentResponse = Schema.Struct({ - "object": Schema.Literal("vector_store.file_content.page").annotate({ - "description": "The object type, which is always `vector_store.file_content.page`" +export const ResponseImageGenCallGeneratingEvent = Schema.Struct({ + "type": Schema.Literal("response.image_generation_call.generating").annotate({ + "description": "The type of the event. Always 'response.image_generation_call.generating'." }), - "data": Schema.Array( - Schema.Struct({ - "type": Schema.optionalKey( - Schema.String.annotate({ "description": "The content type (currently only `\"text\"`)" }) - ), - "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content" })) - }) - ).annotate({ "description": "Parsed content of the file." }), - "has_more": Schema.Boolean.annotate({ "description": "Indicates if there are more content pages to fetch." }), - "next_page": Schema.Union([ - Schema.String.annotate({ "description": "The token for the next page, if any." }), - Schema.Null - ]) -}).annotate({ "description": "Represents the parsed content of a vector store file." }) -export type VectorStoreSearchResultContentObject = { readonly "type": "text"; readonly "text": string } -export const VectorStoreSearchResultContentObject = Schema.Struct({ - "type": Schema.Literal("text").annotate({ "description": "The type of content." }), - "text": Schema.String.annotate({ "description": "The text content returned from search." }) -}) -export type Verbosity = "low" | "medium" | "high" | null -export const Verbosity = Schema.Union([ - Schema.Literals(["low", "medium", "high"]).annotate({ - "description": - "Constrains the verbosity of the model's response. Lower values will result in\nmore concise responses, while higher values will result in more verbose responses.\nCurrently supported values are `low`, `medium`, and `high`.\n" + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the image generation item being processed." }), - Schema.Null -]) -export type VoiceConsentDeletedResource = { - readonly "id": string - readonly "object": "audio.voice_consent" - readonly "deleted": boolean -} -export const VoiceConsentDeletedResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The consent recording identifier." }), - "object": Schema.Literal("audio.voice_consent"), - "deleted": Schema.Boolean + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the image generation item being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "title": "ResponseImageGenCallGeneratingEvent", + "description": "Emitted when an image generation tool call is actively generating an image (intermediate state).\n", + "identifier": "ResponseImageGenCallGeneratingEvent" }) -export type VoiceConsentResource = { - readonly "object": "audio.voice_consent" - readonly "id": string - readonly "name": string - readonly "language": string - readonly "created_at": number +export type ResponseImageGenCallInProgressEvent = { + readonly "type": "response.image_generation_call.in_progress" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number } -export const VoiceConsentResource = Schema.Struct({ - "object": Schema.Literal("audio.voice_consent").annotate({ - "description": "The object type, which is always `audio.voice_consent`." +export const ResponseImageGenCallInProgressEvent = Schema.Struct({ + "type": Schema.Literal("response.image_generation_call.in_progress").annotate({ + "description": "The type of the event. Always 'response.image_generation_call.in_progress'." }), - "id": Schema.String.annotate({ "description": "The consent recording identifier." }), - "name": Schema.String.annotate({ "description": "The label provided when the consent recording was uploaded." }), - "language": Schema.String.annotate({ - "description": "The BCP 47 language tag for the consent phrase (for example, `en-US`)." + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the image generation item being processed." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the consent recording was created.", - "format": "unixtime" - }).check(Schema.isInt()) + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the image generation item being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) }).annotate({ - "title": "Voice consent", - "description": "A consent recording used to authorize creation of a custom voice." + "title": "ResponseImageGenCallInProgressEvent", + "description": "Emitted when an image generation tool call is in progress.\n", + "identifier": "ResponseImageGenCallInProgressEvent" }) -export type VoiceIdsShared = - | string - | "alloy" - | "ash" - | "ballad" - | "coral" - | "echo" - | "sage" - | "shimmer" - | "verse" - | "marin" - | "cedar" -export const VoiceIdsShared = Schema.Union([ - Schema.String, - Schema.Literals(["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"]) -]) -export type VoiceResource = { - readonly "object": "audio.voice" - readonly "id": string - readonly "name": string - readonly "created_at": number +export type ResponseImageGenCallPartialImageEvent = { + readonly "type": "response.image_generation_call.partial_image" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number + readonly "partial_image_index": number + readonly "partial_image_b64": string + readonly "size"?: string + readonly "quality"?: string + readonly "background"?: string + readonly "output_format"?: string } -export const VoiceResource = Schema.Struct({ - "object": Schema.Literal("audio.voice").annotate({ - "description": "The object type, which is always `audio.voice`." +export const ResponseImageGenCallPartialImageEvent = Schema.Struct({ + "type": Schema.Literal("response.image_generation_call.partial_image").annotate({ + "description": "The type of the event. Always 'response.image_generation_call.partial_image'." }), - "id": Schema.String.annotate({ "description": "The voice identifier, which can be referenced in API endpoints." }), - "name": Schema.String.annotate({ "description": "The name of the voice." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the voice was created.", - "format": "unixtime" - }).check(Schema.isInt()) -}).annotate({ "title": "Voice", "description": "A custom voice that can be used for audio output." }) -export type WebSearchApproximateLocation = { - readonly "type"?: "approximate" - readonly "country"?: string | null - readonly "region"?: string | null - readonly "city"?: string | null - readonly "timezone"?: string | null -} | null -export const WebSearchApproximateLocation = Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("approximate").annotate({ - "description": "The type of location approximation. Always `approximate`." - }) - ), - "country": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`." - }), - Schema.Null - ]) - ), - "region": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "Free text input for the region of the user, e.g. `California`." }), - Schema.Null - ]) - ), - "city": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "Free text input for the city of the user, e.g. `San Francisco`." }), - Schema.Null - ]) - ), - "timezone": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`." - }), - Schema.Null - ]) - ) - }).annotate({ "title": "Web search approximate location", "description": "The approximate location of the user.\n" }), - Schema.Null -]) -export type WebSearchContextSize = "low" | "medium" | "high" -export const WebSearchContextSize = Schema.Literals(["low", "medium", "high"]).annotate({ - "description": - "High level guidance for the amount of context window space to use for the \nsearch. One of `low`, `medium`, or `high`. `medium` is the default.\n" + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the image generation item being processed." + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the image generation item being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "partial_image_index": Schema.Number.annotate({ + "description": "0-based index for the partial image (backend is 1-based, but this is 0-based for the user)." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "partial_image_b64": Schema.String.annotate({ + "description": "Base64-encoded partial image data, suitable for rendering as an image." + }), + "size": Schema.optionalKey(Schema.String.annotate({ "description": "The image size that was used." })), + "quality": Schema.optionalKey(Schema.String.annotate({ "description": "The image quality that was used." })), + "background": Schema.optionalKey(Schema.String.annotate({ "description": "The background setting that was used." })), + "output_format": Schema.optionalKey(Schema.String.annotate({ "description": "The output format that was used." })) +}).annotate({ + "title": "ResponseImageGenCallPartialImageEvent", + "description": "Emitted when a partial image is available during image generation streaming.\n", + "identifier": "ResponseImageGenCallPartialImageEvent" }) -export type WebSearchLocation = { - readonly "country"?: string - readonly "region"?: string - readonly "city"?: string - readonly "timezone"?: string -} -export const WebSearchLocation = Schema.Struct({ - "country": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The two-letter \n[ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user,\ne.g. `US`.\n" - }) - ), - "region": Schema.optionalKey( - Schema.String.annotate({ "description": "Free text input for the region of the user, e.g. `California`.\n" }) - ), - "city": Schema.optionalKey( - Schema.String.annotate({ "description": "Free text input for the city of the user, e.g. `San Francisco`.\n" }) - ), - "timezone": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The [IANA timezone](https://timeapi.io/documentation/iana-timezones) \nof the user, e.g. `America/Los_Angeles`.\n" - }) - ) -}).annotate({ "title": "Web search location", "description": "Approximate location parameters for the search." }) -export type WebSearchToolCall = { - readonly "id": string - readonly "type": "web_search_call" - readonly "status": "in_progress" | "searching" | "completed" | "failed" | "incomplete" - readonly "action"?: - | { - readonly "type": "search" - readonly "query"?: string - readonly "queries"?: ReadonlyArray - readonly "sources"?: ReadonlyArray< - { readonly "type": "url"; readonly "url": string } | { readonly "type": "api"; readonly "name": string } - > - } - | { readonly "type": "open_page"; readonly "url"?: string | null } - | { readonly "type": "find_in_page"; readonly "url": string; readonly "pattern": string } +export type ResponseMCPCallArgumentsDeltaEvent = { + readonly "type": "response.mcp_call_arguments.delta" + readonly "output_index": number + readonly "item_id": string + readonly "delta": string + readonly "sequence_number": number } -export const WebSearchToolCall = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique ID of the web search tool call.\n" }), - "type": Schema.Literal("web_search_call").annotate({ - "description": "The type of the web search tool call. Always `web_search_call`.\n" +export const ResponseMCPCallArgumentsDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.mcp_call_arguments.delta").annotate({ + "description": "The type of the event. Always 'response.mcp_call_arguments.delta'." }), - "status": Schema.Literals(["in_progress", "searching", "completed", "failed", "incomplete"]).annotate({ - "description": "The status of the web search tool call.\n" + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the MCP tool call item being processed." }), - "action": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("search").annotate({ "description": "The action type.\n" }), - "query": Schema.optionalKey(Schema.String.annotate({ "description": "[DEPRECATED] The search query.\n" })), - "queries": Schema.optionalKey( - Schema.Array(Schema.String.annotate({ "description": "A search query.\n" })).annotate({ - "title": "Search queries", - "description": "The search queries.\n" - }) - ), - "sources": Schema.optionalKey( - Schema.Array( - Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("url").annotate({ "description": "The type of source. Always `url`.\n" }), - "url": Schema.String.annotate({ "description": "The URL of the source.\n", "format": "uri" }) - }).annotate({ "title": "Web search source", "description": "A source used in the search.\n" }), - Schema.Struct({ - "type": Schema.Literal("api").annotate({ "description": "The type of source. Always `api`.\n" }), - "name": Schema.String.annotate({ - "description": "The name of the API source, such as `oai-weather`, `oai-sports`, or `oai-finance`.\n" - }) - }).annotate({ "title": "Web search API source", "description": "An API source used in the search.\n" }) - ]) - ).annotate({ "title": "Web search sources", "description": "The sources used in the search.\n" }) - ) - }).annotate({ - "title": "Search action", - "description": - "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" - }), - Schema.Struct({ - "type": Schema.Literal("open_page").annotate({ "description": "The action type. Always `open_page`.\n" }), - "url": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "format": "uri" }), Schema.Null]).annotate({ - "description": "The URL opened by the model.\n" - }) - ) - }).annotate({ - "title": "Open page action", - "description": - "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" - }), - Schema.Struct({ - "type": Schema.Literal("find_in_page").annotate({ "description": "The action type.\n" }), - "url": Schema.String.annotate({ - "description": "The URL of the page searched for the pattern.\n", - "format": "uri" - }), - "pattern": Schema.String.annotate({ "description": "The pattern or text to search for within the page.\n" }) - }).annotate({ - "title": "Find action", - "description": - "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" - }) - ], { mode: "oneOf" })) + "delta": Schema.String.annotate({ + "description": "A JSON string containing the partial update to the arguments for the MCP tool call.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) }).annotate({ - "title": "Web search tool call", - "description": - "The results of a web search tool call. See the\n[web search guide](/docs/guides/tools-web-search) for more information.\n" + "title": "ResponseMCPCallArgumentsDeltaEvent", + "description": "Emitted when there is a delta (partial update) to the arguments of an MCP tool call.\n", + "identifier": "ResponseMCPCallArgumentsDeltaEvent" }) -export type SkillReferenceParam = { - readonly "type": "skill_reference" - readonly "skill_id": string - readonly "version"?: string +export type ResponseMCPCallArgumentsDoneEvent = { + readonly "type": "response.mcp_call_arguments.done" + readonly "output_index": number + readonly "item_id": string + readonly "arguments": string + readonly "sequence_number": number } -export const SkillReferenceParam = Schema.Struct({ - "type": Schema.Literal("skill_reference").annotate({ - "description": "References a skill created with the /v1/skills endpoint." +export const ResponseMCPCallArgumentsDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.mcp_call_arguments.done").annotate({ + "description": "The type of the event. Always 'response.mcp_call_arguments.done'." }), - "skill_id": Schema.String.annotate({ "description": "The ID of the referenced skill." }).check(Schema.isMinLength(1)) - .check(Schema.isMaxLength(64)), - "version": Schema.optionalKey( - Schema.String.annotate({ - "description": "Optional skill version. Use a positive integer or 'latest'. Omit for default." - }) + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the MCP tool call item being processed." + }), + "arguments": Schema.String.annotate({ + "description": "A JSON string containing the finalized arguments for the MCP tool call.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) +}).annotate({ + "title": "ResponseMCPCallArgumentsDoneEvent", + "description": "Emitted when the arguments for an MCP tool call are finalized.\n", + "identifier": "ResponseMCPCallArgumentsDoneEvent" }) -export type InlineSkillParam = { - readonly "type": "inline" - readonly "name": string - readonly "description": string - readonly "source": { readonly "type": "base64"; readonly "media_type": "application/zip"; readonly "data": string } +export type ResponseMCPCallCompletedEvent = { + readonly "type": "response.mcp_call.completed" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number } -export const InlineSkillParam = Schema.Struct({ - "type": Schema.Literal("inline").annotate({ "description": "Defines an inline skill for this request." }), - "name": Schema.String.annotate({ "description": "The name of the skill." }), - "description": Schema.String.annotate({ "description": "The description of the skill." }), - "source": Schema.Struct({ - "type": Schema.Literal("base64").annotate({ - "description": "The type of the inline skill source. Must be `base64`." - }), - "media_type": Schema.Literal("application/zip").annotate({ - "description": "The media type of the inline skill payload. Must be `application/zip`." - }), - "data": Schema.String.annotate({ "description": "Base64-encoded skill zip bundle." }).check(Schema.isMinLength(1)) - .check(Schema.isMaxLength(70254592)) - }).annotate({ "description": "Inline skill payload" }) -}) -export type ContainerNetworkPolicyDisabledParam = { readonly "type": "disabled" } -export const ContainerNetworkPolicyDisabledParam = Schema.Struct({ - "type": Schema.Literal("disabled").annotate({ "description": "Disable outbound network access. Always `disabled`." }) +export const ResponseMCPCallCompletedEvent = Schema.Struct({ + "type": Schema.Literal("response.mcp_call.completed").annotate({ + "description": "The type of the event. Always 'response.mcp_call.completed'." + }), + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that completed." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that completed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPCallCompletedEvent", + "description": "Emitted when an MCP tool call has completed successfully.\n", + "identifier": "ResponseMCPCallCompletedEvent" }) -export type ContainerNetworkPolicyDomainSecretParam = { - readonly "domain": string - readonly "name": string - readonly "value": string +export type ResponseMCPCallFailedEvent = { + readonly "type": "response.mcp_call.failed" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number } -export const ContainerNetworkPolicyDomainSecretParam = Schema.Struct({ - "domain": Schema.String.annotate({ "description": "The domain associated with the secret." }).check( - Schema.isMinLength(1) - ), - "name": Schema.String.annotate({ "description": "The name of the secret to inject for the domain." }).check( - Schema.isMinLength(1) +export const ResponseMCPCallFailedEvent = Schema.Struct({ + "type": Schema.Literal("response.mcp_call.failed").annotate({ + "description": "The type of the event. Always 'response.mcp_call.failed'." + }), + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that failed." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that failed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "value": Schema.String.annotate({ "description": "The secret value to inject for the domain." }).check( - Schema.isMinLength(1) - ).check(Schema.isMaxLength(10485760)) -}) -export type IncludeEnum = - | "file_search_call.results" - | "web_search_call.results" - | "web_search_call.action.sources" - | "message.input_image.image_url" - | "computer_call_output.output.image_url" - | "code_interpreter_call.outputs" - | "reasoning.encrypted_content" - | "message.output_text.logprobs" -export const IncludeEnum = Schema.Literals([ - "file_search_call.results", - "web_search_call.results", - "web_search_call.action.sources", - "message.input_image.image_url", - "computer_call_output.output.image_url", - "code_interpreter_call.outputs", - "reasoning.encrypted_content", - "message.output_text.logprobs" -]).annotate({ - "description": - "Specify additional output data to include in the model response. Currently supported values are:\n- `web_search_call.results`: Include the search results of the web search tool call.\n- `web_search_call.action.sources`: Include the sources of the web search tool call.\n- `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items.\n- `computer_call_output.output.image_url`: Include image urls from the computer call output.\n- `file_search_call.results`: Include the search results of the file search tool call.\n- `message.input_image.image_url`: Include image urls from the input message.\n- `message.output_text.logprobs`: Include logprobs with assistant messages.\n- `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program)." + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPCallFailedEvent", + "description": "Emitted when an MCP tool call has failed.\n", + "identifier": "ResponseMCPCallFailedEvent" }) -export type InputTextContent = { readonly "type": "input_text"; readonly "text": string } -export const InputTextContent = Schema.Struct({ - "type": Schema.Literal("input_text").annotate({ "description": "The type of the input item. Always `input_text`." }), - "text": Schema.String.annotate({ "description": "The text input to the model." }) -}).annotate({ "title": "Input text", "description": "A text input to the model." }) -export type FileCitationBody = { - readonly "type": "file_citation" - readonly "file_id": string - readonly "index": number - readonly "filename": string +export type ResponseMCPCallInProgressEvent = { + readonly "type": "response.mcp_call.in_progress" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string } -export const FileCitationBody = Schema.Struct({ - "type": Schema.Literal("file_citation").annotate({ - "description": "The type of the file citation. Always `file_citation`." +export const ResponseMCPCallInProgressEvent = Schema.Struct({ + "type": Schema.Literal("response.mcp_call.in_progress").annotate({ + "description": "The type of the event. Always 'response.mcp_call.in_progress'." }), - "file_id": Schema.String.annotate({ "description": "The ID of the file." }), - "index": Schema.Number.annotate({ "description": "The index of the file in the list of files." }).check( - Schema.isInt() + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "filename": Schema.String.annotate({ "description": "The filename of the file cited." }) -}).annotate({ "title": "File citation", "description": "A citation to a file." }) -export type UrlCitationBody = { - readonly "type": "url_citation" - readonly "url": string - readonly "start_index": number - readonly "end_index": number - readonly "title": string + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the MCP tool call item being processed." + }) +}).annotate({ + "title": "ResponseMCPCallInProgressEvent", + "description": "Emitted when an MCP tool call is in progress.\n", + "identifier": "ResponseMCPCallInProgressEvent" +}) +export type ResponseMCPListToolsCompletedEvent = { + readonly "type": "response.mcp_list_tools.completed" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number } -export const UrlCitationBody = Schema.Struct({ - "type": Schema.Literal("url_citation").annotate({ - "description": "The type of the URL citation. Always `url_citation`." +export const ResponseMCPListToolsCompletedEvent = Schema.Struct({ + "type": Schema.Literal("response.mcp_list_tools.completed").annotate({ + "description": "The type of the event. Always 'response.mcp_list_tools.completed'." }), - "url": Schema.String.annotate({ "description": "The URL of the web resource.", "format": "uri" }), - "start_index": Schema.Number.annotate({ - "description": "The index of the first character of the URL citation in the message." - }).check(Schema.isInt()), - "end_index": Schema.Number.annotate({ - "description": "The index of the last character of the URL citation in the message." - }).check(Schema.isInt()), - "title": Schema.String.annotate({ "description": "The title of the web resource." }) + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that produced this output." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was processed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) }).annotate({ - "title": "URL citation", - "description": "A citation for a web resource used to generate a model response." + "title": "ResponseMCPListToolsCompletedEvent", + "description": "Emitted when the list of available MCP tools has been successfully retrieved.\n", + "identifier": "ResponseMCPListToolsCompletedEvent" }) -export type ContainerFileCitationBody = { - readonly "type": "container_file_citation" - readonly "container_id": string - readonly "file_id": string - readonly "start_index": number - readonly "end_index": number - readonly "filename": string +export type ResponseMCPListToolsFailedEvent = { + readonly "type": "response.mcp_list_tools.failed" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number } -export const ContainerFileCitationBody = Schema.Struct({ - "type": Schema.Literal("container_file_citation").annotate({ - "description": "The type of the container file citation. Always `container_file_citation`." +export const ResponseMCPListToolsFailedEvent = Schema.Struct({ + "type": Schema.Literal("response.mcp_list_tools.failed").annotate({ + "description": "The type of the event. Always 'response.mcp_list_tools.failed'." }), - "container_id": Schema.String.annotate({ "description": "The ID of the container file." }), - "file_id": Schema.String.annotate({ "description": "The ID of the file." }), - "start_index": Schema.Number.annotate({ - "description": "The index of the first character of the container file citation in the message." - }).check(Schema.isInt()), - "end_index": Schema.Number.annotate({ - "description": "The index of the last character of the container file citation in the message." - }).check(Schema.isInt()), - "filename": Schema.String.annotate({ "description": "The filename of the container file cited." }) + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that failed." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that failed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) }).annotate({ - "title": "Container file citation", - "description": "A citation for a container file used to generate a model response." + "title": "ResponseMCPListToolsFailedEvent", + "description": "Emitted when the attempt to list available MCP tools has failed.\n", + "identifier": "ResponseMCPListToolsFailedEvent" }) -export type TopLogProb = { - readonly "token": string - readonly "logprob": number - readonly "bytes": ReadonlyArray +export type ResponseMCPListToolsInProgressEvent = { + readonly "type": "response.mcp_list_tools.in_progress" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number } -export const TopLogProb = Schema.Struct({ - "token": Schema.String, - "logprob": Schema.Number.check(Schema.isFinite()), - "bytes": Schema.Array(Schema.Number.check(Schema.isInt())) -}).annotate({ "title": "Top log probability", "description": "The top log probability of a token." }) -export type TextContent = { readonly "type": "text"; readonly "text": string } -export const TextContent = Schema.Struct({ "type": Schema.Literal("text"), "text": Schema.String }).annotate({ - "title": "Text Content", - "description": "A text content." -}) -export type SummaryTextContent = { readonly "type": "summary_text"; readonly "text": string } -export const SummaryTextContent = Schema.Struct({ - "type": Schema.Literal("summary_text").annotate({ "description": "The type of the object. Always `summary_text`." }), - "text": Schema.String.annotate({ "description": "A summary of the reasoning output from the model so far." }) -}).annotate({ "title": "Summary text", "description": "A summary text from the model." }) -export type ReasoningTextContent = { readonly "type": "reasoning_text"; readonly "text": string } -export const ReasoningTextContent = Schema.Struct({ - "type": Schema.Literal("reasoning_text").annotate({ - "description": "The type of the reasoning text. Always `reasoning_text`." +export const ResponseMCPListToolsInProgressEvent = Schema.Struct({ + "type": Schema.Literal("response.mcp_list_tools.in_progress").annotate({ + "description": "The type of the event. Always 'response.mcp_list_tools.in_progress'." }), - "text": Schema.String.annotate({ "description": "The reasoning text from the model." }) -}).annotate({ "title": "Reasoning text", "description": "Reasoning text from the model." }) -export type RefusalContent = { readonly "type": "refusal"; readonly "refusal": string } -export const RefusalContent = Schema.Struct({ - "type": Schema.Literal("refusal").annotate({ "description": "The type of the refusal. Always `refusal`." }), - "refusal": Schema.String.annotate({ "description": "The refusal explanation from the model." }) -}).annotate({ "title": "Refusal", "description": "A refusal from the model." }) -export type InputImageContent = { - readonly "type": "input_image" - readonly "image_url"?: string | null - readonly "file_id"?: string | null - readonly "detail": "low" | "high" | "auto" | "original" + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that is being processed." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that is being processed." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPListToolsInProgressEvent", + "description": "Emitted when the system is in the process of retrieving the list of available MCP tools.\n", + "identifier": "ResponseMCPListToolsInProgressEvent" +}) +export type ResponseCustomToolCallInputDeltaEvent = { + readonly "type": "response.custom_tool_call_input.delta" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string + readonly "delta": string } -export const InputImageContent = Schema.Struct({ - "type": Schema.Literal("input_image").annotate({ - "description": "The type of the input item. Always `input_image`." +export const ResponseCustomToolCallInputDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.custom_tool_call_input.delta").annotate({ + "description": "The event type identifier." }), - "image_url": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL.", - "format": "uri" - }), - Schema.Null - ]) + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "file_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), - Schema.Null - ]) + "output_index": Schema.Number.annotate({ "description": "The index of the output this delta applies to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "detail": Schema.Literals(["low", "high", "auto", "original"]).annotate({ - "description": - "The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." - }) + "item_id": Schema.String.annotate({ + "description": "Unique identifier for the API item associated with this event." + }), + "delta": Schema.String.annotate({ "description": "The incremental input data (delta) for the custom tool call." }) }).annotate({ - "title": "Input image", - "description": "An image input to the model. Learn about [image inputs](/docs/guides/vision)." + "title": "ResponseCustomToolCallInputDelta", + "description": "Event representing a delta (partial update) to the input of a custom tool call.\n", + "identifier": "ResponseCustomToolCallInputDeltaEvent" }) -export type ComputerScreenshotContent = { - readonly "type": "computer_screenshot" - readonly "image_url": string | null - readonly "file_id": string | null - readonly "detail": "low" | "high" | "auto" | "original" +export type ResponseCustomToolCallInputDoneEvent = { + readonly "type": "response.custom_tool_call_input.done" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string + readonly "input": string } -export const ComputerScreenshotContent = Schema.Struct({ - "type": Schema.Literal("computer_screenshot").annotate({ - "description": - "Specifies the event type. For a computer screenshot, this property is always set to `computer_screenshot`." +export const ResponseCustomToolCallInputDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.custom_tool_call_input.done").annotate({ + "description": "The event type identifier." }), - "image_url": Schema.Union([ - Schema.String.annotate({ "description": "The URL of the screenshot image.", "format": "uri" }), - Schema.Null - ]), - "file_id": Schema.Union([ - Schema.String.annotate({ "description": "The identifier of an uploaded file that contains the screenshot." }), - Schema.Null - ]), - "detail": Schema.Literals(["low", "high", "auto", "original"]).annotate({ - "description": - "The detail level of the screenshot image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." - }) -}).annotate({ "title": "Computer screenshot", "description": "A screenshot of a computer." }) -export type InputFileContent = { - readonly "type": "input_file" - readonly "file_id"?: string | null - readonly "filename"?: string - readonly "file_data"?: string - readonly "file_url"?: string - readonly "detail"?: "low" | "high" -} -export const InputFileContent = Schema.Struct({ - "type": Schema.Literal("input_file").annotate({ "description": "The type of the input item. Always `input_file`." }), - "file_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), - Schema.Null - ]) - ), - "filename": Schema.optionalKey( - Schema.String.annotate({ "description": "The name of the file to be sent to the model." }) - ), - "file_data": Schema.optionalKey( - Schema.String.annotate({ "description": "The content of the file to be sent to the model.\n" }) + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "file_url": Schema.optionalKey( - Schema.String.annotate({ "description": "The URL of the file to be sent to the model.", "format": "uri" }) + "output_index": Schema.Number.annotate({ "description": "The index of the output this event applies to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "detail": Schema.optionalKey( - Schema.Literals(["low", "high"]).annotate({ - "description": - "The detail level of the file to be sent to the model. Use `low` for the default rendering behavior, or `high` to render the file at higher quality. Defaults to `low`." - }) - ) -}).annotate({ "title": "Input file", "description": "A file input to the model." }) -export type ClickParam = { - readonly "type": "click" - readonly "button": "left" | "right" | "wheel" | "back" | "forward" - readonly "x": number - readonly "y": number - readonly "keys"?: ReadonlyArray | null -} -export const ClickParam = Schema.Struct({ - "type": Schema.Literal("click").annotate({ - "description": "Specifies the event type. For a click action, this property is always `click`." + "item_id": Schema.String.annotate({ + "description": "Unique identifier for the API item associated with this event." }), - "button": Schema.Literals(["left", "right", "wheel", "back", "forward"]).annotate({ - "description": - "Indicates which mouse button was pressed during the click. One of `left`, `right`, `wheel`, `back`, or `forward`." + "input": Schema.String.annotate({ "description": "The complete input data for the custom tool call." }) +}).annotate({ + "title": "ResponseCustomToolCallInputDone", + "description": "Event indicating that input for a custom tool call is complete.\n", + "identifier": "ResponseCustomToolCallInputDoneEvent" +}) +export type ResponseKeepAliveEvent = { readonly "type": "keepalive"; readonly "sequence_number": number } +export const ResponseKeepAliveEvent = Schema.Struct({ + "type": Schema.Literal("keepalive").annotate({ + "description": "The type of the keepalive event. Always `keepalive`." }), - "x": Schema.Number.annotate({ "description": "The x-coordinate where the click occurred." }).check(Schema.isInt()), - "y": Schema.Number.annotate({ "description": "The y-coordinate where the click occurred." }).check(Schema.isInt()), - "keys": Schema.optionalKey( - Schema.Union([ - Schema.Array(Schema.String).annotate({ "description": "The keys being held while clicking." }), - Schema.Null - ]) + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this keepalive event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "title": "Click", "description": "A click action." }) -export type DoubleClickAction = { - readonly "type": "double_click" - readonly "x": number - readonly "y": number - readonly "keys": ReadonlyArray | null +}).annotate({ + "title": "Keep alive", + "description": "A keepalive event emitted during long-running response streams.", + "identifier": "ResponseKeepAliveEvent" +}) +export type ResponseApplyPatchCallOperationDiffDeltaEvent = { + readonly "type": "response.apply_patch_call_operation_diff.delta" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string + readonly "delta": string } -export const DoubleClickAction = Schema.Struct({ - "type": Schema.Literal("double_click").annotate({ - "description": "Specifies the event type. For a double click action, this property is always set to `double_click`." +export const ResponseApplyPatchCallOperationDiffDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.apply_patch_call_operation_diff.delta").annotate({ + "description": "The event type identifier." }), - "x": Schema.Number.annotate({ "description": "The x-coordinate where the double click occurred." }).check( - Schema.isInt() + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "y": Schema.Number.annotate({ "description": "The y-coordinate where the double click occurred." }).check( - Schema.isInt() + "output_index": Schema.Number.annotate({ "description": "The index of the output this delta applies to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "keys": Schema.Union([ - Schema.Array(Schema.String).annotate({ "description": "The keys being held while double-clicking." }), - Schema.Null - ]) -}).annotate({ "title": "DoubleClick", "description": "A double click action." }) -export type CoordParam = { readonly "x": number; readonly "y": number } -export const CoordParam = Schema.Struct({ - "x": Schema.Number.annotate({ "description": "The x-coordinate." }).check(Schema.isInt()), - "y": Schema.Number.annotate({ "description": "The y-coordinate." }).check(Schema.isInt()) -}).annotate({ "title": "Coordinate", "description": "An x/y coordinate pair, e.g. `{ x: 100, y: 200 }`." }) -export type KeyPressAction = { readonly "type": "keypress"; readonly "keys": ReadonlyArray } -export const KeyPressAction = Schema.Struct({ - "type": Schema.Literal("keypress").annotate({ - "description": "Specifies the event type. For a keypress action, this property is always set to `keypress`." + "item_id": Schema.String.annotate({ + "description": "Unique identifier for the API item associated with this event." }), - "keys": Schema.Array( - Schema.String.annotate({ "description": "One of the keys the model is requesting to be pressed." }) - ).annotate({ - "description": - "The combination of keys the model is requesting to be pressed. This is an array of strings, each representing a key." - }) -}).annotate({ "title": "KeyPress", "description": "A collection of keypresses the model would like to perform." }) -export type MoveParam = { - readonly "type": "move" - readonly "x": number - readonly "y": number - readonly "keys"?: ReadonlyArray | null + "delta": Schema.String.annotate({ "description": "The incremental diff data for the apply_patch tool call." }) +}).annotate({ + "title": "ResponseApplyPatchCallOperationDiffDelta", + "description": "Event representing a delta for an apply_patch tool call operation diff.", + "identifier": "ResponseApplyPatchCallOperationDiffDeltaEvent" +}) +export type ResponseApplyPatchCallOperationDiffDoneEvent = { + readonly "type": "response.apply_patch_call_operation_diff.done" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string + readonly "delta"?: string } -export const MoveParam = Schema.Struct({ - "type": Schema.Literal("move").annotate({ - "description": "Specifies the event type. For a move action, this property is always set to `move`." +export const ResponseApplyPatchCallOperationDiffDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.apply_patch_call_operation_diff.done").annotate({ + "description": "The event type identifier." }), - "x": Schema.Number.annotate({ "description": "The x-coordinate to move to." }).check(Schema.isInt()), - "y": Schema.Number.annotate({ "description": "The y-coordinate to move to." }).check(Schema.isInt()), - "keys": Schema.optionalKey( - Schema.Union([ - Schema.Array(Schema.String).annotate({ "description": "The keys being held while moving the mouse." }), - Schema.Null - ]) + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "output_index": Schema.Number.annotate({ "description": "The index of the output this event applies to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item_id": Schema.String.annotate({ + "description": "Unique identifier for the API item associated with this event." + }), + "delta": Schema.optionalKey( + Schema.String.annotate({ "description": "The final diff data for the apply_patch tool call." }) ) -}).annotate({ "title": "Move", "description": "A mouse move action." }) -export type ScreenshotParam = { readonly "type": "screenshot" } -export const ScreenshotParam = Schema.Struct({ - "type": Schema.Literal("screenshot").annotate({ - "description": "Specifies the event type. For a screenshot action, this property is always set to `screenshot`." +}).annotate({ + "title": "ResponseApplyPatchCallOperationDiffDone", + "description": "Event indicating that the operation diff for an apply_patch tool call is complete.", + "identifier": "ResponseApplyPatchCallOperationDiffDoneEvent" +}) +export type MessageContentImageFileObject = { + readonly "type": "image_file" + readonly "image_file": { readonly "file_id": string; readonly "detail"?: "auto" | "low" | "high" } +} +export const MessageContentImageFileObject = Schema.Struct({ + "type": Schema.Literal("image_file").annotate({ "description": "Always `image_file`." }), + "image_file": Schema.Struct({ + "file_id": Schema.String.annotate({ + "description": + "The [File](https://developers.openai.com/api/reference/resources/files) ID of the image in the message content. Set `purpose=\"vision\"` when uploading the File if you need to later display the file content." + }), + "detail": Schema.optionalKey( + Schema.Literals(["auto", "low", "high"]).annotate({ + "description": + "Specifies the detail level of the image if specified by the user. `low` uses fewer tokens, you can opt in to high resolution using `high`." + }) + ) }) -}).annotate({ "title": "Screenshot", "description": "A screenshot action." }) -export type ScrollParam = { - readonly "type": "scroll" - readonly "x": number - readonly "y": number - readonly "scroll_x": number - readonly "scroll_y": number - readonly "keys"?: ReadonlyArray | null +}).annotate({ + "title": "Image file", + "description": + "References an image [File](https://developers.openai.com/api/reference/resources/files) in the content of a message.", + "identifier": "MessageContentImageFileObject" +}) +export type MessageContentImageUrlObject = { + readonly "type": "image_url" + readonly "image_url": { readonly "url": string; readonly "detail"?: "auto" | "low" | "high" } } -export const ScrollParam = Schema.Struct({ - "type": Schema.Literal("scroll").annotate({ - "description": "Specifies the event type. For a scroll action, this property is always set to `scroll`." +export const MessageContentImageUrlObject = Schema.Struct({ + "type": Schema.Literal("image_url").annotate({ "description": "The type of the content part." }), + "image_url": Schema.Struct({ + "url": Schema.String.annotate({ + "description": "The external URL of the image, must be a supported image types: jpeg, jpg, png, gif, webp.", + "format": "uri" + }), + "detail": Schema.optionalKey( + Schema.Literals(["auto", "low", "high"]).annotate({ + "description": + "Specifies the detail level of the image. `low` uses fewer tokens, you can opt in to high resolution using `high`. Default value is `auto`" + }) + ) + }) +}).annotate({ + "title": "Image URL", + "description": "References an image URL in the content of a message.", + "identifier": "MessageContentImageUrlObject" +}) +export type MessageRequestContentTextObject = { readonly "type": "text"; readonly "text": string } +export const MessageRequestContentTextObject = Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "Always `text`." }), + "text": Schema.String.annotate({ "description": "Text content to be sent to the model" }) +}).annotate({ + "title": "Text", + "description": "The text content that is part of a message.", + "identifier": "MessageRequestContentTextObject" +}) +export type AssistantToolsFileSearchTypeOnly = { readonly "type": "file_search" } +export const AssistantToolsFileSearchTypeOnly = Schema.Struct({ + "type": Schema.Literal("file_search").annotate({ "description": "The type of tool being defined: `file_search`" }) +}).annotate({ "title": "FileSearch tool", "identifier": "AssistantToolsFileSearchTypeOnly" }) +export type TruncationObject = { readonly "type": "auto" | "last_messages"; readonly "last_messages"?: number | null } +export const TruncationObject = Schema.Struct({ + "type": Schema.Literals(["auto", "last_messages"]).annotate({ + "description": + "The truncation strategy to use for the thread. The default is `auto`. If set to `last_messages`, the thread will be truncated to the n most recent messages in the thread. When set to `auto`, messages in the middle of the thread will be dropped to fit the context length of the model, `max_prompt_tokens`." }), - "x": Schema.Number.annotate({ "description": "The x-coordinate where the scroll occurred." }).check(Schema.isInt()), - "y": Schema.Number.annotate({ "description": "The y-coordinate where the scroll occurred." }).check(Schema.isInt()), - "scroll_x": Schema.Number.annotate({ "description": "The horizontal scroll distance." }).check(Schema.isInt()), - "scroll_y": Schema.Number.annotate({ "description": "The vertical scroll distance." }).check(Schema.isInt()), - "keys": Schema.optionalKey( + "last_messages": Schema.optionalKey( Schema.Union([ - Schema.Array(Schema.String).annotate({ "description": "The keys being held while scrolling." }), + Schema.Number.annotate({ + "description": "The number of most recent messages from the thread when constructing the context for the run." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ), Schema.Null ]) ) -}).annotate({ "title": "Scroll", "description": "A scroll action." }) -export type TypeParam = { readonly "type": "type"; readonly "text": string } -export const TypeParam = Schema.Struct({ - "type": Schema.Literal("type").annotate({ - "description": "Specifies the event type. For a type action, this property is always set to `type`." - }), - "text": Schema.String.annotate({ "description": "The text to type." }) -}).annotate({ "title": "Type", "description": "An action to type in text." }) -export type WaitParam = { readonly "type": "wait" } -export const WaitParam = Schema.Struct({ - "type": Schema.Literal("wait").annotate({ - "description": "Specifies the event type. For a wait action, this property is always set to `wait`." - }) -}).annotate({ "title": "Wait", "description": "A wait action." }) -export type ComputerCallSafetyCheckParam = { - readonly "id": string - readonly "code"?: string | null - readonly "message"?: string | null +}).annotate({ + "title": "Thread Truncation Controls", + "description": + "Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run.", + "identifier": "TruncationObject" +}) +export type AssistantsNamedToolChoice = { + readonly "type": "function" | "code_interpreter" | "file_search" + readonly "function"?: { readonly "name": string } } -export const ComputerCallSafetyCheckParam = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The ID of the pending safety check." }), - "code": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "The type of the pending safety check." }), Schema.Null]) - ), - "message": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "Details about the pending safety check." }), Schema.Null]) +export const AssistantsNamedToolChoice = Schema.Struct({ + "type": Schema.Literals(["function", "code_interpreter", "file_search"]).annotate({ + "description": "The type of the tool. If type is `function`, the function name must be set" + }), + "function": Schema.optionalKey( + Schema.Struct({ "name": Schema.String.annotate({ "description": "The name of the function to call." }) }) ) -}).annotate({ "description": "A pending safety check for the computer call." }) -export type ToolSearchCall = { - readonly "type": "tool_search_call" +}).annotate({ + "description": "Specifies a tool the model should use. Use to force the model to call a specific tool.", + "identifier": "AssistantsNamedToolChoice" +}) +export type RunToolCallObject = { readonly "id": string - readonly "call_id": string | null - readonly "execution": "server" | "client" - readonly "arguments": unknown - readonly "status": "in_progress" | "completed" | "incomplete" - readonly "created_by"?: string + readonly "type": "function" + readonly "function": { readonly "name": string; readonly "arguments": string } } -export const ToolSearchCall = Schema.Struct({ - "type": Schema.Literal("tool_search_call").annotate({ - "description": "The type of the item. Always `tool_search_call`." +export const RunToolCallObject = Schema.Struct({ + "id": Schema.String.annotate({ + "description": + "The ID of the tool call. This ID must be referenced when you submit the tool outputs in using the [Submit tool outputs to run](https://developers.openai.com/api/docs/assistants/migration) endpoint." }), - "id": Schema.String.annotate({ "description": "The unique ID of the tool search call item." }), - "call_id": Schema.Union([ - Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }), - Schema.Null - ]), - "execution": Schema.Literals(["server", "client"]).annotate({ - "description": "Whether tool search was executed by the server or by the client." + "type": Schema.Literal("function").annotate({ + "description": "The type of tool call the output is required for. For now, this is always `function`." }), - "arguments": Schema.Unknown.annotate({ "description": "Arguments used for the tool search call." }), - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": "The status of the tool search call item that was recorded." + "function": Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the function." }), + "arguments": Schema.String.annotate({ + "description": "The arguments that the model expects you to pass to the function." + }) + }).annotate({ "description": "The function definition." }) +}).annotate({ "description": "Tool call objects", "identifier": "RunToolCallObject" }) +export type RunCompletionUsage = { + readonly "completion_tokens": number + readonly "prompt_tokens": number + readonly "total_tokens": number +} | null +export const RunCompletionUsage = Schema.Union([ + Schema.Struct({ + "completion_tokens": Schema.Number.annotate({ + "description": "Number of completion tokens used over the course of the run." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "prompt_tokens": Schema.Number.annotate({ + "description": "Number of prompt tokens used over the course of the run." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (prompt + completion)." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })) + }).annotate({ + "description": + "Usage statistics related to the run. This value will be `null` if the run is not in a terminal state (i.e. `in_progress`, `queued`, etc.)." }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) - ) + Schema.Null +]).annotate({ "identifier": "RunCompletionUsage" }) +export type RunStepDetailsMessageCreationObject = { + readonly "type": "message_creation" + readonly "message_creation": { readonly "message_id": string } +} +export const RunStepDetailsMessageCreationObject = Schema.Struct({ + "type": Schema.Literal("message_creation").annotate({ "description": "Always `message_creation`." }), + "message_creation": Schema.Struct({ + "message_id": Schema.String.annotate({ "description": "The ID of the message that was created by this run step." }) + }) +}).annotate({ + "title": "Message creation", + "description": "Details of the message creation by the run step.", + "identifier": "RunStepDetailsMessageCreationObject" }) -export type FunctionTool = { - readonly "type": "function" - readonly "name": string - readonly "description"?: string | null - readonly "parameters": {} | null - readonly "strict": boolean | null - readonly "defer_loading"?: boolean +export type RunStepDetailsToolCallsCodeOutputLogsObject = { readonly "type": "logs"; readonly "logs": string } +export const RunStepDetailsToolCallsCodeOutputLogsObject = Schema.Struct({ + "type": Schema.Literal("logs").annotate({ "description": "Always `logs`." }), + "logs": Schema.String.annotate({ "description": "The text output from the Code Interpreter tool call." }) +}).annotate({ + "title": "Code Interpreter log output", + "description": "Text output from the Code Interpreter tool call as part of a run step.", + "identifier": "RunStepDetailsToolCallsCodeOutputLogsObject" +}) +export type RunStepDetailsToolCallsCodeOutputImageObject = { + readonly "type": "image" + readonly "image": { readonly "file_id": string } } -export const FunctionTool = Schema.Struct({ - "type": Schema.Literal("function").annotate({ "description": "The type of the function tool. Always `function`." }), - "name": Schema.String.annotate({ "description": "The name of the function to call." }), - "description": Schema.optionalKey( - Schema.Union([ +export const RunStepDetailsToolCallsCodeOutputImageObject = Schema.Struct({ + "type": Schema.Literal("image").annotate({ "description": "Always `image`." }), + "image": Schema.Struct({ + "file_id": Schema.String.annotate({ + "description": "The [file](https://developers.openai.com/api/reference/resources/files) ID of the image." + }) + }) +}).annotate({ "title": "Code Interpreter image output", "identifier": "RunStepDetailsToolCallsCodeOutputImageObject" }) +export type RunStepDetailsToolCallsFileSearchResultObject = { + readonly "file_id": string + readonly "file_name": string + readonly "score": number + readonly "content"?: ReadonlyArray<{ readonly "type"?: "text"; readonly "text"?: string }> +} +export const RunStepDetailsToolCallsFileSearchResultObject = Schema.Struct({ + "file_id": Schema.String.annotate({ "description": "The ID of the file that result was found in." }), + "file_name": Schema.String.annotate({ "description": "The name of the file that result was found in." }), + "score": Schema.Number.annotate({ + "description": "The score of the result. All values must be a floating point number between 0 and 1." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + "content": Schema.optionalKey( + Schema.Array( + Schema.Struct({ + "type": Schema.optionalKey(Schema.Literal("text").annotate({ "description": "The type of the content." })), + "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content of the file." })) + }) + ).annotate({ + "description": + "The content of the result that was found. The content is only included if requested via the include query parameter." + }) + ) +}).annotate({ + "title": "File search tool call result", + "description": "A result instance of the file search.", + "identifier": "RunStepDetailsToolCallsFileSearchResultObject" +}) +export type RunStepDetailsToolCallsFunctionObject = { + readonly "id": string + readonly "type": "function" + readonly "function": { readonly "name": string; readonly "arguments": string; readonly "output": string | null } +} +export const RunStepDetailsToolCallsFunctionObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the tool call object." }), + "type": Schema.Literal("function").annotate({ + "description": "The type of tool call. This is always going to be `function` for this type of tool call." + }), + "function": Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the function." }), + "arguments": Schema.String.annotate({ "description": "The arguments passed to the function." }), + "output": Schema.Union([ Schema.String.annotate({ "description": - "A description of the function. Used by the model to determine whether or not to call the function." + "The output of the function. This will be `null` if the outputs have not been [submitted](https://developers.openai.com/api/docs/assistants/migration) yet." }), Schema.Null ]) - ), - "parameters": Schema.Union([ - Schema.Struct({}).annotate({ "description": "A JSON schema object describing the parameters of the function." }), - Schema.Null - ]), - "strict": Schema.Union([ - Schema.Boolean.annotate({ "description": "Whether to enforce strict parameter validation. Default `true`." }), - Schema.Null - ]), - "defer_loading": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether this function is deferred and loaded via tool search." }) + }).annotate({ "description": "The definition of the function that was called." }) +}).annotate({ "title": "Function tool call", "identifier": "RunStepDetailsToolCallsFunctionObject" }) +export type RunStepCompletionUsage = { + readonly "completion_tokens": number + readonly "prompt_tokens": number + readonly "total_tokens": number +} | null +export const RunStepCompletionUsage = Schema.Union([ + Schema.Struct({ + "completion_tokens": Schema.Number.annotate({ + "description": "Number of completion tokens used over the course of the run step." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "prompt_tokens": Schema.Number.annotate({ + "description": "Number of prompt tokens used over the course of the run step." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (prompt + completion)." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })) + }).annotate({ + "description": + "Usage statistics related to the run step. This value will be `null` while the run step's status is `in_progress`." + }), + Schema.Null +]).annotate({ "identifier": "RunStepCompletionUsage" }) +export type RunStepDeltaStepDetailsMessageCreationObject = { + readonly "type": "message_creation" + readonly "message_creation"?: { readonly "message_id"?: string } +} +export const RunStepDeltaStepDetailsMessageCreationObject = Schema.Struct({ + "type": Schema.Literal("message_creation").annotate({ "description": "Always `message_creation`." }), + "message_creation": Schema.optionalKey( + Schema.Struct({ + "message_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the message that was created by this run step." }) + ) + }) ) }).annotate({ - "title": "Function", - "description": - "Defines a function in your own code the model can choose to call. Learn more about [function calling](https://platform.openai.com/docs/guides/function-calling)." -}) -export type ComputerTool = { readonly "type": "computer" } -export const ComputerTool = Schema.Struct({ - "type": Schema.Literal("computer").annotate({ "description": "The type of the computer tool. Always `computer`." }) -}).annotate({ - "title": "Computer", - "description": - "A tool that controls a virtual computer. Learn more about the [computer tool](https://platform.openai.com/docs/guides/tools-computer-use)." + "title": "Message creation", + "description": "Details of the message creation by the run step.", + "identifier": "RunStepDeltaStepDetailsMessageCreationObject" }) -export type ComputerUsePreviewTool = { - readonly "type": "computer_use_preview" - readonly "environment": "windows" | "mac" | "linux" | "ubuntu" | "browser" - readonly "display_width": number - readonly "display_height": number +export type RunStepDeltaStepDetailsToolCallsCodeOutputLogsObject = { + readonly "index": number + readonly "type": "logs" + readonly "logs"?: string } -export const ComputerUsePreviewTool = Schema.Struct({ - "type": Schema.Literal("computer_use_preview").annotate({ - "description": "The type of the computer use tool. Always `computer_use_preview`." - }), - "environment": Schema.Literals(["windows", "mac", "linux", "ubuntu", "browser"]).annotate({ - "description": "The type of computer environment to control." - }), - "display_width": Schema.Number.annotate({ "description": "The width of the computer display." }).check( - Schema.isInt() +export const RunStepDeltaStepDetailsToolCallsCodeOutputLogsObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the output in the outputs array." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "display_height": Schema.Number.annotate({ "description": "The height of the computer display." }).check( - Schema.isInt() + "type": Schema.Literal("logs").annotate({ "description": "Always `logs`." }), + "logs": Schema.optionalKey( + Schema.String.annotate({ "description": "The text output from the Code Interpreter tool call." }) ) }).annotate({ - "title": "Computer use preview", - "description": - "A tool that controls a virtual computer. Learn more about the [computer tool](https://platform.openai.com/docs/guides/tools-computer-use)." -}) -export type InputFidelity = "high" | "low" -export const InputFidelity = Schema.Literals(["high", "low"]).annotate({ - "description": - "Control how much effort the model will exert to match the style and features, especially facial features, of input images. This parameter is only supported for `gpt-image-1` and `gpt-image-1.5` and later models, unsupported for `gpt-image-1-mini`. Supports `high` and `low`. Defaults to `low`." + "title": "Code interpreter log output", + "description": "Text output from the Code Interpreter tool call as part of a run step.", + "identifier": "RunStepDeltaStepDetailsToolCallsCodeOutputLogsObject" }) -export type LocalShellToolParam = { readonly "type": "local_shell" } -export const LocalShellToolParam = Schema.Struct({ - "type": Schema.Literal("local_shell").annotate({ - "description": "The type of the local shell tool. Always `local_shell`." - }) +export type RunStepDeltaStepDetailsToolCallsCodeOutputImageObject = { + readonly "index": number + readonly "type": "image" + readonly "image"?: { readonly "file_id"?: string } +} +export const RunStepDeltaStepDetailsToolCallsCodeOutputImageObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the output in the outputs array." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "type": Schema.Literal("image").annotate({ "description": "Always `image`." }), + "image": Schema.optionalKey( + Schema.Struct({ + "file_id": Schema.optionalKey( + Schema.String.annotate({ + "description": "The [file](https://developers.openai.com/api/reference/resources/files) ID of the image." + }) + ) + }) + ) }).annotate({ - "title": "Local shell tool", - "description": "A tool that allows the model to execute shell commands in a local environment." -}) -export type LocalSkillParam = { readonly "name": string; readonly "description": string; readonly "path": string } -export const LocalSkillParam = Schema.Struct({ - "name": Schema.String.annotate({ "description": "The name of the skill." }), - "description": Schema.String.annotate({ "description": "The description of the skill." }), - "path": Schema.String.annotate({ "description": "The path to the directory containing the skill." }) -}) -export type ContainerReferenceParam = { readonly "type": "container_reference"; readonly "container_id": string } -export const ContainerReferenceParam = Schema.Struct({ - "type": Schema.Literal("container_reference").annotate({ - "description": "References a container created with the /v1/containers endpoint" - }), - "container_id": Schema.String.annotate({ "description": "The ID of the referenced container." }) + "title": "Code interpreter image output", + "identifier": "RunStepDeltaStepDetailsToolCallsCodeOutputImageObject" }) -export type CustomTextFormatParam = { readonly "type": "text" } -export const CustomTextFormatParam = Schema.Struct({ - "type": Schema.Literal("text").annotate({ "description": "Unconstrained text format. Always `text`." }) -}).annotate({ "title": "Text format", "description": "Unconstrained free-form text." }) -export type CustomGrammarFormatParam = { - readonly "type": "grammar" - readonly "syntax": "lark" | "regex" - readonly "definition": string +export type RunStepDeltaStepDetailsToolCallsFileSearchObject = { + readonly "index": number + readonly "id"?: string + readonly "type": "file_search" + readonly "file_search": { readonly [x: string]: Schema.Json } } -export const CustomGrammarFormatParam = Schema.Struct({ - "type": Schema.Literal("grammar").annotate({ "description": "Grammar format. Always `grammar`." }), - "syntax": Schema.Literals(["lark", "regex"]).annotate({ - "description": "The syntax of the grammar definition. One of `lark` or `regex`." +export const RunStepDeltaStepDetailsToolCallsFileSearchObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the tool call in the tool calls array." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the tool call object." })), + "type": Schema.Literal("file_search").annotate({ + "description": "The type of tool call. This is always going to be `file_search` for this type of tool call." }), - "definition": Schema.String.annotate({ "description": "The grammar definition." }) -}).annotate({ "title": "Grammar format", "description": "A grammar defined by the user." }) -export type EmptyModelParam = {} -export const EmptyModelParam = Schema.Struct({}) -export type ToolSearchToolParam = { - readonly "type": "tool_search" - readonly "execution"?: "server" | "client" - readonly "description"?: string | null - readonly "parameters"?: {} | null + "file_search": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "For now, this is always going to be an empty object." + }) +}).annotate({ "title": "File search tool call", "identifier": "RunStepDeltaStepDetailsToolCallsFileSearchObject" }) +export type RunStepDeltaStepDetailsToolCallsFunctionObject = { + readonly "index": number + readonly "id"?: string + readonly "type": "function" + readonly "function"?: { readonly "name"?: string; readonly "arguments"?: string; readonly "output"?: string | null } } -export const ToolSearchToolParam = Schema.Struct({ - "type": Schema.Literal("tool_search").annotate({ "description": "The type of the tool. Always `tool_search`." }), - "execution": Schema.optionalKey( - Schema.Literals(["server", "client"]).annotate({ - "description": "Whether tool search is executed by the server or by the client." - }) +export const RunStepDeltaStepDetailsToolCallsFunctionObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the tool call in the tool calls array." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "description": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "Description shown to the model for a client-executed tool search tool." - }), - Schema.Null - ]) + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the tool call object." })), + "type": Schema.Literal("function").annotate({ + "description": "The type of tool call. This is always going to be `function` for this type of tool call." + }), + "function": Schema.optionalKey( + Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function." })), + "arguments": Schema.optionalKey( + Schema.String.annotate({ "description": "The arguments passed to the function." }) + ), + "output": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The output of the function. This will be `null` if the outputs have not been [submitted](https://developers.openai.com/api/docs/assistants/migration) yet." + }), + Schema.Null + ]) + ) + }).annotate({ "description": "The definition of the function that was called." }) + ) +}).annotate({ "title": "Function tool call", "identifier": "RunStepDeltaStepDetailsToolCallsFunctionObject" }) +export type MessageContentTextAnnotationsFileCitationObject = { + readonly "type": "file_citation" + readonly "text": string + readonly "file_citation": { readonly "file_id": string } + readonly "start_index": number + readonly "end_index": number +} +export const MessageContentTextAnnotationsFileCitationObject = Schema.Struct({ + "type": Schema.Literal("file_citation").annotate({ "description": "Always `file_citation`." }), + "text": Schema.String.annotate({ "description": "The text in the message content that needs to be replaced." }), + "file_citation": Schema.Struct({ + "file_id": Schema.String.annotate({ "description": "The ID of the specific File the citation is from." }) + }), + "start_index": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) ), - "parameters": Schema.optionalKey( - Schema.Union([ - Schema.Struct({}).annotate({ "description": "Parameter schema for a client-executed tool search tool." }), - Schema.Null - ]) + "end_index": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) ) }).annotate({ - "title": "Tool search tool", - "description": "Hosted or BYOT tool search configuration for deferred tools." -}) -export type SearchContentType = "text" | "image" -export const SearchContentType = Schema.Literals(["text", "image"]) -export type ApplyPatchToolParam = { readonly "type": "apply_patch" } -export const ApplyPatchToolParam = Schema.Struct({ - "type": Schema.Literal("apply_patch").annotate({ "description": "The type of the tool. Always `apply_patch`." }) -}).annotate({ - "title": "Apply patch tool", - "description": "Allows the assistant to create, delete, or update files using unified diffs." + "title": "File citation", + "description": + "A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the \"file_search\" tool to search files.", + "identifier": "MessageContentTextAnnotationsFileCitationObject" }) -export type CompactionBody = { - readonly "type": "compaction" - readonly "id": string - readonly "encrypted_content": string - readonly "created_by"?: string +export type MessageContentTextAnnotationsFilePathObject = { + readonly "type": "file_path" + readonly "text": string + readonly "file_path": { readonly "file_id": string } + readonly "start_index": number + readonly "end_index": number } -export const CompactionBody = Schema.Struct({ - "type": Schema.Literal("compaction").annotate({ "description": "The type of the item. Always `compaction`." }), - "id": Schema.String.annotate({ "description": "The unique ID of the compaction item." }), - "encrypted_content": Schema.String.annotate({ - "description": "The encrypted content that was produced by compaction." +export const MessageContentTextAnnotationsFilePathObject = Schema.Struct({ + "type": Schema.Literal("file_path").annotate({ "description": "Always `file_path`." }), + "text": Schema.String.annotate({ "description": "The text in the message content that needs to be replaced." }), + "file_path": Schema.Struct({ + "file_id": Schema.String.annotate({ "description": "The ID of the file that was generated." }) }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + "start_index": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ), + "end_index": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) ) }).annotate({ - "title": "Compaction item", + "title": "File path", "description": - "A compaction item generated by the [`v1/responses/compact` API](/docs/api-reference/responses/compact)." + "A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file.", + "identifier": "MessageContentTextAnnotationsFilePathObject" }) -export type CodeInterpreterOutputLogs = { readonly "type": "logs"; readonly "logs": string } -export const CodeInterpreterOutputLogs = Schema.Struct({ - "type": Schema.Literal("logs").annotate({ "description": "The type of the output. Always `logs`." }), - "logs": Schema.String.annotate({ "description": "The logs output from the code interpreter." }) -}).annotate({ "title": "Code interpreter output logs", "description": "The logs output from the code interpreter." }) -export type CodeInterpreterOutputImage = { readonly "type": "image"; readonly "url": string } -export const CodeInterpreterOutputImage = Schema.Struct({ - "type": Schema.Literal("image").annotate({ "description": "The type of the output. Always `image`." }), - "url": Schema.String.annotate({ - "description": "The URL of the image output from the code interpreter.", - "format": "uri" - }) -}).annotate({ "title": "Code interpreter output image", "description": "The image output from the code interpreter." }) -export type LocalShellExecAction = { - readonly "type": "exec" - readonly "command": ReadonlyArray - readonly "timeout_ms"?: number | null - readonly "working_directory"?: string | null - readonly "env": {} - readonly "user"?: string | null +export type MessageContentRefusalObject = { readonly "type": "refusal"; readonly "refusal": string } +export const MessageContentRefusalObject = Schema.Struct({ + "type": Schema.Literal("refusal").annotate({ "description": "Always `refusal`." }), + "refusal": Schema.String +}).annotate({ + "title": "Refusal", + "description": "The refusal content generated by the assistant.", + "identifier": "MessageContentRefusalObject" +}) +export type MessageDeltaContentImageFileObject = { + readonly "index": number + readonly "type": "image_file" + readonly "image_file"?: { readonly "file_id"?: string; readonly "detail"?: "auto" | "low" | "high" } } -export const LocalShellExecAction = Schema.Struct({ - "type": Schema.Literal("exec").annotate({ "description": "The type of the local shell action. Always `exec`." }), - "command": Schema.Array(Schema.String).annotate({ "description": "The command to run." }), - "timeout_ms": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "Optional timeout in milliseconds for the command." }).check( - Schema.isInt() +export const MessageDeltaContentImageFileObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the content part in the message." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "type": Schema.Literal("image_file").annotate({ "description": "Always `image_file`." }), + "image_file": Schema.optionalKey(Schema.Struct({ + "file_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The [File](https://developers.openai.com/api/reference/resources/files) ID of the image in the message content. Set `purpose=\"vision\"` when uploading the File if you need to later display the file content." + }) + ), + "detail": Schema.optionalKey( + Schema.Literals(["auto", "low", "high"]).annotate({ + "description": + "Specifies the detail level of the image if specified by the user. `low` uses fewer tokens, you can opt in to high resolution using `high`." + }) + ) + })) +}).annotate({ + "title": "Image file", + "description": + "References an image [File](https://developers.openai.com/api/reference/resources/files) in the content of a message.", + "identifier": "MessageDeltaContentImageFileObject" +}) +export type MessageDeltaContentTextAnnotationsFileCitationObject = { + readonly "index": number + readonly "type": "file_citation" + readonly "text"?: string + readonly "file_citation"?: { readonly "file_id"?: string; readonly "quote"?: string } + readonly "start_index"?: number + readonly "end_index"?: number +} +export const MessageDeltaContentTextAnnotationsFileCitationObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the annotation in the text content part." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "type": Schema.Literal("file_citation").annotate({ "description": "Always `file_citation`." }), + "text": Schema.optionalKey( + Schema.String.annotate({ "description": "The text in the message content that needs to be replaced." }) + ), + "file_citation": Schema.optionalKey( + Schema.Struct({ + "file_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the specific File the citation is from." }) ), - Schema.Null - ]) + "quote": Schema.optionalKey(Schema.String.annotate({ "description": "The specific quote in the file." })) + }) ), - "working_directory": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "Optional working directory to run the command in." }), - Schema.Null - ]) + "start_index": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ) ), - "env": Schema.Struct({}).annotate({ "description": "Environment variables to set for the command." }), - "user": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "Optional user to run the command as." }), Schema.Null]) + "end_index": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ) ) -}).annotate({ "title": "Local shell exec action", "description": "Execute a shell command on the server." }) -export type LocalEnvironmentResource = { readonly "type": "local" } -export const LocalEnvironmentResource = Schema.Struct({ - "type": Schema.Literal("local").annotate({ "description": "The environment type. Always `local`." }) }).annotate({ - "title": "Local Environment", - "description": "Represents the use of a local environment to perform shell actions." + "title": "File citation", + "description": + "A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the \"file_search\" tool to search files.", + "identifier": "MessageDeltaContentTextAnnotationsFileCitationObject" }) -export type ContainerReferenceResource = { readonly "type": "container_reference"; readonly "container_id": string } -export const ContainerReferenceResource = Schema.Struct({ - "type": Schema.Literal("container_reference").annotate({ - "description": "The environment type. Always `container_reference`." - }), - "container_id": Schema.String -}).annotate({ "title": "Container Reference", "description": "Represents a container created with /v1/containers." }) -export type FunctionShellCallOutputTimeoutOutcome = { readonly "type": "timeout" } -export const FunctionShellCallOutputTimeoutOutcome = Schema.Struct({ - "type": Schema.Literal("timeout").annotate({ "description": "The outcome type. Always `timeout`." }) +export type MessageDeltaContentTextAnnotationsFilePathObject = { + readonly "index": number + readonly "type": "file_path" + readonly "text"?: string + readonly "file_path"?: { readonly "file_id"?: string } + readonly "start_index"?: number + readonly "end_index"?: number +} +export const MessageDeltaContentTextAnnotationsFilePathObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the annotation in the text content part." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "type": Schema.Literal("file_path").annotate({ "description": "Always `file_path`." }), + "text": Schema.optionalKey( + Schema.String.annotate({ "description": "The text in the message content that needs to be replaced." }) + ), + "file_path": Schema.optionalKey( + Schema.Struct({ + "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the file that was generated." })) + }) + ), + "start_index": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ) + ), + "end_index": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ) + ) }).annotate({ - "title": "Shell call timeout outcome", - "description": "Indicates that the shell call exceeded its configured time limit." + "title": "File path", + "description": + "A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file.", + "identifier": "MessageDeltaContentTextAnnotationsFilePathObject" }) -export type FunctionShellCallOutputExitOutcome = { readonly "type": "exit"; readonly "exit_code": number } -export const FunctionShellCallOutputExitOutcome = Schema.Struct({ - "type": Schema.Literal("exit").annotate({ "description": "The outcome type. Always `exit`." }), - "exit_code": Schema.Number.annotate({ "description": "Exit code from the shell process." }).check(Schema.isInt()) +export type MessageDeltaContentRefusalObject = { + readonly "index": number + readonly "type": "refusal" + readonly "refusal"?: string +} +export const MessageDeltaContentRefusalObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the refusal part in the message." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "type": Schema.Literal("refusal").annotate({ "description": "Always `refusal`." }), + "refusal": Schema.optionalKey(Schema.String) }).annotate({ - "title": "Shell call exit outcome", - "description": "Indicates that the shell commands finished and returned an exit code." + "title": "Refusal", + "description": "The refusal content that is part of a message.", + "identifier": "MessageDeltaContentRefusalObject" }) -export type ApplyPatchCreateFileOperation = { - readonly "type": "create_file" - readonly "path": string - readonly "diff": string +export type MessageDeltaContentImageUrlObject = { + readonly "index": number + readonly "type": "image_url" + readonly "image_url"?: { readonly "url"?: string; readonly "detail"?: "auto" | "low" | "high" } } -export const ApplyPatchCreateFileOperation = Schema.Struct({ - "type": Schema.Literal("create_file").annotate({ "description": "Create a new file with the provided diff." }), - "path": Schema.String.annotate({ "description": "Path of the file to create." }), - "diff": Schema.String.annotate({ "description": "Diff to apply." }) +export const MessageDeltaContentImageUrlObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the content part in the message." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "type": Schema.Literal("image_url").annotate({ "description": "Always `image_url`." }), + "image_url": Schema.optionalKey(Schema.Struct({ + "url": Schema.optionalKey( + Schema.String.annotate({ + "description": "The URL of the image, must be a supported image types: jpeg, jpg, png, gif, webp.", + "format": "uri" + }) + ), + "detail": Schema.optionalKey( + Schema.Literals(["auto", "low", "high"]).annotate({ + "description": + "Specifies the detail level of the image. `low` uses fewer tokens, you can opt in to high resolution using `high`." + }) + ) + })) }).annotate({ - "title": "Apply patch create file operation", - "description": "Instruction describing how to create a file via the apply_patch tool." + "title": "Image URL", + "description": "References an image URL in the content of a message.", + "identifier": "MessageDeltaContentImageUrlObject" }) -export type ApplyPatchDeleteFileOperation = { readonly "type": "delete_file"; readonly "path": string } -export const ApplyPatchDeleteFileOperation = Schema.Struct({ - "type": Schema.Literal("delete_file").annotate({ "description": "Delete the specified file." }), - "path": Schema.String.annotate({ "description": "Path of the file to delete." }) -}).annotate({ - "title": "Apply patch delete file operation", - "description": "Instruction describing how to delete a file via the apply_patch tool." +export type DoneEvent = { readonly "event": "done"; readonly "data": "[DONE]" } +export const DoneEvent = Schema.Struct({ "event": Schema.Literal("done"), "data": Schema.Literal("[DONE]") }).annotate({ + "description": "Occurs when a stream ends.", + "identifier": "DoneEvent" }) -export type ApplyPatchUpdateFileOperation = { - readonly "type": "update_file" - readonly "path": string - readonly "diff": string +export type DeleteThreadResponse = { + readonly "id": string + readonly "deleted": boolean + readonly "object": "thread.deleted" } -export const ApplyPatchUpdateFileOperation = Schema.Struct({ - "type": Schema.Literal("update_file").annotate({ "description": "Update an existing file with the provided diff." }), - "path": Schema.String.annotate({ "description": "Path of the file to update." }), - "diff": Schema.String.annotate({ "description": "Diff to apply." }) -}).annotate({ - "title": "Apply patch update file operation", - "description": "Instruction describing how to update a file via the apply_patch tool." -}) -export type ApplyPatchToolCallOutput = { - readonly "type": "apply_patch_call_output" +export const DeleteThreadResponse = Schema.Struct({ + "id": Schema.String, + "deleted": Schema.Boolean, + "object": Schema.Literal("thread.deleted") +}).annotate({ "identifier": "DeleteThreadResponse" }) +export type DeleteMessageResponse = { readonly "id": string - readonly "call_id": string - readonly "status": "completed" | "failed" - readonly "output"?: string | null - readonly "created_by"?: string + readonly "deleted": boolean + readonly "object": "thread.message.deleted" } -export const ApplyPatchToolCallOutput = Schema.Struct({ - "type": Schema.Literal("apply_patch_call_output").annotate({ - "description": "The type of the item. Always `apply_patch_call_output`." - }), - "id": Schema.String.annotate({ - "description": "The unique ID of the apply patch tool call output. Populated when this item is returned via API." - }), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the apply patch tool call generated by the model." - }), - "status": Schema.Literals(["completed", "failed"]).annotate({ - "description": "The status of the apply patch tool call output. One of `completed` or `failed`." - }), - "output": Schema.optionalKey( +export const DeleteMessageResponse = Schema.Struct({ + "id": Schema.String, + "deleted": Schema.Boolean, + "object": Schema.Literal("thread.message.deleted") +}).annotate({ "identifier": "DeleteMessageResponse" }) +export type SubmitToolOutputsRunRequest = { + readonly "tool_outputs": ReadonlyArray<{ readonly "tool_call_id"?: string; readonly "output"?: string }> + readonly "stream"?: boolean | null +} +export const SubmitToolOutputsRunRequest = Schema.Struct({ + "tool_outputs": Schema.Array(Schema.Struct({ + "tool_call_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The ID of the tool call in the `required_action` object within the run object the output is being submitted for." + }) + ), + "output": Schema.optionalKey( + Schema.String.annotate({ "description": "The output of the tool call to be submitted to continue the run." }) + ) + })).annotate({ "description": "A list of tools for which the outputs are being submitted." }), + "stream": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ "description": "Optional textual output returned by the apply patch tool." }), + Schema.Boolean.annotate({ + "description": + "If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message.\n" + }), Schema.Null ]) - ), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the entity that created this tool call output." }) ) -}).annotate({ - "title": "Apply patch tool call output", - "description": "The output emitted by an apply patch tool call." -}) -export type InputTextContentParam = { readonly "type": "input_text"; readonly "text": string } -export const InputTextContentParam = Schema.Struct({ - "type": Schema.Literal("input_text").annotate({ "description": "The type of the input item. Always `input_text`." }), - "text": Schema.String.annotate({ "description": "The text input to the model." }).check(Schema.isMaxLength(10485760)) -}).annotate({ "title": "Input text", "description": "A text input to the model." }) -export type InputImageContentParamAutoParam = { - readonly "type": "input_image" - readonly "image_url"?: string | null - readonly "file_id"?: string | null - readonly "detail"?: "low" | "high" | "auto" | "original" | null -} -export const InputImageContentParamAutoParam = Schema.Struct({ - "type": Schema.Literal("input_image").annotate({ - "description": "The type of the input item. Always `input_image`." - }), - "image_url": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL.", - "format": "uri" - }).check(Schema.isMaxLength(20971520)), - Schema.Null - ]) - ), - "file_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), - Schema.Null - ]) - ), - "detail": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["low", "high", "auto", "original"]).annotate({ - "description": - "The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." - }), - Schema.Null - ]) - ) -}).annotate({ - "title": "Input image", - "description": "An image input to the model. Learn about [image inputs](/docs/guides/vision)" -}) -export type InputFileContentParam = { - readonly "type": "input_file" - readonly "file_id"?: string | null - readonly "filename"?: string | null - readonly "file_data"?: string | null - readonly "file_url"?: string | null - readonly "detail"?: "low" | "high" -} -export const InputFileContentParam = Schema.Struct({ - "type": Schema.Literal("input_file").annotate({ "description": "The type of the input item. Always `input_file`." }), - "file_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), - Schema.Null - ]) - ), - "filename": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The name of the file to be sent to the model." }), - Schema.Null - ]) - ), - "file_data": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The base64-encoded data of the file to be sent to the model." }).check( - Schema.isMaxLength(73400320) - ), - Schema.Null - ]) - ), - "file_url": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The URL of the file to be sent to the model.", "format": "uri" }), - Schema.Null - ]) - ), - "detail": Schema.optionalKey( - Schema.Literals(["low", "high"]).annotate({ +}).annotate({ "identifier": "SubmitToolOutputsRunRequest" }) +export type CompleteUploadRequest = { readonly "part_ids": ReadonlyArray; readonly "md5"?: string } +export const CompleteUploadRequest = Schema.Struct({ + "part_ids": Schema.Array(Schema.String).annotate({ "description": "The ordered list of Part IDs.\n" }), + "md5": Schema.optionalKey( + Schema.String.annotate({ "description": - "The detail level of the file to be sent to the model. Use `low` for the default rendering behavior, or `high` to render the file at higher quality. Defaults to `low`." + "The optional md5 checksum for the file contents to verify if the bytes uploaded matches what you expect.\n" }) ) -}).annotate({ "title": "Input file", "description": "A file input to the model." }) -export type FunctionShellCallOutputTimeoutOutcomeParam = { readonly "type": "timeout" } -export const FunctionShellCallOutputTimeoutOutcomeParam = Schema.Struct({ - "type": Schema.Literal("timeout").annotate({ "description": "The outcome type. Always `timeout`." }) -}).annotate({ - "title": "Shell call timeout outcome", - "description": "Indicates that the shell call exceeded its configured time limit." -}) -export type FunctionShellCallOutputExitOutcomeParam = { readonly "type": "exit"; readonly "exit_code": number } -export const FunctionShellCallOutputExitOutcomeParam = Schema.Struct({ - "type": Schema.Literal("exit").annotate({ "description": "The outcome type. Always `exit`." }), - "exit_code": Schema.Number.annotate({ "description": "The exit code returned by the shell process." }).check( - Schema.isInt() - ) -}).annotate({ - "title": "Shell call exit outcome", - "description": "Indicates that the shell commands finished and returned an exit code." -}) -export type ApplyPatchCreateFileOperationParam = { - readonly "type": "create_file" - readonly "path": string - readonly "diff": string -} -export const ApplyPatchCreateFileOperationParam = Schema.Struct({ - "type": Schema.Literal("create_file").annotate({ "description": "The operation type. Always `create_file`." }), - "path": Schema.String.annotate({ "description": "Path of the file to create relative to the workspace root." }).check( - Schema.isMinLength(1) - ), - "diff": Schema.String.annotate({ "description": "Unified diff content to apply when creating the file." }).check( - Schema.isMaxLength(10485760) - ) -}).annotate({ - "title": "Apply patch create file operation", - "description": "Instruction for creating a new file via the apply_patch tool." -}) -export type ApplyPatchDeleteFileOperationParam = { readonly "type": "delete_file"; readonly "path": string } -export const ApplyPatchDeleteFileOperationParam = Schema.Struct({ - "type": Schema.Literal("delete_file").annotate({ "description": "The operation type. Always `delete_file`." }), - "path": Schema.String.annotate({ "description": "Path of the file to delete relative to the workspace root." }).check( - Schema.isMinLength(1) - ) -}).annotate({ - "title": "Apply patch delete file operation", - "description": "Instruction for deleting an existing file via the apply_patch tool." -}) -export type ApplyPatchUpdateFileOperationParam = { - readonly "type": "update_file" - readonly "path": string - readonly "diff": string -} -export const ApplyPatchUpdateFileOperationParam = Schema.Struct({ - "type": Schema.Literal("update_file").annotate({ "description": "The operation type. Always `update_file`." }), - "path": Schema.String.annotate({ "description": "Path of the file to update relative to the workspace root." }).check( - Schema.isMinLength(1) - ), - "diff": Schema.String.annotate({ "description": "Unified diff content to apply to the existing file." }).check( - Schema.isMaxLength(10485760) - ) -}).annotate({ - "title": "Apply patch update file operation", - "description": "Instruction for updating an existing file via the apply_patch tool." -}) -export type CompactionTriggerItemParam = { readonly "type": "compaction_trigger" } -export const CompactionTriggerItemParam = Schema.Struct({ - "type": Schema.Literal("compaction_trigger").annotate({ - "description": "The type of the item. Always `compaction_trigger`." - }) -}).annotate({ - "title": "Compaction trigger", - "description": "Compacts the current context. Must be the final input item." -}) -export type ItemReferenceParam = { readonly "type"?: "item_reference" | null; readonly "id": string } -export const ItemReferenceParam = Schema.Struct({ - "type": Schema.optionalKey( - Schema.Union([ - Schema.Literal("item_reference").annotate({ - "description": "The type of item to reference. Always `item_reference`." - }), - Schema.Null - ]) - ), - "id": Schema.String.annotate({ "description": "The ID of the item to reference." }) -}).annotate({ "title": "Item reference", "description": "An internal identifier for an item to reference." }) -export type ConversationResource = { +}).annotate({ "identifier": "CompleteUploadRequest" }) +export type UploadPart = { readonly "id": string - readonly "object": "conversation" - readonly "metadata": unknown readonly "created_at": number + readonly "upload_id": string + readonly "object": "upload.part" } -export const ConversationResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique ID of the conversation." }), - "object": Schema.Literal("conversation").annotate({ - "description": "The object type, which is always `conversation`." - }), - "metadata": Schema.Unknown.annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard.\n Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters." +export const UploadPart = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The upload Part unique identifier, which can be referenced in API endpoints." }), "created_at": Schema.Number.annotate({ - "description": "The time at which the conversation was created, measured in seconds since the Unix epoch.", + "description": "The Unix timestamp (in seconds) for when the Part was created.", "format": "unixtime" - }).check(Schema.isInt()) -}) -export type ImageGenOutputTokensDetails = { readonly "image_tokens": number; readonly "text_tokens": number } -export const ImageGenOutputTokensDetails = Schema.Struct({ - "image_tokens": Schema.Number.annotate({ "description": "The number of image output tokens generated by the model." }) - .check(Schema.isInt()), - "text_tokens": Schema.Number.annotate({ "description": "The number of text output tokens generated by the model." }) - .check(Schema.isInt()) -}).annotate({ - "title": "Image generation output token details", - "description": "The output token details for the image generation." -}) -export type ImageGenInputUsageDetails = { readonly "text_tokens": number; readonly "image_tokens": number } -export const ImageGenInputUsageDetails = Schema.Struct({ - "text_tokens": Schema.Number.annotate({ "description": "The number of text tokens in the input prompt." }).check( - Schema.isInt() - ), - "image_tokens": Schema.Number.annotate({ "description": "The number of image tokens in the input prompt." }).check( - Schema.isInt() - ) -}).annotate({ - "title": "Input usage details", - "description": "The input tokens detailed information for the image generation." -}) -export type SpecificApplyPatchParam = { readonly "type": "apply_patch" } -export const SpecificApplyPatchParam = Schema.Struct({ - "type": Schema.Literal("apply_patch").annotate({ "description": "The tool to call. Always `apply_patch`." }) -}).annotate({ - "title": "Specific apply patch tool choice", - "description": "Forces the model to call the apply_patch tool when executing a tool call." -}) -export type SpecificFunctionShellParam = { readonly "type": "shell" } -export const SpecificFunctionShellParam = Schema.Struct({ - "type": Schema.Literal("shell").annotate({ "description": "The tool to call. Always `shell`." }) + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "upload_id": Schema.String.annotate({ "description": "The ID of the Upload object that this Part was added to." }), + "object": Schema.Literal("upload.part").annotate({ "description": "The object type, which is always `upload.part`." }) }).annotate({ - "title": "Specific shell tool choice", - "description": "Forces the model to call the shell tool when a tool call is required." + "title": "UploadPart", + "description": "The upload Part represents a chunk of bytes we can add to an Upload object.\n", + "identifier": "UploadPart" }) -export type ConversationParam_2 = { readonly "id": string } -export const ConversationParam_2 = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique ID of the conversation." }) -}).annotate({ "title": "Conversation object", "description": "The conversation that this response belongs to." }) -export type ContextManagementParam = { readonly "type": string; readonly "compact_threshold"?: number | null } -export const ContextManagementParam = Schema.Struct({ - "type": Schema.String.annotate({ - "description": "The context management entry type. Currently only 'compaction' is supported." +export type VectorStoreExpirationAfter = { readonly "anchor": "last_active_at"; readonly "days": number } +export const VectorStoreExpirationAfter = Schema.Struct({ + "anchor": Schema.Literal("last_active_at").annotate({ + "description": "Anchor timestamp after which the expiration policy applies. Supported anchors: `last_active_at`." }), - "compact_threshold": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "Token threshold at which compaction should be triggered for this entry." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1000)), - Schema.Null - ]) - ) + "days": Schema.Number.annotate({ + "description": "The number of days after the anchor time that the vector store will expire." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(365).annotate({ "expected": "a value less than or equal to 365" })) +}).annotate({ + "title": "Vector store expiration policy", + "description": "The expiration policy for a vector store.", + "identifier": "VectorStoreExpirationAfter" }) -export type Conversation_2 = { readonly "id": string } -export const Conversation_2 = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The unique ID of the conversation that this response was associated with." - }) +export type AutoChunkingStrategyRequestParam = { readonly "type": "auto" } +export const AutoChunkingStrategyRequestParam = Schema.Struct({ + "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }).annotate({ - "title": "Conversation", + "title": "Auto Chunking Strategy", "description": - "The conversation that this response belonged to. Input items and output items from this response were automatically added to this conversation." + "The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`.", + "identifier": "AutoChunkingStrategyRequestParam" }) -export type UpdateConversationBody = { readonly "metadata": {} | null } -export const UpdateConversationBody = Schema.Struct({ - "metadata": Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]).annotate({ +export type StaticChunkingStrategy = { + readonly "max_chunk_size_tokens": number + readonly "chunk_overlap_tokens": number +} +export const StaticChunkingStrategy = Schema.Struct({ + "max_chunk_size_tokens": Schema.Number.annotate({ "description": - "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard.\n Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters." - }) -}) -export type DeletedConversationResource = { - readonly "object": "conversation.deleted" - readonly "deleted": boolean + "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(100).annotate({ "expected": "a value greater than or equal to 100" }) + ).check(Schema.isLessThanOrEqualTo(4096).annotate({ "expected": "a value less than or equal to 4096" })), + "chunk_overlap_tokens": Schema.Number.annotate({ + "description": + "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ "identifier": "StaticChunkingStrategy" }) +export type DeleteVectorStoreResponse = { readonly "id": string + readonly "deleted": boolean + readonly "object": "vector_store.deleted" } -export const DeletedConversationResource = Schema.Struct({ - "object": Schema.Literal("conversation.deleted"), +export const DeleteVectorStoreResponse = Schema.Struct({ + "id": Schema.String, "deleted": Schema.Boolean, - "id": Schema.String -}) -export type OrderEnum = "asc" | "desc" -export const OrderEnum = Schema.Literals(["asc", "desc"]) -export type VideoResource = { + "object": Schema.Literal("vector_store.deleted") +}).annotate({ "identifier": "DeleteVectorStoreResponse" }) +export type VectorStoreFileBatchObject = { readonly "id": string - readonly "object": "video" - readonly "model": - | string - | "sora-2" - | "sora-2-pro" - | "sora-2-2025-10-06" - | "sora-2-pro-2025-10-06" - | "sora-2-2025-12-08" - readonly "status": "queued" | "in_progress" | "completed" | "failed" - readonly "progress": number + readonly "object": "vector_store.file_batch" readonly "created_at": number - readonly "completed_at": number | null - readonly "expires_at": number | null - readonly "prompt": string | null - readonly "size": "720x1280" | "1280x720" | "1024x1792" | "1792x1024" - readonly "seconds": string - readonly "remixed_from_video_id": string | null - readonly "error": { readonly "code": string; readonly "message": string } | null + readonly "vector_store_id": string + readonly "status": "in_progress" | "completed" | "cancelled" | "failed" + readonly "file_counts": { + readonly "in_progress": number + readonly "completed": number + readonly "failed": number + readonly "cancelled": number + readonly "total": number + } } -export const VideoResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Unique identifier for the video job." }), - "object": Schema.Literal("video").annotate({ "description": "The object type, which is always `video`." }), - "model": Schema.Union([ - Schema.String, - Schema.Literals(["sora-2", "sora-2-pro", "sora-2-2025-10-06", "sora-2-pro-2025-10-06", "sora-2-2025-12-08"]) - ]).annotate({ "description": "The video generation model that produced the job." }), - "status": Schema.Literals(["queued", "in_progress", "completed", "failed"]).annotate({ - "description": "Current lifecycle status of the video job." +export const VectorStoreFileBatchObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("vector_store.file_batch").annotate({ + "description": "The object type, which is always `vector_store.file_batch`." }), - "progress": Schema.Number.annotate({ "description": "Approximate completion percentage for the generation task." }) - .check(Schema.isInt()), "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (seconds) for when the job was created.", + "description": "The Unix timestamp (in seconds) for when the vector store files batch was created.", "format": "unixtime" - }).check(Schema.isInt()), - "completed_at": Schema.Union([ - Schema.Number.annotate({ - "description": "Unix timestamp (seconds) for when the job completed, if finished.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "expires_at": Schema.Union([ - Schema.Number.annotate({ - "description": "Unix timestamp (seconds) for when the downloadable assets expire, if set.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "prompt": Schema.Union([ - Schema.String.annotate({ "description": "The prompt that was used to generate the video." }), - Schema.Null - ]), - "size": Schema.Literals(["720x1280", "1280x720", "1024x1792", "1792x1024"]).annotate({ - "description": "The resolution of the generated video." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "vector_store_id": Schema.String.annotate({ + "description": + "The ID of the [vector store](https://developers.openai.com/api/reference/resources/vector_stores) that the [File](https://developers.openai.com/api/reference/resources/files) is attached to." }), - "seconds": Schema.String.annotate({ - "description": "Duration of the generated clip in seconds. For extensions, this is the stitched total duration." + "status": Schema.Literals(["in_progress", "completed", "cancelled", "failed"]).annotate({ + "description": + "The status of the vector store files batch, which can be either `in_progress`, `completed`, `cancelled` or `failed`." }), - "remixed_from_video_id": Schema.Union([ - Schema.String.annotate({ "description": "Identifier of the source video if this video is a remix." }), - Schema.Null - ]), - "error": Schema.Union([ + "file_counts": Schema.Struct({ + "in_progress": Schema.Number.annotate({ "description": "The number of files that are currently being processed." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "completed": Schema.Number.annotate({ "description": "The number of files that have been processed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "failed": Schema.Number.annotate({ "description": "The number of files that have failed to process." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "cancelled": Schema.Number.annotate({ "description": "The number of files that where cancelled." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "total": Schema.Number.annotate({ "description": "The total number of files." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }) +}).annotate({ + "title": "Vector store file batch", + "description": "A batch of files attached to a vector store.", + "identifier": "VectorStoreFileBatchObject" +}) +export type OtherChunkingStrategyResponseParam = { readonly "type": "other" } +export const OtherChunkingStrategyResponseParam = Schema.Struct({ + "type": Schema.Literal("other").annotate({ "description": "Always `other`." }) +}).annotate({ + "title": "Other Chunking Strategy", + "description": + "This is returned when the chunking strategy is unknown. Typically, this is because the file was indexed before the `chunking_strategy` concept was introduced in the API.", + "identifier": "OtherChunkingStrategyResponseParam" +}) +export type DeleteVectorStoreFileResponse = { + readonly "id": string + readonly "deleted": boolean + readonly "object": "vector_store.file.deleted" +} +export const DeleteVectorStoreFileResponse = Schema.Struct({ + "id": Schema.String, + "deleted": Schema.Boolean, + "object": Schema.Literal("vector_store.file.deleted") +}).annotate({ "identifier": "DeleteVectorStoreFileResponse" }) +export type VectorStoreFileContentResponse = { + readonly "object": "vector_store.file_content.page" + readonly "data": ReadonlyArray<{ readonly "type"?: string; readonly "text"?: string }> + readonly "has_more": boolean + readonly "next_page": string | null +} +export const VectorStoreFileContentResponse = Schema.Struct({ + "object": Schema.Literal("vector_store.file_content.page").annotate({ + "description": "The object type, which is always `vector_store.file_content.page`" + }), + "data": Schema.Array( Schema.Struct({ - "code": Schema.String.annotate({ "description": "A machine-readable error code that was returned." }), - "message": Schema.String.annotate({ - "description": "A human-readable description of the error that was returned." - }) - }).annotate({ - "title": "Error", - "description": "Error payload that explains why generation failed, if applicable." - }), + "type": Schema.optionalKey( + Schema.String.annotate({ "description": "The content type (currently only `\"text\"`)" }) + ), + "text": Schema.optionalKey(Schema.String.annotate({ "description": "The text content" })) + }) + ).annotate({ "description": "Parsed content of the file." }), + "has_more": Schema.Boolean.annotate({ "description": "Indicates if there are more content pages to fetch." }), + "next_page": Schema.Union([ + Schema.String.annotate({ "description": "The token for the next page, if any." }), Schema.Null ]) -}).annotate({ "title": "Video job", "description": "Structured information describing a generated video job." }) -export type ImageRefParam_2 = { readonly "image_url"?: string; readonly "file_id"?: string } -export const ImageRefParam_2 = Schema.Struct({ - "image_url": Schema.optionalKey( - Schema.String.annotate({ "description": "A fully qualified URL or base64-encoded data URL.", "format": "uri" }) - .check(Schema.isMaxLength(20971520)) - ), - "file_id": Schema.optionalKey(Schema.String) +}).annotate({ + "description": "Represents the parsed content of a vector store file.", + "identifier": "VectorStoreFileContentResponse" }) -export type CreateVideoJsonBody = { - readonly "model"?: - | string - | "sora-2" - | "sora-2-pro" - | "sora-2-2025-10-06" - | "sora-2-pro-2025-10-06" - | "sora-2-2025-12-08" - readonly "prompt": string - readonly "input_reference"?: { readonly "image_url"?: string; readonly "file_id"?: string } - readonly "seconds"?: "4" | "8" | "12" - readonly "size"?: "720x1280" | "1280x720" | "1024x1792" | "1792x1024" +export type VectorStoreSearchResultContentObject = { readonly "type": "text"; readonly "text": string } +export const VectorStoreSearchResultContentObject = Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "The type of content." }), + "text": Schema.String.annotate({ "description": "The text content returned from search." }) +}).annotate({ "identifier": "VectorStoreSearchResultContentObject" }) +export type DeletedConversationResource = { + readonly "object": "conversation.deleted" + readonly "deleted": boolean + readonly "id": string } -export const CreateVideoJsonBody = Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals(["sora-2", "sora-2-pro", "sora-2-2025-10-06", "sora-2-pro-2025-10-06", "sora-2-2025-12-08"]) - ]).annotate({ - "description": "The video generation model to use (allowed values: sora-2, sora-2-pro). Defaults to `sora-2`." +export const DeletedConversationResource = Schema.Struct({ + "object": Schema.Literal("conversation.deleted"), + "deleted": Schema.Boolean, + "id": Schema.String +}).annotate({ "identifier": "DeletedConversationResource" }) +export type SafetyCaseNoticeType = "warning" | "deactivation" +export const SafetyCaseNoticeType = Schema.Literals(["warning", "deactivation"]).annotate({ + "identifier": "SafetyCaseNoticeType" +}) +export type SafetyAlertErrorType = + | "potentially_unintended_data_transfer" + | "potentially_unintended_data_access" + | "potentially_unintended_destructive_activity" + | "other" +export const SafetyAlertErrorType = Schema.Literals([ + "potentially_unintended_data_transfer", + "potentially_unintended_data_access", + "potentially_unintended_destructive_activity", + "other" +]).annotate({ "identifier": "SafetyAlertErrorType" }) +export type DecisionsUsageBucketWidth = "1m" | "1h" | "1d" +export const DecisionsUsageBucketWidth = Schema.Literals(["1m", "1h", "1d"]).annotate({ + "identifier": "DecisionsUsageBucketWidth" +}) +export type DecisionsUsageGroupBy = + | "project_id" + | "user_id" + | "api_key_id" + | "model" + | "batch" + | "service_tier" + | "api_source" +export const DecisionsUsageGroupBy = Schema.Literals([ + "project_id", + "user_id", + "api_key_id", + "model", + "batch", + "service_tier", + "api_source" +]).annotate({ "identifier": "DecisionsUsageGroupBy" }) +export type DecisionsUsageApiSource = "agents_api" | "unlabeled" +export const DecisionsUsageApiSource = Schema.Literals(["agents_api", "unlabeled"]).annotate({ + "identifier": "DecisionsUsageApiSource" +}) +export type DecisionsUsageErrorDetails = { + readonly "code": string | null + readonly "message": string + readonly "param": string | null + readonly "type": string +} +export const DecisionsUsageErrorDetails = Schema.Struct({ + "code": Schema.Union([Schema.String, Schema.Null]), + "message": Schema.String, + "param": Schema.Union([Schema.String, Schema.Null]), + "type": Schema.String +}).annotate({ "identifier": "DecisionsUsageErrorDetails" }) +export type ExternalStorageOrder = "asc" | "desc" +export const ExternalStorageOrder = Schema.Literals(["asc", "desc"]).annotate({ "identifier": "ExternalStorageOrder" }) +export type ExternalStorageStatus = "pending" | "validated" | "unhealthy" +export const ExternalStorageStatus = Schema.Literals(["pending", "validated", "unhealthy"]).annotate({ + "identifier": "ExternalStorageStatus" +}) +export type AwsExternalStorageProviderParams = { + readonly "type": "aws" + readonly "bucket": string + readonly "role_arn": string +} +export const AwsExternalStorageProviderParams = Schema.Struct({ + "type": Schema.Literal("aws"), + "bucket": Schema.String, + "role_arn": Schema.String +}).annotate({ "identifier": "AwsExternalStorageProviderParams" }) +export type AzureExternalStorageProviderParams = { + readonly "type": "azure" + readonly "tenant_id": string + readonly "subscription_id": string + readonly "resource_group": string + readonly "account_name": string + readonly "container": string +} +export const AzureExternalStorageProviderParams = Schema.Struct({ + "type": Schema.Literal("azure"), + "tenant_id": Schema.String, + "subscription_id": Schema.String, + "resource_group": Schema.String, + "account_name": Schema.String, + "container": Schema.String +}).annotate({ "identifier": "AzureExternalStorageProviderParams" }) +export type GcpExternalStorageProviderParams = { + readonly "type": "gcp" + readonly "bucket": string + readonly "workload_identity_project_number": string + readonly "workload_identity_pool_id": string + readonly "workload_identity_provider_id": string +} +export const GcpExternalStorageProviderParams = Schema.Struct({ + "type": Schema.Literal("gcp"), + "bucket": Schema.String, + "workload_identity_project_number": Schema.String, + "workload_identity_pool_id": Schema.String, + "workload_identity_provider_id": Schema.String +}).annotate({ "identifier": "GcpExternalStorageProviderParams" }) +export type OciExternalStorageProviderParams = { + readonly "type": "oci" + readonly "tenancy_ocid": string + readonly "region": string + readonly "bucket": string +} +export const OciExternalStorageProviderParams = Schema.Struct({ + "type": Schema.Literal("oci"), + "tenancy_ocid": Schema.String, + "region": Schema.String, + "bucket": Schema.String +}).annotate({ "identifier": "OciExternalStorageProviderParams" }) +export type ExternalStorageDeletedResource = { + readonly "object": "organization.external_storage.deleted" + readonly "id": string + readonly "deleted": boolean +} +export const ExternalStorageDeletedResource = Schema.Struct({ + "object": Schema.Literal("organization.external_storage.deleted"), + "id": Schema.String, + "deleted": Schema.Boolean +}).annotate({ "identifier": "ExternalStorageDeletedResource" }) +export type SpendLimitCurrency = string | "USD" +export const SpendLimitCurrency = Schema.Union([Schema.String, Schema.Literal("USD")]).annotate({ + "identifier": "SpendLimitCurrency" +}) +export type SpendLimitInterval = string | "month" +export const SpendLimitInterval = Schema.Union([Schema.String, Schema.Literal("month")]).annotate({ + "identifier": "SpendLimitInterval" +}) +export type SpendLimitEnforcementStatus = string | "inactive" | "enforcing" +export const SpendLimitEnforcementStatus = Schema.Union([Schema.String, Schema.Literals(["inactive", "enforcing"])]) + .annotate({ "identifier": "SpendLimitEnforcementStatus" }) +export type UpdateOrganizationSpendLimitBody = { + readonly "threshold_amount": number + readonly "currency": "USD" + readonly "interval": "month" +} +export const UpdateOrganizationSpendLimitBody = Schema.Struct({ + "threshold_amount": Schema.Number.annotate({ "description": "The hard spend limit amount, in cents." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" })), + "currency": Schema.Literal("USD").annotate({ + "description": "The currency for the threshold amount. Currently, only `USD` is supported." + }), + "interval": Schema.Literal("month").annotate({ + "description": "The time interval for evaluating spend against the threshold. Currently, only `month` is supported." + }) +}).annotate({ + "description": "Parameters for the hard spend limit you want to create or replace.", + "identifier": "UpdateOrganizationSpendLimitBody" +}) +export type OrganizationSpendLimitDeletedResource = { + readonly "object": "organization.spend_limit.deleted" + readonly "deleted": boolean +} +export const OrganizationSpendLimitDeletedResource = Schema.Struct({ + "object": Schema.Literal("organization.spend_limit.deleted").annotate({ + "description": "The object type, which is always `organization.spend_limit.deleted`." + }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the hard spend limit was deleted." }) +}).annotate({ + "description": "Confirmation payload returned after deleting an organization hard spend limit.", + "identifier": "OrganizationSpendLimitDeletedResource" +}) +export type UpdateProjectSpendLimitBody = { + readonly "threshold_amount": number + readonly "currency": "USD" + readonly "interval": "month" +} +export const UpdateProjectSpendLimitBody = Schema.Struct({ + "threshold_amount": Schema.Number.annotate({ "description": "The hard spend limit amount, in cents." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" })), + "currency": Schema.Literal("USD").annotate({ + "description": "The currency for the threshold amount. Currently, only `USD` is supported." + }), + "interval": Schema.Literal("month").annotate({ + "description": "The time interval for evaluating spend against the threshold. Currently, only `month` is supported." + }) +}).annotate({ + "description": "Parameters for the hard spend limit you want to create or replace.", + "identifier": "UpdateProjectSpendLimitBody" +}) +export type ProjectSpendLimitDeletedResource = { + readonly "object": "project.spend_limit.deleted" + readonly "deleted": boolean +} +export const ProjectSpendLimitDeletedResource = Schema.Struct({ + "object": Schema.Literal("project.spend_limit.deleted").annotate({ + "description": "The object type, which is always `project.spend_limit.deleted`." + }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the hard spend limit was deleted." }) +}).annotate({ + "description": "Confirmation payload returned after deleting a project hard spend limit.", + "identifier": "ProjectSpendLimitDeletedResource" +}) +export type CreateProjectServiceAccountApiKeyBody = { + readonly "name"?: string + readonly "scopes"?: ReadonlyArray + readonly "expires_in_seconds"?: number | null +} +export const CreateProjectServiceAccountApiKeyBody = Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "API key name." })), + "scopes": Schema.optionalKey( + Schema.Array(Schema.String.annotate({ "description": "API key scope." })).annotate({ + "description": "API key scopes." }) ), - "prompt": Schema.String.annotate({ "description": "Text prompt that describes the video to generate." }).check( - Schema.isMinLength(1) - ).check(Schema.isMaxLength(32000)), - "input_reference": Schema.optionalKey( - Schema.Struct({ - "image_url": Schema.optionalKey( - Schema.String.annotate({ "description": "A fully qualified URL or base64-encoded data URL.", "format": "uri" }) - .check(Schema.isMaxLength(20971520)) + "expires_in_seconds": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "Number of seconds until the API key expires." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" })).check( + Schema.isLessThanOrEqualTo(31536000).annotate({ "expected": "a value less than or equal to 31536000" }) ), - "file_id": Schema.optionalKey(Schema.String) - }).annotate({ - "description": - "Optional reference object that guides generation. Provide exactly one of `image_url` or `file_id`." - }) - ), - "seconds": Schema.optionalKey( - Schema.Literals(["4", "8", "12"]).annotate({ - "description": "Clip duration in seconds (allowed values: 4, 8, 12). Defaults to 4 seconds." - }) - ), - "size": Schema.optionalKey( - Schema.Literals(["720x1280", "1280x720", "1024x1792", "1792x1024"]).annotate({ - "description": - "Output resolution formatted as width x height (allowed values: 720x1280, 1280x720, 1024x1792, 1792x1024). Defaults to 720x1280." - }) + Schema.Null + ]) ) }).annotate({ - "title": "Create video JSON request", - "description": "JSON parameters for creating a new video generation job." + "description": "The service account API key create request payload.", + "identifier": "CreateProjectServiceAccountApiKeyBody" }) -export type CreateVideoCharacterBody = { readonly "video": string; readonly "name": string } -export const CreateVideoCharacterBody = Schema.Struct({ - "video": Schema.String.annotate({ "description": "Video file used to create a character.", "format": "binary" }), - "name": Schema.String.annotate({ "description": "Display name for this API character." }).check(Schema.isMinLength(1)) - .check(Schema.isMaxLength(80)) -}).annotate({ - "title": "Create character request", - "description": "Parameters for creating a character from an uploaded video." +export type ServiceAccountApiKeyBody = { + readonly "object": "organization.project.service_account.api_key" + readonly "value": string + readonly "name": string + readonly "created_at": number + readonly "expires_at"?: number | null + readonly "id": string +} +export const ServiceAccountApiKeyBody = Schema.Struct({ + "object": Schema.Literal("organization.project.service_account.api_key").annotate({ + "description": "The object type, which is always `organization.project.service_account.api_key`" + }), + "value": Schema.String.annotate({ "description": "The unredacted API key value." }), + "name": Schema.String.annotate({ "description": "The name of the API key." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) when the API key was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "expires_at": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) when the API key expires, or null if it does not expire.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ), + "id": Schema.String.annotate({ "description": "The identifier of the API key." }) +}).annotate({ "identifier": "ServiceAccountApiKeyBody" }) +export type ProvenanceCheckObject = "content_provenance_check" +export const ProvenanceCheckObject = Schema.Literal("content_provenance_check").annotate({ + "identifier": "ProvenanceCheckObject" +}) +export type ProvenanceDetectionResultApi = "detected" | "not_detected" +export const ProvenanceDetectionResultApi = Schema.Literals(["detected", "not_detected"]).annotate({ + "identifier": "ProvenanceDetectionResultApi" +}) +export type C2PAValidationStateApi = "trusted" | "valid" | "invalid" | "not_present" +export const C2PAValidationStateApi = Schema.Literals(["trusted", "valid", "invalid", "not_present"]).annotate({ + "identifier": "C2PAValidationStateApi" }) +export type OrderEnum = "asc" | "desc" +export const OrderEnum = Schema.Literals(["asc", "desc"]).annotate({ "identifier": "OrderEnum" }) +export type VideoModel = + | string + | "sora-2" + | "sora-2-pro" + | "sora-2-2025-10-06" + | "sora-2-pro-2025-10-06" + | "sora-2-2025-12-08" +export const VideoModel = Schema.Union([ + Schema.String, + Schema.Literals(["sora-2", "sora-2-pro", "sora-2-2025-10-06", "sora-2-pro-2025-10-06", "sora-2-2025-12-08"]) +]).annotate({ "identifier": "VideoModel" }) +export type VideoStatus = "queued" | "in_progress" | "completed" | "failed" +export const VideoStatus = Schema.Literals(["queued", "in_progress", "completed", "failed"]).annotate({ + "identifier": "VideoStatus" +}) +export type VideoSize = "720x1280" | "1280x720" | "1024x1792" | "1792x1024" +export const VideoSize = Schema.Literals(["720x1280", "1280x720", "1024x1792", "1792x1024"]).annotate({ + "identifier": "VideoSize" +}) +export type ImageRefParam_2 = { readonly "image_url"?: string; readonly "file_id"?: string } +export const ImageRefParam_2 = Schema.Struct({ + "image_url": Schema.optionalKey( + Schema.String.annotate({ "description": "A fully qualified URL or base64-encoded data URL.", "format": "uri" }) + .check(Schema.isMaxCodePoints(20971520).annotate({ "expected": "a string with at most 20971520 code points" })) + ), + "file_id": Schema.optionalKey(Schema.String) +}).annotate({ "identifier": "ImageRefParam-2" }) +export type VideoSeconds = "4" | "8" | "12" +export const VideoSeconds = Schema.Literals(["4", "8", "12"]).annotate({ "identifier": "VideoSeconds" }) export type VideoCharacterResource = { readonly "id": string | null readonly "name": string | null @@ -9677,40 +9971,12 @@ export const VideoCharacterResource = Schema.Struct({ "created_at": Schema.Number.annotate({ "description": "Unix timestamp (in seconds) when the character was created.", "format": "unixtime" - }).check(Schema.isInt()) -}) + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ "identifier": "VideoCharacterResource" }) export type VideoReferenceInputParam = { readonly "id": string } export const VideoReferenceInputParam = Schema.Struct({ "id": Schema.String.annotate({ "description": "The identifier of the completed video." }) -}).annotate({ "description": "Reference to the completed video." }) -export type CreateVideoEditJsonBody = { readonly "video": { readonly "id": string }; readonly "prompt": string } -export const CreateVideoEditJsonBody = Schema.Struct({ - "video": Schema.Struct({ "id": Schema.String.annotate({ "description": "The identifier of the completed video." }) }) - .annotate({ "description": "Reference to the completed video to edit." }), - "prompt": Schema.String.annotate({ "description": "Text prompt that describes how to edit the source video." }).check( - Schema.isMinLength(1) - ).check(Schema.isMaxLength(32000)) -}).annotate({ - "title": "Create video edit JSON request", - "description": "JSON parameters for editing an existing generated video." -}) -export type CreateVideoExtendJsonBody = { - readonly "video": { readonly "id": string } - readonly "prompt": string - readonly "seconds": "4" | "8" | "12" -} -export const CreateVideoExtendJsonBody = Schema.Struct({ - "video": Schema.Struct({ "id": Schema.String.annotate({ "description": "The identifier of the completed video." }) }) - .annotate({ "description": "Reference to the completed video to extend." }), - "prompt": Schema.String.annotate({ "description": "Updated text prompt that directs the extension generation." }) - .check(Schema.isMinLength(1)).check(Schema.isMaxLength(32000)), - "seconds": Schema.Literals(["4", "8", "12"]).annotate({ - "description": "Length of the newly generated extension segment in seconds (allowed values: 4, 8, 12, 16, 20)." - }) -}).annotate({ - "title": "Create video extension JSON request", - "description": "JSON parameters for extending an existing generated video." -}) +}).annotate({ "description": "Reference to the completed video.", "identifier": "VideoReferenceInputParam" }) export type DeletedVideoResource = { readonly "object": "video.deleted" readonly "deleted": boolean @@ -9724,24 +9990,42 @@ export const DeletedVideoResource = Schema.Struct({ "id": Schema.String.annotate({ "description": "Identifier of the deleted video." }) }).annotate({ "title": "Deleted video response", - "description": "Confirmation payload returned after deleting a video." + "description": "Confirmation payload returned after deleting a video.", + "identifier": "DeletedVideoResource" }) export type VideoContentVariant = "video" | "thumbnail" | "spritesheet" -export const VideoContentVariant = Schema.Literals(["video", "thumbnail", "spritesheet"]) +export const VideoContentVariant = Schema.Literals(["video", "thumbnail", "spritesheet"]).annotate({ + "identifier": "VideoContentVariant" +}) export type CreateVideoRemixBody = { readonly "prompt": string } export const CreateVideoRemixBody = Schema.Struct({ "prompt": Schema.String.annotate({ "description": "Updated text prompt that directs the remix generation." }).check( - Schema.isMinLength(1) - ).check(Schema.isMaxLength(32000)) + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(32000).annotate({ "expected": "a string with at most 32000 code points" })) }).annotate({ "title": "Create video remix request", - "description": "Parameters for remixing an existing generated video." + "description": "Parameters for remixing an existing generated video.", + "identifier": "CreateVideoRemixBody" +}) +export type TruncationEnum = "auto" | "disabled" +export const TruncationEnum = Schema.Literals(["auto", "disabled"]).annotate({ "identifier": "TruncationEnum" }) +export type PersonalityEnum = string | "friendly" | "pragmatic" +export const PersonalityEnum = Schema.Union([Schema.String, Schema.Literals(["friendly", "pragmatic"])]).annotate({ + "identifier": "PersonalityEnum" }) export type TokenCountsResource = { readonly "object": "response.input_tokens"; readonly "input_tokens": number } export const TokenCountsResource = Schema.Struct({ "object": Schema.Literal("response.input_tokens"), - "input_tokens": Schema.Number.check(Schema.isInt()) -}).annotate({ "title": "Token counts" }) + "input_tokens": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ "title": "Token counts", "identifier": "TokenCountsResource" }) +export type PromptCacheRetentionEnum = "in_memory" | "in-memory" | "24h" +export const PromptCacheRetentionEnum = Schema.Literals(["in_memory", "in-memory", "24h"]).annotate({ + "identifier": "PromptCacheRetentionEnum" +}) +export type ServiceTierEnum = "auto" | "default" | "fast" | "flex" | "priority" +export const ServiceTierEnum = Schema.Literals(["auto", "default", "fast", "flex", "priority"]).annotate({ + "identifier": "ServiceTierEnum" +}) export type SkillResource = { readonly "id": string readonly "object": "skill" @@ -9759,26 +10043,31 @@ export const SkillResource = Schema.Struct({ "created_at": Schema.Number.annotate({ "description": "Unix timestamp (seconds) for when the skill was created.", "format": "unixtime" - }).check(Schema.isInt()), + }).check(Schema.isInt().annotate({ "expected": "an integer" })), "default_version": Schema.String.annotate({ "description": "Default version for the skill." }), "latest_version": Schema.String.annotate({ "description": "Latest version for the skill." }) -}) +}).annotate({ "identifier": "SkillResource" }) export type CreateSkillBody = { readonly "files": ReadonlyArray | string } export const CreateSkillBody = Schema.Struct({ "files": Schema.Union([ Schema.Array(Schema.String.annotate({ "format": "binary" })).annotate({ "description": "Skill files to upload (directory upload) or a single zip file." - }).check(Schema.isMaxLength(500)), + }).check(Schema.isMaxLength(500).annotate({ "expected": "a value with a length of at most 500" })), Schema.String.annotate({ "description": "Skill zip file to upload.", "format": "binary" }) ], { mode: "oneOf" }) }).annotate({ "title": "Create skill request", - "description": "Uploads a skill either as a directory (multipart `files[]`) or as a single zip file." + "description": "Uploads a skill either as a directory (multipart `files[]`) or as a single zip file.", + "identifier": "CreateSkillBody" }) export type SetDefaultSkillVersionBody = { readonly "default_version": string } export const SetDefaultSkillVersionBody = Schema.Struct({ "default_version": Schema.String.annotate({ "description": "The skill version number to set as default." }) -}).annotate({ "title": "Update skill request", "description": "Updates the default version pointer for a skill." }) +}).annotate({ + "title": "Update skill request", + "description": "Updates the default version pointer for a skill.", + "identifier": "SetDefaultSkillVersionBody" +}) export type DeletedSkillResource = { readonly "object": "skill.deleted" readonly "deleted": boolean @@ -9788,7 +10077,7 @@ export const DeletedSkillResource = Schema.Struct({ "object": Schema.Literal("skill.deleted"), "deleted": Schema.Boolean, "id": Schema.String -}) +}).annotate({ "identifier": "DeletedSkillResource" }) export type SkillVersionResource = { readonly "object": "skill.version" readonly "id": string @@ -9806,22 +10095,26 @@ export const SkillVersionResource = Schema.Struct({ "created_at": Schema.Number.annotate({ "description": "Unix timestamp (seconds) for when the version was created.", "format": "unixtime" - }).check(Schema.isInt()), + }).check(Schema.isInt().annotate({ "expected": "an integer" })), "name": Schema.String.annotate({ "description": "Name of the skill version." }), "description": Schema.String.annotate({ "description": "Description of the skill version." }) -}) +}).annotate({ "identifier": "SkillVersionResource" }) export type CreateSkillVersionBody = { readonly "files": ReadonlyArray | string; readonly "default"?: boolean } export const CreateSkillVersionBody = Schema.Struct({ "files": Schema.Union([ Schema.Array(Schema.String.annotate({ "format": "binary" })).annotate({ "description": "Skill files to upload (directory upload) or a single zip file." - }).check(Schema.isMaxLength(500)), + }).check(Schema.isMaxLength(500).annotate({ "expected": "a value with a length of at most 500" })), Schema.String.annotate({ "description": "Skill zip file to upload.", "format": "binary" }) ], { mode: "oneOf" }), "default": Schema.optionalKey( Schema.Boolean.annotate({ "description": "Whether to set this version as the default." }) ) -}).annotate({ "title": "Create skill version request", "description": "Uploads a new immutable version of a skill." }) +}).annotate({ + "title": "Create skill version request", + "description": "Uploads a new immutable version of a skill.", + "identifier": "CreateSkillVersionBody" +}) export type DeletedSkillVersionResource = { readonly "object": "skill.version.deleted" readonly "deleted": boolean @@ -9833,305 +10126,219 @@ export const DeletedSkillVersionResource = Schema.Struct({ "deleted": Schema.Boolean, "id": Schema.String, "version": Schema.String.annotate({ "description": "The deleted skill version." }) +}).annotate({ "identifier": "DeletedSkillVersionResource" }) +export type ChatkitWorkflowTracing = { readonly "enabled": boolean } +export const ChatkitWorkflowTracing = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Indicates whether tracing is enabled." }) +}).annotate({ + "title": "Tracing Configuration", + "description": "Controls diagnostic tracing during the session.", + "identifier": "ChatkitWorkflowTracing" }) -export type ChatSessionResource = { - readonly "id": string - readonly "object": "chatkit.session" - readonly "expires_at": number - readonly "client_secret": string - readonly "workflow": { - readonly "id": string - readonly "version": string | null - readonly "state_variables": {} | null - readonly "tracing": { readonly "enabled": boolean } - } - readonly "user": string - readonly "rate_limits": { readonly "max_requests_per_1_minute": number } - readonly "max_requests_per_1_minute": number - readonly "status": "active" | "expired" | "cancelled" - readonly "chatkit_configuration": { - readonly "automatic_thread_titling": { readonly "enabled": boolean } - readonly "file_upload": { - readonly "enabled": boolean - readonly "max_file_size": number | null - readonly "max_files": number | null - } - readonly "history": { readonly "enabled": boolean; readonly "recent_threads": number | null } - } -} -export const ChatSessionResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier for the ChatKit session." }), - "object": Schema.Literal("chatkit.session").annotate({ - "description": "Type discriminator that is always `chatkit.session`." - }), - "expires_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) for when the session expires.", - "format": "unixtime" - }).check(Schema.isInt()), - "client_secret": Schema.String.annotate({ - "description": "Ephemeral client secret that authenticates session requests." - }), - "workflow": Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier of the workflow backing the session." }), - "version": Schema.Union([ - Schema.String.annotate({ - "description": - "Specific workflow version used for the session. Defaults to null when using the latest deployment." - }), - Schema.Null - ]), - "state_variables": Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "State variable key-value pairs applied when invoking the workflow. Defaults to null when no overrides were provided." - }), - Schema.Null - ]), - "tracing": Schema.Struct({ - "enabled": Schema.Boolean.annotate({ "description": "Indicates whether tracing is enabled." }) - }).annotate({ "title": "Tracing Configuration", "description": "Tracing settings applied to the workflow." }) - }).annotate({ "title": "Workflow", "description": "Workflow metadata for the session." }), - "user": Schema.String.annotate({ "description": "User identifier associated with the session." }), - "rate_limits": Schema.Struct({ - "max_requests_per_1_minute": Schema.Number.annotate({ - "description": "Maximum allowed requests per one-minute window." - }).check(Schema.isInt()) - }).annotate({ "title": "Rate limits", "description": "Resolved rate limit values." }), +export type ChatSessionRateLimits = { readonly "max_requests_per_1_minute": number } +export const ChatSessionRateLimits = Schema.Struct({ "max_requests_per_1_minute": Schema.Number.annotate({ - "description": "Convenience copy of the per-minute request limit." - }).check(Schema.isInt()), - "status": Schema.Literals(["active", "expired", "cancelled"]).annotate({ - "description": "Current lifecycle state of the session." - }), - "chatkit_configuration": Schema.Struct({ - "automatic_thread_titling": Schema.Struct({ - "enabled": Schema.Boolean.annotate({ "description": "Whether automatic thread titling is enabled." }) - }).annotate({ "title": "Automatic thread titling", "description": "Automatic thread titling preferences." }), - "file_upload": Schema.Struct({ - "enabled": Schema.Boolean.annotate({ "description": "Indicates if uploads are enabled for the session." }), - "max_file_size": Schema.Union([ - Schema.Number.annotate({ "description": "Maximum upload size in megabytes." }).check(Schema.isInt()), - Schema.Null - ]), - "max_files": Schema.Union([ - Schema.Number.annotate({ "description": "Maximum number of uploads allowed during the session." }).check( - Schema.isInt() - ), - Schema.Null - ]) - }).annotate({ "title": "File upload settings", "description": "Upload settings for the session." }), - "history": Schema.Struct({ - "enabled": Schema.Boolean.annotate({ "description": "Indicates if chat history is persisted for the session." }), - "recent_threads": Schema.Union([ - Schema.Number.annotate({ - "description": - "Number of prior threads surfaced in history views. Defaults to null when all history is retained." - }).check(Schema.isInt()), - Schema.Null - ]) - }).annotate({ "title": "History settings", "description": "History retention configuration." }) - }).annotate({ - "title": "ChatKit configuration", - "description": "Resolved ChatKit feature configuration for the session." - }) + "description": "Maximum allowed requests per one-minute window." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) }).annotate({ - "title": "The chat session object", - "description": "Represents a ChatKit session and its resolved configuration." + "title": "Rate limits", + "description": "Active per-minute request limit for the session.", + "identifier": "ChatSessionRateLimits" }) -export type CreateChatSessionBody = { - readonly "workflow": { - readonly "id": string - readonly "version"?: string - readonly "state_variables"?: {} - readonly "tracing"?: { readonly "enabled"?: boolean } - } - readonly "user": string - readonly "expires_after"?: { readonly "anchor": "created_at"; readonly "seconds": number } - readonly "rate_limits"?: { readonly "max_requests_per_1_minute"?: number } - readonly "chatkit_configuration"?: { - readonly "automatic_thread_titling"?: { readonly "enabled"?: boolean } - readonly "file_upload"?: { - readonly "enabled"?: boolean - readonly "max_file_size"?: number - readonly "max_files"?: number - } - readonly "history"?: { readonly "enabled"?: boolean; readonly "recent_threads"?: number } - } -} -export const CreateChatSessionBody = Schema.Struct({ - "workflow": Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier for the workflow invoked by the session." }), - "version": Schema.optionalKey( - Schema.String.annotate({ - "description": "Specific workflow version to run. Defaults to the latest deployed version." - }) +export type ChatSessionStatus = "active" | "expired" | "cancelled" +export const ChatSessionStatus = Schema.Literals(["active", "expired", "cancelled"]).annotate({ + "identifier": "ChatSessionStatus" +}) +export type ChatSessionAutomaticThreadTitling = { readonly "enabled": boolean } +export const ChatSessionAutomaticThreadTitling = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Whether automatic thread titling is enabled." }) +}).annotate({ + "title": "Automatic thread titling", + "description": "Automatic thread title preferences for the session.", + "identifier": "ChatSessionAutomaticThreadTitling" +}) +export type ChatSessionFileUpload = { + readonly "enabled": boolean + readonly "max_file_size": number | null + readonly "max_files": number | null +} +export const ChatSessionFileUpload = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Indicates if uploads are enabled for the session." }), + "max_file_size": Schema.Union([ + Schema.Number.annotate({ "description": "Maximum upload size in megabytes." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "state_variables": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "State variables forwarded to the workflow. Keys may be up to 64 characters, values must be primitive types, and the map defaults to an empty object." - }).check(Schema.isMaxProperties(64)) + Schema.Null + ]), + "max_files": Schema.Union([ + Schema.Number.annotate({ "description": "Maximum number of uploads allowed during the session." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "tracing": Schema.optionalKey( - Schema.Struct({ - "enabled": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether tracing is enabled during the session. Defaults to true." }) - ) - }).annotate({ - "title": "Tracing Configuration", - "description": - "Optional tracing overrides for the workflow invocation. When omitted, tracing is enabled by default." - }) + Schema.Null + ]) +}).annotate({ + "title": "File upload settings", + "description": "Upload permissions and limits applied to the session.", + "identifier": "ChatSessionFileUpload" +}) +export type ChatSessionHistory = { readonly "enabled": boolean; readonly "recent_threads": number | null } +export const ChatSessionHistory = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Indicates if chat history is persisted for the session." }), + "recent_threads": Schema.Union([ + Schema.Number.annotate({ + "description": "Number of prior threads surfaced in history views. Defaults to null when all history is retained." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) +}).annotate({ + "title": "History settings", + "description": "History retention preferences returned for the session.", + "identifier": "ChatSessionHistory" +}) +export type WorkflowTracingParam = { readonly "enabled"?: boolean } +export const WorkflowTracingParam = Schema.Struct({ + "enabled": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether tracing is enabled during the session. Defaults to true." }) + ) +}).annotate({ + "title": "Tracing Configuration", + "description": "Controls diagnostic tracing during the session.", + "identifier": "WorkflowTracingParam" +}) +export type ExpiresAfterParam = { readonly "anchor": "created_at"; readonly "seconds": number } +export const ExpiresAfterParam = Schema.Struct({ + "anchor": Schema.Literal("created_at").annotate({ + "description": "Base timestamp used to calculate expiration. Currently fixed to `created_at`." + }), + "seconds": Schema.Number.annotate({ + "description": "Number of seconds after the anchor when the session expires.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(600).annotate({ "expected": "a value less than or equal to 600" })) +}).annotate({ + "title": "Expiration overrides", + "description": "Controls when the session expires relative to an anchor timestamp.", + "identifier": "ExpiresAfterParam" +}) +export type RateLimitsParam = { readonly "max_requests_per_1_minute"?: number } +export const RateLimitsParam = Schema.Struct({ + "max_requests_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Maximum number of requests allowed per minute for the session. Defaults to 10." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) ) - }).annotate({ "title": "Workflow settings", "description": "Workflow that powers the session." }), - "user": Schema.String.annotate({ - "description": - "A free-form string that identifies your end user; ensures this Session can access other objects that have the same `user` scope." - }).check(Schema.isMinLength(1)), - "expires_after": Schema.optionalKey( - Schema.Struct({ - "anchor": Schema.Literal("created_at").annotate({ - "description": "Base timestamp used to calculate expiration. Currently fixed to `created_at`." - }), - "seconds": Schema.Number.annotate({ - "description": "Number of seconds after the anchor when the session expires.", - "format": "int64" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(600)) - }).annotate({ - "title": "Expiration overrides", - "description": "Optional override for session expiration timing in seconds from creation. Defaults to 10 minutes." - }) + ) +}).annotate({ + "title": "Rate limit overrides", + "description": "Controls request rate limits for the session.", + "identifier": "RateLimitsParam" +}) +export type AutomaticThreadTitlingParam = { readonly "enabled"?: boolean } +export const AutomaticThreadTitlingParam = Schema.Struct({ + "enabled": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Enable automatic thread title generation. Defaults to true." }) + ) +}).annotate({ + "title": "Automatic thread titling configuration", + "description": "Controls whether ChatKit automatically generates thread titles.", + "identifier": "AutomaticThreadTitlingParam" +}) +export type FileUploadParam = { + readonly "enabled"?: boolean + readonly "max_file_size"?: number + readonly "max_files"?: number +} +export const FileUploadParam = Schema.Struct({ + "enabled": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Enable uploads for this session. Defaults to false." }) ), - "rate_limits": Schema.optionalKey( - Schema.Struct({ - "max_requests_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Maximum number of requests allowed per minute for the session. Defaults to 10." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)) - ) - }).annotate({ - "title": "Rate limit overrides", - "description": "Optional override for per-minute request limits. When omitted, defaults to 10." - }) + "max_file_size": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Maximum size in megabytes for each uploaded file. Defaults to 512 MB, which is the maximum allowable size." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(512).annotate({ "expected": "a value less than or equal to 512" })) ), - "chatkit_configuration": Schema.optionalKey( - Schema.Struct({ - "automatic_thread_titling": Schema.optionalKey( - Schema.Struct({ - "enabled": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Enable automatic thread title generation. Defaults to true." }) - ) - }).annotate({ - "title": "Automatic thread titling configuration", - "description": - "Configuration for automatic thread titling. When omitted, automatic thread titling is enabled by default." - }) - ), - "file_upload": Schema.optionalKey( - Schema.Struct({ - "enabled": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Enable uploads for this session. Defaults to false." }) - ), - "max_file_size": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Maximum size in megabytes for each uploaded file. Defaults to 512 MB, which is the maximum allowable size." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(512)) - ), - "max_files": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Maximum number of files that can be uploaded to the session. Defaults to 10." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)) - ) - }).annotate({ - "title": "File upload configuration", - "description": - "Configuration for upload enablement and limits. When omitted, uploads are disabled by default (max_files 10, max_file_size 512 MB)." - }) - ), - "history": Schema.optionalKey( - Schema.Struct({ - "enabled": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": "Enables chat users to access previous ChatKit threads. Defaults to true." - }) - ), - "recent_threads": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Number of recent ChatKit threads users have access to. Defaults to unlimited when unset." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)) - ) - }).annotate({ - "title": "Chat history configuration", - "description": - "Configuration for chat history retention. When omitted, history is enabled by default with no limit on recent_threads (null)." - }) - ) - }).annotate({ - "title": "ChatKit configuration overrides", - "description": "Optional overrides for ChatKit runtime configuration features" + "max_files": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Maximum number of files that can be uploaded to the session. Defaults to 10." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ) + ) +}).annotate({ + "title": "File upload configuration", + "description": "Controls whether users can upload files.", + "identifier": "FileUploadParam" +}) +export type HistoryParam = { readonly "enabled"?: boolean; readonly "recent_threads"?: number } +export const HistoryParam = Schema.Struct({ + "enabled": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Enables chat users to access previous ChatKit threads. Defaults to true." }) + ), + "recent_threads": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Number of recent ChatKit threads users have access to. Defaults to unlimited when unset." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ) ) }).annotate({ - "title": "Create chat session request", - "description": "Parameters for provisioning a new ChatKit session." + "title": "Chat history configuration", + "description": "Controls how much historical context is retained for the session.", + "identifier": "HistoryParam" }) export type UserMessageInputText = { readonly "type": "input_text"; readonly "text": string } export const UserMessageInputText = Schema.Struct({ "type": Schema.Literal("input_text").annotate({ "description": "Type discriminator that is always `input_text`." }), "text": Schema.String.annotate({ "description": "Plain-text content supplied by the user." }) -}).annotate({ "title": "User message input", "description": "Text block that a user contributed to the thread." }) +}).annotate({ + "title": "User message input", + "description": "Text block that a user contributed to the thread.", + "identifier": "UserMessageInputText" +}) export type UserMessageQuotedText = { readonly "type": "quoted_text"; readonly "text": string } export const UserMessageQuotedText = Schema.Struct({ "type": Schema.Literal("quoted_text").annotate({ "description": "Type discriminator that is always `quoted_text`." }), "text": Schema.String.annotate({ "description": "Quoted text content." }) }).annotate({ "title": "User message quoted text", - "description": "Quoted snippet that the user referenced in their message." + "description": "Quoted snippet that the user referenced in their message.", + "identifier": "UserMessageQuotedText" +}) +export type AttachmentType = "image" | "file" +export const AttachmentType = Schema.Literals(["image", "file"]).annotate({ "identifier": "AttachmentType" }) +export type ToolChoice = { readonly "id": string } +export const ToolChoice = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the requested tool." }) +}).annotate({ + "title": "Tool choice", + "description": "Tool selection that the assistant should honor when executing the item.", + "identifier": "ToolChoice" +}) +export type FileAnnotationSource = { readonly "type": "file"; readonly "filename": string } +export const FileAnnotationSource = Schema.Struct({ + "type": Schema.Literal("file").annotate({ "description": "Type discriminator that is always `file`." }), + "filename": Schema.String.annotate({ "description": "Filename referenced by the annotation." }) +}).annotate({ + "title": "File annotation source", + "description": "Attachment source referenced by an annotation.", + "identifier": "FileAnnotationSource" +}) +export type UrlAnnotationSource = { readonly "type": "url"; readonly "url": string } +export const UrlAnnotationSource = Schema.Struct({ + "type": Schema.Literal("url").annotate({ "description": "Type discriminator that is always `url`." }), + "url": Schema.String.annotate({ "description": "URL referenced by the annotation.", "format": "uri" }) +}).annotate({ + "title": "URL annotation source", + "description": "URL backing an annotation entry.", + "identifier": "UrlAnnotationSource" }) -export type Attachment = { - readonly "type": "image" | "file" - readonly "id": string - readonly "name": string - readonly "mime_type": string - readonly "preview_url": string | null -} -export const Attachment = Schema.Struct({ - "type": Schema.Literals(["image", "file"]).annotate({ "description": "Attachment discriminator." }), - "id": Schema.String.annotate({ "description": "Identifier for the attachment." }), - "name": Schema.String.annotate({ "description": "Original display name for the attachment." }), - "mime_type": Schema.String.annotate({ "description": "MIME type of the attachment." }), - "preview_url": Schema.Union([ - Schema.String.annotate({ "description": "Preview URL for rendering the attachment inline.", "format": "uri" }), - Schema.Null - ]) -}).annotate({ "title": "Attachment", "description": "Attachment metadata included on thread items." }) -export type FileAnnotation = { - readonly "type": "file" - readonly "source": { readonly "type": "file"; readonly "filename": string } -} -export const FileAnnotation = Schema.Struct({ - "type": Schema.Literal("file").annotate({ - "description": "Type discriminator that is always `file` for this annotation." - }), - "source": Schema.Struct({ - "type": Schema.Literal("file").annotate({ "description": "Type discriminator that is always `file`." }), - "filename": Schema.String.annotate({ "description": "Filename referenced by the annotation." }) - }).annotate({ "title": "File annotation source", "description": "File attachment referenced by the annotation." }) -}).annotate({ "title": "File annotation", "description": "Annotation that references an uploaded file." }) -export type UrlAnnotation = { - readonly "type": "url" - readonly "source": { readonly "type": "url"; readonly "url": string } -} -export const UrlAnnotation = Schema.Struct({ - "type": Schema.Literal("url").annotate({ - "description": "Type discriminator that is always `url` for this annotation." - }), - "source": Schema.Struct({ - "type": Schema.Literal("url").annotate({ "description": "Type discriminator that is always `url`." }), - "url": Schema.String.annotate({ "description": "URL referenced by the annotation.", "format": "uri" }) - }).annotate({ "title": "URL annotation source", "description": "URL referenced by the annotation." }) -}).annotate({ "title": "URL annotation", "description": "Annotation that references a URL." }) export type WidgetMessageItem = { readonly "id": string readonly "object": "chatkit.thread_item" @@ -10148,12570 +10355,11587 @@ export const WidgetMessageItem = Schema.Struct({ "created_at": Schema.Number.annotate({ "description": "Unix timestamp (in seconds) for when the item was created.", "format": "unixtime" - }).check(Schema.isInt()), + }).check(Schema.isInt().annotate({ "expected": "an integer" })), "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), "type": Schema.Literal("chatkit.widget").annotate({ "description": "Type discriminator that is always `chatkit.widget`." }), "widget": Schema.String.annotate({ "description": "Serialized widget payload rendered in the UI." }) -}).annotate({ "title": "Widget message", "description": "Thread item that renders a widget payload." }) -export type ClientToolCallItem = { - readonly "id": string - readonly "object": "chatkit.thread_item" - readonly "created_at": number - readonly "thread_id": string - readonly "type": "chatkit.client_tool_call" - readonly "status": "in_progress" | "completed" - readonly "call_id": string - readonly "name": string - readonly "arguments": string - readonly "output": string | null -} -export const ClientToolCallItem = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), - "object": Schema.Literal("chatkit.thread_item").annotate({ - "description": "Type discriminator that is always `chatkit.thread_item`." - }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) for when the item was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), - "type": Schema.Literal("chatkit.client_tool_call").annotate({ - "description": "Type discriminator that is always `chatkit.client_tool_call`." - }), - "status": Schema.Literals(["in_progress", "completed"]).annotate({ - "description": "Execution status for the tool call." - }), - "call_id": Schema.String.annotate({ "description": "Identifier for the client tool call." }), - "name": Schema.String.annotate({ "description": "Tool name that was invoked." }), - "arguments": Schema.String.annotate({ "description": "JSON-encoded arguments that were sent to the tool." }), - "output": Schema.Union([ +}).annotate({ + "title": "Widget message", + "description": "Thread item that renders a widget payload.", + "identifier": "WidgetMessageItem" +}) +export type ClientToolCallStatus = "in_progress" | "completed" +export const ClientToolCallStatus = Schema.Literals(["in_progress", "completed"]).annotate({ + "identifier": "ClientToolCallStatus" +}) +export type TaskType = "custom" | "thought" +export const TaskType = Schema.Literals(["custom", "thought"]).annotate({ "identifier": "TaskType" }) +export type ActiveStatus = { readonly "type": "active" } +export const ActiveStatus = Schema.Struct({ + "type": Schema.Literal("active").annotate({ "description": "Status discriminator that is always `active`." }) +}).annotate({ + "title": "Active thread status", + "description": "Indicates that a thread is active.", + "identifier": "ActiveStatus" +}) +export type LockedStatus = { readonly "type": "locked"; readonly "reason": string | null } +export const LockedStatus = Schema.Struct({ + "type": Schema.Literal("locked").annotate({ "description": "Status discriminator that is always `locked`." }), + "reason": Schema.Union([ Schema.String.annotate({ - "description": "JSON-encoded output captured from the tool. Defaults to null while execution is in progress." + "description": "Reason that the thread was locked. Defaults to null when no reason is recorded." }), Schema.Null ]) }).annotate({ - "title": "Client tool call", - "description": "Record of a client side tool invocation initiated by the assistant." + "title": "Locked thread status", + "description": "Indicates that a thread is locked and cannot accept new input.", + "identifier": "LockedStatus" }) -export type TaskItem = { +export type ClosedStatus = { readonly "type": "closed"; readonly "reason": string | null } +export const ClosedStatus = Schema.Struct({ + "type": Schema.Literal("closed").annotate({ "description": "Status discriminator that is always `closed`." }), + "reason": Schema.Union([ + Schema.String.annotate({ + "description": "Reason that the thread was closed. Defaults to null when no reason is recorded." + }), + Schema.Null + ]) +}).annotate({ + "title": "Closed thread status", + "description": "Indicates that a thread has been closed.", + "identifier": "ClosedStatus" +}) +export type DeletedThreadResource = { readonly "id": string - readonly "object": "chatkit.thread_item" - readonly "created_at": number - readonly "thread_id": string - readonly "type": "chatkit.task" - readonly "task_type": "custom" | "thought" - readonly "heading": string | null - readonly "summary": string | null + readonly "object": "chatkit.thread.deleted" + readonly "deleted": boolean } -export const TaskItem = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), - "object": Schema.Literal("chatkit.thread_item").annotate({ - "description": "Type discriminator that is always `chatkit.thread_item`." +export const DeletedThreadResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the deleted thread." }), + "object": Schema.Literal("chatkit.thread.deleted").annotate({ + "description": "Type discriminator that is always `chatkit.thread.deleted`." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) for when the item was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), - "type": Schema.Literal("chatkit.task").annotate({ - "description": "Type discriminator that is always `chatkit.task`." - }), - "task_type": Schema.Literals(["custom", "thought"]).annotate({ "description": "Subtype for the task." }), - "heading": Schema.Union([ - Schema.String.annotate({ "description": "Optional heading for the task. Defaults to null when not provided." }), - Schema.Null - ]), - "summary": Schema.Union([ - Schema.String.annotate({ - "description": "Optional summary that describes the task. Defaults to null when omitted." - }), - Schema.Null - ]) + "deleted": Schema.Boolean.annotate({ "description": "Indicates that the thread has been deleted." }) }).annotate({ - "title": "Task item", - "description": "Task emitted by the workflow to show progress and status updates." + "title": "Deleted thread", + "description": "Confirmation payload returned after deleting a thread.", + "identifier": "DeletedThreadResource" }) -export type TaskGroupTask = { - readonly "type": "custom" | "thought" - readonly "heading": string | null - readonly "summary": string | null +export type DecisionInputText = { readonly "type": "input_text"; readonly "text": string } +export const DecisionInputText = Schema.Struct({ + "type": Schema.Literal("input_text"), + "text": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" })) +}).annotate({ "identifier": "DecisionInputText" }) +export type ImageDetailParam = "low" | "high" | "auto" | "original" +export const ImageDetailParam = Schema.Literals(["low", "high", "auto", "original"]).annotate({ + "identifier": "ImageDetailParam" +}) +export type QuestionParamPredicate = { + readonly "type": "predicate" + readonly "name"?: string + readonly "instructions": string } -export const TaskGroupTask = Schema.Struct({ - "type": Schema.Literals(["custom", "thought"]).annotate({ "description": "Subtype for the grouped task." }), - "heading": Schema.Union([ - Schema.String.annotate({ - "description": "Optional heading for the grouped task. Defaults to null when not provided." - }), +export const QuestionParamPredicate = Schema.Struct({ + "type": Schema.Literal("predicate").annotate({ "description": "The type of the object. Always `predicate`." }), + "name": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "instructions": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) +}).annotate({ + "description": "Estimate how likely it is that a statement about the input is true.", + "identifier": "QuestionParamPredicate" +}) +export type ChoiceValueParam = string | boolean +export const ChoiceValueParam = Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + Schema.Boolean +], { mode: "oneOf" }).annotate({ + "description": "Choice values are typed: a string and a boolean with the same text are distinct.", + "identifier": "ChoiceValueParam" +}) +export type ScoreLevelParam = { readonly "label": string; readonly "description"?: string } +export const ScoreLevelParam = Schema.Struct({ + "label": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "description": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}).annotate({ "identifier": "ScoreLevelParam" }) +export type AnswerResourcePredicate = { + readonly "type": "predicate" + readonly "name": string | null + readonly "probability": number +} +export const AnswerResourcePredicate = Schema.Struct({ + "type": Schema.Literal("predicate").annotate({ "description": "The type of the object. Always `predicate`." }), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), Schema.Null ]), - "summary": Schema.Union([ - Schema.String.annotate({ - "description": "Optional summary that describes the grouped task. Defaults to null when omitted." - }), - Schema.Null - ]) -}).annotate({ "title": "Task group task", "description": "Task entry that appears within a TaskGroup." }) -export type ActiveStatus = { readonly "type": "active" } -export const ActiveStatus = Schema.Struct({ - "type": Schema.Literal("active").annotate({ "description": "Status discriminator that is always `active`." }) -}).annotate({ "title": "Active thread status", "description": "Indicates that a thread is active." }) -export type LockedStatus = { readonly "type": "locked"; readonly "reason": string | null } -export const LockedStatus = Schema.Struct({ - "type": Schema.Literal("locked").annotate({ "description": "Status discriminator that is always `locked`." }), - "reason": Schema.Union([ - Schema.String.annotate({ - "description": "Reason that the thread was locked. Defaults to null when no reason is recorded." - }), + "probability": Schema.Finite +}).annotate({ "identifier": "AnswerResourcePredicate" }) +export type ChoiceValueResource = string | boolean +export const ChoiceValueResource = Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Boolean +], { mode: "oneOf" }).annotate({ + "description": "Choice values are typed: a string and a boolean with the same text are distinct.", + "identifier": "ChoiceValueResource" +}) +export type ScoreProbabilityResource = { + readonly "value": number + readonly "label": string + readonly "probability": number +} +export const ScoreProbabilityResource = Schema.Struct({ + "value": Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "label": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "probability": Schema.Finite +}).annotate({ "identifier": "ScoreProbabilityResource" }) +export type AnswerResourceRefusal = { readonly "type": "refusal"; readonly "name": string | null } +export const AnswerResourceRefusal = Schema.Struct({ + "type": Schema.Literal("refusal").annotate({ "description": "The type of the object. Always `refusal`." }), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), Schema.Null ]) }).annotate({ - "title": "Locked thread status", - "description": "Indicates that a thread is locked and cannot accept new input." + "description": + "The model declined to answer this question. Other questions in the same request can still receive answers.", + "identifier": "AnswerResourceRefusal" }) -export type ClosedStatus = { readonly "type": "closed"; readonly "reason": string | null } -export const ClosedStatus = Schema.Struct({ - "type": Schema.Literal("closed").annotate({ "description": "Status discriminator that is always `closed`." }), - "reason": Schema.Union([ - Schema.String.annotate({ - "description": "Reason that the thread was closed. Defaults to null when no reason is recorded." - }), - Schema.Null - ]) -}).annotate({ "title": "Closed thread status", "description": "Indicates that a thread has been closed." }) -export type DeletedThreadResource = { +export type InputTokensDetailsResource = { readonly "cached_tokens": number; readonly "cache_write_tokens": number } +export const InputTokensDetailsResource = Schema.Struct({ + "cached_tokens": Schema.Number.annotate({ "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check( + Schema.isGreaterThanOrEqualTo(-2147483648).annotate({ "expected": "a value greater than or equal to -2147483648" }) + ).check(Schema.isLessThanOrEqualTo(2147483647).annotate({ "expected": "a value less than or equal to 2147483647" })), + "cache_write_tokens": Schema.Number.annotate({ "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check( + Schema.isGreaterThanOrEqualTo(-2147483648).annotate({ "expected": "a value greater than or equal to -2147483648" }) + ).check(Schema.isLessThanOrEqualTo(2147483647).annotate({ "expected": "a value less than or equal to 2147483647" })) +}).annotate({ "identifier": "InputTokensDetailsResource" }) +export type OutputTokensDetailsResource = { readonly "reasoning_tokens": number } +export const OutputTokensDetailsResource = Schema.Struct({ + "reasoning_tokens": Schema.Number.annotate({ "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check( + Schema.isGreaterThanOrEqualTo(-2147483648).annotate({ "expected": "a value greater than or equal to -2147483648" }) + ).check(Schema.isLessThanOrEqualTo(2147483647).annotate({ "expected": "a value less than or equal to 2147483647" })) +}).annotate({ "identifier": "OutputTokensDetailsResource" }) +export type ListOrderParam = "asc" | "desc" +export const ListOrderParam = Schema.Literals(["asc", "desc"]).annotate({ + "description": "The order in which paginated resources are returned.", + "identifier": "ListOrderParam" +}) +export type EnvironmentTypeParam = "openai_hosted" +export const EnvironmentTypeParam = Schema.Literal("openai_hosted").annotate({ + "description": "The hosting type of an execution environment.", + "identifier": "EnvironmentTypeParam" +}) +export type EnvironmentTypeResource = "openai_hosted" | "self_hosted" +export const EnvironmentTypeResource = Schema.Literals(["openai_hosted", "self_hosted"]).annotate({ + "description": "The kind of execution environment.", + "identifier": "EnvironmentTypeResource" +}) +export type EnvironmentStatusResource = + | "pending" + | "ready" + | "connected" + | "disconnected" + | "suspended" + | "expired" + | "failed" +export const EnvironmentStatusResource = Schema.Literals([ + "pending", + "ready", + "connected", + "disconnected", + "suspended", + "expired", + "failed" +]).annotate({ + "description": "The public lifecycle status of an execution environment.", + "identifier": "EnvironmentStatusResource" +}) +export type HostedEnvironmentFileResourceFileId = { + readonly "type": "file_id" readonly "id": string - readonly "object": "chatkit.thread.deleted" - readonly "deleted": boolean -} -export const DeletedThreadResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier of the deleted thread." }), - "object": Schema.Literal("chatkit.thread.deleted").annotate({ - "description": "Type discriminator that is always `chatkit.thread.deleted`." - }), - "deleted": Schema.Boolean.annotate({ "description": "Indicates that the thread has been deleted." }) -}).annotate({ "title": "Deleted thread", "description": "Confirmation payload returned after deleting a thread." }) -export type ResponseKeepAliveEvent = { readonly "type": "keepalive"; readonly "sequence_number": number } -export const ResponseKeepAliveEvent = Schema.Struct({ - "type": Schema.Literal("keepalive").annotate({ - "description": "The type of the keepalive event. Always `keepalive`." - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this keepalive event." }).check( - Schema.isInt() - ) -}).annotate({ "title": "Keep alive", "description": "A keepalive event emitted during long-running response streams." }) -export type ResponseApplyPatchCallOperationDiffDeltaEvent = { - readonly "type": "response.apply_patch_call_operation_diff.delta" - readonly "sequence_number": number - readonly "output_index": number - readonly "item_id": string - readonly "delta": string + readonly "file_id": string + readonly "path": string + readonly "size_bytes": number } -export const ResponseApplyPatchCallOperationDiffDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.apply_patch_call_operation_diff.delta").annotate({ - "description": "The event type identifier." - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() +export const HostedEnvironmentFileResourceFileId = Schema.Struct({ + "type": Schema.Literal("file_id").annotate({ "description": "The type of the object. Always `file_id`." }), + "id": Schema.String.annotate({ "description": "The session-scoped ID of the file in the execution environment." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "file_id": Schema.String.annotate({ "description": "The ID of the uploaded file." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "output_index": Schema.Number.annotate({ "description": "The index of the output this delta applies to." }).check( - Schema.isInt() + "path": Schema.String.annotate({ "description": "The file's absolute path inside the environment." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "item_id": Schema.String.annotate({ - "description": "Unique identifier for the API item associated with this event." - }), - "delta": Schema.String.annotate({ "description": "The incremental diff data for the apply_patch tool call." }) + "size_bytes": Schema.Number.annotate({ "description": "The decoded file size in bytes.", "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })) }).annotate({ - "title": "ResponseApplyPatchCallOperationDiffDelta", - "description": "Event representing a delta for an apply_patch tool call operation diff." + "description": "A file copied from the OpenAI Files API.", + "identifier": "HostedEnvironmentFileResourceFileId" }) -export type ResponseApplyPatchCallOperationDiffDoneEvent = { - readonly "type": "response.apply_patch_call_operation_diff.done" - readonly "sequence_number": number - readonly "output_index": number - readonly "item_id": string - readonly "delta"?: string +export type HostedEnvironmentFileResourceInline = { + readonly "type": "inline" + readonly "id": string + readonly "path": string + readonly "size_bytes": number +} +export const HostedEnvironmentFileResourceInline = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "The type of the object. Always `inline`." }), + "id": Schema.String.annotate({ "description": "The session-scoped ID of the file in the execution environment." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "path": Schema.String.annotate({ "description": "The file's absolute path inside the environment." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "size_bytes": Schema.Number.annotate({ "description": "The decoded file size in bytes.", "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })) +}).annotate({ + "description": "A file supplied inline when the session was created.", + "identifier": "HostedEnvironmentFileResourceInline" +}) +export type HostedSkillResourceSkillReference = { + readonly "type": "skill_reference" + readonly "skill_id": string + readonly "version": string + readonly "name": string + readonly "description": string } -export const ResponseApplyPatchCallOperationDiffDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.apply_patch_call_operation_diff.done").annotate({ - "description": "The event type identifier." +export const HostedSkillResourceSkillReference = Schema.Struct({ + "type": Schema.Literal("skill_reference").annotate({ + "description": "The type of the object. Always `skill_reference`." }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + "skill_id": Schema.String.annotate({ "description": "The referenced skill ID." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "output_index": Schema.Number.annotate({ "description": "The index of the output this event applies to." }).check( - Schema.isInt() + "version": Schema.String.annotate({ "description": "The concrete skill version installed for this session." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "item_id": Schema.String.annotate({ - "description": "Unique identifier for the API item associated with this event." - }), - "delta": Schema.optionalKey( - Schema.String.annotate({ "description": "The final diff data for the apply_patch tool call." }) + "name": Schema.String.annotate({ "description": "The installed skill name." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "description": Schema.String.annotate({ "description": "The installed skill description." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ) }).annotate({ - "title": "ResponseApplyPatchCallOperationDiffDone", - "description": "Event indicating that the operation diff for an apply_patch tool call is complete." + "description": "A skill installed from the Skills API.", + "identifier": "HostedSkillResourceSkillReference" }) -export type ApiKeyList = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "first_id"?: string | null - readonly "last_id"?: string | null +export type HostedSkillResourceInline = { + readonly "type": "inline" + readonly "name": string + readonly "description": string } -export const ApiKeyList = Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array(AdminApiKey), - "has_more": Schema.Boolean, - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])) +export const HostedSkillResourceInline = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "The type of the object. Always `inline`." }), + "name": Schema.String.annotate({ "description": "The installed skill name." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "description": Schema.String.annotate({ "description": "The installed skill description." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "A skill installed from an inline ZIP archive.", + "identifier": "HostedSkillResourceInline" }) -export type RoleListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "next": string | null -} -export const RoleListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), - "data": Schema.Array(AssignedRoleDetails).annotate({ - "description": "Role assignments returned in the current page." - }), - "has_more": Schema.Boolean.annotate({ - "description": "Whether additional assignments are available when paginating." - }), - "next": Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "Cursor to fetch the next page of results, or `null` when there are no more assignments." - }) -}).annotate({ "description": "Paginated list of roles assigned to a principal." }) -export type AuditLogActorApiKey = { - readonly "id"?: string - readonly "type"?: "user" | "service_account" - readonly "user"?: AuditLogActorUser - readonly "service_account"?: AuditLogActorServiceAccount +export type HostedPluginResourceInline = { + readonly "type": "inline" + readonly "name": string + readonly "description": string } -export const AuditLogActorApiKey = Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The tracking id of the API key." })), - "type": Schema.optionalKey( - Schema.Literals(["user", "service_account"]).annotate({ - "description": "The type of API key. Can be either `user` or `service_account`." - }) +export const HostedPluginResourceInline = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "The type of the object. Always `inline`." }), + "name": Schema.String.annotate({ "description": "The installed plugin name." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "user": Schema.optionalKey(AuditLogActorUser), - "service_account": Schema.optionalKey(AuditLogActorServiceAccount) -}).annotate({ "description": "The API Key used to perform the audit logged action." }) -export type AuditLogActorSession = { readonly "user"?: AuditLogActorUser; readonly "ip_address"?: string } -export const AuditLogActorSession = Schema.Struct({ - "user": Schema.optionalKey(AuditLogActorUser), - "ip_address": Schema.optionalKey( - Schema.String.annotate({ "description": "The IP address from which the action was performed." }) + "description": Schema.String.annotate({ "description": "The installed plugin description." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ) -}).annotate({ "description": "The session in which the audit logged action was performed." }) -export type ChatCompletionAllowedToolsChoice = { - readonly "type": "allowed_tools" - readonly "allowed_tools": ChatCompletionAllowedTools -} -export const ChatCompletionAllowedToolsChoice = Schema.Struct({ - "type": Schema.Literal("allowed_tools").annotate({ - "description": "Allowed tool configuration type. Always `allowed_tools`." - }), - "allowed_tools": ChatCompletionAllowedTools }).annotate({ - "title": "Allowed tools", - "description": "Constrains the tools available to the model to a pre-defined set.\n" + "description": "A plugin installed from an inline ZIP archive.", + "identifier": "HostedPluginResourceInline" }) -export type ChatCompletionMessageToolCalls = ReadonlyArray< - ChatCompletionMessageToolCall | ChatCompletionMessageCustomToolCall -> -export const ChatCompletionMessageToolCalls = Schema.Array( - Schema.Union([ChatCompletionMessageToolCall, ChatCompletionMessageCustomToolCall], { mode: "oneOf" }) -).annotate({ "description": "The tool calls generated by the model, such as function calls." }) -export type ChatCompletionStreamResponseDelta = { - readonly "content"?: string | null - readonly "function_call"?: { readonly "arguments"?: string; readonly "name"?: string } - readonly "tool_calls"?: ReadonlyArray - readonly "role"?: "developer" | "system" | "user" | "assistant" | "tool" - readonly "refusal"?: string | null +export type ErrorBodyResource = { + readonly "type": string + readonly "code": string + readonly "message": string + readonly "param": string | null } -export const ChatCompletionStreamResponseDelta = Schema.Struct({ - "content": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "The contents of the chunk message." }), Schema.Null]) +export const ErrorBodyResource = Schema.Struct({ + "type": Schema.String.annotate({ "description": "The error type." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "function_call": Schema.optionalKey( - Schema.Struct({ - "arguments": Schema.optionalKey(Schema.String.annotate({ - "description": - "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - })), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function to call." })) - }).annotate({ - "description": - "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." - }) + "code": Schema.String.annotate({ "description": "A machine-readable error code." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "tool_calls": Schema.optionalKey(Schema.Array(ChatCompletionMessageToolCallChunk)), - "role": Schema.optionalKey( - Schema.Literals(["developer", "system", "user", "assistant", "tool"]).annotate({ - "description": "The role of the author of this message." - }) + "message": Schema.String.annotate({ "description": "A human-readable error message." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "refusal": Schema.optionalKey( + "param": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The request parameter that caused the error, or null for a request-wide error." }) +}).annotate({ "description": "Details about an API error.", "identifier": "ErrorBodyResource" }) +export type EnvironmentPackagesParam = { + readonly "python"?: ReadonlyArray | null + readonly "system"?: ReadonlyArray | null + readonly "npm"?: ReadonlyArray | null +} +export const EnvironmentPackagesParam = Schema.Struct({ + "python": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ "description": "The refusal message generated by the model." }), + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), Schema.Null - ]) - ) -}).annotate({ "description": "A chat completion delta generated by streamed model responses." }) -export type ChatCompletionRequestAssistantMessageContentPart = - | ChatCompletionRequestMessageContentPartText - | ChatCompletionRequestMessageContentPartRefusal -export const ChatCompletionRequestAssistantMessageContentPart = Schema.Union([ - ChatCompletionRequestMessageContentPartText, - ChatCompletionRequestMessageContentPartRefusal -], { mode: "oneOf" }) -export type ChatCompletionRequestDeveloperMessage = { - readonly "content": string | ReadonlyArray - readonly "role": "developer" - readonly "name"?: string + ]).annotate({ "description": "Python packages to install. Defaults to an empty list." }) + ), + "system": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "System packages to install. Defaults to an empty list." }) + ), + "npm": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "npm packages to install globally. Defaults to an empty list." }) + ) +}).annotate({ + "description": "Packages to install in an OpenAI-hosted environment.", + "identifier": "EnvironmentPackagesParam" +}) +export type SetupCommandParam = { readonly "command": string; readonly "cwd"?: string | null } +export const SetupCommandParam = Schema.Struct({ + "command": Schema.String.annotate({ "description": "The shell command to execute." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(65536).annotate({ "expected": "a string with at most 65536 code points" })), + "cwd": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(4096).annotate({ "expected": "a string with at most 4096 code points" })), + Schema.Null + ]).annotate({ "description": "The absolute working directory. Defaults to `/workspace`." }) + ) +}).annotate({ + "description": "A confidential setup command executed before the hosted agent starts.", + "identifier": "SetupCommandParam" +}) +export type NetworkAccessParam = "enabled" | "disabled" | "restricted" +export const NetworkAccessParam = Schema.Literals(["enabled", "disabled", "restricted"]).annotate({ + "description": "The network access mode for an OpenAI-hosted environment.", + "identifier": "NetworkAccessParam" +}) +export type DesktopParam = { readonly "enabled": boolean } +export const DesktopParam = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Whether to provision the desktop and its browser proxy." }) +}).annotate({ "description": "Desktop configuration for an OpenAI-hosted environment.", "identifier": "DesktopParam" }) +export type HostedSkillParamSkillReference = { + readonly "type": "skill_reference" + readonly "skill_id": string + readonly "version"?: string | null } -export const ChatCompletionRequestDeveloperMessage = Schema.Struct({ - "content": Schema.Union([ - Schema.String.annotate({ "title": "Text content", "description": "The contents of the developer message." }), - Schema.Array(ChatCompletionRequestMessageContentPartText).annotate({ - "title": "Array of content parts", - "description": - "An array of content parts with a defined type. For developer messages, only type `text` is supported." - }).check(Schema.isMinLength(1)) - ], { mode: "oneOf" }).annotate({ "description": "The contents of the developer message." }), - "role": Schema.Literal("developer").annotate({ - "description": "The role of the messages author, in this case `developer`." +export const HostedSkillParamSkillReference = Schema.Struct({ + "type": Schema.Literal("skill_reference").annotate({ + "description": "The type of the object. Always `skill_reference`." }), - "name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "An optional name for the participant. Provides the model information to differentiate between participants of the same role." - }) + "skill_id": Schema.String.annotate({ "description": "The ID of the skill created through `/v1/skills`." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "version": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The skill version, a positive integer or `latest`; omission selects the default." }) ) }).annotate({ - "title": "Developer message", - "description": - "Developer-provided instructions that the model should follow, regardless of\nmessages sent by the user. With o1 models and newer, `developer` messages\nreplace the previous `system` messages.\n" + "description": "References a skill uploaded through the Skills API.", + "identifier": "HostedSkillParamSkillReference" }) -export type ChatCompletionRequestSystemMessageContentPart = ChatCompletionRequestMessageContentPartText -export const ChatCompletionRequestSystemMessageContentPart = Schema.Union( - [ChatCompletionRequestMessageContentPartText], - { mode: "oneOf" } -) -export type ChatCompletionRequestToolMessageContentPart = ChatCompletionRequestMessageContentPartText -export const ChatCompletionRequestToolMessageContentPart = Schema.Union([ChatCompletionRequestMessageContentPartText], { - mode: "oneOf" +export type InlineCapabilitySourceParamBase64 = { + readonly "type": "base64" + readonly "media_type": "application/zip" + readonly "data": string +} +export const InlineCapabilitySourceParamBase64 = Schema.Struct({ + "type": Schema.Literal("base64").annotate({ "description": "The type of the object. Always `base64`." }), + "media_type": Schema.Literal("application/zip").annotate({ + "description": "The archive media type, always `application/zip`." + }), + "data": Schema.String.annotate({ "description": "Standard-base64 encoded ZIP archive bytes." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(70254592).annotate({ "expected": "a string with at most 70254592 code points" })) +}).annotate({ + "description": "Provides ZIP bytes encoded with standard base64.", + "identifier": "InlineCapabilitySourceParamBase64" }) -export type ChatCompletionRequestUserMessageContentPart = - | ChatCompletionRequestMessageContentPartText - | ChatCompletionRequestMessageContentPartImage - | ChatCompletionRequestMessageContentPartAudio - | ChatCompletionRequestMessageContentPartFile -export const ChatCompletionRequestUserMessageContentPart = Schema.Union([ - ChatCompletionRequestMessageContentPartText, - ChatCompletionRequestMessageContentPartImage, - ChatCompletionRequestMessageContentPartAudio, - ChatCompletionRequestMessageContentPartFile -], { mode: "oneOf" }) -export type PredictionContent = { - readonly "type": "content" - readonly "content": string | ReadonlyArray +export type HostedEnvironmentFileParamFileId = { + readonly "type": "file_id" + readonly "file_id": string + readonly "path": string } -export const PredictionContent = Schema.Struct({ - "type": Schema.Literal("content").annotate({ - "description": "The type of the predicted content you want to provide. This type is\ncurrently always `content`.\n" - }), - "content": Schema.Union([ - Schema.String.annotate({ - "title": "Text content", - "description": - "The content used for a Predicted Output. This is often the\ntext of a file you are regenerating with minor changes.\n" - }), - Schema.Array(ChatCompletionRequestMessageContentPartText).annotate({ - "title": "Array of content parts", - "description": - "An array of content parts with a defined type. Supported options differ based on the [model](/docs/models) being used to generate the response. Can contain text inputs." - }).check(Schema.isMinLength(1)) - ], { mode: "oneOf" }).annotate({ - "description": - "The content that should be matched when generating a model response.\nIf generated tokens would match this content, the entire model response\ncan be returned much more quickly.\n" - }) +export const HostedEnvironmentFileParamFileId = Schema.Struct({ + "type": Schema.Literal("file_id").annotate({ "description": "The type of the object. Always `file_id`." }), + "file_id": Schema.String.annotate({ "description": "The ID of the uploaded file." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })), + "path": Schema.String.annotate({ "description": "The absolute destination path inside `/workspace`." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(4096).annotate({ "expected": "a string with at most 4096 code points" })) }).annotate({ - "title": "Static Content", - "description": "Static predicted output content, such as the content of a text file that is\nbeing regenerated.\n" + "description": "A file previously uploaded through the OpenAI Files API.", + "identifier": "HostedEnvironmentFileParamFileId" }) -export type CompoundFilter = { - readonly "type": "and" | "or" - readonly "filters": ReadonlyArray +export type HostedEnvironmentFileParamInline = { + readonly "type": "inline" + readonly "data": string + readonly "path": string } -export const CompoundFilter = Schema.Struct({ - "type": Schema.Literals(["and", "or"]).annotate({ "description": "Type of operation: `and` or `or`." }), - "filters": Schema.Array(Schema.Union([ComparisonFilter, Schema.Unknown], { mode: "oneOf" })).annotate({ - "description": "Array of filters to combine. Items can be `ComparisonFilter` or `CompoundFilter`." - }) -}).annotate({ "title": "Compound Filter", "description": "Combine multiple filters using `and` or `or`." }) -export type CreateCompletionResponse = { +export const HostedEnvironmentFileParamInline = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "The type of the object. Always `inline`." }), + "data": Schema.String.annotate({ "description": "The standard-base64-encoded file contents." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(6990508).annotate({ "expected": "a string with at most 6990508 code points" })), + "path": Schema.String.annotate({ "description": "The absolute destination path inside `/workspace`." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(4096).annotate({ "expected": "a string with at most 4096 code points" })) +}).annotate({ + "description": "A file supplied directly as standard-base64 data.", + "identifier": "HostedEnvironmentFileParamInline" +}) +export type EnvironmentFilePageObjectResource = "page" +export const EnvironmentFilePageObjectResource = Schema.Literal("page").annotate({ + "description": "The object type for a page of files in an execution environment.", + "identifier": "EnvironmentFilePageObjectResource" +}) +export type EnvironmentFileResource = { + readonly "object": "agent.environment.file" + readonly "environment_id": string + readonly "path": string + readonly "size_bytes": number +} +export const EnvironmentFileResource = Schema.Struct({ + "object": Schema.Literal("agent.environment.file").annotate({ + "description": "The object type. Always `agent.environment.file`." + }), + "environment_id": Schema.String.annotate({ "description": "The ID of the environment containing this file." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "path": Schema.String.annotate({ "description": "The absolute file path inside the environment's workspace." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "size_bytes": Schema.Number.annotate({ "description": "The file size in bytes.", "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })) +}).annotate({ "description": "A live file in an execution environment.", "identifier": "EnvironmentFileResource" }) +export type SubagentObjectResource = "agent.session.subagent" +export const SubagentObjectResource = Schema.Literal("agent.session.subagent").annotate({ + "description": "The object type for a subagent.", + "identifier": "SubagentObjectResource" +}) +export type OutputTextResource = { readonly "type": "output_text"; readonly "text": string } +export const OutputTextResource = Schema.Struct({ + "type": Schema.Literal("output_text").annotate({ "description": "The content type. Always `output_text`." }), + "text": Schema.String.annotate({ "description": "The text produced by the agent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "A text content part produced by the agent.", "identifier": "OutputTextResource" }) +export type EncryptedContentResource = { readonly "type": "encrypted_content"; readonly "encrypted_content": string } +export const EncryptedContentResource = Schema.Struct({ + "type": Schema.Literal("encrypted_content").annotate({ + "description": "The content type. Always `encrypted_content`." + }), + "encrypted_content": Schema.String.annotate({ "description": "The encrypted content payload." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "Encrypted content exchanged between agents.", "identifier": "EncryptedContentResource" }) +export type SubagentStatusResource = "active" | "closed" +export const SubagentStatusResource = Schema.Literals(["active", "closed"]).annotate({ + "description": "The current status of a subagent.", + "identifier": "SubagentStatusResource" +}) +export type SessionMessageRoleResource = "user" | "assistant" +export const SessionMessageRoleResource = Schema.Literals(["user", "assistant"]).annotate({ + "description": "The author of a session message.", + "identifier": "SessionMessageRoleResource" +}) +export type MessageContentResourceInputText = { readonly "type": "input_text"; readonly "text": string } +export const MessageContentResourceInputText = Schema.Struct({ + "type": Schema.Literal("input_text").annotate({ "description": "The type of the object. Always `input_text`." }), + "text": Schema.String.annotate({ "description": "The text supplied by the user." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "Text supplied by the user.", "identifier": "MessageContentResourceInputText" }) +export type MessageContentResourceInputImage = { readonly "type": "input_image"; readonly "image_url": string } +export const MessageContentResourceInputImage = Schema.Struct({ + "type": Schema.Literal("input_image").annotate({ "description": "The type of the object. Always `input_image`." }), + "image_url": Schema.String.annotate({ + "description": "The URL of the image supplied by the user, which may be a base64-encoded data URL." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) +}).annotate({ "description": "An image supplied by the user.", "identifier": "MessageContentResourceInputImage" }) +export type MessageContentResourceOutputText = { readonly "type": "output_text"; readonly "text": string } +export const MessageContentResourceOutputText = Schema.Struct({ + "type": Schema.Literal("output_text").annotate({ "description": "The type of the object. Always `output_text`." }), + "text": Schema.String.annotate({ "description": "The text produced by the assistant." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "Text produced by the assistant.", "identifier": "MessageContentResourceOutputText" }) +export type OutputItemStatusResource = "in_progress" | "completed" | "incomplete" +export const OutputItemStatusResource = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": "The status of an agent output item.", + "identifier": "OutputItemStatusResource" +}) +export type MessagePhaseResource = "commentary" | "final_answer" +export const MessagePhaseResource = Schema.Literals(["commentary", "final_answer"]).annotate({ + "description": "The phase of an assistant message.", + "identifier": "MessagePhaseResource" +}) +export type SummaryTextResource = { readonly "type": "summary_text"; readonly "text": string } +export const SummaryTextResource = Schema.Struct({ + "type": Schema.Literal("summary_text").annotate({ "description": "The content type. Always `summary_text`." }), + "text": Schema.String.annotate({ "description": "The reasoning summary text." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "A reasoning summary content part.", "identifier": "SummaryTextResource" }) +export type FunctionCallStatusResource = "in_progress" | "completed" | "failed" | "incomplete" +export const FunctionCallStatusResource = Schema.Literals(["in_progress", "completed", "failed", "incomplete"]) + .annotate({ "description": "The status of a tool call.", "identifier": "FunctionCallStatusResource" }) +export type InputContentResourceInputText = { readonly "type": "input_text"; readonly "text": string } +export const InputContentResourceInputText = Schema.Struct({ + "type": Schema.Literal("input_text").annotate({ "description": "The type of the object. Always `input_text`." }), + "text": Schema.String.annotate({ "description": "The text supplied to the agent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "Text input recorded in a session item.", "identifier": "InputContentResourceInputText" }) +export type InputContentResourceInputImage = { readonly "type": "input_image"; readonly "image_url": string } +export const InputContentResourceInputImage = Schema.Struct({ + "type": Schema.Literal("input_image").annotate({ "description": "The type of the object. Always `input_image`." }), + "image_url": Schema.String.annotate({ + "description": "The URL of the image supplied to the agent, which may be a base64-encoded data URL." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) +}).annotate({ + "description": "Image input recorded in a session item.", + "identifier": "InputContentResourceInputImage" +}) +export type ComputerScreenshotResource = { readonly "type": "computer_screenshot"; readonly "image_url": string } +export const ComputerScreenshotResource = Schema.Struct({ + "type": Schema.Literal("computer_screenshot").annotate({ + "description": "The content type. Always `computer_screenshot`." + }), + "image_url": Schema.String.annotate({ "description": "The complete JPEG image as a base64 data URL." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "A browser screenshot emitted by the model during computer use.", + "identifier": "ComputerScreenshotResource" +}) +export type BrowserAuthenticationFieldResource = { readonly "id": string - readonly "choices": ReadonlyArray< - { - readonly "finish_reason": "stop" | "length" | "content_filter" - readonly "index": number - readonly "logprobs": { - readonly "text_offset"?: ReadonlyArray - readonly "token_logprobs"?: ReadonlyArray - readonly "tokens"?: ReadonlyArray - readonly "top_logprobs"?: ReadonlyArray<{}> - } | null - readonly "text": string - } - > - readonly "created": number - readonly "model": string - readonly "system_fingerprint"?: string - readonly "object": "text_completion" - readonly "usage"?: CompletionUsage + readonly "label": string + readonly "type": string + readonly "required": boolean } -export const CreateCompletionResponse = Schema.Struct({ - "id": Schema.String.annotate({ "description": "A unique identifier for the completion." }), - "choices": Schema.Array(Schema.Struct({ - "finish_reason": Schema.Literals(["stop", "length", "content_filter"]).annotate({ - "description": - "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\nor `content_filter` if content was omitted due to a flag from our content filters.\n" - }), - "index": Schema.Number.check(Schema.isInt()), - "logprobs": Schema.Union([ - Schema.Struct({ - "text_offset": Schema.optionalKey(Schema.Array(Schema.Number.check(Schema.isInt()))), - "token_logprobs": Schema.optionalKey(Schema.Array(Schema.Number.check(Schema.isFinite()))), - "tokens": Schema.optionalKey(Schema.Array(Schema.String)), - "top_logprobs": Schema.optionalKey(Schema.Array(Schema.Struct({}))) - }), - Schema.Null - ]), - "text": Schema.String - })).annotate({ "description": "The list of completion choices the model generated for the input prompt." }), - "created": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the completion was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "model": Schema.String.annotate({ "description": "The model used for completion." }), - "system_fingerprint": Schema.optionalKey( - Schema.String.annotate({ - "description": - "This fingerprint represents the backend configuration that the model runs with.\n\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" - }) +export const BrowserAuthenticationFieldResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The field ID to submit as field_id in a fields entry." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "object": Schema.Literal("text_completion").annotate({ - "description": "The object type, which is always \"text_completion\"" - }), - "usage": Schema.optionalKey(CompletionUsage) + "label": Schema.String.annotate({ "description": "The label to display beside the control." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "type": Schema.String.annotate({ "description": "The rendering type, such as email, password, or text." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "required": Schema.Boolean.annotate({ "description": "Whether this control requires a nonempty value." }) }).annotate({ - "description": - "Represents a completion response from the API. Note: both the streamed and non-streamed response objects share the same shape (unlike the chat endpoint).\n" + "description": "A control in a registered browser-login form.", + "identifier": "BrowserAuthenticationFieldResource" }) -export type ContainerFileListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean +export type BrowserAuthenticationOptionResource = { + readonly "id": string + readonly "label": string + readonly "field_ids": ReadonlyArray } -export const ContainerFileListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be 'list'." }), - "data": Schema.Array(ContainerFileResource).annotate({ "description": "A list of container files." }), - "first_id": Schema.String.annotate({ "description": "The ID of the first file in the list." }), - "last_id": Schema.String.annotate({ "description": "The ID of the last file in the list." }), - "has_more": Schema.Boolean.annotate({ "description": "Whether there are more files available." }) +export const BrowserAuthenticationOptionResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The option ID to submit as selected_option." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "label": Schema.String.annotate({ "description": "The method label to display." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "field_ids": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "IDs from the registered fields that this method accepts." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })) +}).annotate({ + "description": "A sign-in method and the fields that belong to it.", + "identifier": "BrowserAuthenticationOptionResource" }) -export type ContainerListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean +export type ComputerUseApprovalResponseKindResourceBrowserAuthenticationSubmitResource = { + readonly "type": "browser_authentication" + readonly "action": "submit" + readonly "selected_option": string | null +} +export const ComputerUseApprovalResponseKindResourceBrowserAuthenticationSubmitResource = Schema.Struct({ + "type": Schema.Literal("browser_authentication"), + "action": Schema.Literal("submit"), + "selected_option": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The chosen sign-in method, or null when no options were offered." }) +}).annotate({ "identifier": "ComputerUseApprovalResponseKindResourceBrowserAuthenticationSubmitResource" }) +export type ComputerUseApprovalResponseKindResourceBrowserAuthenticationCancelResource = { + readonly "type": "browser_authentication" + readonly "action": "cancel" +} +export const ComputerUseApprovalResponseKindResourceBrowserAuthenticationCancelResource = Schema.Struct({ + "type": Schema.Literal("browser_authentication"), + "action": Schema.Literal("cancel") +}).annotate({ "identifier": "ComputerUseApprovalResponseKindResourceBrowserAuthenticationCancelResource" }) +export type WebSearchActionResourceSearch = { + readonly "type": "search" + readonly "query": string | null + readonly "queries": ReadonlyArray | null +} +export const WebSearchActionResourceSearch = Schema.Struct({ + "type": Schema.Literal("search").annotate({ "description": "The type of the object. Always `search`." }), + "query": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The search query, when a single query was used." }), + "queries": Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + Schema.Null + ]).annotate({ "description": "The search queries, when multiple queries were used." }) +}).annotate({ + "description": "A search query or group of search queries.", + "identifier": "WebSearchActionResourceSearch" +}) +export type WebSearchActionResourceOpenPage = { readonly "type": "open_page"; readonly "url": string | null } +export const WebSearchActionResourceOpenPage = Schema.Struct({ + "type": Schema.Literal("open_page").annotate({ "description": "The type of the object. Always `open_page`." }), + "url": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The URL of the page that was opened." }) +}).annotate({ "description": "Opens a web page.", "identifier": "WebSearchActionResourceOpenPage" }) +export type WebSearchActionResourceFindInPage = { + readonly "type": "find_in_page" + readonly "url": string | null + readonly "pattern": string | null +} +export const WebSearchActionResourceFindInPage = Schema.Struct({ + "type": Schema.Literal("find_in_page").annotate({ "description": "The type of the object. Always `find_in_page`." }), + "url": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The URL of the page that was searched." }), + "pattern": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The text pattern that was searched for." }) +}).annotate({ "description": "Finds text within a web page.", "identifier": "WebSearchActionResourceFindInPage" }) +export type WebSearchActionResourceOther = { readonly "type": "other" } +export const WebSearchActionResourceOther = Schema.Struct({ + "type": Schema.Literal("other").annotate({ "description": "The type of the object. Always `other`." }) +}).annotate({ "description": "Another web search action.", "identifier": "WebSearchActionResourceOther" }) +export type TurnObjectResource = "agent.session.turn" +export const TurnObjectResource = Schema.Literal("agent.session.turn").annotate({ + "description": "The object type for a turn.", + "identifier": "TurnObjectResource" +}) +export type TurnStatusResource = "queued" | "in_progress" | "waiting" | "completed" | "failed" | "cancelled" +export const TurnStatusResource = Schema.Literals([ + "queued", + "in_progress", + "waiting", + "completed", + "failed", + "cancelled" +]).annotate({ "description": "The current status of a turn.", "identifier": "TurnStatusResource" }) +export type SessionTurnErrorCodeResource = + | "context_length_exceeded" + | "session_budget_exceeded" + | "usage_limit_exceeded" + | "project_spend_limit_exceeded" + | "organization_spend_limit_exceeded" + | "organization_usage_limit_exceeded" + | "billing_not_active" + | "credit_balance_exhausted" + | "rate_limit_exceeded" + | "flex_unavailable" + | "server_overloaded" + | "cyber_policy" + | "misalignment_policy_violation" + | "connection_failed" + | "server_error" + | "authentication_error" + | "invalid_request" + | "resource_not_found" + | "sandbox_error" + | "executor_version_incompatible" + | "active_turn_not_steerable" + | "request_timeout" + | "internal_error" +export const SessionTurnErrorCodeResource = Schema.Literals([ + "context_length_exceeded", + "session_budget_exceeded", + "usage_limit_exceeded", + "project_spend_limit_exceeded", + "organization_spend_limit_exceeded", + "organization_usage_limit_exceeded", + "billing_not_active", + "credit_balance_exhausted", + "rate_limit_exceeded", + "flex_unavailable", + "server_overloaded", + "cyber_policy", + "misalignment_policy_violation", + "connection_failed", + "server_error", + "authentication_error", + "invalid_request", + "resource_not_found", + "sandbox_error", + "executor_version_incompatible", + "active_turn_not_steerable", + "request_timeout", + "internal_error" +]).annotate({ + "description": "Stable public categories for session request failures.", + "identifier": "SessionTurnErrorCodeResource" +}) +export type InputTokensDetailsResource_2 = { readonly "cached_tokens": number } +export const InputTokensDetailsResource_2 = Schema.Struct({ + "cached_tokens": Schema.Number.annotate({ + "description": "The number of input tokens retrieved from the prompt cache.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "A breakdown of input token usage for a session or turn.", + "identifier": "InputTokensDetailsResource-2" +}) +export type OutputTokensDetailsResource_2 = { readonly "reasoning_tokens": number } +export const OutputTokensDetailsResource_2 = Schema.Struct({ + "reasoning_tokens": Schema.Number.annotate({ + "description": "The number of output tokens used for reasoning.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "A breakdown of output token usage for a session or turn.", + "identifier": "OutputTokensDetailsResource-2" +}) +export type ReasoningEffortResource = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" +export const ReasoningEffortResource = Schema.Literals(["none", "minimal", "low", "medium", "high", "xhigh", "max"]) + .annotate({ + "description": "The amount of reasoning effort used by an agent.", + "identifier": "ReasoningEffortResource" + }) +export type ReasoningSummaryResource = "concise" | "detailed" | "auto" +export const ReasoningSummaryResource = Schema.Literals(["concise", "detailed", "auto"]).annotate({ + "description": "The reasoning summary format requested from an agent.", + "identifier": "ReasoningSummaryResource" +}) +export type TextFormatResourceText = { readonly "type": "text" } +export const TextFormatResourceText = Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "The type of the object. Always `text`." }) +}).annotate({ + "description": "Generates ordinary text without a structured-output constraint.", + "identifier": "TextFormatResourceText" +}) +export type TextFormatResourceJsonSchema = { + readonly "type": "json_schema" + readonly "schema": { readonly [x: string]: Schema.Json } +} +export const TextFormatResourceJsonSchema = Schema.Struct({ + "type": Schema.Literal("json_schema").annotate({ "description": "The type of the object. Always `json_schema`." }), + "schema": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The JSON Schema that generated text must match." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) +}).annotate({ + "description": "Constrains generated text to a JSON Schema.", + "identifier": "TextFormatResourceJsonSchema" +}) +export type VerbosityResource = "low" | "medium" | "high" +export const VerbosityResource = Schema.Literals(["low", "medium", "high"]).annotate({ + "description": "The amount of text produced by an agent.", + "identifier": "VerbosityResource" +}) +export type ServiceTierResource = "auto" | "default" | "flex" | "priority" | "fast" | "ultrafast" +export const ServiceTierResource = Schema.Literals(["auto", "default", "flex", "priority", "fast", "ultrafast"]) + .annotate({ "description": "The service-tier policy configured for an agent.", "identifier": "ServiceTierResource" }) +export type PersistedAgentToolResourceFunction = { + readonly "type": "function" + readonly "name": string + readonly "description": string + readonly "parameters": { readonly [x: string]: Schema.Json } + readonly "defer_loading": boolean +} +export const PersistedAgentToolResourceFunction = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The type of the object. Always `function`." }), + "name": Schema.String.annotate({ "description": "The name of the function." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "description": Schema.String.annotate({ "description": "A description of what the function does." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "parameters": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON Schema object describing the function's arguments." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + "defer_loading": Schema.Boolean.annotate({ + "description": "Whether the function is deferred and discovered through tool search." + }) +}).annotate({ + "description": "A function defined by the application.", + "identifier": "PersistedAgentToolResourceFunction" +}) +export type PersistedAgentToolResourceToolSearch = { readonly "type": "tool_search" } +export const PersistedAgentToolResourceToolSearch = Schema.Struct({ + "type": Schema.Literal("tool_search").annotate({ "description": "The type of the object. Always `tool_search`." }) +}).annotate({ + "description": "Discovers deferred function tools and loads them into the model context.", + "identifier": "PersistedAgentToolResourceToolSearch" +}) +export type PersistedAgentToolResourceProgrammaticToolCalling = { + readonly "type": "programmatic_tool_calling" + readonly "enabled": boolean } -export const ContainerListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be 'list'." }), - "data": Schema.Array(ContainerResource).annotate({ "description": "A list of containers." }), - "first_id": Schema.String.annotate({ "description": "The ID of the first container in the list." }), - "last_id": Schema.String.annotate({ "description": "The ID of the last container in the list." }), - "has_more": Schema.Boolean.annotate({ "description": "Whether there are more containers available." }) +export const PersistedAgentToolResourceProgrammaticToolCalling = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The type of the object. Always `programmatic_tool_calling`." + }), + "enabled": Schema.Boolean.annotate({ "description": "Whether tools can be called from model-generated code." }) +}).annotate({ + "description": "Enables calling tools from model-generated code.", + "identifier": "PersistedAgentToolResourceProgrammaticToolCalling" }) -export type CreateEmbeddingResponse = { - readonly "data": ReadonlyArray - readonly "model": string - readonly "object": "list" - readonly "usage": { readonly "prompt_tokens": number; readonly "total_tokens": number } +export type PersistedMcpTransportResourceHttp = { + readonly "type": "http" + readonly "server_url": string + readonly "headers": { readonly [x: string]: string } } -export const CreateEmbeddingResponse = Schema.Struct({ - "data": Schema.Array(Embedding).annotate({ "description": "The list of embeddings generated by the model." }), - "model": Schema.String.annotate({ "description": "The name of the model used to generate the embedding." }), - "object": Schema.Literal("list").annotate({ "description": "The object type, which is always \"list\"." }), - "usage": Schema.Struct({ - "prompt_tokens": Schema.Number.annotate({ "description": "The number of tokens used by the prompt." }).check( - Schema.isInt() - ), - "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used by the request." }).check( - Schema.isInt() - ) - }).annotate({ "description": "The usage information for the request." }) +export const PersistedMcpTransportResourceHttp = Schema.Struct({ + "type": Schema.Literal("http").annotate({ "description": "The type of the object. Always `http`." }), + "server_url": Schema.String.annotate({ "description": "The URL of the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "headers": Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Non-secret HTTP headers sent to the MCP server." }).check( + Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) +}).annotate({ + "description": "Connects to an MCP server over HTTP.", + "identifier": "PersistedMcpTransportResourceHttp" }) -export type ErrorEvent = { readonly "event": "error"; readonly "data": Error } -export const ErrorEvent = Schema.Struct({ "event": Schema.Literal("error"), "data": Error }).annotate({ - "description": - "Occurs when an [error](/docs/guides/error-codes#api-errors) occurs. This can happen due to an internal server error or a timeout." +export type PersistedMcpTransportResourceStdio = { + readonly "type": "stdio" + readonly "command": string + readonly "args": ReadonlyArray + readonly "cwd": string + readonly "env_vars": ReadonlyArray +} +export const PersistedMcpTransportResourceStdio = Schema.Struct({ + "type": Schema.Literal("stdio").annotate({ "description": "The type of the object. Always `stdio`." }), + "command": Schema.String.annotate({ "description": "The command used to start the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "args": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Arguments passed to the MCP server command." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "cwd": Schema.String.annotate({ "description": "The working directory used to start the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "env_vars": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Environment variable names inherited from the execution environment." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })) +}).annotate({ + "description": "Starts an MCP server as a local process.", + "identifier": "PersistedMcpTransportResourceStdio" }) -export type ErrorResponse = { readonly "error": Error } -export const ErrorResponse = Schema.Struct({ "error": Error }) -export type EvalRunOutputItem = { - readonly "object": "eval.run.output_item" - readonly "id": string - readonly "run_id": string - readonly "eval_id": string - readonly "created_at": number - readonly "status": string - readonly "datasource_item_id": number - readonly "datasource_item": {} - readonly "results": ReadonlyArray - readonly "sample": { - readonly "input": ReadonlyArray<{ readonly "role": string; readonly "content": string }> - readonly "output": ReadonlyArray<{ readonly "role"?: string; readonly "content"?: string }> - readonly "finish_reason": string - readonly "model": string - readonly "usage": { - readonly "total_tokens": number - readonly "completion_tokens": number - readonly "prompt_tokens": number - readonly "cached_tokens": number - } - readonly "error": EvalApiError - readonly "temperature": number - readonly "max_completion_tokens": number - readonly "top_p": number - readonly "seed": number - } -} -export const EvalRunOutputItem = Schema.Struct({ - "object": Schema.Literal("eval.run.output_item").annotate({ - "description": "The type of the object. Always \"eval.run.output_item\"." - }), - "id": Schema.String.annotate({ "description": "Unique identifier for the evaluation run output item." }), - "run_id": Schema.String.annotate({ - "description": "The identifier of the evaluation run associated with this output item." - }), - "eval_id": Schema.String.annotate({ "description": "The identifier of the evaluation group." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the evaluation run was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "status": Schema.String.annotate({ "description": "The status of the evaluation run." }), - "datasource_item_id": Schema.Number.annotate({ "description": "The identifier for the data source item." }).check( - Schema.isInt() - ), - "datasource_item": Schema.Struct({}).annotate({ "description": "Details of the input data source item." }), - "results": Schema.Array(EvalRunOutputItemResult).annotate({ - "description": "A list of grader results for this output item." - }), - "sample": Schema.Struct({ - "input": Schema.Array( - Schema.Struct({ - "role": Schema.String.annotate({ - "description": "The role of the message sender (e.g., system, user, developer)." - }), - "content": Schema.String.annotate({ "description": "The content of the message." }) - }).annotate({ "description": "An input message." }) - ).annotate({ "description": "An array of input messages." }), - "output": Schema.Array( - Schema.Struct({ - "role": Schema.optionalKey( - Schema.String.annotate({ - "description": "The role of the message (e.g. \"system\", \"assistant\", \"user\")." - }) - ), - "content": Schema.optionalKey(Schema.String.annotate({ "description": "The content of the message." })) - }) - ).annotate({ "description": "An array of output messages." }), - "finish_reason": Schema.String.annotate({ "description": "The reason why the sample generation was finished." }), - "model": Schema.String.annotate({ "description": "The model used for generating the sample." }), - "usage": Schema.Struct({ - "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check( - Schema.isInt() - ), - "completion_tokens": Schema.Number.annotate({ "description": "The number of completion tokens generated." }) - .check(Schema.isInt()), - "prompt_tokens": Schema.Number.annotate({ "description": "The number of prompt tokens used." }).check( - Schema.isInt() - ), - "cached_tokens": Schema.Number.annotate({ "description": "The number of tokens retrieved from cache." }).check( - Schema.isInt() - ) - }).annotate({ "description": "Token usage details for the sample." }), - "error": EvalApiError, - "temperature": Schema.Number.annotate({ "description": "The sampling temperature used." }).check(Schema.isFinite()), - "max_completion_tokens": Schema.Number.annotate({ - "description": "The maximum number of tokens allowed for completion." - }).check(Schema.isInt()), - "top_p": Schema.Number.annotate({ "description": "The top_p value used for sampling." }).check(Schema.isFinite()), - "seed": Schema.Number.annotate({ "description": "The seed used for generating the sample." }).check(Schema.isInt()) - }).annotate({ "description": "A sample containing the input and output of the evaluation run." }) -}).annotate({ "title": "EvalRunOutputItem", "description": "A schema representing an evaluation run output item.\n" }) -export type CreateFileRequest = { - readonly "file": string - readonly "purpose": "assistants" | "batch" | "fine-tune" | "vision" | "user_data" | "evals" - readonly "expires_after"?: FileExpirationAfter -} -export const CreateFileRequest = Schema.Struct({ - "file": Schema.String.annotate({ - "description": "The File object (not file name) to be uploaded.\n", - "format": "binary" - }), - "purpose": Schema.Literals(["assistants", "batch", "fine-tune", "vision", "user_data", "evals"]).annotate({ - "description": - "The intended purpose of the uploaded file. One of:\n- `assistants`: Used in the Assistants API\n- `batch`: Used in the Batch API\n- `fine-tune`: Used for fine-tuning\n- `vision`: Images used for vision fine-tuning\n- `user_data`: Flexible file type for any purpose\n- `evals`: Used for eval data sets\n" - }), - "expires_after": Schema.optionalKey(FileExpirationAfter) +export type McpConnectionOriginResource = "service" | "environment" +export const McpConnectionOriginResource = Schema.Literals(["service", "environment"]).annotate({ + "description": "Where outbound MCP HTTP connections originate.", + "identifier": "McpConnectionOriginResource" }) -export type CreateUploadRequest = { - readonly "filename": string - readonly "purpose": "assistants" | "batch" | "fine-tune" | "vision" - readonly "bytes": number - readonly "mime_type": string - readonly "expires_after"?: FileExpirationAfter -} -export const CreateUploadRequest = Schema.Struct({ - "filename": Schema.String.annotate({ "description": "The name of the file to upload.\n" }), - "purpose": Schema.Literals(["assistants", "batch", "fine-tune", "vision"]).annotate({ - "description": - "The intended purpose of the uploaded file.\n\nSee the [documentation on File\npurposes](/docs/api-reference/files/create#files-create-purpose).\n" - }), - "bytes": Schema.Number.annotate({ "description": "The number of bytes in the file you are uploading.\n" }).check( - Schema.isInt() - ), - "mime_type": Schema.String.annotate({ - "description": - "The MIME type of the file.\n\n\nThis must fall within the supported MIME types for your file purpose. See\nthe supported MIME types for assistants and vision.\n" - }), - "expires_after": Schema.optionalKey(FileExpirationAfter) +export type WebSearchModeResource = "disabled" | "cached" | "live" +export const WebSearchModeResource = Schema.Literals(["disabled", "cached", "live"]).annotate({ + "description": "The source used for web search results.", + "identifier": "WebSearchModeResource" }) -export type FileSearchRankingOptions = { readonly "ranker"?: FileSearchRanker; readonly "score_threshold": number } -export const FileSearchRankingOptions = Schema.Struct({ - "ranker": Schema.optionalKey(FileSearchRanker), - "score_threshold": Schema.Number.annotate({ - "description": - "The score threshold for the file search. All values must be a floating point number between 0 and 1." - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)) +export type WebSearchContextSizeResource = "low" | "medium" | "high" +export const WebSearchContextSizeResource = Schema.Literals(["low", "medium", "high"]).annotate({ + "description": "The amount of web search context made available to the model.", + "identifier": "WebSearchContextSizeResource" +}) +export type WebSearchLocationResource = { + readonly "country": string | null + readonly "region": string | null + readonly "city": string | null + readonly "timezone": string | null +} +export const WebSearchLocationResource = Schema.Struct({ + "country": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The two-letter ISO country code, such as `US`." }), + "region": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The region or state name." }), + "city": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The city name." }), + "timezone": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The IANA timezone, such as `America/Los_Angeles`." }) }).annotate({ - "title": "File search tool call ranking options", - "description": - "The ranking options for the file search. If not specified, the file search tool will use the `auto` ranker and a score_threshold of 0.\n\nSee the [file search tool documentation](/docs/assistants/tools/file-search#customizing-file-search-settings) for more information.\n" + "description": "Approximate user location used to localize web search results.", + "identifier": "WebSearchLocationResource" }) -export type RunStepDetailsToolCallsFileSearchRankingOptionsObject = { - readonly "ranker": FileSearchRanker - readonly "score_threshold": number -} -export const RunStepDetailsToolCallsFileSearchRankingOptionsObject = Schema.Struct({ - "ranker": FileSearchRanker, - "score_threshold": Schema.Number.annotate({ +export type PersistedAgentToolResourceComputerUse = { + readonly "type": "computer_use" + readonly "include_screenshots": boolean +} +export const PersistedAgentToolResourceComputerUse = Schema.Struct({ + "type": Schema.Literal("computer_use").annotate({ "description": "The type of the object. Always `computer_use`." }), + "include_screenshots": Schema.Boolean.annotate({ + "description": "Whether computer tool outputs include screenshots." + }) +}).annotate({ + "description": "Browser use in an OpenAI-hosted session.", + "identifier": "PersistedAgentToolResourceComputerUse" +}) +export type MultiAgentConfigResource = { + readonly "enabled": boolean + readonly "max_concurrent_subagents": number | null +} +export const MultiAgentConfigResource = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Whether subagent tools are enabled. Defaults to false." }), + "max_concurrent_subagents": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check( + Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" }) + ), + Schema.Null + ]).annotate({ "description": - "The score threshold for the file search. All values must be a floating point number between 0 and 1." - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)) + "Maximum number of subagents that may run concurrently, or null when disabled. Defaults to 6 when enabled.", + "format": "int64" + }) }).annotate({ - "title": "File search tool call ranking options", - "description": "The ranking options for the file search." + "description": "The resolved configuration for creating and coordinating subagents.", + "identifier": "MultiAgentConfigResource" }) -export type FineTuneDPOMethod = { readonly "hyperparameters"?: FineTuneDPOHyperparameters } -export const FineTuneDPOMethod = Schema.Struct({ "hyperparameters": Schema.optionalKey(FineTuneDPOHyperparameters) }) - .annotate({ "description": "Configuration for the DPO fine-tuning method." }) -export type FineTuneSupervisedMethod = { readonly "hyperparameters"?: FineTuneSupervisedHyperparameters } -export const FineTuneSupervisedMethod = Schema.Struct({ - "hyperparameters": Schema.optionalKey(FineTuneSupervisedHyperparameters) -}).annotate({ "description": "Configuration for the supervised fine-tuning method." }) -export type ListFineTuningCheckpointPermissionResponse = { - readonly "data": ReadonlyArray - readonly "object": "list" - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const ListFineTuningCheckpointPermissionResponse = Schema.Struct({ - "data": Schema.Array(FineTuningCheckpointPermission), - "object": Schema.Literal("list"), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean +export type ReasoningEffortParam = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" +export const ReasoningEffortParam = Schema.Literals(["none", "minimal", "low", "medium", "high", "xhigh", "max"]) + .annotate({ + "description": "The amount of reasoning effort the model should use.", + "identifier": "ReasoningEffortParam" + }) +export type ReasoningSummaryParam = "concise" | "detailed" | "auto" +export const ReasoningSummaryParam = Schema.Literals(["concise", "detailed", "auto"]).annotate({ + "description": "The reasoning summary format requested from the model.", + "identifier": "ReasoningSummaryParam" }) -export type ListFineTuningJobCheckpointsResponse = { - readonly "data": ReadonlyArray - readonly "object": "list" - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const ListFineTuningJobCheckpointsResponse = Schema.Struct({ - "data": Schema.Array(FineTuningJobCheckpoint), - "object": Schema.Literal("list"), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean +export type TextFormatParamText = { readonly "type": "text" } +export const TextFormatParamText = Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "The type of the object. Always `text`." }) +}).annotate({ + "description": "Generates ordinary text without a structured-output constraint.", + "identifier": "TextFormatParamText" }) -export type ListFineTuningJobEventsResponse = { - readonly "data": ReadonlyArray - readonly "object": "list" - readonly "has_more": boolean -} -export const ListFineTuningJobEventsResponse = Schema.Struct({ - "data": Schema.Array(FineTuningJobEvent), - "object": Schema.Literal("list"), - "has_more": Schema.Boolean +export type TextFormatParamJsonSchema = { + readonly "type": "json_schema" + readonly "schema": { readonly [x: string]: Schema.Json } +} +export const TextFormatParamJsonSchema = Schema.Struct({ + "type": Schema.Literal("json_schema").annotate({ "description": "The type of the object. Always `json_schema`." }), + "schema": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The JSON Schema that generated text must match." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) +}).annotate({ "description": "Constrains generated text to a JSON Schema.", "identifier": "TextFormatParamJsonSchema" }) +export type VerbosityParam = "low" | "medium" | "high" +export const VerbosityParam = Schema.Literals(["low", "medium", "high"]).annotate({ + "description": "The amount of text the model should produce.", + "identifier": "VerbosityParam" }) -export type ChatCompletionFunctions = { - readonly "description"?: string +export type ServiceTierParam = "auto" | "default" | "flex" | "priority" | "fast" +export const ServiceTierParam = Schema.Literals(["auto", "default", "flex", "priority", "fast"]).annotate({ + "description": "The service tier used for model requests.", + "identifier": "ServiceTierParam" +}) +export type PersistedAgentToolConfigParamFunction = { + readonly "type": "function" readonly "name": string - readonly "parameters"?: FunctionParameters + readonly "description": string + readonly "parameters": { readonly [x: string]: Schema.Json } + readonly "defer_loading"?: boolean } -export const ChatCompletionFunctions = Schema.Struct({ - "description": Schema.optionalKey( - Schema.String.annotate({ - "description": - "A description of what the function does, used by the model to choose when and how to call the function." - }) +export const PersistedAgentToolConfigParamFunction = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The type of the object. Always `function`." }), + "name": Schema.String.annotate({ "description": "The name of the function." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "description": Schema.String.annotate({ "description": "A description of what the function does." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "parameters": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON Schema object describing the function's arguments." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ) + ).annotate({ "expected": "an object with property names matching the schema" }) ), - "name": Schema.String.annotate({ - "description": - "The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64." - }), - "parameters": Schema.optionalKey(FunctionParameters) + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether this function is deferred and discovered through tool search. Defaults to `false`." + }) + ) +}).annotate({ + "description": "A function defined by the application.", + "identifier": "PersistedAgentToolConfigParamFunction" }) -export type FunctionObject = { - readonly "description"?: string - readonly "name": string - readonly "parameters"?: FunctionParameters - readonly "strict"?: boolean | null +export type PersistedAgentToolConfigParamToolSearch = { readonly "type": "tool_search" } +export const PersistedAgentToolConfigParamToolSearch = Schema.Struct({ + "type": Schema.Literal("tool_search").annotate({ "description": "The type of the object. Always `tool_search`." }) +}).annotate({ + "description": "Discovers deferred function tools and loads them into the model context.", + "identifier": "PersistedAgentToolConfigParamToolSearch" +}) +export type PersistedAgentToolConfigParamProgrammaticToolCalling = { + readonly "type": "programmatic_tool_calling" + readonly "enabled"?: boolean } -export const FunctionObject = Schema.Struct({ - "description": Schema.optionalKey( - Schema.String.annotate({ - "description": - "A description of what the function does, used by the model to choose when and how to call the function." - }) - ), - "name": Schema.String.annotate({ - "description": - "The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64." +export const PersistedAgentToolConfigParamProgrammaticToolCalling = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The type of the object. Always `programmatic_tool_calling`." }), - "parameters": Schema.optionalKey(FunctionParameters), - "strict": Schema.optionalKey(Schema.Union([ + "enabled": Schema.optionalKey( Schema.Boolean.annotate({ - "description": - "Whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the `parameters` field. Only a subset of JSON Schema is supported when `strict` is `true`. Learn more about Structured Outputs in the [function calling guide](/docs/guides/function-calling)." - }), - Schema.Null - ])) + "description": "Whether tools can be called from model-generated code. Defaults to `true`." + }) + ) +}).annotate({ + "description": "Enables calling tools from model-generated code.", + "identifier": "PersistedAgentToolConfigParamProgrammaticToolCalling" }) -export type GroupListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "next": string | null -} -export const GroupListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), - "data": Schema.Array(GroupResponse).annotate({ "description": "Groups returned in the current page." }), - "has_more": Schema.Boolean.annotate({ "description": "Whether additional groups are available when paginating." }), - "next": Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "Cursor to fetch the next page of results, or `null` if there are no more results." - }) -}).annotate({ "description": "Paginated list of organization groups." }) -export type UserListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "next": string | null -} -export const UserListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), - "data": Schema.Array(GroupUser).annotate({ "description": "Users in the current page." }), - "has_more": Schema.Boolean.annotate({ "description": "Whether more users are available when paginating." }), - "next": Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "Cursor to fetch the next page of results, or `null` when no further users are available." - }) -}).annotate({ "description": "Paginated list of user objects returned when inspecting group membership." }) -export type ProjectHostedToolPermissions = { - readonly "file_search": HostedToolPermission - readonly "web_search": HostedToolPermission - readonly "image_generation": HostedToolPermission - readonly "mcp": HostedToolPermission - readonly "code_interpreter": HostedToolPermission -} -export const ProjectHostedToolPermissions = Schema.Struct({ - "file_search": HostedToolPermission, - "web_search": HostedToolPermission, - "image_generation": HostedToolPermission, - "mcp": HostedToolPermission, - "code_interpreter": HostedToolPermission -}).annotate({ "description": "Represents hosted tool permissions for a project." }) -export type ProjectHostedToolPermissionsUpdateRequest = { - readonly "file_search"?: HostedToolPermissionUpdate | null - readonly "web_search"?: HostedToolPermissionUpdate | null - readonly "image_generation"?: HostedToolPermissionUpdate | null - readonly "mcp"?: HostedToolPermissionUpdate | null - readonly "code_interpreter"?: HostedToolPermissionUpdate | null -} -export const ProjectHostedToolPermissionsUpdateRequest = Schema.Struct({ - "file_search": Schema.optionalKey( - Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ - "description": "The file search permission update." - }) +export type PersistedMcpTransportConfigParamHttp = { + readonly "type": "http" + readonly "server_url": string + readonly "headers"?: { readonly [x: string]: string } | null +} +export const PersistedMcpTransportConfigParamHttp = Schema.Struct({ + "type": Schema.Literal("http").annotate({ "description": "The type of the object. Always `http`." }), + "server_url": Schema.String.annotate({ "description": "The URL of the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "headers": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ "description": "Non-secret HTTP headers sent to the MCP server." }) + ) +}).annotate({ + "description": "Connects to an MCP server over HTTP.", + "identifier": "PersistedMcpTransportConfigParamHttp" +}) +export type PersistedMcpTransportConfigParamStdio = { + readonly "type": "stdio" + readonly "command": string + readonly "args"?: ReadonlyArray | null + readonly "cwd": string + readonly "env_vars"?: ReadonlyArray | null +} +export const PersistedMcpTransportConfigParamStdio = Schema.Struct({ + "type": Schema.Literal("stdio").annotate({ "description": "The type of the object. Always `stdio`." }), + "command": Schema.String.annotate({ "description": "The command used to start the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "args": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "Arguments passed to the MCP server command." }) ), - "web_search": Schema.optionalKey( - Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ - "description": "The web search permission update." - }) + "cwd": Schema.String.annotate({ "description": "The working directory used to start the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "env_vars": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "Environment variable names to inherit from the selected execution environment." }) + ) +}).annotate({ + "description": "Starts an MCP server as a local process.", + "identifier": "PersistedMcpTransportConfigParamStdio" +}) +export type McpConnectionOriginParam = "service" | "environment" +export const McpConnectionOriginParam = Schema.Literals(["service", "environment"]).annotate({ + "description": "Where outbound MCP HTTP connections originate.", + "identifier": "McpConnectionOriginParam" +}) +export type WebSearchModeParam = "disabled" | "cached" | "live" +export const WebSearchModeParam = Schema.Literals(["disabled", "cached", "live"]).annotate({ + "description": "The source used for web search results.", + "identifier": "WebSearchModeParam" +}) +export type WebSearchContextSizeParam = "low" | "medium" | "high" +export const WebSearchContextSizeParam = Schema.Literals(["low", "medium", "high"]).annotate({ + "description": "The amount of web search context made available to the model.", + "identifier": "WebSearchContextSizeParam" +}) +export type WebSearchLocationParam = { + readonly "country"?: string | null + readonly "region"?: string | null + readonly "city"?: string | null + readonly "timezone"?: string | null +} +export const WebSearchLocationParam = Schema.Struct({ + "country": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The two-letter ISO country code, such as `US`." }) ), - "image_generation": Schema.optionalKey( - Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ - "description": "The image generation permission update." - }) + "region": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The region or state name." }) ), - "mcp": Schema.optionalKey( - Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ "description": "The MCP permission update." }) + "city": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The city name." }) ), - "code_interpreter": Schema.optionalKey( - Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ - "description": "The code interpreter permission update." + "timezone": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The IANA timezone, such as `America/Los_Angeles`." }) + ) +}).annotate({ + "description": "Approximate user location used to localize web search results.", + "identifier": "WebSearchLocationParam" +}) +export type PersistedAgentToolConfigParamComputerUse = { + readonly "type": "computer_use" + readonly "include_screenshots"?: boolean +} +export const PersistedAgentToolConfigParamComputerUse = Schema.Struct({ + "type": Schema.Literal("computer_use").annotate({ "description": "The type of the object. Always `computer_use`." }), + "include_screenshots": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether computer tool outputs include screenshots. Defaults to `false`." }) ) +}).annotate({ + "description": "Browser use in an OpenAI-hosted session.", + "identifier": "PersistedAgentToolConfigParamComputerUse" }) -export type ImageEditCompletedEvent = { - readonly "type": "image_edit.completed" - readonly "b64_json": string - readonly "created_at": number - readonly "size": "1024x1024" | "1024x1536" | "1536x1024" | "auto" - readonly "quality": "low" | "medium" | "high" | "auto" - readonly "background": "transparent" | "opaque" | "auto" - readonly "output_format": "png" | "webp" | "jpeg" - readonly "usage": ImagesUsage +export type MultiAgentConfigCurrentParam = { readonly "enabled": boolean; readonly "max_concurrent_subagents"?: number } +export const MultiAgentConfigCurrentParam = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ "description": "Whether subagent tools are enabled." }), + "max_concurrent_subagents": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Maximum number of subagents that may run concurrently. Defaults to 6.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })) + ) +}).annotate({ + "description": "Explicit configuration for creating and coordinating subagents.", + "identifier": "MultiAgentConfigCurrentParam" +}) +export type DeletedAgentResource = { + readonly "id": string + readonly "object": "agent.deleted" + readonly "deleted": boolean } -export const ImageEditCompletedEvent = Schema.Struct({ - "type": Schema.Literal("image_edit.completed").annotate({ - "description": "The type of the event. Always `image_edit.completed`.\n" - }), - "b64_json": Schema.String.annotate({ - "description": "Base64-encoded final edited image data, suitable for rendering as an image.\n" - }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp when the event was created.\n", - "format": "unixtime" - }).check(Schema.isInt()), - "size": Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"]).annotate({ - "description": "The size of the edited image.\n" - }), - "quality": Schema.Literals(["low", "medium", "high", "auto"]).annotate({ - "description": "The quality setting for the edited image.\n" - }), - "background": Schema.Literals(["transparent", "opaque", "auto"]).annotate({ - "description": "The background setting for the edited image.\n" - }), - "output_format": Schema.Literals(["png", "webp", "jpeg"]).annotate({ - "description": "The output format for the edited image.\n" - }), - "usage": ImagesUsage -}).annotate({ "description": "Emitted when image editing has completed and the final image is available.\n" }) -export type ImageGenCompletedEvent = { - readonly "type": "image_generation.completed" - readonly "b64_json": string - readonly "created_at": number - readonly "size": "1024x1024" | "1024x1536" | "1536x1024" | "auto" - readonly "quality": "low" | "medium" | "high" | "auto" - readonly "background": "transparent" | "opaque" | "auto" - readonly "output_format": "png" | "webp" | "jpeg" - readonly "usage": ImagesUsage +export const DeletedAgentResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the deleted agent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("agent.deleted").annotate({ "description": "The object type. Always `agent.deleted`." }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the agent was deleted. Always `true`." }) +}).annotate({ "description": "A deleted reusable agent.", "identifier": "DeletedAgentResource" }) +export type EnvironmentPackagesResource = { + readonly "python": ReadonlyArray + readonly "system": ReadonlyArray + readonly "npm": ReadonlyArray +} +export const EnvironmentPackagesResource = Schema.Struct({ + "python": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).annotate({ "description": "Python packages installed in the environment." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" })), + "system": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).annotate({ "description": "System packages installed in the environment." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" })), + "npm": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).annotate({ "description": "npm packages installed globally in the environment." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" })) +}).annotate({ + "description": "Packages installed in an OpenAI-hosted environment.", + "identifier": "EnvironmentPackagesResource" +}) +export type NetworkAccessResource = "enabled" | "disabled" | "restricted" +export const NetworkAccessResource = Schema.Literals(["enabled", "disabled", "restricted"]).annotate({ + "description": "The network access mode for an OpenAI-hosted environment.", + "identifier": "NetworkAccessResource" +}) +export type DesktopResource = { readonly "enabled": boolean } +export const DesktopResource = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ + "description": "Whether the environment provisions a desktop and browser proxy." + }) +}).annotate({ + "description": "The effective desktop configuration for an OpenAI-hosted environment.", + "identifier": "DesktopResource" +}) +export type HostedTemplateSkillResourceSkillReference = { + readonly "type": "skill_reference" + readonly "skill_id": string + readonly "version": string | null } -export const ImageGenCompletedEvent = Schema.Struct({ - "type": Schema.Literal("image_generation.completed").annotate({ - "description": "The type of the event. Always `image_generation.completed`.\n" - }), - "b64_json": Schema.String.annotate({ - "description": "Base64-encoded image data, suitable for rendering as an image.\n" - }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp when the event was created.\n", - "format": "unixtime" - }).check(Schema.isInt()), - "size": Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"]).annotate({ - "description": "The size of the generated image.\n" - }), - "quality": Schema.Literals(["low", "medium", "high", "auto"]).annotate({ - "description": "The quality setting for the generated image.\n" - }), - "background": Schema.Literals(["transparent", "opaque", "auto"]).annotate({ - "description": "The background setting for the generated image.\n" - }), - "output_format": Schema.Literals(["png", "webp", "jpeg"]).annotate({ - "description": "The output format for the generated image.\n" +export const HostedTemplateSkillResourceSkillReference = Schema.Struct({ + "type": Schema.Literal("skill_reference").annotate({ + "description": "The type of the object. Always `skill_reference`." }), - "usage": ImagesUsage -}).annotate({ "description": "Emitted when image generation has completed and the final image is available.\n" }) -export type InviteListResponse = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const InviteListResponse = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`" }), - "data": Schema.Array(Invite), - "first_id": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "The first `invite_id` in the retrieved `list`" - }) + "skill_id": Schema.String.annotate({ "description": "The referenced skill ID." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "last_id": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "The last `invite_id` in the retrieved `list`" - }) + "version": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The requested version selector, including `latest`." }) +}).annotate({ + "description": "A skill resolved afresh from the Skills API whenever a session starts.", + "identifier": "HostedTemplateSkillResourceSkillReference" +}) +export type HostedTemplateSkillResourceInline = { + readonly "type": "inline" + readonly "name": string + readonly "description": string +} +export const HostedTemplateSkillResourceInline = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "The type of the object. Always `inline`." }), + "name": Schema.String.annotate({ "description": "The skill name declared in `SKILL.md`." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "has_more": Schema.Boolean.annotate({ - "description": "The `has_more` property is used for pagination to indicate there are additional results." - }) + "description": Schema.String.annotate({ "description": "The skill description declared in `SKILL.md`." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "Safe metadata for an inline skill archive.", + "identifier": "HostedTemplateSkillResourceInline" }) -export type RealtimeServerEventConversationItemInputAudioTranscriptionCompleted = { - readonly "event_id": string - readonly "type": "conversation.item.input_audio_transcription.completed" - readonly "item_id": string - readonly "content_index": number - readonly "transcript": string - readonly "logprobs"?: ReadonlyArray | null - readonly "usage": { - readonly "type": "tokens" - readonly "input_tokens": number - readonly "input_token_details"?: { readonly "text_tokens"?: number; readonly "audio_tokens"?: number } - readonly "output_tokens": number - readonly "total_tokens": number - } | { readonly "type": "duration"; readonly "seconds": number } +export type HostedTemplateFileResourceFileId = { + readonly "type": "file_id" + readonly "file_id": string + readonly "path": string } -export const RealtimeServerEventConversationItemInputAudioTranscriptionCompleted = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.input_audio_transcription.completed").annotate({ - "description": "The event type, must be\n`conversation.item.input_audio_transcription.completed`.\n" - }), - "item_id": Schema.String.annotate({ - "description": "The ID of the item containing the audio that is being transcribed." - }), - "content_index": Schema.Number.annotate({ "description": "The index of the content part containing the audio." }) - .check(Schema.isInt()), - "transcript": Schema.String.annotate({ "description": "The transcribed text." }), - "logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Array(LogProbProperties).annotate({ "description": "The log probabilities of the transcription." }), - Schema.Null - ]) +export const HostedTemplateFileResourceFileId = Schema.Struct({ + "type": Schema.Literal("file_id").annotate({ "description": "The type of the object. Always `file_id`." }), + "file_id": Schema.String.annotate({ "description": "The ID of the uploaded file." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "usage": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("tokens").annotate({ - "description": "The type of the usage object. Always `tokens` for this variant." - }), - "input_tokens": Schema.Number.annotate({ "description": "Number of input tokens billed for this request." }) - .check(Schema.isInt()), - "input_token_details": Schema.optionalKey( - Schema.Struct({ - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of text tokens billed for this request." }).check( - Schema.isInt() - ) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of audio tokens billed for this request." }).check( - Schema.isInt() - ) - ) - }).annotate({ "description": "Details about the input tokens billed for this request." }) - ), - "output_tokens": Schema.Number.annotate({ "description": "Number of output tokens generated." }).check( - Schema.isInt() - ), - "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (input + output)." }).check( - Schema.isInt() - ) - }).annotate({ - "title": "Token Usage", - "description": - "Usage statistics for the transcription, this is billed according to the ASR model's pricing rather than the realtime model's pricing." - }), - Schema.Struct({ - "type": Schema.Literal("duration").annotate({ - "description": "The type of the usage object. Always `duration` for this variant." - }), - "seconds": Schema.Number.annotate({ - "description": "Duration of the input audio in seconds.", - "format": "double" - }).check(Schema.isFinite()) - }).annotate({ - "title": "Duration Usage", - "description": - "Usage statistics for the transcription, this is billed according to the ASR model's pricing rather than the realtime model's pricing." - }) - ], { mode: "oneOf" }) + "path": Schema.String.annotate({ "description": "The file's absolute path inside the environment." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) }).annotate({ - "description": - "This event is the output of audio transcription for user audio written to the\nuser audio buffer. Transcription begins when the input audio buffer is\ncommitted by the client or server (when VAD is enabled). Transcription runs\nasynchronously with Response creation, so this event may come before or after\nthe Response events.\n\nRealtime API models accept audio natively, and thus input transcription is a\nseparate process run on a separate ASR (Automatic Speech Recognition) model.\nThe transcript may diverge somewhat from the model's interpretation, and\nshould be treated as a rough guide.\n" + "description": "A project-scoped Files API reference resolved separately for each session.", + "identifier": "HostedTemplateFileResourceFileId" }) -export type RealtimeServerEventConversationItemInputAudioTranscriptionDelta = { - readonly "event_id": string - readonly "type": "conversation.item.input_audio_transcription.delta" - readonly "item_id": string - readonly "content_index"?: number - readonly "delta"?: string - readonly "logprobs"?: ReadonlyArray | null +export type HostedTemplateFileResourceInline = { + readonly "type": "inline" + readonly "path": string + readonly "size_bytes": number } -export const RealtimeServerEventConversationItemInputAudioTranscriptionDelta = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.input_audio_transcription.delta").annotate({ - "description": "The event type, must be `conversation.item.input_audio_transcription.delta`." - }), - "item_id": Schema.String.annotate({ - "description": "The ID of the item containing the audio that is being transcribed." - }), - "content_index": Schema.optionalKey( - Schema.Number.annotate({ "description": "The index of the content part in the item's content array." }).check( - Schema.isInt() - ) +export const HostedTemplateFileResourceInline = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "The type of the object. Always `inline`." }), + "path": Schema.String.annotate({ "description": "The file's absolute path inside the environment." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "delta": Schema.optionalKey(Schema.String.annotate({ "description": "The text delta." })), - "logprobs": Schema.optionalKey(Schema.Union([ - Schema.Array(LogProbProperties).annotate({ - "description": - "The log probabilities of the transcription. These can be enabled by configurating the session with `\"include\": [\"item.input_audio_transcription.logprobs\"]`. Each entry in the array corresponds a log probability of which token would be selected for this chunk of transcription. This can help to identify if it was possible there were multiple valid options for a given chunk of transcription." - }), - Schema.Null - ])) + "size_bytes": Schema.Number.annotate({ + "description": "The decoded size of the inline file in bytes.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ) }).annotate({ - "description": - "Returned when the text value of an input audio transcription content part is updated with incremental transcription results.\n" + "description": "Metadata for confidential inline file contents.", + "identifier": "HostedTemplateFileResourceInline" }) -export type MCPListTools = { - readonly "type": "mcp_list_tools" +export type DeletedEnvironmentTemplateResource = { readonly "id": string - readonly "server_label": string - readonly "tools": ReadonlyArray - readonly "error"?: string | null + readonly "object": "agent.environment.template.deleted" + readonly "deleted": boolean } -export const MCPListTools = Schema.Struct({ - "type": Schema.Literal("mcp_list_tools").annotate({ - "description": "The type of the item. Always `mcp_list_tools`.\n" +export const DeletedEnvironmentTemplateResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the deleted environment template." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("agent.environment.template.deleted").annotate({ + "description": "The object type. Always `agent.environment.template.deleted`." }), - "id": Schema.String.annotate({ "description": "The unique ID of the list.\n" }), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server.\n" }), - "tools": Schema.Array(MCPListToolsTool).annotate({ "description": "The tools available on the server.\n" }), - "error": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "Error message if the server could not list tools.\n" }), - Schema.Null - ]) + "deleted": Schema.Boolean.annotate({ "description": "Whether the environment template was deleted. Always `true`." }) +}).annotate({ + "description": "A deleted reusable environment template.", + "identifier": "DeletedEnvironmentTemplateResource" +}) +export type SessionSpendControlResource = { readonly "limit": number; readonly "consumed": number | null } +export const SessionSpendControlResource = Schema.Struct({ + "limit": Schema.Number.annotate({ "description": "The configured positive limit in USD cents.", "format": "int64" }) + .check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check( + Schema.isLessThanOrEqualTo(4503599627370495).annotate({ + "expected": "a value less than or equal to 4503599627370495" + }) + ), + "consumed": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ), + Schema.Null + ]).annotate({ "description": "Best-effort recorded spend floored to whole USD cents, or null when unavailable." }) +}).annotate({ + "description": "Session-wide spending control, present only when a limit is configured.", + "identifier": "SessionSpendControlResource" +}) +export type SessionStatusResource = "idle" | "in_progress" | "requires_action" | "failed" +export const SessionStatusResource = Schema.Literals(["idle", "in_progress", "requires_action", "failed"]).annotate({ + "description": "The current status of a session.", + "identifier": "SessionStatusResource" +}) +export type ComputerUseApprovalRequestKindResourceBrowserOriginAccess = { + readonly "type": "browser_origin_access" + readonly "reason": string | null + readonly "origin": string +} +export const ComputerUseApprovalRequestKindResourceBrowserOriginAccess = Schema.Struct({ + "type": Schema.Literal("browser_origin_access").annotate({ + "description": "The type of the object. Always `browser_origin_access`." + }), + "reason": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The browser's explanation for this request, or null when unavailable." }), + "origin": Schema.String.annotate({ "description": "The origin the browser needs permission to access." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ) -}).annotate({ "title": "MCP list tools", "description": "A list of tools available on an MCP server.\n" }) -export type RealtimeMCPListTools = { - readonly "type": "mcp_list_tools" - readonly "id"?: string - readonly "server_label": string - readonly "tools": ReadonlyArray +}).annotate({ + "description": "A browser origin awaiting the application's approval decision.", + "identifier": "ComputerUseApprovalRequestKindResourceBrowserOriginAccess" +}) +export type SessionRequiredActionResourceFunctionCall = { + readonly "type": "function_call" + readonly "turn_id": string + readonly "call_id": string + readonly "name": string + readonly "arguments": Schema.Json } -export const RealtimeMCPListTools = Schema.Struct({ - "type": Schema.Literal("mcp_list_tools").annotate({ - "description": "The type of the item. Always `mcp_list_tools`." +export const SessionRequiredActionResourceFunctionCall = Schema.Struct({ + "type": Schema.Literal("function_call").annotate({ + "description": "The type of the object. Always `function_call`." }), - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the list." })), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server." }), - "tools": Schema.Array(MCPListToolsTool).annotate({ "description": "The tools available on the server." }) + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that requested the function call." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "call_id": Schema.String.annotate({ "description": "The ID to include when submitting the function result." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "name": Schema.String.annotate({ "description": "The function name." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "arguments": Schema.Json.annotate({ "expected": "JSON value", "description": "The arguments supplied by the model." }) }).annotate({ - "title": "Realtime MCP list tools", - "description": "A Realtime item listing tools available on an MCP server.\n" + "description": "Run a function tool and submit its result.", + "identifier": "SessionRequiredActionResourceFunctionCall" }) -export type MCPTool = { - readonly "type": "mcp" - readonly "server_label": string - readonly "server_url"?: string - readonly "connector_id"?: - | "connector_dropbox" - | "connector_gmail" - | "connector_googlecalendar" - | "connector_googledrive" - | "connector_microsoftteams" - | "connector_outlookcalendar" - | "connector_outlookemail" - | "connector_sharepoint" - readonly "authorization"?: string - readonly "server_description"?: string - readonly "headers"?: {} | null - readonly "allowed_tools"?: ReadonlyArray | MCPToolFilter | null - readonly "require_approval"?: - | { readonly "always"?: MCPToolFilter; readonly "never"?: MCPToolFilter } - | "always" - | "never" - | null - readonly "defer_loading"?: boolean +export type SessionRequiredActionResourceEnvironmentConnection = { + readonly "type": "environment_connection" + readonly "environment_id": string } -export const MCPTool = Schema.Struct({ - "type": Schema.Literal("mcp").annotate({ "description": "The type of the MCP tool. Always `mcp`." }), - "server_label": Schema.String.annotate({ - "description": "A label for this MCP server, used to identify it in tool calls.\n" +export const SessionRequiredActionResourceEnvironmentConnection = Schema.Struct({ + "type": Schema.Literal("environment_connection").annotate({ + "description": "The type of the object. Always `environment_connection`." }), - "server_url": Schema.optionalKey( - Schema.String.annotate({ - "description": "The URL for the MCP server. One of `server_url` or `connector_id` must be\nprovided.\n", - "format": "uri" - }) + "environment_id": Schema.String.annotate({ "description": "The ID of the environment to reconnect." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "Reconnect a session environment.", + "identifier": "SessionRequiredActionResourceEnvironmentConnection" +}) +export type AgentToolResourceFunction = { + readonly "type": "function" + readonly "name": string + readonly "description": string + readonly "parameters": { readonly [x: string]: Schema.Json } + readonly "defer_loading": boolean +} +export const AgentToolResourceFunction = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The type of the object. Always `function`." }), + "name": Schema.String.annotate({ "description": "The name of the function." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "description": Schema.String.annotate({ "description": "A description of what the function does." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "parameters": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON Schema object describing the function's arguments." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + "defer_loading": Schema.Boolean.annotate({ + "description": "Whether the function is deferred and discovered through tool search." + }) +}).annotate({ "description": "A function defined by the application.", "identifier": "AgentToolResourceFunction" }) +export type AgentToolResourceProgrammaticToolCalling = { + readonly "type": "programmatic_tool_calling" + readonly "enabled": boolean +} +export const AgentToolResourceProgrammaticToolCalling = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The type of the object. Always `programmatic_tool_calling`." + }), + "enabled": Schema.Boolean.annotate({ "description": "Whether tools can be called from model-generated code." }) +}).annotate({ + "description": "Enables calling tools from model-generated code.", + "identifier": "AgentToolResourceProgrammaticToolCalling" +}) +export type McpTransportResourceHttp = { readonly "type": "http"; readonly "server_url": string } +export const McpTransportResourceHttp = Schema.Struct({ + "type": Schema.Literal("http").annotate({ "description": "The type of the object. Always `http`." }), + "server_url": Schema.String.annotate({ "description": "The URL of the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "Connects to an MCP server over HTTP.", "identifier": "McpTransportResourceHttp" }) +export type McpTransportResourceStdio = { + readonly "type": "stdio" + readonly "command": string + readonly "args": ReadonlyArray + readonly "cwd": string + readonly "env_vars": ReadonlyArray +} +export const McpTransportResourceStdio = Schema.Struct({ + "type": Schema.Literal("stdio").annotate({ "description": "The type of the object. Always `stdio`." }), + "command": Schema.String.annotate({ "description": "The command used to start the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "args": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Arguments passed to the MCP server command." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "cwd": Schema.String.annotate({ "description": "The working directory used to start the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "env_vars": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Environment variable names inherited from the execution environment." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })) +}).annotate({ "description": "Starts an MCP server as a local process.", "identifier": "McpTransportResourceStdio" }) +export type AgentToolResourceComputerUse = { readonly "type": "computer_use"; readonly "include_screenshots": boolean } +export const AgentToolResourceComputerUse = Schema.Struct({ + "type": Schema.Literal("computer_use").annotate({ "description": "The type of the object. Always `computer_use`." }), + "include_screenshots": Schema.Boolean.annotate({ + "description": "Whether computer tool outputs include screenshots." + }) +}).annotate({ "description": "Browser use in an OpenAI-hosted session.", "identifier": "AgentToolResourceComputerUse" }) +export type EnvironmentResourceNone = { readonly "type": "none" } +export const EnvironmentResourceNone = Schema.Struct({ + "type": Schema.Literal("none").annotate({ "description": "The type of the object. Always `none`." }) +}).annotate({ + "description": "The session talks to CCA without selecting or provisioning an execution environment.", + "identifier": "EnvironmentResourceNone" +}) +export type ContainerSizeResource = "small" | "medium" | "large" +export const ContainerSizeResource = Schema.Literals(["small", "medium", "large"]).annotate({ + "description": "The effective CPU and memory tier of an OpenAI-hosted environment.", + "identifier": "ContainerSizeResource" +}) +export type EnvironmentResourceSelfHosted = { + readonly "type": "self_hosted" + readonly "remote_url": string + readonly "id": string + readonly "workspace_directory": string + readonly "capability_directories": ReadonlyArray +} +export const EnvironmentResourceSelfHosted = Schema.Struct({ + "type": Schema.Literal("self_hosted").annotate({ "description": "The type of the object. Always `self_hosted`." }), + "remote_url": Schema.String.annotate({ + "description": "Pass this URL unchanged to `codex exec-server --remote` when connecting this environment." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "id": Schema.String.annotate({ "description": "The public ID of the environment." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "workspace_directory": Schema.String.annotate({ + "description": "The absolute project directory inside the environment. Defaults to `/workspace`." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "capability_directories": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Directories that contain capabilities exposed to the agent." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })) +}).annotate({ + "description": "An environment hosted by the application.", + "identifier": "EnvironmentResourceSelfHosted" +}) +export type SessionSpendControlParam = { readonly "limit": number | null } +export const SessionSpendControlParam = Schema.Struct({ + "limit": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check( + Schema.isLessThanOrEqualTo(4503599627370495).annotate({ + "expected": "a value less than or equal to 4503599627370495" + }) + ), + Schema.Null + ]).annotate({ "description": "Positive USD cents, or null to remove the limit.", "format": "int64" }) +}).annotate({ + "description": "Sets the session-wide limit without changing recorded spend.", + "identifier": "SessionSpendControlParam" +}) +export type AgentToolConfigParamFunction = { + readonly "type": "function" + readonly "name": string + readonly "description": string + readonly "parameters": { readonly [x: string]: Schema.Json } + readonly "defer_loading"?: boolean +} +export const AgentToolConfigParamFunction = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The type of the object. Always `function`." }), + "name": Schema.String.annotate({ "description": "The name of the function." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "description": Schema.String.annotate({ "description": "A description of what the function does." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "parameters": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON Schema object describing the function's arguments." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ) + ).annotate({ "expected": "an object with property names matching the schema" }) ), - "connector_id": Schema.optionalKey( - Schema.Literals([ - "connector_dropbox", - "connector_gmail", - "connector_googlecalendar", - "connector_googledrive", - "connector_microsoftteams", - "connector_outlookcalendar", - "connector_outlookemail", - "connector_sharepoint" - ]).annotate({ - "description": - "Identifier for service connectors, like those available in ChatGPT. One of\n`server_url` or `connector_id` must be provided. Learn more about service\nconnectors [here](/docs/guides/tools-remote-mcp#connectors).\n\nCurrently supported `connector_id` values are:\n\n- Dropbox: `connector_dropbox`\n- Gmail: `connector_gmail`\n- Google Calendar: `connector_googlecalendar`\n- Google Drive: `connector_googledrive`\n- Microsoft Teams: `connector_microsoftteams`\n- Outlook Calendar: `connector_outlookcalendar`\n- Outlook Email: `connector_outlookemail`\n- SharePoint: `connector_sharepoint`\n" + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether this function is deferred and discovered through tool search. Defaults to `false`." }) - ), - "authorization": Schema.optionalKey( - Schema.String.annotate({ - "description": - "An OAuth access token that can be used with a remote MCP server, either\nwith a custom MCP server URL or a service connector. Your application\nmust handle the OAuth authorization flow and provide the token here.\n" + ) +}).annotate({ "description": "A function defined by the application.", "identifier": "AgentToolConfigParamFunction" }) +export type AgentToolConfigParamToolSearch = { readonly "type": "tool_search" } +export const AgentToolConfigParamToolSearch = Schema.Struct({ + "type": Schema.Literal("tool_search").annotate({ "description": "The type of the object. Always `tool_search`." }) +}).annotate({ + "description": "Discovers deferred function tools and loads them into the model context.", + "identifier": "AgentToolConfigParamToolSearch" +}) +export type AgentToolConfigParamProgrammaticToolCalling = { + readonly "type": "programmatic_tool_calling" + readonly "enabled"?: boolean +} +export const AgentToolConfigParamProgrammaticToolCalling = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The type of the object. Always `programmatic_tool_calling`." + }), + "enabled": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether tools can be called from model-generated code. Defaults to `true`." }) - ), - "server_description": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional description of the MCP server, used to provide more context.\n" }) + ) +}).annotate({ + "description": "Enables calling tools from model-generated code.", + "identifier": "AgentToolConfigParamProgrammaticToolCalling" +}) +export type McpTransportConfigParamHttp = { + readonly "type": "http" + readonly "server_url": string + readonly "authorization"?: string | null + readonly "headers"?: { readonly [x: string]: string } | null +} +export const McpTransportConfigParamHttp = Schema.Struct({ + "type": Schema.Literal("http").annotate({ "description": "The type of the object. Always `http`." }), + "server_url": Schema.String.annotate({ "description": "The URL of the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "authorization": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The authorization value sent to the MCP server, if any." }) ), "headers": Schema.optionalKey( Schema.Union([ - Schema.Struct({}).annotate({ - "description": "Optional HTTP headers to send to the MCP server. Use for authentication\nor other purposes.\n" - }), + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), Schema.Null - ]) + ]).annotate({ "description": "Additional HTTP headers sent to the MCP server." }) + ) +}).annotate({ "description": "Connects to an MCP server over HTTP.", "identifier": "McpTransportConfigParamHttp" }) +export type McpTransportConfigParamStdio = { + readonly "type": "stdio" + readonly "command": string + readonly "args"?: ReadonlyArray | null + readonly "cwd": string + readonly "env"?: { readonly [x: string]: string } | null + readonly "env_vars"?: ReadonlyArray | null +} +export const McpTransportConfigParamStdio = Schema.Struct({ + "type": Schema.Literal("stdio").annotate({ "description": "The type of the object. Always `stdio`." }), + "command": Schema.String.annotate({ "description": "The command used to start the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "args": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "Arguments passed to the MCP server command." }) ), - "allowed_tools": Schema.optionalKey( + "cwd": Schema.String.annotate({ "description": "The working directory used to start the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "env": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.Array(Schema.String).annotate({ - "title": "MCP allowed tools", - "description": "A string array of allowed tool names" - }), - MCPToolFilter - ], { mode: "oneOf" }).annotate({ "description": "List of allowed tool names or a filter object.\n" }), + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), Schema.Null - ]) + ]).annotate({ "description": "Environment variables set for the MCP server process." }) ), - "require_approval": Schema.optionalKey( + "env_vars": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.Struct({ "always": Schema.optionalKey(MCPToolFilter), "never": Schema.optionalKey(MCPToolFilter) }) - .annotate({ - "title": "MCP tool approval filter", - "description": - "Specify which of the MCP server's tools require approval. Can be\n`always`, `never`, or a filter object associated with tools\nthat require approval.\n" - }), - Schema.Literals(["always", "never"]).annotate({ - "title": "MCP tool approval setting", - "description": - "Specify a single approval policy for all tools. One of `always` or\n`never`. When set to `always`, all tools will require approval. When\nset to `never`, all tools will not require approval.\n" - }) - ], { mode: "oneOf" }).annotate({ "description": "Specify which of the MCP server's tools require approval." }), + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), Schema.Null - ]) + ]).annotate({ "description": "Environment variable names to inherit from the selected execution environment." }) + ) +}).annotate({ "description": "Starts an MCP server as a local process.", "identifier": "McpTransportConfigParamStdio" }) +export type AgentToolConfigParamComputerUse = { + readonly "type": "computer_use" + readonly "include_screenshots"?: boolean +} +export const AgentToolConfigParamComputerUse = Schema.Struct({ + "type": Schema.Literal("computer_use").annotate({ "description": "The type of the object. Always `computer_use`." }), + "include_screenshots": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether computer tool outputs include screenshots. Defaults to `false`." + }) + ) +}).annotate({ + "description": "Browser use in an OpenAI-hosted session.", + "identifier": "AgentToolConfigParamComputerUse" +}) +export type EnvironmentParamNone = { readonly "type": "none" } +export const EnvironmentParamNone = Schema.Struct({ + "type": Schema.Literal("none").annotate({ "description": "The type of the object. Always `none`." }) +}).annotate({ "description": "Runs the agent without an execution environment.", "identifier": "EnvironmentParamNone" }) +export type ContainerSizeParam = "small" | "medium" | "large" +export const ContainerSizeParam = Schema.Literals(["small", "medium", "large"]).annotate({ + "description": "The CPU and memory tier for a new OpenAI-hosted session environment.", + "identifier": "ContainerSizeParam" +}) +export type EnvironmentParamSelfHosted = { + readonly "type": "self_hosted" + readonly "capability_directories"?: ReadonlyArray | null + readonly "workspace_directory": string +} +export const EnvironmentParamSelfHosted = Schema.Struct({ + "type": Schema.Literal("self_hosted").annotate({ "description": "The type of the object. Always `self_hosted`." }), + "capability_directories": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ + "description": "Directories that contain capabilities exposed to the agent. Defaults to an empty list." + }) ), - "defer_loading": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether this MCP tool is deferred and discovered via tool search.\n" }) + "workspace_directory": Schema.String.annotate({ + "description": "Absolute project directory inside the self-hosted environment." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) ) }).annotate({ - "title": "MCP tool", - "description": - "Give the model access to additional tools via remote Model Context Protocol\n(MCP) servers. [Learn more about MCP](/docs/guides/tools-remote-mcp).\n" + "description": "An application-hosted environment configured inline.", + "identifier": "EnvironmentParamSelfHosted" }) -export type MessageContentTextObject = { - readonly "type": "text" - readonly "text": { - readonly "value": string - readonly "annotations": ReadonlyArray< - MessageContentTextAnnotationsFileCitationObject | MessageContentTextAnnotationsFilePathObject - > - } +export type InputContentParamInputText = { readonly "type": "input_text"; readonly "text": string } +export const InputContentParamInputText = Schema.Struct({ + "type": Schema.Literal("input_text").annotate({ "description": "The type of the object. Always `input_text`." }), + "text": Schema.String.annotate({ "description": "The text sent to the model." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) +}).annotate({ "description": "Text input to the model.", "identifier": "InputContentParamInputText" }) +export type InputContentParamInputImage = { readonly "type": "input_image"; readonly "image_url": string } +export const InputContentParamInputImage = Schema.Struct({ + "type": Schema.Literal("input_image").annotate({ "description": "The type of the object. Always `input_image`." }), + "image_url": Schema.String.annotate({ "description": "The URL of the image sent to the model." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) +}).annotate({ "description": "Image input to the model.", "identifier": "InputContentParamInputImage" }) +export type SessionErrorResource = { + readonly "type": string + readonly "code": string | null + readonly "message": string + readonly "param": string | null } -export const MessageContentTextObject = Schema.Struct({ - "type": Schema.Literal("text").annotate({ "description": "Always `text`." }), - "text": Schema.Struct({ - "value": Schema.String.annotate({ "description": "The data that makes up the text." }), - "annotations": Schema.Array( - Schema.Union([MessageContentTextAnnotationsFileCitationObject, MessageContentTextAnnotationsFilePathObject], { - mode: "oneOf" - }) - ) - }) -}).annotate({ "title": "Text", "description": "The text content that is part of a message." }) -export type MessageDeltaContentTextObject = { - readonly "index": number - readonly "type": "text" - readonly "text"?: { - readonly "value"?: string - readonly "annotations"?: ReadonlyArray< - MessageDeltaContentTextAnnotationsFileCitationObject | MessageDeltaContentTextAnnotationsFilePathObject - > - } +export const SessionErrorResource = Schema.Struct({ + "type": Schema.String.annotate({ "description": "The error type." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "code": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The machine-readable error code, if any." }), + "message": Schema.String.annotate({ "description": "A customer-safe explanation of the error." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "param": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The request parameter associated with the error, if any." }) +}).annotate({ + "description": "An error payload with the same public fields as Responses API streaming errors.", + "identifier": "SessionErrorResource" +}) +export type SessionEnvironmentStatusResource = + | "pending" + | "ready" + | "connected" + | "disconnected" + | "suspended" + | "expired" + | "failed" +export const SessionEnvironmentStatusResource = Schema.Literals([ + "pending", + "ready", + "connected", + "disconnected", + "suspended", + "expired", + "failed" +]).annotate({ + "description": "The connection status of a session environment.", + "identifier": "SessionEnvironmentStatusResource" +}) +export type SessionEnvironmentErrorResource = { + readonly "type": string + readonly "code": string + readonly "message": string } -export const MessageDeltaContentTextObject = Schema.Struct({ - "index": Schema.Number.annotate({ "description": "The index of the content part in the message." }).check( - Schema.isInt() +export const SessionEnvironmentErrorResource = Schema.Struct({ + "type": Schema.String.annotate({ "description": "The error type." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "type": Schema.Literal("text").annotate({ "description": "Always `text`." }), - "text": Schema.optionalKey(Schema.Struct({ - "value": Schema.optionalKey(Schema.String.annotate({ "description": "The data that makes up the text." })), - "annotations": Schema.optionalKey( - Schema.Array( - Schema.Union([ - MessageDeltaContentTextAnnotationsFileCitationObject, - MessageDeltaContentTextAnnotationsFilePathObject - ], { mode: "oneOf" }) - ) - ) - })) -}).annotate({ "title": "Text", "description": "The text content that is part of a message." }) -export type Batch = { - readonly "id": string - readonly "object": "batch" - readonly "endpoint": string - readonly "model"?: string - readonly "errors"?: { - readonly "object"?: string - readonly "data"?: ReadonlyArray< - { - readonly "code"?: string - readonly "message"?: string - readonly "param"?: string | null - readonly "line"?: number | null - } - > - } - readonly "input_file_id": string - readonly "completion_window": string - readonly "status": - | "validating" - | "failed" - | "in_progress" - | "finalizing" - | "completed" - | "expired" - | "cancelling" - | "cancelled" - readonly "output_file_id"?: string - readonly "error_file_id"?: string - readonly "created_at": number - readonly "in_progress_at"?: number - readonly "expires_at"?: number - readonly "finalizing_at"?: number - readonly "completed_at"?: number - readonly "failed_at"?: number - readonly "expired_at"?: number - readonly "cancelling_at"?: number - readonly "cancelled_at"?: number - readonly "request_counts"?: { readonly "total": number; readonly "completed": number; readonly "failed": number } - readonly "usage"?: { - readonly "input_tokens": number - readonly "input_tokens_details": { readonly "cached_tokens": number } - readonly "output_tokens": number - readonly "output_tokens_details": { readonly "reasoning_tokens": number } - readonly "total_tokens": number - } - readonly "metadata"?: Metadata + "code": Schema.String.annotate({ "description": "A machine-readable error code." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "message": Schema.String.annotate({ "description": "A human-readable error message." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "An error reported while preparing a session environment.", + "identifier": "SessionEnvironmentErrorResource" +}) +export type SessionEventAgentSessionEnvironmentReset = { + readonly "type": "agent.session.environment.reset" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "environment_id": string + readonly "reset_count": number } -export const Batch = Schema.Struct({ - "id": Schema.String, - "object": Schema.Literal("batch").annotate({ "description": "The object type, which is always `batch`." }), - "endpoint": Schema.String.annotate({ "description": "The OpenAI API endpoint used by the batch." }), - "model": Schema.optionalKey(Schema.String.annotate({ - "description": - "Model ID used to process the batch, like `gpt-5-2025-08-07`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model\nguide](/docs/models) to browse and compare available models.\n" - })), - "errors": Schema.optionalKey(Schema.Struct({ - "object": Schema.optionalKey(Schema.String.annotate({ "description": "The object type, which is always `list`." })), - "data": Schema.optionalKey(Schema.Array(Schema.Struct({ - "code": Schema.optionalKey( - Schema.String.annotate({ "description": "An error code identifying the error type." }) - ), - "message": Schema.optionalKey( - Schema.String.annotate({ "description": "A human-readable message providing more details about the error." }) - ), - "param": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The name of the parameter that caused the error, if applicable." }), - Schema.Null - ]) - ), - "line": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The line number of the input file where the error occurred, if applicable." - }).check(Schema.isInt()), - Schema.Null - ]) - ) - }))) - })), - "input_file_id": Schema.String.annotate({ "description": "The ID of the input file for the batch." }), - "completion_window": Schema.String.annotate({ - "description": "The time frame within which the batch should be processed." +export const SessionEventAgentSessionEnvironmentReset = Schema.Struct({ + "type": Schema.Literal("agent.session.environment.reset").annotate({ + "description": "The type of the object. Always `agent.session.environment.reset`." }), - "status": Schema.Literals([ - "validating", - "failed", - "in_progress", - "finalizing", - "completed", - "expired", - "cancelling", - "cancelled" - ]).annotate({ "description": "The current status of the batch." }), - "output_file_id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The ID of the file containing the outputs of successfully executed requests." - }) - ), - "error_file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the file containing the outputs of requests with errors." }) + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "in_progress_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch started processing.", - "format": "unixtime" - }).check(Schema.isInt()) + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "expires_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch will expire.", - "format": "unixtime" - }).check(Schema.isInt()) + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The associated turn, when applicable." }), + "environment_id": Schema.String.annotate({ + "description": "The stable environment ID, retained across sandbox replacements." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "reset_count": Schema.Number.annotate({ + "description": "Monotonically increasing reset number. Repeated notifications share this number.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ) +}).annotate({ + "description": + "Emitted after a hosted sandbox is replaced. Conversation history survives; changes to the previous sandbox's files and processes do not.", + "identifier": "SessionEventAgentSessionEnvironmentReset" +}) +export type SessionEventAgentOutputCommandExecutionOutputDelta = { + readonly "type": "agent.output.command_execution_output.delta" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "delta": string +} +export const SessionEventAgentOutputCommandExecutionOutputDelta = Schema.Struct({ + "type": Schema.Literal("agent.output.command_execution_output.delta").annotate({ + "description": "The type of the object. Always `agent.output.command_execution_output.delta`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "finalizing_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch started finalizing.", - "format": "unixtime" - }).check(Schema.isInt()) + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "completed_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch was completed.", - "format": "unixtime" - }).check(Schema.isInt()) + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the command execution item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "failed_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch failed.", - "format": "unixtime" - }).check(Schema.isInt()) + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "delta": Schema.String.annotate({ "description": "The output text that was appended." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "Emitted when command execution produces an output delta.", + "identifier": "SessionEventAgentOutputCommandExecutionOutputDelta" +}) +export type SessionEventAgentSessionTurnOutputTextDelta = { + readonly "type": "agent.session.turn.output_text.delta" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "delta": string +} +export const SessionEventAgentSessionTurnOutputTextDelta = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.output_text.delta").annotate({ + "description": "The type of the object. Always `agent.session.turn.output_text.delta`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "expired_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch expired.", - "format": "unixtime" - }).check(Schema.isInt()) + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "cancelling_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch started cancelling.", - "format": "unixtime" - }).check(Schema.isInt()) + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the message item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "cancelled_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the batch was cancelled.", - "format": "unixtime" - }).check(Schema.isInt()) + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part in the message.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "delta": Schema.String.annotate({ "description": "The text that was appended." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "Emitted when text is appended to an output text content part.", + "identifier": "SessionEventAgentSessionTurnOutputTextDelta" +}) +export type SessionEventAgentSessionTurnOutputTextDone = { + readonly "type": "agent.session.turn.output_text.done" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "text": string +} +export const SessionEventAgentSessionTurnOutputTextDone = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.output_text.done").annotate({ + "description": "The type of the object. Always `agent.session.turn.output_text.done`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "request_counts": Schema.optionalKey( - Schema.Struct({ - "total": Schema.Number.annotate({ "description": "Total number of requests in the batch." }).check( - Schema.isInt() - ), - "completed": Schema.Number.annotate({ - "description": "Number of requests that have been completed successfully." - }).check(Schema.isInt()), - "failed": Schema.Number.annotate({ "description": "Number of requests that have failed." }).check(Schema.isInt()) - }).annotate({ "description": "The request counts for different statuses within the batch." }) + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "usage": Schema.optionalKey( - Schema.Struct({ - "input_tokens": Schema.Number.annotate({ "description": "The number of input tokens." }).check(Schema.isInt()), - "input_tokens_details": Schema.Struct({ - "cached_tokens": Schema.Number.annotate({ - "description": - "The number of tokens that were retrieved from the cache. [More on\nprompt caching](/docs/guides/prompt-caching).\n" - }).check(Schema.isInt()) - }).annotate({ "description": "A detailed breakdown of the input tokens." }), - "output_tokens": Schema.Number.annotate({ "description": "The number of output tokens." }).check(Schema.isInt()), - "output_tokens_details": Schema.Struct({ - "reasoning_tokens": Schema.Number.annotate({ "description": "The number of reasoning tokens." }).check( - Schema.isInt() - ) - }).annotate({ "description": "A detailed breakdown of the output tokens." }), - "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check( - Schema.isInt() - ) - }).annotate({ - "description": - "Represents token usage details including input tokens, output tokens, a\nbreakdown of output tokens, and the total tokens used. Only populated on\nbatches created after September 7, 2025.\n" - }) + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the message item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "metadata": Schema.optionalKey(Metadata) + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part in the message.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "text": Schema.String.annotate({ "description": "The complete output text." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "Emitted when an output text content part is complete.", + "identifier": "SessionEventAgentSessionTurnOutputTextDone" }) -export type CreateMessageRequest = { - readonly "role": "user" | "assistant" - readonly "content": - | string - | ReadonlyArray - readonly "attachments"?: - | ReadonlyArray< - { - readonly "file_id"?: string - readonly "tools"?: ReadonlyArray - } - > - | null - readonly "metadata"?: Metadata +export type SessionEventAgentSessionTurnReasoningSummaryTextDelta = { + readonly "type": "agent.session.turn.reasoning_summary_text.delta" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "delta": string } -export const CreateMessageRequest = Schema.Struct({ - "role": Schema.Literals(["user", "assistant"]).annotate({ - "description": - "The role of the entity that is creating the message. Allowed values include:\n- `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages.\n- `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation.\n" +export const SessionEventAgentSessionTurnReasoningSummaryTextDelta = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.reasoning_summary_text.delta").annotate({ + "description": "The type of the object. Always `agent.session.turn.reasoning_summary_text.delta`." }), - "content": Schema.Union([ - Schema.String.annotate({ "title": "Text content", "description": "The text contents of the message." }), - Schema.Array( - Schema.Union([MessageContentImageFileObject, MessageContentImageUrlObject, MessageRequestContentTextObject], { - mode: "oneOf" - }) - ).annotate({ - "title": "Array of content parts", - "description": - "An array of content parts with a defined type, each can be of type `text` or images can be passed with `image_url` or `image_file`. Image types are only supported on [Vision-compatible models](/docs/models)." - }).check(Schema.isMinLength(1)) - ], { mode: "oneOf" }), - "attachments": Schema.optionalKey(Schema.Union([ - Schema.Array(Schema.Struct({ - "file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the file to attach to the message." }) - ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([AssistantToolsCode, AssistantToolsFileSearchTypeOnly], { mode: "oneOf" })).annotate({ - "description": "The tools to add this file to." - }) - ) - })).annotate({ "description": "A list of files attached to the message, and the tools they should be added to." }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), Schema.Null - ])), - "metadata": Schema.optionalKey(Metadata) + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the reasoning item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary content part.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "delta": Schema.String.annotate({ "description": "The summary text that was appended." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "Emitted when text is appended to a reasoning summary.", + "identifier": "SessionEventAgentSessionTurnReasoningSummaryTextDelta" }) -export type EvalStoredCompletionsSource = { - readonly "type": "stored_completions" - readonly "metadata"?: Metadata - readonly "model"?: string | null - readonly "created_after"?: number | null - readonly "created_before"?: number | null - readonly "limit"?: number | null +export type SessionEventAgentSessionTurnReasoningSummaryTextDone = { + readonly "type": "agent.session.turn.reasoning_summary_text.done" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "text": string } -export const EvalStoredCompletionsSource = Schema.Struct({ - "type": Schema.Literal("stored_completions").annotate({ - "description": "The type of source. Always `stored_completions`." +export const SessionEventAgentSessionTurnReasoningSummaryTextDone = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.reasoning_summary_text.done").annotate({ + "description": "The type of the object. Always `agent.session.turn.reasoning_summary_text.done`." }), - "metadata": Schema.optionalKey(Metadata), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "An optional model to filter by (e.g., 'gpt-4o')." }), - Schema.Null - ]) + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "created_after": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "An optional Unix timestamp to filter items created after this time." }) - .check(Schema.isInt()), - Schema.Null - ]) + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "created_before": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "An optional Unix timestamp to filter items created before this time." }) - .check(Schema.isInt()), - Schema.Null - ]) + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the reasoning item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "limit": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "An optional maximum number of items to return." }).check(Schema.isInt()), - Schema.Null - ]) + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary content part.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "text": Schema.String.annotate({ "description": "The complete reasoning summary text." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ) }).annotate({ - "title": "StoredCompletionsRunDataSource", - "description": "A StoredCompletionsRunDataSource configuration describing a set of filters\n" + "description": "Emitted when a reasoning summary content part is complete.", + "identifier": "SessionEventAgentSessionTurnReasoningSummaryTextDone" }) -export type ModifyMessageRequest = { readonly "metadata"?: Metadata } -export const ModifyMessageRequest = Schema.Struct({ "metadata": Schema.optionalKey(Metadata) }) -export type ModifyRunRequest = { readonly "metadata"?: Metadata } -export const ModifyRunRequest = Schema.Struct({ "metadata": Schema.optionalKey(Metadata) }) -export type ModifyThreadRequest = { - readonly "tool_resources"?: { - readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } - readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } - } | null - readonly "metadata"?: Metadata +export type DeletedSessionResource = { + readonly "id": string + readonly "object": "agent.session.deleted" + readonly "deleted": boolean } -export const ModifyThreadRequest = Schema.Struct({ - "tool_resources": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "code_interpreter": Schema.optionalKey(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" - }).check(Schema.isMaxLength(20)) - ) - })), - "file_search": Schema.optionalKey(Schema.Struct({ - "vector_store_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "The [vector store](/docs/api-reference/vector-stores/object) attached to this thread. There can be a maximum of 1 vector store attached to the thread.\n" - }).check(Schema.isMaxLength(1)) - ) - })) - }).annotate({ - "description": - "A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" - }), - Schema.Null - ])), - "metadata": Schema.optionalKey(Metadata) +export const DeletedSessionResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the deleted session." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("agent.session.deleted").annotate({ + "description": "The object type. Always `agent.session.deleted`." + }), + "deleted": Schema.Boolean.annotate({ + "description": + "Whether the session has been removed from the public API. Always `true`. Physical cleanup may still be in progress." + }) +}).annotate({ + "description": "A Managed Agents session removed from the public API. Physical cleanup may continue asynchronously.", + "identifier": "DeletedSessionResource" }) -export type ThreadObject = { +export type SessionArtifactResource = { readonly "id": string - readonly "object": "thread" + readonly "object": "agent.session.artifact" + readonly "session_id": string + readonly "environment_id": string + readonly "turn_id": string + readonly "path": string + readonly "size_bytes": number readonly "created_at": number - readonly "tool_resources": { - readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } - readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } - } | null - readonly "metadata": Metadata } -export const ThreadObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), - "object": Schema.Literal("thread").annotate({ "description": "The object type, which is always `thread`." }), +export const SessionArtifactResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The immutable artifact ID." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("agent.session.artifact").annotate({ + "description": "The object type. Always `agent.session.artifact`." + }), + "session_id": Schema.String.annotate({ "description": "The ID of the session that owns the artifact." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "environment_id": Schema.String.annotate({ "description": "The ID of the environment that produced the artifact." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "turn_id": Schema.String.annotate({ "description": "The ID of the completed turn that published the artifact." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "path": Schema.String.annotate({ "description": "The original absolute file path in the execution environment." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "size_bytes": Schema.Number.annotate({ "description": "The immutable artifact size in bytes.", "format": "int64" }) + .check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ), "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the thread was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "tool_resources": Schema.Union([ - Schema.Struct({ - "code_interpreter": Schema.optionalKey(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" - }).check(Schema.isMaxLength(20)) - ) - })), - "file_search": Schema.optionalKey(Schema.Struct({ - "vector_store_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "The [vector store](/docs/api-reference/vector-stores/object) attached to this thread. There can be a maximum of 1 vector store attached to the thread.\n" - }).check(Schema.isMaxLength(1)) - ) - })) - }).annotate({ - "description": - "A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" - }), - Schema.Null - ]), - "metadata": Metadata + "description": "The Unix timestamp, in seconds, when the artifact was published.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) }).annotate({ - "title": "Thread", - "description": "Represents a thread that contains [messages](/docs/api-reference/messages)." + "description": "An immutable file published by a completed hosted session turn.", + "identifier": "SessionArtifactResource" }) -export type UpdateVectorStoreRequest = { - readonly "name"?: string | null - readonly "expires_after"?: { readonly "anchor": "last_active_at"; readonly "days": number } - readonly "metadata"?: Metadata +export type DeletedSessionArtifactResource = { + readonly "id": string + readonly "object": "agent.session.artifact.deleted" + readonly "deleted": boolean } -export const UpdateVectorStoreRequest = Schema.Struct({ - "name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the vector store." }) +export const DeletedSessionArtifactResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the deleted session artifact." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "expires_after": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "anchor": Schema.Literal("last_active_at").annotate({ - "description": - "Anchor timestamp after which the expiration policy applies. Supported anchors: `last_active_at`." - }), - "days": Schema.Number.annotate({ - "description": "The number of days after the anchor time that the vector store will expire." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(365)) - }).annotate({ - "title": "Vector store expiration policy", - "description": "The expiration policy for a vector store." - }) - ])), - "metadata": Schema.optionalKey(Metadata) + "object": Schema.Literal("agent.session.artifact.deleted").annotate({ + "description": "The object type. Always `agent.session.artifact.deleted`." + }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the session artifact was deleted. Always `true`." }) +}).annotate({ + "description": "Confirmation that an immutable session artifact was deleted.", + "identifier": "DeletedSessionArtifactResource" }) -export type ListModelsResponse = { readonly "object": "list"; readonly "data": ReadonlyArray } -export const ListModelsResponse = Schema.Struct({ "object": Schema.Literal("list"), "data": Schema.Array(Model) }) -export type ModelIdsResponses = - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" -export const ModelIdsResponses = Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) -]) -export type RealtimeTranscriptionSessionCreateRequest = { - readonly "turn_detection"?: { - readonly "type"?: "server_vad" - readonly "threshold"?: number - readonly "prefix_padding_ms"?: number - readonly "silence_duration_ms"?: number - } - readonly "input_audio_noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "input_audio_format"?: "pcm16" | "g711_ulaw" | "g711_alaw" - readonly "input_audio_transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - readonly "delay"?: "minimal" | "low" | "medium" | "high" | "xhigh" - } - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> +export type BrowserAuthenticationFieldValueParam = { readonly "field_id": string; readonly "value": string } +export const BrowserAuthenticationFieldValueParam = Schema.Struct({ + "field_id": Schema.String.annotate({ "description": "The field ID from the required action." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "value": Schema.String.annotate({ "description": "The value to enter into the registered control." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(16384).annotate({ "expected": "a string with at most 16384 code points" })) +}).annotate({ + "description": "One user-entered value, including non-password fields such as an email address.", + "identifier": "BrowserAuthenticationFieldValueParam" +}) +export type BrowserOriginAccessDecisionParam = "approve" | "deny" | "cancel" +export const BrowserOriginAccessDecisionParam = Schema.Literals(["approve", "deny", "cancel"]).annotate({ + "description": "The user's decision for a browser origin access request.", + "identifier": "BrowserOriginAccessDecisionParam" +}) +export type SessionInputParamAgentSessionInputCancel = { readonly "type": "agent.session.input.cancel" } +export const SessionInputParamAgentSessionInputCancel = Schema.Struct({ + "type": Schema.Literal("agent.session.input.cancel").annotate({ + "description": "The type of the object. Always `agent.session.input.cancel`." + }) +}).annotate({ + "description": "Cancels the session's active turn.", + "identifier": "SessionInputParamAgentSessionInputCancel" +}) +export type SessionTurnTraceResource = { + readonly "id": string + readonly "object": "agent.session.trace" + readonly "session_id": string + readonly "created_at": number + readonly "otlp": { readonly [x: string]: Schema.Json } } -export const RealtimeTranscriptionSessionCreateRequest = Schema.Struct({ - "turn_detection": Schema.optionalKey( - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("server_vad").annotate({ - "description": - "Type of turn detection. Only `server_vad` is currently supported for transcription sessions.\n" - }) - ), - "threshold": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" - }).check(Schema.isFinite()) - ), - "prefix_padding_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" - }).check(Schema.isInt()) - ), - "silence_duration_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" - }).check(Schema.isInt()) - ) - }).annotate({ - "description": - "Configuration for turn detection. Can be set to `null` to turn off. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech.\n" - }) +export const SessionTurnTraceResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The root turn ID. Use this ID as the pagination anchor." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "input_audio_noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": - "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" - }) + "object": Schema.Literal("agent.session.trace").annotate({ + "description": "The object type, which is always `agent.session.trace`." + }), + "session_id": Schema.String.annotate({ "description": "The session that owns this trace." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "input_audio_format": Schema.optionalKey( - Schema.Literals(["pcm16", "g711_ulaw", "g711_alaw"]).annotate({ - "description": - "The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\nFor `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate,\nsingle channel (mono), and little-endian byte order.\n" - }) + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp in seconds when the root turn was created.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "otlp": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "An OTLP JSON ExportTraceServiceRequest containing resourceSpans. Only currently published data is returned; later trace updates are not awaited." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) +}).annotate({ "identifier": "SessionTurnTraceResource" }) +export type VaultStatusParam = "active" | "archived" +export const VaultStatusParam = Schema.Literals(["active", "archived"]).annotate({ + "description": "Whether a vault or credential is active or archived.", + "identifier": "VaultStatusParam" +}) +export type VaultResource = { + readonly "id": string + readonly "object": "vault" + readonly "name": string | null + readonly "metadata": { readonly [x: string]: string } + readonly "created_at": number +} +export const VaultResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the vault." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "input_audio_transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model to use for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The language of the input audio. Supplying the input language in\n[ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format\nwill improve accuracy and latency.\n" - }) + "object": Schema.Literal("vault").annotate({ "description": "The object type. Always `vault`." }), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The human-readable name of the vault, if set." }), + "metadata": Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Key-value pairs associated with the vault, such as an application or team identifier." }) + .check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the vault was created.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "A collection of credentials for MCP servers and OpenAI-hosted environments.", + "identifier": "VaultResource" +}) +export type CreateVaultParams = { + readonly "name"?: string + readonly "metadata"?: { readonly [x: string]: string } | null +} +export const CreateVaultParams = Schema.Struct({ + "name": Schema.optionalKey( + Schema.String.annotate({ + "description": "The name is trimmed before storage. It must contain 1 to 256 UTF-8 bytes after trimming." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ) + ), + "metadata": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) ), - "prompt": Schema.optionalKey(Schema.String.annotate({ - "description": - "An optional text to guide the model's style or continue a previous audio\nsegment.\nFor `whisper-1`, the [prompt is a list of keywords](/docs/guides/speech-to-text#prompting).\nFor `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example \"expect words related to technology\".\nPrompt is not supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - })), - "delay": Schema.optionalKey( - Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": - "Controls how long the model waits before emitting transcription text.\nHigher values can improve transcription accuracy at the cost of latency.\nOnly supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - }) - ) - }).annotate({ - "description": - "Configuration for input audio transcription. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" + Schema.Null + ]).annotate({ + "description": "Key-value pairs to associate with the vault, such as an application or team identifier." }) + ) +}).annotate({ + "description": "Parameters for creating a vault to store credentials used by agent tools.", + "identifier": "CreateVaultParams" +}) +export type UpdateVaultParams = { + readonly "metadata"?: { readonly [x: string]: string } + readonly "name"?: string | null +} +export const UpdateVaultParams = Schema.Struct({ + "metadata": Schema.optionalKey( + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).annotate({ + "description": + "Replaces all metadata. Omit to leave unchanged, or pass {} to clear it. Up to 16 string key-value pairs, with keys up to 64 and values up to 512 characters." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + Schema.Null + ]).annotate({ "description": - "The set of items to include in the transcription. Current available items are:\n`item.input_audio_transcription.logprobs`\n" + "A replacement name. Omit to leave unchanged, or pass null to clear it. The name is trimmed before storage. It must contain 1 to 256 UTF-8 bytes after trimming." }) ) -}).annotate({ - "title": "Realtime transcription session configuration", - "description": "Realtime transcription session object configuration." -}) -export type RealtimeTranslationClientEventSessionUpdate = { - readonly "event_id"?: string - readonly "type": "session.update" - readonly "session": { - readonly "audio"?: { - readonly "input"?: { - readonly "transcription"?: { readonly "model": string } | null - readonly "noise_reduction"?: { readonly "type": NoiseReductionType } | null - } - readonly "output"?: { readonly "language"?: string } - } - } +}).annotate({ "description": "Fields to replace on an active vault.", "identifier": "UpdateVaultParams" }) +export type DeletedVaultResource = { + readonly "id": string + readonly "object": "vault.deleted" + readonly "deleted": boolean } -export const RealtimeTranslationClientEventSessionUpdate = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) +export const DeletedVaultResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the deleted vault." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "type": Schema.Literal("session.update").annotate({ "description": "The event type, must be `session.update`." }), - "session": Schema.Struct({ - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "transcription": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "model": Schema.String.annotate({ - "description": "The transcription model to use for source transcript deltas." - }) - }).annotate({ - "description": - "Optional source-language transcription. When configured, the server emits\n`session.input_transcript.delta` events. Translation itself still runs from\nthe input audio stream.\n" - }), - Schema.Null - ]) - ), - "noise_reduction": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": NoiseReductionType }).annotate({ - "description": "Optional input noise reduction. Set to `null` to disable it.\n" - }), - Schema.Null - ]) - ) - })), - "output": Schema.optionalKey( - Schema.Struct({ - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": "Target language for translated output audio and transcript deltas.\n" - }) - ) - }) - ) - }).annotate({ "description": "Configuration for translation input and output audio.\n" }) - ) - }).annotate({ - "title": "Realtime translation session update", - "description": - "Translation session fields to update. The session `type` and `model` are set\nat creation and cannot be changed with `session.update`.\n" + "object": Schema.Literal("vault.deleted").annotate({ "description": "The object type. Always `vault.deleted`." }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the resource was deleted. Always `true`." }) +}).annotate({ "description": "Confirmation that a vault was deleted.", "identifier": "DeletedVaultResource" }) +export type McpOauthTokenEndpointAuthResourceNone = { readonly "type": "none" } +export const McpOauthTokenEndpointAuthResourceNone = Schema.Struct({ + "type": Schema.Literal("none").annotate({ "description": "The type of the object. Always `none`." }) +}).annotate({ + "description": "Sends the client ID without a client secret.", + "identifier": "McpOauthTokenEndpointAuthResourceNone" +}) +export type McpOauthTokenEndpointAuthResourceClientSecretBasic = { readonly "type": "client_secret_basic" } +export const McpOauthTokenEndpointAuthResourceClientSecretBasic = Schema.Struct({ + "type": Schema.Literal("client_secret_basic").annotate({ + "description": "The type of the object. Always `client_secret_basic`." }) }).annotate({ - "description": - "Send this event to update the translation session configuration. Translation\nsessions support updates to `audio.output.language`, `audio.input.transcription`,\nand `audio.input.noise_reduction`.\n" + "description": "Sends the client ID and secret using HTTP Basic authentication.", + "identifier": "McpOauthTokenEndpointAuthResourceClientSecretBasic" }) -export type RealtimeTranslationServerEventSessionCreated = { - readonly "event_id": string - readonly "type": "session.created" - readonly "session": { - readonly "id": string - readonly "type": "translation" - readonly "expires_at": number - readonly "model": string - readonly "audio": { - readonly "input"?: { - readonly "transcription"?: { readonly "model": string } | null - readonly "noise_reduction"?: { readonly "type": NoiseReductionType } | null - } - readonly "output"?: { readonly "language"?: string } - } - } +export type McpOauthTokenEndpointAuthResourceClientSecretPost = { readonly "type": "client_secret_post" } +export const McpOauthTokenEndpointAuthResourceClientSecretPost = Schema.Struct({ + "type": Schema.Literal("client_secret_post").annotate({ + "description": "The type of the object. Always `client_secret_post`." + }) +}).annotate({ + "description": "Sends the client ID and secret in the token request body.", + "identifier": "McpOauthTokenEndpointAuthResourceClientSecretPost" +}) +export type VaultCredentialAuthResourceStaticBearer = { + readonly "type": "static_bearer" + readonly "mcp_server_url": string } -export const RealtimeTranslationServerEventSessionCreated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("session.created").annotate({ "description": "The event type, must be `session.created`." }), - "session": Schema.Struct({ - "id": Schema.String.annotate({ - "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" - }), - "type": Schema.Literal("translation").annotate({ - "description": "The session type. Always `translation` for Realtime translation sessions.\n" - }), - "expires_at": Schema.Number.annotate({ - "description": "Expiration timestamp for the session, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()), - "model": Schema.String.annotate({ - "description": - "The Realtime translation model used for this session. This field is set at\nsession creation and cannot be changed with `session.update`.\n" - }), - "audio": Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "transcription": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "model": Schema.String.annotate({ - "description": "The transcription model used for source transcript deltas." - }) - }).annotate({ - "description": - "Optional source-language transcription. When configured, the server emits\n`session.input_transcript.delta` events. Translation itself still runs from\nthe input audio stream.\n" - }), - Schema.Null - ]) - ), - "noise_reduction": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": NoiseReductionType }).annotate({ - "description": "Optional input noise reduction.\n" - }), - Schema.Null - ]) - ) - })), - "output": Schema.optionalKey( - Schema.Struct({ - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": "Target language for translated output audio and transcript deltas.\n" - }) - ) - }) - ) - }).annotate({ "description": "Configuration for translation input and output audio.\n" }) - }).annotate({ "title": "Realtime translation session", "description": "The translation session configuration." }) +export const VaultCredentialAuthResourceStaticBearer = Schema.Struct({ + "type": Schema.Literal("static_bearer").annotate({ + "description": "The type of the object. Always `static_bearer`." + }), + "mcp_server_url": Schema.String.annotate({ "description": "The HTTPS MCP server URL authorized by this credential." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) +}).annotate({ + "description": "Metadata for a bearer-token credential, without automatic OAuth refresh.", + "identifier": "VaultCredentialAuthResourceStaticBearer" +}) +export type VaultCredentialNetworkingResourceUnrestricted = { readonly "type": "unrestricted" } +export const VaultCredentialNetworkingResourceUnrestricted = Schema.Struct({ + "type": Schema.Literal("unrestricted").annotate({ "description": "The type of the object. Always `unrestricted`." }) }).annotate({ "description": - "Returned when a translation session is created. Emitted automatically when a\nnew connection is established as the first server event. This event contains\nthe default translation session configuration.\n" + "Allows substitution for destinations permitted by the environment network policy. Requires `environment.network.access` to be `restricted`, with explicit `allowed_domains`.", + "identifier": "VaultCredentialNetworkingResourceUnrestricted" }) -export type RealtimeTranslationServerEventSessionUpdated = { - readonly "event_id": string - readonly "type": "session.updated" - readonly "session": { - readonly "id": string - readonly "type": "translation" - readonly "expires_at": number - readonly "model": string - readonly "audio": { - readonly "input"?: { - readonly "transcription"?: { readonly "model": string } | null - readonly "noise_reduction"?: { readonly "type": NoiseReductionType } | null - } - readonly "output"?: { readonly "language"?: string } - } - } -} -export const RealtimeTranslationServerEventSessionUpdated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("session.updated").annotate({ "description": "The event type, must be `session.updated`." }), - "session": Schema.Struct({ - "id": Schema.String.annotate({ - "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" - }), - "type": Schema.Literal("translation").annotate({ - "description": "The session type. Always `translation` for Realtime translation sessions.\n" - }), - "expires_at": Schema.Number.annotate({ - "description": "Expiration timestamp for the session, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()), - "model": Schema.String.annotate({ - "description": - "The Realtime translation model used for this session. This field is set at\nsession creation and cannot be changed with `session.update`.\n" - }), - "audio": Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "transcription": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "model": Schema.String.annotate({ - "description": "The transcription model used for source transcript deltas." - }) - }).annotate({ - "description": - "Optional source-language transcription. When configured, the server emits\n`session.input_transcript.delta` events. Translation itself still runs from\nthe input audio stream.\n" - }), - Schema.Null - ]) - ), - "noise_reduction": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": NoiseReductionType }).annotate({ - "description": "Optional input noise reduction.\n" - }), - Schema.Null - ]) - ) - })), - "output": Schema.optionalKey( - Schema.Struct({ - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": "Target language for translated output audio and transcript deltas.\n" - }) - ) - }) - ) - }).annotate({ "description": "Configuration for translation input and output audio.\n" }) - }).annotate({ "title": "Realtime translation session", "description": "The translation session configuration." }) +export type VaultCredentialNetworkingResourceLimited = { + readonly "type": "limited" + readonly "allowed_hosts": ReadonlyArray +} +export const VaultCredentialNetworkingResourceLimited = Schema.Struct({ + "type": Schema.Literal("limited").annotate({ "description": "The type of the object. Always `limited`." }), + "allowed_hosts": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ + "description": + "The 1 to 16 distinct allowed hostnames or IPv4 addresses, normalized to lowercase. Entries contain no scheme, path, port, or wildcard. IPv6 addresses are not supported." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(16).annotate({ "expected": "a value with a length of at most 16" }) + ) }).annotate({ "description": - "Returned when a translation session is updated with a `session.update` event,\nunless there is an error.\n" + "Allows substitution only for the listed hosts. The environment network policy must also allow these hosts.", + "identifier": "VaultCredentialNetworkingResourceLimited" }) -export type RealtimeTranslationSession = { - readonly "id": string - readonly "type": "translation" - readonly "expires_at": number - readonly "model": string - readonly "audio": { - readonly "input"?: { - readonly "transcription"?: { readonly "model": string } | null - readonly "noise_reduction"?: { readonly "type": NoiseReductionType } | null - } - readonly "output"?: { readonly "language"?: string } - } +export type CreateMcpOauthTokenEndpointAuthParamNone = { readonly "type": "none" } +export const CreateMcpOauthTokenEndpointAuthParamNone = Schema.Struct({ + "type": Schema.Literal("none").annotate({ "description": "The type of the object. Always `none`." }) +}).annotate({ + "description": "Sends the client ID without a client secret.", + "identifier": "CreateMcpOauthTokenEndpointAuthParamNone" +}) +export type CreateMcpOauthTokenEndpointAuthParamClientSecretBasic = { + readonly "type": "client_secret_basic" + readonly "client_secret": string } -export const RealtimeTranslationSession = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" - }), - "type": Schema.Literal("translation").annotate({ - "description": "The session type. Always `translation` for Realtime translation sessions.\n" +export const CreateMcpOauthTokenEndpointAuthParamClientSecretBasic = Schema.Struct({ + "type": Schema.Literal("client_secret_basic").annotate({ + "description": "The type of the object. Always `client_secret_basic`." }), - "expires_at": Schema.Number.annotate({ - "description": "Expiration timestamp for the session, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()), - "model": Schema.String.annotate({ - "description": - "The Realtime translation model used for this session. This field is set at\nsession creation and cannot be changed with `session.update`.\n" + "client_secret": Schema.String.annotate({ + "description": "The OAuth client secret to store. Never returned in credential resources." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ) +}).annotate({ + "description": "Sends the client ID and secret using HTTP Basic authentication.", + "identifier": "CreateMcpOauthTokenEndpointAuthParamClientSecretBasic" +}) +export type CreateMcpOauthTokenEndpointAuthParamClientSecretPost = { + readonly "type": "client_secret_post" + readonly "client_secret": string +} +export const CreateMcpOauthTokenEndpointAuthParamClientSecretPost = Schema.Struct({ + "type": Schema.Literal("client_secret_post").annotate({ + "description": "The type of the object. Always `client_secret_post`." }), - "audio": Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "transcription": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "model": Schema.String.annotate({ - "description": "The transcription model used for source transcript deltas." - }) - }).annotate({ - "description": - "Optional source-language transcription. When configured, the server emits\n`session.input_transcript.delta` events. Translation itself still runs from\nthe input audio stream.\n" - }), - Schema.Null - ]) - ), - "noise_reduction": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": NoiseReductionType }).annotate({ - "description": "Optional input noise reduction.\n" - }), - Schema.Null - ]) - ) - })), - "output": Schema.optionalKey( - Schema.Struct({ - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": "Target language for translated output audio and transcript deltas.\n" - }) - ) - }) - ) - }).annotate({ "description": "Configuration for translation input and output audio.\n" }) + "client_secret": Schema.String.annotate({ + "description": "The OAuth client secret to store. Never returned in credential resources." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ) }).annotate({ - "title": "Realtime translation session", - "description": - "A Realtime translation session. Translation sessions continuously translate input\naudio into the configured output language.\n" + "description": "Sends the client ID and secret in the token request body.", + "identifier": "CreateMcpOauthTokenEndpointAuthParamClientSecretPost" }) -export type RealtimeTranslationSessionCreateRequest = { - readonly "model": string - readonly "audio"?: { - readonly "input"?: { - readonly "transcription"?: { readonly "model": string } | null - readonly "noise_reduction"?: { readonly "type": NoiseReductionType } | null - } - readonly "output"?: { readonly "language"?: string } - } +export type CreateVaultCredentialAuthParamStaticBearer = { + readonly "type": "static_bearer" + readonly "mcp_server_url": string + readonly "token": string } -export const RealtimeTranslationSessionCreateRequest = Schema.Struct({ - "model": Schema.String.annotate({ "description": "The Realtime translation model used for this session.\n" }), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "transcription": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "model": Schema.String.annotate({ - "description": "The transcription model to use for source transcript deltas." - }) - }).annotate({ - "description": - "Optional source-language transcription. When configured, the server emits\n`session.input_transcript.delta` events. Translation itself still runs from\nthe input audio stream.\n" - }), - Schema.Null - ]) - ), - "noise_reduction": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": NoiseReductionType }).annotate({ - "description": "Optional input noise reduction. Set to `null` to disable it.\n" - }), - Schema.Null - ]) - ) - })), - "output": Schema.optionalKey( - Schema.Struct({ - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": "Target language for translated output audio and transcript deltas.\n" - }) - ) - }) - ) - }).annotate({ "description": "Configuration for translation input and output audio.\n" }) +export const CreateVaultCredentialAuthParamStaticBearer = Schema.Struct({ + "type": Schema.Literal("static_bearer").annotate({ + "description": "The type of the object. Always `static_bearer`." + }), + "mcp_server_url": Schema.String.annotate({ "description": "The HTTPS MCP server URL authorized by this credential." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "token": Schema.String.annotate({ + "description": "The bearer token to store. This secret is never returned in credential resources." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) ) }).annotate({ - "title": "Realtime translation session configuration", + "description": "A bearer token for an MCP server, without automatic OAuth refresh.", + "identifier": "CreateVaultCredentialAuthParamStaticBearer" +}) +export type VaultCredentialNetworkingParamUnrestricted = { readonly "type": "unrestricted" } +export const VaultCredentialNetworkingParamUnrestricted = Schema.Struct({ + "type": Schema.Literal("unrestricted").annotate({ "description": "The type of the object. Always `unrestricted`." }) +}).annotate({ "description": - "Realtime translation session configuration. Translation sessions stream source\naudio in and translated audio plus transcript deltas out continuously.\n" + "Allows substitution for destinations permitted by the environment network policy. Requires `environment.network.access` to be `restricted`, with explicit `allowed_domains`.", + "identifier": "VaultCredentialNetworkingParamUnrestricted" }) -export type ListFilesResponse = { - readonly "object": string - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean -} -export const ListFilesResponse = Schema.Struct({ - "object": Schema.String, - "data": Schema.Array(OpenAIFile), - "first_id": Schema.String, - "last_id": Schema.String, - "has_more": Schema.Boolean -}) -export type ListCertificatesResponse = { - readonly "data": ReadonlyArray - readonly "first_id": string | null - readonly "last_id": string | null - readonly "has_more": boolean - readonly "object": "list" -} -export const ListCertificatesResponse = Schema.Struct({ - "data": Schema.Array(OrganizationCertificate), - "first_id": Schema.Union([Schema.String, Schema.Null]), - "last_id": Schema.Union([Schema.String, Schema.Null]), - "has_more": Schema.Boolean, - "object": Schema.Literal("list") +export type VaultCredentialNetworkingParamLimited = { + readonly "type": "limited" + readonly "allowed_hosts": ReadonlyArray +} +export const VaultCredentialNetworkingParamLimited = Schema.Struct({ + "type": Schema.Literal("limited").annotate({ "description": "The type of the object. Always `limited`." }), + "allowed_hosts": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).annotate({ + "description": + "The 1 to 16 distinct allowed hostnames or IPv4 addresses, normalized to lowercase. Entries contain no scheme, path, port, or wildcard. IPv6 addresses are not supported." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(16).annotate({ "expected": "a value with a length of at most 16" }) + ) +}).annotate({ + "description": + "Allows substitution only for the listed hosts. The environment network policy must also allow these hosts.", + "identifier": "VaultCredentialNetworkingParamLimited" }) -export type OrganizationCertificateActivationResponse = { - readonly "object": "organization.certificate.activation" - readonly "data": ReadonlyArray +export type RotateMcpOauthTokenEndpointAuthParamClientSecretBasic = { + readonly "type": "client_secret_basic" + readonly "client_secret"?: string | null } -export const OrganizationCertificateActivationResponse = Schema.Struct({ - "object": Schema.Literal("organization.certificate.activation").annotate({ - "description": "The organization certificate activation result type." +export const RotateMcpOauthTokenEndpointAuthParamClientSecretBasic = Schema.Struct({ + "type": Schema.Literal("client_secret_basic").annotate({ + "description": "The type of the object. Always `client_secret_basic`." }), - "data": Schema.Array(OrganizationCertificate) + "client_secret": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "The replacement OAuth client secret. Omit or pass `null` to keep the stored secret. This secret is never returned in resources." + }) + ) +}).annotate({ + "description": "Updates credentials sent using HTTP Basic authentication.", + "identifier": "RotateMcpOauthTokenEndpointAuthParamClientSecretBasic" }) -export type OrganizationCertificateDeactivationResponse = { - readonly "object": "organization.certificate.deactivation" - readonly "data": ReadonlyArray +export type RotateMcpOauthTokenEndpointAuthParamClientSecretPost = { + readonly "type": "client_secret_post" + readonly "client_secret"?: string | null } -export const OrganizationCertificateDeactivationResponse = Schema.Struct({ - "object": Schema.Literal("organization.certificate.deactivation").annotate({ - "description": "The organization certificate deactivation result type." +export const RotateMcpOauthTokenEndpointAuthParamClientSecretPost = Schema.Struct({ + "type": Schema.Literal("client_secret_post").annotate({ + "description": "The type of the object. Always `client_secret_post`." }), - "data": Schema.Array(OrganizationCertificate) + "client_secret": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "The replacement OAuth client secret. Omit or pass `null` to keep the stored secret. This secret is never returned in resources." + }) + ) +}).annotate({ + "description": "Updates credentials sent in the token request body.", + "identifier": "RotateMcpOauthTokenEndpointAuthParamClientSecretPost" }) -export type ListProjectCertificatesResponse = { - readonly "data": ReadonlyArray - readonly "first_id": string | null - readonly "last_id": string | null - readonly "has_more": boolean - readonly "object": "list" -} -export const ListProjectCertificatesResponse = Schema.Struct({ - "data": Schema.Array(OrganizationProjectCertificate), - "first_id": Schema.Union([Schema.String, Schema.Null]), - "last_id": Schema.Union([Schema.String, Schema.Null]), - "has_more": Schema.Boolean, - "object": Schema.Literal("list") +export type RotateVaultCredentialAuthParamStaticBearer = { readonly "type": "static_bearer"; readonly "token": string } +export const RotateVaultCredentialAuthParamStaticBearer = Schema.Struct({ + "type": Schema.Literal("static_bearer").annotate({ + "description": "The type of the object. Always `static_bearer`." + }), + "token": Schema.String.annotate({ + "description": "The replacement bearer token. This secret is never returned in credential resources." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ) +}).annotate({ + "description": "Replace the bearer token for the credential's MCP server.", + "identifier": "RotateVaultCredentialAuthParamStaticBearer" }) -export type OrganizationProjectCertificateActivationResponse = { - readonly "object": "organization.project.certificate.activation" - readonly "data": ReadonlyArray +export type RotateVaultCredentialAuthParamEnvironmentVariable = { + readonly "type": "environment_variable" + readonly "secret_value": string } -export const OrganizationProjectCertificateActivationResponse = Schema.Struct({ - "object": Schema.Literal("organization.project.certificate.activation").annotate({ - "description": "The project certificate activation result type." +export const RotateVaultCredentialAuthParamEnvironmentVariable = Schema.Struct({ + "type": Schema.Literal("environment_variable").annotate({ + "description": "The type of the object. Always `environment_variable`." }), - "data": Schema.Array(OrganizationProjectCertificate) + "secret_value": Schema.String.annotate({ + "description": + "The write-only replacement secret. Never returned in credential resources or supplied directly to sandbox code. Must be nonempty and must not contain carriage returns, newlines, or NUL bytes." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ) +}).annotate({ + "description": + "Replace the secret for an OpenAI-hosted environment credential. The environment variable name and networking configuration remain unchanged.", + "identifier": "RotateVaultCredentialAuthParamEnvironmentVariable" }) -export type OrganizationProjectCertificateDeactivationResponse = { - readonly "object": "organization.project.certificate.deactivation" - readonly "data": ReadonlyArray +export type DeletedVaultCredentialResource = { + readonly "id": string + readonly "object": "vault.credential.deleted" + readonly "deleted": boolean } -export const OrganizationProjectCertificateDeactivationResponse = Schema.Struct({ - "object": Schema.Literal("organization.project.certificate.deactivation").annotate({ - "description": "The project certificate deactivation result type." +export const DeletedVaultCredentialResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the deleted credential." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("vault.credential.deleted").annotate({ + "description": "The object type. Always `vault.credential.deleted`." }), - "data": Schema.Array(OrganizationProjectCertificate) + "deleted": Schema.Boolean.annotate({ "description": "Whether the resource was deleted. Always `true`." }) +}).annotate({ + "description": "Confirmation that a vault credential was deleted.", + "identifier": "DeletedVaultCredentialResource" }) -export type CreateImageRequest = { - readonly "prompt": string - readonly "model"?: string | "gpt-image-1.5" | "dall-e-2" | "dall-e-3" | "gpt-image-1" | "gpt-image-1-mini" | null - readonly "n"?: number - readonly "quality"?: "standard" | "hd" | "low" | "medium" | "high" | "auto" | null - readonly "response_format"?: "url" | "b64_json" | null - readonly "output_format"?: "png" | "jpeg" | "webp" | null - readonly "output_compression"?: number | null - readonly "stream"?: boolean | null - readonly "partial_images"?: PartialImages - readonly "size"?: - | string - | "auto" - | "1024x1024" - | "1536x1024" - | "1024x1536" - | "256x256" - | "512x512" - | "1792x1024" - | "1024x1792" - | null - readonly "moderation"?: "low" | "auto" | null - readonly "background"?: "transparent" | "opaque" | "auto" | null - readonly "style"?: "vivid" | "natural" | null - readonly "user"?: string +export type WebhookEndpointBody = { + readonly "id": string + readonly "object": "webhook_endpoint" + readonly "created_at": number + readonly "updated_at"?: number + readonly "name": string + readonly "url": string + readonly "event_types": ReadonlyArray + readonly "signing_secret_hint": string | null } -export const CreateImageRequest = Schema.Struct({ - "prompt": Schema.String.annotate({ - "description": - "A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models, 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`." +export const WebhookEndpointBody = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the webhook endpoint." }), + "object": Schema.Literal("webhook_endpoint").annotate({ + "description": "The object type, which is always webhook_endpoint." }), - "model": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.String, - Schema.Literals(["gpt-image-1.5", "dall-e-2", "dall-e-3", "gpt-image-1", "gpt-image-1-mini"]) - ]).annotate({ - "description": - "The model to use for image generation. One of `dall-e-2`, `dall-e-3`, or a GPT image model (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`). Defaults to `dall-e-2` unless a parameter specific to the GPT image models is used." - }), - Schema.Null - ]) - ), - "n": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(10)], { - "description": - "The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported." - }) - ) - ]) - ), - "quality": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["standard", "hd", "low", "medium", "high", "auto"]).annotate({ - "description": - "The quality of the image that will be generated.\n\n- `auto` (default value) will automatically select the best quality for the given model.\n- `high`, `medium` and `low` are supported for the GPT image models.\n- `hd` and `standard` are supported for `dall-e-3`.\n- `standard` is the only option for `dall-e-2`.\n" - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "The quality of the image that will be generated.\n\n- `auto` (default value) will automatically select the best quality for the given model.\n- `high`, `medium` and `low` are supported for the GPT image models.\n- `hd` and `standard` are supported for `dall-e-3`.\n- `standard` is the only option for `dall-e-2`.\n" - }) - ]) - ), - "response_format": Schema.optionalKey(Schema.Union([ - Schema.Literals(["url", "b64_json"]).annotate({ - "description": - "The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images." - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "The format in which generated images with `dall-e-2` and `dall-e-3` are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter isn't supported for the GPT image models, which always return base64-encoded images." - }) - ])), - "output_format": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["png", "jpeg", "webp"]).annotate({ - "description": - "The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`." - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`." - }) - ]) - ), - "output_compression": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Null]).annotate({ + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp when the endpoint was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "updated_at": Schema.optionalKey( + Schema.Number.annotate({ "description": - "The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100." - }) + "The Unix timestamp of the last endpoint configuration or signing-secret change. Initialized at creation; tests and unchanged updates do not advance it.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), - "stream": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "name": Schema.String.annotate({ "description": "The human-readable name of the endpoint." }), + "url": Schema.String.annotate({ "description": "The HTTPS URL that receives webhook deliveries." }), + "event_types": Schema.Array(Schema.String).annotate({ + "description": "The event types that trigger deliveries to this endpoint." + }), + "signing_secret_hint": Schema.Union([ + Schema.String.annotate({ "description": "A masked hint for the endpoint's signing secret." }), + Schema.Null + ]) +}).annotate({ "identifier": "WebhookEndpointBody" }) +export type ProjectEventTypeEnum = + | "batch.completed" + | "batch.failed" + | "batch.expired" + | "batch.cancelled" + | "response.completed" + | "response.failed" + | "response.cancelled" + | "response.incomplete" + | "eval.run.succeeded" + | "eval.run.failed" + | "eval.run.canceled" + | "fine_tuning.job.succeeded" + | "fine_tuning.job.failed" + | "fine_tuning.job.cancelled" + | "realtime.call.incoming" + | "video.completed" + | "video.failed" + | "agent.environment.ready" + | "agent.environment.failed" + | "agent.environment.suspended" + | "agent.environment.expired" + | "agent.session.created" + | "agent.session.action_required" + | "agent.session.in_progress" + | "agent.session.idle" + | "agent.session.failed" + | "safety.alert.created" +export const ProjectEventTypeEnum = Schema.Literals([ + "batch.completed", + "batch.failed", + "batch.expired", + "batch.cancelled", + "response.completed", + "response.failed", + "response.cancelled", + "response.incomplete", + "eval.run.succeeded", + "eval.run.failed", + "eval.run.canceled", + "fine_tuning.job.succeeded", + "fine_tuning.job.failed", + "fine_tuning.job.cancelled", + "realtime.call.incoming", + "video.completed", + "video.failed", + "agent.environment.ready", + "agent.environment.failed", + "agent.environment.suspended", + "agent.environment.expired", + "agent.session.created", + "agent.session.action_required", + "agent.session.in_progress", + "agent.session.idle", + "agent.session.failed", + "safety.alert.created" +]).annotate({ "identifier": "ProjectEventTypeEnum" }) +export type WebhookEndpointWithSecretResource = { + readonly "id": string + readonly "object": "webhook_endpoint" + readonly "created_at": number + readonly "updated_at"?: number + readonly "name": string + readonly "url": string + readonly "event_types": ReadonlyArray + readonly "signing_secret_hint": string | null + readonly "signing_secret": string +} +export const WebhookEndpointWithSecretResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the webhook endpoint." }), + "object": Schema.Literal("webhook_endpoint").annotate({ + "description": "The object type, which is always webhook_endpoint." + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp when the endpoint was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "updated_at": Schema.optionalKey( + Schema.Number.annotate({ "description": - "Generate the image in streaming mode. Defaults to `false`. See the\n[Image generation guide](/docs/guides/image-generation) for more information.\nThis parameter is only supported for the GPT image models.\n" - }) - ), - "partial_images": Schema.optionalKey(PartialImages), - "size": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.String, - Schema.Literals(["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"]) - ]).annotate({ - "description": - "The size of the generated images. For `gpt-image-2` and `gpt-image-2-2026-04-21`, arbitrary resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the maximum supported resolution is `3840x2160`. The requested size must also satisfy the model's current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is supported for models that allow automatic sizing. For `dall-e-2`, use one of `256x256`, `512x512`, or `1024x1024`. For `dall-e-3`, use one of `1024x1024`, `1792x1024`, or `1024x1792`." - }), - Schema.Null - ]) - ), - "moderation": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["low", "auto"]).annotate({ - "description": - "Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value)." - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value)." - }) - ]) + "The Unix timestamp of the last endpoint configuration or signing-secret change. Initialized at creation; tests and unchanged updates do not advance it.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), - "background": Schema.optionalKey(Schema.Union([ - Schema.Literals(["transparent", "opaque", "auto"]).annotate({ - "description": - "Allows to set transparency for the background of the generated image(s).\nThis parameter is only supported for the GPT image models. Must be one of\n`transparent`, `opaque` or `auto` (default value). When `auto` is used, the\nmodel will automatically determine the best background for the image.\n\nIf `transparent`, the output format needs to support transparency, so it\nshould be set to either `png` (default value) or `webp`.\n" - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "Allows to set transparency for the background of the generated image(s).\nThis parameter is only supported for the GPT image models. Must be one of\n`transparent`, `opaque` or `auto` (default value). When `auto` is used, the\nmodel will automatically determine the best background for the image.\n\nIf `transparent`, the output format needs to support transparency, so it\nshould be set to either `png` (default value) or `webp`.\n" - }) - ])), - "style": Schema.optionalKey(Schema.Union([ - Schema.Literals(["vivid", "natural"]).annotate({ - "description": - "The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images." - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "The style of the generated images. This parameter is only supported for `dall-e-3`. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images." - }) - ])), - "user": Schema.optionalKey( - Schema.String.annotate({ + "name": Schema.String.annotate({ "description": "The human-readable name of the endpoint." }), + "url": Schema.String.annotate({ "description": "The HTTPS URL that receives webhook deliveries." }), + "event_types": Schema.Array(Schema.String).annotate({ + "description": "The event types that trigger deliveries to this endpoint." + }), + "signing_secret_hint": Schema.Union([ + Schema.String.annotate({ "description": "A masked hint for the endpoint's signing secret." }), + Schema.Null + ]), + "signing_secret": Schema.String.annotate({ + "description": + "The endpoint's signing secret. This is returned only when the endpoint is created or the secret is rotated." + }) +}).annotate({ "identifier": "WebhookEndpointWithSecretResource" }) +export type DeletedWebhookEndpointResource = { + readonly "id": string + readonly "object": "webhook_endpoint.deleted" + readonly "deleted": boolean +} +export const DeletedWebhookEndpointResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the deleted webhook endpoint." }), + "object": Schema.Literal("webhook_endpoint.deleted").annotate({ + "description": "The object type, which is always webhook_endpoint.deleted." + }), + "deleted": Schema.Boolean.annotate({ "description": "Whether the endpoint was deleted." }) +}).annotate({ "identifier": "DeletedWebhookEndpointResource" }) +export type PublicRotateSecretBody = { readonly "keep_old_secret_active_for_24_hours"?: boolean } +export const PublicRotateSecretBody = Schema.Struct({ + "keep_old_secret_active_for_24_hours": Schema.optionalKey( + Schema.Boolean.annotate({ "description": - "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices#end-user-ids).\n" + "Whether to keep the previous signing secret valid for 24 hours after rotation. Defaults to false, which invalidates the previous secret immediately." }) ) +}).annotate({ "identifier": "PublicRotateSecretBody" }) +export type WebhookEndpointTestResultResource = { + readonly "object": "webhook_endpoint.test" + readonly "webhook_endpoint_id": string + readonly "event_type": string + readonly "status_code": number + readonly "success": true +} +export const WebhookEndpointTestResultResource = Schema.Struct({ + "object": Schema.Literal("webhook_endpoint.test").annotate({ + "description": "The object type, which is always webhook_endpoint.test." + }), + "webhook_endpoint_id": Schema.String.annotate({ + "description": "The ID of the webhook endpoint that received the test." + }), + "event_type": Schema.String.annotate({ "description": "The event type sent in the test." }), + "status_code": Schema.Number.annotate({ "description": "The HTTP status code returned by the endpoint." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "success": Schema.Literal(true).annotate({ + "description": + "Whether the test request completed. Always true for returned results; use status_code to determine the endpoint response." + }) +}).annotate({ "identifier": "WebhookEndpointTestResultResource" }) +export type WebhookEventTypeListResource = { readonly "object": "list"; readonly "data": ReadonlyArray } +export const WebhookEventTypeListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always list." }), + "data": Schema.Array(Schema.String).annotate({ + "description": "The webhook event types available to the authenticated project." + }) +}).annotate({ "identifier": "WebhookEventTypeListResource" }) +export type BetaMetadata = { readonly [x: string]: string } | null +export const BetaMetadata = Schema.Union([ + Schema.Record(Schema.String, Schema.String).annotate({ + "description": + "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" + }), + Schema.Null +]).annotate({ "identifier": "BetaMetadata" }) +export type BetaPromptCacheTTLEnum = "30m" +export const BetaPromptCacheTTLEnum = Schema.Literal("30m").annotate({ "identifier": "BetaPromptCacheTTLEnum" }) +export type BetaPromptCacheModeEnum = "implicit" | "explicit" +export const BetaPromptCacheModeEnum = Schema.Literals(["implicit", "explicit"]).annotate({ + "identifier": "BetaPromptCacheModeEnum" }) -export type EditImageBodyJsonParam = { - readonly "model"?: string | "gpt-image-1.5" | "gpt-image-1" | "gpt-image-1-mini" | "chatgpt-image-latest" | null - readonly "images": ReadonlyArray - readonly "mask"?: ImageRefParam - readonly "prompt": string - readonly "n"?: number | null - readonly "quality"?: "low" | "medium" | "high" | "auto" | null - readonly "input_fidelity"?: "high" | "low" | null - readonly "size"?: "auto" | "1024x1024" | "1536x1024" | "1024x1536" | null - readonly "user"?: string - readonly "output_format"?: "png" | "jpeg" | "webp" | null - readonly "output_compression"?: number | null - readonly "moderation"?: "low" | "auto" | null - readonly "background"?: "transparent" | "opaque" | "auto" | null - readonly "stream"?: boolean | null - readonly "partial_images"?: PartialImages -} -export const EditImageBodyJsonParam = Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals(["gpt-image-1.5", "gpt-image-1", "gpt-image-1-mini", "chatgpt-image-latest"]), - Schema.Null - ]).annotate({ "description": "The model to use for image editing." }) - ), - "images": Schema.Array(ImageRefParam).annotate({ - "description": "Input image references to edit.\nFor GPT image models, you can provide up to 16 images.\n" - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(16)), - "mask": Schema.optionalKey(ImageRefParam), - "prompt": Schema.String.annotate({ "description": "A text description of the desired image edit." }).check( - Schema.isMinLength(1) - ).check(Schema.isMaxLength(32000)), - "n": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(10)), - Schema.Null - ]).annotate({ "description": "The number of edited images to generate." }) - ), - "quality": Schema.optionalKey( - Schema.Union([Schema.Literals(["low", "medium", "high", "auto"]), Schema.Null]).annotate({ - "description": "Output quality for GPT image models.\n" - }) - ), - "input_fidelity": Schema.optionalKey( - Schema.Union([Schema.Literals(["high", "low"]), Schema.Null]).annotate({ - "description": "Controls fidelity to the original input image(s)." - }) - ), - "size": Schema.optionalKey( - Schema.Union([Schema.Literals(["auto", "1024x1024", "1536x1024", "1024x1536"]), Schema.Null]).annotate({ - "description": "Requested output image size." - }) - ), - "user": Schema.optionalKey( - Schema.String.annotate({ - "description": - "A unique identifier representing your end-user, which can help OpenAI\nmonitor and detect abuse.\n" - }) - ), - "output_format": Schema.optionalKey( - Schema.Union([Schema.Literals(["png", "jpeg", "webp"]), Schema.Null]).annotate({ - "description": "Output image format. Supported for GPT image models." - }) - ), - "output_compression": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check( - Schema.isLessThanOrEqualTo(100) - ), - Schema.Null - ]).annotate({ "description": "Compression level for `jpeg` or `webp` output." }) - ), - "moderation": Schema.optionalKey( - Schema.Union([Schema.Literals(["low", "auto"]), Schema.Null]).annotate({ - "description": "Moderation level for GPT image models." - }) - ), - "background": Schema.optionalKey( - Schema.Union([Schema.Literals(["transparent", "opaque", "auto"]), Schema.Null]).annotate({ - "description": "Background behavior for generated image output." - }) - ), - "stream": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ "description": "Stream partial image results as events." }) - ), - "partial_images": Schema.optionalKey(PartialImages) +export type BetaModelIdsShared = + | string + | "gpt-6-astra" + | "gpt-6.1-sol" + | "gpt-6-sol" + | "gpt-6-luna" + | "gpt-5.6-sol" + | "gpt-5.6-terra" + | "gpt-5.6-luna" + | "gpt-5.5" + | "gpt-5.5-2026-04-23" + | "gpt-5.4" + | "gpt-5.4-mini" + | "gpt-5.4-nano" + | "gpt-5.4-mini-2026-03-17" + | "gpt-5.4-nano-2026-03-17" + | "gpt-5.3-chat-latest" + | "gpt-5.2" + | "gpt-5.2-2025-12-11" + | "gpt-5.2-chat-latest" + | "gpt-5.2-pro" + | "gpt-5.2-pro-2025-12-11" + | "gpt-5.1" + | "gpt-5.1-2025-11-13" + | "gpt-5.1-codex" + | "gpt-5.1-mini" + | "gpt-5.1-chat-latest" + | "gpt-5" + | "gpt-5-mini" + | "gpt-5-nano" + | "gpt-5-2025-08-07" + | "gpt-5-mini-2025-08-07" + | "gpt-5-nano-2025-08-07" + | "gpt-5-chat-latest" + | "gpt-4.1" + | "gpt-4.1-mini" + | "gpt-4.1-nano" + | "gpt-4.1-2025-04-14" + | "gpt-4.1-mini-2025-04-14" + | "gpt-4.1-nano-2025-04-14" + | "o4-mini" + | "o4-mini-2025-04-16" + | "o3" + | "o3-2025-04-16" + | "o3-mini" + | "o3-mini-2025-01-31" + | "o1" + | "o1-2024-12-17" + | "o1-preview" + | "o1-preview-2024-09-12" + | "o1-mini" + | "o1-mini-2024-09-12" + | "gpt-4o" + | "gpt-4o-2024-11-20" + | "gpt-4o-2024-08-06" + | "gpt-4o-2024-05-13" + | "gpt-audio-mini" + | "gpt-audio-mini-2025-12-15" + | "gpt-4o-audio-preview" + | "gpt-4o-audio-preview-2024-10-01" + | "gpt-4o-audio-preview-2024-12-17" + | "gpt-4o-audio-preview-2025-06-03" + | "gpt-4o-mini-audio-preview" + | "gpt-4o-mini-audio-preview-2024-12-17" + | "gpt-4o-search-preview" + | "gpt-4o-mini-search-preview" + | "gpt-4o-search-preview-2025-03-11" + | "gpt-4o-mini-search-preview-2025-03-11" + | "chatgpt-4o-latest" + | "codex-mini-latest" + | "gpt-4o-mini" + | "gpt-4o-mini-2024-07-18" + | "gpt-4-turbo" + | "gpt-4-turbo-2024-04-09" + | "gpt-4-0125-preview" + | "gpt-4-turbo-preview" + | "gpt-4-1106-preview" + | "gpt-4-vision-preview" + | "gpt-4" + | "gpt-4-0314" + | "gpt-4-0613" + | "gpt-4-32k" + | "gpt-4-32k-0314" + | "gpt-4-32k-0613" + | "gpt-3.5-turbo" + | "gpt-3.5-turbo-16k" + | "gpt-3.5-turbo-0301" + | "gpt-3.5-turbo-0613" + | "gpt-3.5-turbo-1106" + | "gpt-3.5-turbo-0125" + | "gpt-3.5-turbo-16k-0613" +export const BetaModelIdsShared = Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-6-astra", + "gpt-6.1-sol", + "gpt-6-sol", + "gpt-6-luna", + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", + "gpt-5.5", + "gpt-5.5-2026-04-23", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.4-mini-2026-03-17", + "gpt-5.4-nano-2026-03-17", + "gpt-5.3-chat-latest", + "gpt-5.2", + "gpt-5.2-2025-12-11", + "gpt-5.2-chat-latest", + "gpt-5.2-pro", + "gpt-5.2-pro-2025-12-11", + "gpt-5.1", + "gpt-5.1-2025-11-13", + "gpt-5.1-codex", + "gpt-5.1-mini", + "gpt-5.1-chat-latest", + "gpt-5", + "gpt-5-mini", + "gpt-5-nano", + "gpt-5-2025-08-07", + "gpt-5-mini-2025-08-07", + "gpt-5-nano-2025-08-07", + "gpt-5-chat-latest", + "gpt-4.1", + "gpt-4.1-mini", + "gpt-4.1-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "o4-mini", + "o4-mini-2025-04-16", + "o3", + "o3-2025-04-16", + "o3-mini", + "o3-mini-2025-01-31", + "o1", + "o1-2024-12-17", + "o1-preview", + "o1-preview-2024-09-12", + "o1-mini", + "o1-mini-2024-09-12", + "gpt-4o", + "gpt-4o-2024-11-20", + "gpt-4o-2024-08-06", + "gpt-4o-2024-05-13", + "gpt-audio-mini", + "gpt-audio-mini-2025-12-15", + "gpt-4o-audio-preview", + "gpt-4o-audio-preview-2024-10-01", + "gpt-4o-audio-preview-2024-12-17", + "gpt-4o-audio-preview-2025-06-03", + "gpt-4o-mini-audio-preview", + "gpt-4o-mini-audio-preview-2024-12-17", + "gpt-4o-search-preview", + "gpt-4o-mini-search-preview", + "gpt-4o-search-preview-2025-03-11", + "gpt-4o-mini-search-preview-2025-03-11", + "chatgpt-4o-latest", + "codex-mini-latest", + "gpt-4o-mini", + "gpt-4o-mini-2024-07-18", + "gpt-4-turbo", + "gpt-4-turbo-2024-04-09", + "gpt-4-0125-preview", + "gpt-4-turbo-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-4", + "gpt-4-0314", + "gpt-4-0613", + "gpt-4-32k", + "gpt-4-32k-0314", + "gpt-4-32k-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k", + "gpt-3.5-turbo-0301", + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo-1106", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-16k-0613" + ]) +]).annotate({ "identifier": "BetaModelIdsShared" }) +export type BetaResponseFormatText = { readonly "type": "text" } +export const BetaResponseFormatText = Schema.Struct({ + "type": Schema.Literal("text").annotate({ + "description": "The type of response format being defined. Always `text`." + }) }).annotate({ + "title": "Text", + "description": "Default response format. Used to generate text responses.\n", + "identifier": "BetaResponseFormatText" +}) +export type BetaResponseFormatJsonSchemaSchema = { readonly [x: string]: Schema.Json } +export const BetaResponseFormatJsonSchemaSchema = Schema.Record( + Schema.String, + Schema.Json.annotate({ "expected": "JSON value" }) +).annotate({ + "title": "JSON schema", "description": - "JSON request body for image edits.\n\nUse `images` (array of `ImageRefParam`) instead of multipart `image` uploads.\nYou can reference images via external URLs, data URLs, or uploaded file IDs.\nJSON edits support GPT image models only; DALL-E edits require multipart (`dall-e-2` only).\n" + "The schema for the response format, described as a JSON Schema object.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n", + "identifier": "BetaResponseFormatJsonSchemaSchema" }) -export type ProjectListResponse = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const ProjectListResponse = Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array(Project), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean +export type BetaResponseFormatJsonObject = { readonly "type": "json_object" } +export const BetaResponseFormatJsonObject = Schema.Struct({ + "type": Schema.Literal("json_object").annotate({ + "description": "The type of response format being defined. Always `json_object`." + }) +}).annotate({ + "title": "JSON object", + "description": + "JSON object response format. An older method of generating JSON responses.\nUsing `json_schema` is recommended for models that support it. Note that the\nmodel will not generate JSON without a system or user message instructing it\nto do so.\n", + "identifier": "BetaResponseFormatJsonObject" }) -export type ProjectApiKey = { - readonly "object": "organization.project.api_key" - readonly "redacted_value": string - readonly "name": string - readonly "created_at": number - readonly "last_used_at": number | null - readonly "id": string - readonly "owner": { - readonly "type"?: "user" | "service_account" - readonly "user"?: ProjectApiKeyOwnerUser - readonly "service_account"?: ProjectApiKeyOwnerServiceAccount - } -} -export const ProjectApiKey = Schema.Struct({ - "object": Schema.Literal("organization.project.api_key").annotate({ - "description": "The object type, which is always `organization.project.api_key`" +export type BetaVerbosity = "low" | "medium" | "high" | null +export const BetaVerbosity = Schema.Union([ + Schema.Literals(["low", "medium", "high"]).annotate({ + "description": + "Constrains the verbosity of the model's response. Lower values will result in\nmore concise responses, while higher values will result in more verbose responses.\nCurrently supported values are `low`, `medium`, and `high`. The default is\n`medium`.\n" }), - "redacted_value": Schema.String.annotate({ "description": "The redacted value of the API key" }), - "name": Schema.String.annotate({ "description": "The name of the API key" }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the API key was created", - "format": "unixtime" - }).check(Schema.isInt()), - "last_used_at": Schema.Union([Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt()), Schema.Null]) - .annotate({ "description": "The Unix timestamp (in seconds) of when the API key was last used." }), - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), - "owner": Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literals(["user", "service_account"]).annotate({ "description": "`user` or `service_account`" }) - ), - "user": Schema.optionalKey(ProjectApiKeyOwnerUser), - "service_account": Schema.optionalKey(ProjectApiKeyOwnerServiceAccount) - }) -}).annotate({ "description": "Represents an individual API key in a project." }) -export type ProjectGroupListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "next": string | null -} -export const ProjectGroupListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), - "data": Schema.Array(ProjectGroup).annotate({ - "description": "Project group memberships returned in the current page." - }), - "has_more": Schema.Boolean.annotate({ "description": "Whether additional project group memberships are available." }), - "next": Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "Cursor to fetch the next page of results, or `null` when there are no more results." - }) -}).annotate({ "description": "Paginated list of groups that have access to a project." }) -export type ProjectRateLimitListResponse = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const ProjectRateLimitListResponse = Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array(ProjectRateLimit), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean + Schema.Null +]).annotate({ "identifier": "BetaVerbosity" }) +export type BetaCallableToolAllowedCaller = "direct" | "programmatic" +export const BetaCallableToolAllowedCaller = Schema.Literals(["direct", "programmatic"]).annotate({ + "identifier": "BetaCallableToolAllowedCaller" }) -export type ProjectServiceAccountListResponse = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const ProjectServiceAccountListResponse = Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array(ProjectServiceAccount), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean +export type BetaRankerVersionType = "auto" | "default-2024-11-15" +export const BetaRankerVersionType = Schema.Literals(["auto", "default-2024-11-15"]).annotate({ + "identifier": "BetaRankerVersionType" }) -export type ProjectServiceAccountCreateResponse = { - readonly "object": "organization.project.service_account" - readonly "id": string - readonly "name": string - readonly "role": "member" - readonly "created_at": number - readonly "api_key": ProjectServiceAccountApiKey | null +export type BetaHybridSearchOptions = { readonly "embedding_weight": number; readonly "text_weight": number } +export const BetaHybridSearchOptions = Schema.Struct({ + "embedding_weight": Schema.Number.annotate({ + "description": "The weight of the embedding in the reciprocal ranking fusion." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "text_weight": Schema.Number.annotate({ "description": "The weight of the text in the reciprocal ranking fusion." }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })) +}).annotate({ "identifier": "BetaHybridSearchOptions" }) +export type BetaComparisonFilter = { + readonly "type": "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" + readonly "key": string + readonly "value": string | number | boolean | ReadonlyArray } -export const ProjectServiceAccountCreateResponse = Schema.Struct({ - "object": Schema.Literal("organization.project.service_account"), - "id": Schema.String, - "name": Schema.String, - "role": Schema.Literal("member").annotate({ - "description": "Service accounts can only have one role of type `member`" +export const BetaComparisonFilter = Schema.Struct({ + "type": Schema.Literals(["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"]).annotate({ + "description": + "Specifies the comparison operator: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`.\n- `eq`: equals\n- `ne`: not equal\n- `gt`: greater than\n- `gte`: greater than or equal\n- `lt`: less than\n- `lte`: less than or equal\n- `in`: in\n- `nin`: not in\n" }), - "created_at": Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt()), - "api_key": Schema.Union([ProjectServiceAccountApiKey, Schema.Null]) + "key": Schema.String.annotate({ "description": "The key to compare against the value." }), + "value": Schema.Union([ + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.Array(Schema.Union([Schema.String, Schema.Finite], { mode: "oneOf" })) + ], { mode: "oneOf" }).annotate({ + "description": "The value to compare against the attribute key; supports string, number, or boolean types." + }) +}).annotate({ + "title": "Comparison Filter", + "description": + "A filter used to compare a specified attribute key to a given value using a defined comparison operation.\n", + "identifier": "BetaComparisonFilter" }) -export type ProjectUserListResponse = { - readonly "object": string - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const ProjectUserListResponse = Schema.Struct({ - "object": Schema.String, - "data": Schema.Array(ProjectUser), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean +export type BetaComputerTool = { readonly "type": "computer" } +export const BetaComputerTool = Schema.Struct({ + "type": Schema.Literal("computer").annotate({ "description": "The type of the computer tool. Always `computer`." }) +}).annotate({ + "title": "Computer", + "description": + "A tool that controls a virtual computer. Learn more about the [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use).", + "identifier": "BetaComputerTool" }) -export type RealtimeTranscriptionSessionCreateResponseGA = { - readonly "type": "transcription" - readonly "id": string - readonly "object": string - readonly "expires_at"?: number - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> - readonly "audio"?: { - readonly "input"?: { - readonly "format"?: RealtimeAudioFormats - readonly "transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - } - readonly "noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "turn_detection"?: { - readonly "type"?: string - readonly "threshold"?: number - readonly "prefix_padding_ms"?: number - readonly "silence_duration_ms"?: number - } | null - } - } -} -export const RealtimeTranscriptionSessionCreateResponseGA = Schema.Struct({ - "type": Schema.Literal("transcription").annotate({ - "description": "The type of session. Always `transcription` for transcription sessions.\n" - }), - "id": Schema.String.annotate({ - "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" - }), - "object": Schema.String.annotate({ "description": "The object type. Always `realtime.transcription_session`." }), - "expires_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Expiration timestamp for the session, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()) +export type BetaComputerEnvironment = "windows" | "mac" | "linux" | "ubuntu" | "browser" +export const BetaComputerEnvironment = Schema.Literals(["windows", "mac", "linux", "ubuntu", "browser"]).annotate({ + "identifier": "BetaComputerEnvironment" +}) +export type BetaWebSearchApproximateLocation = { + readonly "type"?: "approximate" + readonly "country"?: string | null + readonly "region"?: string | null + readonly "city"?: string | null + readonly "timezone"?: string | null +} | null +export const BetaWebSearchApproximateLocation = Schema.Union([ + Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("approximate").annotate({ + "description": "The type of location approximation. Always `approximate`." + }) + ), + "country": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`." + }), + Schema.Null + ]) + ), + "region": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Free text input for the region of the user, e.g. `California`." }), + Schema.Null + ]) + ), + "city": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Free text input for the city of the user, e.g. `San Francisco`." }), + Schema.Null + ]) + ), + "timezone": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`." + }), + Schema.Null + ]) + ) + }).annotate({ "title": "Web search approximate location", "description": "The approximate location of the user.\n" }), + Schema.Null +]).annotate({ "identifier": "BetaWebSearchApproximateLocation" }) +export type BetaMCPToolFilter = { readonly "tool_names"?: ReadonlyArray; readonly "read_only"?: boolean } +export const BetaMCPToolFilter = Schema.Struct({ + "tool_names": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ "title": "MCP allowed tools", "description": "List of allowed tool names." }) ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ + "read_only": Schema.optionalKey( + Schema.Boolean.annotate({ "description": - "Additional fields to include in server outputs.\n- `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" + "Indicates whether or not a tool modifies data or is read-only. If an\nMCP server is [annotated with `readOnlyHint`](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint),\nit will match this filter.\n" }) - ), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey(RealtimeAudioFormats), - "transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model used for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ "description": "The language of the input audio.\n" }) - ), - "prompt": Schema.optionalKey( - Schema.String.annotate({ - "description": "The prompt configured for input audio transcription, when present.\n" - }) - ) - }).annotate({ "description": "Configuration of the transcription model.\n" }) - ), - "noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": "Configuration for input audio noise reduction.\n" - }) - ), - "turn_detection": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.String.annotate({ - "description": "Type of turn detection, only `server_vad` is currently supported.\n" - }) - ), - "threshold": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" - }).check(Schema.isFinite()) - ), - "prefix_padding_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" - }).check(Schema.isInt()) - ), - "silence_duration_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" - }).check(Schema.isInt()) - ) - }).annotate({ - "description": - "Configuration for turn detection. Can be set to `null` to turn off. Server\nVAD means that the model will detect the start and end of speech based on\naudio volume and respond at the end of user speech. For `gpt-realtime-whisper`, this must be `null`; VAD is not supported.\n" - }), - Schema.Null - ]).annotate({ - "description": - "Configuration for turn detection. For `gpt-realtime-whisper`, this must be `null`; VAD is not supported.\n" - }) - ) - })) - }).annotate({ "description": "Configuration for input audio for the session.\n" }) ) }).annotate({ - "title": "Realtime transcription session configuration object", - "description": "A Realtime transcription session configuration object.\n" + "title": "MCP tool filter", + "description": "A filter object to specify which tools are allowed.\n", + "identifier": "BetaMCPToolFilter" }) -export type RealtimeMCPToolCall = { - readonly "type": "mcp_call" - readonly "id": string - readonly "server_label": string +export type BetaContainerMemoryLimit = "1g" | "4g" | "16g" | "64g" +export const BetaContainerMemoryLimit = Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ + "identifier": "BetaContainerMemoryLimit" +}) +export type BetaContainerNetworkPolicyDisabledParam = { readonly "type": "disabled" } +export const BetaContainerNetworkPolicyDisabledParam = Schema.Struct({ + "type": Schema.Literal("disabled").annotate({ "description": "Disable outbound network access. Always `disabled`." }) +}).annotate({ "identifier": "BetaContainerNetworkPolicyDisabledParam" }) +export type BetaContainerNetworkPolicyDomainSecretParam = { + readonly "domain": string readonly "name": string - readonly "arguments": string - readonly "approval_request_id"?: string | null - readonly "output"?: string | null - readonly "error"?: RealtimeMCPProtocolError | RealtimeMCPToolExecutionError | RealtimeMCPHTTPError | null -} -export const RealtimeMCPToolCall = Schema.Struct({ - "type": Schema.Literal("mcp_call").annotate({ "description": "The type of the item. Always `mcp_call`." }), - "id": Schema.String.annotate({ "description": "The unique ID of the tool call." }), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server running the tool." }), - "name": Schema.String.annotate({ "description": "The name of the tool that was run." }), - "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments passed to the tool." }), - "approval_request_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The ID of an associated approval request, if any." }), - Schema.Null - ]) + readonly "value": string +} +export const BetaContainerNetworkPolicyDomainSecretParam = Schema.Struct({ + "domain": Schema.String.annotate({ "description": "The domain associated with the secret." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) ), - "output": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "The output from the tool call." }), Schema.Null]) + "name": Schema.String.annotate({ "description": "The name of the secret to inject for the domain." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) ), - "error": Schema.optionalKey( - Schema.Union([ - Schema.Union([RealtimeMCPProtocolError, RealtimeMCPToolExecutionError, RealtimeMCPHTTPError], { mode: "oneOf" }) - .annotate({ "description": "The error from the tool call, if any." }), - Schema.Null - ]) - ) -}).annotate({ - "title": "Realtime MCP tool call", - "description": "A Realtime item representing an invocation of a tool on an MCP server.\n" + "value": Schema.String.annotate({ "description": "The secret value to inject for the domain." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" })) +}).annotate({ "identifier": "BetaContainerNetworkPolicyDomainSecretParam" }) +export type BetaProgrammaticToolCallingParam = { readonly "type": "programmatic_tool_calling" } +export const BetaProgrammaticToolCallingParam = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The type of the tool. Always `programmatic_tool_calling`." + }) +}).annotate({ "identifier": "BetaProgrammaticToolCallingParam" }) +export type BetaInputFidelity = "high" | "low" +export const BetaInputFidelity = Schema.Literals(["high", "low"]).annotate({ + "description": + "Control how much effort the model will exert to match the style and features, especially facial features, of input images. Supports `high` and `low` on `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For `gpt-image-2`, omit this parameter. Defaults to `low` on supported models.", + "identifier": "BetaInputFidelity" }) -export type RealtimeReasoning = { readonly "effort"?: RealtimeReasoningEffort } -export const RealtimeReasoning = Schema.Struct({ "effort": Schema.optionalKey(RealtimeReasoningEffort) }).annotate({ - "title": "Realtime reasoning configuration", - "description": "Configuration for reasoning-capable Realtime models such as `gpt-realtime-2`.\n" +export type BetaImageGenActionEnum = "generate" | "edit" | "auto" +export const BetaImageGenActionEnum = Schema.Literals(["generate", "edit", "auto"]).annotate({ + "identifier": "BetaImageGenActionEnum" }) -export type RealtimeTranscriptionSessionCreateRequestGA = { - readonly "type": "transcription" - readonly "audio"?: { - readonly "input"?: { - readonly "format"?: RealtimeAudioFormats - readonly "transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - readonly "delay"?: "minimal" | "low" | "medium" | "high" | "xhigh" - } - readonly "noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "turn_detection"?: RealtimeTurnDetection - } - } - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> +export type BetaLocalShellToolParam = { readonly "type": "local_shell" } +export const BetaLocalShellToolParam = Schema.Struct({ + "type": Schema.Literal("local_shell").annotate({ + "description": "The type of the local shell tool. Always `local_shell`." + }) +}).annotate({ + "title": "Local shell tool", + "description": "A tool that allows the model to execute shell commands in a local environment.", + "identifier": "BetaLocalShellToolParam" +}) +export type BetaSkillReferenceParam = { + readonly "type": "skill_reference" + readonly "skill_id": string + readonly "version"?: string } -export const RealtimeTranscriptionSessionCreateRequestGA = Schema.Struct({ - "type": Schema.Literal("transcription").annotate({ - "description": "The type of session to create. Always `transcription` for transcription sessions.\n" +export const BetaSkillReferenceParam = Schema.Struct({ + "type": Schema.Literal("skill_reference").annotate({ + "description": "References a skill created with the /v1/skills endpoint." }), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey(RealtimeAudioFormats), - "transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model to use for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The language of the input audio. Supplying the input language in\n[ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format\nwill improve accuracy and latency.\n" - }) - ), - "prompt": Schema.optionalKey(Schema.String.annotate({ - "description": - "An optional text to guide the model's style or continue a previous audio\nsegment.\nFor `whisper-1`, the [prompt is a list of keywords](/docs/guides/speech-to-text#prompting).\nFor `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example \"expect words related to technology\".\nPrompt is not supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - })), - "delay": Schema.optionalKey( - Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": - "Controls how long the model waits before emitting transcription text.\nHigher values can improve transcription accuracy at the cost of latency.\nOnly supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - }) - ) - }).annotate({ - "description": - "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" - }) - ), - "noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": - "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" - }) - ), - "turn_detection": Schema.optionalKey(RealtimeTurnDetection) - })) - }).annotate({ "description": "Configuration for input and output audio.\n" }) - ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ - "description": - "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" + "skill_id": Schema.String.annotate({ "description": "The ID of the referenced skill." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "version": Schema.optionalKey( + Schema.String.annotate({ + "description": "Optional skill version. Use a positive integer or 'latest'. Omit for default." }) ) +}).annotate({ "identifier": "BetaSkillReferenceParam" }) +export type BetaInlineSkillSourceParam = { + readonly "type": "base64" + readonly "media_type": "application/zip" + readonly "data": string +} +export const BetaInlineSkillSourceParam = Schema.Struct({ + "type": Schema.Literal("base64").annotate({ + "description": "The type of the inline skill source. Must be `base64`." + }), + "media_type": Schema.Literal("application/zip").annotate({ + "description": "The media type of the inline skill payload. Must be `application/zip`." + }), + "data": Schema.String.annotate({ "description": "Base64-encoded skill zip bundle." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(70254592).annotate({ "expected": "a string with at most 70254592 code points" })) +}).annotate({ "description": "Inline skill payload", "identifier": "BetaInlineSkillSourceParam" }) +export type BetaLocalSkillParam = { readonly "name": string; readonly "description": string; readonly "path": string } +export const BetaLocalSkillParam = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the skill." }), + "description": Schema.String.annotate({ "description": "The description of the skill." }), + "path": Schema.String.annotate({ "description": "The path to the directory containing the skill." }) +}).annotate({ "identifier": "BetaLocalSkillParam" }) +export type BetaContainerReferenceParam = { readonly "type": "container_reference"; readonly "container_id": string } +export const BetaContainerReferenceParam = Schema.Struct({ + "type": Schema.Literal("container_reference").annotate({ + "description": "References a container created with the /v1/containers endpoint" + }), + "container_id": Schema.String.annotate({ "description": "The ID of the referenced container." }) +}).annotate({ "identifier": "BetaContainerReferenceParam" }) +export type BetaCustomTextFormatParam = { readonly "type": "text" } +export const BetaCustomTextFormatParam = Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "Unconstrained text format. Always `text`." }) }).annotate({ - "title": "Realtime transcription session configuration", - "description": "Realtime transcription session object configuration." + "title": "Text format", + "description": "Unconstrained free-form text.", + "identifier": "BetaCustomTextFormatParam" }) -export type Reasoning = { - readonly "effort"?: ReasoningEffort - readonly "summary"?: "auto" | "concise" | "detailed" | null - readonly "generate_summary"?: "auto" | "concise" | "detailed" | null +export type BetaGrammarSyntax1 = "lark" | "regex" +export const BetaGrammarSyntax1 = Schema.Literals(["lark", "regex"]).annotate({ "identifier": "BetaGrammarSyntax1" }) +export type BetaEmptyModelParam = { readonly [x: string]: Schema.Json } +export const BetaEmptyModelParam = Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) + .annotate({ "identifier": "BetaEmptyModelParam" }) +export type BetaToolSearchExecutionType = "server" | "client" +export const BetaToolSearchExecutionType = Schema.Literals(["server", "client"]).annotate({ + "identifier": "BetaToolSearchExecutionType" +}) +export type BetaApproximateLocation = { + readonly "type": "approximate" + readonly "country"?: string | null + readonly "region"?: string | null + readonly "city"?: string | null + readonly "timezone"?: string | null } -export const Reasoning = Schema.Struct({ - "effort": Schema.optionalKey(ReasoningEffort), - "summary": Schema.optionalKey(Schema.Union([ - Schema.Literals(["auto", "concise", "detailed"]).annotate({ - "description": - "A summary of the reasoning performed by the model. This can be\nuseful for debugging and understanding the model's reasoning process.\nOne of `auto`, `concise`, or `detailed`.\n\n`concise` is supported for `computer-use-preview` models and all reasoning models after `gpt-5`.\n" - }), - Schema.Null - ])), - "generate_summary": Schema.optionalKey( +export const BetaApproximateLocation = Schema.Struct({ + "type": Schema.Literal("approximate").annotate({ + "description": "The type of location approximation. Always `approximate`." + }), + "country": Schema.optionalKey( Schema.Union([ - Schema.Literals(["auto", "concise", "detailed"]).annotate({ + Schema.String.annotate({ "description": - "**Deprecated:** use `summary` instead.\n\nA summary of the reasoning performed by the model. This can be\nuseful for debugging and understanding the model's reasoning process.\nOne of `auto`, `concise`, or `detailed`.\n" + "The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`." }), Schema.Null ]) - ) -}).annotate({ - "title": "Reasoning", - "description": - "**gpt-5 and o-series models only**\n\nConfiguration options for\n[reasoning models](https://platform.openai.com/docs/guides/reasoning).\n" -}) -export type ResponseError = { readonly "code": ResponseErrorCode; readonly "message": string } | null -export const ResponseError = Schema.Union([ - Schema.Struct({ - "code": ResponseErrorCode, - "message": Schema.String.annotate({ "description": "A human-readable description of the error.\n" }) - }).annotate({ "description": "An error object returned when the model fails to generate a Response.\n" }), - Schema.Null -]) -export type ResponseFormatJsonSchema = { - readonly "type": "json_schema" - readonly "json_schema": { - readonly "description"?: string - readonly "name": string - readonly "schema"?: ResponseFormatJsonSchemaSchema - readonly "strict"?: boolean | null - } -} -export const ResponseFormatJsonSchema = Schema.Struct({ - "type": Schema.Literal("json_schema").annotate({ - "description": "The type of response format being defined. Always `json_schema`." - }), - "json_schema": Schema.Struct({ - "description": Schema.optionalKey( + ), + "region": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Free text input for the region of the user, e.g. `California`." }), + Schema.Null + ]) + ), + "city": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Free text input for the city of the user, e.g. `San Francisco`." }), + Schema.Null + ]) + ), + "timezone": Schema.optionalKey( + Schema.Union([ Schema.String.annotate({ "description": - "A description of what the response format is for, used by the model to\ndetermine how to respond in the format.\n" - }) - ), - "name": Schema.String.annotate({ - "description": - "The name of the response format. Must be a-z, A-Z, 0-9, or contain\nunderscores and dashes, with a maximum length of 64.\n" - }), - "schema": Schema.optionalKey(ResponseFormatJsonSchemaSchema), - "strict": Schema.optionalKey(Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Whether to enable strict schema adherence when generating the output.\nIf set to true, the model will always follow the exact schema defined\nin the `schema` field. Only a subset of JSON Schema is supported when\n`strict` is `true`. To learn more, read the [Structured Outputs\nguide](/docs/guides/structured-outputs).\n" + "The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`." }), Schema.Null - ])) - }).annotate({ - "title": "JSON schema", - "description": "Structured Outputs configuration options, including a JSON Schema.\n" - }) -}).annotate({ - "title": "JSON schema", + ]) + ) +}).annotate({ "identifier": "BetaApproximateLocation" }) +export type BetaSearchContextSize = "low" | "medium" | "high" +export const BetaSearchContextSize = Schema.Literals(["low", "medium", "high"]).annotate({ + "identifier": "BetaSearchContextSize" +}) +export type BetaSearchContentType = "text" | "image" +export const BetaSearchContentType = Schema.Literals(["text", "image"]).annotate({ + "identifier": "BetaSearchContentType" +}) +export type BetaToolChoiceOptions = "none" | "auto" | "required" +export const BetaToolChoiceOptions = Schema.Literals(["none", "auto", "required"]).annotate({ + "title": "Tool choice mode", "description": - "JSON Schema response format. Used to generate structured JSON responses.\nLearn more about [Structured Outputs](/docs/guides/structured-outputs).\n" + "Controls which (if any) tool is called by the model.\n\n`none` means the model will not call any tool and instead generates a message.\n\n`auto` means the model can pick between generating a message or calling one or\nmore tools.\n\n`required` means the model must call one or more tools.\n", + "identifier": "BetaToolChoiceOptions" }) -export type TextResponseFormatJsonSchema = { - readonly "type": "json_schema" - readonly "description"?: string - readonly "name": string - readonly "schema": ResponseFormatJsonSchemaSchema - readonly "strict"?: boolean | null +export type BetaToolChoiceAllowed = { + readonly "type": "allowed_tools" + readonly "mode": "auto" | "required" + readonly "tools": ReadonlyArray<{ readonly [x: string]: Schema.Json }> } -export const TextResponseFormatJsonSchema = Schema.Struct({ - "type": Schema.Literal("json_schema").annotate({ - "description": "The type of response format being defined. Always `json_schema`." +export const BetaToolChoiceAllowed = Schema.Struct({ + "type": Schema.Literal("allowed_tools").annotate({ + "description": "Allowed tool configuration type. Always `allowed_tools`." }), - "description": Schema.optionalKey( - Schema.String.annotate({ - "description": - "A description of what the response format is for, used by the model to\ndetermine how to respond in the format.\n" - }) - ), - "name": Schema.String.annotate({ + "mode": Schema.Literals(["auto", "required"]).annotate({ "description": - "The name of the response format. Must be a-z, A-Z, 0-9, or contain\nunderscores and dashes, with a maximum length of 64.\n" + "Constrains the tools available to the model to a pre-defined set.\n\n`auto` allows the model to pick from among the allowed tools and generate a\nmessage.\n\n`required` requires the model to call one or more of the allowed tools.\n" }), - "schema": ResponseFormatJsonSchemaSchema, - "strict": Schema.optionalKey(Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Whether to enable strict schema adherence when generating the output.\nIf set to true, the model will always follow the exact schema defined\nin the `schema` field. Only a subset of JSON Schema is supported when\n`strict` is `true`. To learn more, read the [Structured Outputs\nguide](/docs/guides/structured-outputs).\n" - }), - Schema.Null - ])) + "tools": Schema.Array( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A tool definition that the model should be allowed to call.\n" + }) + ).annotate({ + "description": + "A list of tool definitions that the model should be allowed to call.\n\nFor the Responses API, the list of tool definitions might look like:\n```json\n[\n { \"type\": \"function\", \"name\": \"get_weather\" },\n { \"type\": \"mcp\", \"server_label\": \"deepwiki\" },\n { \"type\": \"image_generation\" }\n]\n```\n" + }) }).annotate({ - "title": "JSON schema", - "description": - "JSON Schema response format. Used to generate structured JSON responses.\nLearn more about [Structured Outputs](/docs/guides/structured-outputs).\n" + "title": "Allowed tools", + "description": "Constrains the tools available to the model to a pre-defined set.\n", + "identifier": "BetaToolChoiceAllowed" }) -export type ResponseTextDeltaEvent = { - readonly "type": "response.output_text.delta" - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "delta": string - readonly "sequence_number": number - readonly "logprobs": ReadonlyArray +export type BetaToolChoiceTypes = { + readonly "type": + | "file_search" + | "web_search_preview" + | "computer" + | "computer_use_preview" + | "computer_use" + | "web_search_preview_2025_03_11" + | "image_generation" + | "code_interpreter" } -export const ResponseTextDeltaEvent = Schema.Struct({ - "type": Schema.Literal("response.output_text.delta").annotate({ - "description": "The type of the event. Always `response.output_text.delta`.\n" - }), - "item_id": Schema.String.annotate({ "description": "The ID of the output item that the text delta was added to.\n" }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the text delta was added to.\n" - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part that the text delta was added to.\n" - }).check(Schema.isInt()), - "delta": Schema.String.annotate({ "description": "The text delta that was added.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( - Schema.isInt() - ), - "logprobs": Schema.Array(ResponseLogProb).annotate({ - "description": "The log probabilities of the tokens in the delta.\n" +export const BetaToolChoiceTypes = Schema.Struct({ + "type": Schema.Literals([ + "file_search", + "web_search_preview", + "computer", + "computer_use_preview", + "computer_use", + "web_search_preview_2025_03_11", + "image_generation", + "code_interpreter" + ]).annotate({ + "description": + "The type of hosted tool the model should to use. Learn more about\n[built-in tools](https://developers.openai.com/api/docs/guides/tools).\n\nAllowed values are:\n- `file_search`\n- `web_search_preview`\n- `computer`\n- `computer_use_preview`\n- `computer_use`\n- `code_interpreter`\n- `image_generation`\n" }) -}).annotate({ "description": "Emitted when there is an additional text delta." }) -export type ResponseTextDoneEvent = { - readonly "type": "response.output_text.done" - readonly "item_id": string - readonly "output_index": number - readonly "content_index": number - readonly "text": string - readonly "sequence_number": number - readonly "logprobs": ReadonlyArray -} -export const ResponseTextDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.output_text.done").annotate({ - "description": "The type of the event. Always `response.output_text.done`.\n" - }), - "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the text content is finalized.\n" +}).annotate({ + "title": "Hosted tool", + "description": + "Indicates that the model should use a built-in tool to generate a response.\n[Learn more about built-in tools](https://developers.openai.com/api/docs/guides/tools).\n", + "identifier": "BetaToolChoiceTypes" +}) +export type BetaToolChoiceFunction = { readonly "type": "function"; readonly "name": string } +export const BetaToolChoiceFunction = Schema.Struct({ + "type": Schema.Literal("function").annotate({ + "description": "For function calling, the type is always `function`." }), - "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the text content is finalized.\n" - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ - "description": "The index of the content part that the text content is finalized.\n" - }).check(Schema.isInt()), - "text": Schema.String.annotate({ "description": "The text content that is finalized.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( - Schema.isInt() - ), - "logprobs": Schema.Array(ResponseLogProb).annotate({ - "description": "The log probabilities of the tokens in the delta.\n" + "name": Schema.String.annotate({ "description": "The name of the function to call." }) +}).annotate({ + "title": "Function tool", + "description": "Use this option to force the model to call a specific function.\n", + "identifier": "BetaToolChoiceFunction" +}) +export type BetaToolChoiceMCP = { + readonly "type": "mcp" + readonly "server_label": string + readonly "name"?: string | null +} +export const BetaToolChoiceMCP = Schema.Struct({ + "type": Schema.Literal("mcp").annotate({ "description": "For MCP tools, the type is always `mcp`." }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server to use.\n" }), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The name of the tool to call on the server.\n" }), + Schema.Null + ]) + ) +}).annotate({ + "title": "MCP tool", + "description": "Use this option to force the model to call a specific tool on a remote MCP server.\n", + "identifier": "BetaToolChoiceMCP" +}) +export type BetaToolChoiceCustom = { readonly "type": "custom"; readonly "name": string } +export const BetaToolChoiceCustom = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "For custom tool calling, the type is always `custom`." }), + "name": Schema.String.annotate({ "description": "The name of the custom tool to call." }) +}).annotate({ + "title": "Custom tool", + "description": "Use this option to force the model to call a specific custom tool.\n", + "identifier": "BetaToolChoiceCustom" +}) +export type BetaSpecificProgrammaticToolCallingParam = { readonly "type": "programmatic_tool_calling" } +export const BetaSpecificProgrammaticToolCallingParam = Schema.Struct({ + "type": Schema.Literal("programmatic_tool_calling").annotate({ + "description": "The tool to call. Always `programmatic_tool_calling`." }) -}).annotate({ "description": "Emitted when text content is finalized." }) -export type Prompt = { - readonly "id": string - readonly "version"?: string | null - readonly "variables"?: ResponsePromptVariables -} | null -export const Prompt = Schema.Union([ - Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique identifier of the prompt template to use." }), - "version": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "Optional version of the prompt template." }), Schema.Null]) - ), - "variables": Schema.optionalKey(ResponsePromptVariables) - }).annotate({ +}).annotate({ "identifier": "BetaSpecificProgrammaticToolCallingParam" }) +export type BetaSpecificApplyPatchParam = { readonly "type": "apply_patch" } +export const BetaSpecificApplyPatchParam = Schema.Struct({ + "type": Schema.Literal("apply_patch").annotate({ "description": "The tool to call. Always `apply_patch`." }) +}).annotate({ + "title": "Specific apply patch tool choice", + "description": "Forces the model to call the apply_patch tool when executing a tool call.", + "identifier": "BetaSpecificApplyPatchParam" +}) +export type BetaSpecificFunctionShellParam = { readonly "type": "shell" } +export const BetaSpecificFunctionShellParam = Schema.Struct({ + "type": Schema.Literal("shell").annotate({ "description": "The tool to call. Always `shell`." }) +}).annotate({ + "title": "Specific shell tool choice", + "description": "Forces the model to call the shell tool when a tool call is required.", + "identifier": "BetaSpecificFunctionShellParam" +}) +export type BetaPromptCacheBreakpointConfig = { readonly "mode": "explicit" } +export const BetaPromptCacheBreakpointConfig = Schema.Struct({ + "mode": Schema.Literal("explicit").annotate({ "description": "The breakpoint mode. Always `explicit`." }) +}).annotate({ + "title": "Prompt cache breakpoint", + "description": + "Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.", + "identifier": "BetaPromptCacheBreakpointConfig" +}) +export type BetaImageDetail = "low" | "high" | "auto" | "original" +export const BetaImageDetail = Schema.Literals(["low", "high", "auto", "original"]).annotate({ + "identifier": "BetaImageDetail" +}) +export type BetaFileInputDetail = "auto" | "low" | "high" +export const BetaFileInputDetail = Schema.Literals(["auto", "low", "high"]).annotate({ + "identifier": "BetaFileInputDetail" +}) +export type BetaCyberAccessProgramEnum = "standard" | "daybreak_blue" | "daybreak_red" +export const BetaCyberAccessProgramEnum = Schema.Literals(["standard", "daybreak_blue", "daybreak_red"]).annotate({ + "identifier": "BetaCyberAccessProgramEnum" +}) +export type BetaServiceTierResponses = "auto" | "default" | "flex" | "scale" | "priority" | "fast" | "ultrafast" | null +export const BetaServiceTierResponses = Schema.Union([ + Schema.Literals(["auto", "default", "flex", "scale", "priority", "fast", "ultrafast"]).annotate({ "description": - "Reference to a prompt template and its variables.\n[Learn more](/docs/guides/text?api-mode=responses#reusable-prompts).\n" + "Specifies the processing type used for serving the request.\n - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'.\n - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model.\n - If set to '[flex](https://developers.openai.com/api/docs/guides/flex-processing)', then the request will be processed with the Flex Processing service tier.\n - To opt-in to [Fast mode](https://developers.openai.com/api/docs/guides/fast-mode) at the request level, include the `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat Completions. The response will show `service_tier=priority` regardless of if you specify `service_tier=fast` or `priority` in your request.\n - If set to 'ultrafast', then the request will be processed with the access-controlled Ultrafast Processing service tier. This tier is currently available for `gpt-5.6-sol`; a response served through it will show `service_tier=ultrafast`.\n - When not set, the default behavior is 'auto'.\n\n When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter.\n" }), Schema.Null -]) -export type GroupRoleAssignment = { readonly "object": "group.role"; readonly "group": Group; readonly "role": Role } -export const GroupRoleAssignment = Schema.Struct({ - "object": Schema.Literal("group.role").annotate({ "description": "Always `group.role`." }), - "group": Group, - "role": Role -}).annotate({ "description": "Role assignment linking a group to a role." }) -export type PublicRoleListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "next": string | null -} -export const PublicRoleListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), - "data": Schema.Array(Role).annotate({ "description": "Roles returned in the current page." }), - "has_more": Schema.Boolean.annotate({ "description": "Whether more roles are available when paginating." }), - "next": Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "Cursor to fetch the next page of results, or `null` when there are no additional roles." - }) -}).annotate({ "description": "Paginated list of roles available on an organization or project." }) -export type RunStepDeltaObject = { - readonly "id": string - readonly "object": "thread.run.step.delta" - readonly "delta": { - readonly "step_details"?: { - readonly "type": "message_creation" - readonly "message_creation"?: { readonly "message_id"?: string } - } | { - readonly "type": "tool_calls" - readonly "tool_calls"?: ReadonlyArray< - | RunStepDeltaStepDetailsToolCallsCodeObject - | RunStepDeltaStepDetailsToolCallsFileSearchObject - | RunStepDeltaStepDetailsToolCallsFunctionObject - > - } - } +]).annotate({ "identifier": "BetaServiceTierResponses" }) +export type BetaReasoningModeEnum = string | "standard" | "pro" +export const BetaReasoningModeEnum = Schema.Union([Schema.String, Schema.Literals(["standard", "pro"])]).annotate({ + "identifier": "BetaReasoningModeEnum" +}) +export type BetaReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" | null +export const BetaReasoningEffort = Schema.Union([ + Schema.Literals(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).annotate({ + "description": + "Constrains effort on reasoning for reasoning models. Currently supported\nvalues are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`.\nReducing reasoning effort can result in faster responses and fewer tokens\nused on reasoning in a response. Not all reasoning models support every\nvalue. See the\n[reasoning guide](https://developers.openai.com/api/docs/guides/reasoning)\nfor model-specific support.\n" + }), + Schema.Null +]).annotate({ "identifier": "BetaReasoningEffort" }) +export type BetaMessagePhase = "commentary" | "final_answer" +export const BetaMessagePhase = Schema.Literals(["commentary", "final_answer"]).annotate({ + "description": + "Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`).\nFor models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend\nphase on all assistant messages — dropping it can degrade performance. Not used for user messages.\n", + "identifier": "BetaMessagePhase" +}) +export type BetaAgentTag = { readonly "agent_name": string } +export const BetaAgentTag = Schema.Struct({ + "agent_name": Schema.String.annotate({ "description": "The canonical name of the agent that produced this item." }) +}).annotate({ "identifier": "BetaAgentTag" }) +export type BetaFileCitationBody = { + readonly "type": "file_citation" + readonly "file_id": string + readonly "index": number + readonly "filename": string } -export const RunStepDeltaObject = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The identifier of the run step, which can be referenced in API endpoints." +export const BetaFileCitationBody = Schema.Struct({ + "type": Schema.Literal("file_citation").annotate({ + "description": "The type of the file citation. Always `file_citation`." }), - "object": Schema.Literal("thread.run.step.delta").annotate({ - "description": "The object type, which is always `thread.run.step.delta`." + "file_id": Schema.String.annotate({ "description": "The ID of the file." }), + "index": Schema.Number.annotate({ + "description": "The index in the output text at which to insert the file citation." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "filename": Schema.String.annotate({ "description": "The filename of the file cited." }) +}).annotate({ "title": "File citation", "description": "A citation to a file.", "identifier": "BetaFileCitationBody" }) +export type BetaUrlCitationBody = { + readonly "type": "url_citation" + readonly "url": string + readonly "start_index": number + readonly "end_index": number + readonly "title": string +} +export const BetaUrlCitationBody = Schema.Struct({ + "type": Schema.Literal("url_citation").annotate({ + "description": "The type of the URL citation. Always `url_citation`." }), - "delta": Schema.Struct({ - "step_details": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("message_creation").annotate({ "description": "Always `message_creation`." }), - "message_creation": Schema.optionalKey( - Schema.Struct({ - "message_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the message that was created by this run step." }) - ) - }) - ) - }).annotate({ "title": "Message creation", "description": "The details of the run step." }), - Schema.Struct({ - "type": Schema.Literal("tool_calls").annotate({ "description": "Always `tool_calls`." }), - "tool_calls": Schema.optionalKey( - Schema.Array( - Schema.Union([ - RunStepDeltaStepDetailsToolCallsCodeObject, - RunStepDeltaStepDetailsToolCallsFileSearchObject, - RunStepDeltaStepDetailsToolCallsFunctionObject - ], { mode: "oneOf" }) - ).annotate({ - "description": - "An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `file_search`, or `function`.\n" - }) - ) - }).annotate({ "title": "Tool calls", "description": "The details of the run step." }) - ], { mode: "oneOf" })) - }).annotate({ "description": "The delta containing the fields that have changed on the run step." }) + "url": Schema.String.annotate({ "description": "The URL of the web resource.", "format": "uri" }), + "start_index": Schema.Number.annotate({ + "description": "The index of the first character of the URL citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_index": Schema.Number.annotate({ + "description": "The index of the last character of the URL citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "title": Schema.String.annotate({ "description": "The title of the web resource." }) }).annotate({ - "title": "Run step delta object", - "description": "Represents a run step delta i.e. any changed fields on a run step during streaming.\n" + "title": "URL citation", + "description": "A citation for a web resource used to generate a model response.", + "identifier": "BetaUrlCitationBody" }) -export type CreateSpeechResponseStreamEvent = SpeechAudioDeltaEvent | SpeechAudioDoneEvent -export const CreateSpeechResponseStreamEvent = Schema.Union([SpeechAudioDeltaEvent, SpeechAudioDoneEvent]) -export type ChunkingStrategyRequestParam = { readonly "type": "auto" } | { - readonly "type": "static" - readonly "static": StaticChunkingStrategy +export type BetaContainerFileCitationBody = { + readonly "type": "container_file_citation" + readonly "container_id": string + readonly "file_id": string + readonly "start_index": number + readonly "end_index": number + readonly "filename": string } -export const ChunkingStrategyRequestParam = Schema.Union([ - Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }).annotate({ - "title": "Auto Chunking Strategy", - "description": "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." +export const BetaContainerFileCitationBody = Schema.Struct({ + "type": Schema.Literal("container_file_citation").annotate({ + "description": "The type of the container file citation. Always `container_file_citation`." }), - Schema.Struct({ - "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), - "static": StaticChunkingStrategy - }).annotate({ - "title": "Static Chunking Strategy", - "description": "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }) -], { mode: "oneOf" }) -export type CreateCompletionRequest = { - readonly "model": string | "gpt-3.5-turbo-instruct" | "davinci-002" | "babbage-002" - readonly "prompt": - | string - | ReadonlyArray - | ReadonlyArray - | ReadonlyArray> - | null - readonly "best_of"?: number - readonly "echo"?: boolean | null - readonly "frequency_penalty"?: number - readonly "logit_bias"?: {} - readonly "logprobs"?: number - readonly "max_tokens"?: number - readonly "n"?: number - readonly "presence_penalty"?: number - readonly "seed"?: never - readonly "stop"?: StopConfiguration - readonly "stream"?: boolean | null - readonly "stream_options"?: ChatCompletionStreamOptions - readonly "suffix"?: string | null - readonly "temperature"?: number - readonly "top_p"?: number - readonly "user"?: string + "container_id": Schema.String.annotate({ "description": "The ID of the container file." }), + "file_id": Schema.String.annotate({ "description": "The ID of the file." }), + "start_index": Schema.Number.annotate({ + "description": "The index of the first character of the container file citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_index": Schema.Number.annotate({ + "description": "The index of the last character of the container file citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "filename": Schema.String.annotate({ "description": "The filename of the container file cited." }) +}).annotate({ + "title": "Container file citation", + "description": "A citation for a container file used to generate a model response.", + "identifier": "BetaContainerFileCitationBody" +}) +export type BetaFilePath = { readonly "type": "file_path"; readonly "file_id": string; readonly "index": number } +export const BetaFilePath = Schema.Struct({ + "type": Schema.Literal("file_path").annotate({ "description": "The type of the file path. Always `file_path`.\n" }), + "file_id": Schema.String.annotate({ "description": "The ID of the file.\n" }), + "index": Schema.Number.annotate({ "description": "The index of the file in the list of files.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ "title": "File path", "description": "A path to a file.\n", "identifier": "BetaFilePath" }) +export type BetaTopLogProb = { + readonly "token": string + readonly "logprob": number + readonly "bytes": ReadonlyArray } -export const CreateCompletionRequest = Schema.Struct({ - "model": Schema.Union([Schema.String, Schema.Literals(["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"])]) - .annotate({ - "description": - "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models) for descriptions of them.\n" - }), - "prompt": Schema.Union([ - Schema.Union([ - Schema.String, - Schema.Array(Schema.String), - Schema.Array(Schema.Number.check(Schema.isInt())).check(Schema.isMinLength(1)), - Schema.Array(Schema.Array(Schema.Number.check(Schema.isInt())).check(Schema.isMinLength(1))).check( - Schema.isMinLength(1) - ) - ], { mode: "oneOf" }).annotate({ - "description": - "The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays.\n\nNote that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document.\n" - }), - Schema.Null - ]), - "best_of": Schema.optionalKey( +export const BetaTopLogProb = Schema.Struct({ + "token": Schema.String, + "logprob": Schema.Finite, + "bytes": Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))) +}).annotate({ + "title": "Top log probability", + "description": "The top log probability of a token.", + "identifier": "BetaTopLogProb" +}) +export type BetaRefusalContent = { readonly "type": "refusal"; readonly "refusal": string } +export const BetaRefusalContent = Schema.Struct({ + "type": Schema.Literal("refusal").annotate({ "description": "The type of the refusal. Always `refusal`." }), + "refusal": Schema.String.annotate({ "description": "The refusal explanation from the model." }) +}).annotate({ "title": "Refusal", "description": "A refusal from the model.", "identifier": "BetaRefusalContent" }) +export type BetaVectorStoreFileAttributes = { readonly [x: string]: string | number | boolean } | null +export const BetaVectorStoreFileAttributes = Schema.Union([ + Schema.Record( + Schema.String, Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(20)], { - "description": - "Generates `best_of` completions server-side and returns the \"best\" (the one with the highest log probability per token). Results cannot be streamed.\n\nWhen used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`.\n\n**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\n" - }) - ) - ]) - ), - "echo": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": "Echo back the prompt in addition to the completion\n" - }) + Schema.String.check( + Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" }) + ), + Schema.Finite, + Schema.Boolean + ], { mode: "oneOf" }) + ).annotate({ + "description": + "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard. Keys are strings\nwith a maximum length of 64 characters. Values are strings with a maximum\nlength of 512 characters, booleans, or numbers.\n" + }).check(Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) ), - "frequency_penalty": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(-2), Schema.isLessThanOrEqualTo(2)], { - "description": - "Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\n\n[See more information about frequency and presence penalties.](/docs/guides/text-generation)\n" - }) - ) - ]) + Schema.Null +]).annotate({ "identifier": "BetaVectorStoreFileAttributes" }) +export type BetaClickButtonType = "left" | "right" | "wheel" | "back" | "forward" +export const BetaClickButtonType = Schema.Literals(["left", "right", "wheel", "back", "forward"]).annotate({ + "identifier": "BetaClickButtonType" +}) +export type BetaDoubleClickAction = { + readonly "type": "double_click" + readonly "x": number + readonly "y": number + readonly "keys": ReadonlyArray | null +} +export const BetaDoubleClickAction = Schema.Struct({ + "type": Schema.Literal("double_click").annotate({ + "description": "Specifies the event type. For a double click action, this property is always set to `double_click`." + }), + "x": Schema.Number.annotate({ "description": "The x-coordinate where the double click occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "logit_bias": Schema.optionalKey(Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Modify the likelihood of specified tokens appearing in the completion.\n\nAccepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\n\nAs an example, you can pass `{\"50256\": -100}` to prevent the <|endoftext|> token from being generated.\n" - }) - ])), - "logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(5)], { - "description": - "Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response.\n\nThe maximum value for `logprobs` is 5.\n" - }) - ) - ]) + "y": Schema.Number.annotate({ "description": "The y-coordinate where the double click occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "max_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(0)], { - "description": - "The maximum number of [tokens](/tokenizer) that can be generated in the completion.\n\nThe token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens.\n" - }) - ) - ]) + "keys": Schema.Union([ + Schema.Array(Schema.String).annotate({ "description": "The keys being held while double-clicking." }), + Schema.Null + ]) +}).annotate({ "title": "DoubleClick", "description": "A double click action.", "identifier": "BetaDoubleClickAction" }) +export type BetaCoordParam = { readonly "x": number; readonly "y": number } +export const BetaCoordParam = Schema.Struct({ + "x": Schema.Number.annotate({ "description": "The x-coordinate." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "y": Schema.Number.annotate({ "description": "The y-coordinate." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "Coordinate", + "description": "An x/y coordinate pair, e.g. `{ x: 100, y: 200 }`.", + "identifier": "BetaCoordParam" +}) +export type BetaKeyPressAction = { readonly "type": "keypress"; readonly "keys": ReadonlyArray } +export const BetaKeyPressAction = Schema.Struct({ + "type": Schema.Literal("keypress").annotate({ + "description": "Specifies the event type. For a keypress action, this property is always set to `keypress`." + }), + "keys": Schema.Array( + Schema.String.annotate({ "description": "One of the keys the model is requesting to be pressed." }) + ).annotate({ + "description": + "The combination of keys the model is requesting to be pressed. This is an array of strings, each representing a key." + }) +}).annotate({ + "title": "KeyPress", + "description": "A collection of keypresses the model would like to perform.", + "identifier": "BetaKeyPressAction" +}) +export type BetaMoveParam = { + readonly "type": "move" + readonly "x": number + readonly "y": number + readonly "keys"?: ReadonlyArray | null +} +export const BetaMoveParam = Schema.Struct({ + "type": Schema.Literal("move").annotate({ + "description": "Specifies the event type. For a move action, this property is always set to `move`." + }), + "x": Schema.Number.annotate({ "description": "The x-coordinate to move to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "n": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(128)], { - "description": - "How many completions to generate for each prompt.\n\n**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\n" - }) - ) - ]) + "y": Schema.Number.annotate({ "description": "The y-coordinate to move to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "presence_penalty": Schema.optionalKey( + "keys": Schema.optionalKey( Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(-2), Schema.isLessThanOrEqualTo(2)], { - "description": - "Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\n\n[See more information about frequency and presence penalties.](/docs/guides/text-generation)\n" - }) - ) + Schema.Array(Schema.String).annotate({ "description": "The keys being held while moving the mouse." }), + Schema.Null ]) + ) +}).annotate({ "title": "Move", "description": "A mouse move action.", "identifier": "BetaMoveParam" }) +export type BetaScreenshotParam = { readonly "type": "screenshot" } +export const BetaScreenshotParam = Schema.Struct({ + "type": Schema.Literal("screenshot").annotate({ + "description": "Specifies the event type. For a screenshot action, this property is always set to `screenshot`." + }) +}).annotate({ "title": "Screenshot", "description": "A screenshot action.", "identifier": "BetaScreenshotParam" }) +export type BetaScrollParam = { + readonly "type": "scroll" + readonly "x": number + readonly "y": number + readonly "scroll_x": number + readonly "scroll_y": number + readonly "keys"?: ReadonlyArray | null +} +export const BetaScrollParam = Schema.Struct({ + "type": Schema.Literal("scroll").annotate({ + "description": "Specifies the event type. For a scroll action, this property is always set to `scroll`." + }), + "x": Schema.Number.annotate({ "description": "The x-coordinate where the scroll occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "seed": Schema.optionalKey(Schema.Never), - "stop": Schema.optionalKey(StopConfiguration), - "stream": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": - "Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions).\n" - }) + "y": Schema.Number.annotate({ "description": "The y-coordinate where the scroll occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "stream_options": Schema.optionalKey(ChatCompletionStreamOptions), - "suffix": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "The suffix that comes after a completion of inserted text.\n\nThis parameter is only supported for `gpt-3.5-turbo-instruct`.\n" - }) + "scroll_x": Schema.Number.annotate({ "description": "The horizontal scroll distance." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(2)], { - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n\nWe generally recommend altering this or `top_p` but not both.\n" - }) - ) - ]) + "scroll_y": Schema.Number.annotate({ "description": "The vertical scroll distance." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "top_p": Schema.optionalKey( + "keys": Schema.optionalKey( Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(1)], { - "description": - "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }) - ) + Schema.Array(Schema.String).annotate({ "description": "The keys being held while scrolling." }), + Schema.Null ]) + ) +}).annotate({ "title": "Scroll", "description": "A scroll action.", "identifier": "BetaScrollParam" }) +export type BetaTypeParam = { readonly "type": "type"; readonly "text": string } +export const BetaTypeParam = Schema.Struct({ + "type": Schema.Literal("type").annotate({ + "description": "Specifies the event type. For a type action, this property is always set to `type`." + }), + "text": Schema.String.annotate({ "description": "The text to type." }) +}).annotate({ "title": "Type", "description": "An action to type in text.", "identifier": "BetaTypeParam" }) +export type BetaWaitParam = { readonly "type": "wait" } +export const BetaWaitParam = Schema.Struct({ + "type": Schema.Literal("wait").annotate({ + "description": "Specifies the event type. For a wait action, this property is always set to `wait`." + }) +}).annotate({ "title": "Wait", "description": "A wait action.", "identifier": "BetaWaitParam" }) +export type BetaComputerCallSafetyCheckParam = { + readonly "id": string + readonly "code"?: string | null + readonly "message"?: string | null +} +export const BetaComputerCallSafetyCheckParam = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the pending safety check." }), + "code": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The type of the pending safety check." }), Schema.Null]) ), - "user": Schema.optionalKey( - Schema.String.annotate({ - "description": - "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices#end-user-ids).\n" - }) + "message": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Details about the pending safety check." }), Schema.Null]) ) +}).annotate({ + "description": "A pending safety check for the computer call.", + "identifier": "BetaComputerCallSafetyCheckParam" }) -export type TranscriptTextDoneEvent = { - readonly "type": "transcript.text.done" - readonly "text": string - readonly "logprobs"?: ReadonlyArray< - { readonly "token"?: string; readonly "logprob"?: number; readonly "bytes"?: ReadonlyArray } - > - readonly "usage"?: TranscriptTextUsageTokens +export type Beta_AgentTagParam = { readonly "agent_name": string } +export const Beta_AgentTagParam = Schema.Struct({ + "agent_name": Schema.String.annotate({ "description": "The canonical name of the agent that produced this item." }) +}).annotate({ "description": "The agent that produced this item.", "identifier": "Beta_AgentTagParam" }) +export type BetaComputerScreenshotImage = { + readonly "type": "computer_screenshot" + readonly "image_url"?: string + readonly "file_id"?: string } -export const TranscriptTextDoneEvent = Schema.Struct({ - "type": Schema.Literal("transcript.text.done").annotate({ - "description": "The type of the event. Always `transcript.text.done`.\n" +export const BetaComputerScreenshotImage = Schema.Struct({ + "type": Schema.Literal("computer_screenshot").annotate({ + "description": + "Specifies the event type. For a computer screenshot, this property is \nalways set to `computer_screenshot`.\n" }), - "text": Schema.String.annotate({ "description": "The text that was transcribed.\n" }), - "logprobs": Schema.optionalKey( - Schema.Array(Schema.Struct({ - "token": Schema.optionalKey( - Schema.String.annotate({ "description": "The token that was used to generate the log probability.\n" }) - ), - "logprob": Schema.optionalKey( - Schema.Number.annotate({ "description": "The log probability of the token.\n" }).check(Schema.isFinite()) - ), - "bytes": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "description": "The bytes that were used to generate the log probability.\n" - }) - ) - })).annotate({ - "description": - "The log probabilities of the individual tokens in the transcription. Only included if you [create a transcription](/docs/api-reference/audio/create-transcription) with the `include[]` parameter set to `logprobs`.\n" + "image_url": Schema.optionalKey( + Schema.String.annotate({ "description": "The URL of the screenshot image.", "format": "uri" }) + ), + "file_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of an uploaded file that contains the screenshot." }) + ) +}).annotate({ + "description": "A computer screenshot image used with the computer use tool.\n", + "identifier": "BetaComputerScreenshotImage" +}) +export type BetaFunctionCallItemStatus = "in_progress" | "completed" | "incomplete" +export const BetaFunctionCallItemStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "BetaFunctionCallItemStatus" +}) +export type BetaWebSearchCallStatus = "in_progress" | "searching" | "completed" | "failed" | "incomplete" +export const BetaWebSearchCallStatus = Schema.Literals([ + "in_progress", + "searching", + "completed", + "failed", + "incomplete" +]).annotate({ "identifier": "BetaWebSearchCallStatus" }) +export type BetaWebSearchActionSearch = { + readonly "type": "search" + readonly "query"?: string + readonly "queries"?: ReadonlyArray + readonly "sources"?: ReadonlyArray<{ readonly "type": "url"; readonly "url": string }> +} +export const BetaWebSearchActionSearch = Schema.Struct({ + "type": Schema.Literal("search").annotate({ "description": "The action type.\n" }), + "query": Schema.optionalKey(Schema.String.annotate({ "description": "The search query.\n" })), + "queries": Schema.optionalKey( + Schema.Array(Schema.String.annotate({ "description": "A search query.\n" })).annotate({ + "title": "Search queries", + "description": "The search queries.\n" }) ), - "usage": Schema.optionalKey(TranscriptTextUsageTokens) + "sources": Schema.optionalKey( + Schema.Array( + Schema.Struct({ + "type": Schema.Literal("url").annotate({ "description": "The type of source. Always `url`.\n" }), + "url": Schema.String.annotate({ "description": "The URL of the source.\n", "format": "uri" }) + }).annotate({ "title": "Web search source", "description": "A source used in the search.\n" }) + ).annotate({ "title": "Web search sources", "description": "The sources used in the search.\n" }) + ) }).annotate({ - "description": - "Emitted when the transcription is complete. Contains the complete transcription text. Only emitted when you [create a transcription](/docs/api-reference/audio/create-transcription) with the `Stream` parameter set to `true`." + "title": "Search action", + "description": "Action type \"search\" - Performs a web search query.\n", + "identifier": "BetaWebSearchActionSearch" }) -export type CreateTranscriptionResponseDiarizedJson = { - readonly "task": "transcribe" - readonly "duration": number - readonly "text": string - readonly "segments": ReadonlyArray - readonly "usage"?: { - readonly "type": "tokens" - readonly "input_tokens": number - readonly "input_token_details"?: { readonly "text_tokens"?: number; readonly "audio_tokens"?: number } - readonly "output_tokens": number - readonly "total_tokens": number - } | { readonly "type": "duration"; readonly "seconds": number } +export type BetaWebSearchActionOpenPage = { readonly "type": "open_page"; readonly "url"?: string | null } +export const BetaWebSearchActionOpenPage = Schema.Struct({ + "type": Schema.Literal("open_page").annotate({ "description": "The action type.\n" }), + "url": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "format": "uri" }), Schema.Null]).annotate({ + "description": "The URL opened by the model.\n" + }) + ) +}).annotate({ + "title": "Open page action", + "description": "Action type \"open_page\" - Opens a specific URL from search results.\n", + "identifier": "BetaWebSearchActionOpenPage" +}) +export type BetaWebSearchActionFind = { + readonly "type": "find_in_page" + readonly "url": string + readonly "pattern": string } -export const CreateTranscriptionResponseDiarizedJson = Schema.Struct({ - "task": Schema.Literal("transcribe").annotate({ - "description": "The type of task that was run. Always `transcribe`." - }), - "duration": Schema.Number.annotate({ "description": "Duration of the input audio in seconds.", "format": "double" }) - .check(Schema.isFinite()), - "text": Schema.String.annotate({ "description": "The concatenated transcript text for the entire audio input." }), - "segments": Schema.Array(TranscriptionDiarizedSegment).annotate({ - "description": "Segments of the transcript annotated with timestamps and speaker labels." - }), - "usage": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("tokens").annotate({ - "description": "The type of the usage object. Always `tokens` for this variant." - }), - "input_tokens": Schema.Number.annotate({ "description": "Number of input tokens billed for this request." }) - .check(Schema.isInt()), - "input_token_details": Schema.optionalKey( - Schema.Struct({ - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of text tokens billed for this request." }).check( - Schema.isInt() - ) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Number of audio tokens billed for this request." }).check( - Schema.isInt() - ) - ) - }).annotate({ "description": "Details about the input tokens billed for this request." }) - ), - "output_tokens": Schema.Number.annotate({ "description": "Number of output tokens generated." }).check( - Schema.isInt() - ), - "total_tokens": Schema.Number.annotate({ "description": "Total number of tokens used (input + output)." }).check( - Schema.isInt() - ) - }).annotate({ "title": "Token Usage", "description": "Token or duration usage statistics for the request." }), - Schema.Struct({ - "type": Schema.Literal("duration").annotate({ - "description": "The type of the usage object. Always `duration` for this variant." - }), - "seconds": Schema.Number.annotate({ - "description": "Duration of the input audio in seconds.", - "format": "double" - }).check(Schema.isFinite()) - }).annotate({ "title": "Duration Usage", "description": "Token or duration usage statistics for the request." }) - ], { mode: "oneOf" })) +export const BetaWebSearchActionFind = Schema.Struct({ + "type": Schema.Literal("find_in_page").annotate({ "description": "The action type.\n" }), + "url": Schema.String.annotate({ "description": "The URL of the page searched for the pattern.\n", "format": "uri" }), + "pattern": Schema.String.annotate({ "description": "The pattern or text to search for within the page.\n" }) +}).annotate({ + "title": "Find action", + "description": "Action type \"find_in_page\": Searches for a pattern within a loaded page.\n", + "identifier": "BetaWebSearchActionFind" +}) +export type BetaDirectToolCallCaller = { readonly "type": "direct" } +export const BetaDirectToolCallCaller = Schema.Struct({ "type": Schema.Literal("direct") }).annotate({ + "identifier": "BetaDirectToolCallCaller" +}) +export type BetaProgramToolCallCaller = { readonly "type": "program"; readonly "caller_id": string } +export const BetaProgramToolCallCaller = Schema.Struct({ + "type": Schema.Literal("program"), + "caller_id": Schema.String.annotate({ + "description": "The call ID of the program item that produced this tool call." + }) +}).annotate({ "identifier": "BetaProgramToolCallCaller" }) +export type BetaPromptCacheBreakpointParam = { readonly "mode": "explicit" } +export const BetaPromptCacheBreakpointParam = Schema.Struct({ + "mode": Schema.Literal("explicit").annotate({ "description": "The breakpoint mode. Always `explicit`." }) }).annotate({ + "title": "Prompt cache breakpoint", "description": - "Represents a diarized transcription response returned by the model, including the combined transcript and speaker-segment annotations.\n" + "Marks the exact end of a reusable prompt prefix. The breakpoint inherits its TTL from the request's `prompt_cache_options.ttl`; the boundary is not rounded to a token block.", + "identifier": "BetaPromptCacheBreakpointParam" }) -export type CreateTranslationResponseVerboseJson = { - readonly "language": string - readonly "duration": number - readonly "text": string - readonly "segments"?: ReadonlyArray -} -export const CreateTranslationResponseVerboseJson = Schema.Struct({ - "language": Schema.String.annotate({ "description": "The language of the output translation (always `english`)." }), - "duration": Schema.Number.annotate({ "description": "The duration of the input audio.", "format": "double" }).check( - Schema.isFinite() - ), - "text": Schema.String.annotate({ "description": "The translated text." }), - "segments": Schema.optionalKey( - Schema.Array(TranscriptionSegment).annotate({ - "description": "Segments of the translated text and their corresponding details." - }) +export type BetaDetailEnum = "low" | "high" | "auto" | "original" +export const BetaDetailEnum = Schema.Literals(["low", "high", "auto", "original"]).annotate({ + "identifier": "BetaDetailEnum" +}) +export type BetaFileDetailEnum = "auto" | "low" | "high" +export const BetaFileDetailEnum = Schema.Literals(["auto", "low", "high"]).annotate({ + "identifier": "BetaFileDetailEnum" +}) +export type BetaDirectToolCallCallerParam = { readonly "type": "direct" } +export const BetaDirectToolCallCallerParam = Schema.Struct({ + "type": Schema.Literal("direct").annotate({ "description": "The caller type. Always `direct`." }) +}).annotate({ "identifier": "BetaDirectToolCallCallerParam" }) +export type BetaProgramToolCallCallerParam = { readonly "type": "program"; readonly "caller_id": string } +export const BetaProgramToolCallCallerParam = Schema.Struct({ + "type": Schema.Literal("program").annotate({ "description": "The caller type. Always `program`." }), + "caller_id": Schema.String.annotate({ + "description": "The call ID of the program item that produced this tool call." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ) +}).annotate({ "identifier": "BetaProgramToolCallCallerParam" }) +export type BetaEncryptedContentParam = { readonly "type": "encrypted_content"; readonly "encrypted_content": string } +export const BetaEncryptedContentParam = Schema.Struct({ + "type": Schema.Literal("encrypted_content").annotate({ + "description": "The type of the input item. Always `encrypted_content`." + }), + "encrypted_content": Schema.String.annotate({ "description": "Opaque encrypted content." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) ) +}).annotate({ + "title": "Encrypted content", + "description": "Opaque encrypted content that Responses API decrypts inside trusted model execution.", + "identifier": "BetaEncryptedContentParam" }) -export type CreateTranscriptionResponseVerboseJson = { - readonly "language": string - readonly "duration": number - readonly "text": string - readonly "words"?: ReadonlyArray - readonly "segments"?: ReadonlyArray - readonly "usage"?: TranscriptTextUsageDuration +export type BetaMultiAgentAction1 = + | "spawn_agent" + | "interrupt_agent" + | "list_agents" + | "send_message" + | "followup_task" + | "wait_agent" +export const BetaMultiAgentAction1 = Schema.Literals([ + "spawn_agent", + "interrupt_agent", + "list_agents", + "send_message", + "followup_task", + "wait_agent" +]).annotate({ "identifier": "BetaMultiAgentAction1" }) +export type BetaFileCitationParam = { + readonly "type": "file_citation" + readonly "index": number + readonly "file_id": string + readonly "filename": string } -export const CreateTranscriptionResponseVerboseJson = Schema.Struct({ - "language": Schema.String.annotate({ "description": "The language of the input audio." }), - "duration": Schema.Number.annotate({ "description": "The duration of the input audio.", "format": "double" }).check( - Schema.isFinite() +export const BetaFileCitationParam = Schema.Struct({ + "type": Schema.Literal("file_citation").annotate({ "description": "The citation type. Always `file_citation`." }), + "index": Schema.Number.annotate({ "description": "The index of the file in the list of files." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })), + "file_id": Schema.String.annotate({ "description": "The ID of the file." }), + "filename": Schema.String.annotate({ "description": "The filename of the file cited." }) +}).annotate({ "identifier": "BetaFileCitationParam" }) +export type BetaUrlCitationParam = { + readonly "type": "url_citation" + readonly "start_index": number + readonly "end_index": number + readonly "url": string + readonly "title": string +} +export const BetaUrlCitationParam = Schema.Struct({ + "type": Schema.Literal("url_citation").annotate({ "description": "The citation type. Always `url_citation`." }), + "start_index": Schema.Number.annotate({ + "description": "The index of the first character of the citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) ), - "text": Schema.String.annotate({ "description": "The transcribed text." }), - "words": Schema.optionalKey( - Schema.Array(TranscriptionWord).annotate({ "description": "Extracted words and their corresponding timestamps." }) + "end_index": Schema.Number.annotate({ + "description": "The index of the last character of the citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ), + "url": Schema.String.annotate({ "description": "The URL of the cited resource.", "format": "uri" }), + "title": Schema.String.annotate({ "description": "The title of the cited resource." }) +}).annotate({ "identifier": "BetaUrlCitationParam" }) +export type BetaContainerFileCitationParam = { + readonly "type": "container_file_citation" + readonly "start_index": number + readonly "end_index": number + readonly "container_id": string + readonly "file_id": string + readonly "filename": string +} +export const BetaContainerFileCitationParam = Schema.Struct({ + "type": Schema.Literal("container_file_citation").annotate({ + "description": "The citation type. Always `container_file_citation`." + }), + "start_index": Schema.Number.annotate({ + "description": "The index of the first character of the citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) ), - "segments": Schema.optionalKey( - Schema.Array(TranscriptionSegment).annotate({ - "description": "Segments of the transcribed text and their corresponding details." - }) + "end_index": Schema.Number.annotate({ + "description": "The index of the last character of the citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) ), - "usage": Schema.optionalKey(TranscriptTextUsageDuration) + "container_id": Schema.String.annotate({ "description": "The ID of the container." }), + "file_id": Schema.String.annotate({ "description": "The ID of the container file." }), + "filename": Schema.String.annotate({ "description": "The filename of the container file cited." }) +}).annotate({ "identifier": "BetaContainerFileCitationParam" }) +export type BetaSummaryTextContent = { readonly "type": "summary_text"; readonly "text": string } +export const BetaSummaryTextContent = Schema.Struct({ + "type": Schema.Literal("summary_text").annotate({ "description": "The type of the object. Always `summary_text`." }), + "text": Schema.String.annotate({ "description": "A summary of the reasoning output from the model so far." }) }).annotate({ - "description": "Represents a verbose json transcription response returned by model, based on the provided input." + "title": "Summary text", + "description": "A summary text from the model.", + "identifier": "BetaSummaryTextContent" }) -export type UsageTimeBucket = { - readonly "object": "bucket" - readonly "start_time": number - readonly "end_time": number - readonly "results": ReadonlyArray< - | UsageCompletionsResult - | UsageEmbeddingsResult - | UsageModerationsResult - | UsageImagesResult - | UsageAudioSpeechesResult - | UsageAudioTranscriptionsResult - | UsageVectorStoresResult - | UsageCodeInterpreterSessionsResult - | UsageFileSearchCallsResult - | UsageWebSearchCallsResult - | CostsResult - > +export type BetaReasoningTextContent = { readonly "type": "reasoning_text"; readonly "text": string } +export const BetaReasoningTextContent = Schema.Struct({ + "type": Schema.Literal("reasoning_text").annotate({ + "description": "The type of the reasoning text. Always `reasoning_text`." + }), + "text": Schema.String.annotate({ "description": "The reasoning text from the model." }) +}).annotate({ + "title": "Reasoning text", + "description": "Reasoning text from the model.", + "identifier": "BetaReasoningTextContent" +}) +export type BetaImageBackground = "transparent" | "opaque" | "auto" +export const BetaImageBackground = Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "identifier": "BetaImageBackground" +}) +export type BetaImageOutputFormat = "png" | "webp" | "jpeg" +export const BetaImageOutputFormat = Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "identifier": "BetaImageOutputFormat" +}) +export type BetaCodeInterpreterOutputLogs = { readonly "type": "logs"; readonly "logs": string } +export const BetaCodeInterpreterOutputLogs = Schema.Struct({ + "type": Schema.Literal("logs").annotate({ "description": "The type of the output. Always `logs`." }), + "logs": Schema.String.annotate({ "description": "The logs output from the code interpreter." }) +}).annotate({ + "title": "Code interpreter output logs", + "description": "The logs output from the code interpreter.", + "identifier": "BetaCodeInterpreterOutputLogs" +}) +export type BetaCodeInterpreterOutputImage = { readonly "type": "image"; readonly "url": string } +export const BetaCodeInterpreterOutputImage = Schema.Struct({ + "type": Schema.Literal("image").annotate({ "description": "The type of the output. Always `image`." }), + "url": Schema.String.annotate({ + "description": "The URL of the image output from the code interpreter.", + "format": "uri" + }) +}).annotate({ + "title": "Code interpreter output image", + "description": "The image output from the code interpreter.", + "identifier": "BetaCodeInterpreterOutputImage" +}) +export type BetaLocalShellExecAction = { + readonly "type": "exec" + readonly "command": ReadonlyArray + readonly "timeout_ms"?: number | null + readonly "working_directory"?: string | null + readonly "env": { readonly [x: string]: string } + readonly "user"?: string | null } -export const UsageTimeBucket = Schema.Struct({ - "object": Schema.Literal("bucket"), - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.Number.check(Schema.isInt()), - "results": Schema.Array( +export const BetaLocalShellExecAction = Schema.Struct({ + "type": Schema.Literal("exec").annotate({ "description": "The type of the local shell action. Always `exec`." }), + "command": Schema.Array(Schema.String).annotate({ "description": "The command to run." }), + "timeout_ms": Schema.optionalKey( Schema.Union([ - UsageCompletionsResult, - UsageEmbeddingsResult, - UsageModerationsResult, - UsageImagesResult, - UsageAudioSpeechesResult, - UsageAudioTranscriptionsResult, - UsageVectorStoresResult, - UsageCodeInterpreterSessionsResult, - UsageFileSearchCallsResult, - UsageWebSearchCallsResult, - CostsResult - ], { mode: "oneOf" }) + Schema.Number.annotate({ "description": "Optional timeout in milliseconds for the command." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null + ]) + ), + "working_directory": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Optional working directory to run the command in." }), + Schema.Null + ]) + ), + "env": Schema.Record(Schema.String, Schema.String).annotate({ + "description": "Environment variables to set for the command." + }), + "user": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Optional user to run the command as." }), Schema.Null]) ) +}).annotate({ + "title": "Local shell exec action", + "description": "Execute a shell command on the server.", + "identifier": "BetaLocalShellExecAction" }) -export type UserListResponse = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const UserListResponse = Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array(User), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean -}) -export type UserRoleAssignment = { readonly "object": "user.role"; readonly "user": User; readonly "role": Role } -export const UserRoleAssignment = Schema.Struct({ - "object": Schema.Literal("user.role").annotate({ "description": "Always `user.role`." }), - "user": User, - "role": Role -}).annotate({ "description": "Role assignment linking a user to a role." }) -export type CreateTranscriptionRequest = { - readonly "file": string - readonly "model": - | string - | "whisper-1" - | "gpt-4o-transcribe" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe-diarize" - readonly "language"?: string - readonly "prompt"?: string - readonly "response_format"?: AudioResponseFormat - readonly "temperature"?: number - readonly "include"?: ReadonlyArray - readonly "timestamp_granularities"?: ReadonlyArray<"word" | "segment"> - readonly "stream"?: boolean | null - readonly "chunking_strategy"?: "auto" | VadConfig | null - readonly "known_speaker_names"?: ReadonlyArray - readonly "known_speaker_references"?: ReadonlyArray +export type BetaFunctionShellActionParam = { + readonly "commands": ReadonlyArray + readonly "timeout_ms"?: number | null + readonly "max_output_length"?: number | null } -export const CreateTranscriptionRequest = Schema.Struct({ - "file": Schema.String.annotate({ - "description": - "The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.\n", - "format": "binary" +export const BetaFunctionShellActionParam = Schema.Struct({ + "commands": Schema.Array(Schema.String).annotate({ + "description": "Ordered shell commands for the execution environment to run." }), - "model": Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-transcribe", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe-diarize" + "timeout_ms": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "Maximum wall-clock time in milliseconds to allow the shell commands to run." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null ]) - ]).annotate({ - "description": - "ID of the model to use. The options are `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`.\n" - }), - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency.\n" - }) ), - "prompt": Schema.optionalKey( - Schema.String.annotate({ - "description": - "An optional text to guide the model's style or continue a previous audio segment. The [prompt](/docs/guides/speech-to-text#prompting) should match the audio language. This field is not supported when using `gpt-4o-transcribe-diarize`.\n" - }) - ), - "response_format": Schema.optionalKey(AudioResponseFormat), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit.\n" - }).check(Schema.isFinite()) - ), - "include": Schema.optionalKey( - Schema.Array(TranscriptionInclude).annotate({ - "description": - "Additional information to include in the transcription response.\n`logprobs` will return the log probabilities of the tokens in the\nresponse to understand the model's confidence in the transcription.\n`logprobs` only works with response_format set to `json` and only with\nthe models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`.\n" - }) - ), - "timestamp_granularities": Schema.optionalKey( - Schema.Array(Schema.Literals(["word", "segment"])).annotate({ - "description": - "The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency.\nThis option is not available for `gpt-4o-transcribe-diarize`.\n" - }) - ), - "stream": Schema.optionalKey(Schema.Union([ - Schema.Boolean.annotate({ - "description": - "If set to true, the model response data will be streamed to the client\nas it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).\nSee the [Streaming section of the Speech-to-Text guide](/docs/guides/speech-to-text?lang=curl#streaming-transcriptions)\nfor more information.\n\nNote: Streaming is not supported for the `whisper-1` model and will be ignored.\n" - }), - Schema.Null - ])), - "chunking_strategy": Schema.optionalKey( + "max_output_length": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.Literal("auto").annotate({ - "description": "Automatically set chunking parameters based on the audio. Must be set to `\"auto\"`.\n" - }), - VadConfig - ]).annotate({ - "description": - "Controls how the audio is cut into chunks. When set to `\"auto\"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. Required when using `gpt-4o-transcribe-diarize` for inputs longer than 30 seconds. " - }), + Schema.Number.annotate({ + "description": "Maximum number of UTF-8 characters to capture from combined stdout and stderr output." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) + ) +}).annotate({ + "title": "Shell action", + "description": "Commands and limits describing how to run the shell tool call.", + "identifier": "BetaFunctionShellActionParam" +}) +export type BetaFunctionShellCallItemStatus = "in_progress" | "completed" | "incomplete" +export const BetaFunctionShellCallItemStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "title": "Shell call status", + "description": "Status values reported for shell tool calls.", + "identifier": "BetaFunctionShellCallItemStatus" +}) +export type BetaFunctionShellCallOutputTimeoutOutcomeParam = { readonly "type": "timeout" } +export const BetaFunctionShellCallOutputTimeoutOutcomeParam = Schema.Struct({ + "type": Schema.Literal("timeout").annotate({ "description": "The outcome type. Always `timeout`." }) +}).annotate({ + "title": "Shell call timeout outcome", + "description": "Indicates that the shell call exceeded its configured time limit.", + "identifier": "BetaFunctionShellCallOutputTimeoutOutcomeParam" +}) +export type BetaFunctionShellCallOutputExitOutcomeParam = { readonly "type": "exit"; readonly "exit_code": number } +export const BetaFunctionShellCallOutputExitOutcomeParam = Schema.Struct({ + "type": Schema.Literal("exit").annotate({ "description": "The outcome type. Always `exit`." }), + "exit_code": Schema.Number.annotate({ "description": "The exit code returned by the shell process." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "Shell call exit outcome", + "description": "Indicates that the shell commands finished and returned an exit code.", + "identifier": "BetaFunctionShellCallOutputExitOutcomeParam" +}) +export type BetaApplyPatchCallStatusParam = "in_progress" | "completed" +export const BetaApplyPatchCallStatusParam = Schema.Literals(["in_progress", "completed"]).annotate({ + "title": "Apply patch call status", + "description": "Status values reported for apply_patch tool calls.", + "identifier": "BetaApplyPatchCallStatusParam" +}) +export type BetaApplyPatchCreateFileOperationParam = { + readonly "type": "create_file" + readonly "path": string + readonly "diff": string +} +export const BetaApplyPatchCreateFileOperationParam = Schema.Struct({ + "type": Schema.Literal("create_file").annotate({ "description": "The operation type. Always `create_file`." }), + "path": Schema.String.annotate({ "description": "Path of the file to create relative to the workspace root." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) ), - "known_speaker_names": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "Optional list of speaker names that correspond to the audio samples provided in `known_speaker_references[]`. Each entry should be a short identifier (for example `customer` or `agent`). Up to 4 speakers are supported.\n" - }).check(Schema.isMaxLength(4)) - ), - "known_speaker_references": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "Optional list of audio samples (as [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)) that contain known speaker references matching `known_speaker_names[]`. Each sample must be between 2 and 10 seconds, and can use any of the same input audio formats supported by `file`.\n" - }).check(Schema.isMaxLength(4)) + "diff": Schema.String.annotate({ "description": "Unified diff content to apply when creating the file." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) ) +}).annotate({ + "title": "Apply patch create file operation", + "description": "Instruction for creating a new file via the apply_patch tool.", + "identifier": "BetaApplyPatchCreateFileOperationParam" }) -export type CreateVectorStoreRequest = { - readonly "file_ids"?: ReadonlyArray - readonly "name"?: string - readonly "description"?: string - readonly "expires_after"?: VectorStoreExpirationAfter - readonly "chunking_strategy"?: { readonly "type": "auto" } | { - readonly "type": "static" - readonly "static": StaticChunkingStrategy - } - readonly "metadata"?: Metadata +export type BetaApplyPatchDeleteFileOperationParam = { readonly "type": "delete_file"; readonly "path": string } +export const BetaApplyPatchDeleteFileOperationParam = Schema.Struct({ + "type": Schema.Literal("delete_file").annotate({ "description": "The operation type. Always `delete_file`." }), + "path": Schema.String.annotate({ "description": "Path of the file to delete relative to the workspace root." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ) +}).annotate({ + "title": "Apply patch delete file operation", + "description": "Instruction for deleting an existing file via the apply_patch tool.", + "identifier": "BetaApplyPatchDeleteFileOperationParam" +}) +export type BetaApplyPatchUpdateFileOperationParam = { + readonly "type": "update_file" + readonly "path": string + readonly "diff": string } -export const CreateVectorStoreRequest = Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [File](/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files." - }).check(Schema.isMaxLength(500)) +export const BetaApplyPatchUpdateFileOperationParam = Schema.Struct({ + "type": Schema.Literal("update_file").annotate({ "description": "The operation type. Always `update_file`." }), + "path": Schema.String.annotate({ "description": "Path of the file to update relative to the workspace root." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) ), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the vector store." })), + "diff": Schema.String.annotate({ "description": "Unified diff content to apply to the existing file." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ) +}).annotate({ + "title": "Apply patch update file operation", + "description": "Instruction for updating an existing file via the apply_patch tool.", + "identifier": "BetaApplyPatchUpdateFileOperationParam" +}) +export type BetaApplyPatchCallOutputStatusParam = "completed" | "failed" +export const BetaApplyPatchCallOutputStatusParam = Schema.Literals(["completed", "failed"]).annotate({ + "title": "Apply patch call output status", + "description": "Outcome values reported for apply_patch tool call outputs.", + "identifier": "BetaApplyPatchCallOutputStatusParam" +}) +export type BetaMCPListToolsTool = { + readonly "name": string + readonly "description"?: string | null + readonly "input_schema": { readonly [x: string]: Schema.Json } + readonly "annotations"?: { readonly [x: string]: Schema.Json } | null +} +export const BetaMCPListToolsTool = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the tool.\n" }), "description": Schema.optionalKey( - Schema.String.annotate({ - "description": "A description for the vector store. Can be used to describe the vector store's purpose." - }) + Schema.Union([Schema.String.annotate({ "description": "The description of the tool.\n" }), Schema.Null]) ), - "expires_after": Schema.optionalKey(VectorStoreExpirationAfter), - "chunking_strategy": Schema.optionalKey( + "input_schema": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The JSON schema describing the tool's input.\n" + }), + "annotations": Schema.optionalKey( Schema.Union([ - Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }).annotate({ - "title": "Auto Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty." + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Additional annotations about the tool.\n" }), - Schema.Struct({ - "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), - "static": StaticChunkingStrategy - }).annotate({ - "title": "Static Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty." - }) - ], { mode: "oneOf" }) - ), - "metadata": Schema.optionalKey(Metadata) + Schema.Null + ]) + ) +}).annotate({ + "title": "MCP list tools tool", + "description": "A tool available on an MCP server.\n", + "identifier": "BetaMCPListToolsTool" }) -export type VectorStoreObject = { - readonly "id": string - readonly "object": "vector_store" - readonly "created_at": number - readonly "name": string - readonly "usage_bytes": number - readonly "file_counts": { - readonly "in_progress": number - readonly "completed": number - readonly "failed": number - readonly "cancelled": number - readonly "total": number - } - readonly "status": "expired" | "in_progress" | "completed" - readonly "expires_after"?: VectorStoreExpirationAfter - readonly "expires_at"?: number | null - readonly "last_active_at": number | null - readonly "metadata": Metadata +export type BetaMCPProtocolError = { + readonly "type": "mcp_protocol_error" + readonly "code": number + readonly "message": string } -export const VectorStoreObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), - "object": Schema.Literal("vector_store").annotate({ - "description": "The object type, which is always `vector_store`." - }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the vector store was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "name": Schema.String.annotate({ "description": "The name of the vector store." }), - "usage_bytes": Schema.Number.annotate({ - "description": "The total number of bytes used by the files in the vector store." - }).check(Schema.isInt()), - "file_counts": Schema.Struct({ - "in_progress": Schema.Number.annotate({ "description": "The number of files that are currently being processed." }) - .check(Schema.isInt()), - "completed": Schema.Number.annotate({ "description": "The number of files that have been successfully processed." }) - .check(Schema.isInt()), - "failed": Schema.Number.annotate({ "description": "The number of files that have failed to process." }).check( - Schema.isInt() - ), - "cancelled": Schema.Number.annotate({ "description": "The number of files that were cancelled." }).check( - Schema.isInt() - ), - "total": Schema.Number.annotate({ "description": "The total number of files." }).check(Schema.isInt()) - }), - "status": Schema.Literals(["expired", "in_progress", "completed"]).annotate({ - "description": - "The status of the vector store, which can be either `expired`, `in_progress`, or `completed`. A status of `completed` indicates that the vector store is ready for use." +export const BetaMCPProtocolError = Schema.Struct({ + "type": Schema.Literal("mcp_protocol_error"), + "code": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "message": Schema.String +}).annotate({ "identifier": "BetaMCPProtocolError" }) +export type BetaMCPToolExecutionError = { readonly "type": "mcp_tool_execution_error"; readonly "content": Schema.Json } +export const BetaMCPToolExecutionError = Schema.Struct({ + "type": Schema.Literal("mcp_tool_execution_error"), + "content": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ "identifier": "BetaMCPToolExecutionError" }) +export type BetaHTTPError = { readonly "type": "http_error"; readonly "code": number; readonly "message": string } +export const BetaHTTPError = Schema.Struct({ + "type": Schema.Literal("http_error"), + "code": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "message": Schema.String +}).annotate({ "identifier": "BetaHTTPError" }) +export type BetaMCPToolCallStatus = "in_progress" | "completed" | "incomplete" | "calling" | "failed" +export const BetaMCPToolCallStatus = Schema.Literals(["in_progress", "completed", "incomplete", "calling", "failed"]) + .annotate({ "identifier": "BetaMCPToolCallStatus" }) +export type BetaProgramOutputItemStatus = "completed" | "incomplete" +export const BetaProgramOutputItemStatus = Schema.Literals(["completed", "incomplete"]).annotate({ + "identifier": "BetaProgramOutputItemStatus" +}) +export type BetaIncludeEnum = + | "file_search_call.results" + | "web_search_call.results" + | "web_search_call.action.sources" + | "message.input_image.image_url" + | "computer_call_output.output.image_url" + | "code_interpreter_call.outputs" + | "reasoning.encrypted_content" + | "message.output_text.logprobs" +export const BetaIncludeEnum = Schema.Literals([ + "file_search_call.results", + "web_search_call.results", + "web_search_call.action.sources", + "message.input_image.image_url", + "computer_call_output.output.image_url", + "code_interpreter_call.outputs", + "reasoning.encrypted_content", + "message.output_text.logprobs" +]).annotate({ + "description": + "Specify additional output data to include in the model response. Currently supported values are:\n- `web_search_call.results`: Include the search results of the web search tool call.\n- `web_search_call.action.sources`: Include the sources of the web search tool call.\n- `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items.\n- `computer_call_output.output.image_url`: Include image urls from the computer call output.\n- `file_search_call.results`: Include the search results of the file search tool call.\n- `message.input_image.image_url`: Include image urls from the input message.\n- `message.output_text.logprobs`: Include logprobs with assistant messages.\n- `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program).", + "identifier": "BetaIncludeEnum" +}) +export type BetaModerationMode = "score" | "block" +export const BetaModerationMode = Schema.Literals(["score", "block"]).annotate({ "identifier": "BetaModerationMode" }) +export type BetaResponseStreamOptions = { readonly "include_obfuscation"?: boolean } | null +export const BetaResponseStreamOptions = Schema.Union([ + Schema.Struct({ + "include_obfuscation": Schema.optionalKey(Schema.Boolean.annotate({ + "description": + "When true, stream obfuscation will be enabled. Stream obfuscation adds\nrandom characters to an `obfuscation` field on streaming delta events to\nnormalize payload sizes as a mitigation to certain side-channel attacks.\nThese obfuscation fields are included by default, but add a small amount\nof overhead to the data stream. You can set `include_obfuscation` to\nfalse to optimize for bandwidth if you trust the network links between\nyour application and the OpenAI API.\n" + })) + }).annotate({ "description": "Options for streaming responses. Only set this when you set `stream: true`.\n" }), + Schema.Null +]).annotate({ "identifier": "BetaResponseStreamOptions" }) +export type BetaConversationParam_2 = { readonly "id": string } +export const BetaConversationParam_2 = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the conversation." }) +}).annotate({ + "title": "Conversation object", + "description": "The conversation that this response belongs to.", + "identifier": "BetaConversationParam-2" +}) +export type BetaContextManagementParam = { readonly "type": string; readonly "compact_threshold"?: number | null } +export const BetaContextManagementParam = Schema.Struct({ + "type": Schema.String.annotate({ + "description": "The context management entry type. Currently only 'compaction' is supported." }), - "expires_after": Schema.optionalKey(VectorStoreExpirationAfter), - "expires_at": Schema.optionalKey( + "compact_threshold": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the vector store will expire.", - "format": "unixtime" - }).check(Schema.isInt()), + "description": "Token threshold at which compaction should be triggered for this entry." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1000).annotate({ "expected": "a value greater than or equal to 1000" }) + ), Schema.Null ]) - ), - "last_active_at": Schema.Union([ + ) +}).annotate({ "identifier": "BetaContextManagementParam" }) +export type BetaMultiAgentParam = { readonly "enabled": boolean; readonly "max_concurrent_subagents"?: number } +export const BetaMultiAgentParam = Schema.Struct({ + "enabled": Schema.Boolean.annotate({ + "description": "Whether to enable server-hosted multi-agent execution for this response." + }), + "max_concurrent_subagents": Schema.optionalKey( Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the vector store was last active.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "metadata": Metadata + "description": + "`max_concurrent_subagents` sets the maximum number of subagents that can be active simultaneously across the entire agent tree. It includes all descendants—children, grandchildren, and deeper subagents—but excludes the root agent.\nThe API does not impose a fixed upper bound on this setting. The default is `3`, which is recommended for most workloads. Multi-agent runs also have no fixed limit on tree depth or the total number of subagents created during a run." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ) + ) }).annotate({ - "title": "Vector store", - "description": "A vector store is a collection of processed files can be used by the `file_search` tool." + "description": "Configuration for server-hosted multi-agent execution.", + "identifier": "BetaMultiAgentParam" }) -export type FileSearchToolCall = { - readonly "id": string - readonly "type": "file_search_call" - readonly "status": "in_progress" | "searching" | "completed" | "incomplete" | "failed" - readonly "queries": ReadonlyArray - readonly "results"?: - | ReadonlyArray< - { - readonly "file_id"?: string - readonly "text"?: string - readonly "filename"?: string - readonly "attributes"?: VectorStoreFileAttributes - readonly "score"?: number - } - > - | null -} -export const FileSearchToolCall = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique ID of the file search tool call.\n" }), - "type": Schema.Literal("file_search_call").annotate({ - "description": "The type of the file search tool call. Always `file_search_call`.\n" - }), - "status": Schema.Literals(["in_progress", "searching", "completed", "incomplete", "failed"]).annotate({ - "description": - "The status of the file search tool call. One of `in_progress`,\n`searching`, `incomplete` or `failed`,\n" +export type BetaResponseErrorCode = + | "server_error" + | "rate_limit_exceeded" + | "invalid_prompt" + | "data_residency_mismatch" + | "bio_policy" + | "misalignment_policy_violation" + | "vector_store_timeout" + | "invalid_image" + | "invalid_image_format" + | "invalid_base64_image" + | "invalid_image_url" + | "image_too_large" + | "image_too_small" + | "image_parse_error" + | "image_content_policy_violation" + | "invalid_image_mode" + | "image_file_too_large" + | "unsupported_image_media_type" + | "empty_image_file" + | "failed_to_download_image" + | "image_file_not_found" +export const BetaResponseErrorCode = Schema.Literals([ + "server_error", + "rate_limit_exceeded", + "invalid_prompt", + "data_residency_mismatch", + "bio_policy", + "misalignment_policy_violation", + "vector_store_timeout", + "invalid_image", + "invalid_image_format", + "invalid_base64_image", + "invalid_image_url", + "image_too_large", + "image_too_small", + "image_parse_error", + "image_content_policy_violation", + "invalid_image_mode", + "image_file_too_large", + "unsupported_image_media_type", + "empty_image_file", + "failed_to_download_image", + "image_file_not_found" +]).annotate({ "description": "The error code for the response.\n", "identifier": "BetaResponseErrorCode" }) +export type Beta_MisalignmentErrorType = + | string + | "potentially_unintended_data_transfer" + | "potentially_unintended_data_access" + | "potentially_unintended_destructive_activity" + | "other" +export const Beta_MisalignmentErrorType = Schema.Union([ + Schema.String, + Schema.Literals([ + "potentially_unintended_data_transfer", + "potentially_unintended_data_access", + "potentially_unintended_destructive_activity", + "other" + ]) +]).annotate({ "identifier": "Beta_MisalignmentErrorType" }) +export type Beta_MisalignmentSteer = { readonly "message": string } +export const Beta_MisalignmentSteer = Schema.Struct({ + "message": Schema.String.annotate({ "description": "The public continuation instruction." }) +}).annotate({ "identifier": "Beta_MisalignmentSteer" }) +export type BetaTextContent = { readonly "type": "text"; readonly "text": string } +export const BetaTextContent = Schema.Struct({ "type": Schema.Literal("text"), "text": Schema.String }).annotate({ + "title": "Text Content", + "description": "A text content.", + "identifier": "BetaTextContent" +}) +export type BetaEncryptedContent = { readonly "type": "encrypted_content"; readonly "encrypted_content": string } +export const BetaEncryptedContent = Schema.Struct({ + "type": Schema.Literal("encrypted_content").annotate({ + "description": "The type of the input item. Always `encrypted_content`." }), - "queries": Schema.Array(Schema.String).annotate({ "description": "The queries used to search for files.\n" }), - "results": Schema.optionalKey(Schema.Union([ - Schema.Array(Schema.Struct({ - "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the file.\n" })), - "text": Schema.optionalKey( - Schema.String.annotate({ "description": "The text that was retrieved from the file.\n" }) - ), - "filename": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the file.\n" })), - "attributes": Schema.optionalKey(VectorStoreFileAttributes), - "score": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The relevance score of the file - a value between 0 and 1.\n", - "format": "float" - }).check(Schema.isFinite()) - ) - })).annotate({ "description": "The results of the file search tool call.\n" }), - Schema.Null - ])) + "encrypted_content": Schema.String.annotate({ "description": "Opaque encrypted content." }) }).annotate({ - "title": "File search tool call", - "description": - "The results of a file search tool call. See the\n[file search guide](/docs/guides/tools-file-search) for more information.\n" + "title": "Encrypted content", + "description": "Opaque encrypted content that Responses API decrypts inside trusted model execution.", + "identifier": "BetaEncryptedContent" }) -export type UpdateVectorStoreFileAttributesRequest = { readonly "attributes": VectorStoreFileAttributes } -export const UpdateVectorStoreFileAttributesRequest = Schema.Struct({ "attributes": VectorStoreFileAttributes }) -export type VectorStoreFileObject = { - readonly "id": string - readonly "object": "vector_store.file" - readonly "usage_bytes": number - readonly "created_at": number - readonly "vector_store_id": string - readonly "status": "in_progress" | "completed" | "cancelled" | "failed" - readonly "last_error": { - readonly "code": "server_error" | "unsupported_file" | "invalid_file" - readonly "message": string - } | null - readonly "chunking_strategy"?: { readonly "type": "static"; readonly "static": StaticChunkingStrategy } | { - readonly "type": "other" - } - readonly "attributes"?: VectorStoreFileAttributes +export type BetaMultiAgentAction = + | "spawn_agent" + | "interrupt_agent" + | "list_agents" + | "send_message" + | "followup_task" + | "wait_agent" +export const BetaMultiAgentAction = Schema.Literals([ + "spawn_agent", + "interrupt_agent", + "list_agents", + "send_message", + "followup_task", + "wait_agent" +]).annotate({ "identifier": "BetaMultiAgentAction" }) +export type BetaProgramOutputStatus = "completed" | "incomplete" +export const BetaProgramOutputStatus = Schema.Literals(["completed", "incomplete"]).annotate({ + "identifier": "BetaProgramOutputStatus" +}) +export type BetaFunctionCallStatus = "in_progress" | "completed" | "incomplete" +export const BetaFunctionCallStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "BetaFunctionCallStatus" +}) +export type BetaFunctionCallOutputStatusEnum = "in_progress" | "completed" | "incomplete" +export const BetaFunctionCallOutputStatusEnum = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "BetaFunctionCallOutputStatusEnum" +}) +export type BetaMessageRole = + | "unknown" + | "user" + | "assistant" + | "system" + | "critic" + | "discriminator" + | "developer" + | "tool" +export const BetaMessageRole = Schema.Literals([ + "unknown", + "user", + "assistant", + "system", + "critic", + "discriminator", + "developer", + "tool" +]).annotate({ "identifier": "BetaMessageRole" }) +export type BetaFunctionShellAction = { + readonly "commands": ReadonlyArray + readonly "timeout_ms": number | null + readonly "max_output_length": number | null } -export const VectorStoreFileObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), - "object": Schema.Literal("vector_store.file").annotate({ - "description": "The object type, which is always `vector_store.file`." - }), - "usage_bytes": Schema.Number.annotate({ - "description": "The total vector store usage in bytes. Note that this may be different from the original file size." - }).check(Schema.isInt()), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the vector store file was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "vector_store_id": Schema.String.annotate({ - "description": - "The ID of the [vector store](/docs/api-reference/vector-stores/object) that the [File](/docs/api-reference/files) is attached to." - }), - "status": Schema.Literals(["in_progress", "completed", "cancelled", "failed"]).annotate({ - "description": - "The status of the vector store file, which can be either `in_progress`, `completed`, `cancelled`, or `failed`. The status `completed` indicates that the vector store file is ready for use." - }), - "last_error": Schema.Union([ - Schema.Struct({ - "code": Schema.Literals(["server_error", "unsupported_file", "invalid_file"]).annotate({ - "description": "One of `server_error`, `unsupported_file`, or `invalid_file`." - }), - "message": Schema.String.annotate({ "description": "A human-readable description of the error." }) - }).annotate({ - "description": "The last error associated with this vector store file. Will be `null` if there are no errors." - }), +export const BetaFunctionShellAction = Schema.Struct({ + "commands": Schema.Array(Schema.String.annotate({ "description": "A list of commands to run." })), + "timeout_ms": Schema.Union([ + Schema.Number.annotate({ "description": "Optional timeout in milliseconds for the commands." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), Schema.Null ]), - "chunking_strategy": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), - "static": StaticChunkingStrategy - }).annotate({ "title": "Static Chunking Strategy", "description": "The strategy used to chunk the file." }), - Schema.Struct({ "type": Schema.Literal("other").annotate({ "description": "Always `other`." }) }).annotate({ - "title": "Other Chunking Strategy", - "description": "The strategy used to chunk the file." - }) - ], { mode: "oneOf" }) - ), - "attributes": Schema.optionalKey(VectorStoreFileAttributes) -}).annotate({ "title": "Vector store files", "description": "A list of files attached to a vector store." }) -export type VectorStoreSearchResultItem = { - readonly "file_id": string - readonly "filename": string - readonly "score": number - readonly "attributes": VectorStoreFileAttributes - readonly "content": ReadonlyArray -} -export const VectorStoreSearchResultItem = Schema.Struct({ - "file_id": Schema.String.annotate({ "description": "The ID of the vector store file." }), - "filename": Schema.String.annotate({ "description": "The name of the vector store file." }), - "score": Schema.Number.annotate({ "description": "The similarity score for the result." }).check(Schema.isFinite()) - .check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - "attributes": VectorStoreFileAttributes, - "content": Schema.Array(VectorStoreSearchResultContentObject).annotate({ - "description": "Content chunks from the file." - }) + "max_output_length": Schema.Union([ + Schema.Number.annotate({ "description": "Optional maximum number of characters to return from each command." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) +}).annotate({ + "title": "Shell exec action", + "description": "Execute a shell command.", + "identifier": "BetaFunctionShellAction" }) -export type VoiceConsentListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean +export type BetaFunctionShellCallStatus = "in_progress" | "completed" | "incomplete" +export const BetaFunctionShellCallStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "BetaFunctionShellCallStatus" +}) +export type BetaLocalEnvironmentResource = { readonly "type": "local" } +export const BetaLocalEnvironmentResource = Schema.Struct({ + "type": Schema.Literal("local").annotate({ "description": "The environment type. Always `local`." }) +}).annotate({ + "title": "Local Environment", + "description": "Represents the use of a local environment to perform shell actions.", + "identifier": "BetaLocalEnvironmentResource" +}) +export type BetaContainerReferenceResource = { readonly "type": "container_reference"; readonly "container_id": string } +export const BetaContainerReferenceResource = Schema.Struct({ + "type": Schema.Literal("container_reference").annotate({ + "description": "The environment type. Always `container_reference`." + }), + "container_id": Schema.String +}).annotate({ + "title": "Container Reference", + "description": "Represents a container created with /v1/containers.", + "identifier": "BetaContainerReferenceResource" +}) +export type BetaFunctionShellCallOutputStatusEnum = "in_progress" | "completed" | "incomplete" +export const BetaFunctionShellCallOutputStatusEnum = Schema.Literals(["in_progress", "completed", "incomplete"]) + .annotate({ "identifier": "BetaFunctionShellCallOutputStatusEnum" }) +export type BetaFunctionShellCallOutputTimeoutOutcome = { readonly "type": "timeout" } +export const BetaFunctionShellCallOutputTimeoutOutcome = Schema.Struct({ + "type": Schema.Literal("timeout").annotate({ "description": "The outcome type. Always `timeout`." }) +}).annotate({ + "title": "Shell call timeout outcome", + "description": "Indicates that the shell call exceeded its configured time limit.", + "identifier": "BetaFunctionShellCallOutputTimeoutOutcome" +}) +export type BetaFunctionShellCallOutputExitOutcome = { readonly "type": "exit"; readonly "exit_code": number } +export const BetaFunctionShellCallOutputExitOutcome = Schema.Struct({ + "type": Schema.Literal("exit").annotate({ "description": "The outcome type. Always `exit`." }), + "exit_code": Schema.Number.annotate({ "description": "Exit code from the shell process." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "Shell call exit outcome", + "description": "Indicates that the shell commands finished and returned an exit code.", + "identifier": "BetaFunctionShellCallOutputExitOutcome" +}) +export type BetaApplyPatchCallStatus = "in_progress" | "completed" +export const BetaApplyPatchCallStatus = Schema.Literals(["in_progress", "completed"]).annotate({ + "identifier": "BetaApplyPatchCallStatus" +}) +export type BetaApplyPatchCreateFileOperation = { + readonly "type": "create_file" + readonly "path": string + readonly "diff": string } -export const VoiceConsentListResource = Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array(VoiceConsentResource), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean +export const BetaApplyPatchCreateFileOperation = Schema.Struct({ + "type": Schema.Literal("create_file").annotate({ "description": "Create a new file with the provided diff." }), + "path": Schema.String.annotate({ "description": "Path of the file to create." }), + "diff": Schema.String.annotate({ "description": "Diff to apply." }) +}).annotate({ + "title": "Apply patch create file operation", + "description": "Instruction describing how to create a file via the apply_patch tool.", + "identifier": "BetaApplyPatchCreateFileOperation" }) -export type CreateSpeechRequest = { - readonly "model": string | "tts-1" | "tts-1-hd" | "gpt-4o-mini-tts" | "gpt-4o-mini-tts-2025-12-15" - readonly "input": string - readonly "instructions"?: string - readonly "voice": VoiceIdsShared | { readonly "id": string } - readonly "response_format"?: "mp3" | "opus" | "aac" | "flac" | "wav" | "pcm" - readonly "speed"?: number - readonly "stream_format"?: "sse" | "audio" +export type BetaApplyPatchDeleteFileOperation = { readonly "type": "delete_file"; readonly "path": string } +export const BetaApplyPatchDeleteFileOperation = Schema.Struct({ + "type": Schema.Literal("delete_file").annotate({ "description": "Delete the specified file." }), + "path": Schema.String.annotate({ "description": "Path of the file to delete." }) +}).annotate({ + "title": "Apply patch delete file operation", + "description": "Instruction describing how to delete a file via the apply_patch tool.", + "identifier": "BetaApplyPatchDeleteFileOperation" +}) +export type BetaApplyPatchUpdateFileOperation = { + readonly "type": "update_file" + readonly "path": string + readonly "diff": string } -export const CreateSpeechRequest = Schema.Struct({ - "model": Schema.Union([ - Schema.String, - Schema.Literals(["tts-1", "tts-1-hd", "gpt-4o-mini-tts", "gpt-4o-mini-tts-2025-12-15"]) - ]).annotate({ - "description": - "One of the available [TTS models](/docs/models#tts): `tts-1`, `tts-1-hd`, `gpt-4o-mini-tts`, or `gpt-4o-mini-tts-2025-12-15`.\n" - }), - "input": Schema.String.annotate({ - "description": "The text to generate audio for. The maximum length is 4096 characters." - }).check(Schema.isMaxLength(4096)), - "instructions": Schema.optionalKey( - Schema.String.annotate({ +export const BetaApplyPatchUpdateFileOperation = Schema.Struct({ + "type": Schema.Literal("update_file").annotate({ "description": "Update an existing file with the provided diff." }), + "path": Schema.String.annotate({ "description": "Path of the file to update." }), + "diff": Schema.String.annotate({ "description": "Diff to apply." }) +}).annotate({ + "title": "Apply patch update file operation", + "description": "Instruction describing how to update a file via the apply_patch tool.", + "identifier": "BetaApplyPatchUpdateFileOperation" +}) +export type BetaApplyPatchCallOutputStatus = "completed" | "failed" +export const BetaApplyPatchCallOutputStatus = Schema.Literals(["completed", "failed"]).annotate({ + "identifier": "BetaApplyPatchCallOutputStatus" +}) +export type BetaResponseUsage = { + readonly "input_tokens": number + readonly "input_tokens_details": { readonly "cached_tokens": number; readonly "cache_write_tokens": number } + readonly "output_tokens": number + readonly "output_tokens_details": { readonly "reasoning_tokens": number } + readonly "total_tokens": number +} +export const BetaResponseUsage = Schema.Struct({ + "input_tokens": Schema.Number.annotate({ "description": "The number of input tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "input_tokens_details": Schema.Struct({ + "cached_tokens": Schema.Number.annotate({ "description": - "Control the voice of your generated audio with additional instructions. Does not work with `tts-1` or `tts-1-hd`." - }).check(Schema.isMaxLength(4096)) + "The number of tokens that were retrieved from the cache.\n[More on prompt caching](https://developers.openai.com/api/docs/guides/prompt-caching).\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "cache_write_tokens": Schema.Number.annotate({ + "description": "The number of input tokens that were written to the cache." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + }).annotate({ "description": "A detailed breakdown of the input tokens." }), + "output_tokens": Schema.Number.annotate({ "description": "The number of output tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "voice": Schema.Union([ - VoiceIdsShared, - Schema.Struct({ "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) }) - .annotate({ "description": "Custom voice reference." }) - ]).annotate({ - "title": "Voice", - "description": - "The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ \"id\": \"voice_1234\" }`. Previews of the voices are available in the [Text to speech guide](/docs/guides/text-to-speech#voice-options)." + "output_tokens_details": Schema.Struct({ + "reasoning_tokens": Schema.Number.annotate({ "description": "The number of reasoning tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "A detailed breakdown of the output tokens." }), + "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": + "Represents token usage details including input tokens, output tokens,\na breakdown of output tokens, and the total tokens used.\n", + "identifier": "BetaResponseUsage" +}) +export type BetaCacheMissReasonTypeEnum = + | "model_changed" + | "prompt_cache_key_changed" + | "tools_changed" + | "text_format_changed" + | "reasoning_effort_changed" + | "verbosity_changed" + | "context_compacted" + | "input_changed" + | "service_tier_changed" +export const BetaCacheMissReasonTypeEnum = Schema.Literals([ + "model_changed", + "prompt_cache_key_changed", + "tools_changed", + "text_format_changed", + "reasoning_effort_changed", + "verbosity_changed", + "context_compacted", + "input_changed", + "service_tier_changed" +]).annotate({ "identifier": "BetaCacheMissReasonTypeEnum" }) +export type BetaPromptCacheHitDiagnosticsBody = { readonly "type": "cache_hit" } +export const BetaPromptCacheHitDiagnosticsBody = Schema.Struct({ "type": Schema.Literal("cache_hit") }).annotate({ + "identifier": "BetaPromptCacheHitDiagnosticsBody" +}) +export type BetaPromptCacheComparisonResponseNotFoundDiagnosticsBody = { + readonly "type": "comparison_response_not_found" +} +export const BetaPromptCacheComparisonResponseNotFoundDiagnosticsBody = Schema.Struct({ + "type": Schema.Literal("comparison_response_not_found") +}).annotate({ "identifier": "BetaPromptCacheComparisonResponseNotFoundDiagnosticsBody" }) +export type BetaPromptCacheUnavailableDiagnosticsBody = { readonly "type": "unavailable" } +export const BetaPromptCacheUnavailableDiagnosticsBody = Schema.Struct({ "type": Schema.Literal("unavailable") }) + .annotate({ "identifier": "BetaPromptCacheUnavailableDiagnosticsBody" }) +export type BetaModerationInputType = "text" | "image" +export const BetaModerationInputType = Schema.Literals(["text", "image"]).annotate({ + "identifier": "BetaModerationInputType" +}) +export type BetaModerationErrorBody = { readonly "type": "error"; readonly "code": string; readonly "message": string } +export const BetaModerationErrorBody = Schema.Struct({ + "type": Schema.Literal("error").annotate({ + "description": "The object type, which was always `error` for moderation failures." }), - "response_format": Schema.optionalKey( - Schema.Literals(["mp3", "opus", "aac", "flac", "wav", "pcm"]).annotate({ - "description": "The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`, `wav`, and `pcm`." - }) - ), - "speed": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default." - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0.25)).check(Schema.isLessThanOrEqualTo(4)) + "code": Schema.String.annotate({ "description": "The error code." }), + "message": Schema.String.annotate({ "description": "The error message." }) +}).annotate({ + "title": "Moderation error", + "description": "An error produced while attempting moderation for the response input or output.", + "identifier": "BetaModerationErrorBody" +}) +export type BetaResponseConversation = { readonly "id": string } +export const BetaResponseConversation = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The unique ID of the conversation that this response was associated with." + }) +}).annotate({ + "title": "Conversation", + "description": + "The conversation that this response belonged to. Input items and output items from this response were automatically added to this conversation.", + "identifier": "BetaResponseConversation" +}) +export type BetaShellCallOutputDelta = { readonly "stdout"?: string; readonly "stderr"?: string } +export const BetaShellCallOutputDelta = Schema.Struct({ + "stdout": Schema.optionalKey(Schema.String.annotate({ "description": "The stdout delta that was emitted." })), + "stderr": Schema.optionalKey(Schema.String.annotate({ "description": "The stderr delta that was emitted." })) +}).annotate({ + "title": "Shell call output delta", + "description": "A delta of stdout/stderr emitted while a shell call was running.", + "identifier": "BetaShellCallOutputDelta" +}) +export type BetaResponseLogProb = { + readonly "token": string + readonly "logprob": number + readonly "top_logprobs"?: ReadonlyArray<{ readonly "token"?: string; readonly "logprob"?: number }> +} +export const BetaResponseLogProb = Schema.Struct({ + "token": Schema.String.annotate({ "description": "A possible text token." }), + "logprob": Schema.Number.annotate({ "description": "The log probability of this token.\n" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) ), - "stream_format": Schema.optionalKey( - Schema.Literals(["sse", "audio"]).annotate({ - "description": - "The format to stream the audio in. Supported formats are `sse` and `audio`. `sse` is not supported for `tts-1` or `tts-1-hd`." - }) + "top_logprobs": Schema.optionalKey( + Schema.Array(Schema.Struct({ + "token": Schema.optionalKey(Schema.String.annotate({ "description": "A possible text token." })), + "logprob": Schema.optionalKey( + Schema.Number.annotate({ "description": "The log probability of this token." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) + ) + })).annotate({ "description": "The log probabilities of up to 20 of the most likely tokens.\n" }) ) +}).annotate({ + "description": + "A logprob is the logarithmic probability that the model assigns to producing \na particular token at a given position in the sequence. Less-negative (higher) \nlogprob values indicate greater model confidence in that token choice.\n", + "identifier": "BetaResponseLogProb" }) -export type RealtimeSessionCreateResponse = { - readonly "id"?: string - readonly "object"?: string - readonly "expires_at"?: number - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> - readonly "model"?: string - readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> - readonly "instructions"?: string - readonly "audio"?: { - readonly "input"?: { - readonly "format"?: RealtimeAudioFormats - readonly "transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - } - readonly "noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "turn_detection"?: { - readonly "type"?: string - readonly "threshold"?: number - readonly "prefix_padding_ms"?: number - readonly "silence_duration_ms"?: number - } - } - readonly "output"?: { - readonly "format"?: RealtimeAudioFormats - readonly "voice"?: VoiceIdsShared - readonly "speed"?: number - } - } - readonly "tracing"?: "auto" | { - readonly "workflow_name"?: string - readonly "group_id"?: string - readonly "metadata"?: {} - } - readonly "turn_detection"?: { - readonly "type"?: string - readonly "threshold"?: number - readonly "prefix_padding_ms"?: number - readonly "silence_duration_ms"?: number - } - readonly "tools"?: ReadonlyArray - readonly "tool_choice"?: string - readonly "max_output_tokens"?: number | "inf" +export type BetaPromptCacheRetentionEnum = "in_memory" | "24h" +export const BetaPromptCacheRetentionEnum = Schema.Literals(["in_memory", "24h"]).annotate({ + "identifier": "BetaPromptCacheRetentionEnum" +}) +export type BetaServiceTierEnum = "auto" | "default" | "fast" | "flex" | "priority" +export const BetaServiceTierEnum = Schema.Literals(["auto", "default", "fast", "flex", "priority"]).annotate({ + "identifier": "BetaServiceTierEnum" +}) +export type BetaMessageStatus = "in_progress" | "completed" | "incomplete" +export const BetaMessageStatus = Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "identifier": "BetaMessageStatus" +}) +export type BetaMessagePhase_2 = "commentary" | "final_answer" +export const BetaMessagePhase_2 = Schema.Literals(["commentary", "final_answer"]).annotate({ + "identifier": "BetaMessagePhase-2" +}) +export type BetaTruncationEnum = "auto" | "disabled" +export const BetaTruncationEnum = Schema.Literals(["auto", "disabled"]).annotate({ "identifier": "BetaTruncationEnum" }) +export type BetaPersonalityEnum = string | "friendly" | "pragmatic" +export const BetaPersonalityEnum = Schema.Union([Schema.String, Schema.Literals(["friendly", "pragmatic"])]).annotate({ + "identifier": "BetaPersonalityEnum" +}) +export type BetaTokenCountsResource = { readonly "object": "response.input_tokens"; readonly "input_tokens": number } +export const BetaTokenCountsResource = Schema.Struct({ + "object": Schema.Literal("response.input_tokens"), + "input_tokens": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ "title": "Token counts", "identifier": "BetaTokenCountsResource" }) +export type FileSearchRankingOptions = { readonly "ranker"?: FileSearchRanker; readonly "score_threshold": number } +export const FileSearchRankingOptions = Schema.Struct({ + "ranker": Schema.optionalKey(FileSearchRanker), + "score_threshold": Schema.Number.annotate({ + "description": + "The score threshold for the file search. All values must be a floating point number between 0 and 1." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })) +}).annotate({ + "title": "File search tool call ranking options", + "description": + "The ranking options for the file search. If not specified, the file search tool will use the `auto` ranker and a score_threshold of 0.\n\nSee the [file search tool documentation](https://developers.openai.com/api/docs/guides/tools-file-search#retrieval-customization) for more information.\n", + "identifier": "FileSearchRankingOptions" +}) +export type RunStepDetailsToolCallsFileSearchRankingOptionsObject = { + readonly "ranker": FileSearchRanker + readonly "score_threshold": number } -export const RealtimeSessionCreateResponse = Schema.Struct({ - "id": Schema.optionalKey( +export const RunStepDetailsToolCallsFileSearchRankingOptionsObject = Schema.Struct({ + "ranker": FileSearchRanker, + "score_threshold": Schema.Number.annotate({ + "description": + "The score threshold for the file search. All values must be a floating point number between 0 and 1." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })) +}).annotate({ + "title": "File search tool call ranking options", + "description": "The ranking options for the file search.", + "identifier": "RunStepDetailsToolCallsFileSearchRankingOptionsObject" +}) +export type FunctionObject = { + readonly "description"?: string + readonly "name": string + readonly "parameters"?: FunctionParameters + readonly "strict"?: boolean | null +} +export const FunctionObject = Schema.Struct({ + "description": Schema.optionalKey( Schema.String.annotate({ - "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" - }) - ), - "object": Schema.optionalKey( - Schema.String.annotate({ "description": "The object type. Always `realtime.session`." }) - ), - "expires_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Expiration timestamp for the session, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ "description": - "Additional fields to include in server outputs.\n- `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" + "A description of what the function does, used by the model to choose when and how to call the function." }) ), - "model": Schema.optionalKey(Schema.String.annotate({ "description": "The Realtime model used for this session." })), - "output_modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": "The set of modalities the model can respond with. To disable audio,\nset this to [\"text\"].\n" + "name": Schema.String.annotate({ + "description": + "The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64." + }), + "parameters": Schema.optionalKey(FunctionParameters), + "strict": Schema.optionalKey(Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the `parameters` field. Only a subset of JSON Schema is supported when `strict` is `true`. Learn more about Structured Outputs in the [function calling guide](https://developers.openai.com/api/docs/guides/function-calling)." + }), + Schema.Null + ])) +}).annotate({ "identifier": "FunctionObject" }) +export type ChatCompletionFunctions = { + readonly "description"?: string + readonly "name": string + readonly "parameters"?: FunctionParameters +} +export const ChatCompletionFunctions = Schema.Struct({ + "description": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A description of what the function does, used by the model to choose when and how to call the function." }) ), - "instructions": Schema.optionalKey(Schema.String.annotate({ + "name": Schema.String.annotate({ "description": - "The default system instructions (i.e. system message) prepended to model\ncalls. This field allows the client to guide the model on desired\nresponses. The model can be instructed on response content and format,\n(e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good\nresponses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion\ninto your voice\", \"laugh frequently\"). The instructions are not guaranteed\nto be followed by the model, but they provide guidance to the model on the\ndesired behavior.\n\nNote that the server sets default instructions which will be used if this\nfield is not set and are visible in the `session.created` event at the\nstart of the session.\n" - })), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey(RealtimeAudioFormats), - "transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model used for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ "description": "The language of the input audio.\n" }) - ), - "prompt": Schema.optionalKey( - Schema.String.annotate({ - "description": "The prompt configured for input audio transcription, when present.\n" - }) - ) - }).annotate({ "description": "Configuration for input audio transcription.\n" }) - ), - "noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": "Configuration for input audio noise reduction.\n" - }) - ), - "turn_detection": Schema.optionalKey( - Schema.Struct({ - "type": Schema.optionalKey( - Schema.String.annotate({ - "description": "Type of turn detection, only `server_vad` is currently supported.\n" - }) - ), - "threshold": Schema.optionalKey(Schema.Number.check(Schema.isFinite())), - "prefix_padding_ms": Schema.optionalKey(Schema.Number.check(Schema.isInt())), - "silence_duration_ms": Schema.optionalKey(Schema.Number.check(Schema.isInt())) - }).annotate({ "description": "Configuration for turn detection.\n" }) - ) - })), - "output": Schema.optionalKey( - Schema.Struct({ - "format": Schema.optionalKey(RealtimeAudioFormats), - "voice": Schema.optionalKey(VoiceIdsShared), - "speed": Schema.optionalKey(Schema.Number.check(Schema.isFinite())) - }) - ) - }).annotate({ "description": "Configuration for input and output audio for the session.\n" }) - ), - "tracing": Schema.optionalKey( - Schema.Union([ - Schema.Literal("auto").annotate({ "description": "Default tracing mode for the session.\n" }), - Schema.Struct({ - "workflow_name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The name of the workflow to attach to this trace. This is used to\nname the trace in the traces dashboard.\n" - }) - ), - "group_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The group id to attach to this trace to enable filtering and\ngrouping in the traces dashboard.\n" - }) - ), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "The arbitrary metadata to attach to this trace to enable\nfiltering in the traces dashboard.\n" - }) - ) - }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) - ], { mode: "oneOf" }).annotate({ - "title": "Tracing Configuration", - "description": - "Configuration options for tracing. Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" - }) - ), - "turn_detection": Schema.optionalKey( - Schema.Struct({ - "type": Schema.optionalKey( - Schema.String.annotate({ "description": "Type of turn detection, only `server_vad` is currently supported.\n" }) - ), - "threshold": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" - }).check(Schema.isFinite()) - ), - "prefix_padding_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" - }).check(Schema.isInt()) - ), - "silence_duration_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" - }).check(Schema.isInt()) - ) - }).annotate({ - "description": - "Configuration for turn detection. Can be set to `null` to turn off. Server\nVAD means that the model will detect the start and end of speech based on\naudio volume and respond at the end of user speech.\n" - }) - ), - "tools": Schema.optionalKey( - Schema.Array(RealtimeFunctionTool).annotate({ "description": "Tools (functions) available to the model." }) - ), - "tool_choice": Schema.optionalKey( - Schema.String.annotate({ - "description": "How the model chooses tools. Options are `auto`, `none`, `required`, or\nspecify a function.\n" - }) - ), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" - }) - ) -}).annotate({ - "title": "Realtime session configuration object", - "description": "A Realtime session configuration object.\n" -}) -export type WebSearchTool = { - readonly "type": "web_search" | "web_search_2025_08_26" - readonly "filters"?: { readonly "allowed_domains"?: ReadonlyArray | null } | null - readonly "user_location"?: WebSearchApproximateLocation - readonly "search_context_size"?: "low" | "medium" | "high" -} -export const WebSearchTool = Schema.Struct({ - "type": Schema.Literals(["web_search", "web_search_2025_08_26"]).annotate({ - "description": "The type of the web search tool. One of `web_search` or `web_search_2025_08_26`." + "The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64." }), - "filters": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "allowed_domains": Schema.optionalKey( - Schema.Union([ - Schema.Array(Schema.String.annotate({ "description": "Allowed domain for the search." })).annotate({ - "title": "Allowed domains for the search.", - "description": - "Allowed domains for the search. If not provided, all domains are allowed.\nSubdomains of the provided domains are allowed as well.\n\nExample: `[\"pubmed.ncbi.nlm.nih.gov\"]`\n" - }), - Schema.Null - ]) - ) - }).annotate({ "description": "Filters for the search.\n" }), - Schema.Null - ])), - "user_location": Schema.optionalKey(WebSearchApproximateLocation), - "search_context_size": Schema.optionalKey( - Schema.Literals(["low", "medium", "high"]).annotate({ - "description": - "High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default." - }) - ) + "parameters": Schema.optionalKey(FunctionParameters) +}).annotate({ "identifier": "ChatCompletionFunctions" }) +export type EvalLogsDataSourceConfig = { + readonly "type": "logs" + readonly "metadata"?: Metadata + readonly "schema": { readonly [x: string]: Schema.Json } +} +export const EvalLogsDataSourceConfig = Schema.Struct({ + "type": Schema.Literal("logs").annotate({ "description": "The type of data source. Always `logs`." }), + "metadata": Schema.optionalKey(Metadata), + "schema": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "The json schema for the run data source items.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n" + }) }).annotate({ - "title": "Web search", + "title": "LogsDataSourceConfig", "description": - "Search the Internet for sources related to the prompt. Learn more about the\n[web search tool](/docs/guides/tools-web-search).\n" + "A LogsDataSourceConfig which specifies the metadata property of your logs query.\nThis is usually metadata like `usecase=chatbot` or `prompt-version=v2`, etc.\nThe schema returned by this data source config is used to defined what variables are available in your evals.\n`item` and `sample` are both defined when using this data source config.\n", + "identifier": "EvalLogsDataSourceConfig" }) -export type ContainerNetworkPolicyAllowlistParam = { - readonly "type": "allowlist" - readonly "allowed_domains": ReadonlyArray - readonly "domain_secrets"?: ReadonlyArray +export type EvalStoredCompletionsDataSourceConfig = { + readonly "type": "stored_completions" + readonly "metadata"?: Metadata + readonly "schema": { readonly [x: string]: Schema.Json } } -export const ContainerNetworkPolicyAllowlistParam = Schema.Struct({ - "type": Schema.Literal("allowlist").annotate({ - "description": "Allow outbound network access only to specified domains. Always `allowlist`." +export const EvalStoredCompletionsDataSourceConfig = Schema.Struct({ + "type": Schema.Literal("stored_completions").annotate({ + "description": "The type of data source. Always `stored_completions`." }), - "allowed_domains": Schema.Array(Schema.String).annotate({ - "description": "A list of allowed domains when type is `allowlist`." - }).check(Schema.isMinLength(1)), - "domain_secrets": Schema.optionalKey( - Schema.Array(ContainerNetworkPolicyDomainSecretParam).annotate({ - "description": "Optional domain-scoped secrets for allowlisted domains." - }).check(Schema.isMinLength(1)) - ) -}) -export type EvalItemContentItem = - | EvalItemContentText - | InputTextContent - | EvalItemContentOutputText - | EvalItemInputImage - | InputAudio -export const EvalItemContentItem = Schema.Union([ - EvalItemContentText, - InputTextContent, - EvalItemContentOutputText, - EvalItemInputImage, - InputAudio -], { mode: "oneOf" }).annotate({ - "title": "Eval content item", - "description": "A single content item: input text, output text, input image, or input audio.\n" + "metadata": Schema.optionalKey(Metadata), + "schema": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "The json schema for the run data source items.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n" + }) +}).annotate({ + "title": "StoredCompletionsDataSourceConfig", + "description": "Deprecated in favor of LogsDataSourceConfig.\n", + "identifier": "EvalStoredCompletionsDataSourceConfig" }) -export type Annotation = FileCitationBody | UrlCitationBody | ContainerFileCitationBody | FilePath -export const Annotation = Schema.Union([FileCitationBody, UrlCitationBody, ContainerFileCitationBody, FilePath], { - mode: "oneOf" -}).annotate({ "description": "An annotation that applies to a span of output text." }) -export type LogProb = { - readonly "token": string - readonly "logprob": number - readonly "bytes": ReadonlyArray - readonly "top_logprobs": ReadonlyArray -} -export const LogProb = Schema.Struct({ - "token": Schema.String, - "logprob": Schema.Number.check(Schema.isFinite()), - "bytes": Schema.Array(Schema.Number.check(Schema.isInt())), - "top_logprobs": Schema.Array(TopLogProb) -}).annotate({ "title": "Log probability", "description": "The log probability of a token." }) -export type ReasoningItem = { - readonly "type": "reasoning" - readonly "id": string - readonly "encrypted_content"?: string | null - readonly "summary": ReadonlyArray - readonly "content"?: ReadonlyArray - readonly "status"?: "in_progress" | "completed" | "incomplete" +export type EvalStoredCompletionsSource = { + readonly "type": "stored_completions" + readonly "metadata"?: Metadata + readonly "model"?: string | null + readonly "created_after"?: number | null + readonly "created_before"?: number | null + readonly "limit"?: number | null } -export const ReasoningItem = Schema.Struct({ - "type": Schema.Literal("reasoning").annotate({ "description": "The type of the object. Always `reasoning`.\n" }), - "id": Schema.String.annotate({ "description": "The unique identifier of the reasoning content.\n" }), - "encrypted_content": Schema.optionalKey( +export const EvalStoredCompletionsSource = Schema.Struct({ + "type": Schema.Literal("stored_completions").annotate({ + "description": "The type of source. Always `stored_completions`." + }), + "metadata": Schema.optionalKey(Metadata), + "model": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ - "description": - "The encrypted content of the reasoning item - populated when a response is\ngenerated with `reasoning.encrypted_content` in the `include` parameter.\n" - }), + Schema.String.annotate({ "description": "An optional model to filter by (e.g., 'gpt-6-astra')." }), Schema.Null ]) ), - "summary": Schema.Array(SummaryTextContent).annotate({ "description": "Reasoning summary content.\n" }), - "content": Schema.optionalKey( - Schema.Array(ReasoningTextContent).annotate({ "description": "Reasoning text content.\n" }) + "created_after": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "An optional Unix timestamp to filter items created after this time." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) ), - "status": Schema.optionalKey( - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }) - ) -}).annotate({ - "title": "Reasoning", - "description": - "A description of the chain of thought used by a reasoning model while generating\na response. Be sure to include these items in your `input` to the Responses API\nfor subsequent turns of a conversation if you are manually\n[managing context](/docs/guides/conversation-state).\n" -}) -export type FunctionAndCustomToolCallOutput = InputTextContent | InputImageContent | InputFileContent -export const FunctionAndCustomToolCallOutput = Schema.Union([InputTextContent, InputImageContent, InputFileContent], { - mode: "oneOf" -}) -export type InputContent = InputTextContent | InputImageContent | InputFileContent -export const InputContent = Schema.Union([InputTextContent, InputImageContent, InputFileContent], { mode: "oneOf" }) -export type DragParam = { - readonly "type": "drag" - readonly "path": ReadonlyArray - readonly "keys"?: ReadonlyArray | null -} -export const DragParam = Schema.Struct({ - "type": Schema.Literal("drag").annotate({ - "description": "Specifies the event type. For a drag action, this property is always set to `drag`." - }), - "path": Schema.Array(CoordParam).annotate({ - "description": - "An array of coordinates representing the path of the drag action. Coordinates will appear as an array of objects, eg\n```\n[\n { x: 100, y: 200 },\n { x: 200, y: 300 }\n]\n```" - }), - "keys": Schema.optionalKey( + "created_before": Schema.optionalKey( Schema.Union([ - Schema.Array(Schema.String).annotate({ "description": "The keys being held while dragging the mouse." }), + Schema.Number.annotate({ "description": "An optional Unix timestamp to filter items created before this time." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ), + "limit": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "An optional maximum number of items to return." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), Schema.Null ]) ) -}).annotate({ "title": "Drag", "description": "A drag action." }) -export type ComputerToolCallOutputResource = { - readonly "type": "computer_call_output" +}).annotate({ + "title": "StoredCompletionsRunDataSource", + "description": "A StoredCompletionsRunDataSource configuration describing a set of filters\n", + "identifier": "EvalStoredCompletionsSource" +}) +export type ThreadObject = { readonly "id": string - readonly "call_id": string - readonly "acknowledged_safety_checks"?: ReadonlyArray - readonly "output": ComputerScreenshotImage - readonly "status": "completed" | "incomplete" - readonly "created_by"?: string + readonly "object": "thread" + readonly "created_at": number + readonly "tool_resources": { + readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } + readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } + } | null + readonly "metadata": Metadata } -export const ComputerToolCallOutputResource = Schema.Struct({ - "type": Schema.Literal("computer_call_output").annotate({ - "description": "The type of the computer tool call output. Always `computer_call_output`.\n" - }), - "id": Schema.String.annotate({ "description": "The unique ID of the computer call tool output.\n" }), - "call_id": Schema.String.annotate({ "description": "The ID of the computer tool call that produced the output.\n" }), - "acknowledged_safety_checks": Schema.optionalKey( - Schema.Array(ComputerCallSafetyCheckParam).annotate({ - "description": "The safety checks reported by the API that have been acknowledged by the\ndeveloper.\n" - }) - ), - "output": ComputerScreenshotImage, - "status": Schema.Union([ - Schema.Literal("completed").annotate({ +export const ThreadObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("thread").annotate({ "description": "The object type, which is always `thread`." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the thread was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "tool_resources": Schema.Union([ + Schema.Struct({ + "code_interpreter": Schema.optionalKey(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })) + ) + })), + "file_search": Schema.optionalKey(Schema.Struct({ + "vector_store_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "The [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this thread. There can be a maximum of 1 vector store attached to the thread.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ) + })) + }).annotate({ "description": - "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" + "A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" }), - Schema.Literal("incomplete").annotate({ + Schema.Null + ]), + "metadata": Metadata +}).annotate({ + "title": "Thread", + "description": + "Represents a thread that contains [messages](https://developers.openai.com/api/docs/assistants/migration).", + "identifier": "ThreadObject" +}) +export type ModifyThreadRequest = { + readonly "tool_resources"?: { + readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } + readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } + } | null + readonly "metadata"?: Metadata +} +export const ModifyThreadRequest = Schema.Struct({ + "tool_resources": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "code_interpreter": Schema.optionalKey(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })) + ) + })), + "file_search": Schema.optionalKey(Schema.Struct({ + "vector_store_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "The [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this thread. There can be a maximum of 1 vector store attached to the thread.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ) + })) + }).annotate({ "description": - "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" - }) - ]).annotate({ + "A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" + }), + Schema.Null + ])), + "metadata": Schema.optionalKey(Metadata) +}).annotate({ "identifier": "ModifyThreadRequest" }) +export type ModifyMessageRequest = { readonly "metadata"?: Metadata } +export const ModifyMessageRequest = Schema.Struct({ "metadata": Schema.optionalKey(Metadata) }).annotate({ + "identifier": "ModifyMessageRequest" +}) +export type ModifyRunRequest = { readonly "metadata"?: Metadata } +export const ModifyRunRequest = Schema.Struct({ "metadata": Schema.optionalKey(Metadata) }).annotate({ + "identifier": "ModifyRunRequest" +}) +export type UpdateConversationBody = { readonly "metadata": Metadata } +export const UpdateConversationBody = Schema.Struct({ + "metadata": Schema.suspend((): Schema.Codec => Metadata).annotate({ "description": - "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" + "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard.\n Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters." + }) +}).annotate({ "identifier": "UpdateConversationBody" }) +export type ResponseFormatJsonSchema = { + readonly "type": "json_schema" + readonly "json_schema": { + readonly "description"?: string + readonly "name": string + readonly "schema"?: ResponseFormatJsonSchemaSchema + readonly "strict"?: boolean | null + } +} +export const ResponseFormatJsonSchema = Schema.Struct({ + "type": Schema.Literal("json_schema").annotate({ + "description": "The type of response format being defined. Always `json_schema`." }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) - ) -}).annotate({ "title": "Computer tool call output", "description": "The output of a computer tool call.\n" }) -export type CreateImageEditRequest = { - readonly "image": string | ReadonlyArray - readonly "prompt": string - readonly "mask"?: string - readonly "background"?: "transparent" | "opaque" | "auto" | null - readonly "model"?: - | string - | "gpt-image-1.5" - | "dall-e-2" - | "gpt-image-1" - | "gpt-image-1-mini" - | "chatgpt-image-latest" - | null - readonly "n"?: number - readonly "size"?: string | "256x256" | "512x512" | "1024x1024" | "1536x1024" | "1024x1536" | "auto" | null - readonly "response_format"?: "url" | "b64_json" | null - readonly "output_format"?: "png" | "jpeg" | "webp" | null - readonly "output_compression"?: number | null - readonly "user"?: string - readonly "input_fidelity"?: InputFidelity | null - readonly "stream"?: boolean | null - readonly "partial_images"?: PartialImages - readonly "quality"?: "standard" | "low" | "medium" | "high" | "auto" | null + "json_schema": Schema.Struct({ + "description": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A description of what the response format is for, used by the model to\ndetermine how to respond in the format.\n" + }) + ), + "name": Schema.String.annotate({ + "description": + "The name of the response format. Must be a-z, A-Z, 0-9, or contain\nunderscores and dashes, with a maximum length of 64.\n" + }), + "schema": Schema.optionalKey(ResponseFormatJsonSchemaSchema), + "strict": Schema.optionalKey(Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to enable strict schema adherence when generating the output.\nIf set to true, the model will always follow the exact schema defined\nin the `schema` field. Only a subset of JSON Schema is supported when\n`strict` is `true`. To learn more, read the [Structured Outputs\nguide](https://developers.openai.com/api/docs/guides/structured-outputs).\n" + }), + Schema.Null + ])) + }).annotate({ + "title": "JSON schema", + "description": "Structured Outputs configuration options, including a JSON Schema.\n" + }) +}).annotate({ + "title": "JSON schema", + "description": + "JSON Schema response format. Used to generate structured JSON responses.\nLearn more about [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs).\n", + "identifier": "ResponseFormatJsonSchema" +}) +export type TextResponseFormatJsonSchema = { + readonly "type": "json_schema" + readonly "description"?: string + readonly "name": string + readonly "schema": ResponseFormatJsonSchemaSchema + readonly "strict"?: boolean | null } -export const CreateImageEditRequest = Schema.Struct({ - "image": Schema.Union([ - Schema.String.annotate({ "format": "binary" }), - Schema.Array(Schema.String.annotate({ "format": "binary" })).check(Schema.isMaxLength(16)) - ]).annotate({ - "description": - "The image(s) to edit. Must be a supported image file or an array of images.\n\nFor the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, and `gpt-image-1.5`), each image should be a `png`, `webp`, or `jpg`\nfile less than 50MB. You can provide up to 16 images.\n`chatgpt-image-latest` follows the same input constraints as GPT image models.\n\nFor `dall-e-2`, you can only provide one image, and it should be a square\n`png` file less than 4MB.\n" +export const TextResponseFormatJsonSchema = Schema.Struct({ + "type": Schema.Literal("json_schema").annotate({ + "description": "The type of response format being defined. Always `json_schema`." }), - "prompt": Schema.String.annotate({ + "description": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A description of what the response format is for, used by the model to\ndetermine how to respond in the format.\n" + }) + ), + "name": Schema.String.annotate({ "description": - "A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2`, and 32000 characters for the GPT image models." + "The name of the response format. Must be a-z, A-Z, 0-9, or contain\nunderscores and dashes, with a maximum length of 64.\n" }), - "mask": Schema.optionalKey(Schema.String.annotate({ - "description": - "An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. If there are multiple images provided, the mask will be applied on the first image. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`.", - "format": "binary" - })), - "background": Schema.optionalKey(Schema.Union([ - Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "schema": ResponseFormatJsonSchemaSchema, + "strict": Schema.optionalKey(Schema.Union([ + Schema.Boolean.annotate({ "description": - "Allows to set transparency for the background of the generated image(s).\nThis parameter is only supported for the GPT image models. Must be one of\n`transparent`, `opaque` or `auto` (default value). When `auto` is used, the\nmodel will automatically determine the best background for the image.\n\nIf `transparent`, the output format needs to support transparency, so it\nshould be set to either `png` (default value) or `webp`.\n" + "Whether to enable strict schema adherence when generating the output.\nIf set to true, the model will always follow the exact schema defined\nin the `schema` field. Only a subset of JSON Schema is supported when\n`strict` is `true`. To learn more, read the [Structured Outputs\nguide](https://developers.openai.com/api/docs/guides/structured-outputs).\n" }), - Schema.Union([Schema.Null]).annotate({ - "description": - "Allows to set transparency for the background of the generated image(s).\nThis parameter is only supported for the GPT image models. Must be one of\n`transparent`, `opaque` or `auto` (default value). When `auto` is used, the\nmodel will automatically determine the best background for the image.\n\nIf `transparent`, the output format needs to support transparency, so it\nshould be set to either `png` (default value) or `webp`.\n" - }) - ])), - "model": Schema.optionalKey( + Schema.Null + ])) +}).annotate({ + "title": "JSON schema", + "description": + "JSON Schema response format. Used to generate structured JSON responses.\nLearn more about [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs).\n", + "identifier": "TextResponseFormatJsonSchema" +}) +export type MisalignmentErrorDetailsResource = { + readonly "review_target"?: string | null + readonly "error_type"?: _MisalignmentErrorType + readonly "detailed_explanation"?: string + readonly "steer"?: _MisalignmentSteer +} +export const MisalignmentErrorDetailsResource = Schema.Struct({ + "review_target": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.String, - Schema.Literals(["gpt-image-1.5", "dall-e-2", "gpt-image-1", "gpt-image-1-mini", "chatgpt-image-latest"]) - ]).annotate({ "description": "The model to use for image generation. Defaults to `gpt-image-1.5`." }), + Schema.String.annotate({ + "description": "An opaque target for explicitly continuing this review, or null when unavailable." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(96).annotate({ "expected": "a string with at most 96 code points" }) + ).check( + Schema.isPattern(new RegExp("^[A-Za-z0-9._~:-]+$", "u")).annotate({ + "expected": "a string matching the RegExp ^[A-Za-z0-9._~:-]+$" + }) + ), Schema.Null ]) ), - "n": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(10)], { - "description": "The number of images to generate. Must be between 1 and 10." + "error_type": Schema.optionalKey( + Schema.suspend((): Schema.Codec<_MisalignmentErrorType> => _MisalignmentErrorType).annotate({ + "description": "An optional classification; clients must accept additional values." + }) + ), + "detailed_explanation": Schema.optionalKey( + Schema.String.annotate({ "description": "The public explanation for this block." }) + ), + "steer": Schema.optionalKey( + Schema.suspend((): Schema.Codec<_MisalignmentSteer> => _MisalignmentSteer).annotate({ + "description": "An optional public continuation instruction." + }) + ) +}).annotate({ "identifier": "MisalignmentErrorDetailsResource" }) +export type ResponseConfigurationUpdate = { + readonly "id": string + readonly "type": "configuration_update" + readonly "reasoning"?: { readonly "effort"?: ReasoningEffort } +} +export const ResponseConfigurationUpdate = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the configuration update item." }), + "type": Schema.Literal("configuration_update").annotate({ + "description": "The item type. Always `configuration_update`." + }), + "reasoning": Schema.optionalKey( + Schema.Struct({ + "effort": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ReasoningEffort).annotate({ + "description": + "The reasoning effort used for subsequent responses until another\nconfiguration update replaces it.\n" }) ) + }).annotate({ "description": "The reasoning configuration applied by this update." }) + ) +}).annotate({ + "description": + "A configuration update that applies to subsequent responses until it is\nreplaced by another configuration update.\n", + "identifier": "ResponseConfigurationUpdate" +}) +export type EvalResponsesSource = { + readonly "type": "responses" + readonly "metadata"?: { readonly [x: string]: Schema.Json } | null + readonly "model"?: string | null + readonly "instructions_search"?: string | null + readonly "created_after"?: number | null + readonly "created_before"?: number | null + readonly "reasoning_effort"?: ReasoningEffort | null + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "users"?: ReadonlyArray | null + readonly "tools"?: ReadonlyArray | null +} +export const EvalResponsesSource = Schema.Struct({ + "type": Schema.Literal("responses").annotate({ "description": "The type of run data source. Always `responses`." }), + "metadata": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Metadata filter for the responses. This is a query parameter used to select responses." + }), + Schema.Null ]) ), - "size": Schema.optionalKey( + "model": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.String, - Schema.Literals(["256x256", "512x512", "1024x1024", "1536x1024", "1024x1536", "auto"]) - ]).annotate({ + Schema.String.annotate({ "description": - "The size of the generated images. For `gpt-image-2` and `gpt-image-2-2026-04-21`, arbitrary resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the maximum supported resolution is `3840x2160`. The requested size must also satisfy the model's current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is supported for models that allow automatic sizing. For `dall-e-2`, use one of `256x256`, `512x512`, or `1024x1024`. For `dall-e-3`, use one of `1024x1024`, `1792x1024`, or `1024x1792`." + "The name of the model to find responses for. This is a query parameter used to select responses." }), Schema.Null ]) ), - "response_format": Schema.optionalKey(Schema.Union([ - Schema.Literals(["url", "b64_json"]).annotate({ - "description": - "The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images." - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated. This parameter is only supported for `dall-e-2` (default is `url` for `dall-e-2`), as GPT image models always return base64-encoded images." - }) - ])), - "output_format": Schema.optionalKey( + "instructions_search": Schema.optionalKey( Schema.Union([ - Schema.Literals(["png", "jpeg", "webp"]).annotate({ + Schema.String.annotate({ "description": - "The format in which the generated images are returned. This parameter is\nonly supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`.\nThe default value is `png`.\n" + "Optional string to search the 'instructions' field. This is a query parameter used to select responses." }), - Schema.Union([Schema.Null]).annotate({ - "description": - "The format in which the generated images are returned. This parameter is\nonly supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`.\nThe default value is `png`.\n" - }) + Schema.Null ]) ), - "output_compression": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Null]).annotate({ - "description": - "The compression level (0-100%) for the generated images. This parameter\nis only supported for the GPT image models with the `webp` or `jpeg` output\nformats, and defaults to 100.\n" - }) - ), - "user": Schema.optionalKey( - Schema.String.annotate({ - "description": - "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices#end-user-ids).\n" - }) + "created_after": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "Only include items created after this timestamp (inclusive). This is a query parameter used to select responses." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ), + Schema.Null + ]) ), - "input_fidelity": Schema.optionalKey(Schema.Union([InputFidelity, Schema.Null])), - "stream": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": - "Edit the image in streaming mode. Defaults to `false`. See the\n[Image generation guide](/docs/guides/image-generation) for more information.\n" - }) + "created_before": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "Only include items created before this timestamp (inclusive). This is a query parameter used to select responses." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ), + Schema.Null + ]) ), - "partial_images": Schema.optionalKey(PartialImages), - "quality": Schema.optionalKey( + "reasoning_effort": Schema.optionalKey( Schema.Union([ - Schema.Literals(["standard", "low", "medium", "high", "auto"]).annotate({ - "description": "The quality of the image that will be generated for GPT image models. Defaults to `auto`.\n" + Schema.suspend((): Schema.Codec => ReasoningEffort).annotate({ + "description": "Optional reasoning effort parameter. This is a query parameter used to select responses." }), - Schema.Union([Schema.Null]).annotate({ - "description": "The quality of the image that will be generated for GPT image models. Defaults to `auto`.\n" - }) + Schema.Null + ]) + ), + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "Sampling temperature. This is a query parameter used to select responses." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + Schema.Null + ]) + ), + "top_p": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "Nucleus sampling parameter. This is a query parameter used to select responses." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + Schema.Null + ]) + ), + "users": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.String).annotate({ + "description": "List of user identifiers. This is a query parameter used to select responses." + }), + Schema.Null + ]) + ), + "tools": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.String).annotate({ + "description": "List of tool names. This is a query parameter used to select responses." + }), + Schema.Null ]) ) +}).annotate({ + "title": "EvalResponsesSource", + "description": "A EvalResponsesSource object describing a run data source configuration.\n", + "identifier": "EvalResponsesSource" }) -export type ImageGenTool = { - readonly "type": "image_generation" - readonly "model"?: string | "gpt-image-1" | "gpt-image-1-mini" | "gpt-image-1.5" - readonly "quality"?: "low" | "medium" | "high" | "auto" - readonly "size"?: string | "1024x1024" | "1024x1536" | "1536x1024" | "auto" - readonly "output_format"?: "png" | "webp" | "jpeg" - readonly "output_compression"?: number - readonly "moderation"?: "auto" | "low" - readonly "background"?: "transparent" | "opaque" | "auto" - readonly "input_fidelity"?: InputFidelity | null - readonly "input_image_mask"?: { readonly "image_url"?: string; readonly "file_id"?: string } - readonly "partial_images"?: number - readonly "action"?: "generate" | "edit" | "auto" +export type CreateSpeechRequest = { + readonly "model": string | "tts-1" | "tts-1-hd" | "gpt-4o-mini-tts" | "gpt-4o-mini-tts-2025-12-15" + readonly "input": string + readonly "instructions"?: string + readonly "voice": VoiceIdsShared | "fable" | "onyx" | "nova" | { readonly "id": string } + readonly "response_format"?: "mp3" | "opus" | "aac" | "flac" | "wav" | "pcm" + readonly "speed"?: number + readonly "stream_format"?: "sse" | "audio" } -export const ImageGenTool = Schema.Struct({ - "type": Schema.Literal("image_generation").annotate({ - "description": "The type of the image generation tool. Always `image_generation`.\n" +export const CreateSpeechRequest = Schema.Struct({ + "model": Schema.Union([ + Schema.String, + Schema.Literals(["tts-1", "tts-1-hd", "gpt-4o-mini-tts", "gpt-4o-mini-tts-2025-12-15"]) + ]).annotate({ + "description": + "One of the available [TTS models](https://developers.openai.com/api/docs/guides/text-to-speech): `tts-1`, `tts-1-hd`, `gpt-4o-mini-tts`, or `gpt-4o-mini-tts-2025-12-15`.\n" }), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals(["gpt-image-1", "gpt-image-1-mini", "gpt-image-1.5"]).annotate({ - "description": "The image generation model to use. Default: `gpt-image-1`.\n" - }) - ]) - ), - "quality": Schema.optionalKey( - Schema.Literals(["low", "medium", "high", "auto"]).annotate({ + "input": Schema.String.annotate({ + "description": "The text to generate audio for. The maximum length is 4096 characters." + }).check(Schema.isMaxCodePoints(4096).annotate({ "expected": "a string with at most 4096 code points" })), + "instructions": Schema.optionalKey( + Schema.String.annotate({ "description": - "The quality of the generated image. One of `low`, `medium`, `high`,\nor `auto`. Default: `auto`.\n" + "Control the voice of your generated audio with additional instructions. Does not work with `tts-1` or `tts-1-hd`." + }).check(Schema.isMaxCodePoints(4096).annotate({ "expected": "a string with at most 4096 code points" })) + ), + "voice": Schema.Union([ + Schema.Union([VoiceIdsShared, Schema.Literals(["fable", "onyx", "nova"])]), + Schema.Struct({ "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) }) + .annotate({ "description": "Custom voice reference." }) + ]).annotate({ + "title": "Voice", + "description": + "The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`, `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`, and `cedar`. You may also provide a custom voice object with an `id`, for example `{ \"id\": \"voice_1234\" }`. Previews of the voices are available in the [Text to speech guide](https://developers.openai.com/api/docs/guides/text-to-speech#voice-options). Custom voices must be created from audio samples." + }), + "response_format": Schema.optionalKey( + Schema.Literals(["mp3", "opus", "aac", "flac", "wav", "pcm"]).annotate({ + "description": "The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`, `wav`, and `pcm`." }) ), - "size": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"])]).annotate({ + "speed": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0.25).annotate({ "expected": "a value greater than or equal to 0.25" }) + ).check(Schema.isLessThanOrEqualTo(4).annotate({ "expected": "a value less than or equal to 4" })) + ), + "stream_format": Schema.optionalKey( + Schema.Literals(["sse", "audio"]).annotate({ "description": - "The size of the generated images. For `gpt-image-2` and `gpt-image-2-2026-04-21`, arbitrary resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the maximum supported resolution is `3840x2160`. The requested size must also satisfy the model's current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is supported for models that allow automatic sizing. For `dall-e-2`, use one of `256x256`, `512x512`, or `1024x1024`. For `dall-e-3`, use one of `1024x1024`, `1792x1024`, or `1024x1792`." + "The format to stream the audio in. Supported formats are `sse` and `audio`. `sse` is not supported for `tts-1` or `tts-1-hd`." }) - ), - "output_format": Schema.optionalKey( - Schema.Literals(["png", "webp", "jpeg"]).annotate({ - "description": "The output format of the generated image. One of `png`, `webp`, or\n`jpeg`. Default: `png`.\n" + ) +}).annotate({ "identifier": "CreateSpeechRequest" }) +export type VoiceIdsOrCustomVoice = VoiceIdsShared | { readonly "id": string } +export const VoiceIdsOrCustomVoice = Schema.Union([ + VoiceIdsShared, + Schema.Struct({ "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) }) + .annotate({ "description": "Custom voice reference." }) +]).annotate({ + "title": "Voice", + "description": "A built-in voice name or a custom voice reference.\n", + "identifier": "VoiceIdsOrCustomVoice" +}) +export type CreateSpeechResponseStreamEvent = SpeechAudioDeltaEvent | SpeechAudioDoneEvent +export const CreateSpeechResponseStreamEvent = Schema.Union([SpeechAudioDeltaEvent, SpeechAudioDoneEvent]).annotate({ + "identifier": "CreateSpeechResponseStreamEvent" +}) +export type CreateTranslationRequestMultipart = { + readonly "file": __ClientMultipartFile + readonly "model": string | "whisper-1" + readonly "prompt"?: string + readonly "response_format"?: "json" | "text" | "srt" | "verbose_json" | "vtt" + readonly "temperature"?: number +} +export const CreateTranslationRequestMultipart = Schema.Struct({ + "file": __ClientMultipartFile, + "model": Schema.Union([Schema.String, Schema.Literal("whisper-1")]).annotate({ + "description": + "ID of the model to use. Only `whisper-1` (which is powered by our open source Whisper V2 model) is currently available.\n" + }), + "prompt": Schema.optionalKey( + Schema.String.annotate({ + "description": + "An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://developers.openai.com/api/docs/guides/speech-to-text#prompting) should be in English.\n" }) ), - "output_compression": Schema.optionalKey( - Schema.Number.annotate({ "description": "Compression level for the output image. Default: 100.\n" }).check( - Schema.isInt() - ).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)) + "response_format": Schema.optionalKey( + Schema.Literals(["json", "text", "srt", "verbose_json", "vtt"]).annotate({ + "description": + "The format of the output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`.\n" + }) ), - "moderation": Schema.optionalKey( - Schema.Literals(["auto", "low"]).annotate({ - "description": "Moderation level for the generated image. Default: `auto`.\n" + "temperature": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ) +}).annotate({ "identifier": "CreateTranslationRequestMultipart" }) +export type CreateVoiceConsentRequestMultipart = { + readonly "name": string + readonly "recording": __ClientMultipartFile + readonly "language": string +} +export const CreateVoiceConsentRequestMultipart = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The label to use for this consent recording." }), + "recording": __ClientMultipartFile, + "language": Schema.String.annotate({ + "description": "The BCP 47 language tag for the consent phrase (for example, `en-US`)." + }) +}).annotate({ "identifier": "CreateVoiceConsentRequestMultipart" }) +export type CreateVoiceFromConsentRequestMultipart = { + readonly "type"?: "audio_sample" + readonly "name": string + readonly "audio_sample": __ClientMultipartFile + readonly "consent": string +} +export const CreateVoiceFromConsentRequestMultipart = Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("audio_sample").annotate({ + "description": "The voice creation method. Defaults to `audio_sample` when omitted." }) ), - "background": Schema.optionalKey( - Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "name": Schema.String.annotate({ "description": "The name of the new voice." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })), + "audio_sample": __ClientMultipartFile, + "consent": Schema.String.annotate({ "description": "The consent recording ID (for example, `cons_1234`)." }) +}).annotate({ + "title": "Consent", + "description": "Creates a voice from a consent recording and an audio sample. Requires multipart/form-data.", + "identifier": "CreateVoiceFromConsentRequestMultipart" +}) +export type CreateContainerFileBodyMultipart = { readonly "file_id"?: string; readonly "file"?: __ClientMultipartFile } +export const CreateContainerFileBodyMultipart = Schema.Struct({ + "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "Name of the file to create." })), + "file": Schema.optionalKey(__ClientMultipartFile) +}).annotate({ "identifier": "CreateContainerFileBodyMultipart" }) +export type CreateImageVariationRequestMultipart = { + readonly "image": __ClientMultipartFile + readonly "model"?: string | "dall-e-2" | null + readonly "n"?: number | null + readonly "response_format"?: "url" | "b64_json" | null + readonly "size"?: "256x256" | "512x512" | "1024x1024" | null + readonly "user"?: string +} +export const CreateImageVariationRequestMultipart = Schema.Struct({ + "image": __ClientMultipartFile, + "model": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Literal("dall-e-2"), Schema.Null]).annotate({ "description": - "Background type for the generated image. One of `transparent`,\n`opaque`, or `auto`. Default: `auto`.\n" + "The legacy model used by the retired image variations endpoint. This endpoint no longer accepts requests." }) ), - "input_fidelity": Schema.optionalKey(Schema.Union([InputFidelity, Schema.Null])), - "input_image_mask": Schema.optionalKey( - Schema.Struct({ - "image_url": Schema.optionalKey(Schema.String.annotate({ "description": "Base64-encoded mask image.\n" })), - "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "File ID for the mask image.\n" })) - }).annotate({ + "n": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(10).annotate({ "expected": "a value less than or equal to 10" })), + Schema.Null + ]).annotate({ "description": "The number of images to generate. Must be between 1 and 10." }) + ), + "response_format": Schema.optionalKey( + Schema.Union([Schema.Literals(["url", "b64_json"]), Schema.Null]).annotate({ "description": - "Optional mask for inpainting. Contains `image_url`\n(string, optional) and `file_id` (string, optional).\n" + "The format in which the generated images are returned. Must be one of `url` or `b64_json`. URLs are only valid for 60 minutes after the image has been generated." }) ), - "partial_images": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Number of partial images to generate in streaming mode, from 0 (default value) to 3.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(3)) + "size": Schema.optionalKey( + Schema.Union([Schema.Literals(["256x256", "512x512", "1024x1024"]), Schema.Null]).annotate({ + "description": "The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`." + }) ), - "action": Schema.optionalKey( - Schema.Literals(["generate", "edit", "auto"]).annotate({ - "description": "Whether to generate a new image or edit an existing image. Default: `auto`.\n" + "user": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" }) ) }).annotate({ - "title": "Image generation tool", - "description": "A tool that generates images using the GPT image models.\n" + "description": "Legacy request for the retired image variations endpoint.", + "identifier": "CreateImageVariationRequestMultipart" }) -export type LocalEnvironmentParam = { readonly "type": "local"; readonly "skills"?: ReadonlyArray } -export const LocalEnvironmentParam = Schema.Struct({ - "type": Schema.Literal("local").annotate({ "description": "Use a local computer environment." }), - "skills": Schema.optionalKey( - Schema.Array(LocalSkillParam).annotate({ "description": "An optional list of skills." }).check( - Schema.isMaxLength(200) - ) - ) +export type AddUploadPartRequestMultipart = { readonly "data": __ClientMultipartFile } +export const AddUploadPartRequestMultipart = Schema.Struct({ "data": __ClientMultipartFile }).annotate({ + "identifier": "AddUploadPartRequestMultipart" }) -export type CustomToolParam = { - readonly "type": "custom" - readonly "name": string - readonly "description"?: string - readonly "format"?: CustomTextFormatParam | CustomGrammarFormatParam - readonly "defer_loading"?: boolean +export type CreateContentProvenanceBodyMultipart = { readonly "file": __ClientMultipartFile } +export const CreateContentProvenanceBodyMultipart = Schema.Struct({ "file": __ClientMultipartFile }).annotate({ + "identifier": "CreateContentProvenanceBodyMultipart" +}) +export type CreateVideoCharacterBodyMultipart = { readonly "video": __ClientMultipartFile; readonly "name": string } +export const CreateVideoCharacterBodyMultipart = Schema.Struct({ + "video": __ClientMultipartFile, + "name": Schema.String.annotate({ "description": "Display name for this API character." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(80).annotate({ "expected": "a string with at most 80 code points" })) +}).annotate({ + "title": "Create character request", + "description": "Parameters for creating a character from an uploaded video.", + "identifier": "CreateVideoCharacterBodyMultipart" +}) +export type CreateSkillBodyMultipart = { + readonly "files": ReadonlyArray<__ClientMultipartFile> | __ClientMultipartFile } -export const CustomToolParam = Schema.Struct({ - "type": Schema.Literal("custom").annotate({ "description": "The type of the custom tool. Always `custom`." }), - "name": Schema.String.annotate({ "description": "The name of the custom tool, used to identify it in tool calls." }), - "description": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional description of the custom tool, used to provide more context." }) - ), - "format": Schema.optionalKey( - Schema.Union([CustomTextFormatParam, CustomGrammarFormatParam], { mode: "oneOf" }).annotate({ - "description": "The input format for the custom tool. Default is unconstrained text." - }) - ), - "defer_loading": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether this tool should be deferred and discovered via tool search." }) - ) +export const CreateSkillBodyMultipart = Schema.Struct({ + "files": Schema.Union([ + Schema.Array(__ClientMultipartFile).annotate({ + "description": "Skill files to upload (directory upload) or a single zip file." + }).check(Schema.isMaxLength(500).annotate({ "expected": "a value with a length of at most 500" })), + __ClientMultipartFile + ], { mode: "oneOf" }) }).annotate({ - "title": "Custom tool", - "description": - "A custom tool that processes input using a specified format. Learn more about [custom tools](/docs/guides/function-calling#custom-tools)" + "title": "Create skill request", + "description": "Uploads a skill either as a directory (multipart `files[]`) or as a single zip file.", + "identifier": "CreateSkillBodyMultipart" }) -export type FunctionToolParam = { - readonly "name": string - readonly "description"?: string | null - readonly "parameters"?: EmptyModelParam | null - readonly "strict"?: boolean | null - readonly "type": "function" - readonly "defer_loading"?: boolean +export type CreateSkillVersionBodyMultipart = { + readonly "files": ReadonlyArray<__ClientMultipartFile> | __ClientMultipartFile + readonly "default"?: boolean } -export const FunctionToolParam = Schema.Struct({ - "name": Schema.String.check(Schema.isMinLength(1)).check(Schema.isMaxLength(128)).check( - Schema.isPattern(new RegExp("^[a-zA-Z0-9_-]+$")) - ), - "description": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "parameters": Schema.optionalKey(Schema.Union([EmptyModelParam, Schema.Null])), - "strict": Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])), - "type": Schema.Literal("function"), - "defer_loading": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": "Whether this function should be deferred and discovered via tool search." - }) +export const CreateSkillVersionBodyMultipart = Schema.Struct({ + "files": Schema.Union([ + Schema.Array(__ClientMultipartFile).annotate({ + "description": "Skill files to upload (directory upload) or a single zip file." + }).check(Schema.isMaxLength(500).annotate({ "expected": "a value with a length of at most 500" })), + __ClientMultipartFile + ], { mode: "oneOf" }), + "default": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether to set this version as the default." }) ) +}).annotate({ + "title": "Create skill version request", + "description": "Uploads a new immutable version of a skill.", + "identifier": "CreateSkillVersionBodyMultipart" }) -export type WebSearchPreviewTool = { - readonly "type": "web_search_preview" | "web_search_preview_2025_03_11" - readonly "user_location"?: { - readonly "type": "approximate" - readonly "country"?: string | null - readonly "region"?: string | null - readonly "city"?: string | null - readonly "timezone"?: string | null - } | null - readonly "search_context_size"?: "low" | "medium" | "high" - readonly "search_content_types"?: ReadonlyArray +export type CreateTranscriptionRequestMultipart = { + readonly "file": __ClientMultipartFile + readonly "model": + | string + | "whisper-1" + | "gpt-transcribe" + | "gpt-4o-transcribe" + | "gpt-4o-mini-transcribe" + | "gpt-4o-mini-transcribe-2025-12-15" + | "gpt-4o-transcribe-diarize" + readonly "language"?: string + readonly "languages"?: ReadonlyArray + readonly "keywords"?: ReadonlyArray + readonly "prompt"?: string + readonly "response_format"?: AudioResponseFormat + readonly "temperature"?: number + readonly "include"?: ReadonlyArray + readonly "timestamp_granularities"?: ReadonlyArray<"word" | "segment"> + readonly "stream"?: boolean | null + readonly "chunking_strategy"?: "auto" | VadConfig | null + readonly "known_speaker_names"?: ReadonlyArray + readonly "known_speaker_references"?: ReadonlyArray } -export const WebSearchPreviewTool = Schema.Struct({ - "type": Schema.Literals(["web_search_preview", "web_search_preview_2025_03_11"]).annotate({ - "description": "The type of the web search tool. One of `web_search_preview` or `web_search_preview_2025_03_11`." +export const CreateTranscriptionRequestMultipart = Schema.Struct({ + "file": __ClientMultipartFile, + "model": Schema.Union([ + Schema.String, + Schema.Literals([ + "whisper-1", + "gpt-transcribe", + "gpt-4o-transcribe", + "gpt-4o-mini-transcribe", + "gpt-4o-mini-transcribe-2025-12-15", + "gpt-4o-transcribe-diarize" + ]) + ]).annotate({ + "description": + "ID of the model to use. The options are `gpt-transcribe`, `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `whisper-1` (which is powered by our open source Whisper V2 model), and `gpt-4o-transcribe-diarize`.\n" }), - "user_location": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("approximate").annotate({ - "description": "The type of location approximation. Always `approximate`." + "language": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format will improve accuracy and latency.\n" + }) + ), + "languages": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "Possible languages of the input audio, in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format. Supported by `gpt-transcribe`.\n" + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ), + "keywords": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "Words or phrases to guide transcription of the input audio. Supported by `gpt-transcribe`.\n" + }) + ), + "prompt": Schema.optionalKey(Schema.String.annotate({ + "description": + "An optional text to guide the model's style or continue a previous audio segment. The [prompt](https://developers.openai.com/api/docs/guides/speech-to-text#prompting) should match the audio language. This field is not supported when using `gpt-4o-transcribe-diarize`.\n" + })), + "response_format": Schema.optionalKey(AudioResponseFormat), + "temperature": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "include": Schema.optionalKey( + Schema.Array(TranscriptionInclude).annotate({ + "description": + "Additional information to include in the transcription response.\n`logprobs` will return the log probabilities of the tokens in the\nresponse to understand the model's confidence in the transcription.\n`logprobs` only works with response_format set to `json` and only with\nthe models `gpt-4o-transcribe`, `gpt-4o-mini-transcribe`, and `gpt-4o-mini-transcribe-2025-12-15`. This field is not supported when using `gpt-4o-transcribe-diarize`.\n" + }) + ), + "timestamp_granularities": Schema.optionalKey( + Schema.Array(Schema.Literals(["word", "segment"])).annotate({ + "description": + "The timestamp granularities to populate for this transcription. `response_format` must be set `verbose_json` to use timestamp granularities. Either or both of these options are supported: `word`, or `segment`. Note: There is no additional latency for segment timestamps, but generating word timestamps incurs additional latency.\nThis option is not available for `gpt-4o-transcribe-diarize`.\n" + }) + ), + "stream": Schema.optionalKey(Schema.Union([ + Schema.Boolean.annotate({ + "description": + "If set to true, the model response data will be streamed to the client\nas it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).\nSee the [Streaming section of the Speech-to-Text guide](https://developers.openai.com/api/docs/guides/speech-to-text?lang=curl#streaming)\nfor more information.\n\nNote: Streaming is not supported for the `whisper-1` model and will be ignored.\n" + }), + Schema.Null + ])), + "chunking_strategy": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.Literal("auto").annotate({ + "description": "Automatically set chunking parameters based on the audio. Must be set to `\"auto\"`.\n" + }), + VadConfig + ]).annotate({ + "description": + "Controls how the audio is cut into chunks. When set to `\"auto\"`, the server first normalizes loudness and then uses voice activity detection (VAD) to choose boundaries. `server_vad` object can be provided to tweak VAD detection parameters manually. If unset, the audio is transcribed as a single block. Required when using `gpt-4o-transcribe-diarize` for inputs longer than 30 seconds. " }), - "country": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of the user, e.g. `US`." - }), - Schema.Null - ]) - ), - "region": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "Free text input for the region of the user, e.g. `California`." }), - Schema.Null - ]) + Schema.Null + ]) + ), + "known_speaker_names": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "Optional list of speaker names that correspond to the audio samples provided in `known_speaker_references[]`. Each entry should be a short identifier (for example `customer` or `agent`). Up to 4 speakers are supported.\n" + }).check(Schema.isMaxLength(4).annotate({ "expected": "a value with a length of at most 4" })) + ), + "known_speaker_references": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "Optional list of audio samples (as [data URLs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)) that contain known speaker references matching `known_speaker_names[]`. Each sample must be between 2 and 10 seconds, and can use any of the same input audio formats supported by `file`.\n" + }).check(Schema.isMaxLength(4).annotate({ "expected": "a value with a length of at most 4" })) + ) +}).annotate({ "identifier": "CreateTranscriptionRequestMultipart" }) +export type TranscriptTextDoneEvent = { + readonly "type": "transcript.text.done" + readonly "text": string + readonly "languages"?: ReadonlyArray + readonly "logprobs"?: ReadonlyArray< + { readonly "token"?: string; readonly "logprob"?: number; readonly "bytes"?: ReadonlyArray } + > + readonly "usage"?: TranscriptTextUsageTokens +} +export const TranscriptTextDoneEvent = Schema.Struct({ + "type": Schema.Literal("transcript.text.done").annotate({ + "description": "The type of the event. Always `transcript.text.done`.\n" + }), + "text": Schema.String.annotate({ "description": "The text that was transcribed.\n" }), + "languages": Schema.optionalKey( + Schema.Array(TranscriptionLanguage).annotate({ + "description": + "The languages detected in the audio. Returned by `gpt-transcribe`. An empty array indicates that no language could be reliably detected.\n" + }) + ), + "logprobs": Schema.optionalKey( + Schema.Array(Schema.Struct({ + "token": Schema.optionalKey( + Schema.String.annotate({ "description": "The token that was used to generate the log probability.\n" }) ), - "city": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "Free text input for the city of the user, e.g. `San Francisco`." }), - Schema.Null - ]) + "logprob": Schema.optionalKey( + Schema.Number.annotate({ "description": "The log probability of the token.\n" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) ), - "timezone": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the user, e.g. `America/Los_Angeles`." - }), - Schema.Null - ]) + "bytes": Schema.optionalKey( + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).annotate({ + "description": "The bytes that were used to generate the log probability.\n" + }) ) - }).annotate({ "description": "The user's location." }), - Schema.Null - ])), - "search_context_size": Schema.optionalKey( - Schema.Literals(["low", "medium", "high"]).annotate({ + })).annotate({ "description": - "High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default." + "The log probabilities of the individual tokens in the transcription. Only included if you [create a transcription](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create) with the `include[]` parameter set to `logprobs`.\n" }) ), - "search_content_types": Schema.optionalKey(Schema.Array(SearchContentType)) + "usage": Schema.optionalKey(TranscriptTextUsageTokens) }).annotate({ - "title": "Web search preview", "description": - "This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://platform.openai.com/docs/guides/tools-web-search)." + "Emitted when the transcription is complete. Contains the complete transcription text. Only emitted when you [create a transcription](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create) with the `Stream` parameter set to `true`.", + "identifier": "TranscriptTextDoneEvent" }) -export type CodeInterpreterToolCall = { - readonly "type": "code_interpreter_call" - readonly "id": string - readonly "status": "in_progress" | "completed" | "incomplete" | "interpreting" | "failed" - readonly "container_id": string - readonly "code": string | null - readonly "outputs": ReadonlyArray | null +export type CreateTranscriptionResponseJson = { + readonly "text": string + readonly "languages"?: ReadonlyArray + readonly "logprobs"?: ReadonlyArray< + { readonly "token"?: string; readonly "logprob"?: number; readonly "bytes"?: ReadonlyArray } + > + readonly "usage"?: TranscriptTextUsageTokens | TranscriptTextUsageDuration } -export const CodeInterpreterToolCall = Schema.Struct({ - "type": Schema.Literal("code_interpreter_call").annotate({ - "description": "The type of the code interpreter tool call. Always `code_interpreter_call`.\n" - }), - "id": Schema.String.annotate({ "description": "The unique ID of the code interpreter tool call.\n" }), - "status": Schema.Literals(["in_progress", "completed", "incomplete", "interpreting", "failed"]).annotate({ - "description": - "The status of the code interpreter tool call. Valid values are `in_progress`, `completed`, `incomplete`, `interpreting`, and `failed`.\n" - }), - "container_id": Schema.String.annotate({ "description": "The ID of the container used to run the code.\n" }), - "code": Schema.Union([ - Schema.String.annotate({ "description": "The code to run, or null if not available.\n" }), - Schema.Null - ]), - "outputs": Schema.Union([ - Schema.Array(Schema.Union([CodeInterpreterOutputLogs, CodeInterpreterOutputImage], { mode: "oneOf" })).annotate({ +export const CreateTranscriptionResponseJson = Schema.Struct({ + "text": Schema.String.annotate({ "description": "The transcribed text." }), + "languages": Schema.optionalKey( + Schema.Array(TranscriptionLanguage).annotate({ "description": - "The outputs generated by the code interpreter, such as logs or images.\nCan be null if no outputs are available.\n" - }), - Schema.Null - ]) -}).annotate({ "title": "Code interpreter tool call", "description": "A tool call to run code.\n" }) -export type LocalShellToolCall = { - readonly "type": "local_shell_call" - readonly "id": string - readonly "call_id": string - readonly "action": LocalShellExecAction - readonly "status": "in_progress" | "completed" | "incomplete" + "The languages detected in the audio. Returned by `gpt-transcribe`. An empty array indicates that no language could be reliably detected.\n" + }) + ), + "logprobs": Schema.optionalKey( + Schema.Array(Schema.Struct({ + "token": Schema.optionalKey(Schema.String.annotate({ "description": "The token in the transcription." })), + "logprob": Schema.optionalKey( + Schema.Number.annotate({ "description": "The log probability of the token." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) + ), + "bytes": Schema.optionalKey(Schema.Array(Schema.Finite).annotate({ "description": "The bytes of the token." })) + })).annotate({ + "description": + "The log probabilities of the tokens in the transcription. Only returned with the models `gpt-4o-transcribe` and `gpt-4o-mini-transcribe` if `logprobs` is added to the `include` array.\n" + }) + ), + "usage": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => TranscriptTextUsageTokens).annotate({ + "title": "Token Usage" + }), + Schema.suspend((): Schema.Codec => TranscriptTextUsageDuration).annotate({ + "title": "Duration Usage" + }) + ], { mode: "oneOf" }).annotate({ "description": "Token usage statistics for the request." }) + ) +}).annotate({ + "description": "Represents a transcription response returned by model, based on the provided input.", + "identifier": "CreateTranscriptionResponseJson" +}) +export type CreateTranscriptionResponseDiarizedJson = { + readonly "task": "transcribe" + readonly "duration": number + readonly "text": string + readonly "segments": ReadonlyArray + readonly "usage"?: TranscriptTextUsageTokens | TranscriptTextUsageDuration } -export const LocalShellToolCall = Schema.Struct({ - "type": Schema.Literal("local_shell_call").annotate({ - "description": "The type of the local shell call. Always `local_shell_call`.\n" - }), - "id": Schema.String.annotate({ "description": "The unique ID of the local shell call.\n" }), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the local shell tool call generated by the model.\n" +export const CreateTranscriptionResponseDiarizedJson = Schema.Struct({ + "task": Schema.Literal("transcribe").annotate({ + "description": "The type of task that was run. Always `transcribe`." }), - "action": LocalShellExecAction, - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": "The status of the local shell call.\n" - }) -}).annotate({ "title": "Local shell call", "description": "A tool call to run a command on the local shell.\n" }) -export type FunctionShellCall = { - readonly "type": "shell_call" - readonly "id": string - readonly "call_id": string - readonly "action": { - readonly "commands": ReadonlyArray - readonly "timeout_ms": number | null - readonly "max_output_length": number | null - } - readonly "status": "in_progress" | "completed" | "incomplete" - readonly "environment": LocalEnvironmentResource | ContainerReferenceResource | null - readonly "created_by"?: string -} -export const FunctionShellCall = Schema.Struct({ - "type": Schema.Literal("shell_call").annotate({ "description": "The type of the item. Always `shell_call`." }), - "id": Schema.String.annotate({ - "description": "The unique ID of the shell tool call. Populated when this item is returned via API." + "duration": Schema.Number.annotate({ "description": "Duration of the input audio in seconds.", "format": "double" }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "text": Schema.String.annotate({ "description": "The concatenated transcript text for the entire audio input." }), + "segments": Schema.Array(TranscriptionDiarizedSegment).annotate({ + "description": "Segments of the transcript annotated with timestamps and speaker labels." }), - "call_id": Schema.String.annotate({ "description": "The unique ID of the shell tool call generated by the model." }), - "action": Schema.Struct({ - "commands": Schema.Array(Schema.String.annotate({ "description": "A list of commands to run." })), - "timeout_ms": Schema.Union([ - Schema.Number.annotate({ "description": "Optional timeout in milliseconds for the commands." }).check( - Schema.isInt() - ), - Schema.Null - ]), - "max_output_length": Schema.Union([ - Schema.Number.annotate({ "description": "Optional maximum number of characters to return from each command." }) - .check(Schema.isInt()), - Schema.Null - ]) - }).annotate({ - "title": "Shell exec action", - "description": "The shell commands and limits that describe how to run the tool call." - }), - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": "The status of the shell call. One of `in_progress`, `completed`, or `incomplete`." - }), - "environment": Schema.Union([ - Schema.Union([LocalEnvironmentResource, ContainerReferenceResource], { mode: "oneOf" }), - Schema.Null - ]), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the entity that created this tool call." }) - ) -}).annotate({ - "title": "Shell tool call", - "description": "A tool call that executes one or more shell commands in a managed environment." -}) -export type FunctionShellCallOutputContent = { - readonly "stdout": string - readonly "stderr": string - readonly "outcome": FunctionShellCallOutputTimeoutOutcome | FunctionShellCallOutputExitOutcome - readonly "created_by"?: string -} -export const FunctionShellCallOutputContent = Schema.Struct({ - "stdout": Schema.String.annotate({ "description": "The standard output that was captured." }), - "stderr": Schema.String.annotate({ "description": "The standard error output that was captured." }), - "outcome": Schema.Union([FunctionShellCallOutputTimeoutOutcome, FunctionShellCallOutputExitOutcome], { - mode: "oneOf" - }).annotate({ - "title": "Shell call outcome", - "description": - "Represents either an exit outcome (with an exit code) or a timeout outcome for a shell call output chunk." - }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) - ) -}).annotate({ - "title": "Shell call output content", - "description": "The content of a shell tool call output that was emitted." -}) -export type ApplyPatchToolCall = { - readonly "type": "apply_patch_call" - readonly "id": string - readonly "call_id": string - readonly "status": "in_progress" | "completed" - readonly "operation": ApplyPatchCreateFileOperation | ApplyPatchDeleteFileOperation | ApplyPatchUpdateFileOperation - readonly "created_by"?: string -} -export const ApplyPatchToolCall = Schema.Struct({ - "type": Schema.Literal("apply_patch_call").annotate({ - "description": "The type of the item. Always `apply_patch_call`." - }), - "id": Schema.String.annotate({ - "description": "The unique ID of the apply patch tool call. Populated when this item is returned via API." - }), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the apply patch tool call generated by the model." - }), - "status": Schema.Literals(["in_progress", "completed"]).annotate({ - "description": "The status of the apply patch tool call. One of `in_progress` or `completed`." - }), - "operation": Schema.Union([ - ApplyPatchCreateFileOperation, - ApplyPatchDeleteFileOperation, - ApplyPatchUpdateFileOperation - ], { mode: "oneOf" }).annotate({ - "title": "Apply patch operation", - "description": "One of the create_file, delete_file, or update_file operations applied via apply_patch." - }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the entity that created this tool call." }) + "usage": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => TranscriptTextUsageTokens).annotate({ + "title": "Token Usage" + }), + Schema.suspend((): Schema.Codec => TranscriptTextUsageDuration).annotate({ + "title": "Duration Usage" + }) + ], { mode: "oneOf" }).annotate({ "description": "Token or duration usage statistics for the request." }) ) }).annotate({ - "title": "Apply patch tool call", - "description": "A tool call that applies file diffs by creating, deleting, or updating files." -}) -export type FunctionShellCallOutputContentParam = { - readonly "stdout": string - readonly "stderr": string - readonly "outcome": FunctionShellCallOutputTimeoutOutcomeParam | FunctionShellCallOutputExitOutcomeParam -} -export const FunctionShellCallOutputContentParam = Schema.Struct({ - "stdout": Schema.String.annotate({ "description": "Captured stdout output for the shell call." }).check( - Schema.isMaxLength(10485760) - ), - "stderr": Schema.String.annotate({ "description": "Captured stderr output for the shell call." }).check( - Schema.isMaxLength(10485760) - ), - "outcome": Schema.Union([FunctionShellCallOutputTimeoutOutcomeParam, FunctionShellCallOutputExitOutcomeParam], { - mode: "oneOf" - }).annotate({ - "title": "Shell call outcome", - "description": "The exit or timeout outcome associated with this shell call." - }) -}).annotate({ - "title": "Shell output content", - "description": "Captured stdout and stderr for a portion of a shell tool call output." -}) -export type ImageGenUsage = { - readonly "input_tokens": number - readonly "total_tokens": number - readonly "output_tokens": number - readonly "output_tokens_details"?: ImageGenOutputTokensDetails - readonly "input_tokens_details": ImageGenInputUsageDetails -} -export const ImageGenUsage = Schema.Struct({ - "input_tokens": Schema.Number.annotate({ - "description": "The number of tokens (images and text) in the input prompt." - }).check(Schema.isInt()), - "total_tokens": Schema.Number.annotate({ - "description": "The total number of tokens (images and text) used for the image generation." - }).check(Schema.isInt()), - "output_tokens": Schema.Number.annotate({ "description": "The number of output tokens generated by the model." }) - .check(Schema.isInt()), - "output_tokens_details": Schema.optionalKey(ImageGenOutputTokensDetails), - "input_tokens_details": ImageGenInputUsageDetails -}).annotate({ - "title": "Image generation usage", - "description": "For `gpt-image-1` only, the token usage information for the image generation." -}) -export type ToolChoiceParam = - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam -export const ToolChoiceParam = Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam -], { mode: "oneOf" }).annotate({ - "description": - "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n" -}) -export type ConversationParam = string | ConversationParam_2 -export const ConversationParam = Schema.Union([ - Schema.String.annotate({ "title": "Conversation ID", "description": "The unique ID of the conversation.\n" }), - ConversationParam_2 -], { mode: "oneOf" }).annotate({ "description": - "The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request.\nInput items and output items from this response are automatically added to this conversation after this response completes.\n" -}) -export type VideoListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string | null - readonly "last_id": string | null - readonly "has_more": boolean -} -export const VideoListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), - "data": Schema.Array(VideoResource).annotate({ "description": "A list of items" }), - "first_id": Schema.Union([ - Schema.String.annotate({ "description": "The ID of the first item in the list." }), - Schema.Null - ]), - "last_id": Schema.Union([ - Schema.String.annotate({ "description": "The ID of the last item in the list." }), - Schema.Null - ]), - "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) + "Represents a diarized transcription response returned by the model, including the combined transcript and speaker-segment annotations.\n", + "identifier": "CreateTranscriptionResponseDiarizedJson" }) -export type CreateVideoMultipartBody = { - readonly "model"?: - | string - | "sora-2" - | "sora-2-pro" - | "sora-2-2025-10-06" - | "sora-2-pro-2025-10-06" - | "sora-2-2025-12-08" - readonly "prompt": string - readonly "input_reference"?: string | ImageRefParam_2 - readonly "seconds"?: "4" | "8" | "12" - readonly "size"?: "720x1280" | "1280x720" | "1024x1792" | "1792x1024" +export type CreateTranscriptionResponseVerboseJson = { + readonly "language": string + readonly "duration": number + readonly "text": string + readonly "words"?: ReadonlyArray + readonly "segments"?: ReadonlyArray + readonly "usage"?: TranscriptTextUsageDuration } -export const CreateVideoMultipartBody = Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals(["sora-2", "sora-2-pro", "sora-2-2025-10-06", "sora-2-pro-2025-10-06", "sora-2-2025-12-08"]) - ]).annotate({ - "description": "The video generation model to use (allowed values: sora-2, sora-2-pro). Defaults to `sora-2`." - }) +export const CreateTranscriptionResponseVerboseJson = Schema.Struct({ + "language": Schema.String.annotate({ "description": "The language of the input audio." }), + "duration": Schema.Number.annotate({ "description": "The duration of the input audio.", "format": "double" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) ), - "prompt": Schema.String.annotate({ "description": "Text prompt that describes the video to generate." }).check( - Schema.isMinLength(1) - ).check(Schema.isMaxLength(32000)), - "input_reference": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "Optional reference asset upload or reference object that guides generation.", - "format": "binary" - }), - ImageRefParam_2 - ], { mode: "oneOf" }) + "text": Schema.String.annotate({ "description": "The transcribed text." }), + "words": Schema.optionalKey( + Schema.Array(TranscriptionWord).annotate({ "description": "Extracted words and their corresponding timestamps." }) ), - "seconds": Schema.optionalKey( - Schema.Literals(["4", "8", "12"]).annotate({ - "description": "Clip duration in seconds (allowed values: 4, 8, 12). Defaults to 4 seconds." + "segments": Schema.optionalKey( + Schema.Array(TranscriptionSegment).annotate({ + "description": "Segments of the transcribed text and their corresponding details." }) ), - "size": Schema.optionalKey( - Schema.Literals(["720x1280", "1280x720", "1024x1792", "1792x1024"]).annotate({ - "description": - "Output resolution formatted as width x height (allowed values: 720x1280, 1280x720, 1024x1792, 1792x1024). Defaults to 720x1280." - }) - ) -}).annotate({ - "title": "Create video multipart request", - "description": "Multipart parameters for creating a new video generation job." -}) -export type CreateVideoEditMultipartBody = { - readonly "video": string | VideoReferenceInputParam - readonly "prompt": string -} -export const CreateVideoEditMultipartBody = Schema.Struct({ - "video": Schema.Union([ - Schema.String.annotate({ "description": "Reference to the completed video to edit.", "format": "binary" }), - VideoReferenceInputParam - ], { mode: "oneOf" }), - "prompt": Schema.String.annotate({ "description": "Text prompt that describes how to edit the source video." }).check( - Schema.isMinLength(1) - ).check(Schema.isMaxLength(32000)) + "usage": Schema.optionalKey(TranscriptTextUsageDuration) }).annotate({ - "title": "Create video edit multipart request", - "description": "Parameters for editing an existing generated video." + "description": "Represents a verbose json transcription response returned by model, based on the provided input.", + "identifier": "CreateTranscriptionResponseVerboseJson" }) -export type CreateVideoExtendMultipartBody = { - readonly "video": VideoReferenceInputParam | string - readonly "prompt": string - readonly "seconds": "4" | "8" | "12" +export type CreateTranslationResponseVerboseJson = { + readonly "language": string + readonly "duration": number + readonly "text": string + readonly "segments"?: ReadonlyArray } -export const CreateVideoExtendMultipartBody = Schema.Struct({ - "video": Schema.Union([ - VideoReferenceInputParam, - Schema.String.annotate({ "description": "Reference to the completed video to extend.", "format": "binary" }) - ], { mode: "oneOf" }), - "prompt": Schema.String.annotate({ "description": "Updated text prompt that directs the extension generation." }) - .check(Schema.isMinLength(1)).check(Schema.isMaxLength(32000)), - "seconds": Schema.Literals(["4", "8", "12"]).annotate({ - "description": "Length of the newly generated extension segment in seconds (allowed values: 4, 8, 12, 16, 20)." - }) -}).annotate({ - "title": "Create video extension multipart request", - "description": "Multipart parameters for extending an existing generated video." -}) -export type SkillListResource = { +export const CreateTranslationResponseVerboseJson = Schema.Struct({ + "language": Schema.String.annotate({ "description": "The language of the output translation (always `english`)." }), + "duration": Schema.Number.annotate({ "description": "The duration of the input audio.", "format": "double" }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "text": Schema.String.annotate({ "description": "The translated text." }), + "segments": Schema.optionalKey( + Schema.Array(TranscriptionSegment).annotate({ + "description": "Segments of the translated text and their corresponding details." + }) + ) +}).annotate({ "identifier": "CreateTranslationResponseVerboseJson" }) +export type VoiceConsentListResource = { readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string | null - readonly "last_id": string | null + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null readonly "has_more": boolean } -export const SkillListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), - "data": Schema.Array(SkillResource).annotate({ "description": "A list of items" }), - "first_id": Schema.Union([ - Schema.String.annotate({ "description": "The ID of the first item in the list." }), - Schema.Null - ]), - "last_id": Schema.Union([ - Schema.String.annotate({ "description": "The ID of the last item in the list." }), - Schema.Null - ]), - "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) -}) -export type SkillVersionListResource = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string | null - readonly "last_id": string | null - readonly "has_more": boolean -} -export const SkillVersionListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), - "data": Schema.Array(SkillVersionResource).annotate({ "description": "A list of items" }), - "first_id": Schema.Union([ - Schema.String.annotate({ "description": "The ID of the first item in the list." }), - Schema.Null - ]), - "last_id": Schema.Union([ - Schema.String.annotate({ "description": "The ID of the last item in the list." }), - Schema.Null - ]), - "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) -}) -export type UserMessageItem = { +export const VoiceConsentListResource = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(VoiceConsentResource), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "VoiceConsentListResource" }) +export type Batch = { readonly "id": string - readonly "object": "chatkit.thread_item" + readonly "object": "batch" + readonly "endpoint": string + readonly "model"?: string + readonly "errors"?: + | { readonly "object"?: string; readonly "data"?: ReadonlyArray } & { + readonly [x: string]: Schema.Json + } + | null + readonly "input_file_id": string + readonly "completion_window": string + readonly "status": + | "validating" + | "failed" + | "in_progress" + | "finalizing" + | "completed" + | "expired" + | "cancelling" + | "cancelled" + readonly "output_file_id"?: string | null + readonly "error_file_id"?: string | null readonly "created_at": number - readonly "thread_id": string - readonly "type": "chatkit.user_message" - readonly "content": ReadonlyArray - readonly "attachments": ReadonlyArray - readonly "inference_options": { - readonly "tool_choice": { readonly "id": string } | null - readonly "model": string | null - } | null + readonly "in_progress_at"?: number | null + readonly "expires_at"?: number | null + readonly "finalizing_at"?: number | null + readonly "completed_at"?: number | null + readonly "failed_at"?: number | null + readonly "expired_at"?: number | null + readonly "cancelling_at"?: number | null + readonly "cancelled_at"?: number | null + readonly "request_counts"?: BatchRequestCounts + readonly "usage"?: { + readonly "input_tokens": number + readonly "input_tokens_details": { readonly "cached_tokens": number } + readonly "output_tokens": number + readonly "output_tokens_details": { readonly "reasoning_tokens": number } + readonly "total_tokens": number + } + readonly "metadata"?: Metadata } -export const UserMessageItem = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), - "object": Schema.Literal("chatkit.thread_item").annotate({ - "description": "Type discriminator that is always `chatkit.thread_item`." +export const Batch = Schema.Struct({ + "id": Schema.String, + "object": Schema.Literal("batch").annotate({ "description": "The object type, which is always `batch`." }), + "endpoint": Schema.String.annotate({ "description": "The OpenAI API endpoint used by the batch." }), + "model": Schema.optionalKey(Schema.String.annotate({ + "description": + "Model ID used to process the batch, like `gpt-6-astra`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model\nguide](https://developers.openai.com/api/docs/models) to browse and compare available models.\n" + })), + "errors": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "object": Schema.optionalKey( + Schema.String.annotate({ "description": "The object type, which is always `list`." }) + ), + "data": Schema.optionalKey(Schema.Array(BatchError)) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]) + ), + "input_file_id": Schema.String.annotate({ "description": "The ID of the input file for the batch." }), + "completion_window": Schema.String.annotate({ + "description": "The time frame within which the batch should be processed." }), + "status": Schema.Literals([ + "validating", + "failed", + "in_progress", + "finalizing", + "completed", + "expired", + "cancelling", + "cancelled" + ]).annotate({ "description": "The current status of the batch." }), + "output_file_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The ID of the file containing the outputs of successfully executed requests." + }) + ), + "error_file_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The ID of the file containing the outputs of requests with errors." + }) + ), "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) for when the item was created.", + "description": "The Unix timestamp (in seconds) for when the batch was created.", "format": "unixtime" - }).check(Schema.isInt()), - "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), - "type": Schema.Literal("chatkit.user_message"), - "content": Schema.Array( - Schema.Union([UserMessageInputText, UserMessageQuotedText], { mode: "oneOf" }).annotate({ - "description": "Content blocks that comprise a user message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "in_progress_at": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": "The Unix timestamp (in seconds) for when the batch started processing.", + "format": "unixtime" }) - ).annotate({ "description": "Ordered content elements supplied by the user." }), - "attachments": Schema.Array(Attachment).annotate({ - "description": "Attachments associated with the user message. Defaults to an empty list." - }), - "inference_options": Schema.Union([ + ), + "expires_at": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": "The Unix timestamp (in seconds) for when the batch will expire.", + "format": "unixtime" + }) + ), + "finalizing_at": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": "The Unix timestamp (in seconds) for when the batch started finalizing.", + "format": "unixtime" + }) + ), + "completed_at": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": "The Unix timestamp (in seconds) for when the batch was completed.", + "format": "unixtime" + }) + ), + "failed_at": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": "The Unix timestamp (in seconds) for when the batch failed.", + "format": "unixtime" + }) + ), + "expired_at": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": "The Unix timestamp (in seconds) for when the batch expired.", + "format": "unixtime" + }) + ), + "cancelling_at": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": "The Unix timestamp (in seconds) for when the batch started cancelling.", + "format": "unixtime" + }) + ), + "cancelled_at": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": "The Unix timestamp (in seconds) for when the batch was cancelled.", + "format": "unixtime" + }) + ), + "request_counts": Schema.optionalKey(BatchRequestCounts), + "usage": Schema.optionalKey( Schema.Struct({ - "tool_choice": Schema.Union([ - Schema.Struct({ "id": Schema.String.annotate({ "description": "Identifier of the requested tool." }) }) - .annotate({ - "title": "Tool choice", - "description": "Preferred tool to invoke. Defaults to null when ChatKit should auto-select." - }), - Schema.Null - ]), - "model": Schema.Union([ - Schema.String.annotate({ - "description": "Model name that generated the response. Defaults to null when using the session default." - }), - Schema.Null - ]) + "input_tokens": Schema.Number.annotate({ "description": "The number of input tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "input_tokens_details": Schema.Struct({ + "cached_tokens": Schema.Number.annotate({ + "description": + "The number of tokens that were retrieved from the cache. [More on\nprompt caching](https://developers.openai.com/api/docs/guides/prompt-caching).\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + }).annotate({ "description": "A detailed breakdown of the input tokens." }), + "output_tokens": Schema.Number.annotate({ "description": "The number of output tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "output_tokens_details": Schema.Struct({ + "reasoning_tokens": Schema.Number.annotate({ "description": "The number of reasoning tokens." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "A detailed breakdown of the output tokens." }), + "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) }).annotate({ - "title": "Inference options", - "description": "Inference overrides applied to the message. Defaults to null when unset." - }), - Schema.Null - ]) -}).annotate({ "title": "User Message Item", "description": "User-authored messages within a thread." }) -export type ResponseOutputText = { - readonly "type": "output_text" - readonly "text": string - readonly "annotations": ReadonlyArray -} -export const ResponseOutputText = Schema.Struct({ - "type": Schema.Literal("output_text").annotate({ "description": "Type discriminator that is always `output_text`." }), - "text": Schema.String.annotate({ "description": "Assistant generated text." }), - "annotations": Schema.Array( - Schema.Union([FileAnnotation, UrlAnnotation], { mode: "oneOf" }).annotate({ - "description": "Annotation object describing a cited source." + "description": + "Represents token usage details including input tokens, output tokens, a\nbreakdown of output tokens, and the total tokens used. Only populated on\nbatches created after September 7, 2025.\n" }) - ).annotate({ "description": "Ordered list of annotations attached to the response text." }) -}).annotate({ - "title": "Assistant message content", - "description": "Assistant response text accompanied by optional annotations." -}) -export type TaskGroupItem = { - readonly "id": string - readonly "object": "chatkit.thread_item" - readonly "created_at": number - readonly "thread_id": string - readonly "type": "chatkit.task_group" - readonly "tasks": ReadonlyArray + ), + "metadata": Schema.optionalKey(Metadata) +}).annotate({ "identifier": "Batch" }) +export type CreateBatchRequest = { + readonly "input_file_id": string + readonly "endpoint": + | "/v1/responses" + | "/v1/chat/completions" + | "/v1/embeddings" + | "/v1/completions" + | "/v1/moderations" + | "/v1/images/generations" + | "/v1/images/edits" + | "/v1/videos" + readonly "completion_window": "24h" + readonly "metadata"?: Metadata + readonly "output_expires_after"?: BatchFileExpirationAfter } -export const TaskGroupItem = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), - "object": Schema.Literal("chatkit.thread_item").annotate({ - "description": "Type discriminator that is always `chatkit.thread_item`." +export const CreateBatchRequest = Schema.Struct({ + "input_file_id": Schema.String.annotate({ + "description": + "The ID of an uploaded file that contains requests for the new batch.\n\nSee [upload file](https://developers.openai.com/api/reference/resources/files/methods/create) for how to upload a file.\n\nYour input file must be formatted as a [JSONL file](https://developers.openai.com/api/docs/guides/batch#1-prepare-your-batch-file), and must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, and can be up to 200 MB in size.\n" }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) for when the item was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), - "type": Schema.Literal("chatkit.task_group").annotate({ - "description": "Type discriminator that is always `chatkit.task_group`." + "endpoint": Schema.Literals([ + "/v1/responses", + "/v1/chat/completions", + "/v1/embeddings", + "/v1/completions", + "/v1/moderations", + "/v1/images/generations", + "/v1/images/edits", + "/v1/videos" + ]).annotate({ + "description": + "The endpoint to be used for all requests in the batch. Currently `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, `/v1/completions`, `/v1/moderations`, `/v1/images/generations`, `/v1/images/edits`, and `/v1/videos` are supported. Note that `/v1/embeddings` batches are also restricted to a maximum of 50,000 embedding inputs across all requests in the batch." }), - "tasks": Schema.Array(TaskGroupTask).annotate({ "description": "Tasks included in the group." }) -}).annotate({ "title": "Task group", "description": "Collection of workflow tasks grouped together in the thread." }) -export type ThreadResource = { - readonly "id": string - readonly "object": "chatkit.thread" - readonly "created_at": number - readonly "title": string | null - readonly "status": ActiveStatus | LockedStatus | ClosedStatus - readonly "user": string -} -export const ThreadResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier of the thread." }), - "object": Schema.Literal("chatkit.thread").annotate({ - "description": "Type discriminator that is always `chatkit.thread`." + "completion_window": Schema.Literal("24h").annotate({ + "description": "The time frame within which the batch should be processed. Currently only `24h` is supported." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) for when the thread was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "title": Schema.Union([ - Schema.String.annotate({ - "description": "Optional human-readable title for the thread. Defaults to null when no title has been generated." - }), - Schema.Null - ]), - "status": Schema.Union([ActiveStatus, LockedStatus, ClosedStatus], { mode: "oneOf" }).annotate({ - "description": "Current status for the thread. Defaults to `active` for newly created threads." - }), - "user": Schema.String.annotate({ - "description": "Free-form string that identifies your end user who owns the thread." - }) -}).annotate({ "title": "The thread object", "description": "Represents a ChatKit thread and its current status." }) -export type AuditLogActor = { - readonly "type"?: "session" | "api_key" - readonly "session"?: AuditLogActorSession - readonly "api_key"?: AuditLogActorApiKey -} -export const AuditLogActor = Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literals(["session", "api_key"]).annotate({ - "description": "The type of actor. Is either `session` or `api_key`." - }) - ), - "session": Schema.optionalKey(AuditLogActorSession), - "api_key": Schema.optionalKey(AuditLogActorApiKey) -}).annotate({ "description": "The actor who performed the audit logged action." }) -export type ChatCompletionToolChoiceOption = - | "none" - | "auto" - | "required" - | ChatCompletionAllowedToolsChoice - | ChatCompletionNamedToolChoice - | ChatCompletionNamedToolChoiceCustom -export const ChatCompletionToolChoiceOption = Schema.Union([ - Schema.Literals(["none", "auto", "required"]).annotate({ - "title": "Tool choice mode", - "description": - "`none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools.\n" - }), - ChatCompletionAllowedToolsChoice, - ChatCompletionNamedToolChoice, - ChatCompletionNamedToolChoiceCustom -], { mode: "oneOf" }).annotate({ - "description": - "Controls which (if any) tool is called by the model.\n`none` means the model will not call any tool and instead generates a message.\n`auto` means the model can pick between generating a message or calling one or more tools.\n`required` means the model must call one or more tools.\nSpecifying a particular tool via `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.\n\n`none` is the default when no tools are present. `auto` is the default if tools are present.\n" + "metadata": Schema.optionalKey(Metadata), + "output_expires_after": Schema.optionalKey(BatchFileExpirationAfter) +}).annotate({ "identifier": "CreateBatchRequest" }) +export type ChatCompletionMessageToolCalls = ReadonlyArray< + ChatCompletionMessageToolCall | ChatCompletionMessageCustomToolCall +> +export const ChatCompletionMessageToolCalls = Schema.Array( + Schema.Union([ChatCompletionMessageToolCall, ChatCompletionMessageCustomToolCall], { mode: "oneOf" }) +).annotate({ + "description": "The tool calls generated by the model, such as function calls.", + "identifier": "ChatCompletionMessageToolCalls" }) -export type ChatCompletionMessageList = { - readonly "object": "list" - readonly "data": ReadonlyArray< +export type CreateCompletionResponse = { + readonly "id": string + readonly "choices": ReadonlyArray< { - readonly "content": string | null - readonly "refusal": string | null - readonly "tool_calls"?: ChatCompletionMessageToolCalls - readonly "annotations"?: ReadonlyArray< - { - readonly "type": "url_citation" - readonly "url_citation": { - readonly "end_index": number - readonly "start_index": number - readonly "url": string - readonly "title": string - } - } - > - readonly "role": "assistant" - readonly "function_call"?: { readonly "arguments": string; readonly "name": string } - readonly "audio"?: { - readonly "id": string - readonly "expires_at": number - readonly "data": string - readonly "transcript": string + readonly "finish_reason": "stop" | "length" | "content_filter" | null + readonly "index": number + readonly "logprobs": { + readonly "text_offset"?: ReadonlyArray + readonly "token_logprobs"?: ReadonlyArray + readonly "tokens"?: ReadonlyArray + readonly "top_logprobs"?: ReadonlyArray<{ readonly [x: string]: number }> } | null - readonly "id": string - readonly "content_parts"?: - | ReadonlyArray - | null + readonly "text": string } > - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean + readonly "created": number + readonly "model": string + readonly "system_fingerprint"?: string + readonly "object": "text_completion" + readonly "usage"?: CompletionUsage } -export const ChatCompletionMessageList = Schema.Struct({ - "object": Schema.Literal("list").annotate({ - "description": "The type of this object. It is always set to \"list\".\n" +export const CreateCompletionResponse = Schema.Struct({ + "id": Schema.String.annotate({ "description": "A unique identifier for the completion." }), + "choices": Schema.Array(Schema.Struct({ + "finish_reason": Schema.Union([Schema.Literals(["stop", "length", "content_filter"]), Schema.Null]).annotate({ + "description": + "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\nor `content_filter` if content was omitted due to a flag from our content filters. The value is null while a streamed completion is unfinished.\n" + }), + "index": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "logprobs": Schema.Union([ + Schema.Struct({ + "text_offset": Schema.optionalKey( + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))) + ), + "token_logprobs": Schema.optionalKey(Schema.Array(Schema.Finite)), + "tokens": Schema.optionalKey(Schema.Array(Schema.String)), + "top_logprobs": Schema.optionalKey(Schema.Array(Schema.Record(Schema.String, Schema.Finite))) + }), + Schema.Null + ]), + "text": Schema.String + })).annotate({ "description": "The list of completion choices the model generated for the input prompt." }), + "created": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the completion was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "model": Schema.String.annotate({ "description": "The model used for completion." }), + "system_fingerprint": Schema.optionalKey( + Schema.String.annotate({ + "description": + "This fingerprint represents the backend configuration that the model runs with.\n\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" + }) + ), + "object": Schema.Literal("text_completion").annotate({ + "description": "The object type, which is always \"text_completion\"" }), - "data": Schema.Array( - Schema.Struct({ - "content": Schema.Union([Schema.String.annotate({ "description": "The contents of the message." }), Schema.Null]), - "refusal": Schema.Union([ - Schema.String.annotate({ "description": "The refusal message generated by the model." }), - Schema.Null - ]), - "tool_calls": Schema.optionalKey(ChatCompletionMessageToolCalls), - "annotations": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "type": Schema.Literal("url_citation").annotate({ - "description": "The type of the URL citation. Always `url_citation`." - }), - "url_citation": Schema.Struct({ - "end_index": Schema.Number.annotate({ - "description": "The index of the last character of the URL citation in the message." - }).check(Schema.isInt()), - "start_index": Schema.Number.annotate({ - "description": "The index of the first character of the URL citation in the message." - }).check(Schema.isInt()), - "url": Schema.String.annotate({ "description": "The URL of the web resource.", "format": "uri" }), - "title": Schema.String.annotate({ "description": "The title of the web resource." }) - }).annotate({ "description": "A URL citation when using web search." }) - }).annotate({ "description": "A URL citation when using web search.\n" }) - ).annotate({ - "description": - "Annotations for the message, when applicable, as when using the\n[web search tool](/docs/guides/tools-web-search?api-mode=chat).\n" - }) - ), - "role": Schema.Literal("assistant").annotate({ "description": "The role of the author of this message." }), - "function_call": Schema.optionalKey( - Schema.Struct({ - "arguments": Schema.String.annotate({ - "description": - "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - }), - "name": Schema.String.annotate({ "description": "The name of the function to call." }) - }).annotate({ - "description": - "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." - }) - ), - "audio": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "id": Schema.String.annotate({ "description": "Unique identifier for this audio response." }), - "expires_at": Schema.Number.annotate({ - "description": - "The Unix timestamp (in seconds) for when this audio response will\nno longer be accessible on the server for use in multi-turn\nconversations.\n", - "format": "unixtime" - }).check(Schema.isInt()), - "data": Schema.String.annotate({ - "description": - "Base64 encoded audio bytes generated by the model, in the format\nspecified in the request.\n" - }), - "transcript": Schema.String.annotate({ "description": "Transcript of the audio generated by the model." }) - }).annotate({ - "description": - "If the audio output modality is requested, this object contains data\nabout the audio response from the model. [Learn more](/docs/guides/audio).\n" - }), - Schema.Null - ])), - "id": Schema.String.annotate({ "description": "The identifier of the chat message." }), - "content_parts": Schema.optionalKey( - Schema.Union([ - Schema.Array( - Schema.Union([ChatCompletionRequestMessageContentPartText, ChatCompletionRequestMessageContentPartImage], { - mode: "oneOf" - }) - ).annotate({ - "description": - "If a content parts array was provided, this is an array of `text` and `image_url` parts.\nOtherwise, null.\n" - }), - Schema.Null - ]) - ) - }).annotate({ "description": "A chat completion message generated by the model." }) - ).annotate({ "description": "An array of chat completion message objects.\n" }), - "first_id": Schema.String.annotate({ "description": "The identifier of the first chat message in the data array." }), - "last_id": Schema.String.annotate({ "description": "The identifier of the last chat message in the data array." }), - "has_more": Schema.Boolean.annotate({ "description": "Indicates whether there are more chat messages available." }) + "usage": Schema.optionalKey(CompletionUsage) }).annotate({ - "title": "ChatCompletionMessageList", - "description": "An object representing a list of chat completion messages.\n" + "description": + "Represents a completion response from the API. Note: both the streamed and non-streamed response objects share the same shape (unlike the chat endpoint).\n", + "identifier": "CreateCompletionResponse" }) -export type ChatCompletionResponseMessage = { - readonly "content": string | null - readonly "refusal": string | null - readonly "tool_calls"?: ChatCompletionMessageToolCalls - readonly "annotations"?: ReadonlyArray< - { - readonly "type": "url_citation" - readonly "url_citation": { - readonly "end_index": number - readonly "start_index": number - readonly "url": string - readonly "title": string - } - } - > - readonly "role": "assistant" - readonly "function_call"?: { readonly "arguments": string; readonly "name": string } - readonly "audio"?: { - readonly "id": string - readonly "expires_at": number - readonly "data": string - readonly "transcript": string - } | null +export type ModerationResultBody = { + readonly "type": "moderation_result" + readonly "model": string + readonly "flagged": boolean + readonly "categories": { readonly [x: string]: boolean } + readonly "category_scores": { readonly [x: string]: number } + readonly "category_applied_input_types": { readonly [x: string]: ReadonlyArray } } -export const ChatCompletionResponseMessage = Schema.Struct({ - "content": Schema.Union([Schema.String.annotate({ "description": "The contents of the message." }), Schema.Null]), - "refusal": Schema.Union([ - Schema.String.annotate({ "description": "The refusal message generated by the model." }), - Schema.Null - ]), - "tool_calls": Schema.optionalKey(ChatCompletionMessageToolCalls), - "annotations": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "type": Schema.Literal("url_citation").annotate({ - "description": "The type of the URL citation. Always `url_citation`." - }), - "url_citation": Schema.Struct({ - "end_index": Schema.Number.annotate({ - "description": "The index of the last character of the URL citation in the message." - }).check(Schema.isInt()), - "start_index": Schema.Number.annotate({ - "description": "The index of the first character of the URL citation in the message." - }).check(Schema.isInt()), - "url": Schema.String.annotate({ "description": "The URL of the web resource.", "format": "uri" }), - "title": Schema.String.annotate({ "description": "The title of the web resource." }) - }).annotate({ "description": "A URL citation when using web search." }) - }).annotate({ "description": "A URL citation when using web search.\n" }) - ).annotate({ +export const ModerationResultBody = Schema.Struct({ + "type": Schema.Literal("moderation_result").annotate({ + "description": "The object type, which was always `moderation_result` for successful moderation results." + }), + "model": Schema.String.annotate({ "description": "The moderation model that produced this result." }), + "flagged": Schema.Boolean.annotate({ + "description": "A boolean indicating whether the content was flagged by any category." + }), + "categories": Schema.Record(Schema.String, Schema.Boolean).annotate({ + "description": + "A dictionary of moderation categories to booleans, True if the input is flagged under this category." + }), + "category_scores": Schema.Record(Schema.String, Schema.Finite).annotate({ + "description": "A dictionary of moderation categories to scores." + }), + "category_applied_input_types": Schema.Record(Schema.String, Schema.Array(ModerationInputType)).annotate({ + "description": "Which modalities of input are reflected by the score for each category." + }) +}).annotate({ + "title": "Moderation result", + "description": "A moderation result produced for the response input or output.", + "identifier": "ModerationResultBody" +}) +export type PromptCacheOptionsParam = { readonly "ttl"?: PromptCacheTTLEnum; readonly "mode"?: PromptCacheModeEnum } +export const PromptCacheOptionsParam = Schema.Struct({ + "ttl": Schema.optionalKey( + Schema.suspend((): Schema.Codec => PromptCacheTTLEnum).annotate({ "description": - "Annotations for the message, when applicable, as when using the\n[web search tool](/docs/guides/tools-web-search?api-mode=chat).\n" + "The minimum lifetime applied to every implicit and explicit cache breakpoint written by the request. Defaults to `30m`, which is currently the only supported value. The backend may retain cache entries for longer." }) ), - "role": Schema.Literal("assistant").annotate({ "description": "The role of the author of this message." }), - "function_call": Schema.optionalKey( - Schema.Struct({ - "arguments": Schema.String.annotate({ - "description": - "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - }), - "name": Schema.String.annotate({ "description": "The name of the function to call." }) - }).annotate({ + "mode": Schema.optionalKey( + Schema.suspend((): Schema.Codec => PromptCacheModeEnum).annotate({ "description": - "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." + "Controls whether OpenAI automatically creates an implicit cache breakpoint. Defaults to `implicit`. With `implicit`, OpenAI creates one implicit breakpoint and writes up to the latest three explicit breakpoints in the request. With `explicit`, OpenAI does not create an implicit breakpoint and writes up to the latest four explicit breakpoints. If there are no explicit breakpoints, the request does not use prompt caching." }) - ), - "audio": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "id": Schema.String.annotate({ "description": "Unique identifier for this audio response." }), - "expires_at": Schema.Number.annotate({ - "description": - "The Unix timestamp (in seconds) for when this audio response will\nno longer be accessible on the server for use in multi-turn\nconversations.\n", - "format": "unixtime" - }).check(Schema.isInt()), - "data": Schema.String.annotate({ - "description": "Base64 encoded audio bytes generated by the model, in the format\nspecified in the request.\n" - }), - "transcript": Schema.String.annotate({ "description": "Transcript of the audio generated by the model." }) - }).annotate({ - "description": - "If the audio output modality is requested, this object contains data\nabout the audio response from the model. [Learn more](/docs/guides/audio).\n" - }), - Schema.Null - ])) -}).annotate({ "description": "A chat completion message generated by the model." }) -export type CreateChatCompletionStreamResponse = { - readonly "id": string - readonly "choices": ReadonlyArray< - { - readonly "delta": ChatCompletionStreamResponseDelta - readonly "logprobs"?: { - readonly "content": ReadonlyArray< - { - readonly "token": string - readonly "logprob": number - readonly "bytes": ReadonlyArray | null - readonly "top_logprobs": ReadonlyArray< - { readonly "token": string; readonly "logprob": number; readonly "bytes": ReadonlyArray | null } - > - } - > - readonly "refusal": ReadonlyArray< - { - readonly "token": string - readonly "logprob": number - readonly "bytes": ReadonlyArray | null - readonly "top_logprobs": ReadonlyArray< - { readonly "token": string; readonly "logprob": number; readonly "bytes": ReadonlyArray | null } - > - } - > - } - readonly "finish_reason": "stop" | "length" | "tool_calls" | "content_filter" | "function_call" | null - readonly "index": number - } - > - readonly "created": number - readonly "model": string - readonly "service_tier"?: ServiceTier - readonly "system_fingerprint"?: string - readonly "object": "chat.completion.chunk" - readonly "usage"?: { - readonly "completion_tokens": number - readonly "prompt_tokens": number - readonly "total_tokens": number - readonly "completion_tokens_details"?: { - readonly "accepted_prediction_tokens"?: number - readonly "audio_tokens"?: number - readonly "reasoning_tokens"?: number - readonly "rejected_prediction_tokens"?: number - } - readonly "prompt_tokens_details"?: { readonly "audio_tokens"?: number; readonly "cached_tokens"?: number } - } | null + ) +}).annotate({ + "title": "Prompt cache options", + "description": + "Options for prompt caching. Supported for `gpt-5.6` and later models. By default, OpenAI automatically chooses one implicit cache breakpoint. You can add explicit breakpoints to content blocks with `prompt_cache_breakpoint`. Each request can write up to four breakpoints. For cache matching, OpenAI considers up to the latest 80 breakpoints in the conversation, without a content-block lookback limit. Set `mode` to `explicit` to disable the implicit breakpoint. The `ttl` defaults to `30m`, which is currently the only supported value. See the [prompt caching guide](https://developers.openai.com/api/docs/guides/prompt-caching) for current details.", + "identifier": "PromptCacheOptionsParam" +}) +export type PromptCacheOptions = { + readonly "ttl": PromptCacheTTLEnum + readonly "mode": PromptCacheModeEnum + readonly "comparison_response_id"?: string | null } -export const CreateChatCompletionStreamResponse = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "A unique identifier for the chat completion. Each chunk has the same ID." +export const PromptCacheOptions = Schema.Struct({ + "ttl": Schema.suspend((): Schema.Codec => PromptCacheTTLEnum).annotate({ + "description": "The minimum lifetime applied to each cache breakpoint." }), - "choices": Schema.Array(Schema.Struct({ - "delta": ChatCompletionStreamResponseDelta, - "logprobs": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "content": Schema.Union([ - Schema.Array(Schema.Struct({ - "token": Schema.String.annotate({ "description": "The token." }), - "logprob": Schema.Number.annotate({ - "description": - "The log probability of this token, if it is within the top 20 most likely tokens. Otherwise, the value `-9999.0` is used to signify that the token is very unlikely." - }).check(Schema.isFinite()), - "bytes": Schema.Union([ - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "description": - "A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token." - }), - Schema.Null - ]), - "top_logprobs": Schema.Array(Schema.Struct({ - "token": Schema.String.annotate({ "description": "The token." }), - "logprob": Schema.Number.annotate({ - "description": - "The log probability of this token, if it is within the top 20 most likely tokens. Otherwise, the value `-9999.0` is used to signify that the token is very unlikely." - }).check(Schema.isFinite()), - "bytes": Schema.Union([ - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "description": - "A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token." - }), - Schema.Null - ]) - })).annotate({ - "description": - "List of the most likely tokens and their log probability, at this token position. The number of entries may be fewer than the requested `top_logprobs`." - }) - })).annotate({ "description": "A list of message content tokens with log probability information." }) - ]), - "refusal": Schema.Union([ - Schema.Array(Schema.Struct({ - "token": Schema.String.annotate({ "description": "The token." }), - "logprob": Schema.Number.annotate({ - "description": - "The log probability of this token, if it is within the top 20 most likely tokens. Otherwise, the value `-9999.0` is used to signify that the token is very unlikely." - }).check(Schema.isFinite()), - "bytes": Schema.Union([ - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "description": - "A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token." - }), - Schema.Null - ]), - "top_logprobs": Schema.Array(Schema.Struct({ - "token": Schema.String.annotate({ "description": "The token." }), - "logprob": Schema.Number.annotate({ - "description": - "The log probability of this token, if it is within the top 20 most likely tokens. Otherwise, the value `-9999.0` is used to signify that the token is very unlikely." - }).check(Schema.isFinite()), - "bytes": Schema.Union([ - Schema.Array(Schema.Number.check(Schema.isInt())).annotate({ - "description": - "A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token." - }), - Schema.Null - ]) - })).annotate({ - "description": - "List of the most likely tokens and their log probability, at this token position. The number of entries may be fewer than the requested `top_logprobs`." - }) - })).annotate({ "description": "A list of message refusal tokens with log probability information." }) - ]) - }).annotate({ "description": "Log probability information for the choice." }) - ])), - "finish_reason": Schema.Union([ - Schema.Literals(["stop", "length", "tool_calls", "content_filter", "function_call"]).annotate({ - "description": - "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\n`content_filter` if content was omitted due to a flag from our content filters,\n`tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function.\n" - }), - Schema.Union([Schema.Null]).annotate({ - "description": - "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\n`content_filter` if content was omitted due to a flag from our content filters,\n`tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function.\n" - }) - ]), - "index": Schema.Number.annotate({ "description": "The index of the choice in the list of choices." }).check( - Schema.isInt() - ) - })).annotate({ - "description": - "A list of chat completion choices. Can contain more than one elements if `n` is greater than 1. Can also be empty for the\nlast chunk if you set `stream_options: {\"include_usage\": true}`.\n" - }), - "created": Schema.Number.annotate({ - "description": - "The Unix timestamp (in seconds) of when the chat completion was created. Each chunk has the same timestamp.", - "format": "unixtime" - }).check(Schema.isInt()), - "model": Schema.String.annotate({ "description": "The model to generate the completion." }), - "service_tier": Schema.optionalKey(ServiceTier), - "system_fingerprint": Schema.optionalKey( - Schema.String.annotate({ - "description": - "This fingerprint represents the backend configuration that the model runs with.\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" - }) - ), - "object": Schema.Literal("chat.completion.chunk").annotate({ - "description": "The object type, which is always `chat.completion.chunk`." + "mode": Schema.suspend((): Schema.Codec => PromptCacheModeEnum).annotate({ + "description": "Whether implicit prompt-cache breakpoints were enabled." }), - "usage": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "completion_tokens": Schema.Number.annotate({ "description": "Number of tokens in the generated completion." }) - .check(Schema.isInt()), - "prompt_tokens": Schema.Number.annotate({ "description": "Number of tokens in the prompt." }).check( - Schema.isInt() - ), - "total_tokens": Schema.Number.annotate({ - "description": "Total number of tokens used in the request (prompt + completion)." - }).check(Schema.isInt()), - "completion_tokens_details": Schema.optionalKey( - Schema.Struct({ - "accepted_prediction_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "When using Predicted Outputs, the number of tokens in the\nprediction that appeared in the completion.\n" - }).check(Schema.isInt()) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Audio input tokens generated by the model." }).check( - Schema.isInt() - ) - ), - "reasoning_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Tokens generated by the model for reasoning." }).check( - Schema.isInt() - ) - ), - "rejected_prediction_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "When using Predicted Outputs, the number of tokens in the\nprediction that did not appear in the completion. However, like\nreasoning tokens, these tokens are still counted in the total\ncompletion tokens for purposes of billing, output, and context window\nlimits.\n" - }).check(Schema.isInt()) - ) - }).annotate({ "description": "Breakdown of tokens used in a completion." }) - ), - "prompt_tokens_details": Schema.optionalKey( - Schema.Struct({ - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Audio input tokens present in the prompt." }).check(Schema.isInt()) - ), - "cached_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "Cached tokens present in the prompt." }).check(Schema.isInt()) - ) - }).annotate({ "description": "Breakdown of tokens used in the prompt." }) - ) - }).annotate({ - "description": - "An optional field that will only be present when you set\n`stream_options: {\"include_usage\": true}` in your request. When present, it\ncontains a null value **except for the last chunk** which contains the\ntoken usage statistics for the entire request.\n\n**NOTE:** If the stream is interrupted or cancelled, you may not\nreceive the final usage chunk which contains the total token usage for\nthe request.\n" - }), - Schema.Null - ])) + "comparison_response_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The response ID supplied as the prompt cache diagnostics comparison." }), + Schema.Null + ]) + ) }).annotate({ + "title": "Prompt cache options", "description": - "Represents a streamed chunk of a chat completion response returned\nby the model, based on the provided input. \n[Learn more](/docs/guides/streaming-responses).\n" + "The prompt-caching options that were applied to the response. Supported for `gpt-5.6` and later models.", + "identifier": "PromptCacheOptions" }) -export type ChatCompletionRequestAssistantMessage = { - readonly "content"?: string | ReadonlyArray | null - readonly "refusal"?: string | null - readonly "role": "assistant" - readonly "name"?: string - readonly "audio"?: { readonly "id": string } | null - readonly "tool_calls"?: ChatCompletionMessageToolCalls - readonly "function_call"?: { readonly "arguments": string; readonly "name": string } | null +export type ChatCompletionRequestMessageContentPartText = { + readonly "type": "text" + readonly "text": string + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointParam } -export const ChatCompletionRequestAssistantMessage = Schema.Struct({ - "content": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.String.annotate({ "title": "Text content", "description": "The contents of the assistant message." }), - Schema.Array(ChatCompletionRequestAssistantMessageContentPart).annotate({ - "title": "Array of content parts", - "description": - "An array of content parts with a defined type. Can be one or more of type `text`, or exactly one of type `refusal`." - }).check(Schema.isMinLength(1)) - ], { mode: "oneOf" }).annotate({ +export const ChatCompletionRequestMessageContentPartText = Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "The type of the content part." }), + "text": Schema.String.annotate({ "description": "The text content." }), + "prompt_cache_breakpoint": Schema.optionalKey(PromptCacheBreakpointParam) +}).annotate({ + "title": "Text content part", + "description": "Learn about [text inputs](https://developers.openai.com/api/docs/guides/text).\n", + "identifier": "ChatCompletionRequestMessageContentPartText" +}) +export type ChatCompletionRequestMessageContentPartImage = { + readonly "type": "image_url" + readonly "image_url": { readonly "url": string; readonly "detail"?: "auto" | "low" | "high" | "original" } + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointParam +} +export const ChatCompletionRequestMessageContentPartImage = Schema.Struct({ + "type": Schema.Literal("image_url").annotate({ "description": "The type of the content part." }), + "image_url": Schema.Struct({ + "url": Schema.String.annotate({ + "description": "Either a URL of the image or the base64 encoded image data.", + "format": "uri" + }), + "detail": Schema.optionalKey( + Schema.Literals(["auto", "low", "high", "original"]).annotate({ "description": - "The contents of the assistant message. Required unless `tool_calls` or `function_call` is specified.\n" - }), - Schema.Null - ]) - ), - "refusal": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "The refusal message by the assistant." }), Schema.Null]) - ), - "role": Schema.Literal("assistant").annotate({ - "description": "The role of the messages author, in this case `assistant`." + "Specifies the detail level of the image. Learn more in the [Vision guide](https://developers.openai.com/api/docs/guides/images-vision#choose-an-image-detail-level)." + }) + ) }), - "name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "An optional name for the participant. Provides the model information to differentiate between participants of the same role." - }) - ), - "audio": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "id": Schema.String.annotate({ - "description": "Unique identifier for a previous audio response from the model.\n" - }) - }).annotate({ - "description": "Data about a previous audio response from the model.\n[Learn more](/docs/guides/audio).\n" - }), - Schema.Null - ]) - ), - "tool_calls": Schema.optionalKey(ChatCompletionMessageToolCalls), - "function_call": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "arguments": Schema.String.annotate({ - "description": - "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - }), - "name": Schema.String.annotate({ "description": "The name of the function to call." }) - }).annotate({ - "description": - "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." - }), - Schema.Null - ])) + "prompt_cache_breakpoint": Schema.optionalKey(PromptCacheBreakpointParam) }).annotate({ - "title": "Assistant message", - "description": "Messages sent by the model in response to user messages.\n" + "title": "Image content part", + "description": "Learn about [image inputs](https://developers.openai.com/api/docs/guides/images-vision).\n", + "identifier": "ChatCompletionRequestMessageContentPartImage" }) -export type ChatCompletionRequestSystemMessage = { - readonly "content": string | ReadonlyArray - readonly "role": "system" - readonly "name"?: string +export type ChatCompletionRequestMessageContentPartAudio = { + readonly "type": "input_audio" + readonly "input_audio": { readonly "data": string; readonly "format": "wav" | "mp3" } + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointParam } -export const ChatCompletionRequestSystemMessage = Schema.Struct({ - "content": Schema.Union([ - Schema.String.annotate({ "title": "Text content", "description": "The contents of the system message." }), - Schema.Array(ChatCompletionRequestSystemMessageContentPart).annotate({ - "title": "Array of content parts", - "description": - "An array of content parts with a defined type. For system messages, only type `text` is supported." - }).check(Schema.isMinLength(1)) - ], { mode: "oneOf" }).annotate({ "description": "The contents of the system message." }), - "role": Schema.Literal("system").annotate({ - "description": "The role of the messages author, in this case `system`." +export const ChatCompletionRequestMessageContentPartAudio = Schema.Struct({ + "type": Schema.Literal("input_audio").annotate({ + "description": "The type of the content part. Always `input_audio`." }), - "name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "An optional name for the participant. Provides the model information to differentiate between participants of the same role." + "input_audio": Schema.Struct({ + "data": Schema.String.annotate({ "description": "Base64 encoded audio data." }), + "format": Schema.Literals(["wav", "mp3"]).annotate({ + "description": "The format of the encoded audio data. Currently supports \"wav\" and \"mp3\".\n" }) - ) + }), + "prompt_cache_breakpoint": Schema.optionalKey(PromptCacheBreakpointParam) }).annotate({ - "title": "System message", - "description": - "Developer-provided instructions that the model should follow, regardless of\nmessages sent by the user. With o1 models and newer, use `developer` messages\nfor this purpose instead.\n" + "title": "Audio content part", + "description": "Learn about [audio inputs](https://developers.openai.com/api/docs/guides/audio).\n", + "identifier": "ChatCompletionRequestMessageContentPartAudio" }) -export type ChatCompletionRequestToolMessage = { - readonly "role": "tool" - readonly "content": string | ReadonlyArray - readonly "tool_call_id": string +export type ChatCompletionRequestMessageContentPartFile = { + readonly "type": "file" + readonly "file": { readonly "filename"?: string; readonly "file_data"?: string; readonly "file_id"?: string } + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointParam } -export const ChatCompletionRequestToolMessage = Schema.Struct({ - "role": Schema.Literal("tool").annotate({ "description": "The role of the messages author, in this case `tool`." }), - "content": Schema.Union([ - Schema.String.annotate({ "title": "Text content", "description": "The contents of the tool message." }), - Schema.Array(ChatCompletionRequestToolMessageContentPart).annotate({ - "title": "Array of content parts", - "description": "An array of content parts with a defined type. For tool messages, only type `text` is supported." - }).check(Schema.isMinLength(1)) - ], { mode: "oneOf" }).annotate({ "description": "The contents of the tool message." }), - "tool_call_id": Schema.String.annotate({ "description": "Tool call that this message is responding to." }) -}).annotate({ "title": "Tool message" }) -export type ChatCompletionRequestUserMessage = { - readonly "content": string | ReadonlyArray - readonly "role": "user" - readonly "name"?: string +export const ChatCompletionRequestMessageContentPartFile = Schema.Struct({ + "type": Schema.Literal("file").annotate({ "description": "The type of the content part. Always `file`." }), + "file": Schema.Struct({ + "filename": Schema.optionalKey( + Schema.String.annotate({ + "description": "The name of the file, used when passing the file to the model as a\nstring.\n" + }) + ), + "file_data": Schema.optionalKey( + Schema.String.annotate({ + "description": "The base64 encoded file data, used when passing the file to the model\nas a string.\n" + }) + ), + "file_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of an uploaded file to use as input.\n" }) + ) + }), + "prompt_cache_breakpoint": Schema.optionalKey(PromptCacheBreakpointParam) +}).annotate({ + "title": "File content part", + "description": "Learn about [file inputs](https://developers.openai.com/api/docs/guides/text) for text generation.\n", + "identifier": "ChatCompletionRequestMessageContentPartFile" +}) +export type InputTextContentParam = { + readonly "type": "input_text" + readonly "text": string + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointParam | null } -export const ChatCompletionRequestUserMessage = Schema.Struct({ - "content": Schema.Union([ - Schema.String.annotate({ "title": "Text content", "description": "The text contents of the message." }), - Schema.Array(ChatCompletionRequestUserMessageContentPart).annotate({ - "title": "Array of content parts", - "description": - "An array of content parts with a defined type. Supported options differ based on the [model](/docs/models) being used to generate the response. Can contain text, image, or audio inputs." - }).check(Schema.isMinLength(1)) - ], { mode: "oneOf" }).annotate({ "description": "The contents of the user message.\n" }), - "role": Schema.Literal("user").annotate({ "description": "The role of the messages author, in this case `user`." }), - "name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "An optional name for the participant. Provides the model information to differentiate between participants of the same role." - }) - ) +export const InputTextContentParam = Schema.Struct({ + "type": Schema.Literal("input_text").annotate({ "description": "The type of the input item. Always `input_text`." }), + "text": Schema.String.annotate({ "description": "The text input to the model." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "prompt_cache_breakpoint": Schema.optionalKey(Schema.Union([PromptCacheBreakpointParam, Schema.Null])) }).annotate({ - "title": "User message", - "description": "Messages sent by an end user, containing prompts or additional context\ninformation.\n" + "title": "Input text", + "description": "A text input to the model.", + "identifier": "InputTextContentParam" }) -export type VectorStoreSearchRequest = { - readonly "query": string | ReadonlyArray - readonly "rewrite_query"?: boolean - readonly "max_num_results"?: number - readonly "filters"?: ComparisonFilter | CompoundFilter - readonly "ranking_options"?: { - readonly "ranker"?: "none" | "auto" | "default-2024-11-15" - readonly "score_threshold"?: number - } +export type ModelIdsResponses = + | ModelIdsShared + | "o1-pro" + | "o1-pro-2025-03-19" + | "o3-pro" + | "o3-pro-2025-06-10" + | "o3-deep-research" + | "o3-deep-research-2025-06-26" + | "o4-mini-deep-research" + | "o4-mini-deep-research-2025-06-26" + | "computer-use-preview" + | "computer-use-preview-2025-03-11" + | "gpt-5.5-pro" + | "gpt-5.5-pro-2026-04-23" + | "gpt-5-codex" + | "gpt-5-pro" + | "gpt-5-pro-2025-10-06" + | "gpt-5.1-codex-max" + | "gpt-daybreak-blue-latest" + | "gpt-daybreak-red-latest" + | "gpt-5.6-cyber" + | "gpt-rosalind-research" +export const ModelIdsResponses = Schema.Union([ + ModelIdsShared, + Schema.Literals([ + "o1-pro", + "o1-pro-2025-03-19", + "o3-pro", + "o3-pro-2025-06-10", + "o3-deep-research", + "o3-deep-research-2025-06-26", + "o4-mini-deep-research", + "o4-mini-deep-research-2025-06-26", + "computer-use-preview", + "computer-use-preview-2025-03-11", + "gpt-5.5-pro", + "gpt-5.5-pro-2026-04-23", + "gpt-5-codex", + "gpt-5-pro", + "gpt-5-pro-2025-10-06", + "gpt-5.1-codex-max", + "gpt-daybreak-blue-latest", + "gpt-daybreak-red-latest", + "gpt-5.6-cyber", + "gpt-rosalind-research" + ]).annotate({ "title": "ResponsesOnlyModel" }) +]).annotate({ "identifier": "ModelIdsResponses" }) +export type ModerationConfigParam = { readonly "mode": ModerationMode } +export const ModerationConfigParam = Schema.Struct({ "mode": ModerationMode }).annotate({ + "description": "The moderation policy for the response input.", + "identifier": "ModerationConfigParam" +}) +export type CreateCompletionRequest = { + readonly "model": string | "gpt-3.5-turbo-instruct" | "davinci-002" | "babbage-002" + readonly "prompt": + | string + | ReadonlyArray + | ReadonlyArray + | ReadonlyArray> + | null + readonly "best_of"?: number | null + readonly "echo"?: boolean | null + readonly "frequency_penalty"?: number | null + readonly "logit_bias"?: { readonly [x: string]: number } | null + readonly "logprobs"?: number | null + readonly "max_tokens"?: number | null + readonly "n"?: number | null + readonly "presence_penalty"?: number | null + readonly "seed"?: number | null + readonly "stop"?: StopConfiguration + readonly "stream"?: boolean | null + readonly "stream_options"?: ChatCompletionStreamOptions + readonly "suffix"?: string | null + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "user"?: string } -export const VectorStoreSearchRequest = Schema.Struct({ - "query": Schema.Union([ +export const CreateCompletionRequest = Schema.Struct({ + "model": Schema.Union([Schema.String, Schema.Literals(["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"])]) + .annotate({ + "description": + "ID of the model to use. You can use the [List models](https://developers.openai.com/api/reference/resources/models/methods/list) API to see all of your available models, or see our [Model overview](https://developers.openai.com/api/docs/models) for descriptions of them.\n" + }), + "prompt": Schema.Union([ Schema.String, - Schema.Array(Schema.String.annotate({ "description": "A list of queries to search for." })) - ], { mode: "oneOf" }).annotate({ "description": "A query string for a search" }), - "rewrite_query": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether to rewrite the natural language query for vector search." }) + Schema.Array(Schema.String), + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Array( + Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ) + ).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + Schema.Null + ], { mode: "oneOf" }).annotate({ + "description": + "The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays.\n\nNote that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document.\n" + }), + "best_of": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" })), + Schema.Null + ]).annotate({ + "description": + "Generates `best_of` completions server-side and returns the \"best\" (the one with the highest log probability per token). Results cannot be streamed.\n\nWhen used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`.\n\n**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\n" + }) ), - "max_num_results": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum number of results to return. This number should be between 1 and 50 inclusive." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(50)) + "echo": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": "Echo back the prompt in addition to the completion\n" + }) ), - "filters": Schema.optionalKey( - Schema.Union([ComparisonFilter, CompoundFilter], { mode: "oneOf" }).annotate({ - "description": "A filter to apply based on file attributes." + "frequency_penalty": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(-2).annotate({ "expected": "a value greater than or equal to -2" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]).annotate({ + "description": + "Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\n\n[See more information about frequency and presence penalties.](https://developers.openai.com/api/docs/guides/text)\n" }) ), - "ranking_options": Schema.optionalKey( - Schema.Struct({ - "ranker": Schema.optionalKey( - Schema.Literals(["none", "auto", "default-2024-11-15"]).annotate({ - "description": "Enable re-ranking; set to `none` to disable, which can help reduce latency." - }) + "logit_bias": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), + Schema.Null + ]).annotate({ + "description": + "Modify the likelihood of specified tokens appearing in the completion.\n\nAccepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](https://platform.openai.com/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\n\nAs an example, you can pass `{\"50256\": -100}` to prevent the <|endoftext|> token from being generated.\n" + }) + ), + "logprobs": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(5).annotate({ "expected": "a value less than or equal to 5" })), + Schema.Null + ]).annotate({ + "description": + "Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response.\n\nThe maximum value for `logprobs` is 5.\n" + }) + ), + "max_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) ), - "score_threshold": Schema.optionalKey( - Schema.Number.check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check( - Schema.isLessThanOrEqualTo(1) - ) - ) - }).annotate({ "description": "Ranking options for search." }) + Schema.Null + ]).annotate({ + "description": + "The maximum number of [tokens](https://platform.openai.com/tokenizer) that can be generated in the completion.\n\nThe token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens.\n" + }) + ), + "n": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(128).annotate({ "expected": "a value less than or equal to 128" })), + Schema.Null + ]).annotate({ + "description": + "How many completions to generate for each prompt.\n\n**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\n" + }) + ), + "presence_penalty": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(-2).annotate({ "expected": "a value greater than or equal to -2" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]).annotate({ + "description": + "Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\n\n[See more information about frequency and presence penalties.](https://developers.openai.com/api/docs/guides/text)\n" + }) + ), + "seed": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": + "If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result.\n\nDeterminism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend.\n", + "format": "int64" + }) + ), + "stop": Schema.optionalKey(StopConfiguration), + "stream": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": + "Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions).\n" + }) + ), + "stream_options": Schema.optionalKey(ChatCompletionStreamOptions), + "suffix": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "The suffix that comes after a completion of inserted text.\n\nThis parameter is only supported for `gpt-3.5-turbo-instruct`.\n" + }) + ), + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]).annotate({ + "description": + "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n\nWe generally recommend altering this or `top_p` but not both.\n" + }) + ), + "top_p": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + Schema.Null + ]).annotate({ + "description": + "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" + }) + ), + "user": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }) ) +}).annotate({ "identifier": "CreateCompletionRequest" }) +export type ChatCompletionAllowedToolsChoice = { + readonly "type": "allowed_tools" + readonly "allowed_tools": ChatCompletionAllowedTools +} +export const ChatCompletionAllowedToolsChoice = Schema.Struct({ + "type": Schema.Literal("allowed_tools").annotate({ + "description": "Allowed tool configuration type. Always `allowed_tools`." + }), + "allowed_tools": ChatCompletionAllowedTools +}).annotate({ + "title": "Allowed tools", + "description": "Constrains the tools available to the model to a pre-defined set.\n", + "identifier": "ChatCompletionAllowedToolsChoice" }) -export type FileSearchTool = { - readonly "type": "file_search" - readonly "vector_store_ids": ReadonlyArray - readonly "max_num_results"?: number - readonly "ranking_options"?: { - readonly "ranker"?: "auto" | "default-2024-11-15" - readonly "score_threshold"?: number - readonly "hybrid_search"?: { readonly "embedding_weight": number; readonly "text_weight": number } +export type ChatCompletionStreamResponseDelta = { + readonly "audio"?: { + readonly "id"?: string + readonly "expires_at"?: number + readonly "data"?: string + readonly "transcript"?: string } - readonly "filters"?: ComparisonFilter | CompoundFilter | null + readonly "content"?: string | null + readonly "function_call"?: { readonly "arguments"?: string; readonly "name"?: string } + readonly "tool_calls"?: ReadonlyArray + readonly "role"?: "developer" | "system" | "user" | "assistant" | "tool" + readonly "refusal"?: string | null } -export const FileSearchTool = Schema.Struct({ - "type": Schema.Literal("file_search").annotate({ - "description": "The type of the file search tool. Always `file_search`." - }), - "vector_store_ids": Schema.Array(Schema.String).annotate({ - "description": "The IDs of the vector stores to search." - }), - "max_num_results": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum number of results to return. This number should be between 1 and 50 inclusive." - }).check(Schema.isInt()) - ), - "ranking_options": Schema.optionalKey( +export const ChatCompletionStreamResponseDelta = Schema.Struct({ + "audio": Schema.optionalKey( Schema.Struct({ - "ranker": Schema.optionalKey( - Schema.Literals(["auto", "default-2024-11-15"]).annotate({ - "description": "The ranker to use for the file search." - }) - ), - "score_threshold": Schema.optionalKey( + "id": Schema.optionalKey(Schema.String.annotate({ "description": "Unique identifier for this audio response." })), + "expires_at": Schema.optionalKey( Schema.Number.annotate({ "description": - "The score threshold for the file search, a number between 0 and 1. Numbers closer to 1 will attempt to return only the most relevant results, but may return fewer results." - }).check(Schema.isFinite()) + "The Unix timestamp (in seconds) for when this audio response will no\nlonger be accessible on the server for use in multi-turn conversations.\n", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), - "hybrid_search": Schema.optionalKey( - Schema.Struct({ - "embedding_weight": Schema.Number.annotate({ - "description": "The weight of the embedding in the reciprocal ranking fusion." - }).check(Schema.isFinite()), - "text_weight": Schema.Number.annotate({ - "description": "The weight of the text in the reciprocal ranking fusion." - }).check(Schema.isFinite()) - }).annotate({ - "description": - "Weights that control how reciprocal rank fusion balances semantic embedding matches versus sparse keyword matches when hybrid search is enabled." + "data": Schema.optionalKey( + Schema.String.annotate({ + "description": "Base64 encoded audio bytes generated by the model, in the format\nspecified in the request.\n" }) + ), + "transcript": Schema.optionalKey( + Schema.String.annotate({ "description": "Transcript text from this audio chunk." }) ) - }).annotate({ "description": "Ranking options for search." }) + }).annotate({ + "description": + "A partial audio response. Audio chunks may carry an ID, base64 data, or\ntranscript text; the final audio update contains only its expiry timestamp.\n" + }) ), - "filters": Schema.optionalKey( + "content": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The contents of the chunk message." }), Schema.Null]) + ), + "function_call": Schema.optionalKey( + Schema.Struct({ + "arguments": Schema.optionalKey(Schema.String.annotate({ + "description": + "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." + })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function to call." })) + }).annotate({ + "description": + "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." + }) + ), + "tool_calls": Schema.optionalKey(Schema.Array(ChatCompletionMessageToolCallChunk)), + "role": Schema.optionalKey( + Schema.Literals(["developer", "system", "user", "assistant", "tool"]).annotate({ + "description": "The role of the author of this message." + }) + ), + "refusal": Schema.optionalKey( Schema.Union([ - Schema.Union([ComparisonFilter, CompoundFilter]).annotate({ "description": "A filter to apply." }), + Schema.String.annotate({ "description": "The refusal message generated by the model." }), Schema.Null ]) ) }).annotate({ - "title": "File search", "description": - "A tool that searches for relevant content from uploaded files. Learn more about the [file search tool](https://platform.openai.com/docs/guides/tools-file-search)." + "A chat completion delta generated by streamed model responses.\nStreamed audio can arrive in partial updates with an ID, base64 data, or\ntranscript text. The final audio update contains only its expiry timestamp.\n", + "identifier": "ChatCompletionStreamResponseDelta" }) -export type EvalRunOutputItemList = { +export type ContainerListResource = { readonly "object": "list" - readonly "data": ReadonlyArray + readonly "data": ReadonlyArray readonly "first_id": string readonly "last_id": string readonly "has_more": boolean } -export const EvalRunOutputItemList = Schema.Struct({ - "object": Schema.Literal("list").annotate({ - "description": "The type of this object. It is always set to \"list\".\n" - }), - "data": Schema.Array(EvalRunOutputItem).annotate({ "description": "An array of eval run output item objects.\n" }), - "first_id": Schema.String.annotate({ - "description": "The identifier of the first eval run output item in the data array." - }), - "last_id": Schema.String.annotate({ - "description": "The identifier of the last eval run output item in the data array." - }), - "has_more": Schema.Boolean.annotate({ - "description": "Indicates whether there are more eval run output items available." +export const ContainerListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be 'list'." }), + "data": Schema.Array(ContainerResource).annotate({ "description": "A list of containers." }), + "first_id": Schema.String.annotate({ "description": "The ID of the first container in the list." }), + "last_id": Schema.String.annotate({ "description": "The ID of the last container in the list." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more containers available." }) +}).annotate({ "identifier": "ContainerListResource" }) +export type InlineSkillParam = { + readonly "type": "inline" + readonly "name": string + readonly "description": string + readonly "source": InlineSkillSourceParam +} +export const InlineSkillParam = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "Defines an inline skill for this request." }), + "name": Schema.String.annotate({ "description": "The name of the skill." }), + "description": Schema.String.annotate({ "description": "The description of the skill." }), + "source": Schema.suspend((): Schema.Codec => InlineSkillSourceParam).annotate({ + "description": "Inline skill payload" }) -}).annotate({ - "title": "EvalRunOutputItemList", - "description": "An object representing a list of output items for an evaluation run.\n" -}) -export type AssistantToolsFileSearch = { - readonly "type": "file_search" - readonly "file_search"?: { - readonly "max_num_results"?: number - readonly "ranking_options"?: FileSearchRankingOptions - } +}).annotate({ "identifier": "InlineSkillParam" }) +export type ContainerNetworkPolicyAllowlistParam = { + readonly "type": "allowlist" + readonly "allowed_domains": ReadonlyArray + readonly "domain_secrets"?: ReadonlyArray } -export const AssistantToolsFileSearch = Schema.Struct({ - "type": Schema.Literal("file_search").annotate({ "description": "The type of tool being defined: `file_search`" }), - "file_search": Schema.optionalKey( - Schema.Struct({ - "max_num_results": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The maximum number of results the file search tool should output. The default is 20 for `gpt-4*` models and 5 for `gpt-3.5-turbo`. This number should be between 1 and 50 inclusive.\n\nNote that the file search tool may output fewer than `max_num_results` results. See the [file search tool documentation](/docs/assistants/tools/file-search#customizing-file-search-settings) for more information.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check(Schema.isLessThanOrEqualTo(50)) - ), - "ranking_options": Schema.optionalKey(FileSearchRankingOptions) - }).annotate({ "description": "Overrides for the file search tool." }) +export const ContainerNetworkPolicyAllowlistParam = Schema.Struct({ + "type": Schema.Literal("allowlist").annotate({ + "description": "Allow outbound network access only to specified domains. Always `allowlist`." + }), + "allowed_domains": Schema.Array(Schema.String).annotate({ + "description": "A list of allowed domains when type is `allowlist`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "domain_secrets": Schema.optionalKey( + Schema.Array(ContainerNetworkPolicyDomainSecretParam).annotate({ + "description": "Optional domain-scoped secrets for allowlisted domains." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) ) -}).annotate({ "title": "FileSearch tool" }) -export type RunStepDetailsToolCallsFileSearchObject = { - readonly "id": string - readonly "type": "file_search" - readonly "file_search": { - readonly "ranking_options"?: RunStepDetailsToolCallsFileSearchRankingOptionsObject - readonly "results"?: ReadonlyArray - } +}).annotate({ "identifier": "ContainerNetworkPolicyAllowlistParam" }) +export type ContainerFileListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean } -export const RunStepDetailsToolCallsFileSearchObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The ID of the tool call object." }), - "type": Schema.Literal("file_search").annotate({ - "description": "The type of tool call. This is always going to be `file_search` for this type of tool call." - }), - "file_search": Schema.Struct({ - "ranking_options": Schema.optionalKey(RunStepDetailsToolCallsFileSearchRankingOptionsObject), - "results": Schema.optionalKey( - Schema.Array(RunStepDetailsToolCallsFileSearchResultObject).annotate({ - "description": "The results of the file search." - }) - ) - }).annotate({ "description": "For now, this is always going to be an empty object." }) -}).annotate({ "title": "File search tool call" }) -export type AssistantToolsFunction = { readonly "type": "function"; readonly "function": FunctionObject } -export const AssistantToolsFunction = Schema.Struct({ - "type": Schema.Literal("function").annotate({ "description": "The type of tool being defined: `function`" }), - "function": FunctionObject -}).annotate({ "title": "Function tool" }) -export type ChatCompletionTool = { readonly "type": "function"; readonly "function": FunctionObject } -export const ChatCompletionTool = Schema.Struct({ - "type": Schema.Literal("function").annotate({ - "description": "The type of the tool. Currently, only `function` is supported." - }), - "function": FunctionObject -}).annotate({ "title": "Function tool", "description": "A function tool that can be used to generate a response.\n" }) -export type ImageEditStreamEvent = ImageEditPartialImageEvent | ImageEditCompletedEvent -export const ImageEditStreamEvent = Schema.Union([ImageEditPartialImageEvent, ImageEditCompletedEvent]) -export type ImageGenStreamEvent = ImageGenPartialImageEvent | ImageGenCompletedEvent -export const ImageGenStreamEvent = Schema.Union([ImageGenPartialImageEvent, ImageGenCompletedEvent]) -export type MessageObject = { +export const ContainerFileListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be 'list'." }), + "data": Schema.Array(ContainerFileResource).annotate({ "description": "A list of container files." }), + "first_id": Schema.String.annotate({ "description": "The ID of the first file in the list." }), + "last_id": Schema.String.annotate({ "description": "The ID of the last file in the list." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more files available." }) +}).annotate({ "identifier": "ContainerFileListResource" }) +export type InputTextContent = { + readonly "type": "input_text" + readonly "text": string + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointConfig +} +export const InputTextContent = Schema.Struct({ + "type": Schema.Literal("input_text").annotate({ "description": "The type of the input item. Always `input_text`." }), + "text": Schema.String.annotate({ "description": "The text input to the model." }), + "prompt_cache_breakpoint": Schema.optionalKey(PromptCacheBreakpointConfig) +}).annotate({ "title": "Input text", "description": "A text input to the model.", "identifier": "InputTextContent" }) +export type Annotation = FileCitationBody | UrlCitationBody | ContainerFileCitationBody | FilePath +export const Annotation = Schema.Union([FileCitationBody, UrlCitationBody, ContainerFileCitationBody, FilePath], { + mode: "oneOf" +}).annotate({ "description": "An annotation that applies to a span of output text.", "identifier": "Annotation" }) +export type LogProb = { + readonly "token": string + readonly "logprob": number + readonly "bytes": ReadonlyArray + readonly "top_logprobs": ReadonlyArray +} +export const LogProb = Schema.Struct({ + "token": Schema.String, + "logprob": Schema.Finite, + "bytes": Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), + "top_logprobs": Schema.Array(TopLogProb) +}).annotate({ "title": "Log probability", "description": "The log probability of a token.", "identifier": "LogProb" }) +export type ReasoningItem = { + readonly "type": "reasoning" readonly "id": string - readonly "object": "thread.message" - readonly "created_at": number - readonly "thread_id": string - readonly "status": "in_progress" | "incomplete" | "completed" - readonly "incomplete_details": { - readonly "reason": "content_filter" | "max_tokens" | "run_cancelled" | "run_expired" | "run_failed" - } | null - readonly "completed_at": number | null - readonly "incomplete_at": number | null - readonly "role": "user" | "assistant" - readonly "content": ReadonlyArray< - | MessageContentImageFileObject - | MessageContentImageUrlObject - | MessageContentTextObject - | MessageContentRefusalObject - > - readonly "assistant_id": string | null - readonly "run_id": string | null - readonly "attachments": - | ReadonlyArray< - { - readonly "file_id"?: string - readonly "tools"?: ReadonlyArray - } - > - | null - readonly "metadata": Metadata + readonly "encrypted_content"?: string | null + readonly "summary": ReadonlyArray + readonly "content"?: ReadonlyArray + readonly "status"?: "in_progress" | "completed" | "incomplete" } -export const MessageObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), - "object": Schema.Literal("thread.message").annotate({ - "description": "The object type, which is always `thread.message`." - }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the message was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "thread_id": Schema.String.annotate({ - "description": "The [thread](/docs/api-reference/threads) ID that this message belongs to." - }), - "status": Schema.Literals(["in_progress", "incomplete", "completed"]).annotate({ - "description": "The status of the message, which can be either `in_progress`, `incomplete`, or `completed`." - }), - "incomplete_details": Schema.Union([ - Schema.Struct({ - "reason": Schema.Literals(["content_filter", "max_tokens", "run_cancelled", "run_expired", "run_failed"]) - .annotate({ "description": "The reason the message is incomplete." }) - }).annotate({ "description": "On an incomplete message, details about why the message is incomplete." }), - Schema.Null - ]), - "completed_at": Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the message was completed.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "incomplete_at": Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the message was marked as incomplete.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "role": Schema.Literals(["user", "assistant"]).annotate({ - "description": "The entity that produced the message. One of `user` or `assistant`." - }), - "content": Schema.Array( - Schema.Union([ - MessageContentImageFileObject, - MessageContentImageUrlObject, - MessageContentTextObject, - MessageContentRefusalObject - ], { mode: "oneOf" }) - ).annotate({ "description": "The content of the message in array of text and/or images." }), - "assistant_id": Schema.Union([ +export const ReasoningItem = Schema.Struct({ + "type": Schema.Literal("reasoning").annotate({ "description": "The type of the object. Always `reasoning`.\n" }), + "id": Schema.String.annotate({ "description": "The unique identifier of the reasoning content.\n" }), + "encrypted_content": Schema.optionalKey(Schema.Union([ Schema.String.annotate({ "description": - "If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this message." + "The encrypted content of the reasoning item. This is populated by default\nfor reasoning items returned by `POST /v1/responses` and WebSocket\n`response.create` requests.\n\nWhen streaming, use the completed reasoning item and its\n`encrypted_content` from the `response.output_item.done` event in\nsubsequent requests. The `encrypted_content` in\n`response.output_item.added` may be incomplete. This is especially\nimportant when `store` is `false` or when using Zero Data Retention.\n" }), Schema.Null - ]), - "run_id": Schema.Union([ - Schema.String.annotate({ + ])), + "summary": Schema.Array(SummaryTextContent).annotate({ "description": "Reasoning summary content.\n" }), + "content": Schema.optionalKey( + Schema.Array(ReasoningTextContent).annotate({ "description": "Reasoning text content.\n" }) + ), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ "description": - "The ID of the [run](/docs/api-reference/runs) associated with the creation of this message. Value is `null` when messages are created manually using the create message or create thread endpoints." - }), - Schema.Null - ]), - "attachments": Schema.Union([ - Schema.Array(Schema.Struct({ - "file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the file to attach to the message." }) - ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([AssistantToolsCode, AssistantToolsFileSearchTypeOnly], { mode: "oneOf" })).annotate({ - "description": "The tools to add this file to." - }) - ) - })).annotate({ "description": "A list of files attached to the message, and the tools they were added to." }), - Schema.Null - ]), - "metadata": Metadata + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ) }).annotate({ - "title": "The message object", - "description": "Represents a message within a [thread](/docs/api-reference/threads)." + "title": "Reasoning", + "description": + "A description of the chain of thought used by a reasoning model while generating\na response. Be sure to include these items in your `input` to the Responses API\nfor subsequent turns of a conversation if you are manually\n[managing context](https://developers.openai.com/api/docs/guides/conversation-state).\n", + "identifier": "ReasoningItem" }) -export type MessageDeltaObject = { - readonly "id": string - readonly "object": "thread.message.delta" - readonly "delta": { - readonly "role"?: "user" | "assistant" - readonly "content"?: ReadonlyArray< - | MessageDeltaContentImageFileObject - | MessageDeltaContentTextObject - | MessageDeltaContentRefusalObject - | MessageDeltaContentImageUrlObject - > - } +export type InputImageContent = { + readonly "type": "input_image" + readonly "image_url"?: string | null + readonly "file_id"?: string | null + readonly "detail": ImageDetail + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointConfig } -export const MessageDeltaObject = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The identifier of the message, which can be referenced in API endpoints." +export const InputImageContent = Schema.Struct({ + "type": Schema.Literal("input_image").annotate({ + "description": "The type of the input item. Always `input_image`." }), - "object": Schema.Literal("thread.message.delta").annotate({ - "description": "The object type, which is always `thread.message.delta`." + "image_url": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL.", + "format": "uri" + }), + Schema.Null + ]) + ), + "file_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), + Schema.Null + ]) + ), + "detail": Schema.suspend((): Schema.Codec => ImageDetail).annotate({ + "description": + "The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." }), - "delta": Schema.Struct({ - "role": Schema.optionalKey( - Schema.Literals(["user", "assistant"]).annotate({ - "description": "The entity that produced the message. One of `user` or `assistant`." - }) - ), - "content": Schema.optionalKey( - Schema.Array( - Schema.Union([ - MessageDeltaContentImageFileObject, - MessageDeltaContentTextObject, - MessageDeltaContentRefusalObject, - MessageDeltaContentImageUrlObject - ], { mode: "oneOf" }) - ).annotate({ "description": "The content of the message in array of text and/or images." }) - ) - }).annotate({ "description": "The delta containing the fields that have changed on the Message." }) + "prompt_cache_breakpoint": Schema.optionalKey(PromptCacheBreakpointConfig) }).annotate({ - "title": "Message delta object", - "description": "Represents a message delta i.e. any changed fields on a message during streaming.\n" + "title": "Input image", + "description": + "An image input to the model. Learn about [image inputs](https://developers.openai.com/api/docs/guides/images-vision).", + "identifier": "InputImageContent" }) -export type ListBatchesResponse = { - readonly "data": ReadonlyArray - readonly "first_id"?: string - readonly "last_id"?: string - readonly "has_more": boolean - readonly "object": "list" +export type ComputerScreenshotContent = { + readonly "type": "computer_screenshot" + readonly "image_url": string | null + readonly "file_id": string | null + readonly "detail": ImageDetail + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointConfig } -export const ListBatchesResponse = Schema.Struct({ - "data": Schema.Array(Batch), - "first_id": Schema.optionalKey(Schema.String), - "last_id": Schema.optionalKey(Schema.String), - "has_more": Schema.Boolean, - "object": Schema.Literal("list") +export const ComputerScreenshotContent = Schema.Struct({ + "type": Schema.Literal("computer_screenshot").annotate({ + "description": + "Specifies the event type. For a computer screenshot, this property is always set to `computer_screenshot`." + }), + "image_url": Schema.Union([ + Schema.String.annotate({ "description": "The URL of the screenshot image.", "format": "uri" }), + Schema.Null + ]), + "file_id": Schema.Union([ + Schema.String.annotate({ "description": "The identifier of an uploaded file that contains the screenshot." }), + Schema.Null + ]), + "detail": Schema.suspend((): Schema.Codec => ImageDetail).annotate({ + "description": + "The detail level of the screenshot image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." + }), + "prompt_cache_breakpoint": Schema.optionalKey(PromptCacheBreakpointConfig) +}).annotate({ + "title": "Computer screenshot", + "description": "A screenshot of a computer.", + "identifier": "ComputerScreenshotContent" }) -export type CreateThreadRequest = { - readonly "messages"?: ReadonlyArray - readonly "tool_resources"?: { - readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } - readonly "file_search"?: { - readonly "vector_store_ids": ReadonlyArray - readonly "vector_stores"?: ReadonlyArray< - { - readonly "file_ids"?: ReadonlyArray - readonly "chunking_strategy"?: { readonly "type": "auto" } | { - readonly "type": "static" - readonly "static": { readonly "max_chunk_size_tokens": number; readonly "chunk_overlap_tokens": number } - } - readonly "metadata"?: Metadata - } - > - } | { - readonly "vector_stores": ReadonlyArray< - { - readonly "file_ids"?: ReadonlyArray - readonly "chunking_strategy"?: { readonly "type": "auto" } | { - readonly "type": "static" - readonly "static": { readonly "max_chunk_size_tokens": number; readonly "chunk_overlap_tokens": number } - } - readonly "metadata"?: Metadata - } - > - readonly "vector_store_ids"?: ReadonlyArray - } - } | null - readonly "metadata"?: Metadata +export type InputFileContent = { + readonly "type": "input_file" + readonly "file_id"?: string | null + readonly "filename"?: string + readonly "file_data"?: string + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointConfig + readonly "file_url"?: string + readonly "detail"?: FileInputDetail } -export const CreateThreadRequest = Schema.Struct({ - "messages": Schema.optionalKey( - Schema.Array(CreateMessageRequest).annotate({ - "description": "A list of [messages](/docs/api-reference/messages) to start the thread with." - }) +export const InputFileContent = Schema.Struct({ + "type": Schema.Literal("input_file").annotate({ "description": "The type of the input item. Always `input_file`." }), + "file_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), + Schema.Null + ]) ), - "tool_resources": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "code_interpreter": Schema.optionalKey(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" - }).check(Schema.isMaxLength(20)) - ) - })), - "file_search": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "vector_store_ids": Schema.Array(Schema.String).annotate({ - "description": - "The [vector store](/docs/api-reference/vector-stores/object) attached to this thread. There can be a maximum of 1 vector store attached to the thread.\n" - }).check(Schema.isMaxLength(1)), - "vector_stores": Schema.optionalKey( - Schema.Array(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files.\n" - }).check(Schema.isMaxLength(100000000)) - ), - "chunking_strategy": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }) - .annotate({ - "title": "Auto Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }), - Schema.Struct({ - "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), - "static": Schema.Struct({ - "max_chunk_size_tokens": Schema.Number.annotate({ - "description": - "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(100)).check( - Schema.isLessThanOrEqualTo(4096) - ), - "chunk_overlap_tokens": Schema.Number.annotate({ - "description": - "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" - }).check(Schema.isInt()) - }) - }).annotate({ - "title": "Static Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }) - ], { mode: "oneOf" }) - ), - "metadata": Schema.optionalKey(Metadata) - })).annotate({ - "description": - "A helper to create a [vector store](/docs/api-reference/vector-stores/object) with file_ids and attach it to this thread. There can be a maximum of 1 vector store attached to the thread.\n" - }).check(Schema.isMaxLength(1)) - ) - }), - Schema.Struct({ - "vector_stores": Schema.Array(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files.\n" - }).check(Schema.isMaxLength(100000000)) - ), - "chunking_strategy": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }) - .annotate({ - "title": "Auto Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }), - Schema.Struct({ - "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), - "static": Schema.Struct({ - "max_chunk_size_tokens": Schema.Number.annotate({ - "description": - "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(100)).check( - Schema.isLessThanOrEqualTo(4096) - ), - "chunk_overlap_tokens": Schema.Number.annotate({ - "description": - "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" - }).check(Schema.isInt()) - }) - }).annotate({ - "title": "Static Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }) - ], { mode: "oneOf" }) - ), - "metadata": Schema.optionalKey(Metadata) - })).annotate({ - "description": - "A helper to create a [vector store](/docs/api-reference/vector-stores/object) with file_ids and attach it to this thread. There can be a maximum of 1 vector store attached to the thread.\n" - }).check(Schema.isMaxLength(1)), - "vector_store_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "The [vector store](/docs/api-reference/vector-stores/object) attached to this thread. There can be a maximum of 1 vector store attached to the thread.\n" - }).check(Schema.isMaxLength(1)) - ) - }) - ], { mode: "oneOf" })) - }).annotate({ + "filename": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the file to be sent to the model." }) + ), + "file_data": Schema.optionalKey( + Schema.String.annotate({ "description": "The content of the file to be sent to the model.\n" }) + ), + "prompt_cache_breakpoint": Schema.optionalKey(PromptCacheBreakpointConfig), + "file_url": Schema.optionalKey( + Schema.String.annotate({ "description": "The URL of the file to be sent to the model.", "format": "uri" }) + ), + "detail": Schema.optionalKey( + Schema.suspend((): Schema.Codec => FileInputDetail).annotate({ "description": - "A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" - }), - Schema.Null - ])), - "metadata": Schema.optionalKey(Metadata) + "The detail level of the file to be sent to the model. Use `auto` to let the system select the detail level; for GPT-5.6 and later models, `auto` uses high-quality rendering, which may increase input token usage. Use `low` for lower-cost rendering, or `high` to render the file at higher quality. Defaults to `auto`." + }) + ) +}).annotate({ "title": "Input file", "description": "A file input to the model.", "identifier": "InputFileContent" }) +export type ToolCallCaller = DirectToolCallCaller | ProgramToolCallCaller +export const ToolCallCaller = Schema.Union([DirectToolCallCaller, ProgramToolCallCaller], { mode: "oneOf" }).annotate({ + "description": "The execution context that produced this tool call.", + "identifier": "ToolCallCaller" +}) +export type ToolCallCallerParam = DirectToolCallCallerParam | ProgramToolCallCallerParam +export const ToolCallCallerParam = Schema.Union([DirectToolCallCallerParam, ProgramToolCallCallerParam], { + mode: "oneOf" }).annotate({ - "description": - "Options to create a new thread. If no thread is provided when running a\nrequest, an empty thread will be created.\n" + "description": "The execution context that produced this tool call.", + "identifier": "ToolCallCallerParam" }) -export type ThreadStreamEvent = { - readonly "enabled"?: boolean - readonly "event": "thread.created" - readonly "data": ThreadObject +export type FileSearchToolCall = { + readonly "id": string + readonly "type": "file_search_call" + readonly "status": "in_progress" | "searching" | "completed" | "incomplete" | "failed" + readonly "queries": ReadonlyArray + readonly "results"?: + | ReadonlyArray< + { + readonly "file_id"?: string + readonly "text"?: string + readonly "filename"?: string + readonly "attributes"?: VectorStoreFileAttributes + readonly "score"?: number + } + > + | null } -export const ThreadStreamEvent = Schema.Union([ - Schema.Struct({ - "enabled": Schema.optionalKey( - Schema.Boolean.annotate({ "description": "Whether to enable input audio transcription." }) - ), - "event": Schema.Literal("thread.created"), - "data": ThreadObject - }).annotate({ "description": "Occurs when a new [thread](/docs/api-reference/threads/object) is created." }) -], { mode: "oneOf" }) -export type ModelIdsCompaction = ModelIdsResponses | string | null -export const ModelIdsCompaction = Schema.Union([ModelIdsResponses, Schema.String, Schema.Null]).annotate({ - "description": - "Model ID used to generate the response, like `gpt-5` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](/docs/models) to browse and compare available models." -}) -export type RealtimeTranslationClientSecretCreateResponse = { - readonly "value": string - readonly "expires_at": number - readonly "session": RealtimeTranslationSession -} -export const RealtimeTranslationClientSecretCreateResponse = Schema.Struct({ - "value": Schema.String.annotate({ "description": "The generated client secret value." }), - "expires_at": Schema.Number.annotate({ - "description": "Expiration timestamp for the client secret, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()), - "session": RealtimeTranslationSession -}).annotate({ - "title": "Realtime translation session and client secret", - "description": "Response from creating a translation session and client secret for the Realtime API.\n" -}) -export type RealtimeTranslationClientSecretCreateRequest = { - readonly "expires_after"?: { readonly "anchor"?: "created_at"; readonly "seconds"?: number } - readonly "session": RealtimeTranslationSessionCreateRequest -} -export const RealtimeTranslationClientSecretCreateRequest = Schema.Struct({ - "expires_after": Schema.optionalKey( - Schema.Struct({ - "anchor": Schema.optionalKey( - Schema.Literal("created_at").annotate({ - "description": - "The anchor point for the client secret expiration, meaning that `seconds` will be added to the `created_at` time of the client secret to produce an expiration timestamp. Only `created_at` is currently supported.\n" - }) +export const FileSearchToolCall = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the file search tool call.\n" }), + "type": Schema.Literal("file_search_call").annotate({ + "description": "The type of the file search tool call. Always `file_search_call`.\n" + }), + "status": Schema.Literals(["in_progress", "searching", "completed", "incomplete", "failed"]).annotate({ + "description": + "The status of the file search tool call. One of `in_progress`,\n`searching`, `incomplete` or `failed`,\n" + }), + "queries": Schema.Array(Schema.String).annotate({ "description": "The queries used to search for files.\n" }), + "results": Schema.optionalKey(Schema.Union([ + Schema.Array(Schema.Struct({ + "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the file.\n" })), + "text": Schema.optionalKey( + Schema.String.annotate({ "description": "The text that was retrieved from the file.\n" }) ), - "seconds": Schema.optionalKey( + "filename": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the file.\n" })), + "attributes": Schema.optionalKey(VectorStoreFileAttributes), + "score": Schema.optionalKey( Schema.Number.annotate({ - "description": - "The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200` (2 hours). This default to 600 seconds (10 minutes) if not specified.\n", - "format": "int64" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(10)).check(Schema.isLessThanOrEqualTo(7200)) + "description": "The relevance score of the file - a value between 0 and 1.\n", + "format": "float" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) ) - }).annotate({ - "title": "Client secret expiration", - "description": - "Configuration for the client secret expiration. Expiration refers to the time after which\na client secret will no longer be valid for creating sessions. The session itself may\ncontinue after that time once started. A secret can be used to create multiple sessions\nuntil it expires.\n" - }) - ), - "session": RealtimeTranslationSessionCreateRequest + })).annotate({ "description": "The results of the file search tool call.\n" }), + Schema.Null + ])) }).annotate({ - "title": "Realtime translation client secret creation request", - "description": "Create a translation session and client secret for the Realtime API.\n" -}) -export type ProjectApiKeyListResponse = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean -} -export const ProjectApiKeyListResponse = Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array(ProjectApiKey), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean -}) -export type RealtimeConversationItem = - | RealtimeConversationItemMessageSystem - | RealtimeConversationItemMessageUser - | RealtimeConversationItemMessageAssistant - | RealtimeConversationItemFunctionCall - | RealtimeConversationItemFunctionCallOutput - | RealtimeMCPApprovalResponse - | RealtimeMCPListTools - | RealtimeMCPToolCall - | RealtimeMCPApprovalRequest -export const RealtimeConversationItem = Schema.Union([ - RealtimeConversationItemMessageSystem, - RealtimeConversationItemMessageUser, - RealtimeConversationItemMessageAssistant, - RealtimeConversationItemFunctionCall, - RealtimeConversationItemFunctionCallOutput, - RealtimeMCPApprovalResponse, - RealtimeMCPListTools, - RealtimeMCPToolCall, - RealtimeMCPApprovalRequest -]).annotate({ "description": "A single item within a Realtime conversation." }) -export type AssistantsApiResponseFormatOption = - | "auto" - | ResponseFormatText - | ResponseFormatJsonObject - | ResponseFormatJsonSchema -export const AssistantsApiResponseFormatOption = Schema.Union([ - Schema.Literal("auto").annotate({ "description": "`auto` is the default value\n" }), - ResponseFormatText, - ResponseFormatJsonObject, - ResponseFormatJsonSchema -], { mode: "oneOf" }).annotate({ + "title": "File search tool call", "description": - "Specifies the format that the model must output. Compatible with [GPT-4o](/docs/models#gpt-4o), [GPT-4 Turbo](/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`.\n\nSetting to `{ \"type\": \"json_schema\", \"json_schema\": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](/docs/guides/structured-outputs).\n\nSetting to `{ \"type\": \"json_object\" }` enables JSON mode, which ensures the message the model generates is valid JSON.\n\n**Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly \"stuck\" request. Also note that the message content may be partially cut off if `finish_reason=\"length\"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length.\n" + "The results of a file search tool call. See the\n[file search guide](https://developers.openai.com/api/docs/guides/tools-file-search) for more information.\n", + "identifier": "FileSearchToolCall" }) -export type TextResponseFormatConfiguration = - | ResponseFormatText - | TextResponseFormatJsonSchema - | ResponseFormatJsonObject -export const TextResponseFormatConfiguration = Schema.Union([ - ResponseFormatText, - TextResponseFormatJsonSchema, - ResponseFormatJsonObject -], { mode: "oneOf" }).annotate({ - "description": - "An object specifying the format that the model must output.\n\nConfiguring `{ \"type\": \"json_schema\" }` enables Structured Outputs, \nwhich ensures the model will match your supplied JSON schema. Learn more in the \n[Structured Outputs guide](/docs/guides/structured-outputs).\n\nThe default format is `{ \"type\": \"text\" }` with no additional options.\n\n**Not recommended for gpt-4o and newer models:**\n\nSetting to `{ \"type\": \"json_object\" }` enables the older JSON mode, which\nensures the message the model generates is valid JSON. Using `json_schema`\nis preferred for models that support it.\n" -}) -export type RealtimeCallCreateRequest = { - readonly "sdp": string - readonly "session"?: { - readonly "type": "realtime" - readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> - readonly "model"?: - | string - | "gpt-realtime" - | "gpt-realtime-1.5" - | "gpt-realtime-2" - | "gpt-realtime-2025-08-28" - | "gpt-4o-realtime-preview" - | "gpt-4o-realtime-preview-2024-10-01" - | "gpt-4o-realtime-preview-2024-12-17" - | "gpt-4o-realtime-preview-2025-06-03" - | "gpt-4o-mini-realtime-preview" - | "gpt-4o-mini-realtime-preview-2024-12-17" - | "gpt-realtime-mini" - | "gpt-realtime-mini-2025-10-06" - | "gpt-realtime-mini-2025-12-15" - | "gpt-audio-1.5" - | "gpt-audio-mini" - | "gpt-audio-mini-2025-10-06" - | "gpt-audio-mini-2025-12-15" - readonly "instructions"?: string - readonly "audio"?: { - readonly "input"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - readonly "delay"?: "minimal" | "low" | "medium" | "high" | "xhigh" - } - readonly "noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "turn_detection"?: RealtimeTurnDetection - } - readonly "output"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "voice"?: VoiceIdsShared | { readonly "id": string } - readonly "speed"?: number - } - } - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> - readonly "tracing"?: "auto" | { - readonly "workflow_name"?: string - readonly "group_id"?: string - readonly "metadata"?: {} - } | null - readonly "tools"?: ReadonlyArray - readonly "tool_choice"?: ToolChoiceOptions | ToolChoiceFunction | ToolChoiceMCP - readonly "parallel_tool_calls"?: boolean - readonly "reasoning"?: RealtimeReasoning - readonly "max_output_tokens"?: number | "inf" - readonly "truncation"?: RealtimeTruncation - readonly "prompt"?: Prompt - } +export type UpdateVectorStoreFileAttributesRequest = { readonly "attributes": VectorStoreFileAttributes } +export const UpdateVectorStoreFileAttributesRequest = Schema.Struct({ "attributes": VectorStoreFileAttributes }) + .annotate({ "identifier": "UpdateVectorStoreFileAttributesRequest" }) +export type WebSearchToolCall = { + readonly "id": string + readonly "type": "web_search_call" + readonly "status": WebSearchCallStatus + readonly "action"?: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind } -export const RealtimeCallCreateRequest = Schema.Struct({ - "sdp": Schema.String.annotate({ - "description": "WebRTC Session Description Protocol (SDP) offer generated by the caller." +export const WebSearchToolCall = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the web search tool call.\n" }), + "type": Schema.Literal("web_search_call").annotate({ + "description": "The type of the web search tool call. Always `web_search_call`.\n" }), - "session": Schema.optionalKey( - Schema.Struct({ - "type": Schema.Literal("realtime").annotate({ - "description": "The type of session to create. Always `realtime` for the Realtime API.\n" - }), - "output_modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": - "The set of modalities the model can respond with. It defaults to `[\"audio\"]`, indicating\nthat the model will respond with audio plus a transcript. `[\"text\"]` can be used to make\nthe model respond with text only. It is not possible to request both `text` and `audio` at the same time.\n" - }) - ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "gpt-realtime", - "gpt-realtime-1.5", - "gpt-realtime-2", - "gpt-realtime-2025-08-28", - "gpt-4o-realtime-preview", - "gpt-4o-realtime-preview-2024-10-01", - "gpt-4o-realtime-preview-2024-12-17", - "gpt-4o-realtime-preview-2025-06-03", - "gpt-4o-mini-realtime-preview", - "gpt-4o-mini-realtime-preview-2024-12-17", - "gpt-realtime-mini", - "gpt-realtime-mini-2025-10-06", - "gpt-realtime-mini-2025-12-15", - "gpt-audio-1.5", - "gpt-audio-mini", - "gpt-audio-mini-2025-10-06", - "gpt-audio-mini-2025-12-15" - ]) - ]).annotate({ "description": "The Realtime model used for this session.\n" }) - ), - "instructions": Schema.optionalKey(Schema.String.annotate({ - "description": - "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\n\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" - })), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the input audio." }) - ), - "transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model to use for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The language of the input audio. Supplying the input language in\n[ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format\nwill improve accuracy and latency.\n" - }) - ), - "prompt": Schema.optionalKey(Schema.String.annotate({ - "description": - "An optional text to guide the model's style or continue a previous audio\nsegment.\nFor `whisper-1`, the [prompt is a list of keywords](/docs/guides/speech-to-text#prompting).\nFor `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example \"expect words related to technology\".\nPrompt is not supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - })), - "delay": Schema.optionalKey( - Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": - "Controls how long the model waits before emitting transcription text.\nHigher values can improve transcription accuracy at the cost of latency.\nOnly supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - }) - ) - }).annotate({ - "description": - "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" - }) - ), - "noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": - "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" - }) - ), - "turn_detection": Schema.optionalKey(RealtimeTurnDetection) - })), - "output": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the output audio." }) - ), - "voice": Schema.optionalKey( - Schema.Union([ - VoiceIdsShared, - Schema.Struct({ - "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) - }).annotate({ "description": "Custom voice reference." }) - ]).annotate({ - "title": "Voice", - "description": - "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`,\n`marin`, and `cedar`. You may also provide a custom voice object with\nan `id`, for example `{ \"id\": \"voice_1234\" }`. Voice cannot be changed\nduring the session once the model has responded with audio at least once.\nWe recommend `marin` and `cedar` for best quality.\n" - }) - ), - "speed": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The speed of the model's spoken response as a multiple of the original speed.\n1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress.\n\nThis parameter is a post-processing adjustment to the audio after it is generated, it's\nalso possible to prompt the model to speak faster or slower.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0.25)).check( - Schema.isLessThanOrEqualTo(1.5) - ) - ) - })) - }).annotate({ "description": "Configuration for input and output audio.\n" }) - ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ - "description": - "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" - }) - ), - "tracing": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.Literal("auto").annotate({ - "title": "auto", - "description": - "Enables tracing and sets default values for tracing configuration options. Always `auto`.\n" - }), - Schema.Struct({ - "workflow_name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The name of the workflow to attach to this trace. This is used to\nname the trace in the Traces Dashboard.\n" - }) - ), - "group_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The group id to attach to this trace to enable filtering and\ngrouping in the Traces Dashboard.\n" - }) - ), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "The arbitrary metadata to attach to this trace to enable\nfiltering in the Traces Dashboard.\n" - }) - ) - }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) - ], { mode: "oneOf" }).annotate({ - "title": "Tracing Configuration", - "description": - "Realtime API can write session traces to the [Traces Dashboard](https://platform.openai.com/logs?api=traces). Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" - }), - Schema.Null - ]) - ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([RealtimeFunctionTool, MCPTool], { mode: "oneOf" })).annotate({ - "description": "Tools available to the model." - }) - ), - "tool_choice": Schema.optionalKey( - Schema.Union([ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMCP], { mode: "oneOf" }).annotate({ - "description": - "How the model chooses tools. Provide one of the string modes or force a specific\nfunction/MCP tool.\n" - }) - ), - "parallel_tool_calls": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": - "Whether the model may call multiple tools in parallel. Only supported by\nreasoning Realtime models such as `gpt-realtime-2`.\n" - }) - ), - "reasoning": Schema.optionalKey(RealtimeReasoning), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" - }) - ), - "truncation": Schema.optionalKey(RealtimeTruncation), - "prompt": Schema.optionalKey(Prompt) - }).annotate({ "title": "Realtime session configuration", "description": "Realtime session object configuration." }) + "status": Schema.suspend((): Schema.Codec => WebSearchCallStatus).annotate({ + "description": "The status of the web search tool call.\n" + }), + "action": Schema.optionalKey( + Schema.Union([WebSearchActionSearch, WebSearchActionOpenPage, WebSearchActionFind], { mode: "oneOf" }).annotate({ + "description": + "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" + }) ) }).annotate({ - "title": "Realtime call creation request", + "title": "Web search tool call", "description": - "Parameters required to initiate a realtime call and receive the SDP answer\nneeded to complete a WebRTC peer connection. Provide an SDP offer generated\nby your client and optionally configure the session that will answer the call." -}) -export type RealtimeClientEventSessionUpdate = { - readonly "event_id"?: string - readonly "type": "session.update" - readonly "session": { - readonly "type": "realtime" - readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> - readonly "model"?: - | string - | "gpt-realtime" - | "gpt-realtime-1.5" - | "gpt-realtime-2" - | "gpt-realtime-2025-08-28" - | "gpt-4o-realtime-preview" - | "gpt-4o-realtime-preview-2024-10-01" - | "gpt-4o-realtime-preview-2024-12-17" - | "gpt-4o-realtime-preview-2025-06-03" - | "gpt-4o-mini-realtime-preview" - | "gpt-4o-mini-realtime-preview-2024-12-17" - | "gpt-realtime-mini" - | "gpt-realtime-mini-2025-10-06" - | "gpt-realtime-mini-2025-12-15" - | "gpt-audio-1.5" - | "gpt-audio-mini" - | "gpt-audio-mini-2025-10-06" - | "gpt-audio-mini-2025-12-15" - readonly "instructions"?: string - readonly "audio"?: { - readonly "input"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - readonly "delay"?: "minimal" | "low" | "medium" | "high" | "xhigh" - } - readonly "noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "turn_detection"?: RealtimeTurnDetection - } - readonly "output"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "voice"?: VoiceIdsShared | { readonly "id": string } - readonly "speed"?: number - } - } - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> - readonly "tracing"?: "auto" | { - readonly "workflow_name"?: string - readonly "group_id"?: string - readonly "metadata"?: {} - } | null - readonly "tools"?: ReadonlyArray - readonly "tool_choice"?: ToolChoiceOptions | ToolChoiceFunction | ToolChoiceMCP - readonly "parallel_tool_calls"?: boolean - readonly "reasoning"?: RealtimeReasoning - readonly "max_output_tokens"?: number | "inf" - readonly "truncation"?: RealtimeTruncation - readonly "prompt"?: Prompt - } | { - readonly "type": "transcription" - readonly "audio"?: { - readonly "input"?: { - readonly "format"?: RealtimeAudioFormats - readonly "transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - readonly "delay"?: "minimal" | "low" | "medium" | "high" | "xhigh" - } - readonly "noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "turn_detection"?: RealtimeTurnDetection - } - } - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> - } + "The results of a web search tool call. See the\n[web search guide](https://developers.openai.com/api/docs/guides/tools-web-search) for more information.\n", + "identifier": "WebSearchToolCall" +}) +export type ImageGenToolCall = { + readonly "type": "image_generation_call" + readonly "id": string + readonly "status": "in_progress" | "completed" | "generating" | "failed" + readonly "result": string | null + readonly "size"?: string | "1024x1024" | "1024x1536" | "1536x1024" | null + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" | null + readonly "action"?: ImageGenActionEnum | null + readonly "background"?: ImageBackground | null + readonly "output_format"?: ImageOutputFormat | null + readonly "revised_prompt"?: string | null } -export const RealtimeClientEventSessionUpdate = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "Optional client-generated ID used to identify this event. This is an arbitrary string that a client may assign. It will be passed back if there is an error with the event, but the corresponding `session.updated` event will not include it." - }).check(Schema.isMaxLength(512)) +export const ImageGenToolCall = Schema.Struct({ + "type": Schema.Literal("image_generation_call").annotate({ + "description": "The type of the image generation call. Always `image_generation_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the image generation call." }), + "status": Schema.Literals(["in_progress", "completed", "generating", "failed"]).annotate({ + "description": "The status of the image generation call." + }), + "result": Schema.Union([ + Schema.String.annotate({ "description": "The generated image encoded in base64." }), + Schema.Null + ]), + "size": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." + }), + Schema.Null + ]) ), - "type": Schema.Literal("session.update").annotate({ "description": "The event type, must be `session.update`." }), - "session": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("realtime").annotate({ - "description": "The type of session to create. Always `realtime` for the Realtime API.\n" + "quality": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": + "The quality of the image generated by the image generation tool call. One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`." }), - "output_modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": - "The set of modalities the model can respond with. It defaults to `[\"audio\"]`, indicating\nthat the model will respond with audio plus a transcript. `[\"text\"]` can be used to make\nthe model respond with text only. It is not possible to request both `text` and `audio` at the same time.\n" - }) - ), - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "gpt-realtime", - "gpt-realtime-1.5", - "gpt-realtime-2", - "gpt-realtime-2025-08-28", - "gpt-4o-realtime-preview", - "gpt-4o-realtime-preview-2024-10-01", - "gpt-4o-realtime-preview-2024-12-17", - "gpt-4o-realtime-preview-2025-06-03", - "gpt-4o-mini-realtime-preview", - "gpt-4o-mini-realtime-preview-2024-12-17", - "gpt-realtime-mini", - "gpt-realtime-mini-2025-10-06", - "gpt-realtime-mini-2025-12-15", - "gpt-audio-1.5", - "gpt-audio-mini", - "gpt-audio-mini-2025-10-06", - "gpt-audio-mini-2025-12-15" - ]) - ]).annotate({ "description": "The Realtime model used for this session.\n" }) - ), - "instructions": Schema.optionalKey(Schema.String.annotate({ - "description": - "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\n\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" - })), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the input audio." }) - ), - "transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model to use for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The language of the input audio. Supplying the input language in\n[ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format\nwill improve accuracy and latency.\n" - }) - ), - "prompt": Schema.optionalKey(Schema.String.annotate({ - "description": - "An optional text to guide the model's style or continue a previous audio\nsegment.\nFor `whisper-1`, the [prompt is a list of keywords](/docs/guides/speech-to-text#prompting).\nFor `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example \"expect words related to technology\".\nPrompt is not supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - })), - "delay": Schema.optionalKey( - Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": - "Controls how long the model waits before emitting transcription text.\nHigher values can improve transcription accuracy at the cost of latency.\nOnly supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - }) - ) - }).annotate({ - "description": - "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" - }) - ), - "noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": - "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" - }) - ), - "turn_detection": Schema.optionalKey(RealtimeTurnDetection) - })), - "output": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the output audio." }) - ), - "voice": Schema.optionalKey( - Schema.Union([ - VoiceIdsShared, - Schema.Struct({ - "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) - }).annotate({ "description": "Custom voice reference." }) - ]).annotate({ - "title": "Voice", - "description": - "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`,\n`marin`, and `cedar`. You may also provide a custom voice object with\nan `id`, for example `{ \"id\": \"voice_1234\" }`. Voice cannot be changed\nduring the session once the model has responded with audio at least once.\nWe recommend `marin` and `cedar` for best quality.\n" - }) - ), - "speed": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The speed of the model's spoken response as a multiple of the original speed.\n1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress.\n\nThis parameter is a post-processing adjustment to the audio after it is generated, it's\nalso possible to prompt the model to speak faster or slower.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0.25)).check( - Schema.isLessThanOrEqualTo(1.5) - ) - ) - })) - }).annotate({ "description": "Configuration for input and output audio.\n" }) - ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ - "description": - "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" - }) - ), - "tracing": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.Literal("auto").annotate({ - "title": "auto", - "description": - "Enables tracing and sets default values for tracing configuration options. Always `auto`.\n" - }), - Schema.Struct({ - "workflow_name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The name of the workflow to attach to this trace. This is used to\nname the trace in the Traces Dashboard.\n" - }) - ), - "group_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The group id to attach to this trace to enable filtering and\ngrouping in the Traces Dashboard.\n" - }) - ), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "The arbitrary metadata to attach to this trace to enable\nfiltering in the Traces Dashboard.\n" - }) - ) - }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) - ], { mode: "oneOf" }).annotate({ - "title": "Tracing Configuration", - "description": - "Realtime API can write session traces to the [Traces Dashboard](https://platform.openai.com/logs?api=traces). Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" - }), - Schema.Null - ]) - ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([RealtimeFunctionTool, MCPTool], { mode: "oneOf" })).annotate({ - "description": "Tools available to the model." - }) - ), - "tool_choice": Schema.optionalKey( - Schema.Union([ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMCP], { mode: "oneOf" }).annotate({ - "description": - "How the model chooses tools. Provide one of the string modes or force a specific\nfunction/MCP tool.\n" - }) - ), - "parallel_tool_calls": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": - "Whether the model may call multiple tools in parallel. Only supported by\nreasoning Realtime models such as `gpt-realtime-2`.\n" - }) - ), - "reasoning": Schema.optionalKey(RealtimeReasoning), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" - }) - ), - "truncation": Schema.optionalKey(RealtimeTruncation), - "prompt": Schema.optionalKey(Prompt) - }).annotate({ - "title": "Realtime session configuration", - "description": "Update the Realtime session. Choose either a realtime\nsession or a transcription session.\n" - }), - Schema.Struct({ - "type": Schema.Literal("transcription").annotate({ - "description": "The type of session to create. Always `transcription` for transcription sessions.\n" + Schema.Null + ]) + ), + "action": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ImageGenActionEnum).annotate({ + "description": "The action used for image generation." }), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey(RealtimeAudioFormats), - "transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model to use for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The language of the input audio. Supplying the input language in\n[ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format\nwill improve accuracy and latency.\n" - }) - ), - "prompt": Schema.optionalKey(Schema.String.annotate({ - "description": - "An optional text to guide the model's style or continue a previous audio\nsegment.\nFor `whisper-1`, the [prompt is a list of keywords](/docs/guides/speech-to-text#prompting).\nFor `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example \"expect words related to technology\".\nPrompt is not supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - })), - "delay": Schema.optionalKey( - Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": - "Controls how long the model waits before emitting transcription text.\nHigher values can improve transcription accuracy at the cost of latency.\nOnly supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - }) - ) - }).annotate({ - "description": - "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" - }) - ), - "noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": - "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" - }) - ), - "turn_detection": Schema.optionalKey(RealtimeTurnDetection) - })) - }).annotate({ "description": "Configuration for input and output audio.\n" }) - ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ - "description": - "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" - }) - ) - }).annotate({ - "title": "Realtime transcription session configuration", - "description": "Update the Realtime session. Choose either a realtime\nsession or a transcription session.\n" - }) - ], { mode: "oneOf" }) + Schema.Null + ]) + ), + "background": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ImageBackground).annotate({ + "description": "The background setting used for generation." + }), + Schema.Null + ]) + ), + "output_format": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ImageOutputFormat).annotate({ + "description": "The output format used for generation." + }), + Schema.Null + ]) + ), + "revised_prompt": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The prompt that was used after any model prompt rewriting." }), + Schema.Null + ]) + ) }).annotate({ - "description": - "Send this event to update the session’s configuration.\nThe client may send this event at any time to update any field\nexcept for `voice` and `model`. `voice` can be updated only if there have been no other audio outputs yet.\n\nWhen the server receives a `session.update`, it will respond\nwith a `session.updated` event showing the full, effective configuration.\nOnly the fields that are present in the `session.update` are updated. To clear a field like\n`instructions`, pass an empty string. To clear a field like `tools`, pass an empty array.\nTo clear a field like `turn_detection`, pass `null`.\n" + "title": "Image generation call", + "description": "An image generation request made by the model.", + "identifier": "ImageGenToolCall" }) -export type RealtimeSession = { - readonly "id"?: string - readonly "object"?: "realtime.session" - readonly "modalities"?: ReadonlyArray<"text" | "audio"> - readonly "model"?: - | string - | "gpt-realtime" - | "gpt-realtime-1.5" - | "gpt-realtime-2025-08-28" - | "gpt-4o-realtime-preview" - | "gpt-4o-realtime-preview-2024-10-01" - | "gpt-4o-realtime-preview-2024-12-17" - | "gpt-4o-realtime-preview-2025-06-03" - | "gpt-4o-mini-realtime-preview" - | "gpt-4o-mini-realtime-preview-2024-12-17" - | "gpt-realtime-mini" - | "gpt-realtime-mini-2025-10-06" - | "gpt-realtime-mini-2025-12-15" - | "gpt-audio-1.5" - | "gpt-audio-mini" - | "gpt-audio-mini-2025-10-06" - | "gpt-audio-mini-2025-12-15" - readonly "instructions"?: string - readonly "voice"?: - | string - | "alloy" - | "ash" - | "ballad" - | "coral" - | "echo" - | "sage" - | "shimmer" - | "verse" - | "marin" - | "cedar" - readonly "input_audio_format"?: "pcm16" | "g711_ulaw" | "g711_alaw" - readonly "output_audio_format"?: "pcm16" | "g711_ulaw" | "g711_alaw" - readonly "input_audio_transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - } | null - readonly "turn_detection"?: RealtimeTurnDetection - readonly "input_audio_noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "speed"?: number - readonly "tracing"?: "auto" | { - readonly "workflow_name"?: string - readonly "group_id"?: string - readonly "metadata"?: {} - } | null - readonly "tools"?: ReadonlyArray - readonly "tool_choice"?: string - readonly "temperature"?: number - readonly "max_response_output_tokens"?: number | "inf" - readonly "expires_at"?: number - readonly "prompt"?: Prompt | null - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> | null +export type ClickParam = { + readonly "type": "click" + readonly "button": ClickButtonType + readonly "x": number + readonly "y": number + readonly "keys"?: ReadonlyArray | null } -export const RealtimeSession = Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ - "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" - }) - ), - "object": Schema.optionalKey( - Schema.Literal("realtime.session").annotate({ "description": "The object type. Always `realtime.session`." }) +export const ClickParam = Schema.Struct({ + "type": Schema.Literal("click").annotate({ + "description": "Specifies the event type. For a click action, this property is always `click`." + }), + "button": Schema.suspend((): Schema.Codec => ClickButtonType).annotate({ + "description": + "Indicates which mouse button was pressed during the click. One of `left`, `right`, `wheel`, `back`, or `forward`." + }), + "x": Schema.Number.annotate({ "description": "The x-coordinate where the click occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": "The set of modalities the model can respond with. To disable audio,\nset this to [\"text\"].\n" - }) + "y": Schema.Number.annotate({ "description": "The y-coordinate where the click occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "model": Schema.optionalKey( + "keys": Schema.optionalKey( Schema.Union([ - Schema.String, - Schema.Literals([ - "gpt-realtime", - "gpt-realtime-1.5", - "gpt-realtime-2025-08-28", - "gpt-4o-realtime-preview", - "gpt-4o-realtime-preview-2024-10-01", - "gpt-4o-realtime-preview-2024-12-17", - "gpt-4o-realtime-preview-2025-06-03", - "gpt-4o-mini-realtime-preview", - "gpt-4o-mini-realtime-preview-2024-12-17", - "gpt-realtime-mini", - "gpt-realtime-mini-2025-10-06", - "gpt-realtime-mini-2025-12-15", - "gpt-audio-1.5", - "gpt-audio-mini", - "gpt-audio-mini-2025-10-06", - "gpt-audio-mini-2025-12-15" - ]) - ]).annotate({ "description": "The Realtime model used for this session.\n" }) - ), - "instructions": Schema.optionalKey(Schema.String.annotate({ + Schema.Array(Schema.String).annotate({ "description": "The keys being held while clicking." }), + Schema.Null + ]) + ) +}).annotate({ "title": "Click", "description": "A click action.", "identifier": "ClickParam" }) +export type DragParam = { + readonly "type": "drag" + readonly "path": ReadonlyArray + readonly "keys"?: ReadonlyArray | null +} +export const DragParam = Schema.Struct({ + "type": Schema.Literal("drag").annotate({ + "description": "Specifies the event type. For a drag action, this property is always set to `drag`." + }), + "path": Schema.Array(CoordParam).annotate({ "description": - "The default system instructions (i.e. system message) prepended to model\ncalls. This field allows the client to guide the model on desired\nresponses. The model can be instructed on response content and format,\n(e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good\nresponses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion\ninto your voice\", \"laugh frequently\"). The instructions are not\nguaranteed to be followed by the model, but they provide guidance to the\nmodel on the desired behavior.\n\n\nNote that the server sets default instructions which will be used if this\nfield is not set and are visible in the `session.created` event at the\nstart of the session.\n" - })), - "voice": Schema.optionalKey( + "An array of coordinates representing the path of the drag action. Coordinates will appear as an array of objects, eg\n```\n[\n { x: 100, y: 200 },\n { x: 200, y: 300 }\n]\n```" + }), + "keys": Schema.optionalKey( Schema.Union([ - Schema.String, - Schema.Literals(["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"]) - ]).annotate({ - "description": - "The voice the model uses to respond. Voice cannot be changed during the\nsession once the model has responded with audio at least once. Current\nvoice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`,\n`shimmer`, and `verse`.\n" - }) - ), - "input_audio_format": Schema.optionalKey( - Schema.Literals(["pcm16", "g711_ulaw", "g711_alaw"]).annotate({ - "description": - "The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\nFor `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate,\nsingle channel (mono), and little-endian byte order.\n" + Schema.Array(Schema.String).annotate({ "description": "The keys being held while dragging the mouse." }), + Schema.Null + ]) + ) +}).annotate({ "title": "Drag", "description": "A drag action.", "identifier": "DragParam" }) +export type ComputerToolCallOutputResource = { + readonly "type": "computer_call_output" + readonly "id": string + readonly "call_id": string + readonly "acknowledged_safety_checks"?: ReadonlyArray + readonly "output": ComputerScreenshotImage + readonly "status": "completed" | "incomplete" + readonly "created_by"?: string +} +export const ComputerToolCallOutputResource = Schema.Struct({ + "type": Schema.Literal("computer_call_output").annotate({ + "description": "The type of the computer tool call output. Always `computer_call_output`.\n" + }), + "id": Schema.String.annotate({ "description": "The ID of the computer tool call output.\n" }), + "call_id": Schema.String.annotate({ "description": "The ID of the computer tool call that produced the output.\n" }), + "acknowledged_safety_checks": Schema.optionalKey( + Schema.Array(ComputerCallSafetyCheckParam).annotate({ + "description": "The safety checks reported by the API that have been acknowledged by the\ndeveloper.\n" }) ), - "output_audio_format": Schema.optionalKey( - Schema.Literals(["pcm16", "g711_ulaw", "g711_alaw"]).annotate({ - "description": - "The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\nFor `pcm16`, output audio is sampled at a rate of 24kHz.\n" - }) + "output": ComputerScreenshotImage, + "status": Schema.Literals(["completed", "incomplete"]).annotate({ + "description": + "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "identifier": "ComputerToolCallOutputResource" }) +export type ToolSearchCall = { + readonly "type": "tool_search_call" + readonly "id": string + readonly "call_id": string | null + readonly "execution": ToolSearchExecutionType + readonly "arguments": Schema.Json + readonly "status": FunctionCallStatus + readonly "created_by"?: string +} +export const ToolSearchCall = Schema.Struct({ + "type": Schema.Literal("tool_search_call").annotate({ + "description": "The type of the item. Always `tool_search_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the tool search call item." }), + "call_id": Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }), + Schema.Null + ]), + "execution": Schema.suspend((): Schema.Codec => ToolSearchExecutionType).annotate({ + "description": "Whether tool search was executed by the server or by the client." + }), + "arguments": Schema.Json.annotate({ + "expected": "JSON value", + "description": "Arguments used for the tool search call." + }), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatus).annotate({ + "description": "The status of the tool search call item that was recorded." + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ "identifier": "ToolSearchCall" }) +export type FunctionTool = { + readonly "type": "function" + readonly "name": string + readonly "async"?: boolean + readonly "description"?: string | null + readonly "parameters": { readonly [x: string]: Schema.Json } | null + readonly "output_schema"?: { readonly [x: string]: Schema.Json } | null + readonly "strict": boolean | null + readonly "defer_loading"?: boolean + readonly "allowed_callers"?: ReadonlyArray | null +} +export const FunctionTool = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The type of the function tool. Always `function`." }), + "name": Schema.String.annotate({ "description": "The name of the function to call." }), + "async": Schema.optionalKey(Schema.Boolean), + "description": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "A description of the function. Used by the model to determine whether or not to call the function." + }), + Schema.Null + ]) ), - "input_audio_transcription": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model used for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`.\n" - }) - ), - "language": Schema.optionalKey(Schema.String.annotate({ "description": "The language of the input audio.\n" })), - "prompt": Schema.optionalKey( - Schema.String.annotate({ - "description": "The prompt configured for input audio transcription, when present.\n" - }) - ) - }).annotate({ - "description": - "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://platform.openai.com/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" + "parameters": Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON schema object describing the parameters of the function." }), Schema.Null - ])), - "turn_detection": Schema.optionalKey(RealtimeTurnDetection), - "input_audio_noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": - "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" - }) - ), - "speed": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The speed of the model's spoken response. 1.0 is the default speed. 0.25 is\nthe minimum speed. 1.5 is the maximum speed. This value can only be changed\nin between model turns, not while a response is in progress.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0.25)).check(Schema.isLessThanOrEqualTo(1.5)) - ), - "tracing": Schema.optionalKey( + ]), + "output_schema": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.Literal("auto").annotate({ "description": "Default tracing mode for the session.\n" }), - Schema.Struct({ - "workflow_name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The name of the workflow to attach to this trace. This is used to\nname the trace in the traces dashboard.\n" - }) - ), - "group_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The group id to attach to this trace to enable filtering and\ngrouping in the traces dashboard.\n" - }) - ), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "The arbitrary metadata to attach to this trace to enable\nfiltering in the traces dashboard.\n" - }) - ) - }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) - ], { mode: "oneOf" }).annotate({ - "title": "Tracing Configuration", - "description": - "Configuration options for tracing. Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON schema object describing the JSON value encoded in string outputs for this function." }), Schema.Null ]) ), - "tools": Schema.optionalKey( - Schema.Array(RealtimeFunctionTool).annotate({ "description": "Tools (functions) available to the model." }) + "strict": Schema.Union([ + Schema.Boolean.annotate({ + "description": "Whether strict parameter validation is enforced for this function tool." + }), + Schema.Null + ]), + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether this function is deferred and loaded via tool search." }) ), - "tool_choice": Schema.optionalKey( - Schema.String.annotate({ - "description": "How the model chooses tools. Options are `auto`, `none`, `required`, or\nspecify a function.\n" + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(CallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }), + Schema.Null + ]) + ) +}).annotate({ + "title": "Function", + "description": + "Defines a function in your own code the model can choose to call. Learn more about [function calling](https://developers.openai.com/api/docs/guides/function-calling).", + "identifier": "FunctionTool" +}) +export type ApplyPatchToolParam = { + readonly "type": "apply_patch" + readonly "allowed_callers"?: ReadonlyArray | null +} +export const ApplyPatchToolParam = Schema.Struct({ + "type": Schema.Literal("apply_patch").annotate({ "description": "The type of the tool. Always `apply_patch`." }), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(CallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ + "title": "Apply patch tool", + "description": "Allows the assistant to create, delete, or update files using unified diffs.", + "identifier": "ApplyPatchToolParam" +}) +export type RankingOptions = { + readonly "ranker"?: RankerVersionType + readonly "score_threshold"?: number + readonly "hybrid_search"?: HybridSearchOptions +} +export const RankingOptions = Schema.Struct({ + "ranker": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RankerVersionType).annotate({ + "description": "The ranker to use for the file search." }) ), - "temperature": Schema.optionalKey( + "score_threshold": Schema.optionalKey( Schema.Number.annotate({ "description": - "Sampling temperature for the model, limited to [0.6, 1.2]. For audio models a temperature of 0.8 is highly recommended for best performance.\n" - }).check(Schema.isFinite()) + "The score threshold for the file search, a number between 0 and 1. Numbers closer to 1 will attempt to return only the most relevant results, but may return fewer results." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) ), - "max_response_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ + "hybrid_search": Schema.optionalKey( + Schema.suspend((): Schema.Codec => HybridSearchOptions).annotate({ "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" + "Weights that control how reciprocal rank fusion balances semantic embedding matches versus sparse keyword matches when hybrid search is enabled." }) - ), - "expires_at": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Expiration timestamp for the session, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()) - ), - "prompt": Schema.optionalKey(Schema.Union([Prompt, Schema.Null])), - "include": Schema.optionalKey( - Schema.Union([ - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ - "description": - "Additional fields to include in server outputs.\n- `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" - }), - Schema.Null - ]) ) -}).annotate({ "description": "Realtime session object for the beta interface." }) -export type RealtimeSessionCreateRequest = { - readonly "client_secret": { readonly "value": string; readonly "expires_at": number } - readonly "modalities"?: ReadonlyArray<"text" | "audio"> - readonly "instructions"?: string - readonly "voice"?: VoiceIdsShared | { readonly "id": string } - readonly "input_audio_format"?: string - readonly "output_audio_format"?: string - readonly "input_audio_transcription"?: { readonly "model"?: string } - readonly "speed"?: number - readonly "tracing"?: "auto" | { - readonly "workflow_name"?: string - readonly "group_id"?: string - readonly "metadata"?: {} - } - readonly "turn_detection"?: { - readonly "type"?: string - readonly "threshold"?: number - readonly "prefix_padding_ms"?: number - readonly "silence_duration_ms"?: number +}).annotate({ "identifier": "RankingOptions" }) +export type Filters = ComparisonFilter | CompoundFilter +export const Filters = Schema.Union([ComparisonFilter, CompoundFilter]).annotate({ "identifier": "Filters" }) +export type VectorStoreSearchRequest = { + readonly "query": string | ReadonlyArray + readonly "rewrite_query"?: boolean + readonly "max_num_results"?: number + readonly "filters"?: ComparisonFilter | CompoundFilter + readonly "ranking_options"?: { + readonly "ranker"?: "none" | "auto" | "default-2024-11-15" + readonly "score_threshold"?: number } - readonly "tools"?: ReadonlyArray< - { - readonly "type"?: "function" - readonly "name"?: string - readonly "description"?: string - readonly "parameters"?: {} - } - > - readonly "tool_choice"?: string - readonly "temperature"?: number - readonly "max_response_output_tokens"?: number | "inf" - readonly "truncation"?: RealtimeTruncation - readonly "prompt"?: Prompt } -export const RealtimeSessionCreateRequest = Schema.Struct({ - "client_secret": Schema.Struct({ - "value": Schema.String.annotate({ - "description": - "Ephemeral key usable in client environments to authenticate connections\nto the Realtime API. Use this in client-side environments rather than\na standard API token, which should only be used server-side.\n" - }), - "expires_at": Schema.Number.annotate({ - "description": "Timestamp for when the token expires. Currently, all tokens expire\nafter one minute.\n", - "format": "unixtime" - }).check(Schema.isInt()) - }).annotate({ "description": "Ephemeral key returned by the API." }), - "modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": "The set of modalities the model can respond with. To disable audio,\nset this to [\"text\"].\n" - }) - ), - "instructions": Schema.optionalKey(Schema.String.annotate({ - "description": - "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" - })), - "voice": Schema.optionalKey( - Schema.Union([ - VoiceIdsShared, - Schema.Struct({ "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) }) - .annotate({ "description": "Custom voice reference." }) - ]).annotate({ - "title": "Voice", - "description": - "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`,\n`marin`, and `cedar`. You may also provide a custom voice object with an\n`id`, for example `{ \"id\": \"voice_1234\" }`. Voice cannot be changed during\nthe session once the model has responded with audio at least once.\n" - }) +export const VectorStoreSearchRequest = Schema.Struct({ + "query": Schema.Union([ + Schema.String, + Schema.Array(Schema.String.annotate({ "description": "A list of queries to search for." })) + ], { mode: "oneOf" }).annotate({ "description": "A query string for a search" }), + "rewrite_query": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether to rewrite the natural language query for vector search." }) ), - "input_audio_format": Schema.optionalKey( - Schema.String.annotate({ - "description": "The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\n" - }) + "max_num_results": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum number of results to return. This number should be between 1 and 50 inclusive." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(50).annotate({ "expected": "a value less than or equal to 50" })) ), - "output_audio_format": Schema.optionalKey( - Schema.String.annotate({ - "description": "The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\n" + "filters": Schema.optionalKey( + Schema.Union([ComparisonFilter, CompoundFilter], { mode: "oneOf" }).annotate({ + "description": "A filter to apply based on file attributes." }) ), - "input_audio_transcription": Schema.optionalKey( + "ranking_options": Schema.optionalKey( Schema.Struct({ - "model": Schema.optionalKey(Schema.String.annotate({ "description": "The model to use for transcription.\n" })) - }).annotate({ + "ranker": Schema.optionalKey( + Schema.Literals(["none", "auto", "default-2024-11-15"]).annotate({ + "description": "Enable re-ranking; set to `none` to disable, which can help reduce latency." + }) + ), + "score_threshold": Schema.optionalKey( + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })) + ) + }).annotate({ "description": "Ranking options for search." }) + ) +}).annotate({ "identifier": "VectorStoreSearchRequest" }) +export type ComputerUsePreviewTool = { + readonly "type": "computer_use_preview" + readonly "environment": ComputerEnvironment + readonly "display_width": number + readonly "display_height": number +} +export const ComputerUsePreviewTool = Schema.Struct({ + "type": Schema.Literal("computer_use_preview").annotate({ + "description": "The type of the computer use tool. Always `computer_use_preview`." + }), + "environment": Schema.suspend((): Schema.Codec => ComputerEnvironment).annotate({ + "description": "The type of computer environment to control." + }), + "display_width": Schema.Number.annotate({ "description": "The width of the computer display." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "display_height": Schema.Number.annotate({ "description": "The height of the computer display." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "Computer use preview", + "description": + "A tool that controls a virtual computer. Learn more about the [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use).", + "identifier": "ComputerUsePreviewTool" +}) +export type WebSearchTool = { + readonly "type": "web_search" | "web_search_2025_08_26" + readonly "external_web_access"?: boolean + readonly "filters"?: { readonly "allowed_domains"?: ReadonlyArray | null } | null + readonly "user_location"?: WebSearchApproximateLocation + readonly "search_context_size"?: "low" | "medium" | "high" +} +export const WebSearchTool = Schema.Struct({ + "type": Schema.Literals(["web_search", "web_search_2025_08_26"]).annotate({ + "description": "The type of the web search tool. One of `web_search` or `web_search_2025_08_26`." + }), + "external_web_access": Schema.optionalKey( + Schema.Boolean.annotate({ "description": - "Configuration for input audio transcription, defaults to off and can be\nset to `null` to turn off once on. Input audio transcription is not native\nto the model, since the model consumes audio directly. Transcription runs\nasynchronously and should be treated as rough guidance\nrather than the representation understood by the model.\n" + "Allow live internet access for web search. Defaults to true when omitted. When false, the web search tool runs in offline/cache-only mode and will not fetch new external content." }) ), - "speed": Schema.optionalKey( - Schema.Number.annotate({ + "filters": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "allowed_domains": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.String.annotate({ "description": "Allowed domain for the search." })).annotate({ + "title": "Allowed domains for the search.", + "description": + "Allowed domains for the search. If not provided, all domains are allowed.\nSubdomains of the provided domains are allowed as well.\n\nExample: `[\"pubmed.ncbi.nlm.nih.gov\"]`\n" + }), + Schema.Null + ]) + ) + }).annotate({ "description": "Filters for the search.\n" }), + Schema.Null + ])), + "user_location": Schema.optionalKey( + Schema.suspend((): Schema.Codec => WebSearchApproximateLocation).annotate({ "description": - "The speed of the model's spoken response. 1.0 is the default speed. 0.25 is\nthe minimum speed. 1.5 is the maximum speed. This value can only be changed\nin between model turns, not while a response is in progress.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0.25)).check(Schema.isLessThanOrEqualTo(1.5)) + "The approximate location of the user. If omitted or null, defaults to the\nUnited States. To avoid this fallback, pass `{\"type\": \"approximate\"}` without\nlocation fields. To localize results, provide the relevant location fields.\n" + }) ), - "tracing": Schema.optionalKey( - Schema.Union([ - Schema.Literal("auto").annotate({ "description": "Default tracing mode for the session.\n" }), - Schema.Struct({ - "workflow_name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The name of the workflow to attach to this trace. This is used to\nname the trace in the traces dashboard.\n" - }) - ), - "group_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The group id to attach to this trace to enable filtering and\ngrouping in the traces dashboard.\n" - }) - ), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "The arbitrary metadata to attach to this trace to enable\nfiltering in the traces dashboard.\n" - }) - ) - }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) - ], { mode: "oneOf" }).annotate({ - "title": "Tracing Configuration", + "search_context_size": Schema.optionalKey( + Schema.Literals(["low", "medium", "high"]).annotate({ "description": - "Configuration options for tracing. Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" + "High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default." + }) + ) +}).annotate({ + "title": "Web search", + "description": + "Search the Internet for sources related to the prompt. Learn more about the\n[web search tool](https://developers.openai.com/api/docs/guides/tools-web-search).\n", + "identifier": "WebSearchTool" +}) +export type MCPTool = { + readonly "type": "mcp" + readonly "server_label": string + readonly "server_url"?: string + readonly "connector_id"?: + | "connector_dropbox" + | "connector_gmail" + | "connector_googlecalendar" + | "connector_googledrive" + | "connector_microsoftteams" + | "connector_outlookcalendar" + | "connector_outlookemail" + | "connector_sharepoint" + readonly "tunnel_id"?: string + readonly "authorization"?: string + readonly "server_description"?: string + readonly "headers"?: { readonly [x: string]: string } | null + readonly "allowed_tools"?: ReadonlyArray | MCPToolFilter | null + readonly "allowed_callers"?: ReadonlyArray | null + readonly "require_approval"?: + | { readonly "always"?: MCPToolFilter; readonly "never"?: MCPToolFilter } + | "always" + | "never" + | null + readonly "defer_loading"?: boolean +} +export const MCPTool = Schema.Struct({ + "type": Schema.Literal("mcp").annotate({ "description": "The type of the MCP tool. Always `mcp`." }), + "server_label": Schema.String.annotate({ + "description": "A label for this MCP server, used to identify it in tool calls.\n" + }), + "server_url": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The URL for the MCP server. One of `server_url`, `connector_id`, or\n`tunnel_id` must be provided.\n", + "format": "uri" }) ), - "turn_detection": Schema.optionalKey( - Schema.Struct({ - "type": Schema.optionalKey( - Schema.String.annotate({ "description": "Type of turn detection, only `server_vad` is currently supported.\n" }) - ), - "threshold": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" - }).check(Schema.isFinite()) - ), - "prefix_padding_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" - }).check(Schema.isInt()) - ), - "silence_duration_ms": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" - }).check(Schema.isInt()) - ) - }).annotate({ + "connector_id": Schema.optionalKey( + Schema.Literals([ + "connector_dropbox", + "connector_gmail", + "connector_googlecalendar", + "connector_googledrive", + "connector_microsoftteams", + "connector_outlookcalendar", + "connector_outlookemail", + "connector_sharepoint" + ]).annotate({ "description": - "Configuration for turn detection. Can be set to `null` to turn off. Server\nVAD means that the model will detect the start and end of speech based on\naudio volume and respond at the end of user speech.\n" + "Identifier for service connectors, like those available in ChatGPT. One of\n`server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more\nabout service connectors [here](https://developers.openai.com/api/docs/guides/tools-connectors-mcp#connectors).\n\nThis field is deprecated for models released after September 1, 2026.\nUse `server_url` to connect to a remote MCP server, or `tunnel_id` to\nconnect through a Secure MCP Tunnel.\n\nCurrently supported `connector_id` values are:\n\n- Dropbox: `connector_dropbox`\n- Gmail: `connector_gmail`\n- Google Calendar: `connector_googlecalendar`\n- Google Drive: `connector_googledrive`\n- Microsoft Teams: `connector_microsoftteams`\n- Outlook Calendar: `connector_outlookcalendar`\n- Outlook Email: `connector_outlookemail`\n- SharePoint: `connector_sharepoint`\n" }) ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("function").annotate({ "description": "The type of the tool, i.e. `function`." }) - ), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function." })), - "description": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The description of the function, including guidance on when and how\nto call it, and guidance about what to tell the user when calling\n(if anything).\n" - }) - ), - "parameters": Schema.optionalKey( - Schema.Struct({}).annotate({ "description": "Parameters of the function in JSON Schema." }) - ) - })).annotate({ "description": "Tools (functions) available to the model." }) + "tunnel_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The Secure MCP Tunnel ID to use instead of a direct server URL. One of\n`server_url`, `connector_id`, or `tunnel_id` must be provided.\n" + }).check( + Schema.isPattern(new RegExp("^tunnel_[a-z0-9]{32}$", "u")).annotate({ + "expected": "a string matching the RegExp ^tunnel_[a-z0-9]{32}$" + }) + ) ), - "tool_choice": Schema.optionalKey( + "authorization": Schema.optionalKey( Schema.String.annotate({ - "description": "How the model chooses tools. Options are `auto`, `none`, `required`, or\nspecify a function.\n" + "description": + "An OAuth access token that can be used with a remote MCP server, either\nwith a custom MCP server URL or a service connector. Your application\nmust handle the OAuth authorization flow and provide the token here.\n" }) ), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Sampling temperature for the model, limited to [0.6, 1.2]. Defaults to 0.8.\n" - }).check(Schema.isFinite()) + "server_description": Schema.optionalKey( + Schema.String.annotate({ "description": "Optional description of the MCP server, used to provide more context.\n" }) ), - "max_response_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" - }) + "headers": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.String).annotate({ + "description": "Optional HTTP headers to send to the MCP server. Use for authentication\nor other purposes.\n" + }), + Schema.Null + ]) ), - "truncation": Schema.optionalKey(RealtimeTruncation), - "prompt": Schema.optionalKey(Prompt) + "allowed_tools": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.Array(Schema.String).annotate({ + "title": "MCP allowed tools", + "description": "A string array of allowed tool names" + }), + MCPToolFilter + ], { mode: "oneOf" }).annotate({ "description": "List of allowed tool names or a filter object.\n" }), + Schema.Null + ]) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(CallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ), + "require_approval": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.Struct({ "always": Schema.optionalKey(MCPToolFilter), "never": Schema.optionalKey(MCPToolFilter) }) + .annotate({ + "title": "MCP tool approval filter", + "description": + "Specify which of the MCP server's tools require approval. Can be\n`always`, `never`, or a filter object associated with tools\nthat require approval.\n" + }), + Schema.Literals(["always", "never"]).annotate({ + "title": "MCP tool approval setting", + "description": + "Specify a single approval policy for all tools. One of `always` or\n`never`. When set to `always`, all tools will require approval. When\nset to `never`, all tools will not require approval.\n" + }) + ], { mode: "oneOf" }).annotate({ "description": "Specify which of the MCP server's tools require approval." }), + Schema.Null + ]) + ), + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether this MCP tool is deferred and discovered via tool search.\n" }) + ) }).annotate({ - "description": "A new Realtime session configuration, with an ephemeral key. Default TTL\nfor keys is one minute.\n" + "title": "MCP tool", + "description": + "Give the model access to additional tools via remote Model Context Protocol\n(MCP) servers. [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp).\n", + "identifier": "MCPTool" }) -export type RealtimeSessionCreateRequestGA = { - readonly "type": "realtime" - readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> +export type ImageGenTool = { + readonly "type": "image_generation" readonly "model"?: | string - | "gpt-realtime" - | "gpt-realtime-1.5" - | "gpt-realtime-2" - | "gpt-realtime-2025-08-28" - | "gpt-4o-realtime-preview" - | "gpt-4o-realtime-preview-2024-10-01" - | "gpt-4o-realtime-preview-2024-12-17" - | "gpt-4o-realtime-preview-2025-06-03" - | "gpt-4o-mini-realtime-preview" - | "gpt-4o-mini-realtime-preview-2024-12-17" - | "gpt-realtime-mini" - | "gpt-realtime-mini-2025-10-06" - | "gpt-realtime-mini-2025-12-15" - | "gpt-audio-1.5" - | "gpt-audio-mini" - | "gpt-audio-mini-2025-10-06" - | "gpt-audio-mini-2025-12-15" - readonly "instructions"?: string - readonly "audio"?: { - readonly "input"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - readonly "delay"?: "minimal" | "low" | "medium" | "high" | "xhigh" - } - readonly "noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "turn_detection"?: RealtimeTurnDetection - } - readonly "output"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "voice"?: VoiceIdsShared | { readonly "id": string } - readonly "speed"?: number - } - } - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> - readonly "tracing"?: "auto" | { - readonly "workflow_name"?: string - readonly "group_id"?: string - readonly "metadata"?: {} - } | null - readonly "tools"?: ReadonlyArray - readonly "tool_choice"?: ToolChoiceOptions | ToolChoiceFunction | ToolChoiceMCP - readonly "parallel_tool_calls"?: boolean - readonly "reasoning"?: RealtimeReasoning - readonly "max_output_tokens"?: number | "inf" - readonly "truncation"?: RealtimeTruncation - readonly "prompt"?: Prompt + | "gpt-image-1" + | "gpt-image-1-mini" + | "gpt-image-1.5" + | "gpt-image-2" + | "gpt-image-2-2026-04-21" + | "gpt-image-2.5-sunburst" + | "gpt-image-2.5-sunburst-2026-09-08" + | "gpt-image-2.5-flare" + | "gpt-image-2.5-flare-2026-09-08" + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" + readonly "size"?: string | "1024x1024" | "1024x1536" | "1536x1024" | "auto" + readonly "output_format"?: "png" | "webp" | "jpeg" + readonly "output_compression"?: number + readonly "moderation"?: "auto" | "low" + readonly "background"?: "transparent" | "opaque" | "auto" + readonly "input_fidelity"?: InputFidelity | null + readonly "input_image_mask"?: { readonly "image_url"?: string; readonly "file_id"?: string } + readonly "partial_images"?: number + readonly "action"?: ImageGenActionEnum } -export const RealtimeSessionCreateRequestGA = Schema.Struct({ - "type": Schema.Literal("realtime").annotate({ - "description": "The type of session to create. Always `realtime` for the Realtime API.\n" +export const ImageGenTool = Schema.Struct({ + "type": Schema.Literal("image_generation").annotate({ + "description": "The type of the image generation tool. Always `image_generation`.\n" }), - "output_modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": - "The set of modalities the model can respond with. It defaults to `[\"audio\"]`, indicating\nthat the model will respond with audio plus a transcript. `[\"text\"]` can be used to make\nthe model respond with text only. It is not possible to request both `text` and `audio` at the same time.\n" - }) - ), "model": Schema.optionalKey( Schema.Union([ Schema.String, Schema.Literals([ - "gpt-realtime", - "gpt-realtime-1.5", - "gpt-realtime-2", - "gpt-realtime-2025-08-28", - "gpt-4o-realtime-preview", - "gpt-4o-realtime-preview-2024-10-01", - "gpt-4o-realtime-preview-2024-12-17", - "gpt-4o-realtime-preview-2025-06-03", - "gpt-4o-mini-realtime-preview", - "gpt-4o-mini-realtime-preview-2024-12-17", - "gpt-realtime-mini", - "gpt-realtime-mini-2025-10-06", - "gpt-realtime-mini-2025-12-15", - "gpt-audio-1.5", - "gpt-audio-mini", - "gpt-audio-mini-2025-10-06", - "gpt-audio-mini-2025-12-15" - ]) - ]).annotate({ "description": "The Realtime model used for this session.\n" }) - ), - "instructions": Schema.optionalKey(Schema.String.annotate({ - "description": - "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\n\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" - })), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the input audio." }) - ), - "transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model to use for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`. Use `gpt-4o-transcribe-diarize` when you need diarization with speaker labels.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The language of the input audio. Supplying the input language in\n[ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) format\nwill improve accuracy and latency.\n" - }) - ), - "prompt": Schema.optionalKey(Schema.String.annotate({ - "description": - "An optional text to guide the model's style or continue a previous audio\nsegment.\nFor `whisper-1`, the [prompt is a list of keywords](/docs/guides/speech-to-text#prompting).\nFor `gpt-4o-transcribe` models (excluding `gpt-4o-transcribe-diarize`), the prompt is a free text string, for example \"expect words related to technology\".\nPrompt is not supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - })), - "delay": Schema.optionalKey( - Schema.Literals(["minimal", "low", "medium", "high", "xhigh"]).annotate({ - "description": - "Controls how long the model waits before emitting transcription text.\nHigher values can improve transcription accuracy at the cost of latency.\nOnly supported with `gpt-realtime-whisper` in GA Realtime sessions.\n" - }) - ) - }).annotate({ - "description": - "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" - }) - ), - "noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": - "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" - }) - ), - "turn_detection": Schema.optionalKey(RealtimeTurnDetection) - })), - "output": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the output audio." }) - ), - "voice": Schema.optionalKey( - Schema.Union([ - VoiceIdsShared, - Schema.Struct({ - "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) - }).annotate({ "description": "Custom voice reference." }) - ]).annotate({ - "title": "Voice", - "description": - "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`,\n`marin`, and `cedar`. You may also provide a custom voice object with\nan `id`, for example `{ \"id\": \"voice_1234\" }`. Voice cannot be changed\nduring the session once the model has responded with audio at least once.\nWe recommend `marin` and `cedar` for best quality.\n" - }) - ), - "speed": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The speed of the model's spoken response as a multiple of the original speed.\n1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress.\n\nThis parameter is a post-processing adjustment to the audio after it is generated, it's\nalso possible to prompt the model to speak faster or slower.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0.25)).check(Schema.isLessThanOrEqualTo(1.5)) - ) - })) - }).annotate({ "description": "Configuration for input and output audio.\n" }) + "gpt-image-1", + "gpt-image-1-mini", + "gpt-image-1.5", + "gpt-image-2", + "gpt-image-2-2026-04-21", + "gpt-image-2.5-sunburst", + "gpt-image-2.5-sunburst-2026-09-08", + "gpt-image-2.5-flare", + "gpt-image-2.5-flare-2026-09-08" + ]).annotate({ + "description": + "The image generation model to use. One of `gpt-image-1`,\n`gpt-image-1-mini`, `gpt-image-1.5`, `gpt-image-2`,\n`gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`,\n`gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`,\n`gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`. Default:\n`gpt-image-1`.\n" + }) + ]) ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ + "quality": Schema.optionalKey( + Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ "description": - "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" + "The quality of the generated image. The GPT image models support `low`,\n`medium`, and `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`,\nincluding their `2026-09-08` snapshots, also support `xhigh` and `max`.\nDefault: `auto`.\n" }) ), - "tracing": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.Literal("auto").annotate({ - "title": "auto", - "description": "Enables tracing and sets default values for tracing configuration options. Always `auto`.\n" - }), - Schema.Struct({ - "workflow_name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The name of the workflow to attach to this trace. This is used to\nname the trace in the Traces Dashboard.\n" - }) - ), - "group_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The group id to attach to this trace to enable filtering and\ngrouping in the Traces Dashboard.\n" - }) - ), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "The arbitrary metadata to attach to this trace to enable\nfiltering in the Traces Dashboard.\n" - }) - ) - }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) - ], { mode: "oneOf" }).annotate({ - "title": "Tracing Configuration", - "description": - "Realtime API can write session traces to the [Traces Dashboard](https://platform.openai.com/logs?api=traces). Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" - }), - Schema.Null - ]) + "size": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"])]).annotate({ + "description": + "The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the maximum supported resolution is `3840x2160`. The requested size must also satisfy the model's current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is supported for models that allow automatic sizing." + }) ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([RealtimeFunctionTool, MCPTool], { mode: "oneOf" })).annotate({ - "description": "Tools available to the model." + "output_format": Schema.optionalKey( + Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "description": "The output format of the generated image. One of `png`, `webp`, or\n`jpeg`. Default: `png`.\n" }) ), - "tool_choice": Schema.optionalKey( - Schema.Union([ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMCP], { mode: "oneOf" }).annotate({ - "description": - "How the model chooses tools. Provide one of the string modes or force a specific\nfunction/MCP tool.\n" + "output_compression": Schema.optionalKey( + Schema.Number.annotate({ "description": "Compression level for the output image. Default: 100.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })).check( + Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" }) + ) + ), + "moderation": Schema.optionalKey( + Schema.Literals(["auto", "low"]).annotate({ + "description": "Moderation level for the generated image. Default: `auto`.\n" }) ), - "parallel_tool_calls": Schema.optionalKey( - Schema.Boolean.annotate({ + "background": Schema.optionalKey( + Schema.Literals(["transparent", "opaque", "auto"]).annotate({ "description": - "Whether the model may call multiple tools in parallel. Only supported by\nreasoning Realtime models such as `gpt-realtime-2`.\n" + "Set the background of the generated image. One of `transparent`, `opaque`,\nor `auto`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including\ntheir `2026-09-08` snapshots, support `opaque` and `transparent`\nbackgrounds. Transparent backgrounds are available for supported GPT Image\nmodels. For `gpt-image-2` and `gpt-image-2-2026-04-21`, this support is in\npreview. When using `transparent`, set the output format to `png` or `webp`.\nDefault: `auto`.\n" }) ), - "reasoning": Schema.optionalKey(RealtimeReasoning), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ + "input_fidelity": Schema.optionalKey(Schema.Union([InputFidelity, Schema.Null])), + "input_image_mask": Schema.optionalKey( + Schema.Struct({ + "image_url": Schema.optionalKey(Schema.String.annotate({ "description": "Base64-encoded mask image.\n" })), + "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "File ID for the mask image.\n" })) + }).annotate({ "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" + "Optional mask for inpainting. Contains `image_url`\n(string, optional) and `file_id` (string, optional).\n" }) ), - "truncation": Schema.optionalKey(RealtimeTruncation), - "prompt": Schema.optionalKey(Prompt) -}).annotate({ "title": "Realtime session configuration", "description": "Realtime session object configuration." }) -export type RealtimeSessionCreateResponseGA = { - readonly "type": "realtime" - readonly "id": string - readonly "object": "realtime.session" - readonly "expires_at"?: number - readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> - readonly "model"?: - | string - | "gpt-realtime" - | "gpt-realtime-1.5" - | "gpt-realtime-2" - | "gpt-realtime-2025-08-28" - | "gpt-4o-realtime-preview" - | "gpt-4o-realtime-preview-2024-10-01" - | "gpt-4o-realtime-preview-2024-12-17" - | "gpt-4o-realtime-preview-2025-06-03" - | "gpt-4o-mini-realtime-preview" - | "gpt-4o-mini-realtime-preview-2024-12-17" - | "gpt-realtime-mini" - | "gpt-realtime-mini-2025-10-06" - | "gpt-realtime-mini-2025-12-15" - | "gpt-audio-1.5" - | "gpt-audio-mini" - | "gpt-audio-mini-2025-10-06" - | "gpt-audio-mini-2025-12-15" - readonly "instructions"?: string - readonly "audio"?: { - readonly "input"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "transcription"?: { - readonly "model"?: - | string - | "whisper-1" - | "gpt-4o-mini-transcribe" - | "gpt-4o-mini-transcribe-2025-12-15" - | "gpt-4o-transcribe" - | "gpt-4o-transcribe-diarize" - | "gpt-realtime-whisper" - readonly "language"?: string - readonly "prompt"?: string - } - readonly "noise_reduction"?: { readonly "type"?: NoiseReductionType } - readonly "turn_detection"?: RealtimeTurnDetection - } - readonly "output"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "voice"?: - | string - | "alloy" - | "ash" - | "ballad" - | "coral" - | "echo" - | "sage" - | "shimmer" - | "verse" - | "marin" - | "cedar" - readonly "speed"?: number - } - } - readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> - readonly "tracing"?: "auto" | { - readonly "workflow_name"?: string - readonly "group_id"?: string - readonly "metadata"?: {} - } | null - readonly "tools"?: ReadonlyArray - readonly "tool_choice"?: ToolChoiceOptions | ToolChoiceFunction | ToolChoiceMCP - readonly "reasoning"?: RealtimeReasoning - readonly "max_output_tokens"?: number | "inf" - readonly "truncation"?: RealtimeTruncation - readonly "prompt"?: Prompt -} -export const RealtimeSessionCreateResponseGA = Schema.Struct({ - "type": Schema.Literal("realtime").annotate({ - "description": "The type of session to create. Always `realtime` for the Realtime API.\n" - }), - "id": Schema.String.annotate({ - "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" - }), - "object": Schema.Literal("realtime.session").annotate({ - "description": "The object type. Always `realtime.session`." - }), - "expires_at": Schema.optionalKey( + "partial_images": Schema.optionalKey( Schema.Number.annotate({ - "description": "Expiration timestamp for the session, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()) + "description": "Number of partial images to generate in streaming mode, from 0 (default value) to 3.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(3).annotate({ "expected": "a value less than or equal to 3" })) ), - "output_modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": - "The set of modalities the model can respond with. It defaults to `[\"audio\"]`, indicating\nthat the model will respond with audio plus a transcript. `[\"text\"]` can be used to make\nthe model respond with text only. It is not possible to request both `text` and `audio` at the same time.\n" + "action": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ImageGenActionEnum).annotate({ + "description": "Whether to generate a new image or edit an existing image. Default: `auto`.\n" }) - ), - "model": Schema.optionalKey( + ) +}).annotate({ + "title": "Image generation tool", + "description": "A tool that generates images using the GPT image models.\n", + "identifier": "ImageGenTool" +}) +export type LocalEnvironmentParam = { readonly "type": "local"; readonly "skills"?: ReadonlyArray } +export const LocalEnvironmentParam = Schema.Struct({ + "type": Schema.Literal("local").annotate({ "description": "Use a local computer environment." }), + "skills": Schema.optionalKey( + Schema.Array(LocalSkillParam).annotate({ "description": "An optional list of skills." }).check( + Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" }) + ) + ) +}).annotate({ "identifier": "LocalEnvironmentParam" }) +export type CustomGrammarFormatParam = { + readonly "type": "grammar" + readonly "syntax": GrammarSyntax1 + readonly "definition": string +} +export const CustomGrammarFormatParam = Schema.Struct({ + "type": Schema.Literal("grammar").annotate({ "description": "Grammar format. Always `grammar`." }), + "syntax": Schema.suspend((): Schema.Codec => GrammarSyntax1).annotate({ + "description": "The syntax of the grammar definition. One of `lark` or `regex`." + }), + "definition": Schema.String.annotate({ "description": "The grammar definition." }) +}).annotate({ + "title": "Grammar format", + "description": "A grammar defined by the user.", + "identifier": "CustomGrammarFormatParam" +}) +export type FunctionToolParam = { + readonly "name": string + readonly "description"?: string | null + readonly "parameters"?: EmptyModelParam | null + readonly "strict"?: boolean | null + readonly "type": "function" + readonly "async"?: boolean + readonly "output_schema"?: { readonly [x: string]: Schema.Json } | null + readonly "defer_loading"?: boolean + readonly "allowed_callers"?: ReadonlyArray | null +} +export const FunctionToolParam = Schema.Struct({ + "name": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })).check( + Schema.isPattern(new RegExp("^[a-zA-Z0-9_-]+$", "u")).annotate({ + "expected": "a string matching the RegExp ^[a-zA-Z0-9_-]+$" + }) + ), + "description": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "parameters": Schema.optionalKey(Schema.Union([EmptyModelParam, Schema.Null])), + "strict": Schema.optionalKey( Schema.Union([ - Schema.String, - Schema.Literals([ - "gpt-realtime", - "gpt-realtime-1.5", - "gpt-realtime-2", - "gpt-realtime-2025-08-28", - "gpt-4o-realtime-preview", - "gpt-4o-realtime-preview-2024-10-01", - "gpt-4o-realtime-preview-2024-12-17", - "gpt-4o-realtime-preview-2025-06-03", - "gpt-4o-mini-realtime-preview", - "gpt-4o-mini-realtime-preview-2024-12-17", - "gpt-realtime-mini", - "gpt-realtime-mini-2025-10-06", - "gpt-realtime-mini-2025-12-15", - "gpt-audio-1.5", - "gpt-audio-mini", - "gpt-audio-mini-2025-10-06", - "gpt-audio-mini-2025-12-15" - ]) - ]).annotate({ "description": "The Realtime model used for this session.\n" }) - ), - "instructions": Schema.optionalKey(Schema.String.annotate({ - "description": - "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\n\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" - })), - "audio": Schema.optionalKey( - Schema.Struct({ - "input": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the input audio." }) - ), - "transcription": Schema.optionalKey( - Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals([ - "whisper-1", - "gpt-4o-mini-transcribe", - "gpt-4o-mini-transcribe-2025-12-15", - "gpt-4o-transcribe", - "gpt-4o-transcribe-diarize", - "gpt-realtime-whisper" - ]) - ]).annotate({ - "description": - "The model used for transcription. Current options are `whisper-1`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, and `gpt-realtime-whisper`.\n" - }) - ), - "language": Schema.optionalKey( - Schema.String.annotate({ "description": "The language of the input audio.\n" }) - ), - "prompt": Schema.optionalKey( - Schema.String.annotate({ - "description": "The prompt configured for input audio transcription, when present.\n" - }) - ) - }).annotate({ - "description": - "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](/docs/api-reference/audio/createTranscription) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" - }) - ), - "noise_reduction": Schema.optionalKey( - Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }).annotate({ - "description": - "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" - }) - ), - "turn_detection": Schema.optionalKey(RealtimeTurnDetection) - })), - "output": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the output audio." }) - ), - "voice": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals(["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"]) - ]).annotate({ - "description": - "The voice the model uses to respond. Voice cannot be changed during the\nsession once the model has responded with audio at least once. Current\nvoice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`,\n`shimmer`, `verse`, `marin`, and `cedar`. We recommend `marin` and `cedar` for\nbest quality.\n" - }) - ), - "speed": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The speed of the model's spoken response as a multiple of the original speed.\n1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress.\n\nThis parameter is a post-processing adjustment to the audio after it is generated, it's\nalso possible to prompt the model to speak faster or slower.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0.25)).check(Schema.isLessThanOrEqualTo(1.5)) - ) - })) - }).annotate({ "description": "Configuration for input and output audio.\n" }) + Schema.Boolean.annotate({ + "description": + "Whether to enforce strict parameter validation. If omitted, Responses attempts to use strict validation when the schema is compatible, and falls back to non-strict validation otherwise." + }), + Schema.Null + ]) ), - "include": Schema.optionalKey( - Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ + "type": Schema.Literal("function"), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": - "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" + "Whether the tool response can be returned asynchronously versus immediately returned on next response creation." }) ), - "tracing": Schema.optionalKey( + "output_schema": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.Literal("auto").annotate({ - "title": "auto", - "description": "Enables tracing and sets default values for tracing configuration options. Always `auto`.\n" - }), - Schema.Struct({ - "workflow_name": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The name of the workflow to attach to this trace. This is used to\nname the trace in the Traces Dashboard.\n" - }) - ), - "group_id": Schema.optionalKey( - Schema.String.annotate({ - "description": - "The group id to attach to this trace to enable filtering and\ngrouping in the Traces Dashboard.\n" - }) - ), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "The arbitrary metadata to attach to this trace to enable\nfiltering in the Traces Dashboard.\n" - }) - ) - }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) - ], { mode: "oneOf" }).annotate({ - "title": "Tracing Configuration", + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ "description": - "Realtime API can write session traces to the [Traces Dashboard](https://platform.openai.com/logs?api=traces). Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" + "A JSON Schema describing the JSON value encoded in string outputs for this function tool. This does not describe content-array outputs." }), Schema.Null ]) ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([RealtimeFunctionTool, MCPTool], { mode: "oneOf" })).annotate({ - "description": "Tools available to the model." + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether this function should be deferred and discovered via tool search." }) ), - "tool_choice": Schema.optionalKey( - Schema.Union([ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMCP], { mode: "oneOf" }).annotate({ - "description": - "How the model chooses tools. Provide one of the string modes or force a specific\nfunction/MCP tool.\n" + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(CallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ "identifier": "FunctionToolParam" }) +export type ToolSearchToolParam = { + readonly "type": "tool_search" + readonly "execution"?: ToolSearchExecutionType + readonly "description"?: string | null + readonly "parameters"?: EmptyModelParam | null +} +export const ToolSearchToolParam = Schema.Struct({ + "type": Schema.Literal("tool_search").annotate({ "description": "The type of the tool. Always `tool_search`." }), + "execution": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ToolSearchExecutionType).annotate({ + "description": "Whether tool search is executed by the server or by the client." }) ), - "reasoning": Schema.optionalKey(RealtimeReasoning), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" - }) + "description": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "Description shown to the model for a client-executed tool search tool." + }), + Schema.Null + ]) ), - "truncation": Schema.optionalKey(RealtimeTruncation), - "prompt": Schema.optionalKey(Prompt) + "parameters": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => EmptyModelParam).annotate({ + "description": "Parameter schema for a client-executed tool search tool." + }), + Schema.Null + ]) + ) }).annotate({ - "title": "Realtime session configuration object", - "description": "A Realtime session configuration object.\n" + "title": "Tool search tool", + "description": "Hosted or BYOT tool search configuration for deferred tools.", + "identifier": "ToolSearchToolParam" }) -export type CreateVectorStoreFileRequest = { - readonly "file_id": string - readonly "chunking_strategy"?: ChunkingStrategyRequestParam - readonly "attributes"?: VectorStoreFileAttributes -} -export const CreateVectorStoreFileRequest = Schema.Struct({ - "file_id": Schema.String.annotate({ - "description": - "A [File](/docs/api-reference/files) ID that the vector store should use. Useful for tools like `file_search` that can access files. For multi-file ingestion, we recommend [`file_batches`](/docs/api-reference/vector-stores-file-batches/createBatch) to minimize per-vector-store write requests." - }), - "chunking_strategy": Schema.optionalKey(ChunkingStrategyRequestParam), - "attributes": Schema.optionalKey(VectorStoreFileAttributes) -}) -export type CreateTranscriptionResponseStreamEvent = - | TranscriptTextSegmentEvent - | TranscriptTextDeltaEvent - | TranscriptTextDoneEvent -export const CreateTranscriptionResponseStreamEvent = Schema.Union([ - TranscriptTextSegmentEvent, - TranscriptTextDeltaEvent, - TranscriptTextDoneEvent -]) -export type UsageResponse = { - readonly "object": "page" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "next_page": string | null -} -export const UsageResponse = Schema.Struct({ - "object": Schema.Literal("page"), - "data": Schema.Array(UsageTimeBucket), - "has_more": Schema.Boolean, - "next_page": Schema.Union([Schema.String, Schema.Null]) -}) -export type ListVectorStoresResponse = { - readonly "object": string - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean - readonly [x: string]: unknown -} -export const ListVectorStoresResponse = Schema.StructWithRest( - Schema.Struct({ - "object": Schema.String, - "data": Schema.Array(VectorStoreObject), - "first_id": Schema.String, - "last_id": Schema.String, - "has_more": Schema.Boolean - }), - [Schema.Record(Schema.String, Schema.Json)] -) -export type ListVectorStoreFilesResponse = { - readonly "object": string - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean - readonly [x: string]: unknown -} -export const ListVectorStoreFilesResponse = Schema.StructWithRest( - Schema.Struct({ - "object": Schema.String, - "data": Schema.Array(VectorStoreFileObject), - "first_id": Schema.String, - "last_id": Schema.String, - "has_more": Schema.Boolean - }), - [Schema.Record(Schema.String, Schema.Json)] -) -export type VectorStoreSearchResultsPage = { - readonly "object": "vector_store.search_results.page" - readonly "search_query": ReadonlyArray - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "next_page": string | null -} -export const VectorStoreSearchResultsPage = Schema.Struct({ - "object": Schema.Literal("vector_store.search_results.page").annotate({ - "description": "The object type, which is always `vector_store.search_results.page`" - }), - "search_query": Schema.Array(Schema.String.annotate({ "description": "The query used for this search." })), - "data": Schema.Array(VectorStoreSearchResultItem).annotate({ "description": "The list of search result items." }), - "has_more": Schema.Boolean.annotate({ "description": "Indicates if there are more results to fetch." }), - "next_page": Schema.Union([ - Schema.String.annotate({ "description": "The token for the next page, if any." }), - Schema.Null - ]) -}) -export type CreateContainerBody = { +export type ToolSearchOutputFunctionToolParam = { readonly "name": string - readonly "file_ids"?: ReadonlyArray - readonly "expires_after"?: { readonly "anchor": "last_active_at"; readonly "minutes": number } - readonly "skills"?: ReadonlyArray - readonly "memory_limit"?: "1g" | "4g" | "16g" | "64g" - readonly "network_policy"?: ContainerNetworkPolicyDisabledParam | ContainerNetworkPolicyAllowlistParam -} -export const CreateContainerBody = Schema.Struct({ - "name": Schema.String.annotate({ "description": "Name of the container to create." }), - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ "description": "IDs of files to copy to the container." }) + readonly "description"?: string | null + readonly "parameters"?: EmptyModelParam | null + readonly "strict"?: boolean | null + readonly "type": "function" + readonly "async"?: boolean + readonly "output_schema"?: { readonly [x: string]: Schema.Json } | null + readonly "defer_loading"?: boolean + readonly "allowed_callers"?: ReadonlyArray | null +} +export const ToolSearchOutputFunctionToolParam = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the loaded function tool." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })).check( + Schema.isPattern(new RegExp("^(?![\\s\\S]*[\\r\\n])[a-zA-Z0-9_.-]+$", "u")).annotate({ + "expected": "a string matching the RegExp ^(?![\\s\\S]*[\\r\\n])[a-zA-Z0-9_.-]+$" + }) ), - "expires_after": Schema.optionalKey( - Schema.Struct({ - "anchor": Schema.Literal("last_active_at").annotate({ - "description": "Time anchor for the expiration time. Currently only 'last_active_at' is supported." + "description": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "parameters": Schema.optionalKey(Schema.Union([EmptyModelParam, Schema.Null])), + "strict": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to enforce strict parameter validation. If omitted, Responses attempts to use strict validation when the schema is compatible, and falls back to non-strict validation otherwise." }), - "minutes": Schema.Number.check(Schema.isInt()) - }).annotate({ "description": "Container expiration time in seconds relative to the 'anchor' time." }) - ), - "skills": Schema.optionalKey( - Schema.Array(Schema.Union([SkillReferenceParam, InlineSkillParam], { mode: "oneOf" })).annotate({ - "description": "An optional list of skills referenced by id or inline data." - }) + Schema.Null + ]) ), - "memory_limit": Schema.optionalKey( - Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ - "description": "Optional memory limit for the container. Defaults to \"1g\"." + "type": Schema.Literal("function"), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Whether the tool response can be returned asynchronously versus immediately returned on next response creation." }) ), - "network_policy": Schema.optionalKey( - Schema.Union([ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam], { mode: "oneOf" }) - .annotate({ "description": "Network access policy for the container." }) - ) -}) -export type AutoCodeInterpreterToolParam = { - readonly "type": "auto" - readonly "file_ids"?: ReadonlyArray - readonly "memory_limit"?: "1g" | "4g" | "16g" | "64g" | null - readonly "network_policy"?: ContainerNetworkPolicyDisabledParam | ContainerNetworkPolicyAllowlistParam -} -export const AutoCodeInterpreterToolParam = Schema.Struct({ - "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }), - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": "An optional list of uploaded files to make available to your code." - }).check(Schema.isMaxLength(50)) - ), - "memory_limit": Schema.optionalKey( + "output_schema": Schema.optionalKey( Schema.Union([ - Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ - "description": "The memory limit for the code interpreter container." + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "A JSON Schema describing the JSON value encoded in string outputs for this function tool. This does not describe content-array outputs." }), Schema.Null ]) ), - "network_policy": Schema.optionalKey( - Schema.Union([ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam], { mode: "oneOf" }) - .annotate({ "description": "Network access policy for the container." }) + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether this function should be deferred and discovered via tool search." + }) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(CallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) ) -}).annotate({ - "title": "CodeInterpreterToolAuto", - "description": - "Configuration for a code interpreter container. Optionally specify the IDs of the files to run the code on." -}) -export type ContainerAutoParam = { - readonly "type": "container_auto" - readonly "file_ids"?: ReadonlyArray - readonly "memory_limit"?: "1g" | "4g" | "16g" | "64g" | null - readonly "network_policy"?: ContainerNetworkPolicyDisabledParam | ContainerNetworkPolicyAllowlistParam - readonly "skills"?: ReadonlyArray +}).annotate({ "identifier": "ToolSearchOutputFunctionToolParam" }) +export type WebSearchPreviewTool = { + readonly "type": "web_search_preview" | "web_search_preview_2025_03_11" + readonly "user_location"?: ApproximateLocation | null + readonly "search_context_size"?: SearchContextSize + readonly "search_content_types"?: ReadonlyArray } -export const ContainerAutoParam = Schema.Struct({ - "type": Schema.Literal("container_auto").annotate({ - "description": "Automatically creates a container for this request" +export const WebSearchPreviewTool = Schema.Struct({ + "type": Schema.Literals(["web_search_preview", "web_search_preview_2025_03_11"]).annotate({ + "description": "The type of the web search tool. One of `web_search_preview` or `web_search_preview_2025_03_11`." }), - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": "An optional list of uploaded files to make available to your code." - }).check(Schema.isMaxLength(50)) - ), - "memory_limit": Schema.optionalKey( + "user_location": Schema.optionalKey( Schema.Union([ - Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ "description": "The memory limit for the container." }), + Schema.suspend((): Schema.Codec => ApproximateLocation).annotate({ + "description": + "The approximate location of the user. If omitted or null, defaults to the United States. To avoid this fallback, pass `{\"type\": \"approximate\"}` without location fields. To localize results, provide the relevant location fields." + }), Schema.Null ]) ), - "network_policy": Schema.optionalKey( - Schema.Union([ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam], { mode: "oneOf" }) - .annotate({ "description": "Network access policy for the container." }) + "search_context_size": Schema.optionalKey( + Schema.suspend((): Schema.Codec => SearchContextSize).annotate({ + "description": + "High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default." + }) ), - "skills": Schema.optionalKey( - Schema.Array(Schema.Union([SkillReferenceParam, InlineSkillParam], { mode: "oneOf" })).annotate({ - "description": "An optional list of skills referenced by id or inline data." - }).check(Schema.isMaxLength(200)) - ) -}) -export type EvalItemContentArray = ReadonlyArray -export const EvalItemContentArray = Schema.Array(EvalItemContentItem).annotate({ - "title": "An array of Input text, Output text, Input image, and Input audio", + "search_content_types": Schema.optionalKey(Schema.Array(SearchContentType)) +}).annotate({ + "title": "Web search preview", "description": - "A list of inputs, each of which may be either an input text, output text, input\nimage, or input audio object.\n" + "This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search).", + "identifier": "WebSearchPreviewTool" }) -export type OutputTextContent = { - readonly "type": "output_text" - readonly "text": string - readonly "annotations": ReadonlyArray - readonly "logprobs": ReadonlyArray -} -export const OutputTextContent = Schema.Struct({ - "type": Schema.Literal("output_text").annotate({ - "description": "The type of the output text. Always `output_text`." - }), - "text": Schema.String.annotate({ "description": "The text output from the model." }), - "annotations": Schema.Array(Annotation).annotate({ "description": "The annotations of the text output." }), - "logprobs": Schema.Array(LogProb) -}).annotate({ "title": "Output text", "description": "A text output from the model." }) -export type CustomToolCallOutput = { - readonly "type": "custom_tool_call_output" - readonly "id"?: string +export type ProgramOutput = { + readonly "type": "program_output" + readonly "id": string readonly "call_id": string - readonly "output": string | ReadonlyArray + readonly "result": string + readonly "status": ProgramOutputStatus +} +export const ProgramOutput = Schema.Struct({ + "type": Schema.Literal("program_output").annotate({ + "description": "The type of the item. Always `program_output`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the program output item." }), + "call_id": Schema.String.annotate({ "description": "The call ID of the program item." }), + "result": Schema.String.annotate({ "description": "The result produced by the program item." }), + "status": Schema.suspend((): Schema.Codec => ProgramOutputStatus).annotate({ + "description": "The terminal status of the program output item." + }) +}).annotate({ "identifier": "ProgramOutput" }) +export type CodeInterpreterToolCall = { + readonly "type": "code_interpreter_call" + readonly "id": string + readonly "status": "in_progress" | "completed" | "incomplete" | "interpreting" | "failed" + readonly "container_id": string + readonly "code": string | null + readonly "outputs": ReadonlyArray | null } -export const CustomToolCallOutput = Schema.Struct({ - "type": Schema.Literal("custom_tool_call_output").annotate({ - "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" +export const CodeInterpreterToolCall = Schema.Struct({ + "type": Schema.Literal("code_interpreter_call").annotate({ + "description": "The type of the code interpreter tool call. Always `code_interpreter_call`.\n" }), - "id": Schema.optionalKey( - Schema.String.annotate({ "description": "The unique ID of the custom tool call output in the OpenAI platform.\n" }) - ), - "call_id": Schema.String.annotate({ - "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" + "id": Schema.String.annotate({ "description": "The unique ID of the code interpreter tool call.\n" }), + "status": Schema.Literals(["in_progress", "completed", "incomplete", "interpreting", "failed"]).annotate({ + "description": + "The status of the code interpreter tool call. Valid values are `in_progress`, `completed`, `incomplete`, `interpreting`, and `failed`.\n" }), - "output": Schema.Union([ - Schema.String.annotate({ - "title": "string output", - "description": "A string of the output of the custom tool call.\n" + "container_id": Schema.String.annotate({ "description": "The ID of the container used to run the code.\n" }), + "code": Schema.Union([ + Schema.String.annotate({ "description": "The code to run, or null if not available.\n" }), + Schema.Null + ]), + "outputs": Schema.Union([ + Schema.Array(Schema.Union([CodeInterpreterOutputLogs, CodeInterpreterOutputImage], { mode: "oneOf" })).annotate({ + "description": + "The outputs generated by the code interpreter, such as logs or images.\nCan be null if no outputs are available.\n" }), - Schema.Array(FunctionAndCustomToolCallOutput).annotate({ - "title": "output content list", - "description": "Text, image, or file output of the custom tool call.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" - }) + Schema.Null + ]) }).annotate({ - "title": "Custom tool call output", - "description": "The output of a custom tool call from your code, being sent back to the model.\n" + "title": "Code interpreter tool call", + "description": "A tool call to run code.\n", + "identifier": "CodeInterpreterToolCall" }) -export type CustomToolCallOutputResource = { - readonly "type": "custom_tool_call_output" +export type LocalShellToolCall = { + readonly "type": "local_shell_call" readonly "id": string readonly "call_id": string - readonly "output": string | ReadonlyArray + readonly "action": LocalShellExecAction readonly "status": "in_progress" | "completed" | "incomplete" - readonly "created_by"?: string } -export const CustomToolCallOutputResource = Schema.Struct({ - "type": Schema.Literal("custom_tool_call_output").annotate({ - "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" - }), - "id": Schema.String.annotate({ "description": "The unique ID of the custom tool call output item.\n" }), - "call_id": Schema.String.annotate({ - "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" +export const LocalShellToolCall = Schema.Struct({ + "type": Schema.Literal("local_shell_call").annotate({ + "description": "The type of the local shell call. Always `local_shell_call`.\n" }), - "output": Schema.Union([ - Schema.String.annotate({ - "title": "string output", - "description": "A string of the output of the custom tool call.\n" - }), - Schema.Array(FunctionAndCustomToolCallOutput).annotate({ - "title": "output content list", - "description": "Text, image, or file output of the custom tool call.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" + "id": Schema.String.annotate({ "description": "The unique ID of the local shell call.\n" }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the local shell tool call generated by the model.\n" }), + "action": LocalShellExecAction, "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": "The status of the local shell call.\n" + }) +}).annotate({ + "title": "Local shell call", + "description": "A tool call to run a command on the local shell.\n", + "identifier": "LocalShellToolCall" +}) +export type FunctionShellCallOutputContent = { + readonly "stdout": string + readonly "stderr": string + readonly "outcome": FunctionShellCallOutputTimeoutOutcome | FunctionShellCallOutputExitOutcome + readonly "created_by"?: string +} +export const FunctionShellCallOutputContent = Schema.Struct({ + "stdout": Schema.String.annotate({ "description": "The standard output that was captured." }), + "stderr": Schema.String.annotate({ "description": "The standard error output that was captured." }), + "outcome": Schema.Union([FunctionShellCallOutputTimeoutOutcome, FunctionShellCallOutputExitOutcome], { + mode: "oneOf" + }).annotate({ + "title": "Shell call outcome", "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + "Represents either an exit outcome (with an exit code) or a timeout outcome for a shell call output chunk." }), "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) ) }).annotate({ - "title": "Custom tool call output", - "description": "The output of a custom tool call from your code, being sent back to the model.\n" + "title": "Shell call output content", + "description": "The content of a shell tool call output that was emitted.", + "identifier": "FunctionShellCallOutputContent" }) -export type FunctionToolCallOutput = { - readonly "id"?: string - readonly "type": "function_call_output" - readonly "call_id": string - readonly "output": string | ReadonlyArray - readonly "status"?: "in_progress" | "completed" | "incomplete" +export type MCPListTools = { + readonly "type": "mcp_list_tools" + readonly "id": string + readonly "server_label": string + readonly "tools": ReadonlyArray + readonly "error"?: string | null } -export const FunctionToolCallOutput = Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The unique ID of the function tool call output. Populated when this item\nis returned via API.\n" - }) - ), - "type": Schema.Literal("function_call_output").annotate({ - "description": "The type of the function tool call output. Always `function_call_output`.\n" - }), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the function tool call generated by the model.\n" - }), - "output": Schema.Union([ - Schema.String.annotate({ - "title": "string output", - "description": "A string of the output of the function call.\n" - }), - Schema.Array(FunctionAndCustomToolCallOutput).annotate({ - "title": "output content list", - "description": "Text, image, or file output of the function call.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "The output from the function call generated by your code.\nCan be a string or an list of output content.\n" +export const MCPListTools = Schema.Struct({ + "type": Schema.Literal("mcp_list_tools").annotate({ + "description": "The type of the item. Always `mcp_list_tools`.\n" }), - "status": Schema.optionalKey( - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }) + "id": Schema.String.annotate({ "description": "The unique ID of the list.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server.\n" }), + "tools": Schema.Array(MCPListToolsTool).annotate({ "description": "The tools available on the server.\n" }), + "error": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Error message if the server could not list tools.\n" }), + Schema.Null + ]) ) -}).annotate({ "title": "Function tool call output", "description": "The output of a function tool call.\n" }) -export type FunctionToolCallOutputResource = { - readonly "id": string - readonly "type": "function_call_output" - readonly "call_id": string - readonly "output": string | ReadonlyArray - readonly "status": "in_progress" | "completed" | "incomplete" - readonly "created_by"?: string +}).annotate({ + "title": "MCP list tools", + "description": "A list of tools available on an MCP server.\n", + "identifier": "MCPListTools" +}) +export type MCPToolCallError = MCPProtocolError | MCPToolExecutionError | HTTPError +export const MCPToolCallError = Schema.Union([MCPProtocolError, MCPToolExecutionError, HTTPError], { mode: "oneOf" }) + .annotate({ "identifier": "MCPToolCallError" }) +export type InputImageContentParamAutoParam = { + readonly "type": "input_image" + readonly "image_url"?: string | null + readonly "file_id"?: string | null + readonly "detail"?: DetailEnum | null + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointParam | null } -export const FunctionToolCallOutputResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique ID of the function call tool output.\n" }), - "type": Schema.Literal("function_call_output").annotate({ - "description": "The type of the function tool call output. Always `function_call_output`.\n" - }), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the function tool call generated by the model.\n" - }), - "output": Schema.Union([ - Schema.String.annotate({ - "title": "string output", - "description": "A string of the output of the function call.\n" - }), - Schema.Array(FunctionAndCustomToolCallOutput).annotate({ - "title": "output content list", - "description": "Text, image, or file output of the function call.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "The output from the function call generated by your code.\nCan be a string or an list of output content.\n" - }), - "status": Schema.Union([ - Schema.Literal("in_progress").annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }), - Schema.Literal("completed").annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }), - Schema.Literal("incomplete").annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" - }) - ]).annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" +export const InputImageContentParamAutoParam = Schema.Struct({ + "type": Schema.Literal("input_image").annotate({ + "description": "The type of the input item. Always `input_image`." }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) - ) -}).annotate({ "title": "Function tool call output", "description": "The output of a function tool call.\n" }) -export type InputMessageContentList = ReadonlyArray -export const InputMessageContentList = Schema.Array(InputContent).annotate({ - "title": "Input item content list", - "description": "A list of one or many input items to the model, containing different content \ntypes.\n" + "image_url": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL.", + "format": "uri" + }).check(Schema.isMaxCodePoints(20971520).annotate({ "expected": "a string with at most 20971520 code points" })), + Schema.Null + ]) + ), + "file_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), + Schema.Null + ]) + ), + "detail": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => DetailEnum).annotate({ + "description": + "The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." + }), + Schema.Null + ]) + ), + "prompt_cache_breakpoint": Schema.optionalKey(Schema.Union([PromptCacheBreakpointParam, Schema.Null])) +}).annotate({ + "title": "Input image", + "description": + "An image input to the model. Learn about [image inputs](https://developers.openai.com/api/docs/guides/images-vision)", + "identifier": "InputImageContentParamAutoParam" }) -export type ComputerAction = - | ClickParam - | DoubleClickAction - | DragParam - | KeyPressAction - | MoveParam - | ScreenshotParam - | ScrollParam - | TypeParam - | WaitParam -export const ComputerAction = Schema.Union([ - ClickParam, - DoubleClickAction, - DragParam, - KeyPressAction, - MoveParam, - ScreenshotParam, - ScrollParam, - TypeParam, - WaitParam -], { mode: "oneOf" }) -export type NamespaceToolParam = { - readonly "type": "namespace" - readonly "name": string - readonly "description": string - readonly "tools": ReadonlyArray +export type InputFileContentParam = { + readonly "type": "input_file" + readonly "file_id"?: string | null + readonly "filename"?: string | null + readonly "file_data"?: string | null + readonly "file_url"?: string | null + readonly "detail"?: FileDetailEnum + readonly "prompt_cache_breakpoint"?: PromptCacheBreakpointParam | null } -export const NamespaceToolParam = Schema.Struct({ - "type": Schema.Literal("namespace").annotate({ "description": "The type of the tool. Always `namespace`." }), - "name": Schema.String.annotate({ "description": "The namespace name used in tool calls (for example, `crm`)." }) - .check(Schema.isMinLength(1)), - "description": Schema.String.annotate({ "description": "A description of the namespace shown to the model." }).check( - Schema.isMinLength(1) +export const InputFileContentParam = Schema.Struct({ + "type": Schema.Literal("input_file").annotate({ "description": "The type of the input item. Always `input_file`." }), + "file_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), + Schema.Null + ]) ), - "tools": Schema.Array( - Schema.Union([FunctionToolParam, CustomToolParam], { mode: "oneOf" }).annotate({ - "description": "A function or custom tool that belongs to a namespace." + "filename": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The name of the file to be sent to the model." }), + Schema.Null + ]) + ), + "file_data": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The base64-encoded data of the file to be sent to the model." }).check( + Schema.isMaxCodePoints(73400320).annotate({ "expected": "a string with at most 73400320 code points" }) + ), + Schema.Null + ]) + ), + "file_url": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The URL of the file to be sent to the model.", "format": "uri" }), + Schema.Null + ]) + ), + "detail": Schema.optionalKey( + Schema.suspend((): Schema.Codec => FileDetailEnum).annotate({ + "description": + "The detail level of the file to be sent to the model. Use `auto` to let the system select the detail level; for GPT-5.6 and later models, `auto` uses high-quality rendering, which may increase input token usage. Use `low` for lower-cost rendering, or `high` to render the file at higher quality. Defaults to `auto`." }) - ).annotate({ "description": "The function/custom tools available inside this namespace." }).check( - Schema.isMinLength(1) - ) -}).annotate({ "title": "Namespace", "description": "Groups function/custom tools under a shared namespace." }) -export type FunctionShellCallOutput = { - readonly "type": "shell_call_output" + ), + "prompt_cache_breakpoint": Schema.optionalKey(Schema.Union([PromptCacheBreakpointParam, Schema.Null])) +}).annotate({ + "title": "Input file", + "description": "A file input to the model.", + "identifier": "InputFileContentParam" +}) +export type FunctionShellCallOutputOutcomeParam = + | FunctionShellCallOutputTimeoutOutcomeParam + | FunctionShellCallOutputExitOutcomeParam +export const FunctionShellCallOutputOutcomeParam = Schema.Union([ + FunctionShellCallOutputTimeoutOutcomeParam, + FunctionShellCallOutputExitOutcomeParam +], { mode: "oneOf" }).annotate({ + "title": "Shell call outcome", + "description": "The exit or timeout outcome associated with this shell call.", + "identifier": "FunctionShellCallOutputOutcomeParam" +}) +export type ApplyPatchOperationParam = + | ApplyPatchCreateFileOperationParam + | ApplyPatchDeleteFileOperationParam + | ApplyPatchUpdateFileOperationParam +export const ApplyPatchOperationParam = Schema.Union([ + ApplyPatchCreateFileOperationParam, + ApplyPatchDeleteFileOperationParam, + ApplyPatchUpdateFileOperationParam +], { mode: "oneOf" }).annotate({ + "title": "Apply patch operation", + "description": "One of the create_file, delete_file, or update_file operations supplied to the apply_patch tool.", + "identifier": "ApplyPatchOperationParam" +}) +export type ProgramOutputItemParam = { readonly "id": string + readonly "type": "program_output" readonly "call_id": string - readonly "status": "in_progress" | "completed" | "incomplete" - readonly "output": ReadonlyArray - readonly "max_output_length": number | null - readonly "created_by"?: string + readonly "result": string + readonly "status": ProgramOutputItemStatus +} +export const ProgramOutputItemParam = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of this program output item." }), + "type": Schema.Literal("program_output").annotate({ "description": "The item type. Always `program_output`." }), + "call_id": Schema.String.annotate({ "description": "The call ID of the program item." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "result": Schema.String.annotate({ "description": "The result produced by the program item." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => ProgramOutputItemStatus).annotate({ + "description": "The terminal status of the program output." + }) +}).annotate({ "identifier": "ProgramOutputItemParam" }) +export type CreateEmbeddingResponse = { + readonly "data": ReadonlyArray + readonly "model": string + readonly "object": "list" + readonly "usage": { readonly "prompt_tokens": number; readonly "total_tokens": number } } -export const FunctionShellCallOutput = Schema.Struct({ - "type": Schema.Literal("shell_call_output").annotate({ - "description": "The type of the shell call output. Always `shell_call_output`." +export const CreateEmbeddingResponse = Schema.Struct({ + "data": Schema.Array(Embedding).annotate({ "description": "The list of embeddings generated by the model." }), + "model": Schema.String.annotate({ "description": "The name of the model used to generate the embedding." }), + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always \"list\"." }), + "usage": Schema.Struct({ + "prompt_tokens": Schema.Number.annotate({ "description": "The number of tokens used by the prompt." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used by the request." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "The usage information for the request." }) +}).annotate({ "identifier": "CreateEmbeddingResponse" }) +export type CreateEvalJsonlRunDataSource = { + readonly "type": "jsonl" + readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource +} +export const CreateEvalJsonlRunDataSource = Schema.Struct({ + "type": Schema.Literal("jsonl").annotate({ "description": "The type of data source. Always `jsonl`." }), + "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource], { mode: "oneOf" }).annotate({ + "description": "Determines what populates the `item` namespace in the data source." + }) +}).annotate({ + "title": "JsonlRunDataSource", + "description": "A JsonlRunDataSource object with that specifies a JSONL file that matches the eval \n", + "identifier": "CreateEvalJsonlRunDataSource" +}) +export type EvalRunOutputItem = { + readonly "object": "eval.run.output_item" + readonly "id": string + readonly "run_id": string + readonly "eval_id": string + readonly "created_at": number + readonly "status": string + readonly "datasource_item_id": number + readonly "datasource_item": { readonly [x: string]: Schema.Json } + readonly "results": ReadonlyArray + readonly "sample": { + readonly "input": ReadonlyArray<{ readonly "role": string; readonly "content": string }> + readonly "output": ReadonlyArray<{ readonly "role"?: string; readonly "content"?: string }> + readonly "finish_reason": string + readonly "model": string + readonly "usage": { + readonly "total_tokens": number + readonly "completion_tokens": number + readonly "prompt_tokens": number + readonly "cached_tokens": number + } + readonly "error": EvalApiError | null + readonly "temperature": number + readonly "max_completion_tokens": number + readonly "top_p": number + readonly "seed": number + } +} +export const EvalRunOutputItem = Schema.Struct({ + "object": Schema.Literal("eval.run.output_item").annotate({ + "description": "The type of the object. Always \"eval.run.output_item\"." }), - "id": Schema.String.annotate({ - "description": "The unique ID of the shell call output. Populated when this item is returned via API." + "id": Schema.String.annotate({ "description": "Unique identifier for the evaluation run output item." }), + "run_id": Schema.String.annotate({ + "description": "The identifier of the evaluation run associated with this output item." }), - "call_id": Schema.String.annotate({ "description": "The unique ID of the shell tool call generated by the model." }), - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": "The status of the shell call output. One of `in_progress`, `completed`, or `incomplete`." + "eval_id": Schema.String.annotate({ "description": "The identifier of the evaluation group." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the evaluation run was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "status": Schema.String.annotate({ "description": "The status of the evaluation run." }), + "datasource_item_id": Schema.Number.annotate({ "description": "The identifier for the data source item." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "datasource_item": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Details of the input data source item." }), - "output": Schema.Array(FunctionShellCallOutputContent).annotate({ - "description": "An array of shell call output contents" + "results": Schema.Array(EvalRunOutputItemResult).annotate({ + "description": "A list of grader results for this output item." }), - "max_output_length": Schema.Union([ - Schema.Number.annotate({ - "description": - "The maximum length of the shell command output. This is generated by the model and should be passed back with the raw output." - }).check(Schema.isInt()), - Schema.Null - ]), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) - ) -}).annotate({ "title": "Shell call output", "description": "The output of a shell tool call that was emitted." }) -export type ImagesResponse = { - readonly "created": number - readonly "data"?: ReadonlyArray - readonly "background"?: "transparent" | "opaque" - readonly "output_format"?: "png" | "webp" | "jpeg" - readonly "size"?: "1024x1024" | "1024x1536" | "1536x1024" - readonly "quality"?: "low" | "medium" | "high" - readonly "usage"?: ImageGenUsage + "sample": Schema.Struct({ + "input": Schema.Array( + Schema.Struct({ + "role": Schema.String.annotate({ + "description": "The role of the message sender (e.g., system, user, developer)." + }), + "content": Schema.String.annotate({ "description": "The content of the message." }) + }).annotate({ "description": "An input message." }) + ).annotate({ "description": "An array of input messages." }), + "output": Schema.Array( + Schema.Struct({ + "role": Schema.optionalKey( + Schema.String.annotate({ + "description": "The role of the message (e.g. \"system\", \"assistant\", \"user\")." + }) + ), + "content": Schema.optionalKey(Schema.String.annotate({ "description": "The content of the message." })) + }) + ).annotate({ "description": "An array of output messages." }), + "finish_reason": Schema.String.annotate({ "description": "The reason why the sample generation was finished." }), + "model": Schema.String.annotate({ "description": "The model used for generating the sample." }), + "usage": Schema.Struct({ + "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "completion_tokens": Schema.Number.annotate({ "description": "The number of completion tokens generated." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "prompt_tokens": Schema.Number.annotate({ "description": "The number of prompt tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "cached_tokens": Schema.Number.annotate({ "description": "The number of tokens retrieved from cache." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "Token usage details for the sample." }), + "error": Schema.Union([EvalApiError, Schema.Null]), + "temperature": Schema.Number.annotate({ "description": "The sampling temperature used." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "max_completion_tokens": Schema.Number.annotate({ + "description": "The maximum number of tokens allowed for completion." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "top_p": Schema.Number.annotate({ "description": "The top_p value used for sampling." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ), + "seed": Schema.Number.annotate({ "description": "The seed used for generating the sample." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "A sample containing the input and output of the evaluation run." }) +}).annotate({ + "title": "EvalRunOutputItem", + "description": "A schema representing an evaluation run output item.\n", + "identifier": "EvalRunOutputItem" +}) +export type ListFilesResponse = { + readonly "object": string + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean } -export const ImagesResponse = Schema.Struct({ - "created": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the image was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "data": Schema.optionalKey(Schema.Array(Image).annotate({ "description": "The list of generated images." })), - "background": Schema.optionalKey( - Schema.Literals(["transparent", "opaque"]).annotate({ - "description": "The background parameter used for the image generation. Either `transparent` or `opaque`." - }) - ), - "output_format": Schema.optionalKey( - Schema.Literals(["png", "webp", "jpeg"]).annotate({ - "description": "The output format of the image generation. Either `png`, `webp`, or `jpeg`." - }) - ), - "size": Schema.optionalKey( - Schema.Literals(["1024x1024", "1024x1536", "1536x1024"]).annotate({ - "description": "The size of the image generated. Either `1024x1024`, `1024x1536`, or `1536x1024`." - }) - ), - "quality": Schema.optionalKey( - Schema.Literals(["low", "medium", "high"]).annotate({ - "description": "The quality of the image generated. Either `low`, `medium`, or `high`." - }) - ), - "usage": Schema.optionalKey(ImageGenUsage) -}).annotate({ "title": "Image generation response", "description": "The response from the image generation endpoint." }) -export type AssistantMessageItem = { +export const ListFilesResponse = Schema.Struct({ + "object": Schema.String, + "data": Schema.Array(OpenAIFile), + "first_id": Schema.String, + "last_id": Schema.String, + "has_more": Schema.Boolean +}).annotate({ "identifier": "ListFilesResponse" }) +export type Upload = { readonly "id": string - readonly "object": "chatkit.thread_item" readonly "created_at": number - readonly "thread_id": string - readonly "type": "chatkit.assistant_message" - readonly "content": ReadonlyArray + readonly "filename": string + readonly "bytes": number + readonly "purpose": string + readonly "status": "pending" | "completed" | "cancelled" | "expired" + readonly "expires_at": number + readonly "object"?: "upload" + readonly "file"?: OpenAIFile | null } -export const AssistantMessageItem = Schema.Struct({ - "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), - "object": Schema.Literal("chatkit.thread_item").annotate({ - "description": "Type discriminator that is always `chatkit.thread_item`." +export const Upload = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The Upload unique identifier, which can be referenced in API endpoints." }), "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) for when the item was created.", + "description": "The Unix timestamp (in seconds) for when the Upload was created.", "format": "unixtime" - }).check(Schema.isInt()), - "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), - "type": Schema.Literal("chatkit.assistant_message").annotate({ - "description": "Type discriminator that is always `chatkit.assistant_message`." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "filename": Schema.String.annotate({ "description": "The name of the file to be uploaded." }), + "bytes": Schema.Number.annotate({ "description": "The intended number of bytes to be uploaded." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "purpose": Schema.String.annotate({ + "description": + "The intended purpose of the file. [Please refer here](https://developers.openai.com/api/reference/resources/files#%28resource%29%20files%20%3E%20%28model%29%20file_object%20%3E%20%28schema%29%20%3E%20%28property%29%20purpose) for acceptable values." }), - "content": Schema.Array(ResponseOutputText).annotate({ "description": "Ordered assistant response segments." }) -}).annotate({ "title": "Assistant message", "description": "Assistant-authored message within a thread." }) -export type ThreadListResource = { + "status": Schema.Literals(["pending", "completed", "cancelled", "expired"]).annotate({ + "description": "The status of the Upload." + }), + "expires_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the Upload will expire.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "object": Schema.optionalKey( + Schema.Literal("upload").annotate({ "description": "The object type, which is always \"upload\"." }) + ), + "file": Schema.optionalKey( + Schema.Union([OpenAIFile, Schema.Null]).annotate({ + "description": "The ready File object after the Upload is completed." + }) + ) +}).annotate({ + "title": "Upload", + "description": "The Upload object can accept byte chunks in the form of Parts.\n", + "identifier": "Upload" +}) +export type CreateFileRequestMultipart = { + readonly "file": __ClientMultipartFile + readonly "purpose": "assistants" | "batch" | "fine-tune" | "vision" | "user_data" | "evals" + readonly "expires_after"?: FileExpirationAfter +} +export const CreateFileRequestMultipart = Schema.Struct({ + "file": __ClientMultipartFile, + "purpose": Schema.Literals(["assistants", "batch", "fine-tune", "vision", "user_data", "evals"]).annotate({ + "description": + "The intended purpose of the uploaded file. One of:\n- `assistants`: Used in the Assistants API\n- `batch`: Used in the Batch API\n- `fine-tune`: Used for fine-tuning\n- `vision`: Images used for vision fine-tuning\n- `user_data`: Flexible file type for any purpose\n- `evals`: Used for eval data sets\n" + }), + "expires_after": Schema.optionalKey(FileExpirationAfter) +}).annotate({ "identifier": "CreateFileRequestMultipart" }) +export type CreateUploadRequest = { + readonly "filename": string + readonly "purpose": "assistants" | "batch" | "fine-tune" | "vision" + readonly "bytes": number + readonly "mime_type": string + readonly "expires_after"?: FileExpirationAfter +} +export const CreateUploadRequest = Schema.Struct({ + "filename": Schema.String.annotate({ "description": "The name of the file to upload.\n" }), + "purpose": Schema.Literals(["assistants", "batch", "fine-tune", "vision"]).annotate({ + "description": + "The intended purpose of the uploaded file.\n\nSee the [documentation on File\npurposes](https://developers.openai.com/api/reference/resources/files/methods/create#%28resource%29%20files%20%3E%20%28method%29%20create%20%3E%20%28params%29%200%20%3E%20%28param%29%20purpose%20%3E%20%28schema%29).\n" + }), + "bytes": Schema.Number.annotate({ "description": "The number of bytes in the file you are uploading.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "mime_type": Schema.String.annotate({ + "description": + "The MIME type of the file.\n\n\nThis must fall within the supported MIME types for your file purpose. See\nthe supported MIME types for assistants and vision.\n" + }), + "expires_after": Schema.optionalKey(FileExpirationAfter) +}).annotate({ "identifier": "CreateUploadRequest" }) +export type ListFineTuningCheckpointPermissionResponse = { + readonly "data": ReadonlyArray readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string | null - readonly "last_id": string | null + readonly "first_id"?: string | null + readonly "last_id"?: string | null readonly "has_more": boolean } -export const ThreadListResource = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), - "data": Schema.Array(ThreadResource).annotate({ "description": "A list of items" }), - "first_id": Schema.Union([ - Schema.String.annotate({ "description": "The ID of the first item in the list." }), - Schema.Null - ]), - "last_id": Schema.Union([ - Schema.String.annotate({ "description": "The ID of the last item in the list." }), - Schema.Null - ]), - "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) -}).annotate({ "title": "Threads", "description": "A paginated list of ChatKit threads." }) -export type AuditLog = { - readonly "id": string - readonly "type": AuditLogEventType - readonly "effective_at": number - readonly "project"?: { readonly "id"?: string; readonly "name"?: string } - readonly "actor"?: AuditLogActor | null - readonly "api_key.created"?: { - readonly "id"?: string - readonly "data"?: { readonly "scopes"?: ReadonlyArray } - } - readonly "api_key.updated"?: { - readonly "id"?: string - readonly "changes_requested"?: { readonly "scopes"?: ReadonlyArray } - } - readonly "api_key.deleted"?: { readonly "id"?: string } - readonly "checkpoint.permission.created"?: { - readonly "id"?: string - readonly "data"?: { readonly "project_id"?: string; readonly "fine_tuned_model_checkpoint"?: string } - } - readonly "checkpoint.permission.deleted"?: { readonly "id"?: string } - readonly "external_key.registered"?: { readonly "id"?: string; readonly "data"?: {} } - readonly "external_key.removed"?: { readonly "id"?: string } - readonly "group.created"?: { readonly "id"?: string; readonly "data"?: { readonly "group_name"?: string } } - readonly "group.updated"?: { - readonly "id"?: string - readonly "changes_requested"?: { readonly "group_name"?: string } - } - readonly "group.deleted"?: { readonly "id"?: string } - readonly "scim.enabled"?: { readonly "id"?: string } - readonly "scim.disabled"?: { readonly "id"?: string } - readonly "invite.sent"?: { - readonly "id"?: string - readonly "data"?: { readonly "email"?: string; readonly "role"?: string } - } - readonly "invite.accepted"?: { readonly "id"?: string } - readonly "invite.deleted"?: { readonly "id"?: string } - readonly "ip_allowlist.created"?: { - readonly "id"?: string - readonly "name"?: string - readonly "allowed_ips"?: ReadonlyArray - } - readonly "ip_allowlist.updated"?: { readonly "id"?: string; readonly "allowed_ips"?: ReadonlyArray } - readonly "ip_allowlist.deleted"?: { - readonly "id"?: string - readonly "name"?: string - readonly "allowed_ips"?: ReadonlyArray - } - readonly "ip_allowlist.config.activated"?: { - readonly "configs"?: ReadonlyArray<{ readonly "id"?: string; readonly "name"?: string }> - } - readonly "ip_allowlist.config.deactivated"?: { - readonly "configs"?: ReadonlyArray<{ readonly "id"?: string; readonly "name"?: string }> - } - readonly "login.succeeded"?: {} - readonly "login.failed"?: { readonly "error_code"?: string; readonly "error_message"?: string } - readonly "logout.succeeded"?: {} - readonly "logout.failed"?: { readonly "error_code"?: string; readonly "error_message"?: string } - readonly "organization.updated"?: { - readonly "id"?: string - readonly "changes_requested"?: { - readonly "title"?: string - readonly "description"?: string - readonly "name"?: string - readonly "threads_ui_visibility"?: string - readonly "usage_dashboard_visibility"?: string - readonly "api_call_logging"?: string - readonly "api_call_logging_project_ids"?: string - } - } - readonly "project.created"?: { - readonly "id"?: string - readonly "data"?: { readonly "name"?: string; readonly "title"?: string } - } - readonly "project.updated"?: { readonly "id"?: string; readonly "changes_requested"?: { readonly "title"?: string } } - readonly "project.archived"?: { readonly "id"?: string } - readonly "project.deleted"?: { readonly "id"?: string } - readonly "rate_limit.updated"?: { - readonly "id"?: string - readonly "changes_requested"?: { - readonly "max_requests_per_1_minute"?: number - readonly "max_tokens_per_1_minute"?: number - readonly "max_images_per_1_minute"?: number - readonly "max_audio_megabytes_per_1_minute"?: number - readonly "max_requests_per_1_day"?: number - readonly "batch_1_day_max_input_tokens"?: number - } - } - readonly "rate_limit.deleted"?: { readonly "id"?: string } - readonly "role.created"?: { - readonly "id"?: string - readonly "role_name"?: string - readonly "permissions"?: ReadonlyArray - readonly "resource_type"?: string - readonly "resource_id"?: string - } - readonly "role.updated"?: { - readonly "id"?: string - readonly "changes_requested"?: { - readonly "role_name"?: string - readonly "resource_id"?: string - readonly "resource_type"?: string - readonly "permissions_added"?: ReadonlyArray - readonly "permissions_removed"?: ReadonlyArray - readonly "description"?: string - readonly "metadata"?: {} - } - } - readonly "role.deleted"?: { readonly "id"?: string } - readonly "role.assignment.created"?: { - readonly "id"?: string - readonly "principal_id"?: string - readonly "principal_type"?: string - readonly "resource_id"?: string - readonly "resource_type"?: string - } - readonly "role.assignment.deleted"?: { - readonly "id"?: string - readonly "principal_id"?: string - readonly "principal_type"?: string - readonly "resource_id"?: string - readonly "resource_type"?: string - } - readonly "service_account.created"?: { readonly "id"?: string; readonly "data"?: { readonly "role"?: string } } - readonly "service_account.updated"?: { - readonly "id"?: string - readonly "changes_requested"?: { readonly "role"?: string } - } - readonly "service_account.deleted"?: { readonly "id"?: string } - readonly "user.added"?: { readonly "id"?: string; readonly "data"?: { readonly "role"?: string } } - readonly "user.updated"?: { readonly "id"?: string; readonly "changes_requested"?: { readonly "role"?: string } } - readonly "user.deleted"?: { readonly "id"?: string } - readonly "certificate.created"?: { readonly "id"?: string; readonly "name"?: string } - readonly "certificate.updated"?: { readonly "id"?: string; readonly "name"?: string } - readonly "certificate.deleted"?: { readonly "id"?: string; readonly "name"?: string; readonly "certificate"?: string } - readonly "certificates.activated"?: { - readonly "certificates"?: ReadonlyArray<{ readonly "id"?: string; readonly "name"?: string }> - } - readonly "certificates.deactivated"?: { - readonly "certificates"?: ReadonlyArray<{ readonly "id"?: string; readonly "name"?: string }> - } +export const ListFineTuningCheckpointPermissionResponse = Schema.Struct({ + "data": Schema.Array(FineTuningCheckpointPermission), + "object": Schema.Literal("list"), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ListFineTuningCheckpointPermissionResponse" }) +export type FineTuneSupervisedMethod = { readonly "hyperparameters"?: FineTuneSupervisedHyperparameters } +export const FineTuneSupervisedMethod = Schema.Struct({ + "hyperparameters": Schema.optionalKey(FineTuneSupervisedHyperparameters) +}).annotate({ + "description": "Configuration for the supervised fine-tuning method.", + "identifier": "FineTuneSupervisedMethod" +}) +export type FineTuneDPOMethod = { readonly "hyperparameters"?: FineTuneDPOHyperparameters } +export const FineTuneDPOMethod = Schema.Struct({ "hyperparameters": Schema.optionalKey(FineTuneDPOHyperparameters) }) + .annotate({ "description": "Configuration for the DPO fine-tuning method.", "identifier": "FineTuneDPOMethod" }) +export type ListFineTuningJobCheckpointsResponse = { + readonly "data": ReadonlyArray + readonly "object": "list" + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean } -export const AuditLog = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The ID of this log." }), - "type": AuditLogEventType, - "effective_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of the event.", - "format": "unixtime" - }).check(Schema.isInt()), - "project": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The project title." })) - }).annotate({ +export const ListFineTuningJobCheckpointsResponse = Schema.Struct({ + "data": Schema.Array(FineTuningJobCheckpoint), + "object": Schema.Literal("list"), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ListFineTuningJobCheckpointsResponse" }) +export type ListFineTuningJobEventsResponse = { + readonly "data": ReadonlyArray + readonly "object": "list" + readonly "has_more": boolean +} +export const ListFineTuningJobEventsResponse = Schema.Struct({ + "data": Schema.Array(FineTuningJobEvent), + "object": Schema.Literal("list"), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ListFineTuningJobEventsResponse" }) +export type EditImageBodyJsonParam = { + readonly "model"?: + | string + | "gpt-image-1.5" + | "gpt-image-2" + | "gpt-image-2-2026-04-21" + | "gpt-image-2.5-sunburst" + | "gpt-image-2.5-sunburst-2026-09-08" + | "gpt-image-2.5-flare" + | "gpt-image-2.5-flare-2026-09-08" + | "gpt-image-1" + | "gpt-image-1-mini" + | "chatgpt-image-latest" + | null + readonly "images": ReadonlyArray + readonly "mask"?: ImageRefParam + readonly "prompt": string + readonly "n"?: number | null + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" | null + readonly "input_fidelity"?: "high" | "low" | null + readonly "size"?: string | "auto" | "1024x1024" | "1536x1024" | "1024x1536" | null + readonly "user"?: string + readonly "output_format"?: "png" | "jpeg" | "webp" | null + readonly "output_compression"?: number | null + readonly "moderation"?: "low" | "auto" | null + readonly "background"?: "transparent" | "opaque" | "auto" | null + readonly "stream"?: boolean | null + readonly "partial_images"?: PartialImages +} +export const EditImageBodyJsonParam = Schema.Struct({ + "model": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-image-1.5", + "gpt-image-2", + "gpt-image-2-2026-04-21", + "gpt-image-2.5-sunburst", + "gpt-image-2.5-sunburst-2026-09-08", + "gpt-image-2.5-flare", + "gpt-image-2.5-flare-2026-09-08", + "gpt-image-1", + "gpt-image-1-mini", + "chatgpt-image-latest" + ]), + Schema.Null + ]).annotate({ "description": - "The project that the action was scoped to. Absent for actions not scoped to projects. Note that any admin actions taken via Admin API keys are associated with the default project." + "The GPT image model to use for image editing, including `gpt-image-2`, its dated snapshot `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and `gpt-image-2.5-flare-2026-09-08`. Defaults to `gpt-image-2.5-sunburst`." }) ), - "actor": Schema.optionalKey(Schema.Union([AuditLogActor, Schema.Null])), - "api_key.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The tracking ID of the API key." })), - "data": Schema.optionalKey( - Schema.Struct({ - "scopes": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": "A list of scopes allowed for the API key, e.g. `[\"api.model.request\"]`" - }) - ) - }).annotate({ "description": "The payload used to create the API key." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "images": Schema.Array(ImageRefParam).annotate({ + "description": "Input image references to edit.\nFor GPT image models, you can provide up to 16 images.\n" + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(16).annotate({ "expected": "a value with a length of at most 16" }) ), - "api_key.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The tracking ID of the API key." })), - "changes_requested": Schema.optionalKey( - Schema.Struct({ - "scopes": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": "A list of scopes allowed for the API key, e.g. `[\"api.model.request\"]`" - }) - ) - }).annotate({ "description": "The payload used to update the API key." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "mask": Schema.optionalKey(ImageRefParam), + "prompt": Schema.String.annotate({ "description": "A text description of the desired image edit." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(32000).annotate({ "expected": "a string with at most 32000 code points" })), + "n": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(10).annotate({ "expected": "a value less than or equal to 10" })), + Schema.Null + ]).annotate({ "description": "The number of edited images to generate." }) ), - "api_key.deleted": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The tracking ID of the API key." })) - }).annotate({ "description": "The details for events with this `type`." }) + "quality": Schema.optionalKey( + Schema.Union([Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]), Schema.Null]).annotate({ + "description": + "Output quality for GPT image models. The GPT image models support `low`, `medium`,\nand `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their\n`2026-09-08` snapshots, also support `xhigh` and `max`. Defaults to `auto`.\n" + }) ), - "checkpoint.permission.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the checkpoint permission." })), - "data": Schema.optionalKey( - Schema.Struct({ - "project_id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The ID of the project that the checkpoint permission was created for." - }) - ), - "fine_tuned_model_checkpoint": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the fine-tuned model checkpoint." }) - ) - }).annotate({ "description": "The payload used to create the checkpoint permission." }) - ) - }).annotate({ - "description": "The project and fine-tuned model checkpoint that the checkpoint permission was created for." + "input_fidelity": Schema.optionalKey( + Schema.Union([Schema.Literals(["high", "low"]), Schema.Null]).annotate({ + "description": + "Control how much effort the model will exert to match the style and features, especially facial features, of input images. Supports `high` and `low` on `gpt-image-1` and `gpt-image-1.5`; `gpt-image-1-mini` supports only `low`. For `gpt-image-2`, omit this parameter. Defaults to `low` on supported models." }) ), - "checkpoint.permission.deleted": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the checkpoint permission." })) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "external_key.registered": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the external key configuration." })), - "data": Schema.optionalKey( - Schema.Struct({}).annotate({ "description": "The configuration for the external key." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "external_key.removed": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the external key configuration." })) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "group.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the group." })), - "data": Schema.optionalKey( - Schema.Struct({ - "group_name": Schema.optionalKey(Schema.String.annotate({ "description": "The group name." })) - }).annotate({ "description": "Information about the created group." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "group.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the group." })), - "changes_requested": Schema.optionalKey( - Schema.Struct({ - "group_name": Schema.optionalKey(Schema.String.annotate({ "description": "The updated group name." })) - }).annotate({ "description": "The payload used to update the group." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "size": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Literals(["auto", "1024x1024", "1536x1024", "1024x1536"]), Schema.Null]) + .annotate({ + "description": + "The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the maximum supported resolution is `3840x2160`. The requested size must also satisfy the model's current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is supported for models that allow automatic sizing." + }) ), - "group.deleted": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the group." })) }) - .annotate({ "description": "The details for events with this `type`." }) + "user": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A unique identifier representing your end-user, which can help OpenAI\nmonitor and detect abuse.\n" + }) ), - "scim.enabled": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the SCIM was enabled for." })) - }).annotate({ "description": "The details for events with this `type`." }) + "output_format": Schema.optionalKey( + Schema.Union([Schema.Literals(["png", "jpeg", "webp"]), Schema.Null]).annotate({ + "description": "Output image format. Supported for GPT image models." + }) ), - "scim.disabled": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the SCIM was disabled for." })) - }).annotate({ "description": "The details for events with this `type`." }) + "output_compression": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })), + Schema.Null + ]).annotate({ "description": "Compression level for `jpeg` or `webp` output." }) ), - "invite.sent": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the invite." })), - "data": Schema.optionalKey( - Schema.Struct({ - "email": Schema.optionalKey( - Schema.String.annotate({ "description": "The email invited to the organization." }) - ), - "role": Schema.optionalKey( - Schema.String.annotate({ - "description": "The role the email was invited to be. Is either `owner` or `member`." - }) - ) - }).annotate({ "description": "The payload used to create the invite." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "moderation": Schema.optionalKey( + Schema.Union([Schema.Literals(["low", "auto"]), Schema.Null]).annotate({ + "description": "Moderation level for GPT image models." + }) ), - "invite.accepted": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the invite." })) }) - .annotate({ "description": "The details for events with this `type`." }) + "background": Schema.optionalKey( + Schema.Union([Schema.Literals(["transparent", "opaque", "auto"]), Schema.Null]).annotate({ + "description": + "Set the background of the generated image output. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08` snapshots, support `opaque` and `transparent` backgrounds. Transparent backgrounds are available for supported GPT Image models. For `gpt-image-2` and `gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`, set the output format to `png` or `webp`." + }) ), - "invite.deleted": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the invite." })) }) - .annotate({ "description": "The details for events with this `type`." }) + "stream": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ "description": "Stream partial image results as events." }) ), - "ip_allowlist.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." })), - "name": Schema.optionalKey( - Schema.String.annotate({ "description": "The name of the IP allowlist configuration." }) - ), - "allowed_ips": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": "The IP addresses or CIDR ranges included in the configuration." - }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "partial_images": Schema.optionalKey(PartialImages) +}).annotate({ + "description": + "JSON request body for image edits.\n\nUse `images` (array of `ImageRefParam`) instead of multipart `image` uploads.\nYou can reference images via external URLs, data URLs, or uploaded file IDs.\nJSON edits support GPT image models.\n", + "identifier": "EditImageBodyJsonParam" +}) +export type CreateImageEditRequestMultipart = { + readonly "image": __ClientMultipartFile | ReadonlyArray<__ClientMultipartFile> + readonly "prompt": string + readonly "mask"?: __ClientMultipartFile + readonly "background"?: "transparent" | "opaque" | "auto" | null + readonly "model": + | string + | "gpt-image-1.5" + | "gpt-image-2" + | "gpt-image-2-2026-04-21" + | "gpt-image-2.5-sunburst" + | "gpt-image-2.5-sunburst-2026-09-08" + | "gpt-image-2.5-flare" + | "gpt-image-2.5-flare-2026-09-08" + | "gpt-image-1" + | "gpt-image-1-mini" + | "chatgpt-image-latest" + | "dall-e-2" + readonly "n"?: number | null + readonly "size"?: string | "1024x1024" | "1536x1024" | "1024x1536" | "auto" | "256x256" | "512x512" | null + readonly "response_format"?: "url" | "b64_json" | null + readonly "output_format"?: "png" | "jpeg" | "webp" | null + readonly "output_compression"?: number | null + readonly "user"?: string + readonly "input_fidelity"?: InputFidelity | null + readonly "stream"?: boolean | null + readonly "partial_images"?: PartialImages + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" | "standard" | null +} +export const CreateImageEditRequestMultipart = Schema.Struct({ + "image": Schema.Union([ + __ClientMultipartFile, + Schema.Array(__ClientMultipartFile).check( + Schema.isMaxLength(16).annotate({ "expected": "a value with a length of at most 16" }) + ) + ]).annotate({ + "description": + "The image(s) to edit. Must be a supported image file or an array of images.\n\nFor the GPT image models (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`,\n`gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`,\n`gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and\n`gpt-image-2.5-flare-2026-09-08`), each image should be a `png`, `webp`, or `jpg`\nfile less than 50MB. You can provide up to 16 images. `chatgpt-image-latest`\nfollows the same input constraints as GPT image models.\n" + }), + "prompt": Schema.String.annotate({ + "description": + "A text description of the desired image(s). The maximum length is 32000 characters for the GPT image models." + }), + "mask": Schema.optionalKey(__ClientMultipartFile), + "background": Schema.optionalKey( + Schema.Union([Schema.Literals(["transparent", "opaque", "auto"]), Schema.Null]).annotate({ + "description": + "Set the background of the generated image(s). This parameter is only supported for\nthe GPT image models. Must be one of `transparent`, `opaque`, or `auto` (default\nvalue). When `auto` is used, the model will automatically determine the best\nbackground for the image.\n\n`gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08`\nsnapshots, support `opaque` and `transparent` backgrounds. Transparent backgrounds\nare available for supported GPT Image models. For `gpt-image-2` and\n`gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`,\nset the output format to `png` or `webp`.\n" + }) ), - "ip_allowlist.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." })), - "allowed_ips": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": "The updated set of IP addresses or CIDR ranges in the configuration." - }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "model": Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-image-1.5", + "gpt-image-2", + "gpt-image-2-2026-04-21", + "gpt-image-2.5-sunburst", + "gpt-image-2.5-sunburst-2026-09-08", + "gpt-image-2.5-flare", + "gpt-image-2.5-flare-2026-09-08", + "gpt-image-1", + "gpt-image-1-mini", + "chatgpt-image-latest", + "dall-e-2" + ]) + ]).annotate({ + "description": + "The GPT image model to use for image editing (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, `gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`)." + }), + "n": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(10).annotate({ "expected": "a value less than or equal to 10" })), + Schema.Null + ]).annotate({ "description": "The number of images to generate. Must be between 1 and 10." }) ), - "ip_allowlist.deleted": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." })), - "name": Schema.optionalKey( - Schema.String.annotate({ "description": "The name of the IP allowlist configuration." }) - ), - "allowed_ips": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": "The IP addresses or CIDR ranges that were in the configuration." - }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "size": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals(["1024x1024", "1536x1024", "1024x1536", "auto", "256x256", "512x512"]), + Schema.Null + ]).annotate({ + "description": + "The size of the generated images. Defaults to `auto`. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the maximum supported resolution is `3840x2160`. The requested size must also satisfy the model's current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is supported for models that allow automatic sizing." + }) ), - "ip_allowlist.config.activated": Schema.optionalKey( - Schema.Struct({ - "configs": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." }) - ), - "name": Schema.optionalKey( - Schema.String.annotate({ "description": "The name of the IP allowlist configuration." }) - ) - }) - ).annotate({ "description": "The configurations that were activated." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "response_format": Schema.optionalKey( + Schema.Union([Schema.Literals(["url", "b64_json"]), Schema.Null]).annotate({ + "description": + "Legacy response format parameter for retired image models. Unsupported for GPT image models, which always return base64-encoded images." + }) ), - "ip_allowlist.config.deactivated": Schema.optionalKey( - Schema.Struct({ - "configs": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." }) - ), - "name": Schema.optionalKey( - Schema.String.annotate({ "description": "The name of the IP allowlist configuration." }) - ) - }) - ).annotate({ "description": "The configurations that were deactivated." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "output_format": Schema.optionalKey( + Schema.Union([Schema.Literals(["png", "jpeg", "webp"]), Schema.Null]).annotate({ + "description": + "The format in which the generated images are returned. This parameter is\nonly supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`.\nThe default value is `png`.\n" + }) ), - "login.succeeded": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": "This event has no additional fields beyond the standard audit log attributes." + "output_compression": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": + "The compression level (0-100%) for the generated images. This parameter\nis only supported for the GPT image models with the `webp` or `jpeg` output\nformats, and defaults to 100.\n" }) ), - "login.failed": Schema.optionalKey( - Schema.Struct({ - "error_code": Schema.optionalKey(Schema.String.annotate({ "description": "The error code of the failure." })), - "error_message": Schema.optionalKey( - Schema.String.annotate({ "description": "The error message of the failure." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "user": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }) ), - "logout.succeeded": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": "This event has no additional fields beyond the standard audit log attributes." + "input_fidelity": Schema.optionalKey(Schema.Union([InputFidelity, Schema.Null])), + "stream": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": + "Edit the image in streaming mode. Defaults to `false`. See the\n[Image generation guide](https://developers.openai.com/api/docs/guides/image-generation) for more information.\n" }) ), - "logout.failed": Schema.optionalKey( - Schema.Struct({ - "error_code": Schema.optionalKey(Schema.String.annotate({ "description": "The error code of the failure." })), - "error_message": Schema.optionalKey( - Schema.String.annotate({ "description": "The error message of the failure." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "organization.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The organization ID." })), - "changes_requested": Schema.optionalKey( - Schema.Struct({ - "title": Schema.optionalKey(Schema.String.annotate({ "description": "The organization title." })), - "description": Schema.optionalKey(Schema.String.annotate({ "description": "The organization description." })), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The organization name." })), - "threads_ui_visibility": Schema.optionalKey( - Schema.String.annotate({ - "description": - "Visibility of the threads page which shows messages created with the Assistants API and Playground. One of `ANY_ROLE`, `OWNERS`, or `NONE`." - }) - ), - "usage_dashboard_visibility": Schema.optionalKey( - Schema.String.annotate({ - "description": - "Visibility of the usage dashboard which shows activity and costs for your organization. One of `ANY_ROLE` or `OWNERS`." - }) - ), - "api_call_logging": Schema.optionalKey( - Schema.String.annotate({ - "description": - "How your organization logs data from supported API calls. One of `disabled`, `enabled_per_call`, `enabled_for_all_projects`, or `enabled_for_selected_projects`" - }) - ), - "api_call_logging_project_ids": Schema.optionalKey( - Schema.String.annotate({ - "description": "The list of project ids if api_call_logging is set to `enabled_for_selected_projects`" - }) - ) - }).annotate({ "description": "The payload used to update the organization settings." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "project.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), - "data": Schema.optionalKey( - Schema.Struct({ - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The project name." })), - "title": Schema.optionalKey( - Schema.String.annotate({ "description": "The title of the project as seen on the dashboard." }) - ) - }).annotate({ "description": "The payload used to create the project." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "partial_images": Schema.optionalKey(PartialImages), + "quality": Schema.optionalKey( + Schema.Union([Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto", "standard"]), Schema.Null]) + .annotate({ + "description": + "The quality of the image that will be generated for GPT image models. The GPT image models support `low`, `medium`, and `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08` snapshots, also support `xhigh` and `max`. Defaults to `auto`.\n" + }) + ) +}).annotate({ "identifier": "CreateImageEditRequestMultipart" }) +export type CreateImageRequest = { + readonly "prompt": string + readonly "model": + | string + | "gpt-image-1.5" + | "gpt-image-2" + | "gpt-image-2-2026-04-21" + | "gpt-image-2.5-sunburst" + | "gpt-image-2.5-sunburst-2026-09-08" + | "gpt-image-2.5-flare" + | "gpt-image-2.5-flare-2026-09-08" + | "gpt-image-1" + | "gpt-image-1-mini" + | "chatgpt-image-latest" + | "dall-e-2" + | "dall-e-3" + readonly "n"?: number | null + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" | "standard" | "hd" | null + readonly "response_format"?: "url" | "b64_json" | null + readonly "output_format"?: "png" | "jpeg" | "webp" | null + readonly "output_compression"?: number | null + readonly "stream"?: boolean | null + readonly "partial_images"?: PartialImages + readonly "size"?: + | string + | "auto" + | "1024x1024" + | "1536x1024" + | "1024x1536" + | "256x256" + | "512x512" + | "1792x1024" + | "1024x1792" + | null + readonly "moderation"?: "low" | "auto" | null + readonly "background"?: "transparent" | "opaque" | "auto" | null + readonly "style"?: "vivid" | "natural" | null + readonly "user"?: string +} +export const CreateImageRequest = Schema.Struct({ + "prompt": Schema.String.annotate({ + "description": "A text description of the desired image(s). The maximum length is 32000 characters." + }), + "model": Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-image-1.5", + "gpt-image-2", + "gpt-image-2-2026-04-21", + "gpt-image-2.5-sunburst", + "gpt-image-2.5-sunburst-2026-09-08", + "gpt-image-2.5-flare", + "gpt-image-2.5-flare-2026-09-08", + "gpt-image-1", + "gpt-image-1-mini", + "chatgpt-image-latest", + "dall-e-2", + "dall-e-3" + ]) + ]).annotate({ + "description": + "The GPT image model to use for image generation. Specify a model explicitly. Supported models include `gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, `gpt-image-2.5-flare-2026-09-08`, and `chatgpt-image-latest`." + }), + "n": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(10).annotate({ "expected": "a value less than or equal to 10" })), + Schema.Null + ]).annotate({ "description": "The number of images to generate. Must be between 1 and 10." }) ), - "project.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), - "changes_requested": Schema.optionalKey( - Schema.Struct({ - "title": Schema.optionalKey( - Schema.String.annotate({ "description": "The title of the project as seen on the dashboard." }) - ) - }).annotate({ "description": "The payload used to update the project." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "quality": Schema.optionalKey( + Schema.Union([Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto", "standard", "hd"]), Schema.Null]) + .annotate({ + "description": + "The quality of the image that will be generated.\n\n- `auto` (default value) will automatically select the best quality for the given\n model.\n- `high`, `medium` and `low` are supported for the GPT image models.\n- `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08`\n snapshots, also support `xhigh` and `max`.\n" + }) ), - "project.archived": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })) }).annotate({ - "description": "The details for events with this `type`." + "response_format": Schema.optionalKey( + Schema.Union([Schema.Literals(["url", "b64_json"]), Schema.Null]).annotate({ + "description": + "Legacy response format parameter for retired image models. Unsupported for GPT image models, which always return base64-encoded images." }) ), - "project.deleted": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })) }).annotate({ - "description": "The details for events with this `type`." + "output_format": Schema.optionalKey( + Schema.Union([Schema.Literals(["png", "jpeg", "webp"]), Schema.Null]).annotate({ + "description": + "The format in which the generated images are returned. This parameter is only supported for the GPT image models. Must be one of `png`, `jpeg`, or `webp`." }) ), - "rate_limit.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The rate limit ID" })), - "changes_requested": Schema.optionalKey( - Schema.Struct({ - "max_requests_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum requests per minute." }).check(Schema.isInt()) - ), - "max_tokens_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum tokens per minute." }).check(Schema.isInt()) - ), - "max_images_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum images per minute. Only relevant for certain models." - }).check(Schema.isInt()) - ), - "max_audio_megabytes_per_1_minute": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum audio megabytes per minute. Only relevant for certain models." - }).check(Schema.isInt()) - ), - "max_requests_per_1_day": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum requests per day. Only relevant for certain models." }) - .check(Schema.isInt()) - ), - "batch_1_day_max_input_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The maximum batch input tokens per day. Only relevant for certain models." - }).check(Schema.isInt()) - ) - }).annotate({ "description": "The payload used to update the rate limits." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "output_compression": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": + "The compression level (0-100%) for the generated images. This parameter is only supported for the GPT image models with the `webp` or `jpeg` output formats, and defaults to 100." + }) ), - "rate_limit.deleted": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The rate limit ID" })) }) - .annotate({ "description": "The details for events with this `type`." }) + "stream": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": + "Generate the image in streaming mode. Defaults to `false`. See the\n[Image generation guide](https://developers.openai.com/api/docs/guides/image-generation) for more information.\nThis parameter is only supported for the GPT image models.\n" + }) ), - "role.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The role ID." })), - "role_name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the role." })), - "permissions": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ "description": "The permissions granted by the role." }) - ), - "resource_type": Schema.optionalKey( - Schema.String.annotate({ "description": "The type of resource the role belongs to." }) - ), - "resource_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The resource the role is scoped to." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "partial_images": Schema.optionalKey(PartialImages), + "size": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals(["auto", "1024x1024", "1536x1024", "1024x1536", "256x256", "512x512", "1792x1024", "1024x1792"]), + Schema.Null + ]).annotate({ + "description": + "The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the maximum supported resolution is `3840x2160`. The requested size must also satisfy the model's current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is supported for models that allow automatic sizing." + }) ), - "role.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The role ID." })), - "changes_requested": Schema.optionalKey( - Schema.Struct({ - "role_name": Schema.optionalKey( - Schema.String.annotate({ "description": "The updated role name, when provided." }) - ), - "resource_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The resource the role is scoped to." }) - ), - "resource_type": Schema.optionalKey( - Schema.String.annotate({ "description": "The type of resource the role belongs to." }) - ), - "permissions_added": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ "description": "The permissions added to the role." }) - ), - "permissions_removed": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ "description": "The permissions removed from the role." }) - ), - "description": Schema.optionalKey( - Schema.String.annotate({ "description": "The updated role description, when provided." }) - ), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ "description": "Additional metadata stored on the role." }) - ) - }).annotate({ "description": "The payload used to update the role." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "moderation": Schema.optionalKey( + Schema.Union([Schema.Literals(["low", "auto"]), Schema.Null]).annotate({ + "description": + "Control the content-moderation level for images generated by the GPT image models. Must be either `low` for less restrictive filtering or `auto` (default value)." + }) ), - "role.deleted": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The role ID." })) }).annotate({ - "description": "The details for events with this `type`." + "background": Schema.optionalKey( + Schema.Union([Schema.Literals(["transparent", "opaque", "auto"]), Schema.Null]).annotate({ + "description": + "Set the background of the generated image(s). This parameter is only supported for\nthe GPT image models. Must be one of `transparent`, `opaque`, or `auto` (default\nvalue). When `auto` is used, the model will automatically determine the best\nbackground for the image.\n\n`gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08`\nsnapshots, support `opaque` and `transparent` backgrounds. Transparent backgrounds\nare available for supported GPT Image models. For `gpt-image-2` and\n`gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`,\nset the output format to `png` or `webp`.\n" }) ), - "role.assignment.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The identifier of the role assignment." })), - "principal_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The principal (user or group) that received the role." }) - ), - "principal_type": Schema.optionalKey( - Schema.String.annotate({ "description": "The type of principal (user or group) that received the role." }) - ), - "resource_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The resource the role assignment is scoped to." }) - ), - "resource_type": Schema.optionalKey( - Schema.String.annotate({ "description": "The type of resource the role assignment is scoped to." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) + "style": Schema.optionalKey( + Schema.Union([Schema.Literals(["vivid", "natural"]), Schema.Null]).annotate({ + "description": + "Legacy style parameter for retired image models. Unsupported for GPT image models; describe the desired style in the prompt instead." + }) ), - "role.assignment.deleted": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The identifier of the role assignment." })), - "principal_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The principal (user or group) that had the role removed." }) - ), - "principal_type": Schema.optionalKey( - Schema.String.annotate({ "description": "The type of principal (user or group) that had the role removed." }) - ), - "resource_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The resource the role assignment was scoped to." }) - ), - "resource_type": Schema.optionalKey( - Schema.String.annotate({ "description": "The type of resource the role assignment was scoped to." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "service_account.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The service account ID." })), - "data": Schema.optionalKey( - Schema.Struct({ - "role": Schema.optionalKey( - Schema.String.annotate({ "description": "The role of the service account. Is either `owner` or `member`." }) - ) - }).annotate({ "description": "The payload used to create the service account." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "service_account.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The service account ID." })), - "changes_requested": Schema.optionalKey( - Schema.Struct({ - "role": Schema.optionalKey( - Schema.String.annotate({ "description": "The role of the service account. Is either `owner` or `member`." }) - ) - }).annotate({ "description": "The payload used to updated the service account." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "service_account.deleted": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The service account ID." })) }) - .annotate({ "description": "The details for events with this `type`." }) - ), - "user.added": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The user ID." })), - "data": Schema.optionalKey( - Schema.Struct({ - "role": Schema.optionalKey( - Schema.String.annotate({ "description": "The role of the user. Is either `owner` or `member`." }) - ) - }).annotate({ "description": "The payload used to add the user to the project." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "user.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), - "changes_requested": Schema.optionalKey( - Schema.Struct({ - "role": Schema.optionalKey( - Schema.String.annotate({ "description": "The role of the user. Is either `owner` or `member`." }) - ) - }).annotate({ "description": "The payload used to update the user." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "user.deleted": Schema.optionalKey( - Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The user ID." })) }).annotate({ - "description": "The details for events with this `type`." - }) - ), - "certificate.created": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "certificate.updated": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "certificate.deleted": Schema.optionalKey( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })), - "certificate": Schema.optionalKey( - Schema.String.annotate({ "description": "The certificate content in PEM format." }) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "certificates.activated": Schema.optionalKey( - Schema.Struct({ - "certificates": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })) - }) - ) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ), - "certificates.deactivated": Schema.optionalKey( - Schema.Struct({ - "certificates": Schema.optionalKey( - Schema.Array( - Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })) - }) - ) - ) - }).annotate({ "description": "The details for events with this `type`." }) - ) -}).annotate({ "description": "A log of a user action or configuration change within this organization." }) -export type CreateChatCompletionResponse = { - readonly "id": string - readonly "choices": ReadonlyArray< - { - readonly "finish_reason": "stop" | "length" | "tool_calls" | "content_filter" | "function_call" - readonly "index": number - readonly "message": ChatCompletionResponseMessage - readonly "logprobs": { - readonly "content": ReadonlyArray | null - readonly "refusal": ReadonlyArray | null - } | null - } - > - readonly "created": number - readonly "model": string - readonly "service_tier"?: ServiceTier - readonly "system_fingerprint"?: string - readonly "object": "chat.completion" - readonly "usage"?: CompletionUsage -} -export const CreateChatCompletionResponse = Schema.Struct({ - "id": Schema.String.annotate({ "description": "A unique identifier for the chat completion." }), - "choices": Schema.Array(Schema.Struct({ - "finish_reason": Schema.Literals(["stop", "length", "tool_calls", "content_filter", "function_call"]).annotate({ - "description": - "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\n`content_filter` if content was omitted due to a flag from our content filters,\n`tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function.\n" - }), - "index": Schema.Number.annotate({ "description": "The index of the choice in the list of choices." }).check( - Schema.isInt() - ), - "message": ChatCompletionResponseMessage, - "logprobs": Schema.Union([ - Schema.Struct({ - "content": Schema.Union([ - Schema.Array(ChatCompletionTokenLogprob).annotate({ - "description": "A list of message content tokens with log probability information." - }), - Schema.Null - ]), - "refusal": Schema.Union([ - Schema.Array(ChatCompletionTokenLogprob).annotate({ - "description": "A list of message refusal tokens with log probability information." - }), - Schema.Null - ]) - }).annotate({ "description": "Log probability information for the choice." }), - Schema.Null - ]) - })).annotate({ "description": "A list of chat completion choices. Can be more than one if `n` is greater than 1." }), - "created": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) of when the chat completion was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "model": Schema.String.annotate({ "description": "The model used for the chat completion." }), - "service_tier": Schema.optionalKey(ServiceTier), - "system_fingerprint": Schema.optionalKey( + "user": Schema.optionalKey( Schema.String.annotate({ "description": - "This fingerprint represents the backend configuration that the model runs with.\n\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" + "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" }) - ), - "object": Schema.Literal("chat.completion").annotate({ - "description": "The object type, which is always `chat.completion`." - }), - "usage": Schema.optionalKey(CompletionUsage) -}).annotate({ "description": "Represents a chat completion response returned by model, based on the provided input." }) -export type ChatCompletionRequestMessage = - | ChatCompletionRequestDeveloperMessage - | ChatCompletionRequestSystemMessage - | ChatCompletionRequestUserMessage - | ChatCompletionRequestAssistantMessage - | ChatCompletionRequestToolMessage - | ChatCompletionRequestFunctionMessage -export const ChatCompletionRequestMessage = Schema.Union([ - ChatCompletionRequestDeveloperMessage, - ChatCompletionRequestSystemMessage, - ChatCompletionRequestUserMessage, - ChatCompletionRequestAssistantMessage, - ChatCompletionRequestToolMessage, - ChatCompletionRequestFunctionMessage -], { mode: "oneOf" }) -export type RunStepObject = { - readonly "id": string - readonly "object": "thread.run.step" + ) +}).annotate({ "identifier": "CreateImageRequest" }) +export type ImageGenUsage = { + readonly "input_tokens": number + readonly "total_tokens": number + readonly "output_tokens": number + readonly "output_tokens_details"?: ImageGenOutputTokensDetails + readonly "input_tokens_details": ImageGenInputUsageDetails +} +export const ImageGenUsage = Schema.Struct({ + "input_tokens": Schema.Number.annotate({ + "description": "The number of tokens (images and text) in the input prompt." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "total_tokens": Schema.Number.annotate({ + "description": "The total number of tokens (images and text) used for the image generation." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "output_tokens": Schema.Number.annotate({ "description": "The number of output tokens generated by the model." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "output_tokens_details": Schema.optionalKey(ImageGenOutputTokensDetails), + "input_tokens_details": ImageGenInputUsageDetails +}).annotate({ + "title": "Image generation usage", + "description": "For `gpt-image-1` only, the token usage information for the image generation.", + "identifier": "ImageGenUsage" +}) +export type ImageEditCompletedEvent = { + readonly "type": "image_edit.completed" + readonly "b64_json": string readonly "created_at": number - readonly "assistant_id": string - readonly "thread_id": string - readonly "run_id": string - readonly "type": "message_creation" | "tool_calls" - readonly "status": "in_progress" | "cancelled" | "failed" | "completed" | "expired" - readonly "step_details": { - readonly "type": "message_creation" - readonly "message_creation": { readonly "message_id": string } - } | { - readonly "type": "tool_calls" - readonly "tool_calls": ReadonlyArray< - | RunStepDetailsToolCallsCodeObject - | RunStepDetailsToolCallsFileSearchObject - | RunStepDetailsToolCallsFunctionObject - > - } - readonly "last_error": { readonly "code": "server_error" | "rate_limit_exceeded"; readonly "message": string } | null - readonly "expired_at": number | null - readonly "cancelled_at": number | null - readonly "failed_at": number | null - readonly "completed_at": number | null - readonly "metadata": Metadata - readonly "usage": RunStepCompletionUsage + readonly "size": string | "1024x1024" | "1024x1536" | "1536x1024" | "auto" + readonly "quality": "low" | "medium" | "high" | "xhigh" | "max" | "auto" + readonly "background": "transparent" | "opaque" | "auto" + readonly "output_format": "png" | "webp" | "jpeg" + readonly "usage": ImagesUsage } -export const RunStepObject = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The identifier of the run step, which can be referenced in API endpoints." +export const ImageEditCompletedEvent = Schema.Struct({ + "type": Schema.Literal("image_edit.completed").annotate({ + "description": "The type of the event. Always `image_edit.completed`.\n" }), - "object": Schema.Literal("thread.run.step").annotate({ - "description": "The object type, which is always `thread.run.step`." + "b64_json": Schema.String.annotate({ + "description": "Base64-encoded final edited image data, suitable for rendering as an image.\n" }), "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the run step was created.", + "description": "The Unix timestamp when the event was created.\n", "format": "unixtime" - }).check(Schema.isInt()), - "assistant_id": Schema.String.annotate({ - "description": "The ID of the [assistant](/docs/api-reference/assistants) associated with the run step." - }), - "thread_id": Schema.String.annotate({ - "description": "The ID of the [thread](/docs/api-reference/threads) that was run." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "size": Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." }), - "run_id": Schema.String.annotate({ - "description": "The ID of the [run](/docs/api-reference/runs) that this run step is a part of." + "quality": Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": "The quality setting for the edited image.\n" }), - "type": Schema.Literals(["message_creation", "tool_calls"]).annotate({ - "description": "The type of run step, which can be either `message_creation` or `tool_calls`." + "background": Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "description": "The background setting for the edited image.\n" }), - "status": Schema.Literals(["in_progress", "cancelled", "failed", "completed", "expired"]).annotate({ - "description": - "The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, `completed`, or `expired`." + "output_format": Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "description": "The output format for the edited image.\n" }), - "step_details": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("message_creation").annotate({ "description": "Always `message_creation`." }), - "message_creation": Schema.Struct({ - "message_id": Schema.String.annotate({ - "description": "The ID of the message that was created by this run step." - }) - }) - }).annotate({ "title": "Message creation", "description": "The details of the run step." }), - Schema.Struct({ - "type": Schema.Literal("tool_calls").annotate({ "description": "Always `tool_calls`." }), - "tool_calls": Schema.Array( - Schema.Union([ - RunStepDetailsToolCallsCodeObject, - RunStepDetailsToolCallsFileSearchObject, - RunStepDetailsToolCallsFunctionObject - ], { mode: "oneOf" }) - ).annotate({ - "description": - "An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `file_search`, or `function`.\n" - }) - }).annotate({ "title": "Tool calls", "description": "The details of the run step." }) - ], { mode: "oneOf" }), - "last_error": Schema.Union([ - Schema.Struct({ - "code": Schema.Literals(["server_error", "rate_limit_exceeded"]).annotate({ - "description": "One of `server_error` or `rate_limit_exceeded`." - }), - "message": Schema.String.annotate({ "description": "A human-readable description of the error." }) - }).annotate({ - "description": "The last error associated with this run step. Will be `null` if there are no errors." - }), - Schema.Null - ]), - "expired_at": Schema.Union([ - Schema.Number.annotate({ - "description": - "The Unix timestamp (in seconds) for when the run step expired. A step is considered expired if the parent run is expired.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "cancelled_at": Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the run step was cancelled.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "failed_at": Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the run step failed.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "completed_at": Schema.Union([ - Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the run step completed.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "metadata": Metadata, - "usage": RunStepCompletionUsage -}).annotate({ "title": "Run steps", "description": "Represents a step in execution of a run.\n" }) -export type ListMessagesResponse = { - readonly "object": string - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean - readonly [x: string]: unknown + "usage": ImagesUsage +}).annotate({ + "description": "Emitted when image editing has completed and the final image is available.\n", + "identifier": "ImageEditCompletedEvent" +}) +export type ImageGenCompletedEvent = { + readonly "type": "image_generation.completed" + readonly "b64_json": string + readonly "created_at": number + readonly "size": string | "1024x1024" | "1024x1536" | "1536x1024" | "auto" + readonly "quality": "low" | "medium" | "high" | "xhigh" | "max" | "auto" + readonly "background": "transparent" | "opaque" | "auto" + readonly "output_format": "png" | "webp" | "jpeg" + readonly "usage": ImagesUsage } -export const ListMessagesResponse = Schema.StructWithRest( - Schema.Struct({ - "object": Schema.String, - "data": Schema.Array(MessageObject), - "first_id": Schema.String, - "last_id": Schema.String, - "has_more": Schema.Boolean +export const ImageGenCompletedEvent = Schema.Struct({ + "type": Schema.Literal("image_generation.completed").annotate({ + "description": "The type of the event. Always `image_generation.completed`.\n" }), - [Schema.Record(Schema.String, Schema.Json)] -) -export type MessageStreamEvent = - | { readonly "event": "thread.message.created"; readonly "data": MessageObject } - | { readonly "event": "thread.message.in_progress"; readonly "data": MessageObject } - | { readonly "event": "thread.message.delta"; readonly "data": MessageDeltaObject } - | { readonly "event": "thread.message.completed"; readonly "data": MessageObject } - | { readonly "event": "thread.message.incomplete"; readonly "data": MessageObject } -export const MessageStreamEvent = Schema.Union([ - Schema.Struct({ "event": Schema.Literal("thread.message.created"), "data": MessageObject }).annotate({ - "description": "Occurs when a [message](/docs/api-reference/messages/object) is created." + "b64_json": Schema.String.annotate({ + "description": "Base64-encoded image data, suitable for rendering as an image.\n" }), - Schema.Struct({ "event": Schema.Literal("thread.message.in_progress"), "data": MessageObject }).annotate({ - "description": "Occurs when a [message](/docs/api-reference/messages/object) moves to an `in_progress` state." + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp when the event was created.\n", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "size": Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." }), - Schema.Struct({ "event": Schema.Literal("thread.message.delta"), "data": MessageDeltaObject }).annotate({ - "description": "Occurs when parts of a [Message](/docs/api-reference/messages/object) are being streamed." + "quality": Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": "The quality setting for the generated image.\n" }), - Schema.Struct({ "event": Schema.Literal("thread.message.completed"), "data": MessageObject }).annotate({ - "description": "Occurs when a [message](/docs/api-reference/messages/object) is completed." + "background": Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "description": "The background setting for the generated image.\n" }), - Schema.Struct({ "event": Schema.Literal("thread.message.incomplete"), "data": MessageObject }).annotate({ - "description": "Occurs when a [message](/docs/api-reference/messages/object) ends before it is completed." - }) -], { mode: "oneOf" }) -export type RealtimeBetaResponse = { - readonly "id"?: string - readonly "object"?: "realtime.response" - readonly "status"?: "completed" | "cancelled" | "failed" | "incomplete" | "in_progress" - readonly "status_details"?: { - readonly "type"?: "completed" | "cancelled" | "failed" | "incomplete" - readonly "reason"?: "turn_detected" | "client_cancelled" | "max_output_tokens" | "content_filter" - readonly "error"?: { readonly "type"?: string; readonly "code"?: string } - } - readonly "output"?: ReadonlyArray - readonly "metadata"?: Metadata - readonly "usage"?: { - readonly "total_tokens"?: number - readonly "input_tokens"?: number - readonly "output_tokens"?: number - readonly "input_token_details"?: { - readonly "cached_tokens"?: number - readonly "text_tokens"?: number - readonly "image_tokens"?: number - readonly "audio_tokens"?: number - readonly "cached_tokens_details"?: { - readonly "text_tokens"?: number - readonly "image_tokens"?: number - readonly "audio_tokens"?: number - } - } - readonly "output_token_details"?: { readonly "text_tokens"?: number; readonly "audio_tokens"?: number } - } - readonly "conversation_id"?: string + "output_format": Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "description": "The output format for the generated image.\n" + }), + "usage": ImagesUsage +}).annotate({ + "description": "Emitted when image generation has completed and the final image is available.\n", + "identifier": "ImageGenCompletedEvent" +}) +export type LiveInitialSessionAudioOutputParam = { readonly "voice"?: | string | "alloy" | "ash" | "ballad" + | "beacon" + | "bossa" + | "brise" + | "cedar" + | "cinder" | "coral" + | "delta" | "echo" + | "flitz" + | "gleam" + | "harema" + | "juni" + | "marin" + | "meridian" + | "nira" + | "noeul" + | "nuri" + | "quartz" + | "ripple" | "sage" + | "shida" | "shimmer" + | "sillage" + | "stone" + | "tempo" | "verse" - | "marin" - | "cedar" - readonly "modalities"?: ReadonlyArray<"text" | "audio"> - readonly "output_audio_format"?: "pcm16" | "g711_ulaw" | "g711_alaw" - readonly "temperature"?: number - readonly "max_output_tokens"?: number | "inf" + | "vesper" + | "willow" + | LiveCustomVoiceParam } -export const RealtimeBetaResponse = Schema.Struct({ - "id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the response." })), - "object": Schema.optionalKey( - Schema.Literal("realtime.response").annotate({ "description": "The object type, must be `realtime.response`." }) - ), - "status": Schema.optionalKey( - Schema.Literals(["completed", "cancelled", "failed", "incomplete", "in_progress"]).annotate({ +export const LiveInitialSessionAudioOutputParam = Schema.Struct({ + "voice": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.String, + Schema.Literals([ + "alloy", + "ash", + "ballad", + "beacon", + "bossa", + "brise", + "cedar", + "cinder", + "coral", + "delta", + "echo", + "flitz", + "gleam", + "harema", + "juni", + "marin", + "meridian", + "nira", + "noeul", + "nuri", + "quartz", + "ripple", + "sage", + "shida", + "shimmer", + "sillage", + "stone", + "tempo", + "verse", + "vesper", + "willow" + ]) + ]), + LiveCustomVoiceParam + ], { mode: "oneOf" }).annotate({ "description": - "The final status of the response (`completed`, `cancelled`, `failed`, or \n`incomplete`, `in_progress`).\n" + "The voice used for Live speech, as a built-in voice name or a custom voice object containing its ID. Defaults to `marin` and cannot change after startup." }) + ) +}).annotate({ + "description": "Settings for speech generated by the Live model. Choose the voice before starting the session.", + "identifier": "LiveInitialSessionAudioOutputParam" +}) +export type LiveDelegationReasoningInputParam = { + readonly "effort"?: LiveReasoningEffort | null + readonly "summary"?: LiveReasoningSummary | null +} +export const LiveDelegationReasoningInputParam = Schema.Struct({ + "effort": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveReasoningEffort).annotate({ + "description": + "How much reasoning effort the delegated Responses model should use. Supported values depend on the backend model." + }), + Schema.Null + ]) ), - "status_details": Schema.optionalKey( - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literals(["completed", "cancelled", "failed", "incomplete"]).annotate({ - "description": - "The type of error that caused the response to fail, corresponding \nwith the `status` field (`completed`, `cancelled`, `incomplete`, \n`failed`).\n" - }) - ), - "reason": Schema.optionalKey( - Schema.Literals(["turn_detected", "client_cancelled", "max_output_tokens", "content_filter"]).annotate({ - "description": - "The reason the Response did not complete. For a `cancelled` Response, \none of `turn_detected` (the server VAD detected a new start of speech) \nor `client_cancelled` (the client sent a cancel event). For an \n`incomplete` Response, one of `max_output_tokens` or `content_filter` \n(the server-side safety filter activated and cut off the response).\n" - }) + "summary": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveReasoningSummary).annotate({ + "description": "The reasoning summary to request from the delegated Responses model, when supported." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "Reasoning options for Responses requests made on behalf of the Live session.", + "identifier": "LiveDelegationReasoningInputParam" +}) +export type LiveDelegationTextInputParam = { readonly "verbosity"?: LiveTextVerbosity | null } +export const LiveDelegationTextInputParam = Schema.Struct({ + "verbosity": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveTextVerbosity).annotate({ + "description": + "The amount of detail in text generated by the Responses backend. This does not configure the Live model’s spoken delivery." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "Text generation options for the Live session’s Responses backend.", + "identifier": "LiveDelegationTextInputParam" +}) +export type LiveInlineSkillParam = { + readonly "type": "inline" + readonly "name": string + readonly "description": string + readonly "source": LiveInlineSkillSourceParam +} +export const LiveInlineSkillParam = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "Defines an inline skill for this request." }), + "name": Schema.String.annotate({ "description": "The name of the skill." }), + "description": Schema.String.annotate({ "description": "The description of the skill." }), + "source": Schema.suspend((): Schema.Codec => LiveInlineSkillSourceParam).annotate({ + "description": "Inline skill payload" + }) +}).annotate({ "identifier": "LiveInlineSkillParam" }) +export type LiveLocalEnvironmentParam = { + readonly "type": "local" + readonly "skills"?: ReadonlyArray | null +} +export const LiveLocalEnvironmentParam = Schema.Struct({ + "type": Schema.Literal("local").annotate({ "description": "Use a local computer environment." }), + "skills": Schema.optionalKey( + Schema.Union([ + Schema.Array(LiveLocalSkillParam).annotate({ "description": "An optional list of skills." }).check( + Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" }) ), - "error": Schema.optionalKey( - Schema.Struct({ - "type": Schema.optionalKey(Schema.String.annotate({ "description": "The type of error." })), - "code": Schema.optionalKey(Schema.String.annotate({ "description": "Error code, if any." })) - }).annotate({ - "description": - "A description of the error that caused the response to fail, \npopulated when the `status` is `failed`.\n" - }) - ) - }).annotate({ "description": "Additional details about the status." }) - ), - "output": Schema.optionalKey( - Schema.Array(RealtimeConversationItem).annotate({ - "description": "The list of output items generated by the response." - }) + Schema.Null + ]) + ) +}).annotate({ "identifier": "LiveLocalEnvironmentParam" }) +export type LiveAllowedToolsChoiceParam = { + readonly "type": "allowed_tools" + readonly "tools": ReadonlyArray< + | LiveFunctionToolChoiceParam + | LiveMCPToolChoiceParam + | LiveSpecificFileSearchParam + | LiveSpecificWebSearchParam + | LiveSpecificWebSearchPreviewParam + | LiveSpecificImageGenParam + | LiveSpecificComputerParam + | LiveSpecificCodeInterpreterParam + | LiveSpecificProgrammaticToolCallingParam + | LiveSpecificFunctionShellParam + | LiveSpecificCustomToolParam + | LiveSpecificApplyPatchParam + > + readonly "mode"?: LiveToolChoiceValueEnum | null +} +export const LiveAllowedToolsChoiceParam = Schema.Struct({ + "type": Schema.Literal("allowed_tools").annotate({ "description": "The tool choice type. Always `allowed_tools`." }), + "tools": Schema.Array( + Schema.Union([ + LiveFunctionToolChoiceParam, + LiveMCPToolChoiceParam, + LiveSpecificFileSearchParam, + LiveSpecificWebSearchParam, + LiveSpecificWebSearchPreviewParam, + LiveSpecificImageGenParam, + LiveSpecificComputerParam, + LiveSpecificCodeInterpreterParam, + LiveSpecificProgrammaticToolCallingParam, + LiveSpecificFunctionShellParam, + LiveSpecificCustomToolParam, + LiveSpecificApplyPatchParam + ], { mode: "oneOf" }) + ).annotate({ "description": "The tools that the delegated Responses model may call." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxLength(128).annotate({ "expected": "a value with a length of at most 128" })), + "mode": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveToolChoiceValueEnum).annotate({ + "description": "How to select a tool from the allowed set." + }), + Schema.Null + ]) + ) +}).annotate({ "identifier": "LiveAllowedToolsChoiceParam" }) +export type LiveInitialDeveloperMessageItemParam = { + readonly "id"?: string | null + readonly "type"?: "message" + readonly "status"?: LiveInitialMessageStatus | null + readonly "role": "developer" + readonly "content": ReadonlyArray +} +export const LiveInitialDeveloperMessageItemParam = Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "An optional identifier for the supplied history message. Live uses the message’s role and text to initialize the conversation." + }), + Schema.Null + ]) ), - "metadata": Schema.optionalKey(Metadata), - "usage": Schema.optionalKey( - Schema.Struct({ - "total_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The total number of tokens in the Response including input and output \ntext and audio tokens.\n" - }).check(Schema.isInt()) - ), - "input_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of input tokens used in the Response, including text and \naudio tokens.\n" - }).check(Schema.isInt()) - ), - "output_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of output tokens sent in the Response, including text and \naudio tokens.\n" - }).check(Schema.isInt()) - ), - "input_token_details": Schema.optionalKey( - Schema.Struct({ - "cached_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of cached tokens used as input for the Response." }) - .check(Schema.isInt()) - ), - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of text tokens used as input for the Response." }) - .check(Schema.isInt()) - ), - "image_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of image tokens used as input for the Response." }) - .check(Schema.isInt()) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of audio tokens used as input for the Response." }) - .check(Schema.isInt()) - ), - "cached_tokens_details": Schema.optionalKey( - Schema.Struct({ - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of cached text tokens used as input for the Response." - }).check(Schema.isInt()) - ), - "image_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of cached image tokens used as input for the Response." - }).check(Schema.isInt()) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of cached audio tokens used as input for the Response." - }).check(Schema.isInt()) - ) - }).annotate({ "description": "Details about the cached tokens used as input for the Response." }) - ) - }).annotate({ "description": "Details about the input tokens used in the Response." }) - ), - "output_token_details": Schema.optionalKey( - Schema.Struct({ - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of text tokens used in the Response." }).check( - Schema.isInt() - ) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of audio tokens used in the Response." }).check( - Schema.isInt() - ) - ) - }).annotate({ "description": "Details about the output tokens used in the Response." }) - ) - }).annotate({ - "description": - "Usage statistics for the Response, this will correspond to billing. A \nRealtime API session will maintain a conversation context and append new \nItems to the Conversation, thus output from previous turns (text and \naudio tokens) will become the input for later turns.\n" - }) + "type": Schema.optionalKey( + Schema.Literal("message").annotate({ "description": "The history item type. Always `message`." }) ), - "conversation_id": Schema.optionalKey(Schema.String.annotate({ - "description": - "Which conversation the response is added to, determined by the `conversation`\nfield in the `response.create` event. If `auto`, the response will be added to\nthe default conversation and the value of `conversation_id` will be an id like\n`conv_1234`. If `none`, the response will not be added to any conversation and\nthe value of `conversation_id` will be `null`. If responses are being triggered\nby server VAD, the response will be added to the default conversation, thus\nthe `conversation_id` will be an id like `conv_1234`.\n" - })), - "voice": Schema.optionalKey( + "status": Schema.optionalKey( Schema.Union([ - Schema.String, - Schema.Literals(["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"]) - ]).annotate({ - "description": - "The voice the model used to respond.\nCurrent voice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`,\n`shimmer`, and `verse`.\n" - }) + Schema.suspend((): Schema.Codec => LiveInitialMessageStatus).annotate({ + "description": + "The supplied message’s status. Live uses its text as history and does not resume an incomplete message." + }), + Schema.Null + ]) ), - "modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": - "The set of modalities the model used to respond. If there are multiple modalities,\nthe model will pick one, for example if `modalities` is `[\"text\", \"audio\"]`, the model\ncould be responding in either text or audio.\n" - }) + "role": Schema.Literal("developer").annotate({ + "description": "The author of this history message. Always `developer`." + }), + "content": Schema.Array(LiveInitialInputTextContentPartParam).annotate({ + "description": "The message content. Supply exactly one text part for the initial Live conversation history." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" }) + ) +}).annotate({ + "description": "A developer message included in the initial text history of a Live session.", + "identifier": "LiveInitialDeveloperMessageItemParam" +}) +export type LiveInitialUserMessageItemParam = { + readonly "id"?: string | null + readonly "type"?: "message" + readonly "status"?: LiveInitialMessageStatus | null + readonly "role": "user" + readonly "content": ReadonlyArray +} +export const LiveInitialUserMessageItemParam = Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "An optional identifier for the supplied history message. Live uses the message’s role and text to initialize the conversation." + }), + Schema.Null + ]) ), - "output_audio_format": Schema.optionalKey( - Schema.Literals(["pcm16", "g711_ulaw", "g711_alaw"]).annotate({ - "description": "The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\n" - }) + "type": Schema.optionalKey( + Schema.Literal("message").annotate({ "description": "The history item type. Always `message`." }) ), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Sampling temperature for the model, limited to [0.6, 1.2]. Defaults to 0.8.\n" - }).check(Schema.isFinite()) + "status": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveInitialMessageStatus).annotate({ + "description": + "The supplied message’s status. Live uses its text as history and does not resume an incomplete message." + }), + Schema.Null + ]) ), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls, that was used in this response.\n" - }) + "role": Schema.Literal("user").annotate({ "description": "The author of this history message. Always `user`." }), + "content": Schema.Array(LiveInitialInputTextContentPartParam).annotate({ + "description": "The message content. Supply exactly one text part for the initial Live conversation history." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" }) ) -}).annotate({ "description": "The response resource." }) -export type RealtimeBetaResponseCreateParams = { - readonly "modalities"?: ReadonlyArray<"text" | "audio"> - readonly "instructions"?: string - readonly "voice"?: VoiceIdsShared | { readonly "id": string } - readonly "output_audio_format"?: "pcm16" | "g711_ulaw" | "g711_alaw" - readonly "tools"?: ReadonlyArray< - { - readonly "type"?: "function" - readonly "name"?: string - readonly "description"?: string - readonly "parameters"?: {} - } - > - readonly "tool_choice"?: ToolChoiceOptions | ToolChoiceFunction | ToolChoiceMCP - readonly "temperature"?: number - readonly "max_output_tokens"?: number | "inf" - readonly "conversation"?: string | "auto" | "none" - readonly "metadata"?: Metadata - readonly "prompt"?: Prompt - readonly "input"?: ReadonlyArray +}).annotate({ + "description": "A user message included in the initial text history of a Live session.", + "identifier": "LiveInitialUserMessageItemParam" +}) +export type LiveInitialAssistantMessageItemParam = { + readonly "id"?: string | null + readonly "type"?: "message" + readonly "status"?: LiveInitialMessageStatus | null + readonly "role": "assistant" + readonly "content": ReadonlyArray } -export const RealtimeBetaResponseCreateParams = Schema.Struct({ - "modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": "The set of modalities the model can respond with. To disable audio,\nset this to [\"text\"].\n" - }) - ), - "instructions": Schema.optionalKey(Schema.String.annotate({ - "description": - "The default system instructions (i.e. system message) prepended to model \ncalls. This field allows the client to guide the model on desired \nresponses. The model can be instructed on response content and format, \n(e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good \nresponses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion \ninto your voice\", \"laugh frequently\"). The instructions are not guaranteed \nto be followed by the model, but they provide guidance to the model on the \ndesired behavior.\n\nNote that the server sets default instructions which will be used if this \nfield is not set and are visible in the `session.created` event at the \nstart of the session.\n" - })), - "voice": Schema.optionalKey( +export const LiveInitialAssistantMessageItemParam = Schema.Struct({ + "id": Schema.optionalKey( Schema.Union([ - VoiceIdsShared, - Schema.Struct({ "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) }) - .annotate({ "description": "Custom voice reference." }) - ]).annotate({ - "title": "Voice", - "description": - "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`,\n`marin`, and `cedar`. You may also provide a custom voice object with an\n`id`, for example `{ \"id\": \"voice_1234\" }`. Voice cannot be changed during\nthe session once the model has responded with audio at least once.\n" - }) + Schema.String.annotate({ + "description": + "An optional identifier for the supplied history message. Live uses the message’s role and text to initialize the conversation." + }), + Schema.Null + ]) ), - "output_audio_format": Schema.optionalKey( - Schema.Literals(["pcm16", "g711_ulaw", "g711_alaw"]).annotate({ - "description": "The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\n" - }) + "type": Schema.optionalKey( + Schema.Literal("message").annotate({ "description": "The history item type. Always `message`." }) ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("function").annotate({ "description": "The type of the tool, i.e. `function`." }) - ), - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function." })), - "description": Schema.optionalKey( + "status": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveInitialMessageStatus).annotate({ + "description": + "The supplied message’s status. Live uses its text as history and does not resume an incomplete message." + }), + Schema.Null + ]) + ), + "role": Schema.Literal("assistant").annotate({ + "description": "The author of this history message. Always `assistant`." + }), + "content": Schema.Array( + Schema.Union([LiveInitialTextContentPartParam, LiveInitialOutputTextContentPartParam], { mode: "oneOf" }) + ).annotate({ + "description": "The message content. Supply exactly one text part for the initial Live conversation history." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" }) + ) +}).annotate({ + "description": "An assistant message included in the initial text history of a Live session.", + "identifier": "LiveInitialAssistantMessageItemParam" +}) +export type LiveDataChannelConfigParam = { + readonly "allowed_client_events"?: "all" | ReadonlyArray + readonly "allowed_server_events"?: "all" | ReadonlyArray +} +export const LiveDataChannelConfigParam = Schema.Struct({ + "allowed_client_events": Schema.optionalKey( + Schema.Union([ + Schema.Literal("all"), + Schema.Array( Schema.String.annotate({ "description": - "The description of the function, including guidance on when and how \nto call it, and guidance about what to tell the user when calling \n(if anything).\n" - }) - ), - "parameters": Schema.optionalKey( - Schema.Struct({}).annotate({ "description": "Parameters of the function in JSON Schema." }) - ) - })).annotate({ "description": "Tools (functions) available to the model." }) - ), - "tool_choice": Schema.optionalKey( - Schema.Union([ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMCP], { mode: "oneOf" }).annotate({ - "description": - "How the model chooses tools. Provide one of the string modes or force a specific\nfunction/MCP tool.\n" - }) - ), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ - "description": "Sampling temperature for the model, limited to [0.6, 1.2]. Defaults to 0.8.\n" - }).check(Schema.isFinite()) - ), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" - }) - ), - "conversation": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Literals(["auto", "none"])], { mode: "oneOf" }).annotate({ + "A Live client event type allowed on the frontend data channel, such as `session.input_audio.mute`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ).check( + Schema.isPattern(new RegExp("^(?:error|info|[a-z][a-z0-9_-]*(?:\\.[a-z0-9_-]+)+)$", "u")).annotate({ + "expected": "a string matching the RegExp ^(?:error|info|[a-z][a-z0-9_-]*(?:\\.[a-z0-9_-]+)+)$" + }) + ) + ).check(Schema.isMaxLength(256).annotate({ "expected": "a value with a length of at most 256" })) + ], { mode: "oneOf" }).annotate({ "description": - "Controls which conversation the response is added to. Currently supports\n`auto` and `none`, with `auto` as the default value. The `auto` value\nmeans that the contents of the response will be added to the default\nconversation. Set this to `none` to create an out-of-band response which \nwill not add items to default conversation.\n" + "Client event types that the frontend data channel may send. Use 'all' to allow every client event; an empty array allows none. Omission preserves the existing allow-all behavior." }) ), - "metadata": Schema.optionalKey(Metadata), - "prompt": Schema.optionalKey(Prompt), - "input": Schema.optionalKey( - Schema.Array(RealtimeConversationItem).annotate({ + "allowed_server_events": Schema.optionalKey( + Schema.Union([ + Schema.Literal("all"), + Schema.Array(LiveAllowedServerEventParam).check( + Schema.isMaxLength(256).annotate({ "expected": "a value with a length of at most 256" }) + ) + ], { mode: "oneOf" }).annotate({ "description": - "Input items to include in the prompt for the model. Using this field\ncreates a new context for this Response instead of using the default\nconversation. An empty array `[]` will clear the context for this Response.\nNote that this can include references to items from the default conversation.\n" + "Server events that may be sent to the frontend data channel. Use 'all' to allow every server event; an empty array allows none. Omission preserves the existing allow-all behavior. Responses events use an object with type 'response.event' and a response_event selector." }) ) -}).annotate({ "description": "Create a new Realtime response with these parameters" }) -export type RealtimeClientEventConversationItemCreate = { - readonly "event_id"?: string - readonly "type": "conversation.item.create" - readonly "previous_item_id"?: string - readonly "item": RealtimeConversationItem +}).annotate({ + "description": + "Control which Live events an untrusted WebRTC frontend can send and receive over its data channel. These restrictions do not apply to trusted sideband connections.", + "identifier": "LiveDataChannelConfigParam" +}) +export type LiveCreateResponse = { + readonly "session": { readonly "id": string } + readonly "transport": LiveWebRTCTransport } -export const RealtimeClientEventConversationItemCreate = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) - ), - "type": Schema.Literal("conversation.item.create").annotate({ - "description": "The event type, must be `conversation.item.create`." +export const LiveCreateResponse = Schema.Struct({ + "session": Schema.Struct({ + "id": Schema.String.annotate({ + "description": "Opaque session identifier. Preserve the returned value unchanged, including its prefix." + }) + }).annotate({ + "description": "The newly created Live session. Use its ID for session controls and sideband connections." }), - "previous_item_id": Schema.optionalKey(Schema.String.annotate({ - "description": - "The ID of the preceding item after which the new item will be inserted. If not set, the new item will be appended to the end of the conversation.\n\nIf set to `root`, the new item will be added to the beginning of the conversation.\n\nIf set to an existing ID, it allows an item to be inserted mid-conversation. If the ID cannot be found, an error will be returned and the item will not be added.\n" - })), - "item": RealtimeConversationItem + "transport": Schema.suspend((): Schema.Codec => LiveWebRTCTransport).annotate({ + "description": "WebRTC transport with the SDP answer." + }) }).annotate({ "description": - "Add a new Item to the Conversation's context, including messages, function \ncalls, and function call responses. This event can be used both to populate a \n\"history\" of the conversation and to add new items mid-stream, but has the \ncurrent limitation that it cannot populate assistant audio messages.\n\nIf successful, the server will respond with a `conversation.item.created` \nevent, otherwise an `error` event will be sent.\n" + "The created Live session identifier and WebRTC answer. Apply transport.sdp as the peer's remote answer and wait for session.started on the data channel before sending commands.", + "identifier": "LiveCreateResponse" }) -export type RealtimeResponse = { - readonly "id"?: string - readonly "object"?: "realtime.response" - readonly "status"?: "completed" | "cancelled" | "failed" | "incomplete" | "in_progress" - readonly "status_details"?: { - readonly "type"?: "completed" | "cancelled" | "failed" | "incomplete" - readonly "reason"?: "turn_detected" | "client_cancelled" | "max_output_tokens" | "content_filter" - readonly "error"?: { readonly "type"?: string; readonly "code"?: string } - } - readonly "output"?: ReadonlyArray - readonly "metadata"?: Metadata - readonly "audio"?: { - readonly "output"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "voice"?: - | string - | "alloy" - | "ash" - | "ballad" - | "coral" - | "echo" - | "sage" - | "shimmer" - | "verse" - | "marin" - | "cedar" - } - } - readonly "usage"?: { - readonly "total_tokens"?: number - readonly "input_tokens"?: number - readonly "output_tokens"?: number - readonly "input_token_details"?: { - readonly "cached_tokens"?: number - readonly "text_tokens"?: number - readonly "image_tokens"?: number - readonly "audio_tokens"?: number - readonly "cached_tokens_details"?: { - readonly "text_tokens"?: number - readonly "image_tokens"?: number - readonly "audio_tokens"?: number - } - } - readonly "output_token_details"?: { readonly "text_tokens"?: number; readonly "audio_tokens"?: number } - } - readonly "conversation_id"?: string - readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> - readonly "max_output_tokens"?: number | "inf" +export type LiveSIPTrunk = { + readonly "provider_url": string + readonly "auth": LiveSIPTrunkAuth + readonly "caller_number": string } -export const RealtimeResponse = Schema.Struct({ - "id": Schema.optionalKey( - Schema.String.annotate({ "description": "The unique ID of the response, will look like `resp_1234`." }) - ), - "object": Schema.optionalKey( - Schema.Literal("realtime.response").annotate({ "description": "The object type, must be `realtime.response`." }) - ), - "status": Schema.optionalKey( - Schema.Literals(["completed", "cancelled", "failed", "incomplete", "in_progress"]).annotate({ - "description": - "The final status of the response (`completed`, `cancelled`, `failed`, or \n`incomplete`, `in_progress`).\n" +export const LiveSIPTrunk = Schema.Struct({ + "provider_url": Schema.String.annotate({ + "description": + "Provider endpoint in the form `sips:host[:port][;transport=tcp]`. The default port is 5061. IPv6 addresses must be bracketed. TLS signaling is required; plaintext SIP is not supported. Do not include userinfo, a path, URI headers, or other URI parameters. Local hostnames and literal private, loopback, link-local, unspecified, multicast, and broadcast IP addresses are rejected." + }), + "auth": LiveSIPTrunkAuth, + "caller_number": Schema.String.annotate({ + "description": "Caller phone number in E.164 format to use in the SIP From header." + }).check( + Schema.isPattern(new RegExp("^\\+[1-9][0-9]{1,14}$", "u")).annotate({ + "expected": "a string matching the RegExp ^\\+[1-9][0-9]{1,14}$" }) - ), - "status_details": Schema.optionalKey( + ) +}).annotate({ + "description": + "SIP trunk configuration supplied for this call. Keep trunk credentials on your server. The creation response does not return this configuration.", + "identifier": "LiveSIPTrunk" +}) +export type LiveSessionCreateResponse = { + readonly "session": Session + readonly "transport": LiveWebRTCTransport | { readonly "type": "sip" } +} +export const LiveSessionCreateResponse = Schema.Struct({ + "session": Session, + "transport": Schema.Union([ + LiveWebRTCTransport, Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literals(["completed", "cancelled", "failed", "incomplete"]).annotate({ - "description": - "The type of error that caused the response to fail, corresponding \nwith the `status` field (`completed`, `cancelled`, `incomplete`, \n`failed`).\n" - }) - ), - "reason": Schema.optionalKey( - Schema.Literals(["turn_detected", "client_cancelled", "max_output_tokens", "content_filter"]).annotate({ - "description": - "The reason the Response did not complete. For a `cancelled` Response, one of `turn_detected` (the server VAD detected a new start of speech) or `client_cancelled` (the client sent a cancel event). For an `incomplete` Response, one of `max_output_tokens` or `content_filter` (the server-side safety filter activated and cut off the response).\n" - }) - ), - "error": Schema.optionalKey( - Schema.Struct({ - "type": Schema.optionalKey(Schema.String.annotate({ "description": "The type of error." })), - "code": Schema.optionalKey(Schema.String.annotate({ "description": "Error code, if any." })) - }).annotate({ - "description": - "A description of the error that caused the response to fail, \npopulated when the `status` is `failed`.\n" - }) - ) - }).annotate({ "description": "Additional details about the status." }) - ), - "output": Schema.optionalKey( - Schema.Array(RealtimeConversationItem).annotate({ - "description": "The list of output items generated by the response." + "type": Schema.Literal("sip").annotate({ + "description": "The transport used for the Live session. Always `sip`." + }) + }).annotate({ "description": "The SIP transport. Trunk credentials and SDP are not returned." }) + ], { mode: "oneOf" }).annotate({ + "description": + "WebRTC transport with an SDP answer, or SIP transport without SDP or trunk credentials. For SIP, attach a sideband using session.id to receive transport.ringing, transport.answered, and transport.failed notifications." + }) +}).annotate({ + "description": + "The created Live session and its transport. WebRTC creation returns 201 Created with an SDP answer. Outbound SIP creation returns 201 Created after initialization, before the callee necessarily answers, without SDP or trunk credentials.", + "identifier": "LiveSessionCreateResponse" +}) +export type ListModelsResponse = { readonly "object": "list"; readonly "data": ReadonlyArray } +export const ListModelsResponse = Schema.Struct({ "object": Schema.Literal("list"), "data": Schema.Array(Model) }) + .annotate({ "identifier": "ListModelsResponse" }) +export type ApiKeyList = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "first_id"?: string | null + readonly "last_id"?: string | null +} +export const ApiKeyList = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(AdminApiKey), + "has_more": Schema.Boolean, + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])) +}).annotate({ "identifier": "ApiKeyList" }) +export type AuditLogActorSession = { readonly "user"?: AuditLogActorUser; readonly "ip_address"?: string } +export const AuditLogActorSession = Schema.Struct({ + "user": Schema.optionalKey(AuditLogActorUser), + "ip_address": Schema.optionalKey( + Schema.String.annotate({ "description": "The IP address from which the action was performed." }) + ) +}).annotate({ + "description": "The session in which the audit logged action was performed.", + "identifier": "AuditLogActorSession" +}) +export type AuditLogActorApiKey = { + readonly "id"?: string + readonly "type"?: "user" | "service_account" + readonly "user"?: AuditLogActorUser + readonly "service_account"?: AuditLogActorServiceAccount +} +export const AuditLogActorApiKey = Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The tracking id of the API key." })), + "type": Schema.optionalKey( + Schema.Literals(["user", "service_account"]).annotate({ + "description": "The type of API key. Can be either `user` or `service_account`." }) ), - "metadata": Schema.optionalKey(Metadata), - "audio": Schema.optionalKey( - Schema.Struct({ - "output": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the output audio." }) - ), - "voice": Schema.optionalKey( - Schema.Union([ - Schema.String, - Schema.Literals(["alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse", "marin", "cedar"]) - ]).annotate({ - "description": - "The voice the model uses to respond. Voice cannot be changed during the\nsession once the model has responded with audio at least once. Current\nvoice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`,\n`shimmer`, `verse`, `marin`, and `cedar`. We recommend `marin` and `cedar` for\nbest quality.\n" - }) - ) - })) - }).annotate({ "description": "Configuration for audio output." }) - ), - "usage": Schema.optionalKey( - Schema.Struct({ - "total_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": - "The total number of tokens in the Response including input and output \ntext and audio tokens.\n" - }).check(Schema.isInt()) - ), - "input_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of input tokens used in the Response, including text and \naudio tokens.\n" - }).check(Schema.isInt()) - ), - "output_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of output tokens sent in the Response, including text and \naudio tokens.\n" - }).check(Schema.isInt()) - ), - "input_token_details": Schema.optionalKey( - Schema.Struct({ - "cached_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of cached tokens used as input for the Response." }) - .check(Schema.isInt()) - ), - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of text tokens used as input for the Response." }) - .check(Schema.isInt()) - ), - "image_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of image tokens used as input for the Response." }) - .check(Schema.isInt()) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of audio tokens used as input for the Response." }) - .check(Schema.isInt()) - ), - "cached_tokens_details": Schema.optionalKey( - Schema.Struct({ - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of cached text tokens used as input for the Response." - }).check(Schema.isInt()) - ), - "image_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of cached image tokens used as input for the Response." - }).check(Schema.isInt()) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ - "description": "The number of cached audio tokens used as input for the Response." - }).check(Schema.isInt()) - ) - }).annotate({ "description": "Details about the cached tokens used as input for the Response." }) - ) - }).annotate({ - "description": - "Details about the input tokens used in the Response. Cached tokens are tokens from previous turns in the conversation that are included as context for the current response. Cached tokens here are counted as a subset of input tokens, meaning input tokens will include cached and uncached tokens." - }) - ), - "output_token_details": Schema.optionalKey( - Schema.Struct({ - "text_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of text tokens used in the Response." }).check( - Schema.isInt() - ) - ), - "audio_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The number of audio tokens used in the Response." }).check( - Schema.isInt() - ) - ) - }).annotate({ "description": "Details about the output tokens used in the Response." }) - ) - }).annotate({ - "description": - "Usage statistics for the Response, this will correspond to billing. A \nRealtime API session will maintain a conversation context and append new \nItems to the Conversation, thus output from previous turns (text and \naudio tokens) will become the input for later turns.\n" - }) - ), - "conversation_id": Schema.optionalKey(Schema.String.annotate({ - "description": - "Which conversation the response is added to, determined by the `conversation`\nfield in the `response.create` event. If `auto`, the response will be added to\nthe default conversation and the value of `conversation_id` will be an id like\n`conv_1234`. If `none`, the response will not be added to any conversation and\nthe value of `conversation_id` will be `null`. If responses are being triggered\nautomatically by VAD the response will be added to the default conversation\n" - })), - "output_modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": - "The set of modalities the model used to respond, currently the only possible values are\n`[\\\"audio\\\"]`, `[\\\"text\\\"]`. Audio output always include a text transcript. Setting the\noutput to mode `text` will disable audio output from the model.\n" - }) - ), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls, that was used in this response.\n" - }) - ) -}).annotate({ "description": "The response resource." }) -export type RealtimeResponseCreateParams = { - readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> - readonly "instructions"?: string - readonly "audio"?: { - readonly "output"?: { - readonly "format"?: { readonly "type"?: "audio/pcm"; readonly "rate"?: 24000 } | { - readonly "type"?: "audio/pcmu" - } | { readonly "type"?: "audio/pcma" } - readonly "voice"?: VoiceIdsShared | { readonly "id": string } - } - } - readonly "tools"?: ReadonlyArray - readonly "tool_choice"?: ToolChoiceOptions | ToolChoiceFunction | ToolChoiceMCP - readonly "parallel_tool_calls"?: boolean - readonly "reasoning"?: RealtimeReasoning - readonly "max_output_tokens"?: number | "inf" - readonly "conversation"?: string | "auto" | "none" - readonly "metadata"?: Metadata - readonly "prompt"?: Prompt - readonly "input"?: ReadonlyArray + "user": Schema.optionalKey(AuditLogActorUser), + "service_account": Schema.optionalKey(AuditLogActorServiceAccount) +}).annotate({ + "description": "The API Key used to perform the audit logged action.", + "identifier": "AuditLogActorApiKey" +}) +export type Provider = + | AwsExternalStorageProviderResponse + | AzureExternalStorageProviderResponse + | GcpExternalStorageProviderResponse + | OciExternalStorageProviderResponse +export const Provider = Schema.Union([ + AwsExternalStorageProviderResponse, + AzureExternalStorageProviderResponse, + GcpExternalStorageProviderResponse, + OciExternalStorageProviderResponse +], { mode: "oneOf" }).annotate({ "identifier": "provider" }) +export type ListCertificatesResponse = { + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean + readonly "object": "list" } -export const RealtimeResponseCreateParams = Schema.Struct({ - "output_modalities": Schema.optionalKey( - Schema.Array(Schema.Literals(["text", "audio"])).annotate({ - "description": - "The set of modalities the model used to respond, currently the only possible values are\n`[\\\"audio\\\"]`, `[\\\"text\\\"]`. Audio output always include a text transcript. Setting the\noutput to mode `text` will disable audio output from the model.\n" - }) - ), - "instructions": Schema.optionalKey(Schema.String.annotate({ - "description": - "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" - })), - "audio": Schema.optionalKey( - Schema.Struct({ - "output": Schema.optionalKey(Schema.Struct({ - "format": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcm").annotate({ "description": "The audio format. Always `audio/pcm`." }) - ), - "rate": Schema.optionalKey( - Schema.Literal(24000).annotate({ "description": "The sample rate of the audio. Always `24000`." }) - ) - }).annotate({ - "title": "PCM audio format", - "description": "The PCM audio format. Only a 24kHz sample rate is supported." - }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcmu").annotate({ "description": "The audio format. Always `audio/pcmu`." }) - ) - }).annotate({ "title": "PCMU audio format", "description": "The G.711 μ-law format." }), - Schema.Struct({ - "type": Schema.optionalKey( - Schema.Literal("audio/pcma").annotate({ "description": "The audio format. Always `audio/pcma`." }) - ) - }).annotate({ "title": "PCMA audio format", "description": "The G.711 A-law format." }) - ]).annotate({ "description": "The format of the output audio." }) - ), - "voice": Schema.optionalKey( - Schema.Union([ - VoiceIdsShared, - Schema.Struct({ - "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) - }).annotate({ "description": "Custom voice reference." }) - ]).annotate({ - "title": "Voice", - "description": - "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`,\n`marin`, and `cedar`. You may also provide a custom voice object with\nan `id`, for example `{ \"id\": \"voice_1234\" }`. Voice cannot be changed\nduring the session once the model has responded with audio at least once.\nWe recommend `marin` and `cedar` for best quality.\n" - }) - ) - })) - }).annotate({ "description": "Configuration for audio input and output." }) - ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([RealtimeFunctionTool, MCPTool], { mode: "oneOf" })).annotate({ - "description": "Tools available to the model." - }) - ), - "tool_choice": Schema.optionalKey( - Schema.Union([ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMCP], { mode: "oneOf" }).annotate({ - "description": - "How the model chooses tools. Provide one of the string modes or force a specific\nfunction/MCP tool.\n" - }) - ), - "parallel_tool_calls": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": - "Whether the model may call multiple tools in parallel. Only supported by\nreasoning Realtime models such as `gpt-realtime-2`.\n" - }) - ), - "reasoning": Schema.optionalKey(RealtimeReasoning), - "max_output_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Literal("inf")], { mode: "oneOf" }).annotate({ - "description": - "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" - }) - ), - "conversation": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Literals(["auto", "none"])], { mode: "oneOf" }).annotate({ - "description": - "Controls which conversation the response is added to. Currently supports\n`auto` and `none`, with `auto` as the default value. The `auto` value\nmeans that the contents of the response will be added to the default\nconversation. Set this to `none` to create an out-of-band response which\nwill not add items to default conversation.\n" - }) - ), - "metadata": Schema.optionalKey(Metadata), - "prompt": Schema.optionalKey(Prompt), - "input": Schema.optionalKey( - Schema.Array(RealtimeConversationItem).annotate({ - "description": - "Input items to include in the prompt for the model. Using this field\ncreates a new context for this Response instead of using the default\nconversation. An empty array `[]` will clear the context for this Response.\nNote that this can include references to items that previously appeared in the session\nusing their id.\n" - }) - ) -}).annotate({ "description": "Create a new Realtime response with these parameters" }) -export type RealtimeServerEventConversationItemAdded = { - readonly "event_id": string - readonly "type": "conversation.item.added" - readonly "previous_item_id"?: string | null - readonly "item": RealtimeConversationItem +export const ListCertificatesResponse = Schema.Struct({ + "data": Schema.Array(OrganizationCertificate), + "first_id": Schema.Union([Schema.String, Schema.Null]), + "last_id": Schema.Union([Schema.String, Schema.Null]), + "has_more": Schema.Boolean, + "object": Schema.Literal("list") +}).annotate({ "identifier": "ListCertificatesResponse" }) +export type OrganizationCertificateActivationResponse = { + readonly "object": "organization.certificate.activation" + readonly "data": ReadonlyArray } -export const RealtimeServerEventConversationItemAdded = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.added").annotate({ - "description": "The event type, must be `conversation.item.added`." +export const OrganizationCertificateActivationResponse = Schema.Struct({ + "object": Schema.Literal("organization.certificate.activation").annotate({ + "description": "The organization certificate activation result type." }), - "previous_item_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The ID of the item that precedes this one, if any. This is used to\nmaintain ordering when items are inserted.\n" - }), - Schema.Null - ]) - ), - "item": RealtimeConversationItem -}).annotate({ - "description": - "Sent by the server when an Item is added to the default Conversation. This can happen in several cases:\n- When the client sends a `conversation.item.create` event.\n- When the input audio buffer is committed. In this case the item will be a user message containing the audio from the buffer.\n- When the model is generating a Response. In this case the `conversation.item.added` event will be sent when the model starts generating a specific Item, and thus it will not yet have any content (and `status` will be `in_progress`).\n\nThe event will include the full content of the Item (except when model is generating a Response) except for audio data, which can be retrieved separately with a `conversation.item.retrieve` event if necessary.\n" -}) -export type RealtimeServerEventConversationItemCreated = { - readonly "event_id": string - readonly "type": "conversation.item.created" - readonly "previous_item_id"?: string | null - readonly "item": RealtimeConversationItem + "data": Schema.Array(OrganizationCertificate) +}).annotate({ "identifier": "OrganizationCertificateActivationResponse" }) +export type OrganizationCertificateDeactivationResponse = { + readonly "object": "organization.certificate.deactivation" + readonly "data": ReadonlyArray } -export const RealtimeServerEventConversationItemCreated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.created").annotate({ - "description": "The event type, must be `conversation.item.created`." +export const OrganizationCertificateDeactivationResponse = Schema.Struct({ + "object": Schema.Literal("organization.certificate.deactivation").annotate({ + "description": "The organization certificate deactivation result type." }), - "previous_item_id": Schema.optionalKey( + "data": Schema.Array(OrganizationCertificate) +}).annotate({ "identifier": "OrganizationCertificateDeactivationResponse" }) +export type UsageTimeBucket = { + readonly "object": "bucket" + readonly "start_time": number + readonly "end_time": number + readonly "results": ReadonlyArray< + | UsageCompletionsResult + | UsageEmbeddingsResult + | UsageModerationsResult + | UsageImagesResult + | UsageAudioSpeechesResult + | UsageAudioTranscriptionsResult + | UsageVectorStoresResult + | UsageCodeInterpreterSessionsResult + | UsageFileSearchCallsResult + | UsageWebSearchCallsResult + | CostsResult + > +} +export const UsageTimeBucket = Schema.Struct({ + "object": Schema.Literal("bucket"), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "results": Schema.Array( Schema.Union([ - Schema.String.annotate({ - "description": - "The ID of the preceding item in the Conversation context, allows the\nclient to understand the order of the conversation. Can be `null` if the\nitem has no predecessor.\n" - }), - Schema.Null - ]) - ), - "item": RealtimeConversationItem -}).annotate({ - "description": - "Returned when a conversation item is created. There are several scenarios that produce this event:\n - The server is generating a Response, which if successful will produce\n either one or two Items, which will be of type `message`\n (role `assistant`) or type `function_call`.\n - The input audio buffer has been committed, either by the client or the\n server (in `server_vad` mode). The server will take the content of the\n input audio buffer and add it to a new user message Item.\n - The client has sent a `conversation.item.create` event to add a new Item\n to the Conversation.\n" -}) -export type RealtimeServerEventConversationItemDone = { - readonly "event_id": string - readonly "type": "conversation.item.done" - readonly "previous_item_id"?: string | null - readonly "item": RealtimeConversationItem + UsageCompletionsResult, + UsageEmbeddingsResult, + UsageModerationsResult, + UsageImagesResult, + UsageAudioSpeechesResult, + UsageAudioTranscriptionsResult, + UsageVectorStoresResult, + UsageCodeInterpreterSessionsResult, + UsageFileSearchCallsResult, + UsageWebSearchCallsResult, + CostsResult + ], { mode: "oneOf" }) + ) +}).annotate({ "identifier": "UsageTimeBucket" }) +export type GroupListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "next": string | null } -export const RealtimeServerEventConversationItemDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.done").annotate({ - "description": "The event type, must be `conversation.item.done`." +export const GroupListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), + "data": Schema.Array(GroupResponse).annotate({ "description": "Groups returned in the current page." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether additional groups are available when paginating." }), + "next": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "Cursor to fetch the next page of results, or `null` if there are no more results." + }) +}).annotate({ "description": "Paginated list of organization groups.", "identifier": "GroupListResource" }) +export type RoleListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "next": string | null +} +export const RoleListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), + "data": Schema.Array(AssignedRoleDetails).annotate({ + "description": "Role assignments returned in the current page." }), - "previous_item_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The ID of the item that precedes this one, if any. This is used to\nmaintain ordering when items are inserted.\n" - }), - Schema.Null - ]) - ), - "item": RealtimeConversationItem + "has_more": Schema.Boolean.annotate({ + "description": "Whether additional assignments are available when paginating." + }), + "next": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "Cursor to fetch the next page of results, or `null` when there are no more assignments." + }) +}).annotate({ "description": "Paginated list of roles assigned to a principal.", "identifier": "RoleListResource" }) +export type GroupRoleAssignment = { readonly "object": "group.role"; readonly "group": Group; readonly "role": Role } +export const GroupRoleAssignment = Schema.Struct({ + "object": Schema.Literal("group.role").annotate({ "description": "Always `group.role`." }), + "group": Group, + "role": Role +}).annotate({ "description": "Role assignment linking a group to a role.", "identifier": "GroupRoleAssignment" }) +export type PublicRoleListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "next": string | null +} +export const PublicRoleListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), + "data": Schema.Array(Role).annotate({ "description": "Roles returned in the current page." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether more roles are available when paginating." }), + "next": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "Cursor to fetch the next page of results, or `null` when there are no additional roles." + }) }).annotate({ - "description": - "Returned when a conversation item is finalized.\n\nThe event will include the full content of the Item except for audio data, which can be retrieved separately with a `conversation.item.retrieve` event if needed.\n" + "description": "Paginated list of roles available on an organization or project.", + "identifier": "PublicRoleListResource" }) -export type RealtimeServerEventConversationItemRetrieved = { - readonly "event_id": string - readonly "type": "conversation.item.retrieved" - readonly "item": RealtimeConversationItem +export type UserListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "next": string | null } -export const RealtimeServerEventConversationItemRetrieved = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("conversation.item.retrieved").annotate({ - "description": "The event type, must be `conversation.item.retrieved`." - }), - "item": RealtimeConversationItem +export const UserListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), + "data": Schema.Array(GroupUser).annotate({ "description": "Users in the current page." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether more users are available when paginating." }), + "next": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "Cursor to fetch the next page of results, or `null` when no further users are available." + }) }).annotate({ - "description": - "Returned when a conversation item is retrieved with `conversation.item.retrieve`. This is provided as a way to fetch the server's representation of an item, for example to get access to the post-processed audio data after noise cancellation and VAD. It includes the full content of the Item, including audio data.\n" + "description": "Paginated list of user objects returned when inspecting group membership.", + "identifier": "UserListResource" }) -export type RealtimeServerEventResponseOutputItemAdded = { - readonly "event_id": string - readonly "type": "response.output_item.added" - readonly "response_id": string - readonly "output_index": number - readonly "item": RealtimeConversationItem +export type InviteListResponse = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean } -export const RealtimeServerEventResponseOutputItemAdded = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.output_item.added").annotate({ - "description": "The event type, must be `response.output_item.added`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the Response to which the item belongs." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the Response." }).check( - Schema.isInt() +export const InviteListResponse = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`" }), + "data": Schema.Array(Invite), + "first_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The first `invite_id` in the retrieved `list`" + }) ), - "item": RealtimeConversationItem -}).annotate({ "description": "Returned when a new Item is created during Response generation." }) -export type RealtimeServerEventResponseOutputItemDone = { - readonly "event_id": string - readonly "type": "response.output_item.done" - readonly "response_id": string - readonly "output_index": number - readonly "item": RealtimeConversationItem -} -export const RealtimeServerEventResponseOutputItemDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.output_item.done").annotate({ - "description": "The event type, must be `response.output_item.done`." - }), - "response_id": Schema.String.annotate({ "description": "The ID of the Response to which the item belongs." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item in the Response." }).check( - Schema.isInt() + "last_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The last `invite_id` in the retrieved `list`" + }) ), - "item": RealtimeConversationItem -}).annotate({ - "description": - "Returned when an Item is done streaming. Also emitted when a Response is \ninterrupted, incomplete, or cancelled.\n" -}) -export type AssistantObject = { + "has_more": Schema.Boolean.annotate({ + "description": "The `has_more` property is used for pagination to indicate there are additional results." + }) +}).annotate({ "identifier": "InviteListResponse" }) +export type Project = { readonly "id": string - readonly "object": "assistant" + readonly "object": "organization.project" + readonly "name"?: string | null readonly "created_at": number - readonly "name": string | null - readonly "description": string | null - readonly "model": string - readonly "instructions": string | null - readonly "tools": ReadonlyArray - readonly "tool_resources"?: { - readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } - readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } - } | null - readonly "metadata": Metadata - readonly "temperature"?: number | null - readonly "top_p"?: number | null - readonly "response_format"?: AssistantsApiResponseFormatOption | null + readonly "archived_at"?: number | null + readonly "status"?: string | null + readonly "external_key_id"?: string | null + readonly "residency"?: PublicProjectResidency } -export const AssistantObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), - "object": Schema.Literal("assistant").annotate({ "description": "The object type, which is always `assistant`." }), +export const Project = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "object": Schema.Literal("organization.project").annotate({ + "description": "The object type, which is always `organization.project`" + }), + "name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The name of the project. This appears in reporting." + }) + ), "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the assistant was created.", + "description": "The Unix timestamp (in seconds) of when the project was created.", "format": "unixtime" - }).check(Schema.isInt()), - "name": Schema.Union([ - Schema.String.annotate({ "description": "The name of the assistant. The maximum length is 256 characters.\n" }) - .check(Schema.isMaxLength(256)), - Schema.Null - ]), - "description": Schema.Union([ - Schema.String.annotate({ - "description": "The description of the assistant. The maximum length is 512 characters.\n" - }).check(Schema.isMaxLength(512)), - Schema.Null - ]), - "model": Schema.String.annotate({ - "description": - "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models) for descriptions of them.\n" - }), - "instructions": Schema.Union([ - Schema.String.annotate({ - "description": "The system instructions that the assistant uses. The maximum length is 256,000 characters.\n" - }).check(Schema.isMaxLength(256000)), - Schema.Null - ]), - "tools": Schema.Array( - Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) - ).annotate({ - "description": - "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`.\n" - }).check(Schema.isMaxLength(128)), - "tool_resources": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "code_interpreter": Schema.optionalKey(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs made available to the `code_interpreter`` tool. There can be a maximum of 20 files associated with the tool.\n" - }).check(Schema.isMaxLength(20)) - ) - })), - "file_search": Schema.optionalKey(Schema.Struct({ - "vector_store_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "The ID of the [vector store](/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" - }).check(Schema.isMaxLength(1)) - ) - })) - }).annotate({ - "description": - "A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" - }), - Schema.Null - ])), - "metadata": Metadata, - "temperature": Schema.optionalKey( + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "archived_at": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), + "description": "The Unix timestamp (in seconds) of when the project was archived or `null`.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ), - "top_p": Schema.optionalKey(Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - Schema.Null - ])), - "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) -}).annotate({ "title": "Assistant", "description": "Represents an `assistant` that can call the model and use tools." }) -export type CreateAssistantRequest = { - readonly "model": string | AssistantSupportedModels - readonly "name"?: string | null - readonly "description"?: string | null - readonly "instructions"?: string | null - readonly "reasoning_effort"?: ReasoningEffort - readonly "tools"?: ReadonlyArray - readonly "tool_resources"?: { - readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } - readonly "file_search"?: { - readonly "vector_store_ids": ReadonlyArray - readonly "vector_stores"?: ReadonlyArray< - { - readonly "file_ids"?: ReadonlyArray - readonly "chunking_strategy"?: { readonly "type": "auto" } | { - readonly "type": "static" - readonly "static": { readonly "max_chunk_size_tokens": number; readonly "chunk_overlap_tokens": number } - } - readonly "metadata"?: Metadata - } - > - } | { - readonly "vector_stores": ReadonlyArray< - { - readonly "file_ids"?: ReadonlyArray - readonly "chunking_strategy"?: { readonly "type": "auto" } | { - readonly "type": "static" - readonly "static": { readonly "max_chunk_size_tokens": number; readonly "chunk_overlap_tokens": number } - } - readonly "metadata"?: Metadata - } - > - readonly "vector_store_ids"?: ReadonlyArray - } - } | null - readonly "metadata"?: Metadata - readonly "temperature"?: number | null - readonly "top_p"?: number | null - readonly "response_format"?: AssistantsApiResponseFormatOption | null + "status": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "`active` or `archived`" }) + ), + "external_key_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The external key associated with the project." + }) + ), + "residency": Schema.optionalKey( + Schema.suspend((): Schema.Codec => PublicProjectResidency).annotate({ + "description": "The residency configuration for the project." + }) + ) +}).annotate({ "description": "Represents an individual project.", "identifier": "Project" }) +export type ProjectCreateRequest = { + readonly "name": string + readonly "geography"?: string | null + readonly "residency"?: PublicProjectResidency | null + readonly "external_key_id"?: string | null } -export const CreateAssistantRequest = Schema.Struct({ - "model": Schema.Union([Schema.String, AssistantSupportedModels]).annotate({ - "description": - "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models) for descriptions of them.\n" - }), - "name": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The name of the assistant. The maximum length is 256 characters.\n" }) - .check(Schema.isMaxLength(256)), - Schema.Null - ]) +export const ProjectCreateRequest = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The friendly name of the project, this name appears in reports." }), + "geography": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "Create the project with the specified data residency region. Your organization must have access to Data residency functionality in order to use. See [data residency controls](https://developers.openai.com/api/docs/guides/your-data#data-residency-controls) to review the functionality and limitations of setting this field.\nDeprecated: use `residency` instead. Do not provide both `geography` and `residency`." + }) ), - "description": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "The description of the assistant. The maximum length is 512 characters.\n" - }).check(Schema.isMaxLength(512)), - Schema.Null - ]) + "residency": Schema.optionalKey( + Schema.Union([PublicProjectResidency, Schema.Null]).annotate({ + "description": + "Create the project with the specified residency configuration. Your organization must have access to the requested residency configuration in order to use it. See [data residency controls](https://developers.openai.com/api/docs/guides/your-data#data-residency-controls) to review the functionality and limitations of setting this field." + }) ), - "instructions": Schema.optionalKey( + "external_key_id": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "External key ID to associate with the project." + }) + ) +}).annotate({ "identifier": "ProjectCreateRequest" }) +export type ProjectApiKey = { + readonly "object": "organization.project.api_key" + readonly "redacted_value": string + readonly "name": string + readonly "created_at": number + readonly "expires_at"?: number | null + readonly "last_used_at": number | null + readonly "id": string + readonly "owner_project_access": "active" | "inactive" + readonly "owner": { + readonly "type"?: "user" | "service_account" + readonly "user"?: ProjectApiKeyOwnerUser + readonly "service_account"?: ProjectApiKeyOwnerServiceAccount + } +} +export const ProjectApiKey = Schema.Struct({ + "object": Schema.Literal("organization.project.api_key").annotate({ + "description": "The object type, which is always `organization.project.api_key`" + }), + "redacted_value": Schema.String.annotate({ "description": "The redacted value of the API key" }), + "name": Schema.String.annotate({ "description": "The name of the API key" }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the API key was created", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "expires_at": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ - "description": "The system instructions that the assistant uses. The maximum length is 256,000 characters.\n" - }).check(Schema.isMaxLength(256000)), + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null - ]) - ), - "reasoning_effort": Schema.optionalKey(ReasoningEffort), - "tools": Schema.optionalKey( - Schema.Array( - Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) - ).annotate({ - "description": - "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`.\n" - }).check(Schema.isMaxLength(128)) + ]).annotate({ + "description": "The Unix timestamp (in seconds) when the API key expires, or null if it does not expire." + }) ), - "tool_resources": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "code_interpreter": Schema.optionalKey(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" - }).check(Schema.isMaxLength(20)) - ) - })), - "file_search": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "vector_store_ids": Schema.Array(Schema.String).annotate({ - "description": - "The [vector store](/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" - }).check(Schema.isMaxLength(1)), - "vector_stores": Schema.optionalKey( - Schema.Array(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files.\n" - }).check(Schema.isMaxLength(100000000)) - ), - "chunking_strategy": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }) - .annotate({ - "title": "Auto Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }), - Schema.Struct({ - "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), - "static": Schema.Struct({ - "max_chunk_size_tokens": Schema.Number.annotate({ - "description": - "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(100)).check( - Schema.isLessThanOrEqualTo(4096) - ), - "chunk_overlap_tokens": Schema.Number.annotate({ - "description": - "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" - }).check(Schema.isInt()) - }) - }).annotate({ - "title": "Static Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }) - ], { mode: "oneOf" }) - ), - "metadata": Schema.optionalKey(Metadata) - })).annotate({ - "description": - "A helper to create a [vector store](/docs/api-reference/vector-stores/object) with file_ids and attach it to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" - }).check(Schema.isMaxLength(1)) - ) - }), - Schema.Struct({ - "vector_stores": Schema.Array(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files.\n" - }).check(Schema.isMaxLength(100000000)) - ), - "chunking_strategy": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }) - .annotate({ - "title": "Auto Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }), - Schema.Struct({ - "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), - "static": Schema.Struct({ - "max_chunk_size_tokens": Schema.Number.annotate({ - "description": - "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(100)).check( - Schema.isLessThanOrEqualTo(4096) - ), - "chunk_overlap_tokens": Schema.Number.annotate({ - "description": - "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" - }).check(Schema.isInt()) - }) - }).annotate({ - "title": "Static Chunking Strategy", - "description": - "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." - }) - ], { mode: "oneOf" }) - ), - "metadata": Schema.optionalKey(Metadata) - })).annotate({ - "description": - "A helper to create a [vector store](/docs/api-reference/vector-stores/object) with file_ids and attach it to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" - }).check(Schema.isMaxLength(1)), - "vector_store_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "The [vector store](/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" - }).check(Schema.isMaxLength(1)) - ) - }) - ], { mode: "oneOf" })) - }).annotate({ - "description": - "A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" - }), - Schema.Null - ])), - "metadata": Schema.optionalKey(Metadata), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), - Schema.Null - ]) - ), - "top_p": Schema.optionalKey(Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), + "last_used_at": Schema.Union([ + Schema.Number.annotate({ "format": "unixtime" }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null - ])), - "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) -}) -export type CreateRunRequest = { - readonly "assistant_id": string - readonly "model"?: string | AssistantSupportedModels | null - readonly "reasoning_effort"?: ReasoningEffort - readonly "instructions"?: string | null - readonly "additional_instructions"?: string | null - readonly "additional_messages"?: ReadonlyArray< - { - readonly "role": "user" | "assistant" - readonly "content": - | string - | ReadonlyArray - readonly "attachments"?: - | ReadonlyArray< - { - readonly "file_id"?: string - readonly "tools"?: ReadonlyArray - } - > - | null - readonly "metadata"?: Metadata - } - > - readonly "tools"?: ReadonlyArray - readonly "metadata"?: Metadata - readonly "temperature"?: number - readonly "top_p"?: number - readonly "stream"?: boolean | null - readonly "max_prompt_tokens"?: number - readonly "max_completion_tokens"?: number - readonly "truncation_strategy"?: { - readonly "type": "auto" | "last_messages" - readonly "last_messages"?: number | null - } - readonly "tool_choice"?: "none" | "auto" | "required" | { - readonly "type": "function" | "code_interpreter" | "file_search" - readonly "function"?: { readonly "name": string } - } - readonly "parallel_tool_calls"?: ParallelToolCalls - readonly "response_format"?: AssistantsApiResponseFormatOption | null + ]).annotate({ "description": "The Unix timestamp (in seconds) of when the API key was last used." }), + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints" }), + "owner_project_access": Schema.Literals(["active", "inactive"]).annotate({ + "description": "Whether the API key's owner currently has effective access to the project." + }), + "owner": Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literals(["user", "service_account"]).annotate({ "description": "`user` or `service_account`" }) + ), + "user": Schema.optionalKey(ProjectApiKeyOwnerUser), + "service_account": Schema.optionalKey(ProjectApiKeyOwnerServiceAccount) + }) +}).annotate({ "description": "Represents an individual API key in a project.", "identifier": "ProjectApiKey" }) +export type ListProjectCertificatesResponse = { + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean + readonly "object": "list" } -export const CreateRunRequest = Schema.Struct({ - "assistant_id": Schema.String.annotate({ - "description": "The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run." +export const ListProjectCertificatesResponse = Schema.Struct({ + "data": Schema.Array(OrganizationProjectCertificate), + "first_id": Schema.Union([Schema.String, Schema.Null]), + "last_id": Schema.Union([Schema.String, Schema.Null]), + "has_more": Schema.Boolean, + "object": Schema.Literal("list") +}).annotate({ "identifier": "ListProjectCertificatesResponse" }) +export type OrganizationProjectCertificateActivationResponse = { + readonly "object": "organization.project.certificate.activation" + readonly "data": ReadonlyArray +} +export const OrganizationProjectCertificateActivationResponse = Schema.Struct({ + "object": Schema.Literal("organization.project.certificate.activation").annotate({ + "description": "The project certificate activation result type." }), - "model": Schema.optionalKey( - Schema.Union([ - Schema.Union([Schema.String, AssistantSupportedModels]).annotate({ - "description": - "The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used." - }), - Schema.Null - ]) - ), - "reasoning_effort": Schema.optionalKey(ReasoningEffort), - "instructions": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis." + "data": Schema.Array(OrganizationProjectCertificate) +}).annotate({ "identifier": "OrganizationProjectCertificateActivationResponse" }) +export type OrganizationProjectCertificateDeactivationResponse = { + readonly "object": "organization.project.certificate.deactivation" + readonly "data": ReadonlyArray +} +export const OrganizationProjectCertificateDeactivationResponse = Schema.Struct({ + "object": Schema.Literal("organization.project.certificate.deactivation").annotate({ + "description": "The project certificate deactivation result type." + }), + "data": Schema.Array(OrganizationProjectCertificate) +}).annotate({ "identifier": "OrganizationProjectCertificateDeactivationResponse" }) +export type ProjectGroupListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "next": string | null +} +export const ProjectGroupListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), + "data": Schema.Array(ProjectGroup).annotate({ + "description": "Project group memberships returned in the current page." + }), + "has_more": Schema.Boolean.annotate({ "description": "Whether additional project group memberships are available." }), + "next": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "Cursor to fetch the next page of results, or `null` when there are no more results." + }) +}).annotate({ + "description": "Paginated list of groups that have access to a project.", + "identifier": "ProjectGroupListResource" +}) +export type ProjectHostedToolPermissions = { + readonly "file_search": HostedToolPermission + readonly "web_search": HostedToolPermission + readonly "image_generation": HostedToolPermission + readonly "mcp": HostedToolPermission + readonly "code_interpreter": HostedToolPermission +} +export const ProjectHostedToolPermissions = Schema.Struct({ + "file_search": HostedToolPermission, + "web_search": HostedToolPermission, + "image_generation": HostedToolPermission, + "mcp": HostedToolPermission, + "code_interpreter": HostedToolPermission +}).annotate({ + "description": "Represents hosted tool permissions for a project.", + "identifier": "ProjectHostedToolPermissions" +}) +export type ProjectHostedToolPermissionsUpdateRequest = { + readonly "file_search"?: HostedToolPermissionUpdate | null + readonly "web_search"?: HostedToolPermissionUpdate | null + readonly "image_generation"?: HostedToolPermissionUpdate | null + readonly "mcp"?: HostedToolPermissionUpdate | null + readonly "code_interpreter"?: HostedToolPermissionUpdate | null +} +export const ProjectHostedToolPermissionsUpdateRequest = Schema.Struct({ + "file_search": Schema.optionalKey( + Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ + "description": "The file search permission update." }) ), - "additional_instructions": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions." + "web_search": Schema.optionalKey( + Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ + "description": "The web search permission update." }) ), - "additional_messages": Schema.optionalKey(Schema.Union([ - Schema.Array(Schema.Struct({ - "role": Schema.Literals(["user", "assistant"]).annotate({ - "description": - "The role of the entity that is creating the message. Allowed values include:\n- `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages.\n- `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation.\n" - }), - "content": Schema.Union([ - Schema.String.annotate({ "title": "Text content", "description": "The text contents of the message." }), - Schema.Array( - Schema.Union([MessageContentImageFileObject, MessageContentImageUrlObject, MessageRequestContentTextObject], { - mode: "oneOf" - }) - ).annotate({ - "title": "Array of content parts", - "description": - "An array of content parts with a defined type, each can be of type `text` or images can be passed with `image_url` or `image_file`. Image types are only supported on [Vision-compatible models](/docs/models)." - }).check(Schema.isMinLength(1)) - ], { mode: "oneOf" }), - "attachments": Schema.optionalKey(Schema.Union([ - Schema.Array(Schema.Struct({ - "file_id": Schema.optionalKey( - Schema.String.annotate({ "description": "The ID of the file to attach to the message." }) - ), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([AssistantToolsCode, AssistantToolsFileSearchTypeOnly], { mode: "oneOf" })) - .annotate({ "description": "The tools to add this file to." }) - ) - })).annotate({ - "description": "A list of files attached to the message, and the tools they should be added to." - }), - Schema.Null - ])), - "metadata": Schema.optionalKey(Metadata) - })).annotate({ "description": "Adds additional messages to the thread before creating the run." }) - ])), - "tools": Schema.optionalKey( - Schema.Union([ - Schema.Array( - Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) - ).check( - Schema.isMaxLength(20, { - "description": - "Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis." - }) - ) - ]) + "image_generation": Schema.optionalKey( + Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ + "description": "The image generation permission update." + }) ), - "metadata": Schema.optionalKey(Metadata), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(2)], { - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" - }) - ) - ]) + "mcp": Schema.optionalKey( + Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ "description": "The MCP permission update." }) ), - "top_p": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(1)], { - "description": - "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" - }) - ) - ]) - ), - "stream": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": - "If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message.\n" + "code_interpreter": Schema.optionalKey( + Schema.Union([HostedToolPermissionUpdate, Schema.Null]).annotate({ + "description": "The code interpreter permission update." }) + ) +}).annotate({ "identifier": "ProjectHostedToolPermissionsUpdateRequest" }) +export type ProjectRateLimitListResponse = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean +} +export const ProjectRateLimitListResponse = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(ProjectRateLimit), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ProjectRateLimitListResponse" }) +export type ProjectServiceAccountListResponse = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean +} +export const ProjectServiceAccountListResponse = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(ProjectServiceAccount), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ProjectServiceAccountListResponse" }) +export type ProjectServiceAccountCreateResponse = { + readonly "object": "organization.project.service_account" + readonly "id": string + readonly "name": string + readonly "role": "member" | "none" + readonly "created_at": number + readonly "api_key": ProjectServiceAccountApiKey | null +} +export const ProjectServiceAccountCreateResponse = Schema.Struct({ + "object": Schema.Literal("organization.project.service_account"), + "id": Schema.String, + "name": Schema.String, + "role": Schema.Literals(["member", "none"]).annotate({ + "description": + "Service accounts created with default project membership have role `member`. Accounts created with `create_service_account_only` have role `none`.\n" + }), + "created_at": Schema.Number.annotate({ "format": "unixtime" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "max_prompt_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(256)], { - "description": - "The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info.\n" - }) - ) - ]) + "api_key": Schema.Union([ProjectServiceAccountApiKey, Schema.Null]) +}).annotate({ "identifier": "ProjectServiceAccountCreateResponse" }) +export type ProjectSpendAlert = { + readonly "id": string + readonly "object": "project.spend_alert" + readonly "threshold_amount": number + readonly "currency": "USD" + readonly "interval": "month" + readonly "notification_channel": SpendAlertNotificationChannel +} +export const ProjectSpendAlert = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("project.spend_alert").annotate({ + "description": "The object type, which is always `project.spend_alert`." + }), + "threshold_amount": Schema.Number.annotate({ "description": "The alert threshold amount, in cents." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "max_completion_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(256)], { - "description": - "The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info.\n" - }) - ) - ]) + "currency": Schema.Literal("USD").annotate({ "description": "The currency for the threshold amount." }), + "interval": Schema.Literal("month").annotate({ + "description": "The time interval for evaluating spend against the threshold." + }), + "notification_channel": SpendAlertNotificationChannel +}).annotate({ + "description": "Represents a spend alert configured at the project level.", + "identifier": "ProjectSpendAlert" +}) +export type CreateSpendAlertBody = { + readonly "threshold_amount": number + readonly "currency": "USD" + readonly "interval": "month" + readonly "notification_channel": SpendAlertNotificationChannel +} +export const CreateSpendAlertBody = Schema.Struct({ + "threshold_amount": Schema.Number.annotate({ "description": "The alert threshold amount, in cents." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })), + "currency": Schema.Literal("USD").annotate({ "description": "The currency for the threshold amount." }), + "interval": Schema.Literal("month").annotate({ + "description": "The time interval for evaluating spend against the threshold." + }), + "notification_channel": SpendAlertNotificationChannel +}).annotate({ + "description": "Parameters for creating or updating a spend alert.", + "identifier": "CreateSpendAlertBody" +}) +export type OrganizationSpendAlert = { + readonly "id": string + readonly "object": "organization.spend_alert" + readonly "threshold_amount": number + readonly "currency": "USD" + readonly "interval": "month" + readonly "notification_channel": SpendAlertNotificationChannel +} +export const OrganizationSpendAlert = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("organization.spend_alert").annotate({ + "description": "The object type, which is always `organization.spend_alert`." + }), + "threshold_amount": Schema.Number.annotate({ "description": "The alert threshold amount, in cents." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "truncation_strategy": Schema.optionalKey(Schema.Union([ + "currency": Schema.Literal("USD").annotate({ "description": "The currency for the threshold amount." }), + "interval": Schema.Literal("month").annotate({ + "description": "The time interval for evaluating spend against the threshold." + }), + "notification_channel": SpendAlertNotificationChannel +}).annotate({ + "description": "Represents a spend alert configured at the organization level.", + "identifier": "OrganizationSpendAlert" +}) +export type ProjectUserListResponse = { + readonly "object": string + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean +} +export const ProjectUserListResponse = Schema.Struct({ + "object": Schema.String, + "data": Schema.Array(ProjectUser), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ProjectUserListResponse" }) +export type UserListResponse = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean +} +export const UserListResponse = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(User), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "UserListResponse" }) +export type UserRoleAssignment = { readonly "object": "user.role"; readonly "user": User; readonly "role": Role } +export const UserRoleAssignment = Schema.Struct({ + "object": Schema.Literal("user.role").annotate({ "description": "Always `user.role`." }), + "user": User, + "role": Role +}).annotate({ "description": "Role assignment linking a user to a role.", "identifier": "UserRoleAssignment" }) +export type RealtimeTranscriptionSessionCreateRequest = { + readonly "turn_detection"?: { + readonly "type"?: "server_vad" + readonly "threshold"?: number + readonly "prefix_padding_ms"?: number + readonly "silence_duration_ms"?: number + } + readonly "input_audio_noise_reduction"?: + | null + | { readonly "type"?: NoiseReductionType } & { readonly [x: string]: Schema.Json } + readonly "input_audio_format"?: "pcm16" | "g711_ulaw" | "g711_alaw" + readonly "input_audio_transcription"?: AudioTranscription + readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> +} +export const RealtimeTranscriptionSessionCreateRequest = Schema.Struct({ + "turn_detection": Schema.optionalKey( Schema.Struct({ - "type": Schema.Literals(["auto", "last_messages"]).annotate({ - "description": - "The truncation strategy to use for the thread. The default is `auto`. If set to `last_messages`, the thread will be truncated to the n most recent messages in the thread. When set to `auto`, messages in the middle of the thread will be dropped to fit the context length of the model, `max_prompt_tokens`." - }), - "last_messages": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "The number of most recent messages from the thread when constructing the context for the run." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), - Schema.Null - ]) + "type": Schema.optionalKey( + Schema.Literal("server_vad").annotate({ + "description": + "Type of turn detection. Only `server_vad` is currently supported for transcription sessions.\n" + }) + ), + "threshold": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "prefix_padding_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "silence_duration_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ) }).annotate({ - "title": "Thread Truncation Controls", "description": - "Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run." + "Configuration for turn detection. Can be set to `null` to turn off. Server VAD means that the model will detect the start and end of speech based on audio volume and respond at the end of user speech.\n" }) - ])), - "tool_choice": Schema.optionalKey( + ), + "input_audio_noise_reduction": Schema.optionalKey( Schema.Union([ - Schema.Union([Schema.Literal("none"), Schema.Literal("auto"), Schema.Literal("required")]).annotate({ - "description": - "`none` means the model will not call any tools and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user.\n" - }), - Schema.Union([ - Schema.Struct({ - "type": Schema.Literals(["function", "code_interpreter", "file_search"]).annotate({ - "description": "The type of the tool. If type is `function`, the function name must be set" - }), - "function": Schema.optionalKey( - Schema.Struct({ "name": Schema.String.annotate({ "description": "The name of the function to call." }) }) - ) - }).annotate({ - "description": "Specifies a tool the model should use. Use to force the model to call a specific tool." - }) + Schema.Null, + Schema.StructWithRest(Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }), [ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) ]) - ], { mode: "oneOf" }).annotate({ + ]).annotate({ "description": - "Controls which (if any) tool is called by the model.\n`none` means the model will not call any tools and instead generates a message.\n`auto` is the default value and means the model can pick between generating a message or calling one or more tools.\n`required` means the model must call one or more tools before responding to the user.\nSpecifying a particular tool like `{\"type\": \"file_search\"}` or `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.\n" + "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" }) ), - "parallel_tool_calls": Schema.optionalKey(ParallelToolCalls), - "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) -}) -export type CreateThreadAndRunRequest = { - readonly "assistant_id": string - readonly "thread"?: CreateThreadRequest - readonly "model"?: - | string - | "gpt-5" - | "gpt-5-mini" - | "gpt-5-nano" - | "gpt-5-2025-08-07" - | "gpt-5-mini-2025-08-07" - | "gpt-5-nano-2025-08-07" - | "gpt-4.1" - | "gpt-4.1-mini" - | "gpt-4.1-nano" - | "gpt-4.1-2025-04-14" - | "gpt-4.1-mini-2025-04-14" - | "gpt-4.1-nano-2025-04-14" - | "gpt-4o" - | "gpt-4o-2024-11-20" - | "gpt-4o-2024-08-06" - | "gpt-4o-2024-05-13" - | "gpt-4o-mini" - | "gpt-4o-mini-2024-07-18" - | "gpt-4.5-preview" - | "gpt-4.5-preview-2025-02-27" - | "gpt-4-turbo" - | "gpt-4-turbo-2024-04-09" - | "gpt-4-0125-preview" - | "gpt-4-turbo-preview" - | "gpt-4-1106-preview" - | "gpt-4-vision-preview" - | "gpt-4" - | "gpt-4-0314" - | "gpt-4-0613" - | "gpt-4-32k" - | "gpt-4-32k-0314" - | "gpt-4-32k-0613" - | "gpt-3.5-turbo" - | "gpt-3.5-turbo-16k" - | "gpt-3.5-turbo-0613" - | "gpt-3.5-turbo-1106" - | "gpt-3.5-turbo-0125" - | "gpt-3.5-turbo-16k-0613" - | null - readonly "instructions"?: string | null - readonly "tools"?: ReadonlyArray - readonly "tool_resources"?: { - readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } - readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } - } - readonly "metadata"?: Metadata - readonly "temperature"?: number - readonly "top_p"?: number - readonly "stream"?: boolean | null - readonly "max_prompt_tokens"?: number - readonly "max_completion_tokens"?: number - readonly "truncation_strategy"?: { - readonly "type": "auto" | "last_messages" - readonly "last_messages"?: number | null - } - readonly "tool_choice"?: "none" | "auto" | "required" | { - readonly "type": "function" | "code_interpreter" | "file_search" - readonly "function"?: { readonly "name": string } - } - readonly "parallel_tool_calls"?: ParallelToolCalls - readonly "response_format"?: AssistantsApiResponseFormatOption | null -} -export const CreateThreadAndRunRequest = Schema.Struct({ - "assistant_id": Schema.String.annotate({ - "description": "The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run." - }), - "thread": Schema.optionalKey(CreateThreadRequest), - "model": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.String, - Schema.Literals([ - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-5-2025-08-07", - "gpt-5-mini-2025-08-07", - "gpt-5-nano-2025-08-07", - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4.1-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "gpt-4o", - "gpt-4o-2024-11-20", - "gpt-4o-2024-08-06", - "gpt-4o-2024-05-13", - "gpt-4o-mini", - "gpt-4o-mini-2024-07-18", - "gpt-4.5-preview", - "gpt-4.5-preview-2025-02-27", - "gpt-4-turbo", - "gpt-4-turbo-2024-04-09", - "gpt-4-0125-preview", - "gpt-4-turbo-preview", - "gpt-4-1106-preview", - "gpt-4-vision-preview", - "gpt-4", - "gpt-4-0314", - "gpt-4-0613", - "gpt-4-32k", - "gpt-4-32k-0314", - "gpt-4-32k-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0613", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-0125", - "gpt-3.5-turbo-16k-0613" - ]) - ]).annotate({ - "description": - "The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used." - }), - Schema.Null - ]) + "input_audio_format": Schema.optionalKey( + Schema.Literals(["pcm16", "g711_ulaw", "g711_alaw"]).annotate({ + "description": + "The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\nFor `pcm16`, input audio must be 16-bit PCM at a 24kHz sample rate,\nsingle channel (mono), and little-endian byte order.\n" + }) ), - "instructions": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ + "input_audio_transcription": Schema.optionalKey( + Schema.suspend((): Schema.Codec => AudioTranscription).annotate({ "description": - "Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis." + "Configuration for input audio transcription. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" }) ), - "tools": Schema.optionalKey( - Schema.Union([ - Schema.Array( - Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) - ).check( - Schema.isMaxLength(20, { - "description": - "Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis." - }) - ) - ]) - ), - "tool_resources": Schema.optionalKey(Schema.Union([ + "include": Schema.optionalKey( + Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ + "description": + "The set of items to include in the transcription. Current available items are:\n`item.input_audio_transcription.logprobs`\n" + }) + ) +}).annotate({ + "title": "Realtime transcription session configuration", + "description": "Realtime transcription session object configuration.", + "identifier": "RealtimeTranscriptionSessionCreateRequest" +}) +export type RealtimeTranslationSessionCreateRequest = { + readonly "model": string + readonly "audio"?: { + readonly "input"?: { + readonly "transcription"?: { readonly "model": string } | null + readonly "noise_reduction"?: { readonly "type": NoiseReductionType } | null + } + readonly "output"?: { readonly "language"?: string } + } +} +export const RealtimeTranslationSessionCreateRequest = Schema.Struct({ + "model": Schema.String.annotate({ "description": "The Realtime translation model used for this session.\n" }), + "audio": Schema.optionalKey( Schema.Struct({ - "code_interpreter": Schema.optionalKey(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [file](/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" - }).check(Schema.isMaxLength(20)) + "input": Schema.optionalKey(Schema.Struct({ + "transcription": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ + "model": Schema.String.annotate({ + "description": "The transcription model to use for source transcript deltas." + }) + }).annotate({ + "description": + "Optional source-language transcription. When configured, the server emits\n`session.input_transcript.delta` events. Translation itself still runs from\nthe input audio stream.\n" + }), + Schema.Null + ]) + ), + "noise_reduction": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ "type": NoiseReductionType }).annotate({ + "description": "Optional input noise reduction. Set to `null` to disable it.\n" + }), + Schema.Null + ]) ) })), - "file_search": Schema.optionalKey(Schema.Struct({ - "vector_store_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "The ID of the [vector store](/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" - }).check(Schema.isMaxLength(1)) - ) - })) - }).annotate({ - "description": - "A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" - }) - ])), - "metadata": Schema.optionalKey(Metadata), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(2)], { - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" - }) - ) - ]) - ), - "top_p": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(1)], { - "description": - "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" - }) - ) - ]) - ), - "stream": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": - "If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message.\n" - }) - ), - "max_prompt_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(256)], { - "description": - "The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info.\n" - }) - ) - ]) - ), - "max_completion_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(256)], { - "description": - "The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info.\n" + "output": Schema.optionalKey( + Schema.Struct({ + "language": Schema.optionalKey( + Schema.String.annotate({ + "description": "Target language for translated output audio and transcript deltas.\n" + }) + ) }) ) - ]) - ), - "truncation_strategy": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "type": Schema.Literals(["auto", "last_messages"]).annotate({ - "description": - "The truncation strategy to use for the thread. The default is `auto`. If set to `last_messages`, the thread will be truncated to the n most recent messages in the thread. When set to `auto`, messages in the middle of the thread will be dropped to fit the context length of the model, `max_prompt_tokens`." - }), - "last_messages": Schema.optionalKey( + }).annotate({ "description": "Configuration for translation input and output audio.\n" }) + ) +}).annotate({ + "title": "Realtime translation session configuration", + "description": + "Realtime translation session configuration. Translation sessions stream source\naudio in and translated audio plus transcript deltas out continuously.\n", + "identifier": "RealtimeTranslationSessionCreateRequest" +}) +export type RealtimeTranslationSession = { + readonly "id": string + readonly "type": "translation" + readonly "expires_at": number + readonly "model": string + readonly "audio": { + readonly "input"?: { + readonly "transcription"?: { readonly "model": string } | null + readonly "noise_reduction"?: { readonly "type": NoiseReductionType } | null + } + readonly "output"?: { readonly "language"?: string } + } +} +export const RealtimeTranslationSession = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" + }), + "type": Schema.Literal("translation").annotate({ + "description": "The session type. Always `translation` for Realtime translation sessions.\n" + }), + "expires_at": Schema.Number.annotate({ + "description": "Expiration timestamp for the session, in seconds since epoch.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "model": Schema.String.annotate({ + "description": + "The Realtime translation model used for this session. This field is set at\nsession creation and cannot be changed with `session.update`.\n" + }), + "audio": Schema.Struct({ + "input": Schema.optionalKey(Schema.Struct({ + "transcription": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ + Schema.Struct({ + "model": Schema.String.annotate({ + "description": "The transcription model used for source transcript deltas." + }) + }).annotate({ "description": - "The number of most recent messages from the thread when constructing the context for the run." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), + "Optional source-language transcription. When configured, the server emits\n`session.input_transcript.delta` events. Translation itself still runs from\nthe input audio stream.\n" + }), Schema.Null ]) - ) - }).annotate({ - "title": "Thread Truncation Controls", - "description": - "Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run." - }) - ])), - "tool_choice": Schema.optionalKey( - Schema.Union([ - Schema.Union([Schema.Literal("none"), Schema.Literal("auto"), Schema.Literal("required")]).annotate({ - "description": - "`none` means the model will not call any tools and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user.\n" - }), - Schema.Union([ - Schema.Struct({ - "type": Schema.Literals(["function", "code_interpreter", "file_search"]).annotate({ - "description": "The type of the tool. If type is `function`, the function name must be set" + ), + "noise_reduction": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ "type": NoiseReductionType }).annotate({ + "description": "Optional input noise reduction.\n" }), - "function": Schema.optionalKey( - Schema.Struct({ "name": Schema.String.annotate({ "description": "The name of the function to call." }) }) - ) - }).annotate({ - "description": "Specifies a tool the model should use. Use to force the model to call a specific tool." - }) - ]) - ], { mode: "oneOf" }).annotate({ - "description": - "Controls which (if any) tool is called by the model.\n`none` means the model will not call any tools and instead generates a message.\n`auto` is the default value and means the model can pick between generating a message or calling one or more tools.\n`required` means the model must call one or more tools before responding to the user.\nSpecifying a particular tool like `{\"type\": \"file_search\"}` or `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.\n" - }) - ), - "parallel_tool_calls": Schema.optionalKey(ParallelToolCalls), - "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) + Schema.Null + ]) + ) + })), + "output": Schema.optionalKey( + Schema.Struct({ + "language": Schema.optionalKey( + Schema.String.annotate({ + "description": "Target language for translated output audio and transcript deltas.\n" + }) + ) + }) + ) + }).annotate({ "description": "Configuration for translation input and output audio.\n" }) +}).annotate({ + "title": "Realtime translation session", + "description": + "A Realtime translation session. Translation sessions continuously translate input\naudio into the configured output language.\n", + "identifier": "RealtimeTranslationSession" }) -export type ModifyAssistantRequest = { - readonly "model"?: string | AssistantSupportedModels - readonly "reasoning_effort"?: ReasoningEffort - readonly "name"?: string | null - readonly "description"?: string | null - readonly "instructions"?: string | null - readonly "tools"?: ReadonlyArray - readonly "tool_resources"?: { - readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } - readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } - } | null - readonly "metadata"?: Metadata - readonly "temperature"?: number | null - readonly "top_p"?: number | null - readonly "response_format"?: AssistantsApiResponseFormatOption | null +export type RealtimeTranscriptionSessionCreateRequestGA = { + readonly "type": "transcription" + readonly "audio"?: { + readonly "input"?: { + readonly "format"?: RealtimeAudioFormats + readonly "transcription"?: AudioTranscription + readonly "noise_reduction"?: + | null + | { readonly "type"?: NoiseReductionType } & { readonly [x: string]: Schema.Json } + readonly "turn_detection"?: RealtimeTurnDetection + } + } + readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> } -export const ModifyAssistantRequest = Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([Schema.String, AssistantSupportedModels]).annotate({ +export const RealtimeTranscriptionSessionCreateRequestGA = Schema.Struct({ + "type": Schema.Literal("transcription").annotate({ + "description": "The type of session to create. Always `transcription` for transcription sessions.\n" + }), + "audio": Schema.optionalKey( + Schema.Struct({ + "input": Schema.optionalKey(Schema.Struct({ + "format": Schema.optionalKey(RealtimeAudioFormats), + "transcription": Schema.optionalKey( + Schema.suspend((): Schema.Codec => AudioTranscription).annotate({ + "description": + "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" + }) + ), + "noise_reduction": Schema.optionalKey( + Schema.Union([ + Schema.Null, + Schema.StructWithRest(Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }), [ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) + ]) + ]).annotate({ + "description": + "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" + }) + ), + "turn_detection": Schema.optionalKey(RealtimeTurnDetection) + })) + }).annotate({ "description": "Configuration for input and output audio.\n" }) + ), + "include": Schema.optionalKey( + Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ "description": - "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models) for descriptions of them.\n" + "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" }) - ), - "reasoning_effort": Schema.optionalKey(ReasoningEffort), - "name": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "The name of the assistant. The maximum length is 256 characters.\n" }) - .check(Schema.isMaxLength(256)), - Schema.Null - ]) - ), - "description": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "The description of the assistant. The maximum length is 512 characters.\n" - }).check(Schema.isMaxLength(512)), - Schema.Null - ]) - ), - "instructions": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "The system instructions that the assistant uses. The maximum length is 256,000 characters.\n" - }).check(Schema.isMaxLength(256000)), - Schema.Null - ]) - ), - "tools": Schema.optionalKey( - Schema.Array( - Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) - ).annotate({ - "description": - "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`.\n" - }).check(Schema.isMaxLength(128)) - ), - "tool_resources": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "code_interpreter": Schema.optionalKey(Schema.Struct({ - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "Overrides the list of [file](/docs/api-reference/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" - }).check(Schema.isMaxLength(20)) - ) - })), - "file_search": Schema.optionalKey(Schema.Struct({ - "vector_store_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "Overrides the [vector store](/docs/api-reference/vector-stores/object) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" - }).check(Schema.isMaxLength(1)) - ) - })) - }).annotate({ - "description": - "A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" - }), - Schema.Null - ])), - "metadata": Schema.optionalKey(Metadata), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), - Schema.Null - ]) - ), - "top_p": Schema.optionalKey(Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - Schema.Null - ])), - "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) + ) +}).annotate({ + "title": "Realtime transcription session configuration", + "description": "Realtime transcription session object configuration.", + "identifier": "RealtimeTranscriptionSessionCreateRequestGA" }) -export type RunObject = { +export type RealtimeReasoning = { readonly "effort"?: RealtimeReasoningEffort } +export const RealtimeReasoning = Schema.Struct({ "effort": Schema.optionalKey(RealtimeReasoningEffort) }).annotate({ + "title": "Realtime reasoning configuration", + "description": "Configuration for reasoning-capable Realtime models such as `gpt-realtime-2`.\n", + "identifier": "RealtimeReasoning" +}) +export type RealtimeTranscriptionSessionCreateResponseGA = { + readonly "type": "transcription" readonly "id": string - readonly "object": "thread.run" - readonly "created_at": number - readonly "thread_id": string - readonly "assistant_id": string - readonly "status": - | "queued" - | "in_progress" - | "requires_action" - | "cancelling" - | "cancelled" - | "failed" - | "completed" - | "incomplete" - | "expired" - readonly "required_action": { - readonly "type": "submit_tool_outputs" - readonly "submit_tool_outputs": { readonly "tool_calls": ReadonlyArray } - } - readonly "last_error": { - readonly "code": "server_error" | "rate_limit_exceeded" | "invalid_prompt" - readonly "message": string - } - readonly "expires_at": never - readonly "started_at": never - readonly "cancelled_at": never - readonly "failed_at": never - readonly "completed_at": never - readonly "incomplete_details": { readonly "reason"?: "max_completion_tokens" | "max_prompt_tokens" } - readonly "model": string - readonly "instructions": string - readonly "tools": ReadonlyArray - readonly "metadata": Metadata - readonly "usage": RunCompletionUsage - readonly "temperature"?: number | null - readonly "top_p"?: number | null - readonly "max_prompt_tokens": number - readonly "max_completion_tokens": number - readonly "truncation_strategy": { - readonly "type": "auto" | "last_messages" - readonly "last_messages"?: number | null - } - readonly "tool_choice": "none" | "auto" | "required" | { - readonly "type": "function" | "code_interpreter" | "file_search" - readonly "function"?: { readonly "name": string } + readonly "object": string + readonly "expires_at"?: number + readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> | null + readonly "audio"?: { + readonly "input"?: { + readonly "format"?: RealtimeAudioFormats + readonly "transcription"?: AudioTranscriptionResponse | null + readonly "noise_reduction"?: + | { readonly "type"?: NoiseReductionType } & { readonly [x: string]: Schema.Json } + | null + readonly "turn_detection"?: { + readonly "type"?: string + readonly "threshold"?: number + readonly "prefix_padding_ms"?: number + readonly "silence_duration_ms"?: number + } | null + } } - readonly "parallel_tool_calls": ParallelToolCalls - readonly "response_format": AssistantsApiResponseFormatOption | null } -export const RunObject = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), - "object": Schema.Literal("thread.run").annotate({ "description": "The object type, which is always `thread.run`." }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the run was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "thread_id": Schema.String.annotate({ - "description": "The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this run." - }), - "assistant_id": Schema.String.annotate({ - "description": "The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run." - }), - "status": Schema.Literals([ - "queued", - "in_progress", - "requires_action", - "cancelling", - "cancelled", - "failed", - "completed", - "incomplete", - "expired" - ]).annotate({ - "description": - "The status of the run, which can be either `queued`, `in_progress`, `requires_action`, `cancelling`, `cancelled`, `failed`, `completed`, `incomplete`, or `expired`." - }), - "required_action": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("submit_tool_outputs").annotate({ - "description": "For now, this is always `submit_tool_outputs`." - }), - "submit_tool_outputs": Schema.Struct({ - "tool_calls": Schema.Array(RunToolCallObject).annotate({ "description": "A list of the relevant tool calls." }) - }).annotate({ "description": "Details on the tool outputs needed for this run to continue." }) - }).annotate({ - "description": "Details on the action required to continue the run. Will be `null` if no action is required." - }) - ]), - "last_error": Schema.Union([ - Schema.Struct({ - "code": Schema.Literals(["server_error", "rate_limit_exceeded", "invalid_prompt"]).annotate({ - "description": "One of `server_error`, `rate_limit_exceeded`, or `invalid_prompt`." - }), - "message": Schema.String.annotate({ "description": "A human-readable description of the error." }) - }).annotate({ "description": "The last error associated with this run. Will be `null` if there are no errors." }) - ]), - "expires_at": Schema.Never, - "started_at": Schema.Never, - "cancelled_at": Schema.Never, - "failed_at": Schema.Never, - "completed_at": Schema.Never, - "incomplete_details": Schema.Union([ - Schema.Struct({ - "reason": Schema.optionalKey( - Schema.Literals(["max_completion_tokens", "max_prompt_tokens"]).annotate({ - "description": - "The reason why the run is incomplete. This will point to which specific token limit was reached over the course of the run." - }) - ) - }).annotate({ "description": "Details on why the run is incomplete. Will be `null` if the run is not incomplete." }) - ]), - "model": Schema.String.annotate({ - "description": "The model that the [assistant](/docs/api-reference/assistants) used for this run." +export const RealtimeTranscriptionSessionCreateResponseGA = Schema.Struct({ + "type": Schema.Literal("transcription").annotate({ + "description": "The type of session. Always `transcription` for transcription sessions.\n" }), - "instructions": Schema.String.annotate({ - "description": "The instructions that the [assistant](/docs/api-reference/assistants) used for this run." + "id": Schema.String.annotate({ + "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" }), - "tools": Schema.Array( - Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) - ).annotate({ - "description": "The list of tools that the [assistant](/docs/api-reference/assistants) used for this run." - }).check(Schema.isMaxLength(20)), - "metadata": Metadata, - "usage": RunCompletionUsage, - "temperature": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isFinite()), Schema.Null]).annotate({ - "description": "The sampling temperature used for this run. If not set, defaults to 1." - }) + "object": Schema.String.annotate({ "description": "The object type. Always `realtime.transcription_session`." }), + "expires_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Expiration timestamp for the session, in seconds since epoch.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), - "top_p": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isFinite()), Schema.Null]).annotate({ - "description": "The nucleus sampling value used for this run. If not set, defaults to 1." + "include": Schema.optionalKey( + Schema.Union([Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")), Schema.Null]).annotate({ + "description": + "Additional fields to include in server outputs.\n- `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" }) ), - "max_prompt_tokens": Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(256)], { - "description": "The maximum number of prompt tokens specified to have been used over the course of the run.\n" - }) - ) - ]), - "max_completion_tokens": Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(256)], { - "description": - "The maximum number of completion tokens specified to have been used over the course of the run.\n" - }) - ) - ]), - "truncation_strategy": Schema.Union([ + "audio": Schema.optionalKey( Schema.Struct({ - "type": Schema.Literals(["auto", "last_messages"]).annotate({ - "description": - "The truncation strategy to use for the thread. The default is `auto`. If set to `last_messages`, the thread will be truncated to the n most recent messages in the thread. When set to `auto`, messages in the middle of the thread will be dropped to fit the context length of the model, `max_prompt_tokens`." - }), - "last_messages": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ + "input": Schema.optionalKey(Schema.Struct({ + "format": Schema.optionalKey(RealtimeAudioFormats), + "transcription": Schema.optionalKey( + Schema.Union([AudioTranscriptionResponse, Schema.Null]).annotate({ + "description": "Configuration of the transcription model.\n" + }) + ), + "noise_reduction": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest(Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }), [ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) + ]), + Schema.Null + ]).annotate({ "description": "Configuration for input audio noise reduction.\n" }) + ), + "turn_detection": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ + "type": Schema.optionalKey( + Schema.String.annotate({ + "description": "Type of turn detection, only `server_vad` is currently supported.\n" + }) + ), + "threshold": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "prefix_padding_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "silence_duration_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ) + }).annotate({ + "description": + "Configuration for turn detection. Can be set to `null` to turn off. Server\nVAD means that the model will detect the start and end of speech based on\naudio volume and respond at the end of user speech. For `gpt-realtime-whisper`, this must be `null`; VAD is not supported.\n" + }), + Schema.Null + ]).annotate({ "description": - "The number of most recent messages from the thread when constructing the context for the run." - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), - Schema.Null - ]) - ) - }).annotate({ - "title": "Thread Truncation Controls", - "description": - "Controls for how a thread will be truncated prior to the run. Use this to control the initial context window of the run." - }) - ]), - "tool_choice": Schema.Union([ - Schema.Union([Schema.Literal("none"), Schema.Literal("auto"), Schema.Literal("required")]).annotate({ - "description": - "`none` means the model will not call any tools and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user.\n" - }), - Schema.Union([ - Schema.Struct({ - "type": Schema.Literals(["function", "code_interpreter", "file_search"]).annotate({ - "description": "The type of the tool. If type is `function`, the function name must be set" - }), - "function": Schema.optionalKey( - Schema.Struct({ "name": Schema.String.annotate({ "description": "The name of the function to call." }) }) + "Configuration for turn detection. For `gpt-realtime-whisper`, this must be `null`; VAD is not supported.\n" + }) ) - }).annotate({ - "description": "Specifies a tool the model should use. Use to force the model to call a specific tool." - }) - ]) - ], { mode: "oneOf" }).annotate({ - "description": - "Controls which (if any) tool is called by the model.\n`none` means the model will not call any tools and instead generates a message.\n`auto` is the default value and means the model can pick between generating a message or calling one or more tools.\n`required` means the model must call one or more tools before responding to the user.\nSpecifying a particular tool like `{\"type\": \"file_search\"}` or `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.\n" - }), - "parallel_tool_calls": ParallelToolCalls, - "response_format": Schema.Union([AssistantsApiResponseFormatOption, Schema.Null]) + })) + }).annotate({ "description": "Configuration for input audio for the session.\n" }) + ) }).annotate({ - "title": "A run on a thread", - "description": "Represents an execution run on a [thread](/docs/api-reference/threads)." + "title": "Realtime transcription session configuration object", + "description": "A Realtime transcription session configuration object.\n", + "identifier": "RealtimeTranscriptionSessionCreateResponseGA" }) -export type ResponseTextParam = { - readonly "format"?: TextResponseFormatConfiguration - readonly "verbosity"?: Verbosity +export type RealtimeSessionCreateResponse = { + readonly "id"?: string + readonly "object"?: string + readonly "expires_at"?: number + readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> + readonly "model"?: string + readonly "output_modalities"?: + | null + | string + | number + | boolean + | { readonly [x: string]: Schema.Json } + | ReadonlyArray<"text" | "audio"> + readonly "instructions"?: string + readonly "audio"?: { + readonly "input"?: { + readonly "format"?: RealtimeAudioFormats + readonly "transcription"?: AudioTranscriptionResponse + readonly "noise_reduction"?: + | { readonly "type"?: NoiseReductionType } & { readonly [x: string]: Schema.Json } + | null + readonly "turn_detection"?: + | { + readonly "type"?: string + readonly "threshold"?: number + readonly "prefix_padding_ms"?: number + readonly "silence_duration_ms"?: number + } & { readonly [x: string]: Schema.Json } + | null + } + readonly "output"?: { + readonly "format"?: RealtimeAudioFormats + readonly "voice"?: VoiceIdsShared + readonly "speed"?: number + } + } + readonly "tracing"?: "auto" | { + readonly "workflow_name"?: string + readonly "group_id"?: string + readonly "metadata"?: { readonly [x: string]: Schema.Json } + } + readonly "turn_detection"?: + | { + readonly "type"?: string + readonly "threshold"?: number + readonly "prefix_padding_ms"?: number + readonly "silence_duration_ms"?: number + } & { readonly [x: string]: Schema.Json } + | null + readonly "tools"?: ReadonlyArray + readonly "tool_choice"?: string + readonly "max_output_tokens"?: number | "inf" } -export const ResponseTextParam = Schema.Struct({ - "format": Schema.optionalKey(TextResponseFormatConfiguration), - "verbosity": Schema.optionalKey(Verbosity) +export const RealtimeSessionCreateResponse = Schema.Struct({ + "id": Schema.optionalKey( + Schema.String.annotate({ + "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" + }) + ), + "object": Schema.optionalKey( + Schema.String.annotate({ "description": "The object type. Always `realtime.session`." }) + ), + "expires_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Expiration timestamp for the session, in seconds since epoch.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "include": Schema.optionalKey( + Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ + "description": + "Additional fields to include in server outputs.\n- `item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" + }) + ), + "model": Schema.optionalKey(Schema.String.annotate({ "description": "The Realtime model used for this session." })), + "output_modalities": Schema.optionalKey( + Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), + Schema.Array(Schema.Literals(["text", "audio"])) + ]).annotate({ + "description": "The set of modalities the model can respond with. To disable audio,\nset this to [\"text\"].\n" + }) + ), + "instructions": Schema.optionalKey(Schema.String.annotate({ + "description": + "The default system instructions (i.e. system message) prepended to model\ncalls. This field allows the client to guide the model on desired\nresponses. The model can be instructed on response content and format,\n(e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good\nresponses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion\ninto your voice\", \"laugh frequently\"). The instructions are not guaranteed\nto be followed by the model, but they provide guidance to the model on the\ndesired behavior.\n\nNote that the server sets default instructions which will be used if this\nfield is not set and are visible in the `session.created` event at the\nstart of the session.\n" + })), + "audio": Schema.optionalKey( + Schema.Struct({ + "input": Schema.optionalKey(Schema.Struct({ + "format": Schema.optionalKey(RealtimeAudioFormats), + "transcription": Schema.optionalKey( + Schema.suspend((): Schema.Codec => AudioTranscriptionResponse).annotate({ + "description": "Configuration for input audio transcription.\n" + }) + ), + "noise_reduction": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest(Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }), [ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) + ]), + Schema.Null + ]).annotate({ "description": "Configuration for input audio noise reduction.\n" }) + ), + "turn_detection": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "type": Schema.optionalKey( + Schema.String.annotate({ + "description": "Type of turn detection, only `server_vad` is currently supported.\n" + }) + ), + "threshold": Schema.optionalKey(Schema.Finite), + "prefix_padding_ms": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "silence_duration_ms": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })) + ) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ "description": "Configuration for turn detection.\n" }) + ) + })), + "output": Schema.optionalKey( + Schema.Struct({ + "format": Schema.optionalKey(RealtimeAudioFormats), + "voice": Schema.optionalKey(VoiceIdsShared), + "speed": Schema.optionalKey(Schema.Finite) + }) + ) + }).annotate({ "description": "Configuration for input and output audio for the session.\n" }) + ), + "tracing": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto").annotate({ "description": "Default tracing mode for the session.\n" }), + Schema.Struct({ + "workflow_name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The name of the workflow to attach to this trace. This is used to\nname the trace in the traces dashboard.\n" + }) + ), + "group_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The group id to attach to this trace to enable filtering and\ngrouping in the traces dashboard.\n" + }) + ), + "metadata": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "The arbitrary metadata to attach to this trace to enable\nfiltering in the traces dashboard.\n" + }) + ) + }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) + ], { mode: "oneOf" }).annotate({ + "title": "Tracing Configuration", + "description": + "Configuration options for tracing. Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" + }) + ), + "turn_detection": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "type": Schema.optionalKey( + Schema.String.annotate({ + "description": "Type of turn detection, only `server_vad` is currently supported.\n" + }) + ), + "threshold": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "prefix_padding_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "silence_duration_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ + "description": + "Configuration for turn detection. Can be set to `null` to turn off. Server\nVAD means that the model will detect the start and end of speech based on\naudio volume and respond at the end of user speech.\n" + }) + ), + "tools": Schema.optionalKey( + Schema.Array(RealtimeFunctionTool).annotate({ "description": "Tools (functions) available to the model." }) + ), + "tool_choice": Schema.optionalKey( + Schema.String.annotate({ + "description": "How the model chooses tools. Options are `auto`, `none`, `required`, or\nspecify a function.\n" + }) + ), + "max_output_tokens": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Literal("inf")], { + mode: "oneOf" + }).annotate({ + "description": + "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" + }) + ) }).annotate({ - "description": - "Configuration options for a text response from the model. Can be plain\ntext or structured JSON data. Learn more:\n- [Text inputs and outputs](/docs/guides/text)\n- [Structured Outputs](/docs/guides/structured-outputs)\n" + "title": "Realtime session configuration object", + "description": "A Realtime session configuration object.\n", + "identifier": "RealtimeSessionCreateResponse" }) -export type RealtimeCreateClientSecretRequest = { - readonly "expires_after"?: { readonly "anchor"?: "created_at"; readonly "seconds"?: number } - readonly "session"?: RealtimeSessionCreateRequestGA | RealtimeTranscriptionSessionCreateRequestGA +export type RealtimeTranscriptionSessionCreateResponse = { + readonly "client_secret": { readonly "value": string; readonly "expires_at": number } + readonly "modalities"?: + | null + | string + | number + | boolean + | { readonly [x: string]: Schema.Json } + | ReadonlyArray<"text" | "audio"> + readonly "input_audio_format"?: string + readonly "input_audio_transcription"?: AudioTranscriptionResponse + readonly "turn_detection"?: { + readonly "type"?: string + readonly "threshold"?: number + readonly "prefix_padding_ms"?: number + readonly "silence_duration_ms"?: number + } } -export const RealtimeCreateClientSecretRequest = Schema.Struct({ - "expires_after": Schema.optionalKey( +export const RealtimeTranscriptionSessionCreateResponse = Schema.Struct({ + "client_secret": Schema.Struct({ + "value": Schema.String.annotate({ + "description": + "Ephemeral key usable in client environments to authenticate connections\nto the Realtime API. Use this in client-side environments rather than\na standard API token, which should only be used server-side.\n" + }), + "expires_at": Schema.Number.annotate({ + "description": "Timestamp for when the token expires. Currently, all tokens expire\nafter one minute.\n", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + }).annotate({ + "description": + "Ephemeral key returned by the API. Only present when the session is\ncreated on the server via REST API.\n" + }), + "modalities": Schema.optionalKey( + Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })), + Schema.Array(Schema.Literals(["text", "audio"])) + ]).annotate({ + "description": "The set of modalities the model can respond with. To disable audio,\nset this to [\"text\"].\n" + }) + ), + "input_audio_format": Schema.optionalKey( + Schema.String.annotate({ + "description": "The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\n" + }) + ), + "input_audio_transcription": Schema.optionalKey( + Schema.suspend((): Schema.Codec => AudioTranscriptionResponse).annotate({ + "description": "Configuration of the transcription model.\n" + }) + ), + "turn_detection": Schema.optionalKey( Schema.Struct({ - "anchor": Schema.optionalKey( - Schema.Literal("created_at").annotate({ + "type": Schema.optionalKey( + Schema.String.annotate({ "description": "Type of turn detection, only `server_vad` is currently supported.\n" }) + ), + "threshold": Schema.optionalKey( + Schema.Number.annotate({ "description": - "The anchor point for the client secret expiration, meaning that `seconds` will be added to the `created_at` time of the client secret to produce an expiration timestamp. Only `created_at` is currently supported.\n" - }) + "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) ), - "seconds": Schema.optionalKey( + "prefix_padding_ms": Schema.optionalKey( Schema.Number.annotate({ "description": - "The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200` (2 hours). This default to 600 seconds (10 minutes) if not specified.\n", - "format": "int64" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(10)).check(Schema.isLessThanOrEqualTo(7200)) + "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "silence_duration_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ) }).annotate({ - "title": "Client secret expiration", "description": - "Configuration for the client secret expiration. Expiration refers to the time after which\na client secret will no longer be valid for creating sessions. The session itself may\ncontinue after that time once started. A secret can be used to create multiple sessions\nuntil it expires.\n" + "Configuration for turn detection. Can be set to `null` to turn off. Server\nVAD means that the model will detect the start and end of speech based on\naudio volume and respond at the end of user speech.\n" }) - ), - "session": Schema.optionalKey( - Schema.Union([RealtimeSessionCreateRequestGA, RealtimeTranscriptionSessionCreateRequestGA], { mode: "oneOf" }) - .annotate({ - "title": "Session configuration", - "description": - "Session configuration to use for the client secret. Choose either a realtime\nsession or a transcription session.\n" - }) ) }).annotate({ - "title": "Realtime client secret creation request", "description": - "Create a session and client secret for the Realtime API. The request can specify\neither a realtime or a transcription session configuration.\n[Learn more about the Realtime API](/docs/guides/realtime).\n" + "A new Realtime transcription session configuration.\n\nWhen a session is created on the server via REST API, the session object\nalso contains an ephemeral key. Default TTL for keys is 10 minutes. This\nproperty is not present when a session is updated via the WebSocket API.\n", + "identifier": "RealtimeTranscriptionSessionCreateResponse" }) -export type RealtimeCreateClientSecretResponse = { - readonly "value": string - readonly "expires_at": number - readonly "session": RealtimeSessionCreateResponseGA | RealtimeTranscriptionSessionCreateResponseGA -} -export const RealtimeCreateClientSecretResponse = Schema.Struct({ - "value": Schema.String.annotate({ "description": "The generated client secret value." }), - "expires_at": Schema.Number.annotate({ - "description": "Expiration timestamp for the client secret, in seconds since epoch.", - "format": "unixtime" - }).check(Schema.isInt()), - "session": Schema.Union([RealtimeSessionCreateResponseGA, RealtimeTranscriptionSessionCreateResponseGA], { - mode: "oneOf" - }).annotate({ - "title": "Session configuration", - "description": "The session configuration for either a realtime or transcription session.\n" - }) -}).annotate({ - "title": "Realtime session and client secret", - "description": "Response from creating a session and client secret for the Realtime API.\n" -}) -export type RealtimeServerEventSessionCreated = { - readonly "event_id": string - readonly "type": "session.created" - readonly "session": RealtimeSessionCreateResponseGA | RealtimeTranscriptionSessionCreateResponseGA -} -export const RealtimeServerEventSessionCreated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("session.created").annotate({ "description": "The event type, must be `session.created`." }), - "session": Schema.Union([RealtimeSessionCreateResponseGA, RealtimeTranscriptionSessionCreateResponseGA], { - mode: "oneOf" - }).annotate({ "description": "The session configuration." }) -}).annotate({ +export type ToolChoiceParam = + | ToolChoiceOptions + | ToolChoiceAllowed + | ToolChoiceTypes + | ToolChoiceFunction + | ToolChoiceMCP + | ToolChoiceCustom + | SpecificProgrammaticToolCallingParam + | SpecificApplyPatchParam + | SpecificFunctionShellParam +export const ToolChoiceParam = Schema.Union([ + ToolChoiceOptions, + ToolChoiceAllowed, + ToolChoiceTypes, + ToolChoiceFunction, + ToolChoiceMCP, + ToolChoiceCustom, + SpecificProgrammaticToolCallingParam, + SpecificApplyPatchParam, + SpecificFunctionShellParam +], { mode: "oneOf" }).annotate({ "description": - "Returned when a Session is created. Emitted automatically when a new\nconnection is established as the first server event. This event will contain\nthe default Session configuration.\n" + "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n", + "identifier": "ToolChoiceParam" }) -export type RealtimeServerEventSessionUpdated = { - readonly "event_id": string - readonly "type": "session.updated" - readonly "session": RealtimeSessionCreateResponseGA | RealtimeTranscriptionSessionCreateResponseGA -} -export const RealtimeServerEventSessionUpdated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("session.updated").annotate({ "description": "The event type, must be `session.updated`." }), - "session": Schema.Union([RealtimeSessionCreateResponseGA, RealtimeTranscriptionSessionCreateResponseGA], { - mode: "oneOf" - }).annotate({ "description": "The session configuration." }) +export type AccessProgramsParam = { readonly "cyber"?: CyberAccessProgramEnum } +export const AccessProgramsParam = Schema.Struct({ + "cyber": Schema.optionalKey( + Schema.suspend((): Schema.Codec => CyberAccessProgramEnum).annotate({ + "description": + "The Cyber access program to use for this request. Supported values are `standard`, `daybreak_blue`, and `daybreak_red`. If omitted, the API resolves the program from the model's Cyber tier and your organization and project access, subject to model-specific eligibility restrictions. By default, models without a Cyber tier use Standard. Blue-tier models use Daybreak Blue when authorized; otherwise they fall back to Standard unless the model requires Daybreak access. Red-tier models use Daybreak Red and require authorization. Requests that require unavailable Daybreak access return 403. An implicit Standard fallback is represented by null in the response's access_programs field, rather than an explicit Standard selection." + }) + ) }).annotate({ - "description": "Returned when a session is updated with a `session.update` event, unless\nthere is an error.\n" + "description": "Domain-specific access programs to use for this request.", + "identifier": "AccessProgramsParam" }) -export type CreateVectorStoreFileBatchRequest = { - readonly "file_ids": ReadonlyArray - readonly "files"?: ReadonlyArray - readonly "chunking_strategy"?: ChunkingStrategyRequestParam - readonly "attributes"?: VectorStoreFileAttributes -} | { - readonly "files": ReadonlyArray - readonly "file_ids"?: ReadonlyArray - readonly "chunking_strategy"?: ChunkingStrategyRequestParam - readonly "attributes"?: VectorStoreFileAttributes +export type AccessProgramsBody = { readonly "cyber": CyberAccessProgramEnum } +export const AccessProgramsBody = Schema.Struct({ + "cyber": Schema.suspend((): Schema.Codec => CyberAccessProgramEnum).annotate({ + "description": "The effective Cyber access program used for this response." + }) +}).annotate({ "identifier": "AccessProgramsBody" }) +export type Reasoning = { + readonly "mode"?: ReasoningModeEnum + readonly "effort"?: ReasoningEffort + readonly "summary"?: "auto" | "concise" | "detailed" | null + readonly "context"?: "auto" | "current_turn" | "all_turns" | null + readonly "generate_summary"?: "auto" | "concise" | "detailed" | null } -export const CreateVectorStoreFileBatchRequest = Schema.Union([ - Schema.Struct({ - "file_ids": Schema.Array(Schema.String).annotate({ +export const Reasoning = Schema.Struct({ + "mode": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ReasoningModeEnum).annotate({ "description": - "A list of [File](/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied to all files in the batch. The maximum batch size is 2000 files. This endpoint is recommended for multi-file ingestion and helps reduce per-vector-store write request pressure. Mutually exclusive with `files`." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(2000)), - "files": Schema.optionalKey( - Schema.Array(CreateVectorStoreFileRequest).annotate({ - "description": - "A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must be specified for each file. The maximum batch size is 2000 files. This endpoint is recommended for multi-file ingestion and helps reduce per-vector-store write request pressure. Mutually exclusive with `file_ids`." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(2000)) - ), - "chunking_strategy": Schema.optionalKey(ChunkingStrategyRequestParam), - "attributes": Schema.optionalKey(VectorStoreFileAttributes) - }), - Schema.Struct({ - "files": Schema.Array(CreateVectorStoreFileRequest).annotate({ + "Controls the reasoning execution mode for the request.\n\nWhen returned on a response, this is the effective execution mode.\n" + }) + ), + "effort": Schema.optionalKey(ReasoningEffort), + "summary": Schema.optionalKey(Schema.Union([ + Schema.Literals(["auto", "concise", "detailed"]).annotate({ "description": - "A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must be specified for each file. The maximum batch size is 2000 files. This endpoint is recommended for multi-file ingestion and helps reduce per-vector-store write request pressure. Mutually exclusive with `file_ids`." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(2000)), - "file_ids": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of [File](/docs/api-reference/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied to all files in the batch. The maximum batch size is 2000 files. This endpoint is recommended for multi-file ingestion and helps reduce per-vector-store write request pressure. Mutually exclusive with `files`." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(2000)) - ), - "chunking_strategy": Schema.optionalKey(ChunkingStrategyRequestParam), - "attributes": Schema.optionalKey(VectorStoreFileAttributes) - }) -]) -export type CodeInterpreterTool = { - readonly "type": "code_interpreter" - readonly "container": string | AutoCodeInterpreterToolParam -} -export const CodeInterpreterTool = Schema.Struct({ - "type": Schema.Literal("code_interpreter").annotate({ - "description": "The type of the code interpreter tool. Always `code_interpreter`.\n" - }), - "container": Schema.Union([ - Schema.String.annotate({ "description": "The container ID." }), - AutoCodeInterpreterToolParam - ], { mode: "oneOf" }).annotate({ - "description": - "The code interpreter container. Can be a container ID or an object that\nspecifies uploaded file IDs to make available to your code, along with an\noptional `memory_limit` setting.\n" - }) -}).annotate({ - "title": "Code interpreter", - "description": "A tool that runs Python code to help generate a response to a prompt.\n" -}) -export type FunctionShellToolParam = { - readonly "type": "shell" - readonly "environment"?: ContainerAutoParam | LocalEnvironmentParam | ContainerReferenceParam | null -} -export const FunctionShellToolParam = Schema.Struct({ - "type": Schema.Literal("shell").annotate({ "description": "The type of the shell tool. Always `shell`." }), - "environment": Schema.optionalKey( + "A summary of the reasoning performed by the model. This can be\nuseful for debugging and understanding the model's reasoning process.\nOne of `auto`, `concise`, or `detailed`.\n\n`concise` is supported for `computer-use-preview` models and all reasoning models after `gpt-5`.\n" + }), + Schema.Null + ])), + "context": Schema.optionalKey(Schema.Union([ + Schema.Literals(["auto", "current_turn", "all_turns"]).annotate({ + "description": + "Controls which reasoning items are rendered back to the model on later turns.\nIf omitted or set to `auto`, the model determines the context mode. The\n`gpt-5.6` model family defaults to `all_turns`; earlier models default to\n`current_turn`.\n\nWhen returned on a response, this is the effective reasoning context mode\nused for the response.\n" + }), + Schema.Null + ])), + "generate_summary": Schema.optionalKey( Schema.Union([ - Schema.Union([ContainerAutoParam, LocalEnvironmentParam, ContainerReferenceParam], { mode: "oneOf" }), + Schema.Literals(["auto", "concise", "detailed"]).annotate({ + "description": + "**Deprecated:** use `summary` instead.\n\nA summary of the reasoning performed by the model. This can be\nuseful for debugging and understanding the model's reasoning process.\nOne of `auto`, `concise`, or `detailed`.\n" + }), Schema.Null ]) ) -}).annotate({ "title": "Shell tool", "description": "A tool that allows the model to execute shell commands." }) -export type EvalItemContent = EvalItemContentItem | EvalItemContentArray -export const EvalItemContent = Schema.Union([EvalItemContentItem, EvalItemContentArray], { mode: "oneOf" }).annotate({ - "title": "Eval content", +}).annotate({ + "title": "Reasoning", "description": - "Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items.\n" + "Configuration options for\n[reasoning models](https://developers.openai.com/api/docs/guides/reasoning).\n", + "identifier": "Reasoning" }) -export type OutputMessageContent = OutputTextContent | RefusalContent -export const OutputMessageContent = Schema.Union([OutputTextContent, RefusalContent], { mode: "oneOf" }) -export type ResponseContentPartAddedEvent = { - readonly "type": "response.content_part.added" +export type ConversationParam = string | ConversationParam_2 +export const ConversationParam = Schema.Union([ + Schema.String.annotate({ "title": "Conversation ID", "description": "The unique ID of the conversation.\n" }), + ConversationParam_2 +], { mode: "oneOf" }).annotate({ + "description": + "The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request.\nInput items and output items from this response are automatically added to this conversation after this response completes.\n", + "identifier": "ConversationParam" +}) +export type PromptCacheMissDiagnosticsBody = { + readonly "type": "cache_miss" + readonly "reason": CacheMissReasonTypeEnum + readonly "cache_missed_tokens": number + readonly "comparison_reusable_tokens"?: number +} +export const PromptCacheMissDiagnosticsBody = Schema.Struct({ + "type": Schema.Literal("cache_miss"), + "reason": Schema.suspend((): Schema.Codec => CacheMissReasonTypeEnum).annotate({ + "description": "The reason prompt cache reuse did not occur." + }), + "cache_missed_tokens": Schema.Number.annotate({ + "description": "The estimated number of input tokens affected after the first detected divergence." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "comparison_reusable_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The raw token count of the reusable prefix in the compared response." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })) + ) +}).annotate({ "identifier": "PromptCacheMissDiagnosticsBody" }) +export type ResponseShellCallOutputContentDeltaStreamingEvent = { + readonly "type": "response.shell_call_output_content.delta" + readonly "sequence_number": number + readonly "item_id": string + readonly "output_index": number + readonly "command_index": number + readonly "delta": ShellCallOutputDelta +} +export const ResponseShellCallOutputContentDeltaStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_output_content.delta").annotate({ + "description": "The type of the event, always `response.shell_call_output_content.delta`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The ID of the output item that was updated." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that produced output." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.suspend((): Schema.Codec => ShellCallOutputDelta).annotate({ + "description": "The stdout/stderr delta that was emitted." + }) +}).annotate({ + "title": "Response shell call output content delta event", + "description": "A streaming event that indicated shell call output was incrementally added.", + "identifier": "ResponseShellCallOutputContentDeltaStreamingEvent" +}) +export type ResponseTextDeltaEvent = { + readonly "type": "response.output_text.delta" readonly "item_id": string readonly "output_index": number readonly "content_index": number - readonly "part": OutputTextContent | RefusalContent | ReasoningTextContent + readonly "delta": string readonly "sequence_number": number + readonly "logprobs": ReadonlyArray } -export const ResponseContentPartAddedEvent = Schema.Struct({ - "type": Schema.Literal("response.content_part.added").annotate({ - "description": "The type of the event. Always `response.content_part.added`.\n" - }), - "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the content part was added to.\n" +export const ResponseTextDeltaEvent = Schema.Struct({ + "type": Schema.Literal("response.output_text.delta").annotate({ + "description": "The type of the event. Always `response.output_text.delta`.\n" }), + "item_id": Schema.String.annotate({ "description": "The ID of the output item that the text delta was added to.\n" }), "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the content part was added to.\n" - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ "description": "The index of the content part that was added.\n" }).check( - Schema.isInt() + "description": "The index of the output item that the text delta was added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part that the text delta was added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "The text delta that was added.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "part": Schema.Union([OutputTextContent, RefusalContent, ReasoningTextContent], { mode: "oneOf" }).annotate({ - "description": "The content part that was added.\n" - }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() - ) -}).annotate({ "description": "Emitted when a new content part is added." }) -export type ResponseContentPartDoneEvent = { - readonly "type": "response.content_part.done" + "logprobs": Schema.Array(ResponseLogProb).annotate({ + "description": "The log probabilities of the tokens in the delta.\n" + }) +}).annotate({ + "description": "Emitted when there is an additional text delta.", + "identifier": "ResponseTextDeltaEvent" +}) +export type ResponseTextDoneEvent = { + readonly "type": "response.output_text.done" readonly "item_id": string readonly "output_index": number readonly "content_index": number + readonly "text": string readonly "sequence_number": number - readonly "part": OutputTextContent | RefusalContent | ReasoningTextContent + readonly "logprobs": ReadonlyArray } -export const ResponseContentPartDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.content_part.done").annotate({ - "description": "The type of the event. Always `response.content_part.done`.\n" +export const ResponseTextDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.output_text.done").annotate({ + "description": "The type of the event. Always `response.output_text.done`.\n" }), "item_id": Schema.String.annotate({ - "description": "The ID of the output item that the content part was added to.\n" + "description": "The ID of the output item that the text content is finalized.\n" }), "output_index": Schema.Number.annotate({ - "description": "The index of the output item that the content part was added to.\n" - }).check(Schema.isInt()), - "content_index": Schema.Number.annotate({ "description": "The index of the content part that is done.\n" }).check( - Schema.isInt() - ), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + "description": "The index of the output item that the text content is finalized.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part that the text content is finalized.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "text": Schema.String.annotate({ "description": "The text content that is finalized.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "part": Schema.Union([OutputTextContent, RefusalContent, ReasoningTextContent], { mode: "oneOf" }).annotate({ - "description": "The content part that is done.\n" + "logprobs": Schema.Array(ResponseLogProb).annotate({ + "description": "The log probabilities of the tokens in the delta.\n" }) -}).annotate({ "description": "Emitted when a content part is done." }) -export type Message = { - readonly "type": "message" - readonly "id": string - readonly "status": "in_progress" | "completed" | "incomplete" - readonly "role": "unknown" | "user" | "assistant" | "system" | "critic" | "discriminator" | "developer" | "tool" - readonly "content": ReadonlyArray< - | InputTextContent - | OutputTextContent - | TextContent - | SummaryTextContent - | ReasoningTextContent - | RefusalContent - | InputImageContent - | ComputerScreenshotContent - | InputFileContent - > - readonly "phase"?: "commentary" | "final_answer" | null +}).annotate({ "description": "Emitted when text content is finalized.", "identifier": "ResponseTextDoneEvent" }) +export type CreateMessageRequest = { + readonly "role": "user" | "assistant" + readonly "content": + | string + | ReadonlyArray + readonly "attachments"?: + | ReadonlyArray< + { + readonly "file_id"?: string + readonly "tools"?: ReadonlyArray + } + > + | null + readonly "metadata"?: Metadata } -export const Message = Schema.Struct({ - "type": Schema.Literal("message").annotate({ "description": "The type of the message. Always set to `message`." }), - "id": Schema.String.annotate({ "description": "The unique ID of the message." }), - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ +export const CreateMessageRequest = Schema.Struct({ + "role": Schema.Literals(["user", "assistant"]).annotate({ "description": - "The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API." + "The role of the entity that is creating the message. Allowed values include:\n- `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages.\n- `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation.\n" }), - "role": Schema.Literals(["unknown", "user", "assistant", "system", "critic", "discriminator", "developer", "tool"]) - .annotate({ + "content": Schema.Union([ + Schema.String.annotate({ "title": "Text content", "description": "The text contents of the message." }), + Schema.Array( + Schema.Union([MessageContentImageFileObject, MessageContentImageUrlObject, MessageRequestContentTextObject], { + mode: "oneOf" + }) + ).annotate({ + "title": "Array of content parts", "description": - "The role of the message. One of `unknown`, `user`, `assistant`, `system`, `critic`, `discriminator`, `developer`, or `tool`." - }), - "content": Schema.Array( - Schema.Union([ - InputTextContent, - OutputTextContent, - TextContent, - SummaryTextContent, - ReasoningTextContent, - RefusalContent, - InputImageContent, - ComputerScreenshotContent, - InputFileContent - ], { mode: "oneOf" }).annotate({ "description": "A content part that makes up an input or output item." }) - ).annotate({ "description": "The content of the message" }), - "phase": Schema.optionalKey(Schema.Union([ - Schema.Literals(["commentary", "final_answer"]).annotate({ - "description": - "Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend phase on all assistant messages — dropping it can degrade performance. Not used for user messages." - }), + "An array of content parts with a defined type, each can be of type `text` or images can be passed with `image_url` or `image_file`. Image types are only supported on [Vision-compatible models](https://developers.openai.com/api/docs/models)." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ], { mode: "oneOf" }), + "attachments": Schema.optionalKey(Schema.Union([ + Schema.Array(Schema.Struct({ + "file_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the file to attach to the message." }) + ), + "tools": Schema.optionalKey( + Schema.Array(Schema.Union([AssistantToolsCode, AssistantToolsFileSearchTypeOnly], { mode: "oneOf" })).annotate({ + "description": "The tools to add this file to." + }) + ) + })).annotate({ "description": "A list of files attached to the message, and the tools they should be added to." }), Schema.Null - ])) -}).annotate({ "title": "Message", "description": "A message to or from the model." }) -export type EasyInputMessage = { - readonly "role": "user" | "assistant" | "system" | "developer" - readonly "content": string | InputMessageContentList - readonly "phase"?: MessagePhase | null - readonly "type"?: "message" -} -export const EasyInputMessage = Schema.Struct({ - "role": Schema.Literals(["user", "assistant", "system", "developer"]).annotate({ - "description": "The role of the message input. One of `user`, `assistant`, `system`, or\n`developer`.\n" - }), - "content": Schema.Union([ - Schema.String.annotate({ "title": "Text input", "description": "A text input to the model.\n" }), - InputMessageContentList - ], { mode: "oneOf" }).annotate({ + ])), + "metadata": Schema.optionalKey(Metadata) +}).annotate({ "identifier": "CreateMessageRequest" }) +export type AssistantsApiToolChoiceOption = "none" | "auto" | "required" | AssistantsNamedToolChoice +export const AssistantsApiToolChoiceOption = Schema.Union([ + Schema.Literals(["none", "auto", "required"]).annotate({ "description": - "Text, image, or audio input to the model, used to generate a response.\nCan also contain previous assistant responses.\n" + "`none` means the model will not call any tools and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools before responding to the user.\n" }), - "phase": Schema.optionalKey(Schema.Union([MessagePhase, Schema.Null])), - "type": Schema.optionalKey( - Schema.Literal("message").annotate({ "description": "The type of the message input. Always `message`.\n" }) - ) -}).annotate({ - "title": "Input message", + AssistantsNamedToolChoice +], { mode: "oneOf" }).annotate({ "description": - "A message input to the model with a role indicating instruction following\nhierarchy. Instructions given with the `developer` or `system` role take\nprecedence over instructions given with the `user` role. Messages with the\n`assistant` role are presumed to have been generated by the model in previous\ninteractions.\n" + "Controls which (if any) tool is called by the model.\n`none` means the model will not call any tools and instead generates a message.\n`auto` is the default value and means the model can pick between generating a message or calling one or more tools.\n`required` means the model must call one or more tools before responding to the user.\nSpecifying a particular tool like `{\"type\": \"file_search\"}` or `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.\n", + "identifier": "AssistantsApiToolChoiceOption" }) -export type InputMessageResource = { - readonly "type": "message" - readonly "role": "user" | "system" | "developer" - readonly "status"?: "in_progress" | "completed" | "incomplete" - readonly "content": InputMessageContentList +export type RunStepDetailsToolCallsCodeObject = { readonly "id": string + readonly "type": "code_interpreter" + readonly "code_interpreter": { + readonly "input": string + readonly "outputs": ReadonlyArray< + RunStepDetailsToolCallsCodeOutputLogsObject | RunStepDetailsToolCallsCodeOutputImageObject + > + } } -export const InputMessageResource = Schema.Struct({ - "type": Schema.Literal("message").annotate({ - "description": "The type of the message input. Always set to `message`.\n" - }), - "role": Schema.Literals(["user", "system", "developer"]).annotate({ - "description": "The role of the message input. One of `user`, `system`, or `developer`.\n" +export const RunStepDetailsToolCallsCodeObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the tool call." }), + "type": Schema.Literal("code_interpreter").annotate({ + "description": "The type of tool call. This is always going to be `code_interpreter` for this type of tool call." }), - "status": Schema.optionalKey( - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "code_interpreter": Schema.Struct({ + "input": Schema.String.annotate({ "description": "The input to the Code Interpreter tool call." }), + "outputs": Schema.Array( + Schema.Union([RunStepDetailsToolCallsCodeOutputLogsObject, RunStepDetailsToolCallsCodeOutputImageObject], { + mode: "oneOf" + }) + ).annotate({ "description": - "The status of item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + "The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a different object type." }) + }).annotate({ "description": "The Code Interpreter tool call definition." }) +}).annotate({ + "title": "Code Interpreter tool call", + "description": "Details of the Code Interpreter tool call the run step was involved in.", + "identifier": "RunStepDetailsToolCallsCodeObject" +}) +export type RunStepDeltaStepDetailsToolCallsCodeObject = { + readonly "index": number + readonly "id"?: string + readonly "type": "code_interpreter" + readonly "code_interpreter"?: { + readonly "input"?: string + readonly "outputs"?: ReadonlyArray< + RunStepDeltaStepDetailsToolCallsCodeOutputLogsObject | RunStepDeltaStepDetailsToolCallsCodeOutputImageObject + > + } +} +export const RunStepDeltaStepDetailsToolCallsCodeObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the tool call in the tool calls array." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "content": InputMessageContentList, - "id": Schema.String.annotate({ "description": "The unique ID of the message input.\n" }) + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the tool call." })), + "type": Schema.Literal("code_interpreter").annotate({ + "description": "The type of tool call. This is always going to be `code_interpreter` for this type of tool call." + }), + "code_interpreter": Schema.optionalKey( + Schema.Struct({ + "input": Schema.optionalKey( + Schema.String.annotate({ "description": "The input to the Code Interpreter tool call." }) + ), + "outputs": Schema.optionalKey( + Schema.Array( + Schema.Union([ + RunStepDeltaStepDetailsToolCallsCodeOutputLogsObject, + RunStepDeltaStepDetailsToolCallsCodeOutputImageObject + ], { mode: "oneOf" }) + ).annotate({ + "description": + "The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a different object type." + }) + ) + }).annotate({ "description": "The Code Interpreter tool call definition." }) + ) }).annotate({ - "title": "Input message", - "description": - "A message input to the model with a role indicating instruction following\nhierarchy. Instructions given with the `developer` or `system` role take\nprecedence over instructions given with the `user` role.\n" + "title": "Code interpreter tool call", + "description": "Details of the Code Interpreter tool call the run step was involved in.", + "identifier": "RunStepDeltaStepDetailsToolCallsCodeObject" }) -export type ComputerActionList = ReadonlyArray -export const ComputerActionList = Schema.Array(ComputerAction).annotate({ - "title": "Computer Action List", - "description": - "Flattened batched actions for `computer_use`. Each action includes an\n`type` discriminator and action-specific fields.\n" +export type MessageContentTextObject = { + readonly "type": "text" + readonly "text": { + readonly "value": string + readonly "annotations": ReadonlyArray< + MessageContentTextAnnotationsFileCitationObject | MessageContentTextAnnotationsFilePathObject + > + } +} +export const MessageContentTextObject = Schema.Struct({ + "type": Schema.Literal("text").annotate({ "description": "Always `text`." }), + "text": Schema.Struct({ + "value": Schema.String.annotate({ "description": "The data that makes up the text." }), + "annotations": Schema.Array( + Schema.Union([MessageContentTextAnnotationsFileCitationObject, MessageContentTextAnnotationsFilePathObject], { + mode: "oneOf" + }) + ) + }) +}).annotate({ + "title": "Text", + "description": "The text content that is part of a message.", + "identifier": "MessageContentTextObject" }) -export type ThreadItem = - | UserMessageItem - | AssistantMessageItem - | WidgetMessageItem - | ClientToolCallItem - | TaskItem - | TaskGroupItem -export const ThreadItem = Schema.Union([ - UserMessageItem, - AssistantMessageItem, - WidgetMessageItem, - ClientToolCallItem, - TaskItem, - TaskGroupItem -], { mode: "oneOf" }).annotate({ "title": "The thread item" }) -export type ListAuditLogsResponse = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id"?: string | null - readonly "last_id"?: string | null - readonly "has_more": boolean +export type MessageDeltaContentTextObject = { + readonly "index": number + readonly "type": "text" + readonly "text"?: { + readonly "value"?: string + readonly "annotations"?: ReadonlyArray< + MessageDeltaContentTextAnnotationsFileCitationObject | MessageDeltaContentTextAnnotationsFilePathObject + > + } } -export const ListAuditLogsResponse = Schema.Struct({ - "object": Schema.Literal("list"), - "data": Schema.Array(AuditLog), - "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), - "has_more": Schema.Boolean +export const MessageDeltaContentTextObject = Schema.Struct({ + "index": Schema.Number.annotate({ "description": "The index of the content part in the message." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "type": Schema.Literal("text").annotate({ "description": "Always `text`." }), + "text": Schema.optionalKey(Schema.Struct({ + "value": Schema.optionalKey(Schema.String.annotate({ "description": "The data that makes up the text." })), + "annotations": Schema.optionalKey( + Schema.Array( + Schema.Union([ + MessageDeltaContentTextAnnotationsFileCitationObject, + MessageDeltaContentTextAnnotationsFilePathObject + ], { mode: "oneOf" }) + ) + ) + })) +}).annotate({ + "title": "Text", + "description": "The text content that is part of a message.", + "identifier": "MessageDeltaContentTextObject" }) -export type ChatCompletionList = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean +export type VectorStoreObject = { + readonly "id": string + readonly "object": "vector_store" + readonly "created_at": number + readonly "name": string + readonly "usage_bytes": number + readonly "file_counts": { + readonly "in_progress": number + readonly "completed": number + readonly "failed": number + readonly "cancelled": number + readonly "total": number + } + readonly "status": "expired" | "in_progress" | "completed" + readonly "expires_after"?: VectorStoreExpirationAfter + readonly "expires_at"?: number | null + readonly "last_active_at": number | null + readonly "metadata": Metadata } -export const ChatCompletionList = Schema.Struct({ - "object": Schema.Literal("list").annotate({ - "description": "The type of this object. It is always set to \"list\".\n" +export const VectorStoreObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("vector_store").annotate({ + "description": "The object type, which is always `vector_store`." }), - "data": Schema.Array(CreateChatCompletionResponse).annotate({ - "description": "An array of chat completion objects.\n" + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the vector store was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "name": Schema.String.annotate({ "description": "The name of the vector store." }), + "usage_bytes": Schema.Number.annotate({ + "description": "The total number of bytes used by the files in the vector store." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "file_counts": Schema.Struct({ + "in_progress": Schema.Number.annotate({ "description": "The number of files that are currently being processed." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "completed": Schema.Number.annotate({ "description": "The number of files that have been successfully processed." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "failed": Schema.Number.annotate({ "description": "The number of files that have failed to process." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "cancelled": Schema.Number.annotate({ "description": "The number of files that were cancelled." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "total": Schema.Number.annotate({ "description": "The total number of files." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) }), - "first_id": Schema.String.annotate({ - "description": "The identifier of the first chat completion in the data array." + "status": Schema.Literals(["expired", "in_progress", "completed"]).annotate({ + "description": + "The status of the vector store, which can be either `expired`, `in_progress`, or `completed`. A status of `completed` indicates that the vector store is ready for use." }), - "last_id": Schema.String.annotate({ "description": "The identifier of the last chat completion in the data array." }), - "has_more": Schema.Boolean.annotate({ "description": "Indicates whether there are more Chat Completions available." }) -}).annotate({ "title": "ChatCompletionList", "description": "An object representing a list of Chat Completions.\n" }) -export type CreateChatCompletionRequest = { - readonly "metadata"?: Metadata - readonly "top_logprobs"?: number - readonly "temperature"?: number | null - readonly "top_p"?: number | null - readonly "user"?: string | null - readonly "safety_identifier"?: string - readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null - readonly "messages": ReadonlyArray - readonly "model": - | string - | "gpt-5.4" - | "gpt-5.4-mini" - | "gpt-5.4-nano" - | "gpt-5.4-mini-2026-03-17" - | "gpt-5.4-nano-2026-03-17" - | "gpt-5.3-chat-latest" - | "gpt-5.2" - | "gpt-5.2-2025-12-11" - | "gpt-5.2-chat-latest" - | "gpt-5.2-pro" - | "gpt-5.2-pro-2025-12-11" - | "gpt-5.1" - | "gpt-5.1-2025-11-13" - | "gpt-5.1-codex" - | "gpt-5.1-mini" - | "gpt-5.1-chat-latest" - | "gpt-5" - | "gpt-5-mini" - | "gpt-5-nano" - | "gpt-5-2025-08-07" - | "gpt-5-mini-2025-08-07" - | "gpt-5-nano-2025-08-07" - | "gpt-5-chat-latest" - | "gpt-4.1" - | "gpt-4.1-mini" - | "gpt-4.1-nano" - | "gpt-4.1-2025-04-14" - | "gpt-4.1-mini-2025-04-14" - | "gpt-4.1-nano-2025-04-14" - | "o4-mini" - | "o4-mini-2025-04-16" - | "o3" - | "o3-2025-04-16" - | "o3-mini" - | "o3-mini-2025-01-31" - | "o1" - | "o1-2024-12-17" - | "o1-preview" - | "o1-preview-2024-09-12" - | "o1-mini" - | "o1-mini-2024-09-12" - | "gpt-4o" - | "gpt-4o-2024-11-20" - | "gpt-4o-2024-08-06" - | "gpt-4o-2024-05-13" - | "gpt-4o-audio-preview" - | "gpt-4o-audio-preview-2024-10-01" - | "gpt-4o-audio-preview-2024-12-17" - | "gpt-4o-audio-preview-2025-06-03" - | "gpt-4o-mini-audio-preview" - | "gpt-4o-mini-audio-preview-2024-12-17" - | "gpt-4o-search-preview" - | "gpt-4o-mini-search-preview" - | "gpt-4o-search-preview-2025-03-11" - | "gpt-4o-mini-search-preview-2025-03-11" - | "chatgpt-4o-latest" - | "codex-mini-latest" - | "gpt-4o-mini" - | "gpt-4o-mini-2024-07-18" - | "gpt-4-turbo" - | "gpt-4-turbo-2024-04-09" - | "gpt-4-0125-preview" - | "gpt-4-turbo-preview" - | "gpt-4-1106-preview" - | "gpt-4-vision-preview" - | "gpt-4" - | "gpt-4-0314" - | "gpt-4-0613" - | "gpt-4-32k" - | "gpt-4-32k-0314" - | "gpt-4-32k-0613" - | "gpt-3.5-turbo" - | "gpt-3.5-turbo-16k" - | "gpt-3.5-turbo-0301" - | "gpt-3.5-turbo-0613" - | "gpt-3.5-turbo-1106" - | "gpt-3.5-turbo-0125" - | "gpt-3.5-turbo-16k-0613" - readonly "modalities"?: ResponseModalities - readonly "verbosity"?: Verbosity - readonly "reasoning_effort"?: ReasoningEffort - readonly "max_completion_tokens"?: number | null - readonly "frequency_penalty"?: number - readonly "presence_penalty"?: number - readonly "web_search_options"?: { - readonly "user_location"?: { readonly "type": "approximate"; readonly "approximate": WebSearchLocation } - readonly "search_context_size"?: WebSearchContextSize - } - readonly "response_format"?: ResponseFormatText | ResponseFormatJsonSchema | ResponseFormatJsonObject - readonly "audio"?: { - readonly "voice": VoiceIdsShared | { readonly "id": string } - readonly "format": "wav" | "aac" | "mp3" | "flac" | "opus" | "pcm16" - } - readonly "store"?: boolean | null - readonly "stream"?: boolean | null - readonly "stop"?: StopConfiguration - readonly "logit_bias"?: {} - readonly "logprobs"?: boolean | null - readonly "max_tokens"?: number | null - readonly "n"?: number - readonly "prediction"?: PredictionContent | null - readonly "seed"?: number - readonly "stream_options"?: ChatCompletionStreamOptions - readonly "tools"?: ReadonlyArray - readonly "tool_choice"?: ChatCompletionToolChoiceOption - readonly "parallel_tool_calls"?: ParallelToolCalls - readonly "function_call"?: "none" | "auto" | ChatCompletionFunctionCallOption - readonly "functions"?: ReadonlyArray + "expires_after": Schema.optionalKey(VectorStoreExpirationAfter), + "expires_at": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the vector store will expire.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ), + "last_active_at": Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the vector store was last active.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "metadata": Metadata +}).annotate({ + "title": "Vector store", + "description": "A vector store is a collection of processed files can be used by the `file_search` tool.", + "identifier": "VectorStoreObject" +}) +export type UpdateVectorStoreRequest = { + readonly "name"?: string | null + readonly "expires_after"?: VectorStoreExpirationAfter | null + readonly "metadata"?: Metadata } -export const CreateChatCompletionRequest = Schema.Struct({ - "metadata": Schema.optionalKey(Metadata), - "top_logprobs": Schema.optionalKey( +export const UpdateVectorStoreRequest = Schema.Struct({ + "name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the vector store." }) + ), + "expires_after": Schema.optionalKey(Schema.Union([VectorStoreExpirationAfter, Schema.Null])), + "metadata": Schema.optionalKey(Metadata) +}).annotate({ "identifier": "UpdateVectorStoreRequest" }) +export type StaticChunkingStrategyRequestParam = { + readonly "type": "static" + readonly "static": StaticChunkingStrategy +} +export const StaticChunkingStrategyRequestParam = Schema.Struct({ + "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), + "static": StaticChunkingStrategy +}).annotate({ + "title": "Static Chunking Strategy", + "description": "Customize your own chunking strategy by setting chunk size and chunk overlap.", + "identifier": "StaticChunkingStrategyRequestParam" +}) +export type StaticChunkingStrategyResponseParam = { + readonly "type": "static" + readonly "static": StaticChunkingStrategy +} +export const StaticChunkingStrategyResponseParam = Schema.Struct({ + "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), + "static": StaticChunkingStrategy +}).annotate({ "title": "Static Chunking Strategy", "identifier": "StaticChunkingStrategyResponseParam" }) +export type VectorStoreSearchResultItem = { + readonly "file_id": string + readonly "filename": string + readonly "score": number + readonly "attributes": VectorStoreFileAttributes + readonly "content": ReadonlyArray +} +export const VectorStoreSearchResultItem = Schema.Struct({ + "file_id": Schema.String.annotate({ "description": "The ID of the vector store file." }), + "filename": Schema.String.annotate({ "description": "The name of the vector store file." }), + "score": Schema.Number.annotate({ "description": "The similarity score for the result." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })).check( + Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" }) + ), + "attributes": VectorStoreFileAttributes, + "content": Schema.Array(VectorStoreSearchResultContentObject).annotate({ + "description": "Content chunks from the file." + }) +}).annotate({ "identifier": "VectorStoreSearchResultItem" }) +export type SafetyCaseNotice = { readonly "type": SafetyCaseNoticeType } +export const SafetyCaseNotice = Schema.Struct({ "type": SafetyCaseNoticeType }).annotate({ + "identifier": "SafetyCaseNotice" +}) +export type SafetyAlertResource = { + readonly "id": string + readonly "object": "safety.alert" + readonly "created_at": number + readonly "request_id": string + readonly "response_id": string + readonly "model": string + readonly "request_paused": boolean + readonly "error_type": SafetyAlertErrorType + readonly "reason": string | null + readonly "detailed_explanation"?: string | null +} +export const SafetyAlertResource = Schema.Struct({ + "id": Schema.String, + "object": Schema.Literal("safety.alert"), + "created_at": Schema.Number.annotate({ "format": "unixtime" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "request_id": Schema.String, + "response_id": Schema.String, + "model": Schema.String, + "request_paused": Schema.Boolean.annotate({ + "description": + "Whether block registration succeeded for this request. This does not confirm that response execution stopped." + }), + "error_type": SafetyAlertErrorType, + "reason": Schema.Union([ + Schema.String.annotate({ + "description": "A customer-safe description derived from error_type, or null for zero data retention requests." + }), + Schema.Null + ]), + "detailed_explanation": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup( - [Schema.isFinite(), Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(20)], - { - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n`logprobs` must be set to `true` if this parameter is used.\n" - } - ) - ).check( - Schema.makeFilterGroup([ - Schema.isGreaterThanOrEqualTo(0), - Schema.isLessThanOrEqualTo(20), - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(20)], { - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }) - ], { - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }) - ) - ]) + Schema.String.annotate({ + "description": + "A generated explanation, temporarily available for eligible zero data retention alerts. Omitted when unavailable." + }), + Schema.Null + ]) + ) +}).annotate({ "identifier": "SafetyAlertResource" }) +export type DecisionsUsageResult = { + readonly "api_source"?: DecisionsUsageApiSource | null + readonly "object": "organization.usage.decisions.result" + readonly "input_tokens": number + readonly "input_cached_tokens"?: number | null + readonly "input_cache_write_tokens"?: number | null + readonly "input_cache_write_12h_tokens"?: number | null + readonly "input_uncached_tokens"?: number | null + readonly "output_tokens": number + readonly "input_text_tokens"?: number | null + readonly "output_text_tokens"?: number | null + readonly "input_cached_text_tokens"?: number | null + readonly "input_audio_tokens"?: number | null + readonly "input_cached_audio_tokens"?: number | null + readonly "output_audio_tokens"?: number | null + readonly "input_image_tokens"?: number | null + readonly "input_cached_image_tokens"?: number | null + readonly "output_image_tokens"?: number | null + readonly "num_model_requests": number + readonly "project_id"?: string | null + readonly "user_id"?: string | null + readonly "api_key_id"?: string | null + readonly "model"?: string | null + readonly "batch"?: boolean | null + readonly "service_tier"?: string | null +} +export const DecisionsUsageResult = Schema.Struct({ + "api_source": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => DecisionsUsageApiSource).annotate({ + "description": + "When grouped by `api_source`, `agents_api` identifies attributed Agents API activity and `unlabeled` includes all records without published source attribution, including historical and unknown origins. Unlabeled does not imply direct API usage. Without source grouping, this field is null." + }), + Schema.Null ]) ), - "temperature": Schema.optionalKey( + "object": Schema.Literal("organization.usage.decisions.result"), + "input_tokens": Schema.Number.annotate({ + "description": + "The aggregated number of input tokens used, including cached and cache-write tokens. This includes text, audio, and image tokens. For customers subscribed to Scale Tier, this includes Scale Tier tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "input_cached_tokens": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), + "The aggregated number of cached input tokens used across text, audio, and image inputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ), - "top_p": Schema.optionalKey(Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - Schema.Null - ])), - "user": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }) + "input_cache_write_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The aggregated number of input tokens written to the cache with a 30-minute retention period." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) + "input_cache_write_12h_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The aggregated number of input tokens written to the cache with a 12-hour retention period." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( + "input_uncached_tokens": Schema.optionalKey( Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ + Schema.Number.annotate({ "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), + "The aggregated number of uncached input tokens used across text, audio, and image inputs, excluding cache-write tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ), - "messages": Schema.Array(ChatCompletionRequestMessage).annotate({ + "output_tokens": Schema.Number.annotate({ "description": - "A list of messages comprising the conversation so far. Depending on the\n[model](/docs/models) you use, different message types (modalities) are\nsupported, like [text](/docs/guides/text-generation),\n[images](/docs/guides/vision), and [audio](/docs/guides/audio).\n" - }).check(Schema.isMinLength(1)), - "model": Schema.Union([ - Schema.String, - Schema.Literals([ - "gpt-5.4", - "gpt-5.4-mini", - "gpt-5.4-nano", - "gpt-5.4-mini-2026-03-17", - "gpt-5.4-nano-2026-03-17", - "gpt-5.3-chat-latest", - "gpt-5.2", - "gpt-5.2-2025-12-11", - "gpt-5.2-chat-latest", - "gpt-5.2-pro", - "gpt-5.2-pro-2025-12-11", - "gpt-5.1", - "gpt-5.1-2025-11-13", - "gpt-5.1-codex", - "gpt-5.1-mini", - "gpt-5.1-chat-latest", - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-5-2025-08-07", - "gpt-5-mini-2025-08-07", - "gpt-5-nano-2025-08-07", - "gpt-5-chat-latest", - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4.1-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "o4-mini", - "o4-mini-2025-04-16", - "o3", - "o3-2025-04-16", - "o3-mini", - "o3-mini-2025-01-31", - "o1", - "o1-2024-12-17", - "o1-preview", - "o1-preview-2024-09-12", - "o1-mini", - "o1-mini-2024-09-12", - "gpt-4o", - "gpt-4o-2024-11-20", - "gpt-4o-2024-08-06", - "gpt-4o-2024-05-13", - "gpt-4o-audio-preview", - "gpt-4o-audio-preview-2024-10-01", - "gpt-4o-audio-preview-2024-12-17", - "gpt-4o-audio-preview-2025-06-03", - "gpt-4o-mini-audio-preview", - "gpt-4o-mini-audio-preview-2024-12-17", - "gpt-4o-search-preview", - "gpt-4o-mini-search-preview", - "gpt-4o-search-preview-2025-03-11", - "gpt-4o-mini-search-preview-2025-03-11", - "chatgpt-4o-latest", - "codex-mini-latest", - "gpt-4o-mini", - "gpt-4o-mini-2024-07-18", - "gpt-4-turbo", - "gpt-4-turbo-2024-04-09", - "gpt-4-0125-preview", - "gpt-4-turbo-preview", - "gpt-4-1106-preview", - "gpt-4-vision-preview", - "gpt-4", - "gpt-4-0314", - "gpt-4-0613", - "gpt-4-32k", - "gpt-4-32k-0314", - "gpt-4-32k-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0301", - "gpt-3.5-turbo-0613", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-0125", - "gpt-3.5-turbo-16k-0613" + "The aggregated number of output tokens used across text, audio, and image outputs. For customers subscribed to Scale Tier, this includes Scale Tier tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "input_text_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The aggregated number of uncached text input tokens used, excluding cache-write tokens." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null ]) - ]).annotate({ - "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" - }), - "modalities": Schema.optionalKey(ResponseModalities), - "verbosity": Schema.optionalKey(Verbosity), - "reasoning_effort": Schema.optionalKey(ReasoningEffort), - "max_completion_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Null]).annotate({ - "description": - "An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }) ), - "frequency_penalty": Schema.optionalKey( + "output_text_tokens": Schema.optionalKey( Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(-2), Schema.isLessThanOrEqualTo(2)], { - "description": - "Number between -2.0 and 2.0. Positive values penalize new tokens based on\ntheir existing frequency in the text so far, decreasing the model's\nlikelihood to repeat the same line verbatim.\n" - }) - ) + Schema.Number.annotate({ "description": "The aggregated number of text output tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null ]) ), - "presence_penalty": Schema.optionalKey( + "input_cached_text_tokens": Schema.optionalKey( Schema.Union([ - Schema.Number.check(Schema.isFinite()).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(-2), Schema.isLessThanOrEqualTo(2)], { - "description": - "Number between -2.0 and 2.0. Positive values penalize new tokens based on\nwhether they appear in the text so far, increasing the model's likelihood\nto talk about new topics.\n" - }) - ) + Schema.Number.annotate({ "description": "The aggregated number of cached text input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null ]) ), - "web_search_options": Schema.optionalKey( - Schema.Struct({ - "user_location": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("approximate").annotate({ - "description": "The type of location approximation. Always `approximate`.\n" - }), - "approximate": WebSearchLocation - }).annotate({ "description": "Approximate location parameters for the search.\n" }) - ]) + "input_audio_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "The aggregated number of uncached audio input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "search_context_size": Schema.optionalKey(WebSearchContextSize) - }).annotate({ - "title": "Web search", - "description": - "This tool searches the web for relevant results to use in a response.\nLearn more about the [web search tool](/docs/guides/tools-web-search?api-mode=chat).\n" - }) + Schema.Null + ]) ), - "response_format": Schema.optionalKey( - Schema.Union([ResponseFormatText, ResponseFormatJsonSchema, ResponseFormatJsonObject], { mode: "oneOf" }).annotate({ - "description": - "An object specifying the format that the model must output.\n\nSetting to `{ \"type\": \"json_schema\", \"json_schema\": {...} }` enables\nStructured Outputs which ensures the model will match your supplied JSON\nschema. Learn more in the [Structured Outputs\nguide](/docs/guides/structured-outputs).\n\nSetting to `{ \"type\": \"json_object\" }` enables the older JSON mode, which\nensures the message the model generates is valid JSON. Using `json_schema`\nis preferred for models that support it.\n" - }) + "input_cached_audio_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "The aggregated number of cached audio input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null + ]) ), - "audio": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "voice": Schema.Union([ - VoiceIdsShared, - Schema.Struct({ "id": Schema.String.annotate({ "description": "The custom voice ID, e.g. `voice_1234`." }) }) - .annotate({ "description": "Custom voice reference." }) - ]).annotate({ - "title": "Voice", - "description": - "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `fable`, `nova`, `onyx`,\n`sage`, `shimmer`, `marin`, and `cedar`. You may also provide a\ncustom voice object with an `id`, for example `{ \"id\": \"voice_1234\" }`.\n" - }), - "format": Schema.Literals(["wav", "aac", "mp3", "flac", "opus", "pcm16"]).annotate({ - "description": "Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`,\n`opus`, or `pcm16`.\n" - }) - }).annotate({ - "description": - "Parameters for audio output. Required when audio output is requested with\n`modalities: [\"audio\"]`. [Learn more](/docs/guides/audio).\n" - }) - ])), - "store": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": - "Whether or not to store the output of this chat completion request for\nuse in our [model distillation](/docs/guides/distillation) or\n[evals](/docs/guides/evals) products.\n\nSupports text and image inputs. Note: image inputs over 8MB will be dropped.\n" - }) + "output_audio_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "The aggregated number of audio output tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null + ]) ), - "stream": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": - "If set to true, the model response data will be streamed to the client\nas it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).\nSee the [Streaming section below](/docs/api-reference/chat/streaming)\nfor more information, along with the [streaming responses](/docs/guides/streaming-responses)\nguide for more information on how to handle the streaming events.\n" - }) + "input_image_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "The aggregated number of uncached image input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null + ]) ), - "stop": Schema.optionalKey(StopConfiguration), - "logit_bias": Schema.optionalKey(Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Modify the likelihood of specified tokens appearing in the completion.\n\nAccepts a JSON object that maps tokens (specified by their token ID in the\ntokenizer) to an associated bias value from -100 to 100. Mathematically,\nthe bias is added to the logits generated by the model prior to sampling.\nThe exact effect will vary per model, but values between -1 and 1 should\ndecrease or increase likelihood of selection; values like -100 or 100\nshould result in a ban or exclusive selection of the relevant token.\n" - }) - ])), - "logprobs": Schema.optionalKey( - Schema.Union([Schema.Boolean, Schema.Null]).annotate({ - "description": - "Whether to return log probabilities of the output tokens or not. If true,\nreturns the log probabilities of each output token returned in the\n`content` of `message`.\n" - }) + "input_cached_image_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "The aggregated number of cached image input tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null + ]) ), - "max_tokens": Schema.optionalKey( - Schema.Union([Schema.Number.check(Schema.isInt()), Schema.Null]).annotate({ - "description": - "The maximum number of [tokens](/tokenizer) that can be generated in the\nchat completion. This value can be used to control\n[costs](https://openai.com/api/pricing/) for text generated via API.\n\nThis value is now deprecated in favor of `max_completion_tokens`, and is\nnot compatible with [o-series models](/docs/guides/reasoning).\n" - }) + "output_image_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "The aggregated number of image output tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + Schema.Null + ]) ), - "n": Schema.optionalKey( + "num_model_requests": Schema.Number.annotate({ "description": "The count of requests made to the model." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "project_id": Schema.optionalKey( Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([Schema.isFinite(), Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(128)], { - "description": - "How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs." - }) - ) + Schema.String.annotate({ + "description": "When `group_by=project_id`, this field provides the project ID of the grouped usage result." + }), + Schema.Null ]) ), - "prediction": Schema.optionalKey(Schema.Union([ - Schema.Union([PredictionContent], { mode: "oneOf" }).annotate({ - "description": - "Configuration for a [Predicted Output](/docs/guides/predicted-outputs),\nwhich can greatly improve response times when large parts of the model\nresponse are known ahead of time. This is most common when you are\nregenerating a file with only minor changes to most of the content.\n" - }), - Schema.Null - ])), - "seed": Schema.optionalKey( + "user_id": Schema.optionalKey( Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([ - Schema.isFinite(), - Schema.isGreaterThanOrEqualTo(-9223372036854776000), - Schema.isLessThanOrEqualTo(9223372036854776000) - ], { - "description": - "This feature is in Beta.\nIf specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result.\nDeterminism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend.\n" - }) - ) + Schema.String.annotate({ + "description": "When `group_by=user_id`, this field provides the user ID of the grouped usage result." + }), + Schema.Null ]) ), - "stream_options": Schema.optionalKey(ChatCompletionStreamOptions), - "tools": Schema.optionalKey( - Schema.Array(Schema.Union([ChatCompletionTool, CustomToolChatCompletions], { mode: "oneOf" })).annotate({ - "description": - "A list of tools the model may call. You can provide either\n[custom tools](/docs/guides/function-calling#custom-tools) or\n[function tools](/docs/guides/function-calling).\n" - }) + "api_key_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=api_key_id`, this field provides the API key ID of the grouped usage result." + }), + Schema.Null + ]) ), - "tool_choice": Schema.optionalKey(ChatCompletionToolChoiceOption), - "parallel_tool_calls": Schema.optionalKey(ParallelToolCalls), - "function_call": Schema.optionalKey( + "model": Schema.optionalKey( Schema.Union([ - Schema.Literals(["none", "auto"]).annotate({ - "description": - "`none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function.\n" + Schema.String.annotate({ + "description": "When `group_by=model`, this field provides the model name of the grouped usage result." }), - ChatCompletionFunctionCallOption - ], { mode: "oneOf" }).annotate({ - "description": - "Deprecated in favor of `tool_choice`.\n\nControls which (if any) function is called by the model.\n\n`none` means the model will not call a function and instead generates a\nmessage.\n\n`auto` means the model can pick between generating a message or calling a\nfunction.\n\nSpecifying a particular function via `{\"name\": \"my_function\"}` forces the\nmodel to call that function.\n\n`none` is the default when no functions are present. `auto` is the default\nif functions are present.\n" - }) + Schema.Null + ]) ), - "functions": Schema.optionalKey( - Schema.Array(ChatCompletionFunctions).annotate({ - "description": "Deprecated in favor of `tools`.\n\nA list of functions the model may generate JSON inputs for.\n" - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(128)) + "batch": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": "When `group_by=batch`, this field tells whether the grouped usage result is batch or not." + }), + Schema.Null + ]) + ), + "service_tier": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "When `group_by=service_tier`, this field provides the service tier of the grouped usage result." + }), + Schema.Null + ]) ) +}).annotate({ + "description": "The aggregated Decisions API usage details of the specific time bucket.", + "identifier": "DecisionsUsageResult" }) -export type ListRunStepsResponse = { - readonly "object": string - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean - readonly [x: string]: unknown +export type DecisionsUsageErrorResponse = { readonly "error": DecisionsUsageErrorDetails } +export const DecisionsUsageErrorResponse = Schema.Struct({ "error": DecisionsUsageErrorDetails }).annotate({ + "identifier": "DecisionsUsageErrorResponse" +}) +export type DecisionsUsagePermissionErrorResponse = { readonly "error": DecisionsUsageErrorDetails | string } +export const DecisionsUsagePermissionErrorResponse = Schema.Struct({ + "error": Schema.Union([ + DecisionsUsageErrorDetails, + Schema.String.annotate({ "description": "An explanation of the missing API permissions." }) + ], { mode: "oneOf" }).annotate({ "description": "Details about the permission error." }) +}).annotate({ "identifier": "DecisionsUsagePermissionErrorResponse" }) +export type ExternalStorageResponse = { + readonly "object": "organization.external_storage" + readonly "id": string + readonly "project_id": string + readonly "provider": + | AwsExternalStorageProviderResponse + | AzureExternalStorageProviderResponse + | GcpExternalStorageProviderResponse + | OciExternalStorageProviderResponse + readonly "geography": string + readonly "status": ExternalStorageStatus + readonly "created_at": number } -export const ListRunStepsResponse = Schema.StructWithRest( - Schema.Struct({ - "object": Schema.String, - "data": Schema.Array(RunStepObject), - "first_id": Schema.String, - "last_id": Schema.String, - "has_more": Schema.Boolean - }), - [Schema.Record(Schema.String, Schema.Json)] -) -export type RunStepStreamEvent = - | { readonly "event": "thread.run.step.created"; readonly "data": RunStepObject } - | { readonly "event": "thread.run.step.in_progress"; readonly "data": RunStepObject } - | { readonly "event": "thread.run.step.delta"; readonly "data": RunStepDeltaObject } - | { readonly "event": "thread.run.step.completed"; readonly "data": RunStepObject } - | { readonly "event": "thread.run.step.failed"; readonly "data": RunStepObject } - | { readonly "event": "thread.run.step.cancelled"; readonly "data": RunStepObject } - | { readonly "event": "thread.run.step.expired"; readonly "data": RunStepObject } -export const RunStepStreamEvent = Schema.Union([ - Schema.Struct({ "event": Schema.Literal("thread.run.step.created"), "data": RunStepObject }).annotate({ - "description": "Occurs when a [run step](/docs/api-reference/run-steps/step-object) is created." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.step.in_progress"), "data": RunStepObject }).annotate({ +export const ExternalStorageResponse = Schema.Struct({ + "object": Schema.Literal("organization.external_storage"), + "id": Schema.String, + "project_id": Schema.String, + "provider": Schema.Union([ + AwsExternalStorageProviderResponse, + AzureExternalStorageProviderResponse, + GcpExternalStorageProviderResponse, + OciExternalStorageProviderResponse + ], { mode: "oneOf" }), + "geography": Schema.String, + "status": ExternalStorageStatus, + "created_at": Schema.Number.annotate({ "format": "unixtime" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ "identifier": "ExternalStorageResponse" }) +export type CreateExternalStorageBody = { + readonly "project_id": string + readonly "provider": + | AwsExternalStorageProviderParams + | AzureExternalStorageProviderParams + | GcpExternalStorageProviderParams + | OciExternalStorageProviderParams +} +export const CreateExternalStorageBody = Schema.Struct({ + "project_id": Schema.String, + "provider": Schema.Union([ + AwsExternalStorageProviderParams, + AzureExternalStorageProviderParams, + GcpExternalStorageProviderParams, + OciExternalStorageProviderParams + ], { mode: "oneOf" }) +}).annotate({ "identifier": "CreateExternalStorageBody" }) +export type SpendLimitEnforcement = { readonly "status": SpendLimitEnforcementStatus } +export const SpendLimitEnforcement = Schema.Struct({ + "status": Schema.suspend((): Schema.Codec => SpendLimitEnforcementStatus).annotate({ + "description": "Whether the hard spend limit is currently enforcing." + }) +}).annotate({ + "description": "The current enforcement state of a hard spend limit.", + "identifier": "SpendLimitEnforcement" +}) +export type SynthIDProvenanceResult = { + readonly "type": "synthid" + readonly "outcome": ProvenanceDetectionResultApi + readonly "model": string | null + readonly "generated_at": string | null +} +export const SynthIDProvenanceResult = Schema.Struct({ + "type": Schema.Literal("synthid").annotate({ "description": "The provenance signal type. Always `synthid`." }), + "outcome": Schema.suspend((): Schema.Codec => ProvenanceDetectionResultApi).annotate({ "description": - "Occurs when a [run step](/docs/api-reference/run-steps/step-object) moves to an `in_progress` state." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.step.delta"), "data": RunStepDeltaObject }).annotate({ - "description": "Occurs when parts of a [run step](/docs/api-reference/run-steps/step-object) are being streamed." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.step.completed"), "data": RunStepObject }).annotate({ - "description": "Occurs when a [run step](/docs/api-reference/run-steps/step-object) is completed." + "Whether a supported OpenAI SynthID watermark was detected.\nIf `not_detected`, it means the tool did not find supported signals in the uploaded file. The content could still have been generated by OpenAI if the metadata was stripped or has evidence of tampering, the watermark was degraded, it comes from a legacy generation model, or it was created before provenance signals were available. Content could also still be AI-generated by another company's model, which the tool currently does not detect." }), - Schema.Struct({ "event": Schema.Literal("thread.run.step.failed"), "data": RunStepObject }).annotate({ - "description": "Occurs when a [run step](/docs/api-reference/run-steps/step-object) fails." + "model": Schema.Union([ + Schema.String.annotate({ "description": "The OpenAI model recorded by the provenance signal, when available." }), + Schema.Null + ]), + "generated_at": Schema.Union([ + Schema.String.annotate({ + "description": + "The UTC RFC 3339 timestamp recorded by the provenance signal for when the asset was generated, when available." + }), + Schema.Null + ]) +}).annotate({ "identifier": "SynthIDProvenanceResult" }) +export type C2PAProvenanceResult = { + readonly "type": "c2pa" + readonly "outcome": ProvenanceDetectionResultApi + readonly "validation_state": C2PAValidationStateApi + readonly "issuer": string | null + readonly "model": string | null + readonly "generated_at": string | null +} +export const C2PAProvenanceResult = Schema.Struct({ + "type": Schema.Literal("c2pa").annotate({ "description": "The provenance signal type. Always `c2pa`." }), + "outcome": Schema.suspend((): Schema.Codec => ProvenanceDetectionResultApi).annotate({ + "description": + "Whether a supported OpenAI C2PA provenance signal was detected.\nIf `not_detected`, it means the tool did not find supported signals in the uploaded file. The content could still have been generated by OpenAI if the metadata was stripped or has evidence of tampering, the watermark was degraded, it comes from a legacy generation model, or it was created before provenance signals were available. Content could also still be AI-generated by another company's model, which the tool currently does not detect." }), - Schema.Struct({ "event": Schema.Literal("thread.run.step.cancelled"), "data": RunStepObject }).annotate({ - "description": "Occurs when a [run step](/docs/api-reference/run-steps/step-object) is cancelled." + "validation_state": Schema.suspend((): Schema.Codec => C2PAValidationStateApi).annotate({ + "description": "The validation status of the C2PA manifest in the uploaded image." }), - Schema.Struct({ "event": Schema.Literal("thread.run.step.expired"), "data": RunStepObject }).annotate({ - "description": "Occurs when a [run step](/docs/api-reference/run-steps/step-object) expires." - }) -], { mode: "oneOf" }) -export type RealtimeServerEventResponseCreated = { - readonly "event_id": string - readonly "type": "response.created" - readonly "response": RealtimeResponse + "issuer": Schema.Union([ + Schema.String.annotate({ "description": "The C2PA manifest issuer, when available." }), + Schema.Null + ]), + "model": Schema.Union([ + Schema.String.annotate({ "description": "The OpenAI model recorded by the provenance signal, when available." }), + Schema.Null + ]), + "generated_at": Schema.Union([ + Schema.String.annotate({ + "description": + "The UTC RFC 3339 timestamp recorded by the provenance signal for when the asset was generated, when available." + }), + Schema.Null + ]) +}).annotate({ "identifier": "C2PAProvenanceResult" }) +export type CreateVideoJsonBody = { + readonly "model"?: VideoModel + readonly "prompt": string + readonly "input_reference"?: ImageRefParam_2 + readonly "seconds"?: VideoSeconds + readonly "size"?: VideoSize } -export const RealtimeServerEventResponseCreated = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.created").annotate({ "description": "The event type, must be `response.created`." }), - "response": RealtimeResponse +export const CreateVideoJsonBody = Schema.Struct({ + "model": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VideoModel).annotate({ + "description": "The video generation model to use (allowed values: sora-2, sora-2-pro). Defaults to `sora-2`." + }) + ), + "prompt": Schema.String.annotate({ "description": "Text prompt that describes the video to generate." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(32000).annotate({ "expected": "a string with at most 32000 code points" })), + "input_reference": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ImageRefParam_2).annotate({ + "description": + "Optional reference object that guides generation. Provide exactly one of `image_url` or `file_id`." + }) + ), + "seconds": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VideoSeconds).annotate({ + "description": "Clip duration in seconds (allowed values: 4, 8, 12). Defaults to 4 seconds." + }) + ), + "size": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VideoSize).annotate({ + "description": + "Output resolution formatted as width x height (allowed values: 720x1280, 1280x720, 1024x1792, 1792x1024). Defaults to 720x1280." + }) + ) }).annotate({ - "description": - "Returned when a new Response is created. The first event of response creation,\nwhere the response is in an initial state of `in_progress`.\n" + "title": "Create video JSON request", + "description": "JSON parameters for creating a new video generation job.", + "identifier": "CreateVideoJsonBody" }) -export type RealtimeServerEventResponseDone = { - readonly "event_id": string - readonly "type": "response.done" - readonly "response": RealtimeResponse +export type CreateVideoMultipartBodyMultipart = { + readonly "model"?: VideoModel + readonly "prompt": string + readonly "input_reference"?: __ClientMultipartFile | ImageRefParam_2 + readonly "seconds"?: VideoSeconds + readonly "size"?: VideoSize } -export const RealtimeServerEventResponseDone = Schema.Struct({ - "event_id": Schema.String.annotate({ "description": "The unique ID of the server event." }), - "type": Schema.Literal("response.done").annotate({ "description": "The event type, must be `response.done`." }), - "response": RealtimeResponse +export const CreateVideoMultipartBodyMultipart = Schema.Struct({ + "model": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VideoModel).annotate({ + "description": "The video generation model to use (allowed values: sora-2, sora-2-pro). Defaults to `sora-2`." + }) + ), + "prompt": Schema.String.annotate({ "description": "Text prompt that describes the video to generate." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(32000).annotate({ "expected": "a string with at most 32000 code points" })), + "input_reference": Schema.optionalKey( + Schema.Union([ + __ClientMultipartFile, + Schema.suspend((): Schema.Codec => ImageRefParam_2).annotate({ + "description": + "Optional reference asset upload or reference object that guides generation. Provide exactly one of `image_url` or `file_id` when using an object." + }) + ], { mode: "oneOf" }) + ), + "seconds": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VideoSeconds).annotate({ + "description": "Clip duration in seconds (allowed values: 4, 8, 12). Defaults to 4 seconds." + }) + ), + "size": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VideoSize).annotate({ + "description": + "Output resolution formatted as width x height (allowed values: 720x1280, 1280x720, 1024x1792, 1792x1024). Defaults to 720x1280." + }) + ) }).annotate({ - "description": - "Returned when a Response is done streaming. Always emitted, no matter the \nfinal state. The Response object included in the `response.done` event will \ninclude all output Items in the Response but will omit the raw audio data.\n\nClients should check the `status` field of the Response to determine if it was successful\n(`completed`) or if there was another outcome: `cancelled`, `failed`, or `incomplete`.\n\nA response will contain all output items that were generated during the response, excluding\nany audio content.\n" + "title": "Create video multipart request", + "description": "Multipart parameters for creating a new video generation job.", + "identifier": "CreateVideoMultipartBodyMultipart" }) -export type RealtimeClientEventResponseCreate = { - readonly "event_id"?: string - readonly "type": "response.create" - readonly "response"?: RealtimeResponseCreateParams -} -export const RealtimeClientEventResponseCreate = Schema.Struct({ - "event_id": Schema.optionalKey( - Schema.String.annotate({ "description": "Optional client-generated ID used to identify this event." }).check( - Schema.isMaxLength(512) - ) - ), - "type": Schema.Literal("response.create").annotate({ "description": "The event type, must be `response.create`." }), - "response": Schema.optionalKey(RealtimeResponseCreateParams) +export type CreateVideoEditJsonBody = { readonly "video": VideoReferenceInputParam; readonly "prompt": string } +export const CreateVideoEditJsonBody = Schema.Struct({ + "video": Schema.suspend((): Schema.Codec => VideoReferenceInputParam).annotate({ + "description": "Reference to the completed video to edit." + }), + "prompt": Schema.String.annotate({ "description": "Text prompt that describes how to edit the source video." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(32000).annotate({ "expected": "a string with at most 32000 code points" })) }).annotate({ - "description": - "This event instructs the server to create a Response, which means triggering \nmodel inference. When in Server VAD mode, the server will create Responses \nautomatically.\n\nA Response will include at least one Item, and may have two, in which case \nthe second will be a function call. These Items will be appended to the \nconversation history by default.\n\nThe server will respond with a `response.created` event, events for Items \nand content created, and finally a `response.done` event to indicate the \nResponse is complete.\n\nThe `response.create` event includes inference configuration like \n`instructions` and `tools`. If these are set, they will override the Session's \nconfiguration for this Response only.\n\nResponses can be created out-of-band of the default Conversation, meaning that they can\nhave arbitrary input, and it's possible to disable writing the output to the Conversation.\nOnly one Response can write to the default Conversation at a time, but otherwise multiple\nResponses can be created in parallel. The `metadata` field is a good way to disambiguate\nmultiple simultaneous Responses.\n\nClients can set `conversation` to `none` to create a Response that does not write to the default\nConversation. Arbitrary input can be provided with the `input` field, which is an array accepting\nraw Items and references to existing Items.\n" + "title": "Create video edit JSON request", + "description": "JSON parameters for editing an existing generated video.", + "identifier": "CreateVideoEditJsonBody" }) -export type ListAssistantsResponse = { - readonly "object": string - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean +export type CreateVideoEditMultipartBodyMultipart = { + readonly "video": __ClientMultipartFile | VideoReferenceInputParam + readonly "prompt": string } -export const ListAssistantsResponse = Schema.Struct({ - "object": Schema.String, - "data": Schema.Array(AssistantObject), - "first_id": Schema.String, - "last_id": Schema.String, - "has_more": Schema.Boolean +export const CreateVideoEditMultipartBodyMultipart = Schema.Struct({ + "video": Schema.Union([ + __ClientMultipartFile, + Schema.suspend((): Schema.Codec => VideoReferenceInputParam).annotate({ + "description": "Reference to the completed video to edit." + }) + ], { mode: "oneOf" }), + "prompt": Schema.String.annotate({ "description": "Text prompt that describes how to edit the source video." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(32000).annotate({ "expected": "a string with at most 32000 code points" })) +}).annotate({ + "title": "Create video edit multipart request", + "description": "Parameters for editing an existing generated video.", + "identifier": "CreateVideoEditMultipartBodyMultipart" }) -export type ListRunsResponse = { - readonly "object": string - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean +export type CreateVideoExtendJsonBody = { + readonly "video": VideoReferenceInputParam + readonly "prompt": string + readonly "seconds": VideoSeconds } -export const ListRunsResponse = Schema.Struct({ - "object": Schema.String, - "data": Schema.Array(RunObject), - "first_id": Schema.String, - "last_id": Schema.String, - "has_more": Schema.Boolean -}) -export type RunStreamEvent = - | { readonly "event": "thread.run.created"; readonly "data": RunObject } - | { readonly "event": "thread.run.queued"; readonly "data": RunObject } - | { readonly "event": "thread.run.in_progress"; readonly "data": RunObject } - | { readonly "event": "thread.run.requires_action"; readonly "data": RunObject } - | { readonly "event": "thread.run.completed"; readonly "data": RunObject } - | { readonly "event": "thread.run.incomplete"; readonly "data": RunObject } - | { readonly "event": "thread.run.failed"; readonly "data": RunObject } - | { readonly "event": "thread.run.cancelling"; readonly "data": RunObject } - | { readonly "event": "thread.run.cancelled"; readonly "data": RunObject } - | { readonly "event": "thread.run.expired"; readonly "data": RunObject } -export const RunStreamEvent = Schema.Union([ - Schema.Struct({ "event": Schema.Literal("thread.run.created"), "data": RunObject }).annotate({ - "description": "Occurs when a new [run](/docs/api-reference/runs/object) is created." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.queued"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) moves to a `queued` status." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.in_progress"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) moves to an `in_progress` status." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.requires_action"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) moves to a `requires_action` status." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.completed"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) is completed." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.incomplete"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) ends with status `incomplete`." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.failed"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) fails." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.cancelling"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) moves to a `cancelling` status." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.cancelled"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) is cancelled." - }), - Schema.Struct({ "event": Schema.Literal("thread.run.expired"), "data": RunObject }).annotate({ - "description": "Occurs when a [run](/docs/api-reference/runs/object) expires." - }) -], { mode: "oneOf" }) -export type Tool = - | FunctionTool - | FileSearchTool - | ComputerTool - | ComputerUsePreviewTool - | WebSearchTool - | MCPTool - | CodeInterpreterTool - | ImageGenTool - | LocalShellToolParam - | FunctionShellToolParam - | CustomToolParam - | NamespaceToolParam - | ToolSearchToolParam - | WebSearchPreviewTool - | ApplyPatchToolParam -export const Tool = Schema.Union([ - FunctionTool, - FileSearchTool, - ComputerTool, - ComputerUsePreviewTool, - WebSearchTool, - MCPTool, - CodeInterpreterTool, - ImageGenTool, - LocalShellToolParam, - FunctionShellToolParam, - CustomToolParam, - NamespaceToolParam, - ToolSearchToolParam, - WebSearchPreviewTool, - ApplyPatchToolParam -], { mode: "oneOf" }).annotate({ "description": "A tool that can be used to generate a response.\n" }) -export type CreateEvalItem = { readonly "role": string; readonly "content": string } | { - readonly "role": "user" | "assistant" | "system" | "developer" - readonly "content": EvalItemContent - readonly "type"?: "message" -} -export const CreateEvalItem = Schema.Union([ - Schema.Struct({ - "role": Schema.String.annotate({ - "description": "The role of the message (e.g. \"system\", \"assistant\", \"user\")." - }), - "content": Schema.String.annotate({ "description": "The content of the message." }) - }).annotate({ - "title": "CreateEvalItem", - "description": - "A chat message that makes up the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." +export const CreateVideoExtendJsonBody = Schema.Struct({ + "video": Schema.suspend((): Schema.Codec => VideoReferenceInputParam).annotate({ + "description": "Reference to the completed video to extend." }), - Schema.Struct({ - "role": Schema.Literals(["user", "assistant", "system", "developer"]).annotate({ - "description": "The role of the message input. One of `user`, `assistant`, `system`, or\n`developer`.\n" - }), - "content": EvalItemContent, - "type": Schema.optionalKey( - Schema.Literal("message").annotate({ "description": "The type of the message input. Always `message`.\n" }) - ) - }).annotate({ - "title": "CreateEvalItem", - "description": - "A chat message that makes up the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." + "prompt": Schema.String.annotate({ "description": "Updated text prompt that directs the extension generation." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(32000).annotate({ "expected": "a string with at most 32000 code points" }) + ), + "seconds": Schema.suspend((): Schema.Codec => VideoSeconds).annotate({ + "description": "Length of the newly generated extension segment in seconds (allowed values: 4, 8, 12, 16, 20)." }) -], { mode: "oneOf" }) -export type EvalItem = { - readonly "role": "user" | "assistant" | "system" | "developer" - readonly "content": EvalItemContent - readonly "type"?: "message" -} -export const EvalItem = Schema.Struct({ - "role": Schema.Literals(["user", "assistant", "system", "developer"]).annotate({ - "description": "The role of the message input. One of `user`, `assistant`, `system`, or\n`developer`.\n" - }), - "content": EvalItemContent, - "type": Schema.optionalKey( - Schema.Literal("message").annotate({ "description": "The type of the message input. Always `message`.\n" }) - ) }).annotate({ - "title": "Eval message object", - "description": - "A message input to the model with a role indicating instruction following\nhierarchy. Instructions given with the `developer` or `system` role take\nprecedence over instructions given with the `user` role. Messages with the\n`assistant` role are presumed to have been generated by the model in previous\ninteractions.\n" + "title": "Create video extension JSON request", + "description": "JSON parameters for extending an existing generated video.", + "identifier": "CreateVideoExtendJsonBody" }) -export type OutputMessage = { - readonly "id": string - readonly "type": "message" - readonly "role": "assistant" - readonly "content": ReadonlyArray - readonly "phase"?: MessagePhase | null - readonly "status": "in_progress" | "completed" | "incomplete" -} -export const OutputMessage = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique ID of the output message.\n" }), - "type": Schema.Literal("message").annotate({ "description": "The type of the output message. Always `message`.\n" }), - "role": Schema.Literal("assistant").annotate({ - "description": "The role of the output message. Always `assistant`.\n" - }), - "content": Schema.Array(OutputMessageContent).annotate({ "description": "The content of the output message.\n" }), - "phase": Schema.optionalKey(Schema.Union([MessagePhase, Schema.Null])), - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": - "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" - }) -}).annotate({ "title": "Output message", "description": "An output message from the model.\n" }) -export type ComputerToolCall = { - readonly "type": "computer_call" - readonly "id": string - readonly "call_id": string - readonly "action"?: ComputerAction - readonly "actions"?: ComputerActionList - readonly "pending_safety_checks": ReadonlyArray - readonly "status": "in_progress" | "completed" | "incomplete" +export type CreateVideoExtendMultipartBodyMultipart = { + readonly "video": VideoReferenceInputParam | __ClientMultipartFile + readonly "prompt": string + readonly "seconds": VideoSeconds } -export const ComputerToolCall = Schema.Struct({ - "type": Schema.Literal("computer_call").annotate({ - "description": "The type of the computer call. Always `computer_call`." - }), - "id": Schema.String.annotate({ "description": "The unique ID of the computer call." }), - "call_id": Schema.String.annotate({ - "description": "An identifier used when responding to the tool call with output.\n" - }), - "action": Schema.optionalKey(ComputerAction), - "actions": Schema.optionalKey(ComputerActionList), - "pending_safety_checks": Schema.Array(ComputerCallSafetyCheckParam).annotate({ - "description": "The pending safety checks for the computer call.\n" - }), - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": - "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" +export const CreateVideoExtendMultipartBodyMultipart = Schema.Struct({ + "video": Schema.Union([ + Schema.suspend((): Schema.Codec => VideoReferenceInputParam).annotate({ + "description": "Reference to the completed video to extend." + }), + __ClientMultipartFile + ], { mode: "oneOf" }), + "prompt": Schema.String.annotate({ "description": "Updated text prompt that directs the extension generation." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(32000).annotate({ "expected": "a string with at most 32000 code points" }) + ), + "seconds": Schema.suspend((): Schema.Codec => VideoSeconds).annotate({ + "description": "Length of the newly generated extension segment in seconds (allowed values: 4, 8, 12, 16, 20)." }) }).annotate({ - "title": "Computer tool call", - "description": - "A tool call to a computer use tool. See the\n[computer use guide](/docs/guides/tools-computer-use) for more information.\n" + "title": "Create video extension multipart request", + "description": "Multipart parameters for extending an existing generated video.", + "identifier": "CreateVideoExtendMultipartBodyMultipart" }) -export type ThreadItemListResource = { +export type SkillListResource = { readonly "object": "list" - readonly "data": ReadonlyArray + readonly "data": ReadonlyArray readonly "first_id": string | null readonly "last_id": string | null readonly "has_more": boolean } -export const ThreadItemListResource = Schema.Struct({ +export const SkillListResource = Schema.Struct({ "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), - "data": Schema.Array(ThreadItem).annotate({ "description": "A list of items" }), + "data": Schema.Array(SkillResource).annotate({ "description": "A list of items" }), + "first_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the first item in the list." }), + Schema.Null + ]), + "last_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the last item in the list." }), + Schema.Null + ]), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) +}).annotate({ "identifier": "SkillListResource" }) +export type SkillVersionListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const SkillVersionListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), + "data": Schema.Array(SkillVersionResource).annotate({ "description": "A list of items" }), "first_id": Schema.Union([ Schema.String.annotate({ "description": "The ID of the first item in the list." }), Schema.Null @@ -22721,192 +21945,18750 @@ export const ThreadItemListResource = Schema.Struct({ Schema.Null ]), "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) +}).annotate({ "identifier": "SkillVersionListResource" }) +export type ChatkitWorkflow = { + readonly "id": string + readonly "version": string | null + readonly "state_variables": { readonly [x: string]: string | number | boolean | number | null } | null + readonly "tracing": ChatkitWorkflowTracing +} +export const ChatkitWorkflow = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the workflow backing the session." }), + "version": Schema.Union([ + Schema.String.annotate({ + "description": + "Specific workflow version used for the session. Defaults to null when using the latest deployment." + }), + Schema.Null + ]), + "state_variables": Schema.Union([ + Schema.Record( + Schema.String, + Schema.Union([ + Schema.String, + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Boolean, + Schema.Finite, + Schema.Null + ]) + ).annotate({ + "description": + "State variable key-value pairs applied when invoking the workflow. Defaults to null when no overrides were provided." + }), + Schema.Null + ]), + "tracing": Schema.suspend((): Schema.Codec => ChatkitWorkflowTracing).annotate({ + "description": "Tracing settings applied to the workflow." + }) }).annotate({ - "title": "Thread Items", - "description": "A paginated list of thread items rendered for the ChatKit API." + "title": "Workflow", + "description": "Workflow metadata and state returned for the session.", + "identifier": "ChatkitWorkflow" }) -export type InputItem = - | EasyInputMessage - | { - readonly "type"?: "message" - readonly "role": "user" | "system" | "developer" - readonly "status"?: "in_progress" | "completed" | "incomplete" - readonly "content": InputMessageContentList - } - | { - readonly "id": string - readonly "type": "message" - readonly "role": "assistant" - readonly "content": ReadonlyArray - readonly "phase"?: MessagePhase | null - readonly "status": "in_progress" | "completed" | "incomplete" - } - | { - readonly "id": string - readonly "type": "file_search_call" - readonly "status": "in_progress" | "searching" | "completed" | "incomplete" | "failed" - readonly "queries": ReadonlyArray - readonly "results"?: - | ReadonlyArray< - { - readonly "file_id"?: string - readonly "text"?: string - readonly "filename"?: string - readonly "attributes"?: VectorStoreFileAttributes - readonly "score"?: number - } - > - | null - } - | { - readonly "type": "computer_call" - readonly "id": string - readonly "call_id": string - readonly "action"?: ComputerAction - readonly "actions"?: ComputerActionList - readonly "pending_safety_checks": ReadonlyArray - readonly "status": "in_progress" | "completed" | "incomplete" - } - | { - readonly "id"?: string | null - readonly "call_id": string - readonly "type": "computer_call_output" - readonly "output": ComputerScreenshotImage - readonly "acknowledged_safety_checks"?: ReadonlyArray | null +export type ChatSessionChatkitConfiguration = { + readonly "automatic_thread_titling": ChatSessionAutomaticThreadTitling + readonly "file_upload": ChatSessionFileUpload + readonly "history": ChatSessionHistory +} +export const ChatSessionChatkitConfiguration = Schema.Struct({ + "automatic_thread_titling": Schema.suspend((): Schema.Codec => + ChatSessionAutomaticThreadTitling + ).annotate({ "description": "Automatic thread titling preferences." }), + "file_upload": Schema.suspend((): Schema.Codec => ChatSessionFileUpload).annotate({ + "description": "Upload settings for the session." + }), + "history": Schema.suspend((): Schema.Codec => ChatSessionHistory).annotate({ + "description": "History retention configuration." + }) +}).annotate({ + "title": "ChatKit configuration", + "description": "ChatKit configuration for the session.", + "identifier": "ChatSessionChatkitConfiguration" +}) +export type WorkflowParam = { + readonly "id": string + readonly "version"?: string + readonly "state_variables"?: { readonly [x: string]: string | number | boolean | number } + readonly "tracing"?: WorkflowTracingParam +} +export const WorkflowParam = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier for the workflow invoked by the session." }), + "version": Schema.optionalKey( + Schema.String.annotate({ + "description": "Specific workflow version to run. Defaults to the latest deployed version." + }) + ), + "state_variables": Schema.optionalKey( + Schema.Record( + Schema.String, + Schema.Union([ + Schema.String.check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Boolean, + Schema.Finite + ], { mode: "oneOf" }) + ).annotate({ + "description": + "State variables forwarded to the workflow. Keys may be up to 64 characters, values must be primitive types, and the map defaults to an empty object." + }).check(Schema.isMaxProperties(64).annotate({ "expected": "a value with at most 64 entries" })) + ), + "tracing": Schema.optionalKey( + Schema.suspend((): Schema.Codec => WorkflowTracingParam).annotate({ + "description": + "Optional tracing overrides for the workflow invocation. When omitted, tracing is enabled by default." + }) + ) +}).annotate({ + "title": "Workflow settings", + "description": "Workflow reference and overrides applied to the chat session.", + "identifier": "WorkflowParam" +}) +export type ChatkitConfigurationParam = { + readonly "automatic_thread_titling"?: AutomaticThreadTitlingParam + readonly "file_upload"?: FileUploadParam + readonly "history"?: HistoryParam +} +export const ChatkitConfigurationParam = Schema.Struct({ + "automatic_thread_titling": Schema.optionalKey( + Schema.suspend((): Schema.Codec => AutomaticThreadTitlingParam).annotate({ + "description": + "Configuration for automatic thread titling. When omitted, automatic thread titling is enabled by default." + }) + ), + "file_upload": Schema.optionalKey( + Schema.suspend((): Schema.Codec => FileUploadParam).annotate({ + "description": + "Configuration for upload enablement and limits. When omitted, uploads are disabled by default (max_files 10, max_file_size 512 MB)." + }) + ), + "history": Schema.optionalKey( + Schema.suspend((): Schema.Codec => HistoryParam).annotate({ + "description": + "Configuration for chat history retention. When omitted, history is enabled by default with no limit on recent_threads (null)." + }) + ) +}).annotate({ + "title": "ChatKit configuration overrides", + "description": "Optional per-session configuration settings for ChatKit behavior.", + "identifier": "ChatkitConfigurationParam" +}) +export type Attachment = { + readonly "type": AttachmentType + readonly "id": string + readonly "name": string + readonly "mime_type": string + readonly "preview_url": string | null +} +export const Attachment = Schema.Struct({ + "type": Schema.suspend((): Schema.Codec => AttachmentType).annotate({ + "description": "Attachment discriminator." + }), + "id": Schema.String.annotate({ "description": "Identifier for the attachment." }), + "name": Schema.String.annotate({ "description": "Original display name for the attachment." }), + "mime_type": Schema.String.annotate({ "description": "MIME type of the attachment." }), + "preview_url": Schema.Union([ + Schema.String.annotate({ "description": "Preview URL for rendering the attachment inline.", "format": "uri" }), + Schema.Null + ]) +}).annotate({ + "title": "Attachment", + "description": "Attachment metadata included on thread items.", + "identifier": "Attachment" +}) +export type InferenceOptions = { readonly "tool_choice": ToolChoice | null; readonly "model": string | null } +export const InferenceOptions = Schema.Struct({ + "tool_choice": Schema.Union([ + Schema.suspend((): Schema.Codec => ToolChoice).annotate({ + "description": "Preferred tool to invoke. Defaults to null when ChatKit should auto-select." + }), + Schema.Null + ]), + "model": Schema.Union([ + Schema.String.annotate({ + "description": "Model name that generated the response. Defaults to null when using the session default." + }), + Schema.Null + ]) +}).annotate({ + "title": "Inference options", + "description": "Model and tool overrides applied when generating the assistant response.", + "identifier": "InferenceOptions" +}) +export type FileAnnotation = { readonly "type": "file"; readonly "source": FileAnnotationSource } +export const FileAnnotation = Schema.Struct({ + "type": Schema.Literal("file").annotate({ + "description": "Type discriminator that is always `file` for this annotation." + }), + "source": Schema.suspend((): Schema.Codec => FileAnnotationSource).annotate({ + "description": "File attachment referenced by the annotation." + }) +}).annotate({ + "title": "File annotation", + "description": "Annotation that references an uploaded file.", + "identifier": "FileAnnotation" +}) +export type UrlAnnotation = { readonly "type": "url"; readonly "source": UrlAnnotationSource } +export const UrlAnnotation = Schema.Struct({ + "type": Schema.Literal("url").annotate({ + "description": "Type discriminator that is always `url` for this annotation." + }), + "source": Schema.suspend((): Schema.Codec => UrlAnnotationSource).annotate({ + "description": "URL referenced by the annotation." + }) +}).annotate({ + "title": "URL annotation", + "description": "Annotation that references a URL.", + "identifier": "UrlAnnotation" +}) +export type ClientToolCallItem = { + readonly "id": string + readonly "object": "chatkit.thread_item" + readonly "created_at": number + readonly "thread_id": string + readonly "type": "chatkit.client_tool_call" + readonly "status": ClientToolCallStatus + readonly "call_id": string + readonly "name": string + readonly "arguments": string + readonly "output": string | null +} +export const ClientToolCallItem = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), + "object": Schema.Literal("chatkit.thread_item").annotate({ + "description": "Type discriminator that is always `chatkit.thread_item`." + }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) for when the item was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), + "type": Schema.Literal("chatkit.client_tool_call").annotate({ + "description": "Type discriminator that is always `chatkit.client_tool_call`." + }), + "status": Schema.suspend((): Schema.Codec => ClientToolCallStatus).annotate({ + "description": "Execution status for the tool call." + }), + "call_id": Schema.String.annotate({ "description": "Identifier for the client tool call." }), + "name": Schema.String.annotate({ "description": "Tool name that was invoked." }), + "arguments": Schema.String.annotate({ "description": "JSON-encoded arguments that were sent to the tool." }), + "output": Schema.Union([ + Schema.String.annotate({ + "description": "JSON-encoded output captured from the tool. Defaults to null while execution is in progress." + }), + Schema.Null + ]) +}).annotate({ + "title": "Client tool call", + "description": "Record of a client side tool invocation initiated by the assistant.", + "identifier": "ClientToolCallItem" +}) +export type TaskItem = { + readonly "id": string + readonly "object": "chatkit.thread_item" + readonly "created_at": number + readonly "thread_id": string + readonly "type": "chatkit.task" + readonly "task_type": TaskType + readonly "heading": string | null + readonly "summary": string | null +} +export const TaskItem = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), + "object": Schema.Literal("chatkit.thread_item").annotate({ + "description": "Type discriminator that is always `chatkit.thread_item`." + }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) for when the item was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), + "type": Schema.Literal("chatkit.task").annotate({ + "description": "Type discriminator that is always `chatkit.task`." + }), + "task_type": Schema.suspend((): Schema.Codec => TaskType).annotate({ + "description": "Subtype for the task." + }), + "heading": Schema.Union([ + Schema.String.annotate({ "description": "Optional heading for the task. Defaults to null when not provided." }), + Schema.Null + ]), + "summary": Schema.Union([ + Schema.String.annotate({ + "description": "Optional summary that describes the task. Defaults to null when omitted." + }), + Schema.Null + ]) +}).annotate({ + "title": "Task item", + "description": "Task emitted by the workflow to show progress and status updates.", + "identifier": "TaskItem" +}) +export type TaskGroupTask = { + readonly "type": TaskType + readonly "heading": string | null + readonly "summary": string | null +} +export const TaskGroupTask = Schema.Struct({ + "type": Schema.suspend((): Schema.Codec => TaskType).annotate({ + "description": "Subtype for the grouped task." + }), + "heading": Schema.Union([ + Schema.String.annotate({ + "description": "Optional heading for the grouped task. Defaults to null when not provided." + }), + Schema.Null + ]), + "summary": Schema.Union([ + Schema.String.annotate({ + "description": "Optional summary that describes the grouped task. Defaults to null when omitted." + }), + Schema.Null + ]) +}).annotate({ + "title": "Task group task", + "description": "Task entry that appears within a TaskGroup.", + "identifier": "TaskGroupTask" +}) +export type ThreadResource = { + readonly "id": string + readonly "object": "chatkit.thread" + readonly "created_at": number + readonly "title": string | null + readonly "status": ActiveStatus | LockedStatus | ClosedStatus + readonly "user": string +} +export const ThreadResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the thread." }), + "object": Schema.Literal("chatkit.thread").annotate({ + "description": "Type discriminator that is always `chatkit.thread`." + }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) for when the thread was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "title": Schema.Union([ + Schema.String.annotate({ + "description": "Optional human-readable title for the thread. Defaults to null when no title has been generated." + }), + Schema.Null + ]), + "status": Schema.Union([ActiveStatus, LockedStatus, ClosedStatus], { mode: "oneOf" }).annotate({ + "description": "Current status for the thread. Defaults to `active` for newly created threads." + }), + "user": Schema.String.annotate({ + "description": "Free-form string that identifies your end user who owns the thread." + }) +}).annotate({ + "title": "The thread object", + "description": "Represents a ChatKit thread and its current status.", + "identifier": "ThreadResource" +}) +export type DecisionInputImage = { + readonly "image_url": string + readonly "detail"?: ImageDetailParam | null + readonly "type": "input_image" +} +export const DecisionInputImage = Schema.Struct({ + "image_url": Schema.String.annotate({ + "description": "A base64-encoded image in a data URL or a publicly accessible HTTP(S) image URL." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1073741824).annotate({ "expected": "a string with at most 1073741824 code points" }) + ).check( + Schema.isPattern(new RegExp("^(data:|https?:\\/\\/)", "u")).annotate({ + "expected": "a string matching the RegExp ^(data:|https?:\\/\\/)" + }) + ), + "detail": Schema.optionalKey( + Schema.Union([ImageDetailParam, Schema.Null]).annotate({ + "description": "The image detail level, using the selected model's image profile. Defaults to auto." + }) + ), + "type": Schema.Literal("input_image") +}).annotate({ + "description": + "An image provided as a base64 data URL or a publicly accessible HTTP(S) URL. File IDs are not supported.", + "identifier": "DecisionInputImage" +}) +export type ChoiceOptionParam = { readonly "value": ChoiceValueParam; readonly "description"?: string } +export const ChoiceOptionParam = Schema.Struct({ + "value": ChoiceValueParam, + "description": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}).annotate({ "identifier": "ChoiceOptionParam" }) +export type QuestionParamScore = { + readonly "type": "score" + readonly "name"?: string + readonly "instructions": string + readonly "levels": ReadonlyArray +} +export const QuestionParamScore = Schema.Struct({ + "type": Schema.Literal("score").annotate({ "description": "The type of the object. Always `score`." }), + "name": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "instructions": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "levels": Schema.Array(ScoreLevelParam).check( + Schema.isMinLength(2).annotate({ "expected": "a value with a length of at least 2" }) + ).check(Schema.isMaxLength(10).annotate({ "expected": "a value with a length of at most 10" })) +}).annotate({ + "description": "Rate the input against the supplied ordered levels.", + "identifier": "QuestionParamScore" +}) +export type ChoiceProbabilityResource = { readonly "value": ChoiceValueResource; readonly "probability": number } +export const ChoiceProbabilityResource = Schema.Struct({ "value": ChoiceValueResource, "probability": Schema.Finite }) + .annotate({ "identifier": "ChoiceProbabilityResource" }) +export type AnswerResourceScore = { + readonly "type": "score" + readonly "name": string | null + readonly "score": number + readonly "probabilities": ReadonlyArray + readonly "confidence": number +} +export const AnswerResourceScore = Schema.Struct({ + "type": Schema.Literal("score").annotate({ "description": "The type of the object. Always `score`." }), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]), + "score": Schema.Finite, + "probabilities": Schema.Array(ScoreProbabilityResource).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "confidence": Schema.Finite +}).annotate({ "identifier": "AnswerResourceScore" }) +export type ResponseUsageResource = { + readonly "input_tokens": number + readonly "input_tokens_details": InputTokensDetailsResource + readonly "output_tokens": number + readonly "output_tokens_details": OutputTokensDetailsResource + readonly "total_tokens": number +} +export const ResponseUsageResource = Schema.Struct({ + "input_tokens": Schema.Number.annotate({ "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check( + Schema.isGreaterThanOrEqualTo(-2147483648).annotate({ "expected": "a value greater than or equal to -2147483648" }) + ).check(Schema.isLessThanOrEqualTo(2147483647).annotate({ "expected": "a value less than or equal to 2147483647" })), + "input_tokens_details": InputTokensDetailsResource, + "output_tokens": Schema.Number.annotate({ "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check( + Schema.isGreaterThanOrEqualTo(-2147483648).annotate({ "expected": "a value greater than or equal to -2147483648" }) + ).check(Schema.isLessThanOrEqualTo(2147483647).annotate({ "expected": "a value less than or equal to 2147483647" })), + "output_tokens_details": OutputTokensDetailsResource, + "total_tokens": Schema.Number.annotate({ "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check( + Schema.isGreaterThanOrEqualTo(-2147483648).annotate({ "expected": "a value greater than or equal to -2147483648" }) + ).check(Schema.isLessThanOrEqualTo(2147483647).annotate({ "expected": "a value less than or equal to 2147483647" })) +}).annotate({ "identifier": "ResponseUsageResource" }) +export type HostedEnvironmentFileResource = HostedEnvironmentFileResourceFileId | HostedEnvironmentFileResourceInline +export const HostedEnvironmentFileResource = Schema.Union([ + HostedEnvironmentFileResourceFileId, + HostedEnvironmentFileResourceInline +], { mode: "oneOf" }).annotate({ + "description": "Metadata for a file materialized in an OpenAI-hosted execution environment.", + "identifier": "HostedEnvironmentFileResource" +}) +export type HostedSkillResource = HostedSkillResourceSkillReference | HostedSkillResourceInline +export const HostedSkillResource = Schema.Union([HostedSkillResourceSkillReference, HostedSkillResourceInline], { + mode: "oneOf" +}).annotate({ + "description": "A skill installed in an OpenAI-hosted environment.", + "identifier": "HostedSkillResource" +}) +export type HostedPluginResource = HostedPluginResourceInline +export const HostedPluginResource = Schema.Union([HostedPluginResourceInline], { mode: "oneOf" }).annotate({ + "description": "A plugin installed in an OpenAI-hosted environment.", + "identifier": "HostedPluginResource" +}) +export type ErrorResponse_2 = { readonly "error": ErrorBodyResource } +export const ErrorResponse_2 = Schema.Struct({ + "error": Schema.suspend((): Schema.Codec => ErrorBodyResource).annotate({ + "description": "The error returned by the API." + }) +}).annotate({ "description": "An API error response.", "identifier": "ErrorResponse-2" }) +export type NetworkPolicyParam = { + readonly "access": NetworkAccessParam + readonly "allowed_domains"?: ReadonlyArray | null + readonly "blocked_domains"?: ReadonlyArray | null +} +export const NetworkPolicyParam = Schema.Struct({ + "access": Schema.suspend((): Schema.Codec => NetworkAccessParam).annotate({ + "description": "The environment's network access mode." + }), + "allowed_domains": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "Domains the environment may access when network access is restricted." }) + ), + "blocked_domains": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(100).annotate({ "expected": "a value with a length of at most 100" }) + ), + Schema.Null + ]).annotate({ + "description": + "Domains blocked for both executor and browser when access is restricted. A nonempty list requires `access: restricted` and cannot be combined with nonempty `allowed_domains`. Wildcard domains are not supported." + }) + ) +}).annotate({ "description": "Network access for an OpenAI-hosted environment.", "identifier": "NetworkPolicyParam" }) +export type InlineCapabilitySourceParam = InlineCapabilitySourceParamBase64 +export const InlineCapabilitySourceParam = Schema.Union([InlineCapabilitySourceParamBase64], { mode: "oneOf" }) + .annotate({ + "description": "The encoded ZIP archive for an inline skill or plugin.", + "identifier": "InlineCapabilitySourceParam" + }) +export type HostedEnvironmentFileParam = HostedEnvironmentFileParamFileId | HostedEnvironmentFileParamInline +export const HostedEnvironmentFileParam = Schema.Union([ + HostedEnvironmentFileParamFileId, + HostedEnvironmentFileParamInline +], { mode: "oneOf" }).annotate({ + "description": "A file materialized in an OpenAI-hosted execution environment.", + "identifier": "HostedEnvironmentFileParam" +}) +export type EnvironmentFileListResource = { + readonly "object": EnvironmentFilePageObjectResource + readonly "data": ReadonlyArray + readonly "next": string | null + readonly "has_more": boolean +} +export const EnvironmentFileListResource = Schema.Struct({ + "object": Schema.suspend((): Schema.Codec => EnvironmentFilePageObjectResource) + .annotate({ "description": "The object type. Always `page`." }), + "data": Schema.Array(EnvironmentFileResource).annotate({ "description": "Files available on the current page." }) + .check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "next": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The opaque cursor to use when requesting the next page, if any." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether more files follow this page." }) +}).annotate({ + "description": "A paginated list of live execution environment files.", + "identifier": "EnvironmentFileListResource" +}) +export type SessionEventAgentSessionTurnContentPartAdded = { + readonly "type": "agent.session.turn.content_part.added" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "part": OutputTextResource +} +export const SessionEventAgentSessionTurnContentPartAdded = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.content_part.added").annotate({ + "description": "The type of the object. Always `agent.session.turn.content_part.added`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the message item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part in the message.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "part": Schema.suspend((): Schema.Codec => OutputTextResource).annotate({ + "description": "The initial content part." + }) +}).annotate({ + "description": "Emitted when an output text content part is added.", + "identifier": "SessionEventAgentSessionTurnContentPartAdded" +}) +export type SessionEventAgentSessionTurnContentPartDone = { + readonly "type": "agent.session.turn.content_part.done" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "part": OutputTextResource +} +export const SessionEventAgentSessionTurnContentPartDone = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.content_part.done").annotate({ + "description": "The type of the object. Always `agent.session.turn.content_part.done`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the message item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part in the message.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "part": Schema.suspend((): Schema.Codec => OutputTextResource).annotate({ + "description": "The completed content part." + }) +}).annotate({ + "description": "Emitted when an output content part is complete.", + "identifier": "SessionEventAgentSessionTurnContentPartDone" +}) +export type AgentContentResource = OutputTextResource | EncryptedContentResource +export const AgentContentResource = Schema.Union([OutputTextResource, EncryptedContentResource], { mode: "oneOf" }) + .annotate({ + "description": "A plaintext or encrypted content part exchanged between agents.", + "identifier": "AgentContentResource" + }) +export type MessageContentResource = + | MessageContentResourceInputText + | MessageContentResourceInputImage + | MessageContentResourceOutputText +export const MessageContentResource = Schema.Union([ + MessageContentResourceInputText, + MessageContentResourceInputImage, + MessageContentResourceOutputText +], { mode: "oneOf" }).annotate({ + "description": "A content part in a session message.", + "identifier": "MessageContentResource" +}) +export type AssistantMessageItemResource = { + readonly "type": "message" + readonly "id": string + readonly "turn_id": string + readonly "role": "assistant" + readonly "status": OutputItemStatusResource + readonly "content": ReadonlyArray + readonly "phase": MessagePhaseResource | null +} +export const AssistantMessageItemResource = Schema.Struct({ + "type": Schema.Literal("message").annotate({ "description": "The item type. Always `message`." }), + "id": Schema.String.annotate({ "description": "The ID of the message." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "role": Schema.Literal("assistant").annotate({ + "description": "The role of the message author. Always `assistant`." + }), + "status": Schema.suspend((): Schema.Codec => OutputItemStatusResource).annotate({ + "description": "The status of the message." + }), + "content": Schema.Array(OutputTextResource).annotate({ "description": "The content of the message." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "phase": Schema.Union([MessagePhaseResource, Schema.Null]).annotate({ + "description": "The phase of the assistant message." + }) +}).annotate({ + "description": "An assistant message produced by the agent.", + "identifier": "AssistantMessageItemResource" +}) +export type ReasoningItemResource = { + readonly "type": "reasoning" + readonly "id": string + readonly "turn_id": string + readonly "summary": ReadonlyArray + readonly "status": OutputItemStatusResource | null +} +export const ReasoningItemResource = Schema.Struct({ + "type": Schema.Literal("reasoning").annotate({ "description": "The item type. Always `reasoning`." }), + "id": Schema.String.annotate({ "description": "The ID of the reasoning item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "summary": Schema.Array(SummaryTextResource).annotate({ + "description": "The reasoning summaries produced by the agent." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "status": Schema.Union([OutputItemStatusResource, Schema.Null]).annotate({ + "description": "The status of the reasoning item." + }) +}).annotate({ "description": "A reasoning item produced by the agent.", "identifier": "ReasoningItemResource" }) +export type SessionEventAgentSessionTurnReasoningSummaryPartAdded = { + readonly "type": "agent.session.turn.reasoning_summary_part.added" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "part": SummaryTextResource +} +export const SessionEventAgentSessionTurnReasoningSummaryPartAdded = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.reasoning_summary_part.added").annotate({ + "description": "The type of the object. Always `agent.session.turn.reasoning_summary_part.added`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the reasoning item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary content part.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "part": Schema.suspend((): Schema.Codec => SummaryTextResource).annotate({ + "description": "The initial summary part." + }) +}).annotate({ + "description": "Emitted when a reasoning summary content part is added.", + "identifier": "SessionEventAgentSessionTurnReasoningSummaryPartAdded" +}) +export type SessionEventAgentSessionTurnReasoningSummaryPartDone = { + readonly "type": "agent.session.turn.reasoning_summary_part.done" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "part": SummaryTextResource + readonly "status": "incomplete" | null +} +export const SessionEventAgentSessionTurnReasoningSummaryPartDone = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.reasoning_summary_part.done").annotate({ + "description": "The type of the object. Always `agent.session.turn.reasoning_summary_part.done`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "item_id": Schema.String.annotate({ "description": "The ID of the reasoning item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "output_index": Schema.Number.annotate({ + "description": "The index of the item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "summary_index": Schema.Number.annotate({ "description": "The index of the summary part.", "format": "int64" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })).check( + Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" }) + ), + "part": Schema.suspend((): Schema.Codec => SummaryTextResource).annotate({ + "description": "The completed summary part." + }), + "status": Schema.Union([Schema.Literal("incomplete"), Schema.Null]).annotate({ + "description": "Present as `incomplete` when summary generation was interrupted." + }) +}).annotate({ + "description": "Emitted when a reasoning summary part is complete.", + "identifier": "SessionEventAgentSessionTurnReasoningSummaryPartDone" +}) +export type FunctionCallItemResource = { + readonly "type": "function_call" + readonly "id": string + readonly "turn_id": string + readonly "call_id": string + readonly "name": string + readonly "arguments": Schema.Json + readonly "status": FunctionCallStatusResource +} +export const FunctionCallItemResource = Schema.Struct({ + "type": Schema.Literal("function_call").annotate({ "description": "The item type. Always `function_call`." }), + "id": Schema.String.annotate({ "description": "The ID of the function call item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "call_id": Schema.String.annotate({ "description": "The ID used to submit the function result." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "name": Schema.String.annotate({ "description": "The name of the function to call." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "arguments": Schema.Json.annotate({ + "expected": "JSON value", + "description": "The arguments to pass to the function." + }), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the function call." + }) +}).annotate({ "description": "A function call produced by the agent.", "identifier": "FunctionCallItemResource" }) +export type McpCallItemResource = { + readonly "type": "mcp_call" + readonly "id": string + readonly "turn_id": string + readonly "server_label": string + readonly "name": string + readonly "arguments": Schema.Json + readonly "status": FunctionCallStatusResource + readonly "output": Schema.Json | null + readonly "error": Schema.Json | null +} +export const McpCallItemResource = Schema.Struct({ + "type": Schema.Literal("mcp_call").annotate({ "description": "The item type. Always `mcp_call`." }), + "id": Schema.String.annotate({ "description": "The ID of the MCP call item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "name": Schema.String.annotate({ "description": "The name of the MCP tool." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "arguments": Schema.Json.annotate({ + "expected": "JSON value", + "description": "The arguments passed to the MCP tool." + }), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the MCP tool call." + }), + "output": Schema.Union([Schema.Json.annotate({ "expected": "JSON value" }), Schema.Null]).annotate({ + "description": "The output returned by the MCP tool, if any." + }), + "error": Schema.Union([Schema.Json.annotate({ "expected": "JSON value" }), Schema.Null]).annotate({ + "description": "The error returned by the MCP tool, if any." + }) +}).annotate({ "description": "A call to a tool on an MCP server.", "identifier": "McpCallItemResource" }) +export type CommandExecutionItemResource = { + readonly "type": "command_execution" + readonly "id": string + readonly "turn_id": string + readonly "command": string + readonly "cwd": string | null + readonly "status": FunctionCallStatusResource + readonly "output": string | null + readonly "exit_code": number | null + readonly "duration_ms": number | null +} +export const CommandExecutionItemResource = Schema.Struct({ + "type": Schema.Literal("command_execution").annotate({ "description": "The item type. Always `command_execution`." }), + "id": Schema.String.annotate({ "description": "The ID of the command execution item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "command": Schema.String.annotate({ "description": "The command that was executed." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "cwd": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The working directory used to execute the command." }), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the command execution." + }), + "output": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The command output, if available." }), + "exit_code": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ "description": "The process exit code, if the command completed.", "format": "int64" }), + "duration_ms": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ "description": "The command duration in milliseconds.", "format": "int64" }) +}).annotate({ + "description": "A command execution produced by the agent.", + "identifier": "CommandExecutionItemResource" +}) +export type ResumeSubagentCallItemResource = { + readonly "type": "resume_subagent_call" + readonly "id": string + readonly "turn_id": string + readonly "status": FunctionCallStatusResource + readonly "sender_agent_id": string + readonly "recipient_agent_id": string +} +export const ResumeSubagentCallItemResource = Schema.Struct({ + "type": Schema.Literal("resume_subagent_call").annotate({ + "description": "The item type. Always `resume_subagent_call`." + }), + "id": Schema.String.annotate({ "description": "The ID of the tool call item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the tool call." + }), + "sender_agent_id": Schema.String.annotate({ "description": "The ID of the agent requesting the resume." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "recipient_agent_id": Schema.String.annotate({ "description": "The ID of the agent to resume." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "A request to resume a subagent.", "identifier": "ResumeSubagentCallItemResource" }) +export type WaitForSubagentsCallItemResource = { + readonly "type": "wait_for_subagents_call" + readonly "id": string + readonly "turn_id": string + readonly "status": FunctionCallStatusResource + readonly "sender_agent_id": string + readonly "recipient_agent_ids": ReadonlyArray +} +export const WaitForSubagentsCallItemResource = Schema.Struct({ + "type": Schema.Literal("wait_for_subagents_call").annotate({ + "description": "The item type. Always `wait_for_subagents_call`." + }), + "id": Schema.String.annotate({ "description": "The ID of the tool call item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the tool call." + }), + "sender_agent_id": Schema.String.annotate({ "description": "The ID of the agent waiting for results." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "recipient_agent_ids": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "The IDs of the agents to wait for." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })) +}).annotate({ + "description": "A request to wait for one or more subagents.", + "identifier": "WaitForSubagentsCallItemResource" +}) +export type InterruptSubagentCallItemResource = { + readonly "type": "interrupt_subagent_call" + readonly "id": string + readonly "turn_id": string + readonly "status": FunctionCallStatusResource + readonly "sender_agent_id": string + readonly "recipient_agent_id": string +} +export const InterruptSubagentCallItemResource = Schema.Struct({ + "type": Schema.Literal("interrupt_subagent_call").annotate({ + "description": "The item type. Always `interrupt_subagent_call`." + }), + "id": Schema.String.annotate({ "description": "The ID of the tool call item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the tool call." + }), + "sender_agent_id": Schema.String.annotate({ "description": "The ID of the agent requesting the interrupt." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "recipient_agent_id": Schema.String.annotate({ "description": "The ID of the agent to interrupt." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "A request to interrupt a subagent's current turn. The subagent remains available.", + "identifier": "InterruptSubagentCallItemResource" +}) +export type CloseSubagentCallItemResource = { + readonly "type": "close_subagent_call" + readonly "id": string + readonly "turn_id": string + readonly "status": FunctionCallStatusResource + readonly "sender_agent_id": string + readonly "recipient_agent_id": string +} +export const CloseSubagentCallItemResource = Schema.Struct({ + "type": Schema.Literal("close_subagent_call").annotate({ + "description": "The item type. Always `close_subagent_call`." + }), + "id": Schema.String.annotate({ "description": "The ID of the tool call item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the tool call." + }), + "sender_agent_id": Schema.String.annotate({ "description": "The ID of the agent requesting the close." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "recipient_agent_id": Schema.String.annotate({ "description": "The ID of the agent to close." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ "description": "A request to close a subagent.", "identifier": "CloseSubagentCallItemResource" }) +export type InputContentResource = InputContentResourceInputText | InputContentResourceInputImage +export const InputContentResource = Schema.Union([InputContentResourceInputText, InputContentResourceInputImage], { + mode: "oneOf" +}).annotate({ + "description": "User-provided content recorded in a session item.", + "identifier": "InputContentResource" +}) +export type ComputerUseCallItemResource = { + readonly "type": "computer_use_call" + readonly "id": string + readonly "turn_id": string + readonly "title": string | null + readonly "status": FunctionCallStatusResource + readonly "output": ComputerScreenshotResource | null +} +export const ComputerUseCallItemResource = Schema.Struct({ + "type": Schema.Literal("computer_use_call").annotate({ "description": "The item type. Always `computer_use_call`." }), + "id": Schema.String.annotate({ "description": "The ID of the activity item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "title": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "A model-generated description of the activity, when available." }), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The execution status of the activity." + }), + "output": Schema.Union([ComputerScreenshotResource, Schema.Null]).annotate({ + "description": + "The last screenshot emitted by the model. Null when screenshot inclusion is disabled or the call emitted no screenshot." + }) +}).annotate({ + "description": "One execution of the platform-provided computer-use capability.", + "identifier": "ComputerUseCallItemResource" +}) +export type BrowserAuthenticationHistoryRequestKindResourceBrowserAuthentication = { + readonly "type": "browser_authentication" + readonly "reason": string | null + readonly "credential_origin": string | null + readonly "fields": ReadonlyArray + readonly "options": ReadonlyArray +} +export const BrowserAuthenticationHistoryRequestKindResourceBrowserAuthentication = Schema.Struct({ + "type": Schema.Literal("browser_authentication").annotate({ + "description": "The type of the object. Always `browser_authentication`." + }), + "reason": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "Why the agent needs the user to sign in." }), + "credential_origin": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The registered form or frame origin where values will be entered." }), + "fields": Schema.Array(BrowserAuthenticationFieldResource).annotate({ + "description": "Controls to render. All submitted values are sensitive." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "options": Schema.Array(BrowserAuthenticationOptionResource).annotate({ + "description": "Sign-in methods. Empty for a plain form." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ) +}).annotate({ + "description": "A registered form awaiting the application's response.", + "identifier": "BrowserAuthenticationHistoryRequestKindResourceBrowserAuthentication" +}) +export type ComputerUseApprovalRequestKindResourceBrowserAuthentication = { + readonly "type": "browser_authentication" + readonly "reason": string | null + readonly "credential_origin": string | null + readonly "fields": ReadonlyArray + readonly "options": ReadonlyArray +} +export const ComputerUseApprovalRequestKindResourceBrowserAuthentication = Schema.Struct({ + "type": Schema.Literal("browser_authentication").annotate({ + "description": "The type of the object. Always `browser_authentication`." + }), + "reason": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "Why the agent needs the user to sign in." }), + "credential_origin": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The registered form or frame origin where values will be entered." }), + "fields": Schema.Array(BrowserAuthenticationFieldResource).annotate({ + "description": "Controls to render. All submitted values are sensitive." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "options": Schema.Array(BrowserAuthenticationOptionResource).annotate({ + "description": "Sign-in methods. Empty for a plain form." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ) +}).annotate({ + "description": "A registered form awaiting the application's response.", + "identifier": "ComputerUseApprovalRequestKindResourceBrowserAuthentication" +}) +export type ComputerUseApprovalResponseKindResource = + | ComputerUseApprovalResponseKindResourceBrowserAuthenticationSubmitResource + | ComputerUseApprovalResponseKindResourceBrowserAuthenticationCancelResource +export const ComputerUseApprovalResponseKindResource = Schema.Union([ + ComputerUseApprovalResponseKindResourceBrowserAuthenticationSubmitResource, + ComputerUseApprovalResponseKindResourceBrowserAuthenticationCancelResource +], { mode: "oneOf" }).annotate({ "identifier": "ComputerUseApprovalResponseKindResource" }) +export type WebSearchActionResource = + | WebSearchActionResourceSearch + | WebSearchActionResourceOpenPage + | WebSearchActionResourceFindInPage + | WebSearchActionResourceOther +export const WebSearchActionResource = Schema.Union([ + WebSearchActionResourceSearch, + WebSearchActionResourceOpenPage, + WebSearchActionResourceFindInPage, + WebSearchActionResourceOther +], { mode: "oneOf" }).annotate({ + "description": "An action performed by the web search tool.", + "identifier": "WebSearchActionResource" +}) +export type SessionTurnErrorResource = { readonly "code": SessionTurnErrorCodeResource; readonly "message": string } +export const SessionTurnErrorResource = Schema.Struct({ + "code": Schema.suspend((): Schema.Codec => SessionTurnErrorCodeResource).annotate({ + "description": "A stable, machine-readable failure category." + }), + "message": Schema.String.annotate({ "description": "A customer-safe explanation of the failure." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ) +}).annotate({ + "description": "A customer-safe error describing why a session request failed.", + "identifier": "SessionTurnErrorResource" +}) +export type TokenUsageResource = { + readonly "input_tokens": number + readonly "input_tokens_details": InputTokensDetailsResource_2 + readonly "output_tokens": number + readonly "output_tokens_details": OutputTokensDetailsResource_2 + readonly "total_tokens": number +} +export const TokenUsageResource = Schema.Struct({ + "input_tokens": Schema.Number.annotate({ + "description": "The number of input tokens used by the agent.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "input_tokens_details": Schema.suspend((): Schema.Codec => InputTokensDetailsResource_2) + .annotate({ "description": "A breakdown of the agent's input token usage." }), + "output_tokens": Schema.Number.annotate({ + "description": "The number of output tokens generated by the agent.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "output_tokens_details": Schema.suspend((): Schema.Codec => + OutputTokensDetailsResource_2 + ).annotate({ "description": "A breakdown of the agent's output token usage." }), + "total_tokens": Schema.Number.annotate({ + "description": "The total number of input and output tokens used by the agent.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Recorded token usage for a session or turn. Usage is best effort and may change.", + "identifier": "TokenUsageResource" +}) +export type ReasoningResource = { + readonly "effort": ReasoningEffortResource | null + readonly "summary": ReasoningSummaryResource | null +} +export const ReasoningResource = Schema.Struct({ + "effort": Schema.Union([ReasoningEffortResource, Schema.Null]).annotate({ + "description": "The requested reasoning effort, or `null` when the model selects its own default." + }), + "summary": Schema.Union([ReasoningSummaryResource, Schema.Null]).annotate({ + "description": "The requested reasoning summary format, or `null` when summaries are disabled." + }) +}).annotate({ "description": "The reasoning configuration used by an agent.", "identifier": "ReasoningResource" }) +export type TextFormatResource = TextFormatResourceText | TextFormatResourceJsonSchema +export const TextFormatResource = Schema.Union([TextFormatResourceText, TextFormatResourceJsonSchema], { + mode: "oneOf" +}).annotate({ "description": "The effective output format for generated text.", "identifier": "TextFormatResource" }) +export type PersistedMcpTransportResource = PersistedMcpTransportResourceHttp | PersistedMcpTransportResourceStdio +export const PersistedMcpTransportResource = Schema.Union([ + PersistedMcpTransportResourceHttp, + PersistedMcpTransportResourceStdio +], { mode: "oneOf" }).annotate({ + "description": "A credential-free transport used to connect to an MCP server.", + "identifier": "PersistedMcpTransportResource" +}) +export type PersistedAgentToolResourceWebSearch = { + readonly "type": "web_search" + readonly "mode": WebSearchModeResource + readonly "context_size": WebSearchContextSizeResource + readonly "allowed_domains": ReadonlyArray | null + readonly "location": WebSearchLocationResource | null +} +export const PersistedAgentToolResourceWebSearch = Schema.Struct({ + "type": Schema.Literal("web_search").annotate({ "description": "The type of the object. Always `web_search`." }), + "mode": Schema.suspend((): Schema.Codec => WebSearchModeResource).annotate({ + "description": "The source used for web search results." + }), + "context_size": Schema.suspend((): Schema.Codec => WebSearchContextSizeResource) + .annotate({ "description": "The amount of search context made available to the model. Defaults to `medium`." }), + "allowed_domains": Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + Schema.Null + ]).annotate({ "description": "Allowed search domains, or `null` when the search is unrestricted." }), + "location": Schema.Union([WebSearchLocationResource, Schema.Null]).annotate({ + "description": "Approximate location used to localize search results, if provided." + }) +}).annotate({ "description": "Web search.", "identifier": "PersistedAgentToolResourceWebSearch" }) +export type AgentToolResourceWebSearch = { + readonly "type": "web_search" + readonly "mode": WebSearchModeResource + readonly "context_size": WebSearchContextSizeResource + readonly "allowed_domains": ReadonlyArray | null + readonly "location": WebSearchLocationResource | null +} +export const AgentToolResourceWebSearch = Schema.Struct({ + "type": Schema.Literal("web_search").annotate({ "description": "The type of the object. Always `web_search`." }), + "mode": Schema.suspend((): Schema.Codec => WebSearchModeResource).annotate({ + "description": "The source used for web search results." + }), + "context_size": Schema.suspend((): Schema.Codec => WebSearchContextSizeResource) + .annotate({ "description": "The amount of search context made available to the model. Defaults to `medium`." }), + "allowed_domains": Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + Schema.Null + ]).annotate({ "description": "Allowed search domains, or `null` when the search is unrestricted." }), + "location": Schema.Union([WebSearchLocationResource, Schema.Null]).annotate({ + "description": "Approximate location used to localize search results, if provided." + }) +}).annotate({ "description": "Web search.", "identifier": "AgentToolResourceWebSearch" }) +export type UpdateSessionReasoningParam = { readonly "effort"?: ReasoningEffortParam | null } +export const UpdateSessionReasoningParam = Schema.Struct({ + "effort": Schema.optionalKey( + Schema.Union([ReasoningEffortParam, Schema.Null]).annotate({ + "description": "Omit to keep the current effort. Null selects the model's default effort." + }) + ) +}).annotate({ + "description": "Reasoning effort for subsequent turns. The reasoning summary stays unchanged.", + "identifier": "UpdateSessionReasoningParam" +}) +export type ReasoningParam = { + readonly "effort"?: ReasoningEffortParam | null + readonly "summary"?: ReasoningSummaryParam | null +} +export const ReasoningParam = Schema.Struct({ + "effort": Schema.optionalKey( + Schema.Union([ReasoningEffortParam, Schema.Null]).annotate({ + "description": "The amount of reasoning effort the model should use. Omission lets the model select it." + }) + ), + "summary": Schema.optionalKey( + Schema.Union([ReasoningSummaryParam, Schema.Null]).annotate({ + "description": "Controls whether the response includes a reasoning summary." + }) + ) +}).annotate({ "description": "Reasoning configuration for the agent.", "identifier": "ReasoningParam" }) +export type TextFormatParam = TextFormatParamText | TextFormatParamJsonSchema +export const TextFormatParam = Schema.Union([TextFormatParamText, TextFormatParamJsonSchema], { mode: "oneOf" }) + .annotate({ "description": "The output format for generated text.", "identifier": "TextFormatParam" }) +export type PersistedMcpTransportConfigParam = + | PersistedMcpTransportConfigParamHttp + | PersistedMcpTransportConfigParamStdio +export const PersistedMcpTransportConfigParam = Schema.Union([ + PersistedMcpTransportConfigParamHttp, + PersistedMcpTransportConfigParamStdio +], { mode: "oneOf" }).annotate({ + "description": "A credential-free transport used to connect to an MCP server.", + "identifier": "PersistedMcpTransportConfigParam" +}) +export type PersistedAgentToolConfigParamWebSearch = { + readonly "type": "web_search" + readonly "mode"?: WebSearchModeParam | null + readonly "context_size"?: WebSearchContextSizeParam | null + readonly "allowed_domains"?: ReadonlyArray | null + readonly "location"?: WebSearchLocationParam | null +} +export const PersistedAgentToolConfigParamWebSearch = Schema.Struct({ + "type": Schema.Literal("web_search").annotate({ "description": "The type of the object. Always `web_search`." }), + "mode": Schema.optionalKey( + Schema.Union([WebSearchModeParam, Schema.Null]).annotate({ + "description": "The source used for web search results. Defaults to `live`." + }) + ), + "context_size": Schema.optionalKey( + Schema.Union([WebSearchContextSizeParam, Schema.Null]).annotate({ + "description": "The amount of search context made available to the model. Defaults to `medium`." + }) + ), + "allowed_domains": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "Domains the search may include." }) + ), + "location": Schema.optionalKey( + Schema.Union([WebSearchLocationParam, Schema.Null]).annotate({ + "description": "Approximate location used to localize search results." + }) + ) +}).annotate({ "description": "Web search.", "identifier": "PersistedAgentToolConfigParamWebSearch" }) +export type AgentToolConfigParamWebSearch = { + readonly "type": "web_search" + readonly "mode"?: WebSearchModeParam | null + readonly "context_size"?: WebSearchContextSizeParam | null + readonly "allowed_domains"?: ReadonlyArray | null + readonly "location"?: WebSearchLocationParam | null +} +export const AgentToolConfigParamWebSearch = Schema.Struct({ + "type": Schema.Literal("web_search").annotate({ "description": "The type of the object. Always `web_search`." }), + "mode": Schema.optionalKey( + Schema.Union([WebSearchModeParam, Schema.Null]).annotate({ + "description": "The source used for web search results. Defaults to `live`." + }) + ), + "context_size": Schema.optionalKey( + Schema.Union([WebSearchContextSizeParam, Schema.Null]).annotate({ + "description": "The amount of search context made available to the model. Defaults to `medium`." + }) + ), + "allowed_domains": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "Domains the search may include." }) + ), + "location": Schema.optionalKey( + Schema.Union([WebSearchLocationParam, Schema.Null]).annotate({ + "description": "Approximate location used to localize search results." + }) + ) +}).annotate({ "description": "Web search.", "identifier": "AgentToolConfigParamWebSearch" }) +export type NetworkPolicyResource = { + readonly "access": NetworkAccessResource + readonly "allowed_domains": ReadonlyArray +} +export const NetworkPolicyResource = Schema.Struct({ + "access": Schema.suspend((): Schema.Codec => NetworkAccessResource).annotate({ + "description": "The environment's network access mode." + }), + "allowed_domains": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Domains the environment may access when network access is restricted." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })) +}).annotate({ + "description": "Network access for an OpenAI-hosted environment.", + "identifier": "NetworkPolicyResource" +}) +export type HostedTemplateSkillResource = HostedTemplateSkillResourceSkillReference | HostedTemplateSkillResourceInline +export const HostedTemplateSkillResource = Schema.Union([ + HostedTemplateSkillResourceSkillReference, + HostedTemplateSkillResourceInline +], { mode: "oneOf" }).annotate({ + "description": "Safe metadata for a skill configured by an environment template.", + "identifier": "HostedTemplateSkillResource" +}) +export type HostedTemplateFileResource = HostedTemplateFileResourceFileId | HostedTemplateFileResourceInline +export const HostedTemplateFileResource = Schema.Union([ + HostedTemplateFileResourceFileId, + HostedTemplateFileResourceInline +], { mode: "oneOf" }).annotate({ + "description": "Safe metadata for a file configured by an environment template.", + "identifier": "HostedTemplateFileResource" +}) +export type McpTransportResource = McpTransportResourceHttp | McpTransportResourceStdio +export const McpTransportResource = Schema.Union([McpTransportResourceHttp, McpTransportResourceStdio], { + mode: "oneOf" +}).annotate({ "description": "The transport used to connect to an MCP server.", "identifier": "McpTransportResource" }) +export type McpTransportConfigParam = McpTransportConfigParamHttp | McpTransportConfigParamStdio +export const McpTransportConfigParam = Schema.Union([McpTransportConfigParamHttp, McpTransportConfigParamStdio], { + mode: "oneOf" +}).annotate({ + "description": "The transport used to connect to an MCP server.", + "identifier": "McpTransportConfigParam" +}) +export type InputContentParam = InputContentParamInputText | InputContentParamInputImage +export const InputContentParam = Schema.Union([InputContentParamInputText, InputContentParamInputImage], { + mode: "oneOf" +}).annotate({ "description": "Content included in an input message.", "identifier": "InputContentParam" }) +export type SessionEventError = { + readonly "type": "error" + readonly "event_id": string + readonly "session_id": string + readonly "error": SessionErrorResource +} +export const SessionEventError = Schema.Struct({ + "type": Schema.Literal("error").annotate({ "description": "The type of the object. Always `error`." }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "error": Schema.suspend((): Schema.Codec => SessionErrorResource).annotate({ + "description": "The error that occurred." + }) +}).annotate({ "description": "Emitted when a turn or session fails.", "identifier": "SessionEventError" }) +export type SessionEnvironmentStateResource = { + readonly "id": string + readonly "type": string + readonly "status": SessionEnvironmentStatusResource + readonly "error": SessionEnvironmentErrorResource | null +} +export const SessionEnvironmentStateResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The public ID of the environment." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "type": Schema.String.annotate({ "description": "The environment type." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => SessionEnvironmentStatusResource) + .annotate({ "description": "The environment's connection status." }), + "error": Schema.Union([SessionEnvironmentErrorResource, Schema.Null]).annotate({ + "description": "The error reported while preparing the environment, if any." + }) +}).annotate({ + "description": "The current state of a session environment.", + "identifier": "SessionEnvironmentStateResource" +}) +export type SessionArtifactListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const SessionArtifactListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(SessionArtifactResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "SessionArtifactListResource" +}) +export type ComputerUseApprovalResponseParamBrowserAuthentication = { + readonly "type": "browser_authentication" + readonly "action": "submit" + readonly "fields": ReadonlyArray + readonly "selected_option"?: string | null +} | { readonly "type": "browser_authentication"; readonly "action": "cancel" } +export const ComputerUseApprovalResponseParamBrowserAuthentication = Schema.Union([ + Schema.Struct({ + "type": Schema.Literal("browser_authentication"), + "action": Schema.Literal("submit"), + "fields": Schema.Array(BrowserAuthenticationFieldValueParam).annotate({ + "description": + "Values for up to six active fields in the required action. The submitted field-value mapping and selected option must fit within 120 KiB of JSON." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(6).annotate({ "expected": "a value with a length of at most 6" }) + ), + "selected_option": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The chosen method. Required when the required action contains options." }) + ) + }), + Schema.Struct({ "type": Schema.Literal("browser_authentication"), "action": Schema.Literal("cancel") }) +], { mode: "oneOf" }).annotate({ "identifier": "ComputerUseApprovalResponseParamBrowserAuthentication" }) +export type ComputerUseApprovalResponseParamBrowserOriginAccessParam = { + readonly "type": "browser_origin_access" + readonly "decision": BrowserOriginAccessDecisionParam +} +export const ComputerUseApprovalResponseParamBrowserOriginAccessParam = Schema.Struct({ + "type": Schema.Literal("browser_origin_access"), + "decision": Schema.suspend((): Schema.Codec => BrowserOriginAccessDecisionParam) + .annotate({ "description": "Whether to allow, deny, or cancel the requested origin access." }) +}).annotate({ "identifier": "ComputerUseApprovalResponseParamBrowserOriginAccessParam" }) +export type SessionTraceListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const SessionTraceListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(SessionTurnTraceResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "SessionTraceListResource" +}) +export type VaultStatusFilterParam = VaultStatusParam | ReadonlyArray +export const VaultStatusFilterParam = Schema.Union([ + VaultStatusParam, + Schema.Array(VaultStatusParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" })) +], { mode: "oneOf" }).annotate({ + "description": "One or more lifecycle statuses to include when listing vaults or credentials.", + "identifier": "VaultStatusFilterParam" +}) +export type VaultListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const VaultListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(VaultResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "VaultListResource" +}) +export type McpOauthTokenEndpointAuthResource = + | McpOauthTokenEndpointAuthResourceNone + | McpOauthTokenEndpointAuthResourceClientSecretBasic + | McpOauthTokenEndpointAuthResourceClientSecretPost +export const McpOauthTokenEndpointAuthResource = Schema.Union([ + McpOauthTokenEndpointAuthResourceNone, + McpOauthTokenEndpointAuthResourceClientSecretBasic, + McpOauthTokenEndpointAuthResourceClientSecretPost +], { mode: "oneOf" }).annotate({ + "description": "The client authentication method used for OAuth token refresh.", + "identifier": "McpOauthTokenEndpointAuthResource" +}) +export type VaultCredentialNetworkingResource = + | VaultCredentialNetworkingResourceUnrestricted + | VaultCredentialNetworkingResourceLimited +export const VaultCredentialNetworkingResource = Schema.Union([ + VaultCredentialNetworkingResourceUnrestricted, + VaultCredentialNetworkingResourceLimited +], { mode: "oneOf" }).annotate({ + "description": + "Destination permissions for an environment-variable credential. These do not grant network access to the environment.", + "identifier": "VaultCredentialNetworkingResource" +}) +export type CreateMcpOauthTokenEndpointAuthParam = + | CreateMcpOauthTokenEndpointAuthParamNone + | CreateMcpOauthTokenEndpointAuthParamClientSecretBasic + | CreateMcpOauthTokenEndpointAuthParamClientSecretPost +export const CreateMcpOauthTokenEndpointAuthParam = Schema.Union([ + CreateMcpOauthTokenEndpointAuthParamNone, + CreateMcpOauthTokenEndpointAuthParamClientSecretBasic, + CreateMcpOauthTokenEndpointAuthParamClientSecretPost +], { mode: "oneOf" }).annotate({ + "description": "Client authentication credentials for OAuth token refresh.", + "identifier": "CreateMcpOauthTokenEndpointAuthParam" +}) +export type VaultCredentialNetworkingParam = + | VaultCredentialNetworkingParamUnrestricted + | VaultCredentialNetworkingParamLimited +export const VaultCredentialNetworkingParam = Schema.Union([ + VaultCredentialNetworkingParamUnrestricted, + VaultCredentialNetworkingParamLimited +], { mode: "oneOf" }).annotate({ + "description": + "Destination permissions for an environment-variable credential. These do not grant network access to the environment.", + "identifier": "VaultCredentialNetworkingParam" +}) +export type RotateMcpOauthTokenEndpointAuthParam = + | RotateMcpOauthTokenEndpointAuthParamClientSecretBasic + | RotateMcpOauthTokenEndpointAuthParamClientSecretPost +export const RotateMcpOauthTokenEndpointAuthParam = Schema.Union([ + RotateMcpOauthTokenEndpointAuthParamClientSecretBasic, + RotateMcpOauthTokenEndpointAuthParamClientSecretPost +], { mode: "oneOf" }).annotate({ + "description": "Client-secret updates that preserve the credential's OAuth authentication method.", + "identifier": "RotateMcpOauthTokenEndpointAuthParam" +}) +export type WebhookEndpointListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const WebhookEndpointListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always list." }), + "data": Schema.Array(WebhookEndpointBody).annotate({ "description": "The webhook endpoints in this page." }), + "first_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the first endpoint in this page." }), + Schema.Null + ]), + "last_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the last endpoint in this page." }), + Schema.Null + ]), + "has_more": Schema.Boolean.annotate({ "description": "Whether more webhook endpoints are available." }) +}).annotate({ "identifier": "WebhookEndpointListResource" }) +export type PublicCreateEndpointBody = { + readonly "name": string + readonly "url": string + readonly "event_types": ReadonlyArray +} +export const PublicCreateEndpointBody = Schema.Struct({ + "name": Schema.String.annotate({ "description": "A human-readable name for the webhook endpoint." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })), + "url": Schema.String.annotate({ "description": "The HTTPS URL that receives webhook deliveries." }).check( + Schema.isMaxCodePoints(2048).annotate({ "expected": "a string with at most 2048 code points" }) + ).check( + Schema.isPattern(new RegExp("^https:\\/\\/", "u")).annotate({ + "expected": "a string matching the RegExp ^https:\\/\\/" + }) + ), + "event_types": Schema.Array(ProjectEventTypeEnum).annotate({ + "description": "The event types that trigger deliveries to this endpoint." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) +}).annotate({ "identifier": "PublicCreateEndpointBody" }) +export type PublicUpdateEndpointBody = { + readonly "name"?: string + readonly "url"?: string + readonly "event_types"?: ReadonlyArray +} +export const PublicUpdateEndpointBody = Schema.Struct({ + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "A new human-readable name for the webhook endpoint." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ), + "url": Schema.optionalKey( + Schema.String.annotate({ "description": "A new HTTPS URL that receives webhook deliveries." }).check( + Schema.isMaxCodePoints(2048).annotate({ "expected": "a string with at most 2048 code points" }) + ).check( + Schema.isPattern(new RegExp("^https:\\/\\/", "u")).annotate({ + "expected": "a string matching the RegExp ^https:\\/\\/" + }) + ) + ), + "event_types": Schema.optionalKey( + Schema.Array(ProjectEventTypeEnum).annotate({ + "description": "The complete set of event types that should trigger deliveries." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ) +}).annotate({ "identifier": "PublicUpdateEndpointBody" }) +export type PublicTestEndpointBody = { readonly "event_type": ProjectEventTypeEnum } +export const PublicTestEndpointBody = Schema.Struct({ + "event_type": Schema.suspend((): Schema.Codec => ProjectEventTypeEnum).annotate({ + "description": "The event type to send as a sample delivery." + }) +}).annotate({ "identifier": "PublicTestEndpointBody" }) +export type BetaPromptCacheOptions = { + readonly "ttl": BetaPromptCacheTTLEnum + readonly "mode": BetaPromptCacheModeEnum + readonly "comparison_response_id"?: string | null +} +export const BetaPromptCacheOptions = Schema.Struct({ + "ttl": Schema.suspend((): Schema.Codec => BetaPromptCacheTTLEnum).annotate({ + "description": "The minimum lifetime applied to each cache breakpoint." + }), + "mode": Schema.suspend((): Schema.Codec => BetaPromptCacheModeEnum).annotate({ + "description": "Whether implicit prompt-cache breakpoints were enabled." + }), + "comparison_response_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The response ID supplied as the prompt cache diagnostics comparison." }), + Schema.Null + ]) + ) +}).annotate({ + "title": "Prompt cache options", + "description": + "The prompt-caching options that were applied to the response. Supported for `gpt-5.6` and later models.", + "identifier": "BetaPromptCacheOptions" +}) +export type BetaPromptCacheOptionsParam = { + readonly "ttl"?: BetaPromptCacheTTLEnum + readonly "mode"?: BetaPromptCacheModeEnum +} +export const BetaPromptCacheOptionsParam = Schema.Struct({ + "ttl": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaPromptCacheTTLEnum).annotate({ + "description": + "The minimum lifetime applied to every implicit and explicit cache breakpoint written by the request. Defaults to `30m`, which is currently the only supported value. The backend may retain cache entries for longer." + }) + ), + "mode": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaPromptCacheModeEnum).annotate({ + "description": + "Controls whether OpenAI automatically creates an implicit cache breakpoint. Defaults to `implicit`. With `implicit`, OpenAI creates one implicit breakpoint and writes up to the latest three explicit breakpoints in the request. With `explicit`, OpenAI does not create an implicit breakpoint and writes up to the latest four explicit breakpoints. If there are no explicit breakpoints, the request does not use prompt caching." + }) + ) +}).annotate({ + "title": "Prompt cache options", + "description": + "Options for prompt caching. Supported for `gpt-5.6` and later models. By default, OpenAI automatically chooses one implicit cache breakpoint. You can add explicit breakpoints to content blocks with `prompt_cache_breakpoint`. Each request can write up to four breakpoints. For cache matching, OpenAI considers up to the latest 80 breakpoints in the conversation, without a content-block lookback limit. Set `mode` to `explicit` to disable the implicit breakpoint. The `ttl` defaults to `30m`, which is currently the only supported value. See the [prompt caching guide](https://developers.openai.com/api/docs/guides/prompt-caching) for current details.", + "identifier": "BetaPromptCacheOptionsParam" +}) +export type BetaModelIdsResponses = + | BetaModelIdsShared + | "o1-pro" + | "o1-pro-2025-03-19" + | "o3-pro" + | "o3-pro-2025-06-10" + | "o3-deep-research" + | "o3-deep-research-2025-06-26" + | "o4-mini-deep-research" + | "o4-mini-deep-research-2025-06-26" + | "computer-use-preview" + | "computer-use-preview-2025-03-11" + | "gpt-5.5-pro" + | "gpt-5.5-pro-2026-04-23" + | "gpt-5-codex" + | "gpt-5-pro" + | "gpt-5-pro-2025-10-06" + | "gpt-5.1-codex-max" + | "gpt-daybreak-blue-latest" + | "gpt-daybreak-red-latest" + | "gpt-5.6-cyber" + | "gpt-rosalind-research" +export const BetaModelIdsResponses = Schema.Union([ + BetaModelIdsShared, + Schema.Literals([ + "o1-pro", + "o1-pro-2025-03-19", + "o3-pro", + "o3-pro-2025-06-10", + "o3-deep-research", + "o3-deep-research-2025-06-26", + "o4-mini-deep-research", + "o4-mini-deep-research-2025-06-26", + "computer-use-preview", + "computer-use-preview-2025-03-11", + "gpt-5.5-pro", + "gpt-5.5-pro-2026-04-23", + "gpt-5-codex", + "gpt-5-pro", + "gpt-5-pro-2025-10-06", + "gpt-5.1-codex-max", + "gpt-daybreak-blue-latest", + "gpt-daybreak-red-latest", + "gpt-5.6-cyber", + "gpt-rosalind-research" + ]).annotate({ "title": "ResponsesOnlyModel" }) +]).annotate({ "identifier": "BetaModelIdsResponses" }) +export type BetaTextResponseFormatJsonSchema = { + readonly "type": "json_schema" + readonly "description"?: string + readonly "name": string + readonly "schema": BetaResponseFormatJsonSchemaSchema + readonly "strict"?: boolean | null +} +export const BetaTextResponseFormatJsonSchema = Schema.Struct({ + "type": Schema.Literal("json_schema").annotate({ + "description": "The type of response format being defined. Always `json_schema`." + }), + "description": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A description of what the response format is for, used by the model to\ndetermine how to respond in the format.\n" + }) + ), + "name": Schema.String.annotate({ + "description": + "The name of the response format. Must be a-z, A-Z, 0-9, or contain\nunderscores and dashes, with a maximum length of 64.\n" + }), + "schema": BetaResponseFormatJsonSchemaSchema, + "strict": Schema.optionalKey(Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to enable strict schema adherence when generating the output.\nIf set to true, the model will always follow the exact schema defined\nin the `schema` field. Only a subset of JSON Schema is supported when\n`strict` is `true`. To learn more, read the [Structured Outputs\nguide](https://developers.openai.com/api/docs/guides/structured-outputs).\n" + }), + Schema.Null + ])) +}).annotate({ + "title": "JSON schema", + "description": + "JSON Schema response format. Used to generate structured JSON responses.\nLearn more about [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs).\n", + "identifier": "BetaTextResponseFormatJsonSchema" +}) +export type BetaFunctionTool = { + readonly "type": "function" + readonly "name": string + readonly "async"?: boolean + readonly "description"?: string | null + readonly "parameters": { readonly [x: string]: Schema.Json } | null + readonly "output_schema"?: { readonly [x: string]: Schema.Json } | null + readonly "strict": boolean | null + readonly "defer_loading"?: boolean + readonly "allowed_callers"?: ReadonlyArray | null +} +export const BetaFunctionTool = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The type of the function tool. Always `function`." }), + "name": Schema.String.annotate({ "description": "The name of the function to call." }), + "async": Schema.optionalKey(Schema.Boolean), + "description": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "A description of the function. Used by the model to determine whether or not to call the function." + }), + Schema.Null + ]) + ), + "parameters": Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON schema object describing the parameters of the function." + }), + Schema.Null + ]), + "output_schema": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "A JSON schema object describing the JSON value encoded in string outputs for this function." + }), + Schema.Null + ]) + ), + "strict": Schema.Union([ + Schema.Boolean.annotate({ + "description": "Whether strict parameter validation is enforced for this function tool." + }), + Schema.Null + ]), + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether this function is deferred and loaded via tool search." }) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaCallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }), + Schema.Null + ]) + ) +}).annotate({ + "title": "Function", + "description": + "Defines a function in your own code the model can choose to call. Learn more about [function calling](https://developers.openai.com/api/docs/guides/function-calling).", + "identifier": "BetaFunctionTool" +}) +export type BetaApplyPatchToolParam = { + readonly "type": "apply_patch" + readonly "allowed_callers"?: ReadonlyArray | null +} +export const BetaApplyPatchToolParam = Schema.Struct({ + "type": Schema.Literal("apply_patch").annotate({ "description": "The type of the tool. Always `apply_patch`." }), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaCallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ + "title": "Apply patch tool", + "description": "Allows the assistant to create, delete, or update files using unified diffs.", + "identifier": "BetaApplyPatchToolParam" +}) +export type BetaRankingOptions = { + readonly "ranker"?: BetaRankerVersionType + readonly "score_threshold"?: number + readonly "hybrid_search"?: BetaHybridSearchOptions +} +export const BetaRankingOptions = Schema.Struct({ + "ranker": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaRankerVersionType).annotate({ + "description": "The ranker to use for the file search." + }) + ), + "score_threshold": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The score threshold for the file search, a number between 0 and 1. Numbers closer to 1 will attempt to return only the most relevant results, but may return fewer results." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "hybrid_search": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaHybridSearchOptions).annotate({ + "description": + "Weights that control how reciprocal rank fusion balances semantic embedding matches versus sparse keyword matches when hybrid search is enabled." + }) + ) +}).annotate({ "identifier": "BetaRankingOptions" }) +export type BetaFilters = BetaComparisonFilter | BetaCompoundFilter +export const BetaFilters = Schema.Union([BetaComparisonFilter, BetaCompoundFilter]).annotate({ + "identifier": "BetaFilters" +}) +export type BetaComputerUsePreviewTool = { + readonly "type": "computer_use_preview" + readonly "environment": BetaComputerEnvironment + readonly "display_width": number + readonly "display_height": number +} +export const BetaComputerUsePreviewTool = Schema.Struct({ + "type": Schema.Literal("computer_use_preview").annotate({ + "description": "The type of the computer use tool. Always `computer_use_preview`." + }), + "environment": Schema.suspend((): Schema.Codec => BetaComputerEnvironment).annotate({ + "description": "The type of computer environment to control." + }), + "display_width": Schema.Number.annotate({ "description": "The width of the computer display." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "display_height": Schema.Number.annotate({ "description": "The height of the computer display." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "Computer use preview", + "description": + "A tool that controls a virtual computer. Learn more about the [computer tool](https://developers.openai.com/api/docs/guides/tools-computer-use).", + "identifier": "BetaComputerUsePreviewTool" +}) +export type BetaWebSearchTool = { + readonly "type": "web_search" | "web_search_2025_08_26" + readonly "external_web_access"?: boolean + readonly "filters"?: { readonly "allowed_domains"?: ReadonlyArray | null } | null + readonly "user_location"?: BetaWebSearchApproximateLocation + readonly "search_context_size"?: "low" | "medium" | "high" +} +export const BetaWebSearchTool = Schema.Struct({ + "type": Schema.Literals(["web_search", "web_search_2025_08_26"]).annotate({ + "description": "The type of the web search tool. One of `web_search` or `web_search_2025_08_26`." + }), + "external_web_access": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Allow live internet access for web search. Defaults to true when omitted. When false, the web search tool runs in offline/cache-only mode and will not fetch new external content." + }) + ), + "filters": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "allowed_domains": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.String.annotate({ "description": "Allowed domain for the search." })).annotate({ + "title": "Allowed domains for the search.", + "description": + "Allowed domains for the search. If not provided, all domains are allowed.\nSubdomains of the provided domains are allowed as well.\n\nExample: `[\"pubmed.ncbi.nlm.nih.gov\"]`\n" + }), + Schema.Null + ]) + ) + }).annotate({ "description": "Filters for the search.\n" }), + Schema.Null + ])), + "user_location": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaWebSearchApproximateLocation).annotate({ + "description": + "The approximate location of the user. If omitted or null, defaults to the\nUnited States. To avoid this fallback, pass `{\"type\": \"approximate\"}` without\nlocation fields. To localize results, provide the relevant location fields.\n" + }) + ), + "search_context_size": Schema.optionalKey( + Schema.Literals(["low", "medium", "high"]).annotate({ + "description": + "High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default." + }) + ) +}).annotate({ + "title": "Web search", + "description": + "Search the Internet for sources related to the prompt. Learn more about the\n[web search tool](https://developers.openai.com/api/docs/guides/tools-web-search).\n", + "identifier": "BetaWebSearchTool" +}) +export type BetaMCPTool = { + readonly "type": "mcp" + readonly "server_label": string + readonly "server_url"?: string + readonly "connector_id"?: + | "connector_dropbox" + | "connector_gmail" + | "connector_googlecalendar" + | "connector_googledrive" + | "connector_microsoftteams" + | "connector_outlookcalendar" + | "connector_outlookemail" + | "connector_sharepoint" + readonly "tunnel_id"?: string + readonly "authorization"?: string + readonly "server_description"?: string + readonly "headers"?: { readonly [x: string]: string } | null + readonly "allowed_tools"?: ReadonlyArray | BetaMCPToolFilter | null + readonly "allowed_callers"?: ReadonlyArray | null + readonly "require_approval"?: + | { readonly "always"?: BetaMCPToolFilter; readonly "never"?: BetaMCPToolFilter } + | "always" + | "never" + | null + readonly "defer_loading"?: boolean +} +export const BetaMCPTool = Schema.Struct({ + "type": Schema.Literal("mcp").annotate({ "description": "The type of the MCP tool. Always `mcp`." }), + "server_label": Schema.String.annotate({ + "description": "A label for this MCP server, used to identify it in tool calls.\n" + }), + "server_url": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The URL for the MCP server. One of `server_url`, `connector_id`, or\n`tunnel_id` must be provided.\n", + "format": "uri" + }) + ), + "connector_id": Schema.optionalKey( + Schema.Literals([ + "connector_dropbox", + "connector_gmail", + "connector_googlecalendar", + "connector_googledrive", + "connector_microsoftteams", + "connector_outlookcalendar", + "connector_outlookemail", + "connector_sharepoint" + ]).annotate({ + "description": + "Identifier for service connectors, like those available in ChatGPT. One of\n`server_url`, `connector_id`, or `tunnel_id` must be provided. Learn more\nabout service connectors [here](https://developers.openai.com/api/docs/guides/tools-connectors-mcp#connectors).\n\nThis field is deprecated for models released after September 1, 2026.\nUse `server_url` to connect to a remote MCP server, or `tunnel_id` to\nconnect through a Secure MCP Tunnel.\n\nCurrently supported `connector_id` values are:\n\n- Dropbox: `connector_dropbox`\n- Gmail: `connector_gmail`\n- Google Calendar: `connector_googlecalendar`\n- Google Drive: `connector_googledrive`\n- Microsoft Teams: `connector_microsoftteams`\n- Outlook Calendar: `connector_outlookcalendar`\n- Outlook Email: `connector_outlookemail`\n- SharePoint: `connector_sharepoint`\n" + }) + ), + "tunnel_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The Secure MCP Tunnel ID to use instead of a direct server URL. One of\n`server_url`, `connector_id`, or `tunnel_id` must be provided.\n" + }).check( + Schema.isPattern(new RegExp("^tunnel_[a-z0-9]{32}$", "u")).annotate({ + "expected": "a string matching the RegExp ^tunnel_[a-z0-9]{32}$" + }) + ) + ), + "authorization": Schema.optionalKey( + Schema.String.annotate({ + "description": + "An OAuth access token that can be used with a remote MCP server, either\nwith a custom MCP server URL or a service connector. Your application\nmust handle the OAuth authorization flow and provide the token here.\n" + }) + ), + "server_description": Schema.optionalKey( + Schema.String.annotate({ "description": "Optional description of the MCP server, used to provide more context.\n" }) + ), + "headers": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.String).annotate({ + "description": "Optional HTTP headers to send to the MCP server. Use for authentication\nor other purposes.\n" + }), + Schema.Null + ]) + ), + "allowed_tools": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.Array(Schema.String).annotate({ + "title": "MCP allowed tools", + "description": "A string array of allowed tool names" + }), + BetaMCPToolFilter + ], { mode: "oneOf" }).annotate({ "description": "List of allowed tool names or a filter object.\n" }), + Schema.Null + ]) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaCallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ), + "require_approval": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.Struct({ + "always": Schema.optionalKey(BetaMCPToolFilter), + "never": Schema.optionalKey(BetaMCPToolFilter) + }).annotate({ + "title": "MCP tool approval filter", + "description": + "Specify which of the MCP server's tools require approval. Can be\n`always`, `never`, or a filter object associated with tools\nthat require approval.\n" + }), + Schema.Literals(["always", "never"]).annotate({ + "title": "MCP tool approval setting", + "description": + "Specify a single approval policy for all tools. One of `always` or\n`never`. When set to `always`, all tools will require approval. When\nset to `never`, all tools will not require approval.\n" + }) + ], { mode: "oneOf" }).annotate({ "description": "Specify which of the MCP server's tools require approval." }), + Schema.Null + ]) + ), + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether this MCP tool is deferred and discovered via tool search.\n" }) + ) +}).annotate({ + "title": "MCP tool", + "description": + "Give the model access to additional tools via remote Model Context Protocol\n(MCP) servers. [Learn more about MCP](https://developers.openai.com/api/docs/guides/tools-connectors-mcp).\n", + "identifier": "BetaMCPTool" +}) +export type BetaContainerNetworkPolicyAllowlistParam = { + readonly "type": "allowlist" + readonly "allowed_domains": ReadonlyArray + readonly "domain_secrets"?: ReadonlyArray +} +export const BetaContainerNetworkPolicyAllowlistParam = Schema.Struct({ + "type": Schema.Literal("allowlist").annotate({ + "description": "Allow outbound network access only to specified domains. Always `allowlist`." + }), + "allowed_domains": Schema.Array(Schema.String).annotate({ + "description": "A list of allowed domains when type is `allowlist`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "domain_secrets": Schema.optionalKey( + Schema.Array(BetaContainerNetworkPolicyDomainSecretParam).annotate({ + "description": "Optional domain-scoped secrets for allowlisted domains." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ) +}).annotate({ "identifier": "BetaContainerNetworkPolicyAllowlistParam" }) +export type BetaImageGenTool = { + readonly "type": "image_generation" + readonly "model"?: + | string + | "gpt-image-1" + | "gpt-image-1-mini" + | "gpt-image-1.5" + | "gpt-image-2" + | "gpt-image-2-2026-04-21" + | "gpt-image-2.5-sunburst" + | "gpt-image-2.5-sunburst-2026-09-08" + | "gpt-image-2.5-flare" + | "gpt-image-2.5-flare-2026-09-08" + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" + readonly "size"?: string | "1024x1024" | "1024x1536" | "1536x1024" | "auto" + readonly "output_format"?: "png" | "webp" | "jpeg" + readonly "output_compression"?: number + readonly "moderation"?: "auto" | "low" + readonly "background"?: "transparent" | "opaque" | "auto" + readonly "input_fidelity"?: BetaInputFidelity | null + readonly "input_image_mask"?: { readonly "image_url"?: string; readonly "file_id"?: string } + readonly "partial_images"?: number + readonly "action"?: BetaImageGenActionEnum +} +export const BetaImageGenTool = Schema.Struct({ + "type": Schema.Literal("image_generation").annotate({ + "description": "The type of the image generation tool. Always `image_generation`.\n" + }), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-image-1", + "gpt-image-1-mini", + "gpt-image-1.5", + "gpt-image-2", + "gpt-image-2-2026-04-21", + "gpt-image-2.5-sunburst", + "gpt-image-2.5-sunburst-2026-09-08", + "gpt-image-2.5-flare", + "gpt-image-2.5-flare-2026-09-08" + ]).annotate({ + "description": + "The image generation model to use. One of `gpt-image-1`,\n`gpt-image-1-mini`, `gpt-image-1.5`, `gpt-image-2`,\n`gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`,\n`gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`,\n`gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`. Default:\n`gpt-image-1`.\n" + }) + ]) + ), + "quality": Schema.optionalKey( + Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": + "The quality of the generated image. The GPT image models support `low`,\n`medium`, and `high`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`,\nincluding their `2026-09-08` snapshots, also support `xhigh` and `max`.\nDefault: `auto`.\n" + }) + ), + "size": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024", "auto"])]).annotate({ + "description": + "The size of the generated images. For `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and `gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. Resolutions above `2560x1440` are experimental, and the maximum supported resolution is `3840x2160`. The requested size must also satisfy the model's current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is supported for models that allow automatic sizing." + }) + ), + "output_format": Schema.optionalKey( + Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "description": "The output format of the generated image. One of `png`, `webp`, or\n`jpeg`. Default: `png`.\n" + }) + ), + "output_compression": Schema.optionalKey( + Schema.Number.annotate({ "description": "Compression level for the output image. Default: 100.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" })).check( + Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" }) + ) + ), + "moderation": Schema.optionalKey( + Schema.Literals(["auto", "low"]).annotate({ + "description": "Moderation level for the generated image. Default: `auto`.\n" + }) + ), + "background": Schema.optionalKey( + Schema.Literals(["transparent", "opaque", "auto"]).annotate({ + "description": + "Set the background of the generated image. One of `transparent`, `opaque`,\nor `auto`. `gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including\ntheir `2026-09-08` snapshots, support `opaque` and `transparent`\nbackgrounds. Transparent backgrounds are available for supported GPT Image\nmodels. For `gpt-image-2` and `gpt-image-2-2026-04-21`, this support is in\npreview. When using `transparent`, set the output format to `png` or `webp`.\nDefault: `auto`.\n" + }) + ), + "input_fidelity": Schema.optionalKey(Schema.Union([BetaInputFidelity, Schema.Null])), + "input_image_mask": Schema.optionalKey( + Schema.Struct({ + "image_url": Schema.optionalKey(Schema.String.annotate({ "description": "Base64-encoded mask image.\n" })), + "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "File ID for the mask image.\n" })) + }).annotate({ + "description": + "Optional mask for inpainting. Contains `image_url`\n(string, optional) and `file_id` (string, optional).\n" + }) + ), + "partial_images": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Number of partial images to generate in streaming mode, from 0 (default value) to 3.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(3).annotate({ "expected": "a value less than or equal to 3" })) + ), + "action": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaImageGenActionEnum).annotate({ + "description": "Whether to generate a new image or edit an existing image. Default: `auto`.\n" + }) + ) +}).annotate({ + "title": "Image generation tool", + "description": "A tool that generates images using the GPT image models.\n", + "identifier": "BetaImageGenTool" +}) +export type BetaInlineSkillParam = { + readonly "type": "inline" + readonly "name": string + readonly "description": string + readonly "source": BetaInlineSkillSourceParam +} +export const BetaInlineSkillParam = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "Defines an inline skill for this request." }), + "name": Schema.String.annotate({ "description": "The name of the skill." }), + "description": Schema.String.annotate({ "description": "The description of the skill." }), + "source": Schema.suspend((): Schema.Codec => BetaInlineSkillSourceParam).annotate({ + "description": "Inline skill payload" + }) +}).annotate({ "identifier": "BetaInlineSkillParam" }) +export type BetaLocalEnvironmentParam = { + readonly "type": "local" + readonly "skills"?: ReadonlyArray +} +export const BetaLocalEnvironmentParam = Schema.Struct({ + "type": Schema.Literal("local").annotate({ "description": "Use a local computer environment." }), + "skills": Schema.optionalKey( + Schema.Array(BetaLocalSkillParam).annotate({ "description": "An optional list of skills." }).check( + Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" }) + ) + ) +}).annotate({ "identifier": "BetaLocalEnvironmentParam" }) +export type BetaCustomGrammarFormatParam = { + readonly "type": "grammar" + readonly "syntax": BetaGrammarSyntax1 + readonly "definition": string +} +export const BetaCustomGrammarFormatParam = Schema.Struct({ + "type": Schema.Literal("grammar").annotate({ "description": "Grammar format. Always `grammar`." }), + "syntax": Schema.suspend((): Schema.Codec => BetaGrammarSyntax1).annotate({ + "description": "The syntax of the grammar definition. One of `lark` or `regex`." + }), + "definition": Schema.String.annotate({ "description": "The grammar definition." }) +}).annotate({ + "title": "Grammar format", + "description": "A grammar defined by the user.", + "identifier": "BetaCustomGrammarFormatParam" +}) +export type BetaFunctionToolParam = { + readonly "name": string + readonly "description"?: string | null + readonly "parameters"?: BetaEmptyModelParam | null + readonly "strict"?: boolean | null + readonly "type": "function" + readonly "async"?: boolean + readonly "output_schema"?: { readonly [x: string]: Schema.Json } | null + readonly "defer_loading"?: boolean + readonly "allowed_callers"?: ReadonlyArray | null +} +export const BetaFunctionToolParam = Schema.Struct({ + "name": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })).check( + Schema.isPattern(new RegExp("^[a-zA-Z0-9_-]+$", "u")).annotate({ + "expected": "a string matching the RegExp ^[a-zA-Z0-9_-]+$" + }) + ), + "description": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "parameters": Schema.optionalKey(Schema.Union([BetaEmptyModelParam, Schema.Null])), + "strict": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to enforce strict parameter validation. If omitted, Responses attempts to use strict validation when the schema is compatible, and falls back to non-strict validation otherwise." + }), + Schema.Null + ]) + ), + "type": Schema.Literal("function"), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Whether the tool response can be returned asynchronously versus immediately returned on next response creation." + }) + ), + "output_schema": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "A JSON Schema describing the JSON value encoded in string outputs for this function tool. This does not describe content-array outputs." + }), + Schema.Null + ]) + ), + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether this function should be deferred and discovered via tool search." + }) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaCallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ "identifier": "BetaFunctionToolParam" }) +export type BetaToolSearchOutputFunctionToolParam = { + readonly "name": string + readonly "description"?: string | null + readonly "parameters"?: BetaEmptyModelParam | null + readonly "strict"?: boolean | null + readonly "type": "function" + readonly "async"?: boolean + readonly "output_schema"?: { readonly [x: string]: Schema.Json } | null + readonly "defer_loading"?: boolean + readonly "allowed_callers"?: ReadonlyArray | null +} +export const BetaToolSearchOutputFunctionToolParam = Schema.Struct({ + "name": Schema.String.annotate({ "description": "The name of the loaded function tool." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })).check( + Schema.isPattern(new RegExp("^(?![\\s\\S]*[\\r\\n])[a-zA-Z0-9_.-]+$", "u")).annotate({ + "expected": "a string matching the RegExp ^(?![\\s\\S]*[\\r\\n])[a-zA-Z0-9_.-]+$" + }) + ), + "description": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "parameters": Schema.optionalKey(Schema.Union([BetaEmptyModelParam, Schema.Null])), + "strict": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to enforce strict parameter validation. If omitted, Responses attempts to use strict validation when the schema is compatible, and falls back to non-strict validation otherwise." + }), + Schema.Null + ]) + ), + "type": Schema.Literal("function"), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Whether the tool response can be returned asynchronously versus immediately returned on next response creation." + }) + ), + "output_schema": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "A JSON Schema describing the JSON value encoded in string outputs for this function tool. This does not describe content-array outputs." + }), + Schema.Null + ]) + ), + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether this function should be deferred and discovered via tool search." + }) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaCallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ "identifier": "BetaToolSearchOutputFunctionToolParam" }) +export type BetaToolSearchToolParam = { + readonly "type": "tool_search" + readonly "execution"?: BetaToolSearchExecutionType + readonly "description"?: string | null + readonly "parameters"?: BetaEmptyModelParam | null +} +export const BetaToolSearchToolParam = Schema.Struct({ + "type": Schema.Literal("tool_search").annotate({ "description": "The type of the tool. Always `tool_search`." }), + "execution": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaToolSearchExecutionType).annotate({ + "description": "Whether tool search is executed by the server or by the client." + }) + ), + "description": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "Description shown to the model for a client-executed tool search tool." + }), + Schema.Null + ]) + ), + "parameters": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaEmptyModelParam).annotate({ + "description": "Parameter schema for a client-executed tool search tool." + }), + Schema.Null + ]) + ) +}).annotate({ + "title": "Tool search tool", + "description": "Hosted or BYOT tool search configuration for deferred tools.", + "identifier": "BetaToolSearchToolParam" +}) +export type BetaWebSearchPreviewTool = { + readonly "type": "web_search_preview" | "web_search_preview_2025_03_11" + readonly "user_location"?: BetaApproximateLocation | null + readonly "search_context_size"?: BetaSearchContextSize + readonly "search_content_types"?: ReadonlyArray +} +export const BetaWebSearchPreviewTool = Schema.Struct({ + "type": Schema.Literals(["web_search_preview", "web_search_preview_2025_03_11"]).annotate({ + "description": "The type of the web search tool. One of `web_search_preview` or `web_search_preview_2025_03_11`." + }), + "user_location": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaApproximateLocation).annotate({ + "description": + "The approximate location of the user. If omitted or null, defaults to the United States. To avoid this fallback, pass `{\"type\": \"approximate\"}` without location fields. To localize results, provide the relevant location fields." + }), + Schema.Null + ]) + ), + "search_context_size": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaSearchContextSize).annotate({ + "description": + "High level guidance for the amount of context window space to use for the search. One of `low`, `medium`, or `high`. `medium` is the default." + }) + ), + "search_content_types": Schema.optionalKey(Schema.Array(BetaSearchContentType)) +}).annotate({ + "title": "Web search preview", + "description": + "This tool searches the web for relevant results to use in a response. Learn more about the [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search).", + "identifier": "BetaWebSearchPreviewTool" +}) +export type BetaToolChoiceParam = + | BetaToolChoiceOptions + | BetaToolChoiceAllowed + | BetaToolChoiceTypes + | BetaToolChoiceFunction + | BetaToolChoiceMCP + | BetaToolChoiceCustom + | BetaSpecificProgrammaticToolCallingParam + | BetaSpecificApplyPatchParam + | BetaSpecificFunctionShellParam +export const BetaToolChoiceParam = Schema.Union([ + BetaToolChoiceOptions, + BetaToolChoiceAllowed, + BetaToolChoiceTypes, + BetaToolChoiceFunction, + BetaToolChoiceMCP, + BetaToolChoiceCustom, + BetaSpecificProgrammaticToolCallingParam, + BetaSpecificApplyPatchParam, + BetaSpecificFunctionShellParam +], { mode: "oneOf" }).annotate({ + "description": + "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n", + "identifier": "BetaToolChoiceParam" +}) +export type BetaInputTextContent = { + readonly "type": "input_text" + readonly "text": string + readonly "prompt_cache_breakpoint"?: BetaPromptCacheBreakpointConfig +} +export const BetaInputTextContent = Schema.Struct({ + "type": Schema.Literal("input_text").annotate({ "description": "The type of the input item. Always `input_text`." }), + "text": Schema.String.annotate({ "description": "The text input to the model." }), + "prompt_cache_breakpoint": Schema.optionalKey(BetaPromptCacheBreakpointConfig) +}).annotate({ + "title": "Input text", + "description": "A text input to the model.", + "identifier": "BetaInputTextContent" +}) +export type BetaInputImageContent = { + readonly "type": "input_image" + readonly "image_url"?: string | null + readonly "file_id"?: string | null + readonly "detail": BetaImageDetail + readonly "prompt_cache_breakpoint"?: BetaPromptCacheBreakpointConfig +} +export const BetaInputImageContent = Schema.Struct({ + "type": Schema.Literal("input_image").annotate({ + "description": "The type of the input item. Always `input_image`." + }), + "image_url": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL.", + "format": "uri" + }), + Schema.Null + ]) + ), + "file_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), + Schema.Null + ]) + ), + "detail": Schema.suspend((): Schema.Codec => BetaImageDetail).annotate({ + "description": + "The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." + }), + "prompt_cache_breakpoint": Schema.optionalKey(BetaPromptCacheBreakpointConfig) +}).annotate({ + "title": "Input image", + "description": + "An image input to the model. Learn about [image inputs](https://developers.openai.com/api/docs/guides/images-vision).", + "identifier": "BetaInputImageContent" +}) +export type BetaComputerScreenshotContent = { + readonly "type": "computer_screenshot" + readonly "image_url": string | null + readonly "file_id": string | null + readonly "detail": BetaImageDetail + readonly "prompt_cache_breakpoint"?: BetaPromptCacheBreakpointConfig +} +export const BetaComputerScreenshotContent = Schema.Struct({ + "type": Schema.Literal("computer_screenshot").annotate({ + "description": + "Specifies the event type. For a computer screenshot, this property is always set to `computer_screenshot`." + }), + "image_url": Schema.Union([ + Schema.String.annotate({ "description": "The URL of the screenshot image.", "format": "uri" }), + Schema.Null + ]), + "file_id": Schema.Union([ + Schema.String.annotate({ "description": "The identifier of an uploaded file that contains the screenshot." }), + Schema.Null + ]), + "detail": Schema.suspend((): Schema.Codec => BetaImageDetail).annotate({ + "description": + "The detail level of the screenshot image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." + }), + "prompt_cache_breakpoint": Schema.optionalKey(BetaPromptCacheBreakpointConfig) +}).annotate({ + "title": "Computer screenshot", + "description": "A screenshot of a computer.", + "identifier": "BetaComputerScreenshotContent" +}) +export type BetaInputFileContent = { + readonly "type": "input_file" + readonly "file_id"?: string | null + readonly "filename"?: string + readonly "file_data"?: string + readonly "prompt_cache_breakpoint"?: BetaPromptCacheBreakpointConfig + readonly "file_url"?: string + readonly "detail"?: BetaFileInputDetail +} +export const BetaInputFileContent = Schema.Struct({ + "type": Schema.Literal("input_file").annotate({ "description": "The type of the input item. Always `input_file`." }), + "file_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), + Schema.Null + ]) + ), + "filename": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the file to be sent to the model." }) + ), + "file_data": Schema.optionalKey( + Schema.String.annotate({ "description": "The content of the file to be sent to the model.\n" }) + ), + "prompt_cache_breakpoint": Schema.optionalKey(BetaPromptCacheBreakpointConfig), + "file_url": Schema.optionalKey( + Schema.String.annotate({ "description": "The URL of the file to be sent to the model.", "format": "uri" }) + ), + "detail": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaFileInputDetail).annotate({ + "description": + "The detail level of the file to be sent to the model. Use `auto` to let the system select the detail level; for GPT-5.6 and later models, `auto` uses high-quality rendering, which may increase input token usage. Use `low` for lower-cost rendering, or `high` to render the file at higher quality. Defaults to `auto`." + }) + ) +}).annotate({ + "title": "Input file", + "description": "A file input to the model.", + "identifier": "BetaInputFileContent" +}) +export type BetaAccessProgramsParam = { readonly "cyber"?: BetaCyberAccessProgramEnum } +export const BetaAccessProgramsParam = Schema.Struct({ + "cyber": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaCyberAccessProgramEnum).annotate({ + "description": + "The Cyber access program to use for this request. Supported values are `standard`, `daybreak_blue`, and `daybreak_red`. If omitted, the API resolves the program from the model's Cyber tier and your organization and project access, subject to model-specific eligibility restrictions. By default, models without a Cyber tier use Standard. Blue-tier models use Daybreak Blue when authorized; otherwise they fall back to Standard unless the model requires Daybreak access. Red-tier models use Daybreak Red and require authorization. Requests that require unavailable Daybreak access return 403. An implicit Standard fallback is represented by null in the response's access_programs field, rather than an explicit Standard selection." + }) + ) +}).annotate({ + "description": "Domain-specific access programs to use for this request.", + "identifier": "BetaAccessProgramsParam" +}) +export type BetaAccessProgramsBody = { readonly "cyber": BetaCyberAccessProgramEnum } +export const BetaAccessProgramsBody = Schema.Struct({ + "cyber": Schema.suspend((): Schema.Codec => BetaCyberAccessProgramEnum).annotate({ + "description": "The effective Cyber access program used for this response." + }) +}).annotate({ "identifier": "BetaAccessProgramsBody" }) +export type BetaReasoning = { + readonly "mode"?: BetaReasoningModeEnum + readonly "effort"?: BetaReasoningEffort + readonly "summary"?: "auto" | "concise" | "detailed" | null + readonly "context"?: "auto" | "current_turn" | "all_turns" | null + readonly "generate_summary"?: "auto" | "concise" | "detailed" | null +} +export const BetaReasoning = Schema.Struct({ + "mode": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaReasoningModeEnum).annotate({ + "description": + "Controls the reasoning execution mode for the request.\n\nWhen returned on a response, this is the effective execution mode.\n" + }) + ), + "effort": Schema.optionalKey(BetaReasoningEffort), + "summary": Schema.optionalKey(Schema.Union([ + Schema.Literals(["auto", "concise", "detailed"]).annotate({ + "description": + "A summary of the reasoning performed by the model. This can be\nuseful for debugging and understanding the model's reasoning process.\nOne of `auto`, `concise`, or `detailed`.\n\n`concise` is supported for `computer-use-preview` models and all reasoning models after `gpt-5`.\n" + }), + Schema.Null + ])), + "context": Schema.optionalKey(Schema.Union([ + Schema.Literals(["auto", "current_turn", "all_turns"]).annotate({ + "description": + "Controls which reasoning items are rendered back to the model on later turns.\nIf omitted or set to `auto`, the model determines the context mode. The\n`gpt-5.6` model family defaults to `all_turns`; earlier models default to\n`current_turn`.\n\nWhen returned on a response, this is the effective reasoning context mode\nused for the response.\n" + }), + Schema.Null + ])), + "generate_summary": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["auto", "concise", "detailed"]).annotate({ + "description": + "**Deprecated:** use `summary` instead.\n\nA summary of the reasoning performed by the model. This can be\nuseful for debugging and understanding the model's reasoning process.\nOne of `auto`, `concise`, or `detailed`.\n" + }), + Schema.Null + ]) + ) +}).annotate({ + "title": "Reasoning", + "description": + "Configuration options for\n[reasoning models](https://developers.openai.com/api/docs/guides/reasoning).\n", + "identifier": "BetaReasoning" +}) +export type BetaProgram = { + readonly "agent"?: BetaAgentTag + readonly "type": "program" + readonly "id": string + readonly "call_id": string + readonly "code": string + readonly "fingerprint": string +} +export const BetaProgram = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("program").annotate({ "description": "The type of the item. Always `program`." }), + "id": Schema.String.annotate({ "description": "The unique ID of the program item." }), + "call_id": Schema.String.annotate({ "description": "The stable call ID of the program item." }), + "code": Schema.String.annotate({ "description": "The JavaScript source executed by programmatic tool calling." }), + "fingerprint": Schema.String.annotate({ + "description": "Opaque program replay fingerprint that must be round-tripped." + }) +}).annotate({ "identifier": "BetaProgram" }) +export type BetaCompactionBody = { + readonly "agent"?: BetaAgentTag + readonly "type": "compaction" + readonly "id": string + readonly "encrypted_content": string + readonly "created_by"?: string +} +export const BetaCompactionBody = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("compaction").annotate({ "description": "The type of the item. Always `compaction`." }), + "id": Schema.String.annotate({ "description": "The unique ID of the compaction item." }), + "encrypted_content": Schema.String.annotate({ + "description": "The encrypted content that was produced by compaction." + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ + "title": "Compaction item", + "description": + "A compaction item generated by the [`v1/responses/compact` API](https://developers.openai.com/api/reference/resources/responses/methods/compact).", + "identifier": "BetaCompactionBody" +}) +export type BetaLocalShellToolCallOutput = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "local_shell_call_output" + readonly "id": string + readonly "output": string + readonly "status"?: "in_progress" | "completed" | "incomplete" | null + readonly "call_id": Schema.Json +} +export const BetaLocalShellToolCallOutput = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("local_shell_call_output").annotate({ + "description": "The type of the local shell tool call output. Always `local_shell_call_output`.\n" + }), + "id": Schema.String.annotate({ + "description": "The unique ID of the local shell tool call generated by the model.\n" + }), + "output": Schema.String.annotate({ "description": "A JSON string of the output of the local shell tool call.\n" }), + "status": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": "The status of the item. One of `in_progress`, `completed`, or `incomplete`.\n" + }), + Schema.Null + ]) + ), + "call_id": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ + "title": "Local shell call output", + "description": "The output of a local shell tool call.\n", + "identifier": "BetaLocalShellToolCallOutput" +}) +export type BetaMCPApprovalRequest = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "mcp_approval_request" + readonly "id": string + readonly "server_label": string + readonly "name": string + readonly "arguments": string +} +export const BetaMCPApprovalRequest = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("mcp_approval_request").annotate({ + "description": "The type of the item. Always `mcp_approval_request`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the approval request.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server making the request.\n" }), + "name": Schema.String.annotate({ "description": "The name of the tool to run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of arguments for the tool.\n" }) +}).annotate({ + "title": "MCP approval request", + "description": "A request for human approval of a tool invocation.\n", + "identifier": "BetaMCPApprovalRequest" +}) +export type BetaMCPApprovalResponseResource = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "mcp_approval_response" + readonly "id": string + readonly "approval_request_id": string + readonly "approve": boolean + readonly "reason"?: string | null + readonly "request_id": Schema.Json +} +export const BetaMCPApprovalResponseResource = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("mcp_approval_response").annotate({ + "description": "The type of the item. Always `mcp_approval_response`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the approval response\n" }), + "approval_request_id": Schema.String.annotate({ "description": "The ID of the approval request being answered.\n" }), + "approve": Schema.Boolean.annotate({ "description": "Whether the request was approved.\n" }), + "reason": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Optional reason for the decision.\n" }), Schema.Null]) + ), + "request_id": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ + "title": "MCP approval response", + "description": "A response to an MCP approval request.\n", + "identifier": "BetaMCPApprovalResponseResource" +}) +export type BetaResponseAudioDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.audio.delta" + readonly "sequence_number": number + readonly "delta": string +} +export const BetaResponseAudioDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.audio.delta").annotate({ + "description": "The type of the event. Always `response.audio.delta`.\n" + }), + "sequence_number": Schema.Number.annotate({ + "description": "A sequence number for this chunk of the stream response.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "A chunk of Base64 encoded response audio bytes.\n" }) +}).annotate({ + "description": "Emitted when there is a partial audio response.", + "identifier": "BetaResponseAudioDeltaEvent" +}) +export type BetaResponseAudioDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.audio.done" + readonly "sequence_number": number + readonly "response_id": Schema.Json +} +export const BetaResponseAudioDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.audio.done").annotate({ + "description": "The type of the event. Always `response.audio.done`.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the delta.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "response_id": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ + "description": "Emitted when the audio response is complete.", + "identifier": "BetaResponseAudioDoneEvent" +}) +export type BetaResponseAudioTranscriptDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.audio.transcript.delta" + readonly "delta": string + readonly "sequence_number": number + readonly "response_id": Schema.Json +} +export const BetaResponseAudioTranscriptDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.audio.transcript.delta").annotate({ + "description": "The type of the event. Always `response.audio.transcript.delta`.\n" + }), + "delta": Schema.String.annotate({ "description": "The partial transcript of the audio response.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "response_id": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ + "description": "Emitted when there is a partial transcript of audio.", + "identifier": "BetaResponseAudioTranscriptDeltaEvent" +}) +export type BetaResponseAudioTranscriptDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.audio.transcript.done" + readonly "sequence_number": number + readonly "response_id": Schema.Json +} +export const BetaResponseAudioTranscriptDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.audio.transcript.done").annotate({ + "description": "The type of the event. Always `response.audio.transcript.done`.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "response_id": Schema.Json.annotate({ "expected": "JSON value" }) +}).annotate({ + "description": "Emitted when the full audio transcript is completed.", + "identifier": "BetaResponseAudioTranscriptDoneEvent" +}) +export type BetaResponseCodeInterpreterCallCodeDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.code_interpreter_call_code.delta" + readonly "output_index": number + readonly "item_id": string + readonly "delta": string + readonly "sequence_number": number +} +export const BetaResponseCodeInterpreterCallCodeDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.code_interpreter_call_code.delta").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call_code.delta`." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code is being streamed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "delta": Schema.String.annotate({ + "description": "The partial code snippet being streamed by the code interpreter." + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a partial code snippet is streamed by the code interpreter.", + "identifier": "BetaResponseCodeInterpreterCallCodeDeltaEvent" +}) +export type BetaResponseCodeInterpreterCallCodeDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.code_interpreter_call_code.done" + readonly "output_index": number + readonly "item_id": string + readonly "code": string + readonly "sequence_number": number +} +export const BetaResponseCodeInterpreterCallCodeDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.code_interpreter_call_code.done").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call_code.done`." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code is finalized." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "code": Schema.String.annotate({ "description": "The final code snippet output by the code interpreter." }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when the code snippet is finalized by the code interpreter.", + "identifier": "BetaResponseCodeInterpreterCallCodeDoneEvent" +}) +export type BetaResponseCodeInterpreterCallCompletedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.code_interpreter_call.completed" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseCodeInterpreterCallCompletedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.code_interpreter_call.completed").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call.completed`." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code interpreter call is completed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when the code interpreter call is completed.", + "identifier": "BetaResponseCodeInterpreterCallCompletedEvent" +}) +export type BetaResponseCodeInterpreterCallInProgressEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.code_interpreter_call.in_progress" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseCodeInterpreterCallInProgressEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.code_interpreter_call.in_progress").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call.in_progress`." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code interpreter call is in progress." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a code interpreter call is in progress.", + "identifier": "BetaResponseCodeInterpreterCallInProgressEvent" +}) +export type BetaResponseCodeInterpreterCallInterpretingEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.code_interpreter_call.interpreting" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseCodeInterpreterCallInterpretingEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.code_interpreter_call.interpreting").annotate({ + "description": "The type of the event. Always `response.code_interpreter_call.interpreting`." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response for which the code interpreter is interpreting code." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The unique identifier of the code interpreter tool call item." }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of this event, used to order streaming events." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when the code interpreter is actively interpreting the code snippet.", + "identifier": "BetaResponseCodeInterpreterCallInterpretingEvent" +}) +export type BetaResponseCompactionCompactingStreamingEvent = { + readonly "type": "response.compaction.compacting" + readonly "sequence_number": number + readonly "agent"?: BetaAgentTag + readonly "output_index": number + readonly "item_id": string +} +export const BetaResponseCompactionCompactingStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.compaction.compacting").annotate({ + "description": "The type of the event, always `response.compaction.compacting`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "output_index": Schema.Number.annotate({ "description": "The index of the compaction output item." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item_id": Schema.String.annotate({ "description": "The ID of the compaction output item." }) +}).annotate({ + "title": "Response compaction compacting event", + "description": "Emitted when new summary content is sampled for a compaction trigger. Contains no summary content.", + "identifier": "BetaResponseCompactionCompactingStreamingEvent" +}) +export type BetaResponseErrorEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "error" + readonly "code": string | null + readonly "message": string + readonly "param": string | null + readonly "sequence_number": number +} +export const BetaResponseErrorEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("error").annotate({ "description": "The type of the event. Always `error`.\n" }), + "code": Schema.Union([Schema.String.annotate({ "description": "The error code.\n" }), Schema.Null]), + "message": Schema.String.annotate({ "description": "The error message.\n" }), + "param": Schema.Union([Schema.String.annotate({ "description": "The error parameter.\n" }), Schema.Null]), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ "description": "Emitted when an error occurs.", "identifier": "BetaResponseErrorEvent" }) +export type BetaResponseFileSearchCallCompletedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.file_search_call.completed" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseFileSearchCallCompletedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.file_search_call.completed").annotate({ + "description": "The type of the event. Always `response.file_search_call.completed`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the file search call is initiated.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the file search call is initiated.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a file search call is completed (results found).", + "identifier": "BetaResponseFileSearchCallCompletedEvent" +}) +export type BetaResponseFileSearchCallInProgressEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.file_search_call.in_progress" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseFileSearchCallInProgressEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.file_search_call.in_progress").annotate({ + "description": "The type of the event. Always `response.file_search_call.in_progress`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the file search call is initiated.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the file search call is initiated.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a file search call is initiated.", + "identifier": "BetaResponseFileSearchCallInProgressEvent" +}) +export type BetaResponseFileSearchCallSearchingEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.file_search_call.searching" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseFileSearchCallSearchingEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.file_search_call.searching").annotate({ + "description": "The type of the event. Always `response.file_search_call.searching`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the file search call is searching.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the file search call is initiated.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a file search is currently searching.", + "identifier": "BetaResponseFileSearchCallSearchingEvent" +}) +export type BetaResponseFunctionCallArgumentsDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.function_call_arguments.delta" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number + readonly "delta": string +} +export const BetaResponseFunctionCallArgumentsDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.function_call_arguments.delta").annotate({ + "description": "The type of the event. Always `response.function_call_arguments.delta`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the function-call arguments delta is added to.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the function-call arguments delta is added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "delta": Schema.String.annotate({ "description": "The function-call arguments delta that is added.\n" }) +}).annotate({ + "description": "Emitted when there is a partial function-call arguments delta.", + "identifier": "BetaResponseFunctionCallArgumentsDeltaEvent" +}) +export type BetaResponseFunctionCallArgumentsDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.function_call_arguments.done" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number + readonly "arguments": string +} +export const BetaResponseFunctionCallArgumentsDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.function_call_arguments.done"), + "item_id": Schema.String.annotate({ "description": "The ID of the item." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "arguments": Schema.String.annotate({ "description": "The function-call arguments." }) +}).annotate({ + "description": "Emitted when function-call arguments are finalized.", + "identifier": "BetaResponseFunctionCallArgumentsDoneEvent" +}) +export type BetaResponseShellCallCommandAddedStreamingEvent = { + readonly "type": "response.shell_call_command.added" + readonly "sequence_number": number + readonly "agent"?: BetaAgentTag + readonly "output_index": number + readonly "command_index": number + readonly "command": string +} +export const BetaResponseShellCallCommandAddedStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_command.added").annotate({ + "description": "The type of the event, always `response.shell_call_command.added`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that was added." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "command": Schema.String.annotate({ "description": "The shell command that was added." }) +}).annotate({ + "title": "Response shell command added event", + "description": "A streaming event that indicated a shell command was added to a tool call.", + "identifier": "BetaResponseShellCallCommandAddedStreamingEvent" +}) +export type BetaResponseShellCallCommandDeltaStreamingEvent = { + readonly "type": "response.shell_call_command.delta" + readonly "sequence_number": number + readonly "agent"?: BetaAgentTag + readonly "output_index": number + readonly "command_index": number + readonly "delta": string + readonly "obfuscation"?: string +} +export const BetaResponseShellCallCommandDeltaStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_command.delta").annotate({ + "description": "The type of the event, always `response.shell_call_command.delta`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "delta": Schema.String.annotate({ "description": "The shell command delta that was appended." }), + "obfuscation": Schema.optionalKey( + Schema.String.annotate({ "description": "An obfuscation string that was added to pad the event payload." }) + ) +}).annotate({ + "title": "Response shell command delta event", + "description": "A streaming event that indicated a shell command was incrementally updated.", + "identifier": "BetaResponseShellCallCommandDeltaStreamingEvent" +}) +export type BetaResponseShellCallCommandDoneStreamingEvent = { + readonly "type": "response.shell_call_command.done" + readonly "sequence_number": number + readonly "agent"?: BetaAgentTag + readonly "output_index": number + readonly "command_index": number + readonly "command": string +} +export const BetaResponseShellCallCommandDoneStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_command.done").annotate({ + "description": "The type of the event, always `response.shell_call_command.done`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that was completed." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "command": Schema.String.annotate({ "description": "The final shell command that was emitted." }) +}).annotate({ + "title": "Response shell command done event", + "description": "A streaming event that indicated a shell command was completed.", + "identifier": "BetaResponseShellCallCommandDoneStreamingEvent" +}) +export type BetaResponseReasoningSummaryPartAddedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.reasoning_summary_part.added" + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "sequence_number": number + readonly "part": { readonly "type": "summary_text"; readonly "text": string } +} +export const BetaResponseReasoningSummaryPartAddedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.reasoning_summary_part.added").annotate({ + "description": "The type of the event. Always `response.reasoning_summary_part.added`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the item this summary part is associated with.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this summary part is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary part within the reasoning summary.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "part": Schema.Struct({ + "type": Schema.Literal("summary_text").annotate({ + "description": "The type of the summary part. Always `summary_text`." + }), + "text": Schema.String.annotate({ "description": "The text of the summary part." }) + }).annotate({ "description": "The summary part that was added.\n" }) +}).annotate({ + "description": "Emitted when a new reasoning summary part is added.", + "identifier": "BetaResponseReasoningSummaryPartAddedEvent" +}) +export type BetaResponseReasoningSummaryPartDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.reasoning_summary_part.done" + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "status"?: "incomplete" + readonly "sequence_number": number + readonly "part": { readonly "type": "summary_text"; readonly "text": string } +} +export const BetaResponseReasoningSummaryPartDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.reasoning_summary_part.done").annotate({ + "description": "The type of the event. Always `response.reasoning_summary_part.done`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the item this summary part is associated with.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this summary part is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary part within the reasoning summary.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "status": Schema.optionalKey( + Schema.Literal("incomplete").annotate({ + "description": + "The completion status of the summary part. Omitted when the part completed\nnormally and set to `incomplete` when generation was interrupted.\n" + }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "part": Schema.Struct({ + "type": Schema.Literal("summary_text").annotate({ + "description": "The type of the summary part. Always `summary_text`." + }), + "text": Schema.String.annotate({ "description": "The text of the summary part." }) + }).annotate({ "description": "The completed summary part.\n" }) +}).annotate({ + "description": "Emitted when a reasoning summary part is completed.", + "identifier": "BetaResponseReasoningSummaryPartDoneEvent" +}) +export type BetaResponseReasoningSummaryTextDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.reasoning_summary_text.delta" + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "delta": string + readonly "sequence_number": number +} +export const BetaResponseReasoningSummaryTextDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.reasoning_summary_text.delta").annotate({ + "description": "The type of the event. Always `response.reasoning_summary_text.delta`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the item this summary text delta is associated with.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this summary text delta is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary part within the reasoning summary.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "The text delta that was added to the summary.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a delta is added to a reasoning summary text.", + "identifier": "BetaResponseReasoningSummaryTextDeltaEvent" +}) +export type BetaResponseReasoningSummaryTextDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.reasoning_summary_text.done" + readonly "item_id": string + readonly "output_index": number + readonly "summary_index": number + readonly "text": string + readonly "sequence_number": number +} +export const BetaResponseReasoningSummaryTextDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.reasoning_summary_text.done").annotate({ + "description": "The type of the event. Always `response.reasoning_summary_text.done`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the item this summary text is associated with.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this summary text is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "summary_index": Schema.Number.annotate({ + "description": "The index of the summary part within the reasoning summary.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "text": Schema.String.annotate({ "description": "The full text of the completed reasoning summary.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a reasoning summary text is completed.", + "identifier": "BetaResponseReasoningSummaryTextDoneEvent" +}) +export type BetaResponseReasoningTextDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.reasoning_text.delta" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "delta": string + readonly "sequence_number": number +} +export const BetaResponseReasoningTextDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.reasoning_text.delta").annotate({ + "description": "The type of the event. Always `response.reasoning_text.delta`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the item this reasoning text delta is associated with.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this reasoning text delta is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the reasoning content part this delta is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "The text delta that was added to the reasoning content.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a delta is added to a reasoning text.", + "identifier": "BetaResponseReasoningTextDeltaEvent" +}) +export type BetaResponseReasoningTextDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.reasoning_text.done" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "text": string + readonly "sequence_number": number +} +export const BetaResponseReasoningTextDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.reasoning_text.done").annotate({ + "description": "The type of the event. Always `response.reasoning_text.done`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the item this reasoning text is associated with.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item this reasoning text is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ "description": "The index of the reasoning content part.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "text": Schema.String.annotate({ "description": "The full text of the completed reasoning content.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a reasoning text is completed.", + "identifier": "BetaResponseReasoningTextDoneEvent" +}) +export type BetaResponseRefusalDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.refusal.delta" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "delta": string + readonly "sequence_number": number +} +export const BetaResponseRefusalDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.refusal.delta").annotate({ + "description": "The type of the event. Always `response.refusal.delta`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the refusal text is added to.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the refusal text is added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part that the refusal text is added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "The refusal text that is added.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when there is a partial refusal text.", + "identifier": "BetaResponseRefusalDeltaEvent" +}) +export type BetaResponseRefusalDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.refusal.done" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "refusal": string + readonly "sequence_number": number +} +export const BetaResponseRefusalDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.refusal.done").annotate({ + "description": "The type of the event. Always `response.refusal.done`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the refusal text is finalized.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the refusal text is finalized.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part that the refusal text is finalized.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "refusal": Schema.String.annotate({ "description": "The refusal text that is finalized.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ "description": "Emitted when refusal text is finalized.", "identifier": "BetaResponseRefusalDoneEvent" }) +export type BetaResponseWebSearchCallCompletedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.web_search_call.completed" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseWebSearchCallCompletedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.web_search_call.completed").annotate({ + "description": "The type of the event. Always `response.web_search_call.completed`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the web search call is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "Unique ID for the output item associated with the web search call.\n" + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the web search call being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a web search call is completed.", + "identifier": "BetaResponseWebSearchCallCompletedEvent" +}) +export type BetaResponseWebSearchCallInProgressEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.web_search_call.in_progress" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseWebSearchCallInProgressEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.web_search_call.in_progress").annotate({ + "description": "The type of the event. Always `response.web_search_call.in_progress`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the web search call is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "Unique ID for the output item associated with the web search call.\n" + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the web search call being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a web search call is initiated.", + "identifier": "BetaResponseWebSearchCallInProgressEvent" +}) +export type BetaResponseWebSearchCallSearchingEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.web_search_call.searching" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseWebSearchCallSearchingEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.web_search_call.searching").annotate({ + "description": "The type of the event. Always `response.web_search_call.searching`.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the web search call is associated with.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "Unique ID for the output item associated with the web search call.\n" + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the web search call being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Emitted when a web search call is executing.", + "identifier": "BetaResponseWebSearchCallSearchingEvent" +}) +export type BetaResponseImageGenCallCompletedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.image_generation_call.completed" + readonly "output_index": number + readonly "sequence_number": number + readonly "item_id": string +} +export const BetaResponseImageGenCallCompletedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.image_generation_call.completed").annotate({ + "description": "The type of the event. Always 'response.image_generation_call.completed'." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the image generation item being processed." + }) +}).annotate({ + "title": "ResponseImageGenCallCompletedEvent", + "description": "Emitted when an image generation tool call has completed and the final image is available.\n", + "identifier": "BetaResponseImageGenCallCompletedEvent" +}) +export type BetaResponseImageGenCallGeneratingEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.image_generation_call.generating" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseImageGenCallGeneratingEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.image_generation_call.generating").annotate({ + "description": "The type of the event. Always 'response.image_generation_call.generating'." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the image generation item being processed." + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the image generation item being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "title": "ResponseImageGenCallGeneratingEvent", + "description": "Emitted when an image generation tool call is actively generating an image (intermediate state).\n", + "identifier": "BetaResponseImageGenCallGeneratingEvent" +}) +export type BetaResponseImageGenCallInProgressEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.image_generation_call.in_progress" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number +} +export const BetaResponseImageGenCallInProgressEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.image_generation_call.in_progress").annotate({ + "description": "The type of the event. Always 'response.image_generation_call.in_progress'." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the image generation item being processed." + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the image generation item being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "title": "ResponseImageGenCallInProgressEvent", + "description": "Emitted when an image generation tool call is in progress.\n", + "identifier": "BetaResponseImageGenCallInProgressEvent" +}) +export type BetaResponseImageGenCallPartialImageEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.image_generation_call.partial_image" + readonly "output_index": number + readonly "item_id": string + readonly "sequence_number": number + readonly "partial_image_index": number + readonly "partial_image_b64": string + readonly "size"?: string + readonly "quality"?: string + readonly "background"?: string + readonly "output_format"?: string +} +export const BetaResponseImageGenCallPartialImageEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.image_generation_call.partial_image").annotate({ + "description": "The type of the event. Always 'response.image_generation_call.partial_image'." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the image generation item being processed." + }), + "sequence_number": Schema.Number.annotate({ + "description": "The sequence number of the image generation item being processed." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "partial_image_index": Schema.Number.annotate({ + "description": "0-based index for the partial image (backend is 1-based, but this is 0-based for the user)." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "partial_image_b64": Schema.String.annotate({ + "description": "Base64-encoded partial image data, suitable for rendering as an image." + }), + "size": Schema.optionalKey(Schema.String.annotate({ "description": "The image size that was used." })), + "quality": Schema.optionalKey(Schema.String.annotate({ "description": "The image quality that was used." })), + "background": Schema.optionalKey(Schema.String.annotate({ "description": "The background setting that was used." })), + "output_format": Schema.optionalKey(Schema.String.annotate({ "description": "The output format that was used." })) +}).annotate({ + "title": "ResponseImageGenCallPartialImageEvent", + "description": "Emitted when a partial image is available during image generation streaming.\n", + "identifier": "BetaResponseImageGenCallPartialImageEvent" +}) +export type BetaResponseMCPCallArgumentsDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.mcp_call_arguments.delta" + readonly "output_index": number + readonly "item_id": string + readonly "delta": string + readonly "sequence_number": number +} +export const BetaResponseMCPCallArgumentsDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.mcp_call_arguments.delta").annotate({ + "description": "The type of the event. Always 'response.mcp_call_arguments.delta'." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the MCP tool call item being processed." + }), + "delta": Schema.String.annotate({ + "description": "A JSON string containing the partial update to the arguments for the MCP tool call.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPCallArgumentsDeltaEvent", + "description": "Emitted when there is a delta (partial update) to the arguments of an MCP tool call.\n", + "identifier": "BetaResponseMCPCallArgumentsDeltaEvent" +}) +export type BetaResponseMCPCallArgumentsDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.mcp_call_arguments.done" + readonly "output_index": number + readonly "item_id": string + readonly "arguments": string + readonly "sequence_number": number +} +export const BetaResponseMCPCallArgumentsDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.mcp_call_arguments.done").annotate({ + "description": "The type of the event. Always 'response.mcp_call_arguments.done'." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the MCP tool call item being processed." + }), + "arguments": Schema.String.annotate({ + "description": "A JSON string containing the finalized arguments for the MCP tool call.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPCallArgumentsDoneEvent", + "description": "Emitted when the arguments for an MCP tool call are finalized.\n", + "identifier": "BetaResponseMCPCallArgumentsDoneEvent" +}) +export type BetaResponseMCPCallCompletedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.mcp_call.completed" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number +} +export const BetaResponseMCPCallCompletedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.mcp_call.completed").annotate({ + "description": "The type of the event. Always 'response.mcp_call.completed'." + }), + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that completed." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that completed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPCallCompletedEvent", + "description": "Emitted when an MCP tool call has completed successfully.\n", + "identifier": "BetaResponseMCPCallCompletedEvent" +}) +export type BetaResponseMCPCallFailedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.mcp_call.failed" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number +} +export const BetaResponseMCPCallFailedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.mcp_call.failed").annotate({ + "description": "The type of the event. Always 'response.mcp_call.failed'." + }), + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that failed." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that failed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPCallFailedEvent", + "description": "Emitted when an MCP tool call has failed.\n", + "identifier": "BetaResponseMCPCallFailedEvent" +}) +export type BetaResponseMCPCallInProgressEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.mcp_call.in_progress" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string +} +export const BetaResponseMCPCallInProgressEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.mcp_call.in_progress").annotate({ + "description": "The type of the event. Always 'response.mcp_call.in_progress'." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the MCP tool call item being processed." + }) +}).annotate({ + "title": "ResponseMCPCallInProgressEvent", + "description": "Emitted when an MCP tool call is in progress.\n", + "identifier": "BetaResponseMCPCallInProgressEvent" +}) +export type BetaResponseMCPListToolsCompletedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.mcp_list_tools.completed" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number +} +export const BetaResponseMCPListToolsCompletedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.mcp_list_tools.completed").annotate({ + "description": "The type of the event. Always 'response.mcp_list_tools.completed'." + }), + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that produced this output." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was processed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPListToolsCompletedEvent", + "description": "Emitted when the list of available MCP tools has been successfully retrieved.\n", + "identifier": "BetaResponseMCPListToolsCompletedEvent" +}) +export type BetaResponseMCPListToolsFailedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.mcp_list_tools.failed" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number +} +export const BetaResponseMCPListToolsFailedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.mcp_list_tools.failed").annotate({ + "description": "The type of the event. Always 'response.mcp_list_tools.failed'." + }), + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that failed." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that failed." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPListToolsFailedEvent", + "description": "Emitted when the attempt to list available MCP tools has failed.\n", + "identifier": "BetaResponseMCPListToolsFailedEvent" +}) +export type BetaResponseMCPListToolsInProgressEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.mcp_list_tools.in_progress" + readonly "item_id": string + readonly "output_index": number + readonly "sequence_number": number +} +export const BetaResponseMCPListToolsInProgressEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.mcp_list_tools.in_progress").annotate({ + "description": "The type of the event. Always 'response.mcp_list_tools.in_progress'." + }), + "item_id": Schema.String.annotate({ "description": "The ID of the MCP tool call item that is being processed." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that is being processed." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseMCPListToolsInProgressEvent", + "description": "Emitted when the system is in the process of retrieving the list of available MCP tools.\n", + "identifier": "BetaResponseMCPListToolsInProgressEvent" +}) +export type BetaResponseCustomToolCallInputDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.custom_tool_call_input.delta" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string + readonly "delta": string +} +export const BetaResponseCustomToolCallInputDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.custom_tool_call_input.delta").annotate({ + "description": "The event type identifier." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "output_index": Schema.Number.annotate({ "description": "The index of the output this delta applies to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item_id": Schema.String.annotate({ + "description": "Unique identifier for the API item associated with this event." + }), + "delta": Schema.String.annotate({ "description": "The incremental input data (delta) for the custom tool call." }) +}).annotate({ + "title": "ResponseCustomToolCallInputDelta", + "description": "Event representing a delta (partial update) to the input of a custom tool call.\n", + "identifier": "BetaResponseCustomToolCallInputDeltaEvent" +}) +export type BetaResponseCustomToolCallInputDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.custom_tool_call_input.done" + readonly "sequence_number": number + readonly "output_index": number + readonly "item_id": string + readonly "input": string +} +export const BetaResponseCustomToolCallInputDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.custom_tool_call_input.done").annotate({ + "description": "The event type identifier." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "output_index": Schema.Number.annotate({ "description": "The index of the output this event applies to." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item_id": Schema.String.annotate({ + "description": "Unique identifier for the API item associated with this event." + }), + "input": Schema.String.annotate({ "description": "The complete input data for the custom tool call." }) +}).annotate({ + "title": "ResponseCustomToolCallInputDone", + "description": "Event indicating that input for a custom tool call is complete.\n", + "identifier": "BetaResponseCustomToolCallInputDoneEvent" +}) +export type BetaResponseConfigurationUpdate = { + readonly "agent"?: BetaAgentTag + readonly "id": string + readonly "type": "configuration_update" + readonly "reasoning"?: { readonly "effort"?: BetaReasoningEffort } +} +export const BetaResponseConfigurationUpdate = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "id": Schema.String.annotate({ "description": "The unique ID of the configuration update item." }), + "type": Schema.Literal("configuration_update").annotate({ + "description": "The item type. Always `configuration_update`." + }), + "reasoning": Schema.optionalKey( + Schema.Struct({ + "effort": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaReasoningEffort).annotate({ + "description": + "The reasoning effort used for subsequent responses until another\nconfiguration update replaces it.\n" + }) + ) + }).annotate({ "description": "The reasoning configuration applied by this update." }) + ) +}).annotate({ + "description": + "A configuration update that applies to subsequent responses until it is\nreplaced by another configuration update.\n", + "identifier": "BetaResponseConfigurationUpdate" +}) +export type BetaAnnotation = BetaFileCitationBody | BetaUrlCitationBody | BetaContainerFileCitationBody | BetaFilePath +export const BetaAnnotation = Schema.Union([ + BetaFileCitationBody, + BetaUrlCitationBody, + BetaContainerFileCitationBody, + BetaFilePath +], { mode: "oneOf" }).annotate({ + "description": "An annotation that applies to a span of output text.", + "identifier": "BetaAnnotation" +}) +export type BetaLogProb = { + readonly "token": string + readonly "logprob": number + readonly "bytes": ReadonlyArray + readonly "top_logprobs": ReadonlyArray +} +export const BetaLogProb = Schema.Struct({ + "token": Schema.String, + "logprob": Schema.Finite, + "bytes": Schema.Array(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), + "top_logprobs": Schema.Array(BetaTopLogProb) +}).annotate({ + "title": "Log probability", + "description": "The log probability of a token.", + "identifier": "BetaLogProb" +}) +export type BetaFileSearchToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "id": string + readonly "type": "file_search_call" + readonly "status": "in_progress" | "searching" | "completed" | "incomplete" | "failed" + readonly "queries": ReadonlyArray + readonly "results"?: + | ReadonlyArray< + { + readonly "file_id"?: string + readonly "text"?: string + readonly "filename"?: string + readonly "attributes"?: BetaVectorStoreFileAttributes + readonly "score"?: number + } + > + | null +} +export const BetaFileSearchToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "id": Schema.String.annotate({ "description": "The unique ID of the file search tool call.\n" }), + "type": Schema.Literal("file_search_call").annotate({ + "description": "The type of the file search tool call. Always `file_search_call`.\n" + }), + "status": Schema.Literals(["in_progress", "searching", "completed", "incomplete", "failed"]).annotate({ + "description": + "The status of the file search tool call. One of `in_progress`,\n`searching`, `incomplete` or `failed`,\n" + }), + "queries": Schema.Array(Schema.String).annotate({ "description": "The queries used to search for files.\n" }), + "results": Schema.optionalKey(Schema.Union([ + Schema.Array(Schema.Struct({ + "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the file.\n" })), + "text": Schema.optionalKey( + Schema.String.annotate({ "description": "The text that was retrieved from the file.\n" }) + ), + "filename": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the file.\n" })), + "attributes": Schema.optionalKey(BetaVectorStoreFileAttributes), + "score": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The relevance score of the file - a value between 0 and 1.\n", + "format": "float" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ) + })).annotate({ "description": "The results of the file search tool call.\n" }), + Schema.Null + ])) +}).annotate({ + "title": "File search tool call", + "description": + "The results of a file search tool call. See the\n[file search guide](https://developers.openai.com/api/docs/guides/tools-file-search) for more information.\n", + "identifier": "BetaFileSearchToolCall" +}) +export type BetaClickParam = { + readonly "type": "click" + readonly "button": BetaClickButtonType + readonly "x": number + readonly "y": number + readonly "keys"?: ReadonlyArray | null +} +export const BetaClickParam = Schema.Struct({ + "type": Schema.Literal("click").annotate({ + "description": "Specifies the event type. For a click action, this property is always `click`." + }), + "button": Schema.suspend((): Schema.Codec => BetaClickButtonType).annotate({ + "description": + "Indicates which mouse button was pressed during the click. One of `left`, `right`, `wheel`, `back`, or `forward`." + }), + "x": Schema.Number.annotate({ "description": "The x-coordinate where the click occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "y": Schema.Number.annotate({ "description": "The y-coordinate where the click occurred." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "keys": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.String).annotate({ "description": "The keys being held while clicking." }), + Schema.Null + ]) + ) +}).annotate({ "title": "Click", "description": "A click action.", "identifier": "BetaClickParam" }) +export type BetaDragParam = { + readonly "type": "drag" + readonly "path": ReadonlyArray + readonly "keys"?: ReadonlyArray | null +} +export const BetaDragParam = Schema.Struct({ + "type": Schema.Literal("drag").annotate({ + "description": "Specifies the event type. For a drag action, this property is always set to `drag`." + }), + "path": Schema.Array(BetaCoordParam).annotate({ + "description": + "An array of coordinates representing the path of the drag action. Coordinates will appear as an array of objects, eg\n```\n[\n { x: 100, y: 200 },\n { x: 200, y: 300 }\n]\n```" + }), + "keys": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.String).annotate({ "description": "The keys being held while dragging the mouse." }), + Schema.Null + ]) + ) +}).annotate({ "title": "Drag", "description": "A drag action.", "identifier": "BetaDragParam" }) +export type BetaCompactionTriggerItemParam = { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id"?: string | null + readonly "type": "compaction_trigger" +} +export const BetaCompactionTriggerItemParam = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "id": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The unique ID of this compaction trigger." }), Schema.Null]) + ), + "type": Schema.Literal("compaction_trigger").annotate({ + "description": "The type of the item. Always `compaction_trigger`." + }) +}).annotate({ + "title": "Compaction trigger", + "description": "Compacts the current context. Must be the final input item.", + "identifier": "BetaCompactionTriggerItemParam" +}) +export type BetaItemReferenceParam = { + readonly "agent"?: Beta_AgentTagParam | null + readonly "type"?: "item_reference" | null + readonly "id": string +} +export const BetaItemReferenceParam = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "type": Schema.optionalKey( + Schema.Union([ + Schema.Literal("item_reference").annotate({ + "description": "The type of item to reference. Always `item_reference`." + }), + Schema.Null + ]) + ), + "id": Schema.String.annotate({ "description": "The ID of the item to reference." }) +}).annotate({ + "title": "Item reference", + "description": "An internal identifier for an item to reference.", + "identifier": "BetaItemReferenceParam" +}) +export type BetaProgramItemParam = { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id": string + readonly "type": "program" + readonly "call_id": string + readonly "code": string + readonly "fingerprint": string +} +export const BetaProgramItemParam = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "id": Schema.String.annotate({ "description": "The unique ID of this program item." }), + "type": Schema.Literal("program").annotate({ "description": "The item type. Always `program`." }), + "call_id": Schema.String.annotate({ "description": "The stable call ID of the program item." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "code": Schema.String.annotate({ "description": "The JavaScript source executed by programmatic tool calling." }) + .check(Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" })), + "fingerprint": Schema.String.annotate({ + "description": "Opaque program replay fingerprint that must be round-tripped." + }).check(Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" })) +}).annotate({ "identifier": "BetaProgramItemParam" }) +export type BetaComputerToolCallOutputResource = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "computer_call_output" + readonly "id": string + readonly "call_id": string + readonly "acknowledged_safety_checks"?: ReadonlyArray + readonly "output": BetaComputerScreenshotImage + readonly "status": "completed" | "incomplete" + readonly "created_by"?: string +} +export const BetaComputerToolCallOutputResource = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("computer_call_output").annotate({ + "description": "The type of the computer tool call output. Always `computer_call_output`.\n" + }), + "id": Schema.String.annotate({ "description": "The ID of the computer tool call output.\n" }), + "call_id": Schema.String.annotate({ "description": "The ID of the computer tool call that produced the output.\n" }), + "acknowledged_safety_checks": Schema.optionalKey( + Schema.Array(BetaComputerCallSafetyCheckParam).annotate({ + "description": "The safety checks reported by the API that have been acknowledged by the\ndeveloper.\n" + }) + ), + "output": BetaComputerScreenshotImage, + "status": Schema.Literals(["completed", "incomplete"]).annotate({ + "description": + "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "identifier": "BetaComputerToolCallOutputResource" }) +export type BetaWebSearchToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "id": string + readonly "type": "web_search_call" + readonly "status": BetaWebSearchCallStatus + readonly "action"?: BetaWebSearchActionSearch | BetaWebSearchActionOpenPage | BetaWebSearchActionFind +} +export const BetaWebSearchToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "id": Schema.String.annotate({ "description": "The unique ID of the web search tool call.\n" }), + "type": Schema.Literal("web_search_call").annotate({ + "description": "The type of the web search tool call. Always `web_search_call`.\n" + }), + "status": Schema.suspend((): Schema.Codec => BetaWebSearchCallStatus).annotate({ + "description": "The status of the web search tool call.\n" + }), + "action": Schema.optionalKey( + Schema.Union([BetaWebSearchActionSearch, BetaWebSearchActionOpenPage, BetaWebSearchActionFind], { mode: "oneOf" }) + .annotate({ + "description": + "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" + }) + ) +}).annotate({ + "title": "Web search tool call", + "description": + "The results of a web search tool call. See the\n[web search guide](https://developers.openai.com/api/docs/guides/tools-web-search) for more information.\n", + "identifier": "BetaWebSearchToolCall" +}) +export type BetaToolCallCaller = BetaDirectToolCallCaller | BetaProgramToolCallCaller +export const BetaToolCallCaller = Schema.Union([BetaDirectToolCallCaller, BetaProgramToolCallCaller], { mode: "oneOf" }) + .annotate({ + "description": "The execution context that produced this tool call.", + "identifier": "BetaToolCallCaller" + }) +export type BetaInputTextContentParam = { + readonly "type": "input_text" + readonly "text": string + readonly "prompt_cache_breakpoint"?: BetaPromptCacheBreakpointParam | null +} +export const BetaInputTextContentParam = Schema.Struct({ + "type": Schema.Literal("input_text").annotate({ "description": "The type of the input item. Always `input_text`." }), + "text": Schema.String.annotate({ "description": "The text input to the model." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "prompt_cache_breakpoint": Schema.optionalKey(Schema.Union([BetaPromptCacheBreakpointParam, Schema.Null])) +}).annotate({ + "title": "Input text", + "description": "A text input to the model.", + "identifier": "BetaInputTextContentParam" +}) +export type BetaInputImageContentParamAutoParam = { + readonly "type": "input_image" + readonly "image_url"?: string | null + readonly "file_id"?: string | null + readonly "detail"?: BetaDetailEnum | null + readonly "prompt_cache_breakpoint"?: BetaPromptCacheBreakpointParam | null +} +export const BetaInputImageContentParamAutoParam = Schema.Struct({ + "type": Schema.Literal("input_image").annotate({ + "description": "The type of the input item. Always `input_image`." + }), + "image_url": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The URL of the image to be sent to the model. A fully qualified URL or base64 encoded image in a data URL.", + "format": "uri" + }).check(Schema.isMaxCodePoints(20971520).annotate({ "expected": "a string with at most 20971520 code points" })), + Schema.Null + ]) + ), + "file_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), + Schema.Null + ]) + ), + "detail": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaDetailEnum).annotate({ + "description": + "The detail level of the image to be sent to the model. One of `high`, `low`, `auto`, or `original`. Defaults to `auto`." + }), + Schema.Null + ]) + ), + "prompt_cache_breakpoint": Schema.optionalKey(Schema.Union([BetaPromptCacheBreakpointParam, Schema.Null])) +}).annotate({ + "title": "Input image", + "description": + "An image input to the model. Learn about [image inputs](https://developers.openai.com/api/docs/guides/images-vision)", + "identifier": "BetaInputImageContentParamAutoParam" +}) +export type BetaInputFileContentParam = { + readonly "type": "input_file" + readonly "file_id"?: string | null + readonly "filename"?: string | null + readonly "file_data"?: string | null + readonly "file_url"?: string | null + readonly "detail"?: BetaFileDetailEnum + readonly "prompt_cache_breakpoint"?: BetaPromptCacheBreakpointParam | null +} +export const BetaInputFileContentParam = Schema.Struct({ + "type": Schema.Literal("input_file").annotate({ "description": "The type of the input item. Always `input_file`." }), + "file_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the file to be sent to the model." }), + Schema.Null + ]) + ), + "filename": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The name of the file to be sent to the model." }), + Schema.Null + ]) + ), + "file_data": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The base64-encoded data of the file to be sent to the model." }).check( + Schema.isMaxCodePoints(73400320).annotate({ "expected": "a string with at most 73400320 code points" }) + ), + Schema.Null + ]) + ), + "file_url": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The URL of the file to be sent to the model.", "format": "uri" }), + Schema.Null + ]) + ), + "detail": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaFileDetailEnum).annotate({ + "description": + "The detail level of the file to be sent to the model. Use `auto` to let the system select the detail level; for GPT-5.6 and later models, `auto` uses high-quality rendering, which may increase input token usage. Use `low` for lower-cost rendering, or `high` to render the file at higher quality. Defaults to `auto`." + }) + ), + "prompt_cache_breakpoint": Schema.optionalKey(Schema.Union([BetaPromptCacheBreakpointParam, Schema.Null])) +}).annotate({ + "title": "Input file", + "description": "A file input to the model.", + "identifier": "BetaInputFileContentParam" +}) +export type BetaToolCallCallerParam = BetaDirectToolCallCallerParam | BetaProgramToolCallCallerParam +export const BetaToolCallCallerParam = Schema.Union([BetaDirectToolCallCallerParam, BetaProgramToolCallCallerParam], { + mode: "oneOf" +}).annotate({ + "description": "The execution context that produced this tool call.", + "identifier": "BetaToolCallCallerParam" +}) +export type BetaOutputTextContentParam = { + readonly "type": "output_text" + readonly "text": string + readonly "annotations"?: ReadonlyArray +} +export const BetaOutputTextContentParam = Schema.Struct({ + "type": Schema.Literal("output_text").annotate({ "description": "The content type. Always `output_text`." }), + "text": Schema.String.annotate({ "description": "The text content." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "annotations": Schema.optionalKey( + Schema.Array( + Schema.Union([BetaFileCitationParam, BetaUrlCitationParam, BetaContainerFileCitationParam], { mode: "oneOf" }) + ).annotate({ "description": "Citations associated with the text content." }) + ) +}).annotate({ "identifier": "BetaOutputTextContentParam" }) +export type BetaReasoningItem = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "reasoning" + readonly "id": string + readonly "encrypted_content"?: string | null + readonly "summary": ReadonlyArray + readonly "content"?: ReadonlyArray + readonly "status"?: "in_progress" | "completed" | "incomplete" +} +export const BetaReasoningItem = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("reasoning").annotate({ "description": "The type of the object. Always `reasoning`.\n" }), + "id": Schema.String.annotate({ "description": "The unique identifier of the reasoning content.\n" }), + "encrypted_content": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "The encrypted content of the reasoning item. This is populated by default\nfor reasoning items returned by `POST /v1/responses` and WebSocket\n`response.create` requests.\n\nWhen streaming, use the completed reasoning item and its\n`encrypted_content` from the `response.output_item.done` event in\nsubsequent requests. The `encrypted_content` in\n`response.output_item.added` may be incomplete. This is especially\nimportant when `store` is `false` or when using Zero Data Retention.\n" + }), + Schema.Null + ])), + "summary": Schema.Array(BetaSummaryTextContent).annotate({ "description": "Reasoning summary content.\n" }), + "content": Schema.optionalKey( + Schema.Array(BetaReasoningTextContent).annotate({ "description": "Reasoning text content.\n" }) + ), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ) +}).annotate({ + "title": "Reasoning", + "description": + "A description of the chain of thought used by a reasoning model while generating\na response. Be sure to include these items in your `input` to the Responses API\nfor subsequent turns of a conversation if you are manually\n[managing context](https://developers.openai.com/api/docs/guides/conversation-state).\n", + "identifier": "BetaReasoningItem" +}) +export type BetaImageGenToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "image_generation_call" + readonly "id": string + readonly "status": "in_progress" | "completed" | "generating" | "failed" + readonly "result": string | null + readonly "size"?: string | "1024x1024" | "1024x1536" | "1536x1024" | null + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" | null + readonly "action"?: BetaImageGenActionEnum | null + readonly "background"?: BetaImageBackground | null + readonly "output_format"?: BetaImageOutputFormat | null + readonly "revised_prompt"?: string | null +} +export const BetaImageGenToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "type": Schema.Literal("image_generation_call").annotate({ + "description": "The type of the image generation call. Always `image_generation_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the image generation call." }), + "status": Schema.Literals(["in_progress", "completed", "generating", "failed"]).annotate({ + "description": "The status of the image generation call." + }), + "result": Schema.Union([ + Schema.String.annotate({ "description": "The generated image encoded in base64." }), + Schema.Null + ]), + "size": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." + }), + Schema.Null + ]) + ), + "quality": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": + "The quality of the image generated by the image generation tool call. One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`." + }), + Schema.Null + ]) + ), + "action": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaImageGenActionEnum).annotate({ + "description": "The action used for image generation." + }), + Schema.Null + ]) + ), + "background": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaImageBackground).annotate({ + "description": "The background setting used for generation." + }), + Schema.Null + ]) + ), + "output_format": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaImageOutputFormat).annotate({ + "description": "The output format used for generation." + }), + Schema.Null + ]) + ), + "revised_prompt": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The prompt that was used after any model prompt rewriting." }), + Schema.Null + ]) + ) +}).annotate({ + "title": "Image generation call", + "description": "An image generation request made by the model.", + "identifier": "BetaImageGenToolCall" +}) +export type BetaCodeInterpreterToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "code_interpreter_call" + readonly "id": string + readonly "status": "in_progress" | "completed" | "incomplete" | "interpreting" | "failed" + readonly "container_id": string + readonly "code": string | null + readonly "outputs": ReadonlyArray | null +} +export const BetaCodeInterpreterToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("code_interpreter_call").annotate({ + "description": "The type of the code interpreter tool call. Always `code_interpreter_call`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the code interpreter tool call.\n" }), + "status": Schema.Literals(["in_progress", "completed", "incomplete", "interpreting", "failed"]).annotate({ + "description": + "The status of the code interpreter tool call. Valid values are `in_progress`, `completed`, `incomplete`, `interpreting`, and `failed`.\n" + }), + "container_id": Schema.String.annotate({ "description": "The ID of the container used to run the code.\n" }), + "code": Schema.Union([ + Schema.String.annotate({ "description": "The code to run, or null if not available.\n" }), + Schema.Null + ]), + "outputs": Schema.Union([ + Schema.Array(Schema.Union([BetaCodeInterpreterOutputLogs, BetaCodeInterpreterOutputImage], { mode: "oneOf" })) + .annotate({ + "description": + "The outputs generated by the code interpreter, such as logs or images.\nCan be null if no outputs are available.\n" + }), + Schema.Null + ]) +}).annotate({ + "title": "Code interpreter tool call", + "description": "A tool call to run code.\n", + "identifier": "BetaCodeInterpreterToolCall" +}) +export type BetaLocalShellToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "local_shell_call" + readonly "id": string + readonly "call_id": string + readonly "action": BetaLocalShellExecAction + readonly "status": "in_progress" | "completed" | "incomplete" +} +export const BetaLocalShellToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("local_shell_call").annotate({ + "description": "The type of the local shell call. Always `local_shell_call`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the local shell call.\n" }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the local shell tool call generated by the model.\n" + }), + "action": BetaLocalShellExecAction, + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": "The status of the local shell call.\n" + }) +}).annotate({ + "title": "Local shell call", + "description": "A tool call to run a command on the local shell.\n", + "identifier": "BetaLocalShellToolCall" +}) +export type BetaFunctionShellCallOutputOutcomeParam = + | BetaFunctionShellCallOutputTimeoutOutcomeParam + | BetaFunctionShellCallOutputExitOutcomeParam +export const BetaFunctionShellCallOutputOutcomeParam = Schema.Union([ + BetaFunctionShellCallOutputTimeoutOutcomeParam, + BetaFunctionShellCallOutputExitOutcomeParam +], { mode: "oneOf" }).annotate({ + "title": "Shell call outcome", + "description": "The exit or timeout outcome associated with this shell call.", + "identifier": "BetaFunctionShellCallOutputOutcomeParam" +}) +export type BetaApplyPatchOperationParam = + | BetaApplyPatchCreateFileOperationParam + | BetaApplyPatchDeleteFileOperationParam + | BetaApplyPatchUpdateFileOperationParam +export const BetaApplyPatchOperationParam = Schema.Union([ + BetaApplyPatchCreateFileOperationParam, + BetaApplyPatchDeleteFileOperationParam, + BetaApplyPatchUpdateFileOperationParam +], { mode: "oneOf" }).annotate({ + "title": "Apply patch operation", + "description": "One of the create_file, delete_file, or update_file operations supplied to the apply_patch tool.", + "identifier": "BetaApplyPatchOperationParam" +}) +export type BetaMCPListTools = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "mcp_list_tools" + readonly "id": string + readonly "server_label": string + readonly "tools": ReadonlyArray + readonly "error"?: string | null +} +export const BetaMCPListTools = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("mcp_list_tools").annotate({ + "description": "The type of the item. Always `mcp_list_tools`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the list.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server.\n" }), + "tools": Schema.Array(BetaMCPListToolsTool).annotate({ "description": "The tools available on the server.\n" }), + "error": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Error message if the server could not list tools.\n" }), + Schema.Null + ]) + ) +}).annotate({ + "title": "MCP list tools", + "description": "A list of tools available on an MCP server.\n", + "identifier": "BetaMCPListTools" +}) +export type BetaMCPToolCallError = BetaMCPProtocolError | BetaMCPToolExecutionError | BetaHTTPError +export const BetaMCPToolCallError = Schema.Union([BetaMCPProtocolError, BetaMCPToolExecutionError, BetaHTTPError], { + mode: "oneOf" +}).annotate({ "identifier": "BetaMCPToolCallError" }) +export type BetaProgramOutputItemParam = { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id": string + readonly "type": "program_output" + readonly "call_id": string + readonly "result": string + readonly "status": BetaProgramOutputItemStatus +} +export const BetaProgramOutputItemParam = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "id": Schema.String.annotate({ "description": "The unique ID of this program output item." }), + "type": Schema.Literal("program_output").annotate({ "description": "The item type. Always `program_output`." }), + "call_id": Schema.String.annotate({ "description": "The call ID of the program item." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "result": Schema.String.annotate({ "description": "The result produced by the program item." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => BetaProgramOutputItemStatus).annotate({ + "description": "The terminal status of the program output." + }) +}).annotate({ "identifier": "BetaProgramOutputItemParam" }) +export type BetaModerationConfigParam = { readonly "mode": BetaModerationMode } +export const BetaModerationConfigParam = Schema.Struct({ "mode": BetaModerationMode }).annotate({ + "description": "The moderation policy for the response input.", + "identifier": "BetaModerationConfigParam" +}) +export type BetaConversationParam = string | BetaConversationParam_2 +export const BetaConversationParam = Schema.Union([ + Schema.String.annotate({ "title": "Conversation ID", "description": "The unique ID of the conversation.\n" }), + BetaConversationParam_2 +], { mode: "oneOf" }).annotate({ + "description": + "The conversation that this response belongs to. Items from this conversation are prepended to `input_items` for this response request.\nInput items and output items from this response are automatically added to this conversation after this response completes.\n", + "identifier": "BetaConversationParam" +}) +export type BetaMisalignmentErrorDetailsResource = { + readonly "review_target"?: string | null + readonly "error_type"?: Beta_MisalignmentErrorType + readonly "detailed_explanation"?: string + readonly "steer"?: Beta_MisalignmentSteer +} +export const BetaMisalignmentErrorDetailsResource = Schema.Struct({ + "review_target": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "An opaque target for explicitly continuing this review, or null when unavailable." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(96).annotate({ "expected": "a string with at most 96 code points" }) + ).check( + Schema.isPattern(new RegExp("^[A-Za-z0-9._~:-]+$", "u")).annotate({ + "expected": "a string matching the RegExp ^[A-Za-z0-9._~:-]+$" + }) + ), + Schema.Null + ]) + ), + "error_type": Schema.optionalKey( + Schema.suspend((): Schema.Codec => Beta_MisalignmentErrorType).annotate({ + "description": "An optional classification; clients must accept additional values." + }) + ), + "detailed_explanation": Schema.optionalKey( + Schema.String.annotate({ "description": "The public explanation for this block." }) + ), + "steer": Schema.optionalKey( + Schema.suspend((): Schema.Codec => Beta_MisalignmentSteer).annotate({ + "description": "An optional public continuation instruction." + }) + ) +}).annotate({ "identifier": "BetaMisalignmentErrorDetailsResource" }) +export type BetaMultiAgentCall = { + readonly "agent"?: BetaAgentTag + readonly "type": "multi_agent_call" + readonly "id": string + readonly "call_id": string + readonly "action": BetaMultiAgentAction + readonly "arguments": string +} +export const BetaMultiAgentCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("multi_agent_call").annotate({ + "description": "The type of the multi-agent call. Always `multi_agent_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the multi-agent call item." }), + "call_id": Schema.String.annotate({ "description": "The unique ID linking this call to its output." }), + "action": Schema.suspend((): Schema.Codec => BetaMultiAgentAction).annotate({ + "description": "The multi-agent action to execute." + }), + "arguments": Schema.String.annotate({ "description": "The JSON string of arguments generated for the action." }) +}).annotate({ "identifier": "BetaMultiAgentCall" }) +export type BetaProgramOutput = { + readonly "agent"?: BetaAgentTag + readonly "type": "program_output" + readonly "id": string + readonly "call_id": string + readonly "result": string + readonly "status": BetaProgramOutputStatus +} +export const BetaProgramOutput = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("program_output").annotate({ + "description": "The type of the item. Always `program_output`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the program output item." }), + "call_id": Schema.String.annotate({ "description": "The call ID of the program item." }), + "result": Schema.String.annotate({ "description": "The result produced by the program item." }), + "status": Schema.suspend((): Schema.Codec => BetaProgramOutputStatus).annotate({ + "description": "The terminal status of the program output item." + }) +}).annotate({ "identifier": "BetaProgramOutput" }) +export type BetaToolSearchCall = { + readonly "agent"?: BetaAgentTag + readonly "type": "tool_search_call" + readonly "id": string + readonly "call_id": string | null + readonly "execution": BetaToolSearchExecutionType + readonly "arguments": Schema.Json + readonly "status": BetaFunctionCallStatus + readonly "created_by"?: string +} +export const BetaToolSearchCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("tool_search_call").annotate({ + "description": "The type of the item. Always `tool_search_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the tool search call item." }), + "call_id": Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }), + Schema.Null + ]), + "execution": Schema.suspend((): Schema.Codec => BetaToolSearchExecutionType).annotate({ + "description": "Whether tool search was executed by the server or by the client." + }), + "arguments": Schema.Json.annotate({ + "expected": "JSON value", + "description": "Arguments used for the tool search call." + }), + "status": Schema.suspend((): Schema.Codec => BetaFunctionCallStatus).annotate({ + "description": "The status of the tool search call item that was recorded." + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ "identifier": "BetaToolSearchCall" }) +export type BetaFunctionShellCallOutputContent = { + readonly "stdout": string + readonly "stderr": string + readonly "outcome": BetaFunctionShellCallOutputTimeoutOutcome | BetaFunctionShellCallOutputExitOutcome + readonly "created_by"?: string +} +export const BetaFunctionShellCallOutputContent = Schema.Struct({ + "stdout": Schema.String.annotate({ "description": "The standard output that was captured." }), + "stderr": Schema.String.annotate({ "description": "The standard error output that was captured." }), + "outcome": Schema.Union([BetaFunctionShellCallOutputTimeoutOutcome, BetaFunctionShellCallOutputExitOutcome], { + mode: "oneOf" + }).annotate({ + "title": "Shell call outcome", + "description": + "Represents either an exit outcome (with an exit code) or a timeout outcome for a shell call output chunk." + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ + "title": "Shell call output content", + "description": "The content of a shell tool call output that was emitted.", + "identifier": "BetaFunctionShellCallOutputContent" +}) +export type BetaPromptCacheMissDiagnosticsBody = { + readonly "type": "cache_miss" + readonly "reason": BetaCacheMissReasonTypeEnum + readonly "cache_missed_tokens": number + readonly "comparison_reusable_tokens"?: number +} +export const BetaPromptCacheMissDiagnosticsBody = Schema.Struct({ + "type": Schema.Literal("cache_miss"), + "reason": Schema.suspend((): Schema.Codec => BetaCacheMissReasonTypeEnum).annotate({ + "description": "The reason prompt cache reuse did not occur." + }), + "cache_missed_tokens": Schema.Number.annotate({ + "description": "The estimated number of input tokens affected after the first detected divergence." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "comparison_reusable_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The raw token count of the reusable prefix in the compared response." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })) + ) +}).annotate({ "identifier": "BetaPromptCacheMissDiagnosticsBody" }) +export type BetaModerationResultBody = { + readonly "type": "moderation_result" + readonly "model": string + readonly "flagged": boolean + readonly "categories": { readonly [x: string]: boolean } + readonly "category_scores": { readonly [x: string]: number } + readonly "category_applied_input_types": { readonly [x: string]: ReadonlyArray } +} +export const BetaModerationResultBody = Schema.Struct({ + "type": Schema.Literal("moderation_result").annotate({ + "description": "The object type, which was always `moderation_result` for successful moderation results." + }), + "model": Schema.String.annotate({ "description": "The moderation model that produced this result." }), + "flagged": Schema.Boolean.annotate({ + "description": "A boolean indicating whether the content was flagged by any category." + }), + "categories": Schema.Record(Schema.String, Schema.Boolean).annotate({ + "description": + "A dictionary of moderation categories to booleans, True if the input is flagged under this category." + }), + "category_scores": Schema.Record(Schema.String, Schema.Finite).annotate({ + "description": "A dictionary of moderation categories to scores." + }), + "category_applied_input_types": Schema.Record(Schema.String, Schema.Array(BetaModerationInputType)).annotate({ + "description": "Which modalities of input are reflected by the score for each category." + }) +}).annotate({ + "title": "Moderation result", + "description": "A moderation result produced for the response input or output.", + "identifier": "BetaModerationResultBody" +}) +export type BetaResponseShellCallOutputContentDeltaStreamingEvent = { + readonly "type": "response.shell_call_output_content.delta" + readonly "sequence_number": number + readonly "agent"?: BetaAgentTag + readonly "item_id": string + readonly "output_index": number + readonly "command_index": number + readonly "delta": BetaShellCallOutputDelta +} +export const BetaResponseShellCallOutputContentDeltaStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_output_content.delta").annotate({ + "description": "The type of the event, always `response.shell_call_output_content.delta`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "item_id": Schema.String.annotate({ "description": "The ID of the output item that was updated." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that produced output." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.suspend((): Schema.Codec => BetaShellCallOutputDelta).annotate({ + "description": "The stdout/stderr delta that was emitted." + }) +}).annotate({ + "title": "Response shell call output content delta event", + "description": "A streaming event that indicated shell call output was incrementally added.", + "identifier": "BetaResponseShellCallOutputContentDeltaStreamingEvent" +}) +export type BetaResponseTextDeltaEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.output_text.delta" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "delta": string + readonly "sequence_number": number + readonly "logprobs": ReadonlyArray +} +export const BetaResponseTextDeltaEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.output_text.delta").annotate({ + "description": "The type of the event. Always `response.output_text.delta`.\n" + }), + "item_id": Schema.String.annotate({ "description": "The ID of the output item that the text delta was added to.\n" }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the text delta was added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part that the text delta was added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "delta": Schema.String.annotate({ "description": "The text delta that was added.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "logprobs": Schema.Array(BetaResponseLogProb).annotate({ + "description": "The log probabilities of the tokens in the delta.\n" + }) +}).annotate({ + "description": "Emitted when there is an additional text delta.", + "identifier": "BetaResponseTextDeltaEvent" +}) +export type BetaResponseTextDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.output_text.done" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "text": string + readonly "sequence_number": number + readonly "logprobs": ReadonlyArray +} +export const BetaResponseTextDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.output_text.done").annotate({ + "description": "The type of the event. Always `response.output_text.done`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the text content is finalized.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the text content is finalized.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ + "description": "The index of the content part that the text content is finalized.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "text": Schema.String.annotate({ "description": "The text content that is finalized.\n" }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "logprobs": Schema.Array(BetaResponseLogProb).annotate({ + "description": "The log probabilities of the tokens in the delta.\n" + }) +}).annotate({ "description": "Emitted when text content is finalized.", "identifier": "BetaResponseTextDoneEvent" }) +export type AssistantToolsFileSearch = { + readonly "type": "file_search" + readonly "file_search"?: { + readonly "max_num_results"?: number + readonly "ranking_options"?: FileSearchRankingOptions + } +} +export const AssistantToolsFileSearch = Schema.Struct({ + "type": Schema.Literal("file_search").annotate({ "description": "The type of tool being defined: `file_search`" }), + "file_search": Schema.optionalKey( + Schema.Struct({ + "max_num_results": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The maximum number of results the file search tool should output. The default is 20 for `gpt-4*` models and 5 for `gpt-3.5-turbo`. This number should be between 1 and 50 inclusive.\n\nNote that the file search tool may output fewer than `max_num_results` results. See the [file search tool documentation](https://developers.openai.com/api/docs/guides/tools-file-search#retrieval-customization) for more information.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(50).annotate({ "expected": "a value less than or equal to 50" })) + ), + "ranking_options": Schema.optionalKey(FileSearchRankingOptions) + }).annotate({ "description": "Overrides for the file search tool." }) + ) +}).annotate({ "title": "FileSearch tool", "identifier": "AssistantToolsFileSearch" }) +export type RunStepDetailsToolCallsFileSearchObject = { + readonly "id": string + readonly "type": "file_search" + readonly "file_search": { + readonly "ranking_options"?: RunStepDetailsToolCallsFileSearchRankingOptionsObject + readonly "results"?: ReadonlyArray + } +} +export const RunStepDetailsToolCallsFileSearchObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the tool call object." }), + "type": Schema.Literal("file_search").annotate({ + "description": "The type of tool call. This is always going to be `file_search` for this type of tool call." + }), + "file_search": Schema.Struct({ + "ranking_options": Schema.optionalKey(RunStepDetailsToolCallsFileSearchRankingOptionsObject), + "results": Schema.optionalKey( + Schema.Array(RunStepDetailsToolCallsFileSearchResultObject).annotate({ + "description": "The results of the file search." + }) + ) + }).annotate({ "description": "For now, this is always going to be an empty object." }) +}).annotate({ "title": "File search tool call", "identifier": "RunStepDetailsToolCallsFileSearchObject" }) +export type AssistantToolsFunction = { readonly "type": "function"; readonly "function": FunctionObject } +export const AssistantToolsFunction = Schema.Struct({ + "type": Schema.Literal("function").annotate({ "description": "The type of tool being defined: `function`" }), + "function": FunctionObject +}).annotate({ "title": "Function tool", "identifier": "AssistantToolsFunction" }) +export type ChatCompletionTool = { readonly "type": "function"; readonly "function": FunctionObject } +export const ChatCompletionTool = Schema.Struct({ + "type": Schema.Literal("function").annotate({ + "description": "The type of the tool. Currently, only `function` is supported." + }), + "function": FunctionObject +}).annotate({ + "title": "Function tool", + "description": "A function tool that can be used to generate a response.\n", + "identifier": "ChatCompletionTool" +}) +export type ThreadStreamEvent = { + readonly "enabled"?: boolean + readonly "event": "thread.created" + readonly "data": ThreadObject +} +export const ThreadStreamEvent = Schema.Union([ + Schema.Struct({ + "enabled": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether to enable input audio transcription." }) + ), + "event": Schema.Literal("thread.created"), + "data": ThreadObject + }).annotate({ + "description": "Occurs when a new [thread](https://developers.openai.com/api/docs/assistants/migration) is created." + }) +], { mode: "oneOf" }).annotate({ "identifier": "ThreadStreamEvent" }) +export type AssistantsApiResponseFormatOption = + | "auto" + | ResponseFormatText + | ResponseFormatJsonObject + | ResponseFormatJsonSchema +export const AssistantsApiResponseFormatOption = Schema.Union([ + Schema.Literal("auto").annotate({ "description": "`auto` is the default value\n" }), + ResponseFormatText, + ResponseFormatJsonObject, + ResponseFormatJsonSchema +], { mode: "oneOf" }).annotate({ + "description": + "Specifies the format that the model must output. Compatible with [GPT-4o](https://developers.openai.com/api/docs/models/gpt-4o), [GPT-4 Turbo](https://developers.openai.com/api/docs/models/gpt-4-turbo), and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`.\n\nSetting to `{ \"type\": \"json_schema\", \"json_schema\": {...} }` enables Structured Outputs which ensures the model will match your supplied JSON schema. Learn more in the [Structured Outputs guide](https://developers.openai.com/api/docs/guides/structured-outputs).\n\nSetting to `{ \"type\": \"json_object\" }` enables JSON mode, which ensures the message the model generates is valid JSON.\n\n**Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly \"stuck\" request. Also note that the message content may be partially cut off if `finish_reason=\"length\"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length.\n", + "identifier": "AssistantsApiResponseFormatOption" +}) +export type TextResponseFormatConfiguration = + | ResponseFormatText + | TextResponseFormatJsonSchema + | ResponseFormatJsonObject +export const TextResponseFormatConfiguration = Schema.Union([ + ResponseFormatText, + TextResponseFormatJsonSchema, + ResponseFormatJsonObject +], { mode: "oneOf" }).annotate({ + "description": + "An object specifying the format that the model must output.\n\nConfiguring `{ \"type\": \"json_schema\" }` enables Structured Outputs,\nwhich ensures the model will match your supplied JSON schema. Learn more in the\n[Structured Outputs guide](https://developers.openai.com/api/docs/guides/structured-outputs).\n\nThe default format is `{ \"type\": \"text\" }` with no additional options.\n\n**Not recommended for gpt-4o and newer models:**\n\nSetting to `{ \"type\": \"json_object\" }` enables the older JSON mode, which\nensures the message the model generates is valid JSON. Using `json_schema`\nis preferred for models that support it.\n", + "identifier": "TextResponseFormatConfiguration" +}) +export type Error = { + readonly "code": string | null + readonly "message": string + readonly "param": string | null + readonly "type": string + readonly "misalignment"?: MisalignmentErrorDetailsResource +} +export const Error = Schema.Struct({ + "code": Schema.Union([Schema.String, Schema.Null]), + "message": Schema.String, + "param": Schema.Union([Schema.String, Schema.Null]), + "type": Schema.String, + "misalignment": Schema.optionalKey(MisalignmentErrorDetailsResource) +}).annotate({ "identifier": "Error" }) +export type ResponseError = { + readonly "code": ResponseErrorCode + readonly "message": string + readonly "misalignment"?: MisalignmentErrorDetailsResource +} | null +export const ResponseError = Schema.Union([ + Schema.Struct({ + "code": ResponseErrorCode, + "message": Schema.String.annotate({ "description": "A human-readable description of the error.\n" }), + "misalignment": Schema.optionalKey(MisalignmentErrorDetailsResource) + }).annotate({ "description": "An error object returned when the model fails to generate a Response.\n" }), + Schema.Null +]).annotate({ "identifier": "ResponseError" }) +export type Error_2 = { + readonly "code": string + readonly "message": string + readonly "headers"?: { readonly [x: string]: string } + readonly "misalignment"?: MisalignmentErrorDetailsResource +} +export const Error_2 = Schema.Struct({ + "code": Schema.String.annotate({ "description": "A machine-readable error code that was returned." }), + "message": Schema.String.annotate({ "description": "A human-readable description of the error that was returned." }), + "headers": Schema.optionalKey( + Schema.Record(Schema.String, Schema.String.annotate({ "description": "The retry header value." })).annotate({ + "description": "The Retry-After and Retry-After-Ms headers returned with the original error, if any." + }) + ), + "misalignment": Schema.optionalKey(MisalignmentErrorDetailsResource) +}).annotate({ + "title": "Error", + "description": "An error that occurred while generating the response.", + "identifier": "Error-2" +}) +export type CreateVoiceRequestMultipart = CreateVoiceFromConsentRequestMultipart +export const CreateVoiceRequestMultipart = Schema.Union([CreateVoiceFromConsentRequestMultipart], { mode: "oneOf" }) + .annotate({ "identifier": "CreateVoiceRequestMultipart" }) +export type CreateTranscriptionResponseStreamEvent = + | TranscriptTextSegmentEvent + | TranscriptTextDeltaEvent + | TranscriptTextDoneEvent +export const CreateTranscriptionResponseStreamEvent = Schema.Union([ + TranscriptTextSegmentEvent, + TranscriptTextDeltaEvent, + TranscriptTextDoneEvent +]).annotate({ "identifier": "CreateTranscriptionResponseStreamEvent" }) +export type ListBatchesResponse = { + readonly "data": ReadonlyArray + readonly "first_id"?: string + readonly "last_id"?: string + readonly "has_more": boolean + readonly "object": "list" +} +export const ListBatchesResponse = Schema.Struct({ + "data": Schema.Array(Batch), + "first_id": Schema.optionalKey(Schema.String), + "last_id": Schema.optionalKey(Schema.String), + "has_more": Schema.Boolean, + "object": Schema.Literal("list") +}).annotate({ "identifier": "ListBatchesResponse" }) +export type ChatCompletionResponseMessage = { + readonly "content": string | null + readonly "refusal"?: string | null + readonly "tool_calls"?: ChatCompletionMessageToolCalls | null + readonly "annotations"?: ReadonlyArray< + { + readonly "type": "url_citation" + readonly "url_citation": { + readonly "end_index": number + readonly "start_index": number + readonly "url": string + readonly "title": string + } + } + > + readonly "role": "assistant" + readonly "function_call"?: + | { readonly "arguments": string; readonly "name": string } & { readonly [x: string]: Schema.Json } + | null + readonly "audio"?: { + readonly "id": string + readonly "expires_at": number + readonly "data": string + readonly "transcript": string + } | null +} +export const ChatCompletionResponseMessage = Schema.Struct({ + "content": Schema.Union([Schema.String.annotate({ "description": "The contents of the message." }), Schema.Null]), + "refusal": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The refusal message generated by the model." }), + Schema.Null + ]) + ), + "tool_calls": Schema.optionalKey(Schema.Union([ChatCompletionMessageToolCalls, Schema.Null])), + "annotations": Schema.optionalKey( + Schema.Array( + Schema.Struct({ + "type": Schema.Literal("url_citation").annotate({ + "description": "The type of the URL citation. Always `url_citation`." + }), + "url_citation": Schema.Struct({ + "end_index": Schema.Number.annotate({ + "description": "The index of the last character of the URL citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "start_index": Schema.Number.annotate({ + "description": "The index of the first character of the URL citation in the message." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "url": Schema.String.annotate({ "description": "The URL of the web resource.", "format": "uri" }), + "title": Schema.String.annotate({ "description": "The title of the web resource." }) + }).annotate({ "description": "A URL citation when using web search." }) + }).annotate({ "description": "A URL citation when using web search.\n" }) + ).annotate({ + "description": + "Annotations for the message, when applicable, as when using the\n[web search tool](https://developers.openai.com/api/docs/guides/tools-web-search).\n" + }) + ), + "role": Schema.Literal("assistant").annotate({ "description": "The role of the author of this message." }), + "function_call": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "arguments": Schema.String.annotate({ + "description": + "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." + }), + "name": Schema.String.annotate({ "description": "The name of the function to call." }) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ + "description": + "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." + }) + ), + "audio": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "id": Schema.String.annotate({ "description": "Unique identifier for this audio response." }), + "expires_at": Schema.Number.annotate({ + "description": + "The Unix timestamp (in seconds) for when this audio response will\nno longer be accessible on the server for use in multi-turn\nconversations.\n", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "data": Schema.String.annotate({ + "description": "Base64 encoded audio bytes generated by the model, in the format\nspecified in the request.\n" + }), + "transcript": Schema.String.annotate({ "description": "Transcript of the audio generated by the model." }) + }).annotate({ + "description": + "If the audio output modality is requested, this object contains data\nabout the audio response from the model. [Learn more](https://developers.openai.com/api/docs/guides/audio).\n" + }), + Schema.Null + ])) +}).annotate({ + "description": "A chat completion message generated by the model.", + "identifier": "ChatCompletionResponseMessage" +}) +export type ChatCompletionModerationResults = { + readonly "type": "moderation_results" + readonly "model": string + readonly "results": ReadonlyArray +} +export const ChatCompletionModerationResults = Schema.Struct({ + "type": Schema.Literal("moderation_results").annotate({ + "description": "The object type, which is always `moderation_results`." + }), + "model": Schema.String.annotate({ "description": "The moderation model used to generate the results." }), + "results": Schema.Array(ModerationResultBody).annotate({ "description": "A list of moderation results." }) +}).annotate({ + "description": "Successful moderation results for the request input or generated output.", + "identifier": "ChatCompletionModerationResults" +}) +export type Moderation = { + readonly "input": ModerationResultBody | ModerationErrorBody + readonly "output": ModerationResultBody | ModerationErrorBody +} +export const Moderation = Schema.Struct({ + "input": Schema.Union([ModerationResultBody, ModerationErrorBody], { mode: "oneOf" }).annotate({ + "description": "Moderation for the response input." + }), + "output": Schema.Union([ModerationResultBody, ModerationErrorBody], { mode: "oneOf" }).annotate({ + "description": "Moderation for the response output." + }) +}).annotate({ + "title": "Moderation", + "description": "Moderation results or errors for the response input and output.", + "identifier": "Moderation" +}) +export type ChatCompletionRequestDeveloperMessage = { + readonly "content": string | ReadonlyArray + readonly "role": "developer" + readonly "name"?: string +} +export const ChatCompletionRequestDeveloperMessage = Schema.Struct({ + "content": Schema.Union([ + Schema.String.annotate({ "title": "Text content", "description": "The contents of the developer message." }), + Schema.Array(ChatCompletionRequestMessageContentPartText).annotate({ + "title": "Array of content parts", + "description": + "An array of content parts with a defined type. For developer messages, only type `text` is supported." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ], { mode: "oneOf" }).annotate({ "description": "The contents of the developer message." }), + "role": Schema.Literal("developer").annotate({ + "description": "The role of the messages author, in this case `developer`." + }), + "name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "An optional name for the participant. Provides the model information to differentiate between participants of the same role." + }) + ) +}).annotate({ + "title": "Developer message", + "description": + "Developer-provided instructions that the model should follow, regardless of\nmessages sent by the user. With o1 models and newer, `developer` messages\nreplace the previous `system` messages.\n", + "identifier": "ChatCompletionRequestDeveloperMessage" +}) +export type ChatCompletionRequestSystemMessageContentPart = ChatCompletionRequestMessageContentPartText +export const ChatCompletionRequestSystemMessageContentPart = Schema.Union( + [ChatCompletionRequestMessageContentPartText], + { mode: "oneOf" } +).annotate({ "identifier": "ChatCompletionRequestSystemMessageContentPart" }) +export type ChatCompletionRequestAssistantMessageContentPart = + | ChatCompletionRequestMessageContentPartText + | ChatCompletionRequestMessageContentPartRefusal +export const ChatCompletionRequestAssistantMessageContentPart = Schema.Union([ + ChatCompletionRequestMessageContentPartText, + ChatCompletionRequestMessageContentPartRefusal +], { mode: "oneOf" }).annotate({ "identifier": "ChatCompletionRequestAssistantMessageContentPart" }) +export type ChatCompletionRequestToolMessageContentPart = ChatCompletionRequestMessageContentPartText +export const ChatCompletionRequestToolMessageContentPart = Schema.Union([ChatCompletionRequestMessageContentPartText], { + mode: "oneOf" +}).annotate({ "identifier": "ChatCompletionRequestToolMessageContentPart" }) +export type PredictionContent = { + readonly "type": "content" + readonly "content": string | ReadonlyArray +} +export const PredictionContent = Schema.Struct({ + "type": Schema.Literal("content").annotate({ + "description": "The type of the predicted content you want to provide. This type is\ncurrently always `content`.\n" + }), + "content": Schema.Union([ + Schema.String.annotate({ + "title": "Text content", + "description": + "The content used for a Predicted Output. This is often the\ntext of a file you are regenerating with minor changes.\n" + }), + Schema.Array(ChatCompletionRequestMessageContentPartText).annotate({ + "title": "Array of content parts", + "description": + "An array of content parts with a defined type. Supported options differ based on the [model](https://developers.openai.com/api/docs/models) being used to generate the response. Can contain text inputs." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ], { mode: "oneOf" }).annotate({ + "description": + "The content that should be matched when generating a model response.\nIf generated tokens would match this content, the entire model response\ncan be returned much more quickly.\n" + }) +}).annotate({ + "title": "Static Content", + "description": "Static predicted output content, such as the content of a text file that is\nbeing regenerated.\n", + "identifier": "PredictionContent" +}) +export type ChatCompletionRequestUserMessageContentPart = + | ChatCompletionRequestMessageContentPartText + | ChatCompletionRequestMessageContentPartImage + | ChatCompletionRequestMessageContentPartAudio + | ChatCompletionRequestMessageContentPartFile +export const ChatCompletionRequestUserMessageContentPart = Schema.Union([ + ChatCompletionRequestMessageContentPartText, + ChatCompletionRequestMessageContentPartImage, + ChatCompletionRequestMessageContentPartAudio, + ChatCompletionRequestMessageContentPartFile +], { mode: "oneOf" }).annotate({ "identifier": "ChatCompletionRequestUserMessageContentPart" }) +export type ModelIdsCompaction = ModelIdsResponses | string | null +export const ModelIdsCompaction = Schema.Union([ModelIdsResponses, Schema.String, Schema.Null]).annotate({ + "description": + "Model ID used to generate the response, like `gpt-6-astra`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models) to browse and compare available models.", + "identifier": "ModelIdsCompaction" +}) +export type ModerationPolicyParam = { + readonly "input"?: ModerationConfigParam | null + readonly "output"?: ModerationConfigParam | null +} +export const ModerationPolicyParam = Schema.Struct({ + "input": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ModerationConfigParam).annotate({ + "description": "The moderation policy for the response input." + }), + Schema.Null + ]) + ), + "output": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ModerationConfigParam).annotate({ + "description": "The moderation policy for the response output." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "The policy to apply to moderated response input and output.", + "identifier": "ModerationPolicyParam" +}) +export type ChatCompletionToolChoiceOption = + | "none" + | "auto" + | "required" + | ChatCompletionAllowedToolsChoice + | ChatCompletionNamedToolChoice + | ChatCompletionNamedToolChoiceCustom +export const ChatCompletionToolChoiceOption = Schema.Union([ + Schema.Literals(["none", "auto", "required"]).annotate({ + "title": "Tool choice mode", + "description": + "`none` means the model will not call any tool and instead generates a message. `auto` means the model can pick between generating a message or calling one or more tools. `required` means the model must call one or more tools.\n" + }), + ChatCompletionAllowedToolsChoice, + ChatCompletionNamedToolChoice, + ChatCompletionNamedToolChoiceCustom +], { mode: "oneOf" }).annotate({ + "description": + "Controls which (if any) tool is called by the model.\n`none` means the model will not call any tool and instead generates a message.\n`auto` means the model can pick between generating a message or calling one or more tools.\n`required` means the model must call one or more tools.\nSpecifying a particular tool via `{\"type\": \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that tool.\n\n`none` is the default when no tools are present. `auto` is the default if tools are present.\n", + "identifier": "ChatCompletionToolChoiceOption" +}) +export type CreateContainerBody = { + readonly "name": string + readonly "file_ids"?: ReadonlyArray + readonly "expires_after"?: { readonly "anchor": "last_active_at"; readonly "minutes": number } + readonly "skills"?: ReadonlyArray + readonly "memory_limit"?: "1g" | "4g" | "16g" | "64g" + readonly "network_policy"?: ContainerNetworkPolicyDisabledParam | ContainerNetworkPolicyAllowlistParam +} +export const CreateContainerBody = Schema.Struct({ + "name": Schema.String.annotate({ "description": "Name of the container to create." }), + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ "description": "IDs of files to copy to the container." }) + ), + "expires_after": Schema.optionalKey( + Schema.Struct({ + "anchor": Schema.Literal("last_active_at").annotate({ + "description": "Time anchor for the expiration time. Currently only 'last_active_at' is supported." + }), + "minutes": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })) + }).annotate({ "description": "Container expiration time in seconds relative to the 'anchor' time." }) + ), + "skills": Schema.optionalKey( + Schema.Array(Schema.Union([SkillReferenceParam, InlineSkillParam], { mode: "oneOf" })).annotate({ + "description": "An optional list of skills referenced by id or inline data." + }) + ), + "memory_limit": Schema.optionalKey( + Schema.Literals(["1g", "4g", "16g", "64g"]).annotate({ + "description": "Optional memory limit for the container. Defaults to \"1g\"." + }) + ), + "network_policy": Schema.optionalKey( + Schema.Union([ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam], { mode: "oneOf" }) + .annotate({ "description": "Network access policy for the container." }) + ) +}).annotate({ "identifier": "CreateContainerBody" }) +export type AutoCodeInterpreterToolParam = { + readonly "type": "auto" + readonly "file_ids"?: ReadonlyArray + readonly "memory_limit"?: ContainerMemoryLimit | null + readonly "network_policy"?: ContainerNetworkPolicyDisabledParam | ContainerNetworkPolicyAllowlistParam +} +export const AutoCodeInterpreterToolParam = Schema.Struct({ + "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }), + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "An optional list of uploaded files to make available to your code." + }).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })) + ), + "memory_limit": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ContainerMemoryLimit).annotate({ + "description": "The memory limit for the code interpreter container." + }), + Schema.Null + ]) + ), + "network_policy": Schema.optionalKey( + Schema.Union([ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam], { mode: "oneOf" }) + .annotate({ "description": "Network access policy for the container." }) + ) +}).annotate({ + "title": "CodeInterpreterToolAuto", + "description": + "Configuration for a code interpreter container. Optionally specify the IDs of the files to run the code on.", + "identifier": "AutoCodeInterpreterToolParam" +}) +export type ContainerAutoParam = { + readonly "type": "container_auto" + readonly "file_ids"?: ReadonlyArray + readonly "memory_limit"?: ContainerMemoryLimit | null + readonly "network_policy"?: ContainerNetworkPolicyDisabledParam | ContainerNetworkPolicyAllowlistParam + readonly "skills"?: ReadonlyArray +} +export const ContainerAutoParam = Schema.Struct({ + "type": Schema.Literal("container_auto").annotate({ + "description": "Automatically creates a container for this request" + }), + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "An optional list of uploaded files to make available to your code." + }).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })) + ), + "memory_limit": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ContainerMemoryLimit).annotate({ + "description": "The memory limit for the container." + }), + Schema.Null + ]) + ), + "network_policy": Schema.optionalKey( + Schema.Union([ContainerNetworkPolicyDisabledParam, ContainerNetworkPolicyAllowlistParam], { mode: "oneOf" }) + .annotate({ "description": "Network access policy for the container." }) + ), + "skills": Schema.optionalKey( + Schema.Array(Schema.Union([SkillReferenceParam, InlineSkillParam], { mode: "oneOf" })).annotate({ + "description": "An optional list of skills referenced by id or inline data." + }).check(Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" })) + ) +}).annotate({ "identifier": "ContainerAutoParam" }) +export type EvalItemContentItem = + | EvalItemContentText + | InputTextContent + | EvalItemContentOutputText + | EvalItemInputImage + | InputAudio +export const EvalItemContentItem = Schema.Union([ + EvalItemContentText, + InputTextContent, + EvalItemContentOutputText, + EvalItemInputImage, + InputAudio +], { mode: "oneOf" }).annotate({ + "title": "Eval content item", + "description": "A single content item: input text, output text, input image, or input audio.\n", + "identifier": "EvalItemContentItem" +}) +export type ResponseOutputTextAnnotationAddedEvent = { + readonly "type": "response.output_text.annotation.added" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "annotation_index": number + readonly "sequence_number": number + readonly "annotation": Annotation | null +} +export const ResponseOutputTextAnnotationAddedEvent = Schema.Struct({ + "type": Schema.Literal("response.output_text.annotation.added").annotate({ + "description": "The type of the event. Always 'response.output_text.annotation.added'." + }), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the item to which the annotation is being added." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ "description": "The index of the content part within the output item." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "annotation_index": Schema.Number.annotate({ "description": "The index of the annotation within the content part." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "annotation": Schema.Union([Annotation, Schema.Null]).annotate({ + "description": "The annotation object being added. (See annotation schema for details.)" + }) +}).annotate({ + "title": "ResponseOutputTextAnnotationAddedEvent", + "description": "Emitted when an annotation is added to output text content.\n", + "identifier": "ResponseOutputTextAnnotationAddedEvent" +}) +export type OutputTextContent = { + readonly "type": "output_text" + readonly "text": string + readonly "annotations": ReadonlyArray + readonly "logprobs": ReadonlyArray +} +export const OutputTextContent = Schema.Struct({ + "type": Schema.Literal("output_text").annotate({ + "description": "The type of the output text. Always `output_text`." + }), + "text": Schema.String.annotate({ "description": "The text output from the model." }), + "annotations": Schema.Array(Annotation).annotate({ "description": "The annotations of the text output." }), + "logprobs": Schema.Array(LogProb) +}).annotate({ + "title": "Output text", + "description": "A text output from the model.", + "identifier": "OutputTextContent" +}) +export type FunctionAndCustomToolCallOutput = InputTextContent | InputImageContent | InputFileContent +export const FunctionAndCustomToolCallOutput = Schema.Union([InputTextContent, InputImageContent, InputFileContent], { + mode: "oneOf" +}).annotate({ "identifier": "FunctionAndCustomToolCallOutput" }) +export type InputContent = InputTextContent | InputImageContent | InputFileContent +export const InputContent = Schema.Union([InputTextContent, InputImageContent, InputFileContent], { mode: "oneOf" }) + .annotate({ "identifier": "InputContent" }) +export type ResponsePromptVariables = { + readonly [x: string]: string | InputTextContent | InputImageContent | InputFileContent +} | null +export const ResponsePromptVariables = Schema.Union([ + Schema.Record( + Schema.String, + Schema.Union([Schema.String, InputTextContent, InputImageContent, InputFileContent], { mode: "oneOf" }) + ).annotate({ + "title": "Prompt Variables", + "description": + "Optional map of values to substitute in for variables in your\nprompt. The substitution values can either be strings, or other\nResponse input types like images or files.\n" + }), + Schema.Null +]).annotate({ "identifier": "ResponsePromptVariables" }) +export type FunctionToolCallResource = { + readonly "id": string + readonly "type": "function_call" + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "arguments": string + readonly "status": "in_progress" | "completed" | "incomplete" + readonly "async"?: boolean + readonly "created_by"?: string +} +export const FunctionToolCallResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the function tool call.\n" }), + "type": Schema.Literal("function_call").annotate({ + "description": "The type of the function tool call. Always `function_call`.\n" + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the function tool call generated by the model.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey(Schema.String.annotate({ "description": "The namespace of the function to run.\n" })), + "name": Schema.String.annotate({ "description": "The name of the function to run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments to pass to the function.\n" }), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the function tool call runs asynchronously.\n" }) + ), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "identifier": "FunctionToolCallResource" }) +export type FunctionShellCall = { + readonly "type": "shell_call" + readonly "id": string + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "action": FunctionShellAction + readonly "status": FunctionShellCallStatus + readonly "environment": LocalEnvironmentResource | ContainerReferenceResource | null + readonly "created_by"?: string +} +export const FunctionShellCall = Schema.Struct({ + "type": Schema.Literal("shell_call").annotate({ "description": "The type of the item. Always `shell_call`." }), + "id": Schema.String.annotate({ + "description": "The unique ID of the shell tool call. Populated when this item is returned via API." + }), + "call_id": Schema.String.annotate({ "description": "The unique ID of the shell tool call generated by the model." }), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCaller).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "action": Schema.suspend((): Schema.Codec => FunctionShellAction).annotate({ + "description": "The shell commands and limits that describe how to run the tool call." + }), + "status": Schema.suspend((): Schema.Codec => FunctionShellCallStatus).annotate({ + "description": "The status of the shell call. One of `in_progress`, `completed`, or `incomplete`." + }), + "environment": Schema.Union([ + Schema.Union([LocalEnvironmentResource, ContainerReferenceResource], { mode: "oneOf" }), + Schema.Null + ]), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the entity that created this tool call." }) + ) +}).annotate({ + "title": "Shell tool call", + "description": "A tool call that executes one or more shell commands in a managed environment.", + "identifier": "FunctionShellCall" +}) +export type ApplyPatchToolCall = { + readonly "type": "apply_patch_call" + readonly "id": string + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "status": ApplyPatchCallStatus + readonly "operation": ApplyPatchCreateFileOperation | ApplyPatchDeleteFileOperation | ApplyPatchUpdateFileOperation + readonly "created_by"?: string +} +export const ApplyPatchToolCall = Schema.Struct({ + "type": Schema.Literal("apply_patch_call").annotate({ + "description": "The type of the item. Always `apply_patch_call`." + }), + "id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call. Populated when this item is returned via API." + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call generated by the model." + }), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCaller).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.suspend((): Schema.Codec => ApplyPatchCallStatus).annotate({ + "description": "The status of the apply patch tool call. One of `in_progress` or `completed`." + }), + "operation": Schema.Union([ + ApplyPatchCreateFileOperation, + ApplyPatchDeleteFileOperation, + ApplyPatchUpdateFileOperation + ], { mode: "oneOf" }).annotate({ + "title": "Apply patch operation", + "description": "One of the create_file, delete_file, or update_file operations applied via apply_patch." + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the entity that created this tool call." }) + ) +}).annotate({ + "title": "Apply patch tool call", + "description": "A tool call that applies file diffs by creating, deleting, or updating files.", + "identifier": "ApplyPatchToolCall" +}) +export type ApplyPatchToolCallOutput = { + readonly "type": "apply_patch_call_output" + readonly "id": string + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "status": ApplyPatchCallOutputStatus + readonly "output"?: string | null + readonly "created_by"?: string +} +export const ApplyPatchToolCallOutput = Schema.Struct({ + "type": Schema.Literal("apply_patch_call_output").annotate({ + "description": "The type of the item. Always `apply_patch_call_output`." + }), + "id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call output. Populated when this item is returned via API." + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call generated by the model." + }), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCaller).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.suspend((): Schema.Codec => ApplyPatchCallOutputStatus).annotate({ + "description": "The status of the apply patch tool call output. One of `completed` or `failed`." + }), + "output": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Optional textual output returned by the apply patch tool." }), + Schema.Null + ]) + ), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the entity that created this tool call output." }) + ) +}).annotate({ + "title": "Apply patch tool call output", + "description": "The output emitted by an apply patch tool call.", + "identifier": "ApplyPatchToolCallOutput" +}) +export type CustomToolCall = { + readonly "type": "custom_tool_call" + readonly "id"?: string + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "input": string + readonly "async"?: boolean +} +export const CustomToolCall = Schema.Struct({ + "type": Schema.Literal("custom_tool_call").annotate({ + "description": "The type of the custom tool call. Always `custom_tool_call`.\n" + }), + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the custom tool call in the OpenAI platform.\n" }) + ), + "call_id": Schema.String.annotate({ + "description": "An identifier used to map this custom tool call to a tool call output.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) + ), + "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), + "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model.\n" }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the custom tool call runs asynchronously.\n" }) + ) +}).annotate({ + "title": "Custom tool call", + "description": "A call to a custom tool created by the model.\n", + "identifier": "CustomToolCall" +}) +export type FunctionToolCall = { + readonly "id"?: string + readonly "type": "function_call" + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "arguments": string + readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "async"?: boolean +} +export const FunctionToolCall = Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the function tool call.\n" })), + "type": Schema.Literal("function_call").annotate({ + "description": "The type of the function tool call. Always `function_call`.\n" + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the function tool call generated by the model.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey(Schema.String.annotate({ "description": "The namespace of the function to run.\n" })), + "name": Schema.String.annotate({ "description": "The name of the function to run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments to pass to the function.\n" }), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the function tool call runs asynchronously.\n" }) + ) +}).annotate({ + "title": "Function tool call", + "description": + "A tool call to run a function. See the\n[function calling guide](https://developers.openai.com/api/docs/guides/function-calling) for more information.\n", + "identifier": "FunctionToolCall" +}) +export type CustomToolCallResource = { + readonly "type": "custom_tool_call" + readonly "id": string + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "input": string + readonly "async"?: boolean + readonly "status": FunctionCallStatus + readonly "created_by"?: string +} +export const CustomToolCallResource = Schema.Struct({ + "type": Schema.Literal("custom_tool_call").annotate({ + "description": "The type of the custom tool call. Always `custom_tool_call`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the custom tool call item.\n" }), + "call_id": Schema.String.annotate({ + "description": "An identifier used to map this custom tool call to a tool call output.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) + ), + "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), + "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model.\n" }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the custom tool call runs asynchronously.\n" }) + ), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatus).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "title": "ResponseCustomToolCallItem", "identifier": "CustomToolCallResource" }) +export type ComputerAction = + | ClickParam + | DoubleClickAction + | DragParam + | KeyPressAction + | MoveParam + | ScreenshotParam + | ScrollParam + | TypeParam + | WaitParam +export const ComputerAction = Schema.Union([ + ClickParam, + DoubleClickAction, + DragParam, + KeyPressAction, + MoveParam, + ScreenshotParam, + ScrollParam, + TypeParam, + WaitParam +], { mode: "oneOf" }).annotate({ "identifier": "ComputerAction" }) +export type FileSearchTool = { + readonly "type": "file_search" + readonly "vector_store_ids": ReadonlyArray + readonly "max_num_results"?: number + readonly "ranking_options"?: RankingOptions + readonly "filters"?: Filters | null +} +export const FileSearchTool = Schema.Struct({ + "type": Schema.Literal("file_search").annotate({ + "description": "The type of the file search tool. Always `file_search`." + }), + "vector_store_ids": Schema.Array(Schema.String).annotate({ + "description": "The IDs of the vector stores to search." + }), + "max_num_results": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum number of results to return. This number should be between 1 and 50 inclusive." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "ranking_options": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RankingOptions).annotate({ + "description": "Ranking options for search." + }) + ), + "filters": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Filters).annotate({ "description": "A filter to apply." }), + Schema.Null + ]) + ) +}).annotate({ + "title": "File search", + "description": + "A tool that searches for relevant content from uploaded files. Learn more about the [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search).", + "identifier": "FileSearchTool" +}) +export type CustomToolParam = { + readonly "type": "custom" + readonly "name": string + readonly "async"?: boolean + readonly "description"?: string + readonly "format"?: CustomTextFormatParam | CustomGrammarFormatParam + readonly "defer_loading"?: boolean + readonly "allowed_callers"?: ReadonlyArray | null +} +export const CustomToolParam = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "The type of the custom tool. Always `custom`." }), + "name": Schema.String.annotate({ "description": "The name of the custom tool, used to identify it in tool calls." }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Whether the tool response can be returned asynchronously versus immediately returned on next response creation." + }) + ), + "description": Schema.optionalKey( + Schema.String.annotate({ "description": "Optional description of the custom tool, used to provide more context." }) + ), + "format": Schema.optionalKey( + Schema.Union([CustomTextFormatParam, CustomGrammarFormatParam], { mode: "oneOf" }).annotate({ + "description": "The input format for the custom tool. Default is unconstrained text." + }) + ), + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether this tool should be deferred and discovered via tool search." }) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(CallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ + "title": "Custom tool", + "description": + "A custom tool that processes input using a specified format. Learn more about [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools)", + "identifier": "CustomToolParam" +}) +export type FunctionShellCallOutput = { + readonly "type": "shell_call_output" + readonly "id": string + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "status": FunctionShellCallOutputStatusEnum + readonly "output": ReadonlyArray + readonly "max_output_length": number | null + readonly "created_by"?: string +} +export const FunctionShellCallOutput = Schema.Struct({ + "type": Schema.Literal("shell_call_output").annotate({ + "description": "The type of the shell call output. Always `shell_call_output`." + }), + "id": Schema.String.annotate({ + "description": "The unique ID of the shell call output. Populated when this item is returned via API." + }), + "call_id": Schema.String.annotate({ "description": "The unique ID of the shell tool call generated by the model." }), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCaller).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.suspend((): Schema.Codec => FunctionShellCallOutputStatusEnum) + .annotate({ + "description": "The status of the shell call output. One of `in_progress`, `completed`, or `incomplete`." + }), + "output": Schema.Array(FunctionShellCallOutputContent).annotate({ + "description": "An array of shell call output contents" + }), + "max_output_length": Schema.Union([ + Schema.Number.annotate({ + "description": + "The maximum length of the shell command output. This is generated by the model and should be passed back with the raw output." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ + "title": "Shell call output", + "description": "The output of a shell tool call that was emitted.", + "identifier": "FunctionShellCallOutput" +}) +export type ResponseShellCallOutputContentDoneStreamingEvent = { + readonly "type": "response.shell_call_output_content.done" + readonly "sequence_number": number + readonly "item_id": string + readonly "output_index": number + readonly "command_index": number + readonly "output": ReadonlyArray +} +export const ResponseShellCallOutputContentDoneStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_output_content.done").annotate({ + "description": "The type of the event, always `response.shell_call_output_content.done`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "item_id": Schema.String.annotate({ "description": "The ID of the output item that was updated." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that produced output." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "output": Schema.Array(FunctionShellCallOutputContent).annotate({ + "description": "The output contents emitted for the shell command." + }) +}).annotate({ + "title": "Response shell call output content done event", + "description": "A streaming event that indicated shell call output was completed.", + "identifier": "ResponseShellCallOutputContentDoneStreamingEvent" +}) +export type MCPToolCall = { + readonly "type": "mcp_call" + readonly "id": string + readonly "server_label": string + readonly "name": string + readonly "arguments": string + readonly "output"?: string | null + readonly "error"?: MCPToolCallError | null + readonly "status"?: MCPToolCallStatus + readonly "approval_request_id"?: string | null +} +export const MCPToolCall = Schema.Struct({ + "type": Schema.Literal("mcp_call").annotate({ "description": "The type of the item. Always `mcp_call`.\n" }), + "id": Schema.String.annotate({ "description": "The unique ID of the tool call.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server running the tool.\n" }), + "name": Schema.String.annotate({ "description": "The name of the tool that was run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments passed to the tool.\n" }), + "output": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The output from the tool call.\n" }), Schema.Null]) + ), + "error": Schema.optionalKey( + Schema.Union([MCPToolCallError, Schema.Null]).annotate({ "description": "The error from the tool call, if any." }) + ), + "status": Schema.optionalKey( + Schema.suspend((): Schema.Codec => MCPToolCallStatus).annotate({ + "description": + "The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`.\n" + }) + ), + "approval_request_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "Unique identifier for the MCP tool call approval request.\nInclude this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call.\n" + }), + Schema.Null + ]) + ) +}).annotate({ + "title": "MCP tool call", + "description": "An invocation of a tool on an MCP server.\n", + "identifier": "MCPToolCall" +}) +export type FunctionShellCallOutputContentParam = { + readonly "stdout": string + readonly "stderr": string + readonly "outcome": FunctionShellCallOutputOutcomeParam +} +export const FunctionShellCallOutputContentParam = Schema.Struct({ + "stdout": Schema.String.annotate({ "description": "Captured stdout output for the shell call." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "stderr": Schema.String.annotate({ "description": "Captured stderr output for the shell call." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "outcome": Schema.suspend((): Schema.Codec => + FunctionShellCallOutputOutcomeParam + ).annotate({ "description": "The exit or timeout outcome associated with this shell call." }) +}).annotate({ + "title": "Shell output content", + "description": "Captured stdout and stderr for a portion of a shell tool call output.", + "identifier": "FunctionShellCallOutputContentParam" +}) +export type EvalRunOutputItemList = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean +} +export const EvalRunOutputItemList = Schema.Struct({ + "object": Schema.Literal("list").annotate({ + "description": "The type of this object. It is always set to \"list\".\n" + }), + "data": Schema.Array(EvalRunOutputItem).annotate({ "description": "An array of eval run output item objects.\n" }), + "first_id": Schema.String.annotate({ + "description": "The identifier of the first eval run output item in the data array." + }), + "last_id": Schema.String.annotate({ + "description": "The identifier of the last eval run output item in the data array." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Indicates whether there are more eval run output items available." + }) +}).annotate({ + "title": "EvalRunOutputItemList", + "description": "An object representing a list of output items for an evaluation run.\n", + "identifier": "EvalRunOutputItemList" +}) +export type ImagesResponse = { + readonly "created": number + readonly "data"?: ReadonlyArray + readonly "background"?: "transparent" | "opaque" + readonly "output_format"?: "png" | "webp" | "jpeg" + readonly "size"?: string | "1024x1024" | "1024x1536" | "1536x1024" + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" + readonly "usage"?: ImageGenUsage +} +export const ImagesResponse = Schema.Struct({ + "created": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the image was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "data": Schema.optionalKey(Schema.Array(Image).annotate({ "description": "The list of generated images." })), + "background": Schema.optionalKey( + Schema.Literals(["transparent", "opaque"]).annotate({ + "description": "The background parameter used for the image generation. Either `transparent` or `opaque`." + }) + ), + "output_format": Schema.optionalKey( + Schema.Literals(["png", "webp", "jpeg"]).annotate({ + "description": "The output format of the image generation. Either `png`, `webp`, or `jpeg`." + }) + ), + "size": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." + }) + ), + "quality": Schema.optionalKey( + Schema.Literals(["low", "medium", "high", "xhigh", "max"]).annotate({ + "description": "The quality of the image generated. One of `low`, `medium`, `high`, `xhigh`, or `max`." + }) + ), + "usage": Schema.optionalKey(ImageGenUsage) +}).annotate({ + "title": "Image generation response", + "description": "The response from the image generation endpoint.", + "identifier": "ImagesResponse" +}) +export type ImageEditStreamEvent = ImageEditPartialImageEvent | ImageEditCompletedEvent +export const ImageEditStreamEvent = Schema.Union([ImageEditPartialImageEvent, ImageEditCompletedEvent]).annotate({ + "identifier": "ImageEditStreamEvent" +}) +export type ImageGenStreamEvent = ImageGenPartialImageEvent | ImageGenCompletedEvent +export const ImageGenStreamEvent = Schema.Union([ImageGenPartialImageEvent, ImageGenCompletedEvent]).annotate({ + "identifier": "ImageGenStreamEvent" +}) +export type LiveMediaSessionAudioParam = { readonly "output"?: LiveInitialSessionAudioOutputParam } +export const LiveMediaSessionAudioParam = Schema.Struct({ + "output": Schema.optionalKey(LiveInitialSessionAudioOutputParam) +}).annotate({ + "description": + "Startup audio output configuration. WebRTC and SIP negotiate the media format; audio.format is only accepted for primary WebSockets. Voice cannot change after startup.", + "identifier": "LiveMediaSessionAudioParam" +}) +export type LiveHostedShellContainerAutoParam = { + readonly "type": "container_auto" + readonly "file_ids"?: ReadonlyArray | null + readonly "memory_limit"?: LiveContainerMemoryLimit | null + readonly "network_policy"?: + | LiveContainerNetworkPolicyDisabledParam + | LiveHostedShellNetworkPolicyAllowlistParam + | null + readonly "skills"?: ReadonlyArray | null +} +export const LiveHostedShellContainerAutoParam = Schema.Struct({ + "type": Schema.Literal("container_auto").annotate({ + "description": "Automatically creates a container for this request" + }), + "file_ids": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.String).annotate({ + "description": "An optional list of uploaded files to make available to your code." + }).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })), + Schema.Null + ]) + ), + "memory_limit": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveContainerMemoryLimit).annotate({ + "description": "The memory limit for the container." + }), + Schema.Null + ]) + ), + "network_policy": Schema.optionalKey( + Schema.Union([ + Schema.Union([LiveContainerNetworkPolicyDisabledParam, LiveHostedShellNetworkPolicyAllowlistParam], { + mode: "oneOf" + }).annotate({ "description": "Network access policy for the container." }), + Schema.Null + ]) + ), + "skills": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.Union([LiveSkillReferenceParam, LiveInlineSkillParam], { mode: "oneOf" })).annotate({ + "description": "An optional list of skills referenced by id or inline data." + }).check(Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" })), + Schema.Null + ]) + ) +}).annotate({ "identifier": "LiveHostedShellContainerAutoParam" }) +export type LiveInitialItem = + | LiveInitialDeveloperMessageItemParam + | LiveInitialUserMessageItemParam + | LiveInitialAssistantMessageItemParam +export const LiveInitialItem = Schema.Union([ + LiveInitialDeveloperMessageItemParam, + LiveInitialUserMessageItemParam, + LiveInitialAssistantMessageItemParam +], { mode: "oneOf" }).annotate({ + "description": "A developer, user, or assistant message supplied as text history before the Live session starts.", + "identifier": "LiveInitialItem" +}) +export type LiveClientConfigParam = { readonly "data_channel": LiveDataChannelConfigParam } +export const LiveClientConfigParam = Schema.Struct({ + "data_channel": Schema.suspend((): Schema.Codec => LiveDataChannelConfigParam).annotate({ + "description": "Client and server event permissions for the WebRTC frontend data channel." + }) +}).annotate({ + "description": + "Startup-only capabilities for an untrusted frontend attached to a unified WebRTC session. Trusted sideband connections are unaffected.", + "identifier": "LiveClientConfigParam" +}) +export type LiveSIPTransport = { + readonly "type": "sip" + readonly "destination": string + readonly "trunk": LiveSIPTrunk +} +export const LiveSIPTransport = Schema.Struct({ + "type": Schema.Literal("sip").annotate({ "description": "The transport used for the Live session. Always `sip`." }), + "destination": Schema.String.annotate({ + "description": "Phone number to call in E.164 format. SIP URI destinations are not supported." + }).check( + Schema.isPattern(new RegExp("^\\+[1-9][0-9]{1,14}$", "u")).annotate({ + "expected": "a string matching the RegExp ^\\+[1-9][0-9]{1,14}$" + }) + ), + "trunk": LiveSIPTrunk +}).annotate({ + "description": + "Place an outbound SIP call using your provider's trunk. Outbound SIP calling must be enabled for your organization. The trunk must support TLS signaling, Opus audio, and SDES-SRTP media. See [Telephony and SIP](https://developers.openai.com/api/docs/guides/voice-sip?api=live#place-an-outbound-call).", + "identifier": "LiveSIPTransport" +}) +export type AuditLogActor = { + readonly "type"?: "session" | "api_key" + readonly "session"?: AuditLogActorSession + readonly "api_key"?: AuditLogActorApiKey +} +export const AuditLogActor = Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literals(["session", "api_key"]).annotate({ + "description": "The type of actor. Is either `session` or `api_key`." + }) + ), + "session": Schema.optionalKey(AuditLogActorSession), + "api_key": Schema.optionalKey(AuditLogActorApiKey) +}).annotate({ "description": "The actor who performed the audit logged action.", "identifier": "AuditLogActor" }) +export type UsageResponse = { + readonly "object": "page" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "next_page": string | null +} +export const UsageResponse = Schema.Struct({ + "object": Schema.Literal("page"), + "data": Schema.Array(UsageTimeBucket), + "has_more": Schema.Boolean, + "next_page": Schema.Union([Schema.String, Schema.Null]) +}).annotate({ "identifier": "UsageResponse" }) +export type ProjectListResponse = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean +} +export const ProjectListResponse = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(Project), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ProjectListResponse" }) +export type ProjectApiKeyListResponse = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean +} +export const ProjectApiKeyListResponse = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(ProjectApiKey), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ProjectApiKeyListResponse" }) +export type ProjectSpendAlertListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const ProjectSpendAlertListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), + "data": Schema.Array(ProjectSpendAlert).annotate({ "description": "Spend alerts returned in the current page." }), + "first_id": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The ID of the first spend alert in this page." + }), + "last_id": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The ID of the last spend alert in this page." + }), + "has_more": Schema.Boolean.annotate({ "description": "Whether more spend alerts are available when paginating." }) +}).annotate({ "description": "Paginated list of project spend alerts.", "identifier": "ProjectSpendAlertListResource" }) +export type OrganizationSpendAlertListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const OrganizationSpendAlertListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "Always `list`." }), + "data": Schema.Array(OrganizationSpendAlert).annotate({ + "description": "Spend alerts returned in the current page." + }), + "first_id": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The ID of the first spend alert in this page." + }), + "last_id": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The ID of the last spend alert in this page." + }), + "has_more": Schema.Boolean.annotate({ "description": "Whether more spend alerts are available when paginating." }) +}).annotate({ + "description": "Paginated list of organization spend alerts.", + "identifier": "OrganizationSpendAlertListResource" +}) +export type RealtimeTranslationClientSecretCreateRequest = { + readonly "expires_after"?: { readonly "anchor"?: "created_at"; readonly "seconds"?: number } + readonly "session": RealtimeTranslationSessionCreateRequest +} +export const RealtimeTranslationClientSecretCreateRequest = Schema.Struct({ + "expires_after": Schema.optionalKey( + Schema.Struct({ + "anchor": Schema.optionalKey( + Schema.Literal("created_at").annotate({ + "description": + "The anchor point for the client secret expiration, meaning that `seconds` will be added to the `created_at` time of the client secret to produce an expiration timestamp. Only `created_at` is currently supported.\n" + }) + ), + "seconds": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200` (2 hours). This default to 600 seconds (10 minutes) if not specified.\n", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(10).annotate({ "expected": "a value greater than or equal to 10" }) + ).check(Schema.isLessThanOrEqualTo(7200).annotate({ "expected": "a value less than or equal to 7200" })) + ) + }).annotate({ + "title": "Client secret expiration", + "description": + "Configuration for the client secret expiration. Expiration refers to the time after which\na client secret will no longer be valid for creating sessions. The session itself may\ncontinue after that time once started. A secret can be used to create multiple sessions\nuntil it expires.\n" + }) + ), + "session": RealtimeTranslationSessionCreateRequest +}).annotate({ + "title": "Realtime translation client secret creation request", + "description": "Create a translation session and client secret for the Realtime API.\n", + "identifier": "RealtimeTranslationClientSecretCreateRequest" +}) +export type RealtimeTranslationClientSecretCreateResponse = { + readonly "value": string + readonly "expires_at": number + readonly "session": RealtimeTranslationSession +} +export const RealtimeTranslationClientSecretCreateResponse = Schema.Struct({ + "value": Schema.String.annotate({ "description": "The generated client secret value." }), + "expires_at": Schema.Number.annotate({ + "description": "Expiration timestamp for the client secret, in seconds since epoch.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "session": RealtimeTranslationSession +}).annotate({ + "title": "Realtime translation session and client secret", + "description": "Response from creating a translation session and client secret for the Realtime API.\n", + "identifier": "RealtimeTranslationClientSecretCreateResponse" +}) +export type PromptCacheDiagnostics = + | PromptCacheMissDiagnosticsBody + | PromptCacheHitDiagnosticsBody + | PromptCacheComparisonResponseNotFoundDiagnosticsBody + | PromptCacheUnavailableDiagnosticsBody +export const PromptCacheDiagnostics = Schema.Union([ + PromptCacheMissDiagnosticsBody, + PromptCacheHitDiagnosticsBody, + PromptCacheComparisonResponseNotFoundDiagnosticsBody, + PromptCacheUnavailableDiagnosticsBody +], { mode: "oneOf" }).annotate({ + "description": "Prompt cache diagnostics requested for this response.", + "identifier": "PromptCacheDiagnostics" +}) +export type CreateThreadRequest = { + readonly "messages"?: ReadonlyArray + readonly "tool_resources"?: { + readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } + readonly "file_search"?: { + readonly "vector_store_ids": ReadonlyArray + readonly "vector_stores"?: ReadonlyArray< + { + readonly "file_ids"?: ReadonlyArray + readonly "chunking_strategy"?: { readonly "type": "auto" } | { + readonly "type": "static" + readonly "static": { readonly "max_chunk_size_tokens": number; readonly "chunk_overlap_tokens": number } + } + readonly "metadata"?: Metadata + } + > + } | { + readonly "vector_store_ids"?: ReadonlyArray + readonly "vector_stores": ReadonlyArray< + { + readonly "file_ids"?: ReadonlyArray + readonly "chunking_strategy"?: { readonly "type": "auto" } | { + readonly "type": "static" + readonly "static": { readonly "max_chunk_size_tokens": number; readonly "chunk_overlap_tokens": number } + } + readonly "metadata"?: Metadata + } + > + } + } | null + readonly "metadata"?: Metadata +} +export const CreateThreadRequest = Schema.Struct({ + "messages": Schema.optionalKey( + Schema.Array(CreateMessageRequest).annotate({ + "description": + "A list of [messages](https://developers.openai.com/api/docs/assistants/migration) to start the thread with." + }) + ), + "tool_resources": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "code_interpreter": Schema.optionalKey(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })) + ) + })), + "file_search": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "vector_store_ids": Schema.Array(Schema.String).annotate({ + "description": + "The [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this thread. There can be a maximum of 1 vector store attached to the thread.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })), + "vector_stores": Schema.optionalKey( + Schema.Array(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files.\n" + }).check( + Schema.isMaxLength(100000000).annotate({ "expected": "a value with a length of at most 100000000" }) + ) + ), + "chunking_strategy": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }) + .annotate({ + "title": "Auto Chunking Strategy", + "description": + "The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`." + }), + Schema.Struct({ + "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), + "static": Schema.Struct({ + "max_chunk_size_tokens": Schema.Number.annotate({ + "description": + "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(100).annotate({ + "expected": "a value greater than or equal to 100" + }) + ).check( + Schema.isLessThanOrEqualTo(4096).annotate({ "expected": "a value less than or equal to 4096" }) + ), + "chunk_overlap_tokens": Schema.Number.annotate({ + "description": + "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + }) + }).annotate({ "title": "Static Chunking Strategy" }) + ], { mode: "oneOf" }).annotate({ + "description": + "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." + }) + ), + "metadata": Schema.optionalKey(Metadata) + })).annotate({ + "description": + "A helper to create a [vector store](https://developers.openai.com/api/reference/resources/vector_stores) with file_ids and attach it to this thread. There can be a maximum of 1 vector store attached to the thread.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ) + }), + Schema.Struct({ + "vector_store_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "The [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this thread. There can be a maximum of 1 vector store attached to the thread.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ), + "vector_stores": Schema.Array(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files.\n" + }).check( + Schema.isMaxLength(100000000).annotate({ "expected": "a value with a length of at most 100000000" }) + ) + ), + "chunking_strategy": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }) + .annotate({ + "title": "Auto Chunking Strategy", + "description": + "The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`." + }), + Schema.Struct({ + "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), + "static": Schema.Struct({ + "max_chunk_size_tokens": Schema.Number.annotate({ + "description": + "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(100).annotate({ + "expected": "a value greater than or equal to 100" + }) + ).check( + Schema.isLessThanOrEqualTo(4096).annotate({ "expected": "a value less than or equal to 4096" }) + ), + "chunk_overlap_tokens": Schema.Number.annotate({ + "description": + "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + }) + }).annotate({ "title": "Static Chunking Strategy" }) + ], { mode: "oneOf" }).annotate({ + "description": + "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." + }) + ), + "metadata": Schema.optionalKey(Metadata) + })).annotate({ + "description": + "A helper to create a [vector store](https://developers.openai.com/api/reference/resources/vector_stores) with file_ids and attach it to this thread. There can be a maximum of 1 vector store attached to the thread.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + }) + ], { mode: "oneOf" })) + }).annotate({ + "description": + "A set of resources that are made available to the assistant's tools in this thread. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" + }), + Schema.Null + ])), + "metadata": Schema.optionalKey(Metadata) +}).annotate({ + "description": + "Options to create a new thread. If no thread is provided when running a\nrequest, an empty thread will be created.\n", + "identifier": "CreateThreadRequest" +}) +export type RunStepDeltaStepDetailsToolCallsObject = { + readonly "type": "tool_calls" + readonly "tool_calls"?: ReadonlyArray< + | RunStepDeltaStepDetailsToolCallsCodeObject + | RunStepDeltaStepDetailsToolCallsFileSearchObject + | RunStepDeltaStepDetailsToolCallsFunctionObject + > +} +export const RunStepDeltaStepDetailsToolCallsObject = Schema.Struct({ + "type": Schema.Literal("tool_calls").annotate({ "description": "Always `tool_calls`." }), + "tool_calls": Schema.optionalKey( + Schema.Array( + Schema.Union([ + RunStepDeltaStepDetailsToolCallsCodeObject, + RunStepDeltaStepDetailsToolCallsFileSearchObject, + RunStepDeltaStepDetailsToolCallsFunctionObject + ], { mode: "oneOf" }) + ).annotate({ + "description": + "An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `file_search`, or `function`.\n" + }) + ) +}).annotate({ + "title": "Tool calls", + "description": "Details of the tool call.", + "identifier": "RunStepDeltaStepDetailsToolCallsObject" +}) +export type MessageObject = { + readonly "id": string + readonly "object": "thread.message" + readonly "created_at": number + readonly "thread_id": string + readonly "status": "in_progress" | "incomplete" | "completed" + readonly "incomplete_details": { + readonly "reason": "content_filter" | "max_tokens" | "run_cancelled" | "run_expired" | "run_failed" + } | null + readonly "completed_at": number | null + readonly "incomplete_at": number | null + readonly "role": "user" | "assistant" + readonly "content": ReadonlyArray< + | MessageContentImageFileObject + | MessageContentImageUrlObject + | MessageContentTextObject + | MessageContentRefusalObject + > + readonly "assistant_id": string | null + readonly "run_id": string | null + readonly "attachments": + | ReadonlyArray< + { + readonly "file_id"?: string + readonly "tools"?: ReadonlyArray + } + > + | null + readonly "metadata": Metadata +} +export const MessageObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("thread.message").annotate({ + "description": "The object type, which is always `thread.message`." + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the message was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "thread_id": Schema.String.annotate({ + "description": + "The [thread](https://developers.openai.com/api/docs/assistants/migration) ID that this message belongs to." + }), + "status": Schema.Literals(["in_progress", "incomplete", "completed"]).annotate({ + "description": "The status of the message, which can be either `in_progress`, `incomplete`, or `completed`." + }), + "incomplete_details": Schema.Union([ + Schema.Struct({ + "reason": Schema.Literals(["content_filter", "max_tokens", "run_cancelled", "run_expired", "run_failed"]) + .annotate({ "description": "The reason the message is incomplete." }) + }).annotate({ "description": "On an incomplete message, details about why the message is incomplete." }), + Schema.Null + ]), + "completed_at": Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the message was completed.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "incomplete_at": Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the message was marked as incomplete.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "role": Schema.Literals(["user", "assistant"]).annotate({ + "description": "The entity that produced the message. One of `user` or `assistant`." + }), + "content": Schema.Array( + Schema.Union([ + MessageContentImageFileObject, + MessageContentImageUrlObject, + MessageContentTextObject, + MessageContentRefusalObject + ], { mode: "oneOf" }) + ).annotate({ "description": "The content of the message in array of text and/or images." }), + "assistant_id": Schema.Union([ + Schema.String.annotate({ + "description": + "If applicable, the ID of the [assistant](https://developers.openai.com/api/docs/assistants/migration) that authored this message." + }), + Schema.Null + ]), + "run_id": Schema.Union([ + Schema.String.annotate({ + "description": + "The ID of the [run](https://developers.openai.com/api/docs/assistants/migration) associated with the creation of this message. Value is `null` when messages are created manually using the create message or create thread endpoints." + }), + Schema.Null + ]), + "attachments": Schema.Union([ + Schema.Array(Schema.Struct({ + "file_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the file to attach to the message." }) + ), + "tools": Schema.optionalKey( + Schema.Array(Schema.Union([AssistantToolsCode, AssistantToolsFileSearchTypeOnly], { mode: "oneOf" })).annotate({ + "description": "The tools to add this file to." + }) + ) + })).annotate({ "description": "A list of files attached to the message, and the tools they were added to." }), + Schema.Null + ]), + "metadata": Metadata +}).annotate({ + "title": "The message object", + "description": "Represents a message within a [thread](https://developers.openai.com/api/docs/assistants/migration).", + "identifier": "MessageObject" +}) +export type MessageDeltaObject = { + readonly "id": string + readonly "object": "thread.message.delta" + readonly "delta": { + readonly "role"?: "user" | "assistant" + readonly "content"?: ReadonlyArray< + | MessageDeltaContentImageFileObject + | MessageDeltaContentTextObject + | MessageDeltaContentRefusalObject + | MessageDeltaContentImageUrlObject + > + } +} +export const MessageDeltaObject = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The identifier of the message, which can be referenced in API endpoints." + }), + "object": Schema.Literal("thread.message.delta").annotate({ + "description": "The object type, which is always `thread.message.delta`." + }), + "delta": Schema.Struct({ + "role": Schema.optionalKey( + Schema.Literals(["user", "assistant"]).annotate({ + "description": "The entity that produced the message. One of `user` or `assistant`." + }) + ), + "content": Schema.optionalKey( + Schema.Array( + Schema.Union([ + MessageDeltaContentImageFileObject, + MessageDeltaContentTextObject, + MessageDeltaContentRefusalObject, + MessageDeltaContentImageUrlObject + ], { mode: "oneOf" }) + ).annotate({ "description": "The content of the message in array of text and/or images." }) + ) + }).annotate({ "description": "The delta containing the fields that have changed on the Message." }) +}).annotate({ + "title": "Message delta object", + "description": "Represents a message delta i.e. any changed fields on a message during streaming.\n", + "identifier": "MessageDeltaObject" +}) +export type ListVectorStoresResponse = + | null + | string + | number + | boolean + | { + readonly "object": string + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean + } & { readonly [x: string]: Schema.Json } + | ReadonlyArray +export const ListVectorStoresResponse = Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.StructWithRest( + Schema.Struct({ + "object": Schema.String, + "data": Schema.Array(VectorStoreObject), + "first_id": Schema.String, + "last_id": Schema.String, + "has_more": Schema.Boolean + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Array(Schema.Json.annotate({ "expected": "JSON value" })) +]).annotate({ "identifier": "ListVectorStoresResponse" }) +export type CreateVectorStoreRequest = { + readonly "file_ids"?: ReadonlyArray + readonly "name"?: string + readonly "description"?: string + readonly "expires_after"?: VectorStoreExpirationAfter + readonly "chunking_strategy"?: AutoChunkingStrategyRequestParam | StaticChunkingStrategyRequestParam + readonly "metadata"?: Metadata +} +export const CreateVectorStoreRequest = Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [File](https://developers.openai.com/api/reference/resources/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files." + }).check(Schema.isMaxLength(500).annotate({ "expected": "a value with a length of at most 500" })) + ), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the vector store." })), + "description": Schema.optionalKey( + Schema.String.annotate({ + "description": "A description for the vector store. Can be used to describe the vector store's purpose." + }) + ), + "expires_after": Schema.optionalKey(VectorStoreExpirationAfter), + "chunking_strategy": Schema.optionalKey( + Schema.Union([AutoChunkingStrategyRequestParam, StaticChunkingStrategyRequestParam], { mode: "oneOf" }).annotate({ + "description": + "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. Only applicable if `file_ids` is non-empty." + }) + ), + "metadata": Schema.optionalKey(Metadata) +}).annotate({ "identifier": "CreateVectorStoreRequest" }) +export type ChunkingStrategyRequestParam = AutoChunkingStrategyRequestParam | StaticChunkingStrategyRequestParam +export const ChunkingStrategyRequestParam = Schema.Union([ + AutoChunkingStrategyRequestParam, + StaticChunkingStrategyRequestParam +], { mode: "oneOf" }).annotate({ + "description": "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy.", + "identifier": "ChunkingStrategyRequestParam" +}) +export type VectorStoreFileObject = { + readonly "id": string + readonly "object": "vector_store.file" + readonly "usage_bytes": number + readonly "created_at": number + readonly "vector_store_id": string + readonly "status": "in_progress" | "completed" | "cancelled" | "failed" + readonly "last_error": { + readonly "code": "server_error" | "unsupported_file" | "invalid_file" + readonly "message": string + } | null + readonly "chunking_strategy"?: StaticChunkingStrategyResponseParam | OtherChunkingStrategyResponseParam + readonly "attributes"?: VectorStoreFileAttributes +} +export const VectorStoreFileObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("vector_store.file").annotate({ + "description": "The object type, which is always `vector_store.file`." + }), + "usage_bytes": Schema.Number.annotate({ + "description": "The total vector store usage in bytes. Note that this may be different from the original file size." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the vector store file was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "vector_store_id": Schema.String.annotate({ + "description": + "The ID of the [vector store](https://developers.openai.com/api/reference/resources/vector_stores) that the [File](https://developers.openai.com/api/reference/resources/files) is attached to." + }), + "status": Schema.Literals(["in_progress", "completed", "cancelled", "failed"]).annotate({ + "description": + "The status of the vector store file, which can be either `in_progress`, `completed`, `cancelled`, or `failed`. The status `completed` indicates that the vector store file is ready for use." + }), + "last_error": Schema.Union([ + Schema.Struct({ + "code": Schema.Literals(["server_error", "unsupported_file", "invalid_file"]).annotate({ + "description": "One of `server_error`, `unsupported_file`, or `invalid_file`." + }), + "message": Schema.String.annotate({ "description": "A human-readable description of the error." }) + }).annotate({ + "description": "The last error associated with this vector store file. Will be `null` if there are no errors." + }), + Schema.Null + ]), + "chunking_strategy": Schema.optionalKey( + Schema.Union([StaticChunkingStrategyResponseParam, OtherChunkingStrategyResponseParam], { mode: "oneOf" }).annotate( + { "description": "The strategy used to chunk the file." } + ) + ), + "attributes": Schema.optionalKey(VectorStoreFileAttributes) +}).annotate({ + "title": "Vector store files", + "description": "A list of files attached to a vector store.", + "identifier": "VectorStoreFileObject" +}) +export type VectorStoreSearchResultsPage = { + readonly "object": "vector_store.search_results.page" + readonly "search_query": ReadonlyArray + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "next_page": string | null +} +export const VectorStoreSearchResultsPage = Schema.Struct({ + "object": Schema.Literal("vector_store.search_results.page").annotate({ + "description": "The object type, which is always `vector_store.search_results.page`" + }), + "search_query": Schema.Array(Schema.String.annotate({ "description": "The query used for this search." })), + "data": Schema.Array(VectorStoreSearchResultItem).annotate({ "description": "The list of search result items." }), + "has_more": Schema.Boolean.annotate({ "description": "Indicates if there are more results to fetch." }), + "next_page": Schema.Union([ + Schema.String.annotate({ "description": "The token for the next page, if any." }), + Schema.Null + ]) +}).annotate({ "identifier": "VectorStoreSearchResultsPage" }) +export type SafetyCaseResource = { + readonly "id": string + readonly "object": "safety.case" + readonly "created_at": number + readonly "entity_identifier": string + readonly "reason": string | null + readonly "notice": SafetyCaseNotice +} +export const SafetyCaseResource = Schema.Struct({ + "id": Schema.String, + "object": Schema.Literal("safety.case"), + "created_at": Schema.Number.annotate({ "format": "unixtime" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "entity_identifier": Schema.String, + "reason": Schema.Union([Schema.String, Schema.Null]), + "notice": SafetyCaseNotice +}).annotate({ "identifier": "SafetyCaseResource" }) +export type DecisionsUsageBucket = { + readonly "object": "bucket" + readonly "start_time": number + readonly "end_time": number + readonly "results": ReadonlyArray +} +export const DecisionsUsageBucket = Schema.Struct({ + "object": Schema.Literal("bucket"), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "results": Schema.Array(DecisionsUsageResult) +}).annotate({ "identifier": "DecisionsUsageBucket" }) +export type ExternalStorageListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const ExternalStorageListResource = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(ExternalStorageResponse), + "first_id": Schema.Union([Schema.String, Schema.Null]), + "last_id": Schema.Union([Schema.String, Schema.Null]), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ExternalStorageListResource" }) +export type OrganizationSpendLimitResource = { + readonly "object": "organization.spend_limit" + readonly "threshold_amount": number + readonly "currency": SpendLimitCurrency + readonly "interval": SpendLimitInterval + readonly "enforcement": SpendLimitEnforcement +} +export const OrganizationSpendLimitResource = Schema.Struct({ + "object": Schema.Literal("organization.spend_limit").annotate({ + "description": "The object type, which is always `organization.spend_limit`." + }), + "threshold_amount": Schema.Number.annotate({ "description": "The hard spend limit amount, in cents." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "currency": Schema.suspend((): Schema.Codec => SpendLimitCurrency).annotate({ + "description": "The currency for the threshold amount. Currently, only `USD` is supported." + }), + "interval": Schema.suspend((): Schema.Codec => SpendLimitInterval).annotate({ + "description": "The time interval for evaluating spend against the threshold. Currently, only `month` is supported." + }), + "enforcement": Schema.suspend((): Schema.Codec => SpendLimitEnforcement).annotate({ + "description": "The current enforcement state of the hard spend limit." + }) +}).annotate({ + "description": "Represents a hard spend limit configured at the organization level.", + "identifier": "OrganizationSpendLimitResource" +}) +export type ProjectSpendLimitResource = { + readonly "object": "project.spend_limit" + readonly "threshold_amount": number + readonly "currency": SpendLimitCurrency + readonly "interval": SpendLimitInterval + readonly "enforcement": SpendLimitEnforcement +} +export const ProjectSpendLimitResource = Schema.Struct({ + "object": Schema.Literal("project.spend_limit").annotate({ + "description": "The object type, which is always `project.spend_limit`." + }), + "threshold_amount": Schema.Number.annotate({ "description": "The hard spend limit amount, in cents." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "currency": Schema.suspend((): Schema.Codec => SpendLimitCurrency).annotate({ + "description": "The currency for the threshold amount. Currently, only `USD` is supported." + }), + "interval": Schema.suspend((): Schema.Codec => SpendLimitInterval).annotate({ + "description": "The time interval for evaluating spend against the threshold. Currently, only `month` is supported." + }), + "enforcement": Schema.suspend((): Schema.Codec => SpendLimitEnforcement).annotate({ + "description": "The current enforcement state of the hard spend limit." + }) +}).annotate({ + "description": "Represents a hard spend limit configured at the project level.", + "identifier": "ProjectSpendLimitResource" +}) +export type ProvenanceResource = { + readonly "object": ProvenanceCheckObject + readonly "created_at": number + readonly "results": ReadonlyArray +} +export const ProvenanceResource = Schema.Struct({ + "object": Schema.suspend((): Schema.Codec => ProvenanceCheckObject).annotate({ + "description": "The object type. Always `content_provenance_check` for this endpoint." + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the provenance check was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "results": Schema.Array(Schema.Union([C2PAProvenanceResult, SynthIDProvenanceResult], { mode: "oneOf" })).annotate({ + "description": + "The provenance results that apply to the uploaded file. Image results include C2PA and SynthID; audio results include SynthID." + }) +}).annotate({ "identifier": "ProvenanceResource" }) +export type ChatSessionResource = { + readonly "id": string + readonly "object": "chatkit.session" + readonly "expires_at": number + readonly "client_secret": string + readonly "workflow": ChatkitWorkflow + readonly "user": string + readonly "rate_limits": ChatSessionRateLimits + readonly "max_requests_per_1_minute": number + readonly "status": ChatSessionStatus + readonly "chatkit_configuration": ChatSessionChatkitConfiguration +} +export const ChatSessionResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier for the ChatKit session." }), + "object": Schema.Literal("chatkit.session").annotate({ + "description": "Type discriminator that is always `chatkit.session`." + }), + "expires_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) for when the session expires.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "client_secret": Schema.String.annotate({ + "description": "Ephemeral client secret that authenticates session requests." + }), + "workflow": Schema.suspend((): Schema.Codec => ChatkitWorkflow).annotate({ + "description": "Workflow metadata for the session." + }), + "user": Schema.String.annotate({ "description": "User identifier associated with the session." }), + "rate_limits": Schema.suspend((): Schema.Codec => ChatSessionRateLimits).annotate({ + "description": "Resolved rate limit values." + }), + "max_requests_per_1_minute": Schema.Number.annotate({ + "description": "Convenience copy of the per-minute request limit." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "status": Schema.suspend((): Schema.Codec => ChatSessionStatus).annotate({ + "description": "Current lifecycle state of the session." + }), + "chatkit_configuration": Schema.suspend((): Schema.Codec => + ChatSessionChatkitConfiguration + ).annotate({ "description": "Resolved ChatKit feature configuration for the session." }) +}).annotate({ + "title": "The chat session object", + "description": "Represents a ChatKit session and its resolved configuration.", + "identifier": "ChatSessionResource" +}) +export type CreateChatSessionBody = { + readonly "workflow": WorkflowParam + readonly "user": string + readonly "expires_after"?: ExpiresAfterParam + readonly "rate_limits"?: RateLimitsParam + readonly "chatkit_configuration"?: ChatkitConfigurationParam +} +export const CreateChatSessionBody = Schema.Struct({ + "workflow": Schema.suspend((): Schema.Codec => WorkflowParam).annotate({ + "description": "Workflow that powers the session." + }), + "user": Schema.String.annotate({ + "description": + "A free-form string that identifies your end user; ensures this Session can access other objects that have the same `user` scope." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "expires_after": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ExpiresAfterParam).annotate({ + "description": "Optional override for session expiration timing in seconds from creation. Defaults to 10 minutes." + }) + ), + "rate_limits": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RateLimitsParam).annotate({ + "description": "Optional override for per-minute request limits. When omitted, defaults to 10." + }) + ), + "chatkit_configuration": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ChatkitConfigurationParam).annotate({ + "description": "Optional overrides for ChatKit runtime configuration features" + }) + ) +}).annotate({ + "title": "Create chat session request", + "description": "Parameters for provisioning a new ChatKit session.", + "identifier": "CreateChatSessionBody" +}) +export type UserMessageItem = { + readonly "id": string + readonly "object": "chatkit.thread_item" + readonly "created_at": number + readonly "thread_id": string + readonly "type": "chatkit.user_message" + readonly "content": ReadonlyArray + readonly "attachments": ReadonlyArray + readonly "inference_options": InferenceOptions | null +} +export const UserMessageItem = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), + "object": Schema.Literal("chatkit.thread_item").annotate({ + "description": "Type discriminator that is always `chatkit.thread_item`." + }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) for when the item was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), + "type": Schema.Literal("chatkit.user_message"), + "content": Schema.Array( + Schema.Union([UserMessageInputText, UserMessageQuotedText], { mode: "oneOf" }).annotate({ + "description": "Content blocks that comprise a user message." + }) + ).annotate({ "description": "Ordered content elements supplied by the user." }), + "attachments": Schema.Array(Attachment).annotate({ + "description": "Attachments associated with the user message. Defaults to an empty list." + }), + "inference_options": Schema.Union([ + Schema.suspend((): Schema.Codec => InferenceOptions).annotate({ + "description": "Inference overrides applied to the message. Defaults to null when unset." + }), + Schema.Null + ]) +}).annotate({ + "title": "User Message Item", + "description": "User-authored messages within a thread.", + "identifier": "UserMessageItem" +}) +export type ResponseOutputText = { + readonly "type": "output_text" + readonly "text": string + readonly "annotations": ReadonlyArray +} +export const ResponseOutputText = Schema.Struct({ + "type": Schema.Literal("output_text").annotate({ "description": "Type discriminator that is always `output_text`." }), + "text": Schema.String.annotate({ "description": "Assistant generated text." }), + "annotations": Schema.Array( + Schema.Union([FileAnnotation, UrlAnnotation], { mode: "oneOf" }).annotate({ + "description": "Annotation object describing a cited source." + }) + ).annotate({ "description": "Ordered list of annotations attached to the response text." }) +}).annotate({ + "title": "Assistant message content", + "description": "Assistant response text accompanied by optional annotations.", + "identifier": "ResponseOutputText" +}) +export type TaskGroupItem = { + readonly "id": string + readonly "object": "chatkit.thread_item" + readonly "created_at": number + readonly "thread_id": string + readonly "type": "chatkit.task_group" + readonly "tasks": ReadonlyArray +} +export const TaskGroupItem = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), + "object": Schema.Literal("chatkit.thread_item").annotate({ + "description": "Type discriminator that is always `chatkit.thread_item`." + }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) for when the item was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), + "type": Schema.Literal("chatkit.task_group").annotate({ + "description": "Type discriminator that is always `chatkit.task_group`." + }), + "tasks": Schema.Array(TaskGroupTask).annotate({ "description": "Tasks included in the group." }) +}).annotate({ + "title": "Task group", + "description": "Collection of workflow tasks grouped together in the thread.", + "identifier": "TaskGroupItem" +}) +export type ThreadListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const ThreadListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), + "data": Schema.Array(ThreadResource).annotate({ "description": "A list of items" }), + "first_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the first item in the list." }), + Schema.Null + ]), + "last_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the last item in the list." }), + Schema.Null + ]), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) +}).annotate({ + "title": "Threads", + "description": "A paginated list of ChatKit threads.", + "identifier": "ThreadListResource" +}) +export type DecisionInputContentParts = ReadonlyArray +export const DecisionInputContentParts = Schema.Array( + Schema.Union([DecisionInputText, DecisionInputImage], { mode: "oneOf" }) +).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ + "expected": "a value with a length of at most 16384", + "identifier": "DecisionInputContentParts" + }) +) +export type QuestionParamChoice = { + readonly "type": "choice" + readonly "name"?: string + readonly "instructions": string + readonly "choices": ReadonlyArray +} +export const QuestionParamChoice = Schema.Struct({ + "type": Schema.Literal("choice").annotate({ "description": "The type of the object. Always `choice`." }), + "name": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "instructions": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "choices": Schema.Array(ChoiceOptionParam).annotate({ + "description": "Provide between 2 and 255 choices. Each choice must be unique." + }).check(Schema.isMinLength(2).annotate({ "expected": "a value with a length of at least 2" })).check( + Schema.isMaxLength(255).annotate({ "expected": "a value with a length of at most 255" }) + ) +}).annotate({ + "description": "Choose from the supplied options based on the input.", + "identifier": "QuestionParamChoice" +}) +export type AnswerResourceChoice = { + readonly "type": "choice" + readonly "name": string | null + readonly "choice": ChoiceValueResource + readonly "probabilities": ReadonlyArray + readonly "confidence": number +} +export const AnswerResourceChoice = Schema.Struct({ + "type": Schema.Literal("choice").annotate({ "description": "The type of the object. Always `choice`." }), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]), + "choice": ChoiceValueResource, + "probabilities": Schema.Array(ChoiceProbabilityResource).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "confidence": Schema.Finite +}).annotate({ "identifier": "AnswerResourceChoice" }) +export type PublicEnvironmentResource = { + readonly "type": EnvironmentTypeResource + readonly "id": string + readonly "object": "agent.environment" + readonly "status": EnvironmentStatusResource + readonly "files": ReadonlyArray + readonly "skills": ReadonlyArray + readonly "plugins": ReadonlyArray +} +export const PublicEnvironmentResource = Schema.Struct({ + "type": Schema.suspend((): Schema.Codec => EnvironmentTypeResource).annotate({ + "description": "Whether the environment is hosted by OpenAI or by the application." + }), + "id": Schema.String.annotate({ "description": "The ID of the environment." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("agent.environment").annotate({ + "description": "The object type. Always `agent.environment`." + }), + "status": Schema.suspend((): Schema.Codec => EnvironmentStatusResource).annotate({ + "description": "The current environment connection status." + }), + "files": Schema.Array(HostedEnvironmentFileResource).annotate({ + "description": "Files installed in the environment, without their contents." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "skills": Schema.Array(HostedSkillResource).annotate({ + "description": "Skills installed in the environment, without their archive contents." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "plugins": Schema.Array(HostedPluginResource).annotate({ + "description": "Plugins installed in the environment, without their archive contents." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ) +}).annotate({ + "description": "Safe metadata for a first-class execution environment.", + "identifier": "PublicEnvironmentResource" +}) +export type HostedSkillParamInline = { + readonly "type": "inline" + readonly "name": string + readonly "description": string + readonly "source": InlineCapabilitySourceParam +} +export const HostedSkillParamInline = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "The type of the object. Always `inline`." }), + "name": Schema.String.annotate({ "description": "The skill name declared in `SKILL.md`." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "description": Schema.String.annotate({ "description": "The skill description declared in `SKILL.md`." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "source": Schema.suspend((): Schema.Codec => InlineCapabilitySourceParam).annotate({ + "description": "The inline ZIP archive." + }) +}).annotate({ + "description": "Supplies a skill ZIP directly in the session request.", + "identifier": "HostedSkillParamInline" +}) +export type HostedPluginParamInline = { + readonly "type": "inline" + readonly "name": string + readonly "description": string + readonly "source": InlineCapabilitySourceParam +} +export const HostedPluginParamInline = Schema.Struct({ + "type": Schema.Literal("inline").annotate({ "description": "The type of the object. Always `inline`." }), + "name": Schema.String.annotate({ "description": "The plugin name declared in `.codex-plugin/plugin.json`." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "description": Schema.String.annotate({ + "description": "The plugin description declared in `.codex-plugin/plugin.json`." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "source": Schema.suspend((): Schema.Codec => InlineCapabilitySourceParam).annotate({ + "description": "The inline ZIP archive." + }) +}).annotate({ + "description": "Supplies a plugin ZIP directly in the session request.", + "identifier": "HostedPluginParamInline" +}) +export type SubagentResource = { + readonly "id": string + readonly "object": SubagentObjectResource + readonly "session_id": string + readonly "name": string | null + readonly "instructions": ReadonlyArray | null + readonly "parent_agent_id": string + readonly "status": SubagentStatusResource + readonly "opened_at": number + readonly "closed_at": number | null +} +export const SubagentResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the subagent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.suspend((): Schema.Codec => SubagentObjectResource).annotate({ + "description": "The object type. Always `agent.session.subagent`." + }), + "session_id": Schema.String.annotate({ "description": "The ID of the session that owns the subagent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The runner-assigned nickname, or null when unavailable." }), + "instructions": Schema.Union([ + Schema.Array(AgentContentResource).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + Schema.Null + ]).annotate({ + "description": + "Initial task content, or null when unavailable. Text may contain placeholders for images or audio when only a preview is available." + }), + "parent_agent_id": Schema.String.annotate({ "description": "The ID of the agent that created this subagent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => SubagentStatusResource).annotate({ + "description": "The current status of the subagent." + }), + "opened_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the subagent was first opened. Resuming does not change it.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "closed_at": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ + "description": + "The Unix timestamp, in seconds, when the subagent was closed. Null while active, including after resume.", + "format": "int64" + }) +}).annotate({ "description": "A subagent created within a session.", "identifier": "SubagentResource" }) +export type AgentMessageItemResource = { + readonly "id": string + readonly "turn_id": string + readonly "type": "agent_message" + readonly "sender_agent_id": string + readonly "recipient_agent_id": string + readonly "content": ReadonlyArray +} +export const AgentMessageItemResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the message." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "type": Schema.Literal("agent_message").annotate({ "description": "The item type. Always `agent_message`." }), + "sender_agent_id": Schema.String.annotate({ "description": "The ID or name of the sending agent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "recipient_agent_id": Schema.String.annotate({ "description": "The ID or name of the receiving agent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "content": Schema.Array(AgentContentResource).annotate({ "description": "The content exchanged between the agents." }) + .check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ) +}).annotate({ "description": "A message exchanged between agent threads.", "identifier": "AgentMessageItemResource" }) +export type CreateSubagentCallItemResource = { + readonly "type": "create_subagent_call" + readonly "id": string + readonly "turn_id": string + readonly "status": FunctionCallStatusResource + readonly "agent_id": string + readonly "content": ReadonlyArray + readonly "model": string | null + readonly "reasoning_effort": string | null +} +export const CreateSubagentCallItemResource = Schema.Struct({ + "type": Schema.Literal("create_subagent_call").annotate({ + "description": "The item type. Always `create_subagent_call`." + }), + "id": Schema.String.annotate({ "description": "The ID of the tool call item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the tool call." + }), + "agent_id": Schema.String.annotate({ "description": "The ID of the agent that requested the subagent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "content": Schema.Array(AgentContentResource).annotate({ "description": "The task given to the spawned agent." }) + .check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "model": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The model requested for the spawned agent." }), + "reasoning_effort": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The reasoning effort requested for the spawned agent." }) +}).annotate({ "description": "A request to spawn a subagent.", "identifier": "CreateSubagentCallItemResource" }) +export type SendSubagentInputCallItemResource = { + readonly "type": "send_subagent_input_call" + readonly "id": string + readonly "turn_id": string + readonly "status": FunctionCallStatusResource + readonly "sender_agent_id": string + readonly "recipient_agent_id": string + readonly "content": ReadonlyArray +} +export const SendSubagentInputCallItemResource = Schema.Struct({ + "type": Schema.Literal("send_subagent_input_call").annotate({ + "description": "The item type. Always `send_subagent_input_call`." + }), + "id": Schema.String.annotate({ "description": "The ID of the tool call item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the tool call." + }), + "sender_agent_id": Schema.String.annotate({ "description": "The ID of the agent sending the input." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "recipient_agent_id": Schema.String.annotate({ "description": "The ID of the agent receiving the input." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "content": Schema.Array(AgentContentResource).annotate({ "description": "The input sent to the receiving agent." }) + .check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ) +}).annotate({ + "description": "A request to send input to another agent.", + "identifier": "SendSubagentInputCallItemResource" +}) +export type MessageItemResource = { + readonly "type": "message" + readonly "id": string | null + readonly "turn_id": string + readonly "role": SessionMessageRoleResource + readonly "content": ReadonlyArray + readonly "status": OutputItemStatusResource + readonly "phase": MessagePhaseResource | null +} +export const MessageItemResource = Schema.Struct({ + "type": Schema.Literal("message").annotate({ "description": "The item type. Always `message`." }), + "id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of this item, or null for legacy user messages whose ID was not recorded." }), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "role": Schema.suspend((): Schema.Codec => SessionMessageRoleResource).annotate({ + "description": "The role of the message author." + }), + "content": Schema.Array(MessageContentResource).annotate({ + "description": + "The content of the message. User messages contain input text or images; assistant messages contain output text." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "status": Schema.suspend((): Schema.Codec => OutputItemStatusResource).annotate({ + "description": "The status of the message. User messages are always `completed`." + }), + "phase": Schema.Union([MessagePhaseResource, Schema.Null]).annotate({ + "description": "The phase of an assistant message. Null for user messages." + }) +}).annotate({ + "description": "A user or assistant message recorded in a session.", + "identifier": "MessageItemResource" +}) +export type FunctionCallOutputResource = string | ReadonlyArray +export const FunctionCallOutputResource = Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Array(InputContentResource).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })) +], { mode: "oneOf" }).annotate({ + "description": "The text or model-input content supplied as a function result.", + "identifier": "FunctionCallOutputResource" +}) +export type BrowserAuthenticationHistoryRequestKindResource = + BrowserAuthenticationHistoryRequestKindResourceBrowserAuthentication +export const BrowserAuthenticationHistoryRequestKindResource = Schema.Union([ + BrowserAuthenticationHistoryRequestKindResourceBrowserAuthentication +], { mode: "oneOf" }).annotate({ "identifier": "BrowserAuthenticationHistoryRequestKindResource" }) +export type ComputerUseApprovalRequestKindResource = + | ComputerUseApprovalRequestKindResourceBrowserAuthentication + | ComputerUseApprovalRequestKindResourceBrowserOriginAccess +export const ComputerUseApprovalRequestKindResource = Schema.Union([ + ComputerUseApprovalRequestKindResourceBrowserAuthentication, + ComputerUseApprovalRequestKindResourceBrowserOriginAccess +], { mode: "oneOf" }).annotate({ "identifier": "ComputerUseApprovalRequestKindResource" }) +export type ComputerUseApprovalRequestResultItemResource = { + readonly "id": string + readonly "type": "computer_use_approval_request_result" + readonly "turn_id": string + readonly "request_id": string + readonly "response": ComputerUseApprovalResponseKindResource +} +export const ComputerUseApprovalRequestResultItemResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The stable history item ID." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "type": Schema.Literal("computer_use_approval_request_result"), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "request_id": Schema.String.annotate({ "description": "The registered request answered by this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "response": Schema.suspend((): Schema.Codec => + ComputerUseApprovalResponseKindResource + ).annotate({ "description": "The admitted response, without submitted credential values." }) +}).annotate({ + "description": "A credential-free record of an admitted response, not proof of completion.", + "identifier": "ComputerUseApprovalRequestResultItemResource" +}) +export type WebSearchCallItemResource = { + readonly "type": "web_search_call" + readonly "id": string + readonly "turn_id": string + readonly "status": OutputItemStatusResource + readonly "action": WebSearchActionResource | null +} +export const WebSearchCallItemResource = Schema.Struct({ + "type": Schema.Literal("web_search_call").annotate({ "description": "The item type. Always `web_search_call`." }), + "id": Schema.String.annotate({ "description": "The ID of the web search call." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => OutputItemStatusResource).annotate({ + "description": "The status of the web search call." + }), + "action": Schema.Union([WebSearchActionResource, Schema.Null]).annotate({ + "description": "The action performed by the web search tool." + }) +}).annotate({ "description": "A web search call produced by the agent.", "identifier": "WebSearchCallItemResource" }) +export type TurnResource = { + readonly "id": string + readonly "object": TurnObjectResource + readonly "session_id": string + readonly "agent_id": string + readonly "subagent_id": string | null + readonly "status": TurnStatusResource + readonly "created_at": number + readonly "started_at": number | null + readonly "completed_at": number | null + readonly "error": SessionTurnErrorResource | null + readonly "usage": TokenUsageResource | null +} +export const TurnResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the turn." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.suspend((): Schema.Codec => TurnObjectResource).annotate({ + "description": "The object type. Always `agent.session.turn`." + }), + "session_id": Schema.String.annotate({ "description": "The ID of the session that owns the turn." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "agent_id": Schema.String.annotate({ "description": "The ID of the agent that ran the turn." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "subagent_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the subagent that ran the turn, if applicable." }), + "status": Schema.suspend((): Schema.Codec => TurnStatusResource).annotate({ + "description": "The current status of the turn." + }), + "created_at": Schema.Number.annotate({ + "description": + "The Unix timestamp, in seconds, used to order the turn by creation time. Subagent turns use their start time, falling back to completion time or the subagent opening time when the preceding timestamps are unavailable.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "started_at": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ "description": "The Unix timestamp, in seconds, when the turn started.", "format": "int64" }), + "completed_at": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ + "description": "The Unix timestamp, in seconds, when the turn reached a terminal state.", + "format": "int64" + }), + "error": Schema.Union([SessionTurnErrorResource, Schema.Null]).annotate({ + "description": "A customer-safe error. Non-null only for a failed turn." + }), + "usage": Schema.Union([TokenUsageResource, Schema.Null]).annotate({ + "description": "Best-effort token usage for the turn, or null if unknown. Recorded usage may change." + }) +}).annotate({ "description": "The canonical public representation of a session turn.", "identifier": "TurnResource" }) +export type TextResource = { readonly "format": TextFormatResource; readonly "verbosity": VerbosityResource } +export const TextResource = Schema.Struct({ + "format": Schema.suspend((): Schema.Codec => TextFormatResource).annotate({ + "description": "The effective output format. Defaults to ordinary text." + }), + "verbosity": Schema.suspend((): Schema.Codec => VerbosityResource).annotate({ + "description": "The amount of text produced by the agent. Defaults to `medium`." + }) +}).annotate({ "description": "The text configuration used by an agent.", "identifier": "TextResource" }) +export type PersistedAgentToolResourceMcp = { + readonly "type": "mcp" + readonly "server_label": string + readonly "credential_id": string | null + readonly "transport": PersistedMcpTransportResource + readonly "request_metadata": { readonly [x: string]: Schema.Json } + readonly "allowed_tools": ReadonlyArray | null + readonly "required": boolean + readonly "connection_origin": McpConnectionOriginResource +} +export const PersistedAgentToolResourceMcp = Schema.Struct({ + "type": Schema.Literal("mcp").annotate({ "description": "The type of the object. Always `mcp`." }), + "server_label": Schema.String.annotate({ "description": "A label used to identify the MCP server in tool calls." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "credential_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The vault credential selected for this MCP server, if any." }), + "transport": Schema.suspend((): Schema.Codec => PersistedMcpTransportResource) + .annotate({ "description": "The credential-free transport used to connect to the MCP server." }), + "request_metadata": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Metadata included with requests to this MCP server." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + "allowed_tools": Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + Schema.Null + ]).annotate({ "description": "The MCP tools the agent may call, or null when all server tools are allowed." }), + "required": Schema.Boolean.annotate({ + "description": "Whether this MCP server must initialize before the first turn." + }), + "connection_origin": Schema.suspend((): Schema.Codec => McpConnectionOriginResource) + .annotate({ "description": "Where outbound MCP HTTP connections originate." }) +}).annotate({ + "description": "Tools provided by a remote MCP server without stored credentials.", + "identifier": "PersistedAgentToolResourceMcp" +}) +export type UpdateSessionAgentParam = { + readonly "model"?: string + readonly "reasoning"?: UpdateSessionReasoningParam + readonly "service_tier"?: ServiceTierParam | null +} +export const UpdateSessionAgentParam = Schema.Struct({ + "model": Schema.optionalKey( + Schema.String.annotate({ "description": "The model for subsequent turns. Omit to keep the current model." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "reasoning": Schema.optionalKey( + Schema.suspend((): Schema.Codec => UpdateSessionReasoningParam).annotate({ + "description": "Reasoning settings to update. Omit to keep the current effort." + }) + ), + "service_tier": Schema.optionalKey( + Schema.Union([ServiceTierParam, Schema.Null]).annotate({ + "description": "Omit to keep the current tier. Null resets it to auto." + }) + ) +}).annotate({ + "description": "Model settings that can change after session creation.", + "identifier": "UpdateSessionAgentParam" +}) +export type TextParam = { readonly "format"?: TextFormatParam | null; readonly "verbosity"?: VerbosityParam | null } +export const TextParam = Schema.Struct({ + "format": Schema.optionalKey( + Schema.Union([TextFormatParam, Schema.Null]).annotate({ + "description": "The output format. Omission uses ordinary text (`{\"type\": \"text\"}`)." + }) + ), + "verbosity": Schema.optionalKey( + Schema.Union([VerbosityParam, Schema.Null]).annotate({ + "description": "The amount of text the model should produce. Defaults to `medium`, matching Responses." + }) + ) +}).annotate({ "description": "Configuration for text generated by the agent.", "identifier": "TextParam" }) +export type PersistedAgentToolConfigParamMcp = { + readonly "type": "mcp" + readonly "server_label": string + readonly "credential_id"?: string | null + readonly "transport": PersistedMcpTransportConfigParam + readonly "request_metadata"?: { readonly [x: string]: Schema.Json } | null + readonly "allowed_tools"?: ReadonlyArray | null + readonly "required"?: boolean + readonly "connection_origin"?: McpConnectionOriginParam | null +} +export const PersistedAgentToolConfigParamMcp = Schema.Struct({ + "type": Schema.Literal("mcp").annotate({ "description": "The type of the object. Always `mcp`." }), + "server_label": Schema.String.annotate({ "description": "A label used to identify the MCP server in tool calls." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "credential_id": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "The vault credential selected for this MCP server. Optional when exactly one attached credential matches the server URL." + }) + ), + "transport": Schema.suspend((): Schema.Codec => PersistedMcpTransportConfigParam) + .annotate({ "description": "The credential-free transport used to connect to the MCP server." }), + "request_metadata": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).check( + Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" }) + ).check(Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ "description": "Metadata included with requests to this MCP server." }) + ), + "allowed_tools": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "The MCP tools the agent may call. All server tools are allowed when omitted." }) + ), + "required": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether this MCP server must initialize before the first turn. Defaults to `false`." + }) + ), + "connection_origin": Schema.optionalKey( + Schema.Union([McpConnectionOriginParam, Schema.Null]).annotate({ + "description": "Selects where outbound MCP HTTP connections originate." + }) + ) +}).annotate({ + "description": "Tools provided by a remote MCP server without stored credentials.", + "identifier": "PersistedAgentToolConfigParamMcp" +}) +export type EnvironmentResourceOpenaiHosted = { + readonly "type": "openai_hosted" + readonly "id": string + readonly "container_size"?: ContainerSizeResource | null + readonly "packages": EnvironmentPackagesResource + readonly "network": NetworkPolicyResource + readonly "desktop": DesktopResource + readonly "capability_directories": ReadonlyArray + readonly "skills": ReadonlyArray + readonly "plugins": ReadonlyArray + readonly "files": ReadonlyArray +} +export const EnvironmentResourceOpenaiHosted = Schema.Struct({ + "type": Schema.Literal("openai_hosted").annotate({ + "description": "The type of the object. Always `openai_hosted`." + }), + "id": Schema.String.annotate({ "description": "The public ID of the environment." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "container_size": Schema.optionalKey( + Schema.Union([ContainerSizeResource, Schema.Null]).annotate({ + "description": "The effective CPU and memory tier, or null when unknown or outside the public tiers." + }) + ), + "packages": Schema.suspend((): Schema.Codec => EnvironmentPackagesResource).annotate({ + "description": "Packages installed in the environment." + }), + "network": Schema.suspend((): Schema.Codec => NetworkPolicyResource).annotate({ + "description": "The effective network access policy for the environment." + }), + "desktop": Schema.suspend((): Schema.Codec => DesktopResource).annotate({ + "description": "The effective desktop configuration." + }), + "capability_directories": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Directories that contain capabilities exposed to the agent." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "skills": Schema.Array(HostedSkillResource).annotate({ + "description": "Skills installed in the environment, excluding their archive contents." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "plugins": Schema.Array(HostedPluginResource).annotate({ + "description": "Plugins installed in the environment, excluding their archive contents." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "files": Schema.Array(HostedEnvironmentFileResource).annotate({ + "description": "Files available in the environment, excluding their contents." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" }) + ) +}).annotate({ "description": "An environment hosted by OpenAI.", "identifier": "EnvironmentResourceOpenaiHosted" }) +export type EnvironmentTemplateResource = { + readonly "id": string + readonly "name": string | null + readonly "object": "agent.environment.template" + readonly "created_at": number + readonly "updated_at": number + readonly "packages": EnvironmentPackagesResource + readonly "network": NetworkPolicyResource + readonly "desktop": DesktopResource + readonly "capability_directories": ReadonlyArray + readonly "skills": ReadonlyArray + readonly "plugins": ReadonlyArray + readonly "files": ReadonlyArray +} +export const EnvironmentTemplateResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the reusable environment template." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "An optional human-readable display name for the template." }), + "object": Schema.Literal("agent.environment.template").annotate({ + "description": "The object type. Always `agent.environment.template`." + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the template was created.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "updated_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the template was last updated.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "packages": Schema.suspend((): Schema.Codec => EnvironmentPackagesResource).annotate({ + "description": "Packages installed in each fresh OpenAI-hosted environment." + }), + "network": Schema.suspend((): Schema.Codec => NetworkPolicyResource).annotate({ + "description": "Runtime network access for each OpenAI-hosted environment." + }), + "desktop": Schema.suspend((): Schema.Codec => DesktopResource).annotate({ + "description": "Desktop configuration for each OpenAI-hosted environment." + }), + "capability_directories": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Directories that expose capabilities to the agent." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "skills": Schema.Array(HostedTemplateSkillResource).annotate({ + "description": "Safe skill metadata, preserving unresolved version selectors." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" }) + ), + "plugins": Schema.Array(HostedPluginResource).annotate({ + "description": "Safe plugin metadata, excluding inline archive contents." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(32).annotate({ "expected": "a value with a length of at most 32" }) + ), + "files": Schema.Array(HostedTemplateFileResource).annotate({ + "description": "Safe file metadata, excluding contents and session-scoped file IDs." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" }) + ) +}).annotate({ + "description": "Reusable configuration that provisions a fresh OpenAI-hosted environment for each session.", + "identifier": "EnvironmentTemplateResource" +}) +export type AgentToolResourceMcp = { + readonly "type": "mcp" + readonly "server_label": string + readonly "credential_id": string | null + readonly "transport": McpTransportResource + readonly "request_metadata": { readonly [x: string]: Schema.Json } + readonly "allowed_tools": ReadonlyArray | null + readonly "required": boolean + readonly "connection_origin": McpConnectionOriginResource +} +export const AgentToolResourceMcp = Schema.Struct({ + "type": Schema.Literal("mcp").annotate({ "description": "The type of the object. Always `mcp`." }), + "server_label": Schema.String.annotate({ "description": "A label used to identify the MCP server in tool calls." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "credential_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The attached vault credential selected for this MCP server, if any. Optional when exactly one attached credential matches the server URL." + }), + "transport": Schema.suspend((): Schema.Codec => McpTransportResource).annotate({ + "description": "The transport used to connect to the MCP server." + }), + "request_metadata": Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Metadata included with requests to this MCP server." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + "allowed_tools": Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + Schema.Null + ]).annotate({ "description": "The MCP tools the agent may call." }), + "required": Schema.Boolean.annotate({ + "description": "Whether this MCP server must initialize before the first turn." + }), + "connection_origin": Schema.suspend((): Schema.Codec => McpConnectionOriginResource) + .annotate({ "description": "Where outbound MCP HTTP connections originate." }) +}).annotate({ "description": "Tools provided by a remote MCP server.", "identifier": "AgentToolResourceMcp" }) +export type AgentToolConfigParamMcp = { + readonly "type": "mcp" + readonly "server_label": string + readonly "credential_id"?: string | null + readonly "transport": McpTransportConfigParam + readonly "request_metadata"?: { readonly [x: string]: Schema.Json } | null + readonly "allowed_tools"?: ReadonlyArray | null + readonly "required"?: boolean + readonly "connection_origin"?: McpConnectionOriginParam | null +} +export const AgentToolConfigParamMcp = Schema.Struct({ + "type": Schema.Literal("mcp").annotate({ "description": "The type of the object. Always `mcp`." }), + "server_label": Schema.String.annotate({ "description": "A label used to identify the MCP server in tool calls." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "credential_id": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "The attached vault credential used to authenticate this MCP server. Optional when exactly one attached credential matches the server URL." + }) + ), + "transport": Schema.suspend((): Schema.Codec => McpTransportConfigParam).annotate({ + "description": "The transport used to connect to the MCP server." + }), + "request_metadata": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).check( + Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" }) + ).check(Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" })).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ "description": "Metadata included with requests to this MCP server." }) + ), + "allowed_tools": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "The MCP tools the agent may call. All server tools are allowed when omitted." }) + ), + "required": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether this MCP server must initialize before the first turn. Defaults to `false`." + }) + ), + "connection_origin": Schema.optionalKey( + Schema.Union([McpConnectionOriginParam, Schema.Null]).annotate({ + "description": + "Selects where outbound MCP HTTP connections originate. Omitted or `service` uses the Managed Agents service network; `environment` uses the session's selected environment." + }) + ) +}).annotate({ "description": "Tools provided by a remote MCP server.", "identifier": "AgentToolConfigParamMcp" }) +export type InputMessageParam = { + readonly "type"?: "message" + readonly "role": "user" + readonly "content": ReadonlyArray +} +export const InputMessageParam = Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("message").annotate({ "description": "The type of the input item. Always `message`." }) + ), + "role": Schema.Literal("user").annotate({ "description": "The role of the message author. Always `user`." }), + "content": Schema.Array(InputContentParam).annotate({ "description": "The content of the message." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" })) +}).annotate({ "description": "A user message submitted to a session.", "identifier": "InputMessageParam" }) +export type FunctionCallOutputParam = string | ReadonlyArray +export const FunctionCallOutputParam = Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + Schema.Array(InputContentParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" })) +], { mode: "oneOf" }).annotate({ + "description": "A function result represented as text or supported model-input content.", + "identifier": "FunctionCallOutputParam" +}) +export type SessionEventAgentSessionEnvironmentReady = { + readonly "type": "agent.session.environment.ready" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "environment": SessionEnvironmentStateResource +} +export const SessionEventAgentSessionEnvironmentReady = Schema.Struct({ + "type": Schema.Literal("agent.session.environment.ready").annotate({ + "description": "The type of the object. Always `agent.session.environment.ready`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "environment": Schema.suspend((): Schema.Codec => SessionEnvironmentStateResource) + .annotate({ "description": "The current environment state." }) +}).annotate({ + "description": "Emitted when a hosted session environment is ready to connect.", + "identifier": "SessionEventAgentSessionEnvironmentReady" +}) +export type SessionEventAgentSessionEnvironmentSuspended = { + readonly "type": "agent.session.environment.suspended" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "environment": SessionEnvironmentStateResource +} +export const SessionEventAgentSessionEnvironmentSuspended = Schema.Struct({ + "type": Schema.Literal("agent.session.environment.suspended").annotate({ + "description": "The type of the object. Always `agent.session.environment.suspended`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "environment": Schema.suspend((): Schema.Codec => SessionEnvironmentStateResource) + .annotate({ "description": "The current environment state." }) +}).annotate({ + "description": "Emitted after an idle hosted session environment is checkpointed and stopped.", + "identifier": "SessionEventAgentSessionEnvironmentSuspended" +}) +export type SessionEventAgentSessionEnvironmentExpired = { + readonly "type": "agent.session.environment.expired" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "environment": SessionEnvironmentStateResource +} +export const SessionEventAgentSessionEnvironmentExpired = Schema.Struct({ + "type": Schema.Literal("agent.session.environment.expired").annotate({ + "description": "The type of the object. Always `agent.session.environment.expired`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "environment": Schema.suspend((): Schema.Codec => SessionEnvironmentStateResource) + .annotate({ "description": "The current environment state." }) +}).annotate({ + "description": "Emitted after a suspended hosted session environment and its checkpoint expire.", + "identifier": "SessionEventAgentSessionEnvironmentExpired" +}) +export type SessionEventAgentSessionEnvironmentPending = { + readonly "type": "agent.session.environment.pending" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "environment": SessionEnvironmentStateResource +} +export const SessionEventAgentSessionEnvironmentPending = Schema.Struct({ + "type": Schema.Literal("agent.session.environment.pending").annotate({ + "description": "The type of the object. Always `agent.session.environment.pending`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "environment": Schema.suspend((): Schema.Codec => SessionEnvironmentStateResource) + .annotate({ "description": "The current environment state." }) +}).annotate({ + "description": "Emitted while a session environment is being prepared.", + "identifier": "SessionEventAgentSessionEnvironmentPending" +}) +export type SessionEventAgentSessionEnvironmentConnected = { + readonly "type": "agent.session.environment.connected" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "environment": SessionEnvironmentStateResource +} +export const SessionEventAgentSessionEnvironmentConnected = Schema.Struct({ + "type": Schema.Literal("agent.session.environment.connected").annotate({ + "description": "The type of the object. Always `agent.session.environment.connected`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "environment": Schema.suspend((): Schema.Codec => SessionEnvironmentStateResource) + .annotate({ "description": "The current environment state." }) +}).annotate({ + "description": "Emitted when a session environment connects.", + "identifier": "SessionEventAgentSessionEnvironmentConnected" +}) +export type SessionEventAgentSessionEnvironmentDisconnected = { + readonly "type": "agent.session.environment.disconnected" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "environment": SessionEnvironmentStateResource +} +export const SessionEventAgentSessionEnvironmentDisconnected = Schema.Struct({ + "type": Schema.Literal("agent.session.environment.disconnected").annotate({ + "description": "The type of the object. Always `agent.session.environment.disconnected`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "environment": Schema.suspend((): Schema.Codec => SessionEnvironmentStateResource) + .annotate({ "description": "The current environment state." }) +}).annotate({ + "description": "Emitted when a session environment disconnects.", + "identifier": "SessionEventAgentSessionEnvironmentDisconnected" +}) +export type SessionEventAgentSessionEnvironmentFailed = { + readonly "type": "agent.session.environment.failed" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "environment": SessionEnvironmentStateResource +} +export const SessionEventAgentSessionEnvironmentFailed = Schema.Struct({ + "type": Schema.Literal("agent.session.environment.failed").annotate({ + "description": "The type of the object. Always `agent.session.environment.failed`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "environment": Schema.suspend((): Schema.Codec => SessionEnvironmentStateResource) + .annotate({ "description": "The current environment state." }) +}).annotate({ + "description": "Emitted when a session environment fails.", + "identifier": "SessionEventAgentSessionEnvironmentFailed" +}) +export type ComputerUseApprovalResponseParam = + | ComputerUseApprovalResponseParamBrowserAuthentication + | ComputerUseApprovalResponseParamBrowserOriginAccessParam +export const ComputerUseApprovalResponseParam = Schema.Union([ + ComputerUseApprovalResponseParamBrowserAuthentication, + ComputerUseApprovalResponseParamBrowserOriginAccessParam +], { mode: "oneOf" }).annotate({ "identifier": "ComputerUseApprovalResponseParam" }) +export type McpOauthRefreshResource = { + readonly "token_endpoint": string + readonly "client_id": string + readonly "resource": string | null + readonly "scope": string | null + readonly "token_endpoint_auth": McpOauthTokenEndpointAuthResource +} +export const McpOauthRefreshResource = Schema.Struct({ + "token_endpoint": Schema.String.annotate({ "description": "The HTTPS OAuth token endpoint used for refresh." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "client_id": Schema.String.annotate({ "description": "The OAuth client ID used when requesting a new access token." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "resource": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The resource URI sent to the OAuth token endpoint during refresh, if configured." }), + "scope": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "Space-separated OAuth scopes requested during refresh, if configured." }), + "token_endpoint_auth": Schema.suspend((): Schema.Codec => + McpOauthTokenEndpointAuthResource + ).annotate({ + "description": "How the OAuth client authenticates to the token endpoint, excluding its client secret." + }) +}).annotate({ + "description": "Configuration used to refresh an MCP OAuth access token, excluding secret values.", + "identifier": "McpOauthRefreshResource" +}) +export type VaultCredentialAuthResourceEnvironmentVariable = { + readonly "type": "environment_variable" + readonly "secret_name": string + readonly "networking": VaultCredentialNetworkingResource +} +export const VaultCredentialAuthResourceEnvironmentVariable = Schema.Struct({ + "type": Schema.Literal("environment_variable").annotate({ + "description": "The type of the object. Always `environment_variable`." + }), + "secret_name": Schema.String.annotate({ + "description": "The environment variable name that receives the placeholder in the sandbox." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "networking": Schema.suspend((): Schema.Codec => VaultCredentialNetworkingResource) + .annotate({ + "description": + "The destinations where the proxy can substitute the secret, subject to the environment network policy." + }) +}).annotate({ + "description": + "Metadata for an HTTP credential used only in OpenAI-hosted environments. Sandbox code receives a placeholder. The proxy substitutes the secret for allowed HTTPS destinations on ports 443 and 8443. The real secret is not available to sandbox code for local computation and is never returned in this resource.", + "identifier": "VaultCredentialAuthResourceEnvironmentVariable" +}) +export type CreateMcpOauthRefreshParam = { + readonly "token_endpoint": string + readonly "client_id": string + readonly "resource"?: string | null + readonly "scope"?: string | null + readonly "refresh_token": string + readonly "token_endpoint_auth": CreateMcpOauthTokenEndpointAuthParam +} +export const CreateMcpOauthRefreshParam = Schema.Struct({ + "token_endpoint": Schema.String.annotate({ + "description": "The HTTPS OAuth token endpoint used to exchange the refresh token for a new access token." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "client_id": Schema.String.annotate({ "description": "The OAuth client ID used when requesting a new access token." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "resource": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The resource URI to send to the OAuth token endpoint during refresh, if required." }) + ), + "scope": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "Space-separated OAuth scopes to request during refresh, if required." }) + ), + "refresh_token": Schema.String.annotate({ + "description": "The refresh token to store. This secret is never returned in credential resources." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "token_endpoint_auth": Schema.suspend((): Schema.Codec => + CreateMcpOauthTokenEndpointAuthParam + ).annotate({ "description": "How the OAuth client authenticates to the token endpoint." }) +}).annotate({ + "description": "Configuration for refreshing the access token of an MCP OAuth credential.", + "identifier": "CreateMcpOauthRefreshParam" +}) +export type CreateVaultCredentialAuthParamEnvironmentVariable = { + readonly "type": "environment_variable" + readonly "secret_name": string + readonly "secret_value": string + readonly "networking": VaultCredentialNetworkingParam +} +export const CreateVaultCredentialAuthParamEnvironmentVariable = Schema.Struct({ + "type": Schema.Literal("environment_variable").annotate({ + "description": "The type of the object. Always `environment_variable`." + }), + "secret_name": Schema.String.annotate({ + "description": + "The environment variable name that receives the placeholder, such as `SERVICE_API_KEY`. Use ASCII letters, digits, and underscores, starting with a letter or underscore. Names starting with `CODEX_` and managed proxy or certificate variable names are reserved." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "secret_value": Schema.String.annotate({ + "description": + "The write-only secret to store. Never returned in credential resources or supplied directly to sandbox code. Must be nonempty and must not contain carriage returns, newlines, or NUL bytes." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "networking": Schema.suspend((): Schema.Codec => VaultCredentialNetworkingParam) + .annotate({ + "description": + "The destinations where the proxy can substitute this secret. The environment network policy must also allow them." + }) +}).annotate({ + "description": + "An HTTP credential for OpenAI-hosted environments only. The sandbox receives an environment variable containing a placeholder, not the secret. Use the placeholder unchanged in outgoing requests. The egress proxy replaces the placeholder with the secret for allowed HTTPS destinations on ports 443 and 8443. Sandbox code cannot read the real secret or use it for local computation, such as signing a request.", + "identifier": "CreateVaultCredentialAuthParamEnvironmentVariable" +}) +export type RotateMcpOauthRefreshParam = { + readonly "refresh_token"?: string | null + readonly "scope"?: string | null + readonly "token_endpoint_auth"?: RotateMcpOauthTokenEndpointAuthParam | null +} +export const RotateMcpOauthRefreshParam = Schema.Struct({ + "refresh_token": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "The replacement refresh token. Omit or pass `null` to keep the stored token. This secret is never returned in resources." + }) + ), + "scope": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "Replacement space-separated OAuth scopes for refresh requests. Omit to keep the scopes, or pass `null` to stop sending a scope parameter." + }) + ), + "token_endpoint_auth": Schema.optionalKey( + Schema.Union([RotateMcpOauthTokenEndpointAuthParam, Schema.Null]).annotate({ + "description": "Client-secret updates for the existing token endpoint authentication method." + }) + ) +}).annotate({ + "description": "Updates to an MCP credential's existing OAuth refresh configuration.", + "identifier": "RotateMcpOauthRefreshParam" +}) +export type BetaModelIdsCompaction = BetaModelIdsResponses | string | null +export const BetaModelIdsCompaction = Schema.Union([BetaModelIdsResponses, Schema.String, Schema.Null]).annotate({ + "description": + "Model ID used to generate the response, like `gpt-6-astra`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models) to browse and compare available models.", + "identifier": "BetaModelIdsCompaction" +}) +export type BetaTextResponseFormatConfiguration = + | BetaResponseFormatText + | BetaTextResponseFormatJsonSchema + | BetaResponseFormatJsonObject +export const BetaTextResponseFormatConfiguration = Schema.Union([ + BetaResponseFormatText, + BetaTextResponseFormatJsonSchema, + BetaResponseFormatJsonObject +], { mode: "oneOf" }).annotate({ + "description": + "An object specifying the format that the model must output.\n\nConfiguring `{ \"type\": \"json_schema\" }` enables Structured Outputs,\nwhich ensures the model will match your supplied JSON schema. Learn more in the\n[Structured Outputs guide](https://developers.openai.com/api/docs/guides/structured-outputs).\n\nThe default format is `{ \"type\": \"text\" }` with no additional options.\n\n**Not recommended for gpt-4o and newer models:**\n\nSetting to `{ \"type\": \"json_object\" }` enables the older JSON mode, which\nensures the message the model generates is valid JSON. Using `json_schema`\nis preferred for models that support it.\n", + "identifier": "BetaTextResponseFormatConfiguration" +}) +export type BetaFileSearchTool = { + readonly "type": "file_search" + readonly "vector_store_ids": ReadonlyArray + readonly "max_num_results"?: number + readonly "ranking_options"?: BetaRankingOptions + readonly "filters"?: BetaFilters | null +} +export const BetaFileSearchTool = Schema.Struct({ + "type": Schema.Literal("file_search").annotate({ + "description": "The type of the file search tool. Always `file_search`." + }), + "vector_store_ids": Schema.Array(Schema.String).annotate({ + "description": "The IDs of the vector stores to search." + }), + "max_num_results": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum number of results to return. This number should be between 1 and 50 inclusive." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "ranking_options": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaRankingOptions).annotate({ + "description": "Ranking options for search." + }) + ), + "filters": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaFilters).annotate({ "description": "A filter to apply." }), + Schema.Null + ]) + ) +}).annotate({ + "title": "File search", + "description": + "A tool that searches for relevant content from uploaded files. Learn more about the [file search tool](https://developers.openai.com/api/docs/guides/tools-file-search).", + "identifier": "BetaFileSearchTool" +}) +export type BetaAutoCodeInterpreterToolParam = { + readonly "type": "auto" + readonly "file_ids"?: ReadonlyArray + readonly "memory_limit"?: BetaContainerMemoryLimit | null + readonly "network_policy"?: BetaContainerNetworkPolicyDisabledParam | BetaContainerNetworkPolicyAllowlistParam +} +export const BetaAutoCodeInterpreterToolParam = Schema.Struct({ + "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }), + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "An optional list of uploaded files to make available to your code." + }).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })) + ), + "memory_limit": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaContainerMemoryLimit).annotate({ + "description": "The memory limit for the code interpreter container." + }), + Schema.Null + ]) + ), + "network_policy": Schema.optionalKey( + Schema.Union([BetaContainerNetworkPolicyDisabledParam, BetaContainerNetworkPolicyAllowlistParam], { mode: "oneOf" }) + .annotate({ "description": "Network access policy for the container." }) + ) +}).annotate({ + "title": "CodeInterpreterToolAuto", + "description": + "Configuration for a code interpreter container. Optionally specify the IDs of the files to run the code on.", + "identifier": "BetaAutoCodeInterpreterToolParam" +}) +export type BetaContainerAutoParam = { + readonly "type": "container_auto" + readonly "file_ids"?: ReadonlyArray + readonly "memory_limit"?: BetaContainerMemoryLimit | null + readonly "network_policy"?: BetaContainerNetworkPolicyDisabledParam | BetaContainerNetworkPolicyAllowlistParam + readonly "skills"?: ReadonlyArray +} +export const BetaContainerAutoParam = Schema.Struct({ + "type": Schema.Literal("container_auto").annotate({ + "description": "Automatically creates a container for this request" + }), + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "An optional list of uploaded files to make available to your code." + }).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })) + ), + "memory_limit": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaContainerMemoryLimit).annotate({ + "description": "The memory limit for the container." + }), + Schema.Null + ]) + ), + "network_policy": Schema.optionalKey( + Schema.Union([BetaContainerNetworkPolicyDisabledParam, BetaContainerNetworkPolicyAllowlistParam], { mode: "oneOf" }) + .annotate({ "description": "Network access policy for the container." }) + ), + "skills": Schema.optionalKey( + Schema.Array(Schema.Union([BetaSkillReferenceParam, BetaInlineSkillParam], { mode: "oneOf" })).annotate({ + "description": "An optional list of skills referenced by id or inline data." + }).check(Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" })) + ) +}).annotate({ "identifier": "BetaContainerAutoParam" }) +export type BetaCustomToolParam = { + readonly "type": "custom" + readonly "name": string + readonly "async"?: boolean + readonly "description"?: string + readonly "format"?: BetaCustomTextFormatParam | BetaCustomGrammarFormatParam + readonly "defer_loading"?: boolean + readonly "allowed_callers"?: ReadonlyArray | null +} +export const BetaCustomToolParam = Schema.Struct({ + "type": Schema.Literal("custom").annotate({ "description": "The type of the custom tool. Always `custom`." }), + "name": Schema.String.annotate({ "description": "The name of the custom tool, used to identify it in tool calls." }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Whether the tool response can be returned asynchronously versus immediately returned on next response creation." + }) + ), + "description": Schema.optionalKey( + Schema.String.annotate({ "description": "Optional description of the custom tool, used to provide more context." }) + ), + "format": Schema.optionalKey( + Schema.Union([BetaCustomTextFormatParam, BetaCustomGrammarFormatParam], { mode: "oneOf" }).annotate({ + "description": "The input format for the custom tool. Default is unconstrained text." + }) + ), + "defer_loading": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether this tool should be deferred and discovered via tool search." }) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaCallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ + "title": "Custom tool", + "description": + "A custom tool that processes input using a specified format. Learn more about [custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools)", + "identifier": "BetaCustomToolParam" +}) +export type BetaResponsePromptVariables = { + readonly [x: string]: string | BetaInputTextContent | BetaInputImageContent | BetaInputFileContent +} | null +export const BetaResponsePromptVariables = Schema.Union([ + Schema.Record( + Schema.String, + Schema.Union([Schema.String, BetaInputTextContent, BetaInputImageContent, BetaInputFileContent], { mode: "oneOf" }) + ).annotate({ + "title": "Prompt Variables", + "description": + "Optional map of values to substitute in for variables in your\nprompt. The substitution values can either be strings, or other\nResponse input types like images or files.\n" + }), + Schema.Null +]).annotate({ "identifier": "BetaResponsePromptVariables" }) +export type BetaInputContent = BetaInputTextContent | BetaInputImageContent | BetaInputFileContent +export const BetaInputContent = Schema.Union([BetaInputTextContent, BetaInputImageContent, BetaInputFileContent], { + mode: "oneOf" +}).annotate({ "identifier": "BetaInputContent" }) +export type BetaFunctionAndCustomToolCallOutput = BetaInputTextContent | BetaInputImageContent | BetaInputFileContent +export const BetaFunctionAndCustomToolCallOutput = Schema.Union([ + BetaInputTextContent, + BetaInputImageContent, + BetaInputFileContent +], { mode: "oneOf" }).annotate({ "identifier": "BetaFunctionAndCustomToolCallOutput" }) +export type BetaResponseOutputTextAnnotationAddedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.output_text.annotation.added" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "annotation_index": number + readonly "sequence_number": number + readonly "annotation": BetaAnnotation | null +} +export const BetaResponseOutputTextAnnotationAddedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.output_text.annotation.added").annotate({ + "description": "The type of the event. Always 'response.output_text.annotation.added'." + }), + "item_id": Schema.String.annotate({ + "description": "The unique identifier of the item to which the annotation is being added." + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the response's output array." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ "description": "The index of the content part within the output item." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "annotation_index": Schema.Number.annotate({ "description": "The index of the annotation within the content part." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "annotation": Schema.Union([BetaAnnotation, Schema.Null]).annotate({ + "description": "The annotation object being added. (See annotation schema for details.)" + }) +}).annotate({ + "title": "ResponseOutputTextAnnotationAddedEvent", + "description": "Emitted when an annotation is added to output text content.\n", + "identifier": "BetaResponseOutputTextAnnotationAddedEvent" +}) +export type BetaOutputTextContent = { + readonly "type": "output_text" + readonly "text": string + readonly "annotations": ReadonlyArray + readonly "logprobs": ReadonlyArray +} +export const BetaOutputTextContent = Schema.Struct({ + "type": Schema.Literal("output_text").annotate({ + "description": "The type of the output text. Always `output_text`." + }), + "text": Schema.String.annotate({ "description": "The text output from the model." }), + "annotations": Schema.Array(BetaAnnotation).annotate({ "description": "The annotations of the text output." }), + "logprobs": Schema.Array(BetaLogProb) +}).annotate({ + "title": "Output text", + "description": "A text output from the model.", + "identifier": "BetaOutputTextContent" +}) +export type BetaComputerAction = + | BetaClickParam + | BetaDoubleClickAction + | BetaDragParam + | BetaKeyPressAction + | BetaMoveParam + | BetaScreenshotParam + | BetaScrollParam + | BetaTypeParam + | BetaWaitParam +export const BetaComputerAction = Schema.Union([ + BetaClickParam, + BetaDoubleClickAction, + BetaDragParam, + BetaKeyPressAction, + BetaMoveParam, + BetaScreenshotParam, + BetaScrollParam, + BetaTypeParam, + BetaWaitParam +], { mode: "oneOf" }).annotate({ "identifier": "BetaComputerAction" }) +export type BetaFunctionToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "id"?: string + readonly "type": "function_call" + readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "arguments": string + readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "async"?: boolean +} +export const BetaFunctionToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the function tool call.\n" })), + "type": Schema.Literal("function_call").annotate({ + "description": "The type of the function tool call. Always `function_call`.\n" + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the function tool call generated by the model.\n" + }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey(Schema.String.annotate({ "description": "The namespace of the function to run.\n" })), + "name": Schema.String.annotate({ "description": "The name of the function to run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments to pass to the function.\n" }), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the function tool call runs asynchronously.\n" }) + ) +}).annotate({ + "title": "Function tool call", + "description": + "A tool call to run a function. See the\n[function calling guide](https://developers.openai.com/api/docs/guides/function-calling) for more information.\n", + "identifier": "BetaFunctionToolCall" +}) +export type BetaFunctionShellCall = { + readonly "agent"?: BetaAgentTag + readonly "type": "shell_call" + readonly "id": string + readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null + readonly "action": BetaFunctionShellAction + readonly "status": BetaFunctionShellCallStatus + readonly "environment": BetaLocalEnvironmentResource | BetaContainerReferenceResource | null + readonly "created_by"?: string +} +export const BetaFunctionShellCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("shell_call").annotate({ "description": "The type of the item. Always `shell_call`." }), + "id": Schema.String.annotate({ + "description": "The unique ID of the shell tool call. Populated when this item is returned via API." + }), + "call_id": Schema.String.annotate({ "description": "The unique ID of the shell tool call generated by the model." }), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaToolCallCaller).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "action": Schema.suspend((): Schema.Codec => BetaFunctionShellAction).annotate({ + "description": "The shell commands and limits that describe how to run the tool call." + }), + "status": Schema.suspend((): Schema.Codec => BetaFunctionShellCallStatus).annotate({ + "description": "The status of the shell call. One of `in_progress`, `completed`, or `incomplete`." + }), + "environment": Schema.Union([ + Schema.Union([BetaLocalEnvironmentResource, BetaContainerReferenceResource], { mode: "oneOf" }), + Schema.Null + ]), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the entity that created this tool call." }) + ) +}).annotate({ + "title": "Shell tool call", + "description": "A tool call that executes one or more shell commands in a managed environment.", + "identifier": "BetaFunctionShellCall" +}) +export type BetaApplyPatchToolCall = { + readonly "agent"?: BetaAgentTag + readonly "type": "apply_patch_call" + readonly "id": string + readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null + readonly "status": BetaApplyPatchCallStatus + readonly "operation": + | BetaApplyPatchCreateFileOperation + | BetaApplyPatchDeleteFileOperation + | BetaApplyPatchUpdateFileOperation + readonly "created_by"?: string +} +export const BetaApplyPatchToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("apply_patch_call").annotate({ + "description": "The type of the item. Always `apply_patch_call`." + }), + "id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call. Populated when this item is returned via API." + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call generated by the model." + }), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaToolCallCaller).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.suspend((): Schema.Codec => BetaApplyPatchCallStatus).annotate({ + "description": "The status of the apply patch tool call. One of `in_progress` or `completed`." + }), + "operation": Schema.Union([ + BetaApplyPatchCreateFileOperation, + BetaApplyPatchDeleteFileOperation, + BetaApplyPatchUpdateFileOperation + ], { mode: "oneOf" }).annotate({ + "title": "Apply patch operation", + "description": "One of the create_file, delete_file, or update_file operations applied via apply_patch." + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the entity that created this tool call." }) + ) +}).annotate({ + "title": "Apply patch tool call", + "description": "A tool call that applies file diffs by creating, deleting, or updating files.", + "identifier": "BetaApplyPatchToolCall" +}) +export type BetaApplyPatchToolCallOutput = { + readonly "agent"?: BetaAgentTag + readonly "type": "apply_patch_call_output" + readonly "id": string + readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null + readonly "status": BetaApplyPatchCallOutputStatus + readonly "output"?: string | null + readonly "created_by"?: string +} +export const BetaApplyPatchToolCallOutput = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("apply_patch_call_output").annotate({ + "description": "The type of the item. Always `apply_patch_call_output`." + }), + "id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call output. Populated when this item is returned via API." + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call generated by the model." + }), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaToolCallCaller).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.suspend((): Schema.Codec => BetaApplyPatchCallOutputStatus).annotate( + { "description": "The status of the apply patch tool call output. One of `completed` or `failed`." } + ), + "output": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Optional textual output returned by the apply patch tool." }), + Schema.Null + ]) + ), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the entity that created this tool call output." }) + ) +}).annotate({ + "title": "Apply patch tool call output", + "description": "The output emitted by an apply patch tool call.", + "identifier": "BetaApplyPatchToolCallOutput" +}) +export type BetaCustomToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "custom_tool_call" + readonly "id"?: string + readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "input": string + readonly "async"?: boolean +} +export const BetaCustomToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("custom_tool_call").annotate({ + "description": "The type of the custom tool call. Always `custom_tool_call`.\n" + }), + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the custom tool call in the OpenAI platform.\n" }) + ), + "call_id": Schema.String.annotate({ + "description": "An identifier used to map this custom tool call to a tool call output.\n" + }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) + ), + "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), + "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model.\n" }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the custom tool call runs asynchronously.\n" }) + ) +}).annotate({ + "title": "Custom tool call", + "description": "A call to a custom tool created by the model.\n", + "identifier": "BetaCustomToolCall" +}) +export type BetaFunctionToolCallResource = { + readonly "agent"?: BetaAgentTag | null + readonly "id": string + readonly "type": "function_call" + readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "arguments": string + readonly "status": "in_progress" | "completed" | "incomplete" + readonly "async"?: boolean + readonly "created_by"?: string +} +export const BetaFunctionToolCallResource = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "id": Schema.String.annotate({ "description": "The unique ID of the function tool call.\n" }), + "type": Schema.Literal("function_call").annotate({ + "description": "The type of the function tool call. Always `function_call`.\n" + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the function tool call generated by the model.\n" + }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey(Schema.String.annotate({ "description": "The namespace of the function to run.\n" })), + "name": Schema.String.annotate({ "description": "The name of the function to run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments to pass to the function.\n" }), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the function tool call runs asynchronously.\n" }) + ), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "identifier": "BetaFunctionToolCallResource" }) +export type BetaCustomToolCallResource = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "custom_tool_call" + readonly "id": string + readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "input": string + readonly "async"?: boolean + readonly "status": BetaFunctionCallStatus + readonly "created_by"?: string +} +export const BetaCustomToolCallResource = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("custom_tool_call").annotate({ + "description": "The type of the custom tool call. Always `custom_tool_call`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the custom tool call item.\n" }), + "call_id": Schema.String.annotate({ + "description": "An identifier used to map this custom tool call to a tool call output.\n" + }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) + ), + "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), + "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model.\n" }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the custom tool call runs asynchronously.\n" }) + ), + "status": Schema.suspend((): Schema.Codec => BetaFunctionCallStatus).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "title": "ResponseCustomToolCallItem", "identifier": "BetaCustomToolCallResource" }) +export type BetaFunctionShellCallOutputContentParam = { + readonly "stdout": string + readonly "stderr": string + readonly "outcome": BetaFunctionShellCallOutputOutcomeParam +} +export const BetaFunctionShellCallOutputContentParam = Schema.Struct({ + "stdout": Schema.String.annotate({ "description": "Captured stdout output for the shell call." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "stderr": Schema.String.annotate({ "description": "Captured stderr output for the shell call." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + "outcome": Schema.suspend((): Schema.Codec => + BetaFunctionShellCallOutputOutcomeParam + ).annotate({ "description": "The exit or timeout outcome associated with this shell call." }) +}).annotate({ + "title": "Shell output content", + "description": "Captured stdout and stderr for a portion of a shell tool call output.", + "identifier": "BetaFunctionShellCallOutputContentParam" +}) +export type BetaMCPToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "mcp_call" + readonly "id": string + readonly "server_label": string + readonly "name": string + readonly "arguments": string + readonly "output"?: string | null + readonly "error"?: BetaMCPToolCallError | null + readonly "status"?: BetaMCPToolCallStatus + readonly "approval_request_id"?: string | null +} +export const BetaMCPToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("mcp_call").annotate({ "description": "The type of the item. Always `mcp_call`.\n" }), + "id": Schema.String.annotate({ "description": "The unique ID of the tool call.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server running the tool.\n" }), + "name": Schema.String.annotate({ "description": "The name of the tool that was run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments passed to the tool.\n" }), + "output": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The output from the tool call.\n" }), Schema.Null]) + ), + "error": Schema.optionalKey( + Schema.Union([BetaMCPToolCallError, Schema.Null]).annotate({ + "description": "The error from the tool call, if any." + }) + ), + "status": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaMCPToolCallStatus).annotate({ + "description": + "The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`.\n" + }) + ), + "approval_request_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "Unique identifier for the MCP tool call approval request.\nInclude this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call.\n" + }), + Schema.Null + ]) + ) +}).annotate({ + "title": "MCP tool call", + "description": "An invocation of a tool on an MCP server.\n", + "identifier": "BetaMCPToolCall" +}) +export type BetaModerationPolicyParam = { + readonly "input"?: BetaModerationConfigParam | null + readonly "output"?: BetaModerationConfigParam | null +} +export const BetaModerationPolicyParam = Schema.Struct({ + "input": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaModerationConfigParam).annotate({ + "description": "The moderation policy for the response input." + }), + Schema.Null + ]) + ), + "output": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaModerationConfigParam).annotate({ + "description": "The moderation policy for the response output." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "The policy to apply to moderated response input and output.", + "identifier": "BetaModerationPolicyParam" +}) +export type BetaResponseError = { + readonly "code": BetaResponseErrorCode + readonly "message": string + readonly "misalignment"?: BetaMisalignmentErrorDetailsResource +} | null +export const BetaResponseError = Schema.Union([ + Schema.Struct({ + "code": BetaResponseErrorCode, + "message": Schema.String.annotate({ "description": "A human-readable description of the error.\n" }), + "misalignment": Schema.optionalKey(BetaMisalignmentErrorDetailsResource) + }).annotate({ "description": "An error object returned when the model fails to generate a Response.\n" }), + Schema.Null +]).annotate({ "identifier": "BetaResponseError" }) +export type BetaError = { + readonly "code": string | null + readonly "message": string + readonly "param": string | null + readonly "type": string + readonly "misalignment"?: BetaMisalignmentErrorDetailsResource +} +export const BetaError = Schema.Struct({ + "code": Schema.Union([Schema.String, Schema.Null]), + "message": Schema.String, + "param": Schema.Union([Schema.String, Schema.Null]), + "type": Schema.String, + "misalignment": Schema.optionalKey(BetaMisalignmentErrorDetailsResource) +}).annotate({ "identifier": "BetaError" }) +export type BetaFunctionShellCallOutput = { + readonly "agent"?: BetaAgentTag + readonly "type": "shell_call_output" + readonly "id": string + readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null + readonly "status": BetaFunctionShellCallOutputStatusEnum + readonly "output": ReadonlyArray + readonly "max_output_length": number | null + readonly "created_by"?: string +} +export const BetaFunctionShellCallOutput = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("shell_call_output").annotate({ + "description": "The type of the shell call output. Always `shell_call_output`." + }), + "id": Schema.String.annotate({ + "description": "The unique ID of the shell call output. Populated when this item is returned via API." + }), + "call_id": Schema.String.annotate({ "description": "The unique ID of the shell tool call generated by the model." }), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaToolCallCaller).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.suspend((): Schema.Codec => + BetaFunctionShellCallOutputStatusEnum + ).annotate({ + "description": "The status of the shell call output. One of `in_progress`, `completed`, or `incomplete`." + }), + "output": Schema.Array(BetaFunctionShellCallOutputContent).annotate({ + "description": "An array of shell call output contents" + }), + "max_output_length": Schema.Union([ + Schema.Number.annotate({ + "description": + "The maximum length of the shell command output. This is generated by the model and should be passed back with the raw output." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ + "title": "Shell call output", + "description": "The output of a shell tool call that was emitted.", + "identifier": "BetaFunctionShellCallOutput" +}) +export type BetaResponseShellCallOutputContentDoneStreamingEvent = { + readonly "type": "response.shell_call_output_content.done" + readonly "sequence_number": number + readonly "agent"?: BetaAgentTag + readonly "item_id": string + readonly "output_index": number + readonly "command_index": number + readonly "output": ReadonlyArray +} +export const BetaResponseShellCallOutputContentDoneStreamingEvent = Schema.Struct({ + "type": Schema.Literal("response.shell_call_output_content.done").annotate({ + "description": "The type of the event, always `response.shell_call_output_content.done`." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of the event that was emitted." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "item_id": Schema.String.annotate({ "description": "The ID of the output item that was updated." }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was updated." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "command_index": Schema.Number.annotate({ "description": "The index of the shell command that produced output." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "output": Schema.Array(BetaFunctionShellCallOutputContent).annotate({ + "description": "The output contents emitted for the shell command." + }) +}).annotate({ + "title": "Response shell call output content done event", + "description": "A streaming event that indicated shell call output was completed.", + "identifier": "BetaResponseShellCallOutputContentDoneStreamingEvent" +}) +export type BetaPromptCacheDiagnostics = + | BetaPromptCacheMissDiagnosticsBody + | BetaPromptCacheHitDiagnosticsBody + | BetaPromptCacheComparisonResponseNotFoundDiagnosticsBody + | BetaPromptCacheUnavailableDiagnosticsBody +export const BetaPromptCacheDiagnostics = Schema.Union([ + BetaPromptCacheMissDiagnosticsBody, + BetaPromptCacheHitDiagnosticsBody, + BetaPromptCacheComparisonResponseNotFoundDiagnosticsBody, + BetaPromptCacheUnavailableDiagnosticsBody +], { mode: "oneOf" }).annotate({ + "description": "Prompt cache diagnostics requested for this response.", + "identifier": "BetaPromptCacheDiagnostics" +}) +export type BetaModeration = { + readonly "input": BetaModerationResultBody | BetaModerationErrorBody + readonly "output": BetaModerationResultBody | BetaModerationErrorBody +} +export const BetaModeration = Schema.Struct({ + "input": Schema.Union([BetaModerationResultBody, BetaModerationErrorBody], { mode: "oneOf" }).annotate({ + "description": "Moderation for the response input." + }), + "output": Schema.Union([BetaModerationResultBody, BetaModerationErrorBody], { mode: "oneOf" }).annotate({ + "description": "Moderation for the response output." + }) +}).annotate({ + "title": "Moderation", + "description": "Moderation results or errors for the response input and output.", + "identifier": "BetaModeration" +}) +export type RunStepDetailsToolCallsObject = { + readonly "type": "tool_calls" + readonly "tool_calls": ReadonlyArray< + RunStepDetailsToolCallsCodeObject | RunStepDetailsToolCallsFileSearchObject | RunStepDetailsToolCallsFunctionObject + > +} +export const RunStepDetailsToolCallsObject = Schema.Struct({ + "type": Schema.Literal("tool_calls").annotate({ "description": "Always `tool_calls`." }), + "tool_calls": Schema.Array( + Schema.Union([ + RunStepDetailsToolCallsCodeObject, + RunStepDetailsToolCallsFileSearchObject, + RunStepDetailsToolCallsFunctionObject + ], { mode: "oneOf" }) + ).annotate({ + "description": + "An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `file_search`, or `function`.\n" + }) +}).annotate({ + "title": "Tool calls", + "description": "Details of the tool call.", + "identifier": "RunStepDetailsToolCallsObject" +}) +export type AssistantObject = { + readonly "id": string + readonly "object": "assistant" + readonly "created_at": number + readonly "name": string | null + readonly "description": string | null + readonly "model": string + readonly "instructions": string | null + readonly "tools": ReadonlyArray + readonly "tool_resources"?: { + readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } + readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } + } | null + readonly "metadata": Metadata + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "response_format"?: AssistantsApiResponseFormatOption | null +} +export const AssistantObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("assistant").annotate({ "description": "The object type, which is always `assistant`." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the assistant was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "name": Schema.Union([ + Schema.String.annotate({ "description": "The name of the assistant. The maximum length is 256 characters.\n" }) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })), + Schema.Null + ]), + "description": Schema.Union([ + Schema.String.annotate({ + "description": "The description of the assistant. The maximum length is 512 characters.\n" + }).check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })), + Schema.Null + ]), + "model": Schema.String.annotate({ + "description": + "ID of the model to use. You can use the [List models](https://developers.openai.com/api/reference/resources/models/methods/list) API to see all of your available models, or see our [Model overview](https://developers.openai.com/api/docs/models) for descriptions of them.\n" + }), + "instructions": Schema.Union([ + Schema.String.annotate({ + "description": "The system instructions that the assistant uses. The maximum length is 256,000 characters.\n" + }).check(Schema.isMaxCodePoints(256000).annotate({ "expected": "a string with at most 256000 code points" })), + Schema.Null + ]), + "tools": Schema.Array( + Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) + ).annotate({ + "description": + "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`.\n" + }).check(Schema.isMaxLength(128).annotate({ "expected": "a value with a length of at most 128" })), + "tool_resources": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "code_interpreter": Schema.optionalKey(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs made available to the `code_interpreter`` tool. There can be a maximum of 20 files associated with the tool.\n" + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })) + ) + })), + "file_search": Schema.optionalKey(Schema.Struct({ + "vector_store_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "The ID of the [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ) + })) + }).annotate({ + "description": + "A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" + }), + Schema.Null + ])), + "metadata": Metadata, + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]) + ), + "top_p": Schema.optionalKey(Schema.Union([ + Schema.Number.annotate({ + "description": + "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + Schema.Null + ])), + "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) +}).annotate({ + "title": "Assistant", + "description": "Represents an `assistant` that can call the model and use tools.", + "identifier": "AssistantObject" +}) +export type CreateAssistantRequest = { + readonly "model": string | AssistantSupportedModels + readonly "name"?: string | null + readonly "description"?: string | null + readonly "instructions"?: string | null + readonly "reasoning_effort"?: ReasoningEffort + readonly "tools"?: ReadonlyArray + readonly "tool_resources"?: { + readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } + readonly "file_search"?: { + readonly "vector_store_ids": ReadonlyArray + readonly "vector_stores"?: ReadonlyArray< + { + readonly "file_ids"?: ReadonlyArray + readonly "chunking_strategy"?: { readonly "type": "auto" } | { + readonly "type": "static" + readonly "static": { readonly "max_chunk_size_tokens": number; readonly "chunk_overlap_tokens": number } + } + readonly "metadata"?: Metadata + } + > + } | { + readonly "vector_store_ids"?: ReadonlyArray + readonly "vector_stores": ReadonlyArray< + { + readonly "file_ids"?: ReadonlyArray + readonly "chunking_strategy"?: { readonly "type": "auto" } | { + readonly "type": "static" + readonly "static": { readonly "max_chunk_size_tokens": number; readonly "chunk_overlap_tokens": number } + } + readonly "metadata"?: Metadata + } + > + } + } | null + readonly "metadata"?: Metadata + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "response_format"?: AssistantsApiResponseFormatOption | null +} +export const CreateAssistantRequest = Schema.Struct({ + "model": Schema.Union([Schema.String, AssistantSupportedModels]).annotate({ + "description": + "ID of the model to use. You can use the [List models](https://developers.openai.com/api/reference/resources/models/methods/list) API to see all of your available models, or see our [Model overview](https://developers.openai.com/api/docs/models) for descriptions of them.\n" + }), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The name of the assistant. The maximum length is 256 characters.\n" }) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })), + Schema.Null + ]) + ), + "description": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "The description of the assistant. The maximum length is 512 characters.\n" + }).check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })), + Schema.Null + ]) + ), + "instructions": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "The system instructions that the assistant uses. The maximum length is 256,000 characters.\n" + }).check(Schema.isMaxCodePoints(256000).annotate({ "expected": "a string with at most 256000 code points" })), + Schema.Null + ]) + ), + "reasoning_effort": Schema.optionalKey(ReasoningEffort), + "tools": Schema.optionalKey( + Schema.Array( + Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) + ).annotate({ + "description": + "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`.\n" + }).check(Schema.isMaxLength(128).annotate({ "expected": "a value with a length of at most 128" })) + ), + "tool_resources": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "code_interpreter": Schema.optionalKey(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })) + ) + })), + "file_search": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "vector_store_ids": Schema.Array(Schema.String).annotate({ + "description": + "The [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })), + "vector_stores": Schema.optionalKey( + Schema.Array(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files.\n" + }).check( + Schema.isMaxLength(100000000).annotate({ "expected": "a value with a length of at most 100000000" }) + ) + ), + "chunking_strategy": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }) + .annotate({ + "title": "Auto Chunking Strategy", + "description": + "The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`." + }), + Schema.Struct({ + "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), + "static": Schema.Struct({ + "max_chunk_size_tokens": Schema.Number.annotate({ + "description": + "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(100).annotate({ + "expected": "a value greater than or equal to 100" + }) + ).check( + Schema.isLessThanOrEqualTo(4096).annotate({ "expected": "a value less than or equal to 4096" }) + ), + "chunk_overlap_tokens": Schema.Number.annotate({ + "description": + "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + }) + }).annotate({ "title": "Static Chunking Strategy" }) + ], { mode: "oneOf" }).annotate({ + "description": + "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." + }) + ), + "metadata": Schema.optionalKey(Metadata) + })).annotate({ + "description": + "A helper to create a [vector store](https://developers.openai.com/api/reference/resources/vector_stores) with file_ids and attach it to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ) + }), + Schema.Struct({ + "vector_store_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "The [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ), + "vector_stores": Schema.Array(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs to add to the vector store. For vector stores created before Nov 2025, there can be a maximum of 10,000 files in a vector store. For vector stores created starting in Nov 2025, the limit is 100,000,000 files.\n" + }).check( + Schema.isMaxLength(100000000).annotate({ "expected": "a value with a length of at most 100000000" }) + ) + ), + "chunking_strategy": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ "type": Schema.Literal("auto").annotate({ "description": "Always `auto`." }) }) + .annotate({ + "title": "Auto Chunking Strategy", + "description": + "The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`." + }), + Schema.Struct({ + "type": Schema.Literal("static").annotate({ "description": "Always `static`." }), + "static": Schema.Struct({ + "max_chunk_size_tokens": Schema.Number.annotate({ + "description": + "The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(100).annotate({ + "expected": "a value greater than or equal to 100" + }) + ).check( + Schema.isLessThanOrEqualTo(4096).annotate({ "expected": "a value less than or equal to 4096" }) + ), + "chunk_overlap_tokens": Schema.Number.annotate({ + "description": + "The number of tokens that overlap between chunks. The default value is `400`.\n\nNote that the overlap must not exceed half of `max_chunk_size_tokens`.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + }) + }).annotate({ "title": "Static Chunking Strategy" }) + ], { mode: "oneOf" }).annotate({ + "description": + "The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy." + }) + ), + "metadata": Schema.optionalKey(Metadata) + })).annotate({ + "description": + "A helper to create a [vector store](https://developers.openai.com/api/reference/resources/vector_stores) with file_ids and attach it to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + }) + ], { mode: "oneOf" })) + }).annotate({ + "description": + "A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" + }), + Schema.Null + ])), + "metadata": Schema.optionalKey(Metadata), + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]) + ), + "top_p": Schema.optionalKey(Schema.Union([ + Schema.Number.annotate({ + "description": + "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + Schema.Null + ])), + "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) +}).annotate({ "identifier": "CreateAssistantRequest" }) +export type ModifyAssistantRequest = { + readonly "model"?: string | AssistantSupportedModels + readonly "reasoning_effort"?: ReasoningEffort + readonly "name"?: string | null + readonly "description"?: string | null + readonly "instructions"?: string | null + readonly "tools"?: ReadonlyArray + readonly "tool_resources"?: { + readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } + readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } + } | null + readonly "metadata"?: Metadata + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "response_format"?: AssistantsApiResponseFormatOption | null +} +export const ModifyAssistantRequest = Schema.Struct({ + "model": Schema.optionalKey( + Schema.Union([Schema.String, AssistantSupportedModels]).annotate({ + "description": + "ID of the model to use. You can use the [List models](https://developers.openai.com/api/reference/resources/models/methods/list) API to see all of your available models, or see our [Model overview](https://developers.openai.com/api/docs/models) for descriptions of them.\n" + }) + ), + "reasoning_effort": Schema.optionalKey(ReasoningEffort), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The name of the assistant. The maximum length is 256 characters.\n" }) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })), + Schema.Null + ]) + ), + "description": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "The description of the assistant. The maximum length is 512 characters.\n" + }).check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })), + Schema.Null + ]) + ), + "instructions": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "The system instructions that the assistant uses. The maximum length is 256,000 characters.\n" + }).check(Schema.isMaxCodePoints(256000).annotate({ "expected": "a string with at most 256000 code points" })), + Schema.Null + ]) + ), + "tools": Schema.optionalKey( + Schema.Array( + Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) + ).annotate({ + "description": + "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `file_search`, or `function`.\n" + }).check(Schema.isMaxLength(128).annotate({ "expected": "a value with a length of at most 128" })) + ), + "tool_resources": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "code_interpreter": Schema.optionalKey(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "Overrides the list of [file](https://developers.openai.com/api/reference/resources/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })) + ) + })), + "file_search": Schema.optionalKey(Schema.Struct({ + "vector_store_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "Overrides the [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ) + })) + }).annotate({ + "description": + "A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" + }), + Schema.Null + ])), + "metadata": Schema.optionalKey(Metadata), + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]) + ), + "top_p": Schema.optionalKey(Schema.Union([ + Schema.Number.annotate({ + "description": + "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + Schema.Null + ])), + "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) +}).annotate({ "identifier": "ModifyAssistantRequest" }) +export type RunObject = { + readonly "id": string + readonly "object": "thread.run" + readonly "created_at": number + readonly "thread_id": string + readonly "assistant_id": string + readonly "status": + | "queued" + | "in_progress" + | "requires_action" + | "cancelling" + | "cancelled" + | "failed" + | "completed" + | "incomplete" + | "expired" + readonly "required_action": + | { + readonly "type": "submit_tool_outputs" + readonly "submit_tool_outputs": { readonly "tool_calls": ReadonlyArray } + } & { readonly [x: string]: Schema.Json } + | null + readonly "last_error": + | { readonly "code": "server_error" | "rate_limit_exceeded" | "invalid_prompt"; readonly "message": string } & { + readonly [x: string]: Schema.Json + } + | null + readonly "expires_at": number | null + readonly "started_at": number | null + readonly "cancelled_at": number | null + readonly "failed_at": number | null + readonly "completed_at": number | null + readonly "incomplete_details": + | { readonly "reason"?: "max_completion_tokens" | "max_prompt_tokens" } & { readonly [x: string]: Schema.Json } + | null + readonly "model": string + readonly "instructions": string + readonly "tools": ReadonlyArray + readonly "metadata": Metadata + readonly "usage": RunCompletionUsage + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "max_prompt_tokens": number | null + readonly "max_completion_tokens": number | null + readonly "truncation_strategy": TruncationObject | null + readonly "tool_choice": AssistantsApiToolChoiceOption | null + readonly "parallel_tool_calls": ParallelToolCalls + readonly "response_format": AssistantsApiResponseFormatOption | null +} +export const RunObject = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The identifier, which can be referenced in API endpoints." }), + "object": Schema.Literal("thread.run").annotate({ "description": "The object type, which is always `thread.run`." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the run was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "thread_id": Schema.String.annotate({ + "description": + "The ID of the [thread](https://developers.openai.com/api/docs/assistants/migration) that was executed on as a part of this run." + }), + "assistant_id": Schema.String.annotate({ + "description": + "The ID of the [assistant](https://developers.openai.com/api/docs/assistants/migration) used for execution of this run." + }), + "status": Schema.Literals([ + "queued", + "in_progress", + "requires_action", + "cancelling", + "cancelled", + "failed", + "completed", + "incomplete", + "expired" + ]).annotate({ + "description": + "The status of the run, which can be either `queued`, `in_progress`, `requires_action`, `cancelling`, `cancelled`, `failed`, `completed`, `incomplete`, or `expired`." + }), + "required_action": Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "type": Schema.Literal("submit_tool_outputs").annotate({ + "description": "For now, this is always `submit_tool_outputs`." + }), + "submit_tool_outputs": Schema.Struct({ + "tool_calls": Schema.Array(RunToolCallObject).annotate({ + "description": "A list of the relevant tool calls." + }) + }).annotate({ "description": "Details on the tool outputs needed for this run to continue." }) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ + "description": "Details on the action required to continue the run. Will be `null` if no action is required." + }), + "last_error": Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "code": Schema.Literals(["server_error", "rate_limit_exceeded", "invalid_prompt"]).annotate({ + "description": "One of `server_error`, `rate_limit_exceeded`, or `invalid_prompt`." + }), + "message": Schema.String.annotate({ "description": "A human-readable description of the error." }) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ "description": "The last error associated with this run. Will be `null` if there are no errors." }), + "expires_at": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ "description": "The Unix timestamp (in seconds) for when the run will expire.", "format": "unixtime" }), + "started_at": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ "description": "The Unix timestamp (in seconds) for when the run was started.", "format": "unixtime" }), + "cancelled_at": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ + "description": "The Unix timestamp (in seconds) for when the run was cancelled.", + "format": "unixtime" + }), + "failed_at": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ "description": "The Unix timestamp (in seconds) for when the run failed.", "format": "unixtime" }), + "completed_at": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]).annotate({ + "description": "The Unix timestamp (in seconds) for when the run was completed.", + "format": "unixtime" + }), + "incomplete_details": Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "reason": Schema.optionalKey( + Schema.Literals(["max_completion_tokens", "max_prompt_tokens"]).annotate({ + "description": + "The reason why the run is incomplete. This will point to which specific token limit was reached over the course of the run." + }) + ) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ "description": "Details on why the run is incomplete. Will be `null` if the run is not incomplete." }), + "model": Schema.String.annotate({ + "description": + "The model that the [assistant](https://developers.openai.com/api/docs/assistants/migration) used for this run." + }), + "instructions": Schema.String.annotate({ + "description": + "The instructions that the [assistant](https://developers.openai.com/api/docs/assistants/migration) used for this run." + }), + "tools": Schema.Array( + Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) + ).annotate({ + "description": + "The list of tools that the [assistant](https://developers.openai.com/api/docs/assistants/migration) used for this run." + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })), + "metadata": Metadata, + "usage": RunCompletionUsage, + "temperature": Schema.optionalKey( + Schema.Union([Schema.Finite, Schema.Null]).annotate({ + "description": "The sampling temperature used for this run. If not set, defaults to 1." + }) + ), + "top_p": Schema.optionalKey( + Schema.Union([Schema.Finite, Schema.Null]).annotate({ + "description": "The nucleus sampling value used for this run. If not set, defaults to 1." + }) + ), + "max_prompt_tokens": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(256).annotate({ "expected": "a value greater than or equal to 256" }) + ), + Schema.Null + ]).annotate({ + "description": "The maximum number of prompt tokens specified to have been used over the course of the run.\n" + }), + "max_completion_tokens": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(256).annotate({ "expected": "a value greater than or equal to 256" }) + ), + Schema.Null + ]).annotate({ + "description": "The maximum number of completion tokens specified to have been used over the course of the run.\n" + }), + "truncation_strategy": Schema.Union([TruncationObject, Schema.Null]), + "tool_choice": Schema.Union([AssistantsApiToolChoiceOption, Schema.Null]), + "parallel_tool_calls": ParallelToolCalls, + "response_format": Schema.Union([AssistantsApiResponseFormatOption, Schema.Null]) +}).annotate({ + "title": "A run on a thread", + "description": + "Represents an execution run on a [thread](https://developers.openai.com/api/docs/assistants/migration).", + "identifier": "RunObject" +}) +export type CreateRunRequest = { + readonly "assistant_id": string + readonly "model"?: string | AssistantSupportedModels | null + readonly "reasoning_effort"?: ReasoningEffort + readonly "instructions"?: string | null + readonly "additional_instructions"?: string | null + readonly "additional_messages"?: ReadonlyArray | null + readonly "tools"?: ReadonlyArray | null + readonly "metadata"?: Metadata + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "stream"?: boolean | null + readonly "max_prompt_tokens"?: number | null + readonly "max_completion_tokens"?: number | null + readonly "truncation_strategy"?: TruncationObject | null + readonly "tool_choice"?: AssistantsApiToolChoiceOption | null + readonly "parallel_tool_calls"?: ParallelToolCalls + readonly "response_format"?: AssistantsApiResponseFormatOption | null +} +export const CreateRunRequest = Schema.Struct({ + "assistant_id": Schema.String.annotate({ + "description": + "The ID of the [assistant](https://developers.openai.com/api/docs/assistants/migration) to use to execute this run." + }), + "model": Schema.optionalKey( + Schema.Union([Schema.String, AssistantSupportedModels, Schema.Null]).annotate({ + "description": + "The ID of the [Model](https://developers.openai.com/api/reference/resources/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used." + }) + ), + "reasoning_effort": Schema.optionalKey(ReasoningEffort), + "instructions": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "Overrides the [instructions](https://developers.openai.com/api/docs/assistants/migration) of the assistant. This is useful for modifying the behavior on a per-run basis." + }) + ), + "additional_instructions": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions." + }) + ), + "additional_messages": Schema.optionalKey( + Schema.Union([Schema.Array(CreateMessageRequest), Schema.Null]).annotate({ + "description": "Adds additional messages to the thread before creating the run." + }) + ), + "tools": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) + ).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })), + Schema.Null + ]).annotate({ + "description": + "Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis." + }) + ), + "metadata": Schema.optionalKey(Metadata), + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]).annotate({ + "description": + "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" + }) + ), + "top_p": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + Schema.Null + ]).annotate({ + "description": + "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" + }) + ), + "stream": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": + "If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message.\n" + }) + ), + "max_prompt_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(256).annotate({ "expected": "a value greater than or equal to 256" }) + ), + Schema.Null + ]).annotate({ + "description": + "The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info.\n" + }) + ), + "max_completion_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(256).annotate({ "expected": "a value greater than or equal to 256" }) + ), + Schema.Null + ]).annotate({ + "description": + "The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info.\n" + }) + ), + "truncation_strategy": Schema.optionalKey(Schema.Union([TruncationObject, Schema.Null])), + "tool_choice": Schema.optionalKey(Schema.Union([AssistantsApiToolChoiceOption, Schema.Null])), + "parallel_tool_calls": Schema.optionalKey(ParallelToolCalls), + "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) +}).annotate({ "identifier": "CreateRunRequest" }) +export type ResponseTextParam = { + readonly "format"?: TextResponseFormatConfiguration + readonly "verbosity"?: Verbosity +} +export const ResponseTextParam = Schema.Struct({ + "format": Schema.optionalKey(TextResponseFormatConfiguration), + "verbosity": Schema.optionalKey(Verbosity) +}).annotate({ + "description": + "Configuration options for a text response from the model. Can be plain\ntext or structured JSON data. Learn more:\n- [Text inputs and outputs](https://developers.openai.com/api/docs/guides/text)\n- [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs)\n", + "identifier": "ResponseTextParam" +}) +export type ErrorResponse = { readonly "error": Error } +export const ErrorResponse = Schema.Struct({ "error": Error }).annotate({ "identifier": "ErrorResponse" }) +export type PermissionErrorResponse = { readonly "error": Error | string } +export const PermissionErrorResponse = Schema.Struct({ + "error": Schema.Union([ + Error, + Schema.String.annotate({ "description": "An explanation of the missing API permissions." }) + ]).annotate({ "description": "Details about the permission error." }) +}).annotate({ "identifier": "PermissionErrorResponse" }) +export type ErrorEvent = { readonly "event": "error"; readonly "data": Error } +export const ErrorEvent = Schema.Struct({ "event": Schema.Literal("error"), "data": Error }).annotate({ + "description": + "Occurs when an [error](https://developers.openai.com/api/docs/guides/error-codes#api-errors) occurs. This can happen due to an internal server error or a timeout.", + "identifier": "ErrorEvent" +}) +export type VideoResource = { + readonly "id": string + readonly "object": "video" + readonly "model": VideoModel + readonly "status": VideoStatus + readonly "progress": number + readonly "created_at": number + readonly "completed_at": number | null + readonly "expires_at": number | null + readonly "prompt": string | null + readonly "size": VideoSize + readonly "seconds": string + readonly "remixed_from_video_id": string | null + readonly "error": Error_2 | null +} +export const VideoResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Unique identifier for the video job." }), + "object": Schema.Literal("video").annotate({ "description": "The object type, which is always `video`." }), + "model": Schema.suspend((): Schema.Codec => VideoModel).annotate({ + "description": "The video generation model that produced the job." + }), + "status": Schema.suspend((): Schema.Codec => VideoStatus).annotate({ + "description": "Current lifecycle status of the video job." + }), + "progress": Schema.Number.annotate({ "description": "Approximate completion percentage for the generation task." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (seconds) for when the job was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "completed_at": Schema.Union([ + Schema.Number.annotate({ + "description": "Unix timestamp (seconds) for when the job completed, if finished.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "expires_at": Schema.Union([ + Schema.Number.annotate({ + "description": "Unix timestamp (seconds) for when the downloadable assets expire, if set.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "prompt": Schema.Union([ + Schema.String.annotate({ "description": "The prompt that was used to generate the video." }), + Schema.Null + ]), + "size": Schema.suspend((): Schema.Codec => VideoSize).annotate({ + "description": "The resolution of the generated video." + }), + "seconds": Schema.String.annotate({ + "description": "Duration of the generated clip in seconds. For extensions, this is the stitched total duration." + }), + "remixed_from_video_id": Schema.Union([ + Schema.String.annotate({ "description": "Identifier of the source video if this video is a remix." }), + Schema.Null + ]), + "error": Schema.Union([ + Schema.suspend((): Schema.Codec => Error_2).annotate({ + "description": "Error payload that explains why generation failed, if applicable." + }), + Schema.Null + ]) +}).annotate({ + "title": "Video job", + "description": "Structured information describing a generated video job.", + "identifier": "VideoResource" +}) +export type ChatCompletionModeration = { + readonly "input": ChatCompletionModerationResults | ChatCompletionModerationError + readonly "output": ChatCompletionModerationResults | ChatCompletionModerationError +} +export const ChatCompletionModeration = Schema.Struct({ + "input": Schema.Union([ChatCompletionModerationResults, ChatCompletionModerationError], { mode: "oneOf" }).annotate({ + "description": "Moderation for the request input." + }), + "output": Schema.Union([ChatCompletionModerationResults, ChatCompletionModerationError], { mode: "oneOf" }).annotate({ + "description": "Moderation for the generated output." + }) +}).annotate({ + "description": "Moderation results or errors for the request input and generated output.", + "identifier": "ChatCompletionModeration" +}) +export type ChatCompletionRequestSystemMessage = { + readonly "content": string | ReadonlyArray + readonly "role": "system" + readonly "name"?: string +} +export const ChatCompletionRequestSystemMessage = Schema.Struct({ + "content": Schema.Union([ + Schema.String.annotate({ "title": "Text content", "description": "The contents of the system message." }), + Schema.Array(ChatCompletionRequestSystemMessageContentPart).annotate({ + "title": "Array of content parts", + "description": + "An array of content parts with a defined type. For system messages, only type `text` is supported." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ], { mode: "oneOf" }).annotate({ "description": "The contents of the system message." }), + "role": Schema.Literal("system").annotate({ + "description": "The role of the messages author, in this case `system`." + }), + "name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "An optional name for the participant. Provides the model information to differentiate between participants of the same role." + }) + ) +}).annotate({ + "title": "System message", + "description": + "Developer-provided instructions that the model should follow, regardless of\nmessages sent by the user. With o1 models and newer, use `developer` messages\nfor this purpose instead.\n", + "identifier": "ChatCompletionRequestSystemMessage" +}) +export type ChatCompletionRequestAssistantMessage = { + readonly "content"?: string | ReadonlyArray | null + readonly "refusal"?: string | null + readonly "role": "assistant" + readonly "name"?: string + readonly "audio"?: { readonly "id": string } | null + readonly "tool_calls"?: ChatCompletionMessageToolCalls + readonly "function_call"?: { readonly "arguments": string; readonly "name": string } | null +} +export const ChatCompletionRequestAssistantMessage = Schema.Struct({ + "content": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.String.annotate({ "title": "Text content", "description": "The contents of the assistant message." }), + Schema.Array(ChatCompletionRequestAssistantMessageContentPart).annotate({ + "title": "Array of content parts", + "description": + "An array of content parts with a defined type. Can be one or more of type `text`, or exactly one of type `refusal`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ], { mode: "oneOf" }).annotate({ + "description": + "The contents of the assistant message. Required unless `tool_calls` or `function_call` is specified.\n" + }), + Schema.Null + ]) + ), + "refusal": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The refusal message by the assistant." }), Schema.Null]) + ), + "role": Schema.Literal("assistant").annotate({ + "description": "The role of the messages author, in this case `assistant`." + }), + "name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "An optional name for the participant. Provides the model information to differentiate between participants of the same role." + }) + ), + "audio": Schema.optionalKey( + Schema.Union([ + Schema.Struct({ + "id": Schema.String.annotate({ + "description": "Unique identifier for a previous audio response from the model.\n" + }) + }).annotate({ + "description": + "Data about a previous audio response from the model.\n[Learn more](https://developers.openai.com/api/docs/guides/audio).\n" + }), + Schema.Null + ]) + ), + "tool_calls": Schema.optionalKey(ChatCompletionMessageToolCalls), + "function_call": Schema.optionalKey(Schema.Union([ + Schema.Struct({ + "arguments": Schema.String.annotate({ + "description": + "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." + }), + "name": Schema.String.annotate({ "description": "The name of the function to call." }) + }).annotate({ + "description": + "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." + }), + Schema.Null + ])) +}).annotate({ + "title": "Assistant message", + "description": "Messages sent by the model in response to user messages.\n", + "identifier": "ChatCompletionRequestAssistantMessage" +}) +export type ChatCompletionRequestToolMessage = { + readonly "role": "tool" + readonly "content": string | ReadonlyArray + readonly "tool_call_id": string +} +export const ChatCompletionRequestToolMessage = Schema.Struct({ + "role": Schema.Literal("tool").annotate({ "description": "The role of the messages author, in this case `tool`." }), + "content": Schema.Union([ + Schema.String.annotate({ "title": "Text content", "description": "The contents of the tool message." }), + Schema.Array(ChatCompletionRequestToolMessageContentPart).annotate({ + "title": "Array of content parts", + "description": "An array of content parts with a defined type. For tool messages, only type `text` is supported." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ], { mode: "oneOf" }).annotate({ "description": "The contents of the tool message." }), + "tool_call_id": Schema.String.annotate({ "description": "Tool call that this message is responding to." }) +}).annotate({ "title": "Tool message", "identifier": "ChatCompletionRequestToolMessage" }) +export type ChatCompletionRequestUserMessage = { + readonly "content": string | ReadonlyArray + readonly "role": "user" + readonly "name"?: string +} +export const ChatCompletionRequestUserMessage = Schema.Struct({ + "content": Schema.Union([ + Schema.String.annotate({ "title": "Text content", "description": "The text contents of the message." }), + Schema.Array(ChatCompletionRequestUserMessageContentPart).annotate({ + "title": "Array of content parts", + "description": + "An array of content parts with a defined type. Supported options differ based on the [model](https://developers.openai.com/api/docs/models) being used to generate the response. Can contain text, image, or audio inputs." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + ], { mode: "oneOf" }).annotate({ "description": "The contents of the user message.\n" }), + "role": Schema.Literal("user").annotate({ "description": "The role of the messages author, in this case `user`." }), + "name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "An optional name for the participant. Provides the model information to differentiate between participants of the same role." + }) + ) +}).annotate({ + "title": "User message", + "description": "Messages sent by an end user, containing prompts or additional context\ninformation.\n", + "identifier": "ChatCompletionRequestUserMessage" +}) +export type ModerationParam = { readonly "model": string; readonly "policy"?: ModerationPolicyParam | null } +export const ModerationParam = Schema.Struct({ + "model": Schema.String.annotate({ + "description": "The moderation model to use for moderated completions, e.g. 'omni-moderation-latest'." + }), + "policy": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ModerationPolicyParam).annotate({ + "description": "The policy to apply to moderated response input and output." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "Configuration for running moderation on the input and output of this response.", + "identifier": "ModerationParam" +}) +export type CodeInterpreterTool = { + readonly "type": "code_interpreter" + readonly "container": string | AutoCodeInterpreterToolParam + readonly "allowed_callers"?: ReadonlyArray | null +} +export const CodeInterpreterTool = Schema.Struct({ + "type": Schema.Literal("code_interpreter").annotate({ + "description": "The type of the code interpreter tool. Always `code_interpreter`.\n" + }), + "container": Schema.Union([ + Schema.String.annotate({ "description": "The container ID." }), + AutoCodeInterpreterToolParam + ], { mode: "oneOf" }).annotate({ + "description": + "The code interpreter container. Can be a container ID or an object that\nspecifies uploaded file IDs to make available to your code, along with an\noptional `memory_limit` setting.\n" + }), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(CallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ + "title": "Code interpreter", + "description": "A tool that runs Python code to help generate a response to a prompt.\n", + "identifier": "CodeInterpreterTool" +}) +export type FunctionShellToolParam = { + readonly "type": "shell" + readonly "environment"?: ContainerAutoParam | LocalEnvironmentParam | ContainerReferenceParam | null + readonly "allowed_callers"?: ReadonlyArray | null +} +export const FunctionShellToolParam = Schema.Struct({ + "type": Schema.Literal("shell").annotate({ "description": "The type of the shell tool. Always `shell`." }), + "environment": Schema.optionalKey( + Schema.Union([ + Schema.Union([ContainerAutoParam, LocalEnvironmentParam, ContainerReferenceParam], { mode: "oneOf" }), + Schema.Null + ]) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(CallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ + "title": "Shell tool", + "description": "A tool that allows the model to execute shell commands.", + "identifier": "FunctionShellToolParam" +}) +export type EvalItemContentArray = ReadonlyArray +export const EvalItemContentArray = Schema.Array(EvalItemContentItem).annotate({ + "title": "An array of Input text, Output text, Input image, and Input audio", + "description": + "A list of inputs, each of which may be either an input text, output text, input\nimage, or input audio object.\n", + "identifier": "EvalItemContentArray" +}) +export type Message = { + readonly "type": "message" + readonly "id": string + readonly "status": MessageStatus + readonly "role": MessageRole + readonly "content": ReadonlyArray< + | InputTextContent + | OutputTextContent + | TextContent + | SummaryTextContent + | ReasoningTextContent + | RefusalContent + | InputImageContent + | ComputerScreenshotContent + | InputFileContent + > + readonly "phase"?: MessagePhase_2 | null +} +export const Message = Schema.Struct({ + "type": Schema.Literal("message").annotate({ "description": "The type of the message. Always set to `message`." }), + "id": Schema.String.annotate({ "description": "The unique ID of the message." }), + "status": Schema.suspend((): Schema.Codec => MessageStatus).annotate({ + "description": + "The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API." + }), + "role": Schema.suspend((): Schema.Codec => MessageRole).annotate({ + "description": + "The role of the message. One of `unknown`, `user`, `assistant`, `system`, `critic`, `discriminator`, `developer`, or `tool`." + }), + "content": Schema.Array( + Schema.Union([ + InputTextContent, + OutputTextContent, + TextContent, + SummaryTextContent, + ReasoningTextContent, + RefusalContent, + InputImageContent, + ComputerScreenshotContent, + InputFileContent + ], { mode: "oneOf" }).annotate({ "description": "A content part that makes up an input or output item." }) + ).annotate({ "description": "The content of the message" }), + "phase": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => MessagePhase_2).annotate({ + "description": + "Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend phase on all assistant messages — dropping it can degrade performance. Not used for user messages." + }), + Schema.Null + ]) + ) +}).annotate({ "title": "Message", "description": "A message to or from the model.", "identifier": "Message" }) +export type OutputMessageContent = OutputTextContent | RefusalContent +export const OutputMessageContent = Schema.Union([OutputTextContent, RefusalContent], { mode: "oneOf" }).annotate({ + "identifier": "OutputMessageContent" +}) +export type OutputContent = OutputTextContent | RefusalContent | ReasoningTextContent +export const OutputContent = Schema.Union([OutputTextContent, RefusalContent, ReasoningTextContent], { mode: "oneOf" }) + .annotate({ "identifier": "OutputContent" }) +export type FunctionToolCallOutputResource = { + readonly "id": string + readonly "type": "function_call_output" + readonly "call_id"?: string + readonly "name"?: string + readonly "namespace"?: string + readonly "caller"?: ToolCallCallerParam | null + readonly "output": string | ReadonlyArray + readonly "status": "in_progress" | "completed" | "incomplete" + readonly "created_by"?: string +} +export const FunctionToolCallOutputResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the function call tool output.\n" }), + "type": Schema.Literal("function_call_output").annotate({ + "description": "The type of the function tool call output. Always `function_call_output`.\n" + }), + "call_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the function tool call generated by the model.\n" }) + ), + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the tool that produced the output.\n" }) + ), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the tool that produced the output.\n" }) + ), + "caller": Schema.optionalKey(Schema.Union([ToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the function call.\n" + }), + Schema.Array(FunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the function call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the function call generated by your code.\nCan be a string or an list of output content.\n" + }), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "identifier": "FunctionToolCallOutputResource" }) +export type CustomToolCallOutput = { + readonly "type": "custom_tool_call_output" + readonly "id"?: string + readonly "call_id": string + readonly "caller"?: ToolCallCallerParam | null + readonly "output": string | ReadonlyArray +} +export const CustomToolCallOutput = Schema.Struct({ + "type": Schema.Literal("custom_tool_call_output").annotate({ + "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" + }), + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the custom tool call output in the OpenAI platform.\n" }) + ), + "call_id": Schema.String.annotate({ + "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the custom tool call.\n" + }), + Schema.Array(FunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the custom tool call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" + }) +}).annotate({ + "title": "Custom tool call output", + "description": "The output of a custom tool call from your code, being sent back to the model.\n", + "identifier": "CustomToolCallOutput" +}) +export type CustomToolCallOutputResource = { + readonly "type": "custom_tool_call_output" + readonly "id": string + readonly "call_id": string + readonly "caller"?: ToolCallCallerParam | null + readonly "output": string | ReadonlyArray + readonly "status": FunctionCallOutputStatusEnum + readonly "created_by"?: string +} +export const CustomToolCallOutputResource = Schema.Struct({ + "type": Schema.Literal("custom_tool_call_output").annotate({ + "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the custom tool call output item.\n" }), + "call_id": Schema.String.annotate({ + "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the custom tool call.\n" + }), + Schema.Array(FunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the custom tool call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" + }), + "status": Schema.suspend((): Schema.Codec => FunctionCallOutputStatusEnum).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "title": "ResponseCustomToolCallOutputItem", "identifier": "CustomToolCallOutputResource" }) +export type FunctionToolCallOutput = { + readonly "id"?: string + readonly "type": "function_call_output" + readonly "call_id"?: string + readonly "name"?: string + readonly "namespace"?: string + readonly "caller"?: ToolCallCallerParam | null + readonly "output": string | ReadonlyArray + readonly "status"?: "in_progress" | "completed" | "incomplete" +} +export const FunctionToolCallOutput = Schema.Struct({ + "id": Schema.optionalKey( + Schema.String.annotate({ + "description": "The unique ID of the function tool call output. Populated when this item\nis returned via API.\n" + }) + ), + "type": Schema.Literal("function_call_output").annotate({ + "description": "The type of the function tool call output. Always `function_call_output`.\n" + }), + "call_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the function tool call generated by the model.\n" }) + ), + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the tool that produced the output.\n" }) + ), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the tool that produced the output.\n" }) + ), + "caller": Schema.optionalKey(Schema.Union([ToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the function call.\n" + }), + Schema.Array(FunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the function call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the function call generated by your code.\nCan be a string or an list of output content.\n" + }), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ) +}).annotate({ + "title": "Function tool call output", + "description": "The output of a function tool call.\n", + "identifier": "FunctionToolCallOutput" +}) +export type InputMessageContentList = ReadonlyArray +export const InputMessageContentList = Schema.Array(InputContent).annotate({ + "title": "Input item content list", + "description": "A list of one or many input items to the model, containing different content \ntypes.\n", + "identifier": "InputMessageContentList" +}) +export type Prompt = { + readonly "id": string + readonly "version"?: string | null + readonly "variables"?: ResponsePromptVariables +} | null +export const Prompt = Schema.Union([ + Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique identifier of the prompt template to use." }), + "version": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Optional version of the prompt template." }), Schema.Null]) + ), + "variables": Schema.optionalKey(ResponsePromptVariables) + }).annotate({ + "description": + "Reference to a prompt template and its variables.\n[Learn more](https://developers.openai.com/api/docs/guides/text?api-mode=responses#version-prompts-in-code).\n" + }), + Schema.Null +]).annotate({ "identifier": "Prompt" }) +export type ComputerActionList = ReadonlyArray +export const ComputerActionList = Schema.Array(ComputerAction).annotate({ + "title": "Computer Action List", + "description": + "Flattened batched actions for `computer_use`. Each action includes an\n`type` discriminator and action-specific fields.\n", + "identifier": "ComputerActionList" +}) +export type NamespaceToolParam = { + readonly "type": "namespace" + readonly "name": string + readonly "description": string + readonly "tools": ReadonlyArray +} +export const NamespaceToolParam = Schema.Struct({ + "type": Schema.Literal("namespace").annotate({ "description": "The type of the tool. Always `namespace`." }), + "name": Schema.String.annotate({ "description": "The namespace name used in tool calls (for example, `crm`)." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "description": Schema.String.annotate({ "description": "A description of the namespace shown to the model." }), + "tools": Schema.Array( + Schema.Union([FunctionToolParam, CustomToolParam], { mode: "oneOf" }).annotate({ + "description": "A function or custom tool that belongs to a namespace." + }) + ).annotate({ "description": "The function/custom tools available inside this namespace." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ) +}).annotate({ + "title": "Namespace", + "description": "Groups function/custom tools under a shared namespace.", + "identifier": "NamespaceToolParam" +}) +export type ToolSearchOutputNamespaceToolParam = { + readonly "type": "namespace" + readonly "name": string + readonly "description": string + readonly "tools": ReadonlyArray +} +export const ToolSearchOutputNamespaceToolParam = Schema.Struct({ + "type": Schema.Literal("namespace").annotate({ "description": "The type of the tool. Always `namespace`." }), + "name": Schema.String.annotate({ "description": "The namespace name used in tool calls (for example, `crm`)." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "description": Schema.String.annotate({ "description": "A description of the namespace shown to the model." }), + "tools": Schema.Array( + Schema.Union([ToolSearchOutputFunctionToolParam, CustomToolParam], { mode: "oneOf" }).annotate({ + "description": "A function or custom tool loaded into a namespace by tool search." + }) + ).annotate({ "description": "The function/custom tools loaded inside this namespace." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ) +}).annotate({ + "title": "Namespace", + "description": "Groups function/custom tools under a shared namespace.", + "identifier": "ToolSearchOutputNamespaceToolParam" +}) +export type LiveHostedShellToolInputParam = { + readonly "type": "shell" + readonly "environment"?: + | LiveHostedShellContainerAutoParam + | LiveContainerReferenceParam + | LiveLocalEnvironmentParam + | null +} +export const LiveHostedShellToolInputParam = Schema.Struct({ + "type": Schema.Literal("shell"), + "environment": Schema.optionalKey( + Schema.Union([ + Schema.Union([LiveHostedShellContainerAutoParam, LiveContainerReferenceParam, LiveLocalEnvironmentParam], { + mode: "oneOf" + }), + Schema.Null + ]) + ) +}).annotate({ + "description": + "A Responses shell tool. Use a hosted container or return local shell results with response.item.create. Domain secrets are not supported.", + "identifier": "LiveHostedShellToolInputParam" +}) +export type Input = ReadonlyArray +export const Input = Schema.Array(LiveInitialItem).annotate({ + "description": + "Ordered text-only history supplied before startup. Supports developer, user, and assistant messages with one text part each; at most 128 messages and 8,192 rendered tokens in total." +}).check( + Schema.isMaxLength(128).annotate({ "expected": "a value with a length of at most 128", "identifier": "input" }) +) +export type AuditLog = { + readonly "id": string + readonly "type": AuditLogEventType + readonly "effective_at": number + readonly "project"?: { readonly "id"?: string; readonly "name"?: string } + readonly "actor"?: AuditLogActor | null + readonly "api_key.created"?: { + readonly "id"?: string + readonly "data"?: { readonly "scopes"?: ReadonlyArray } + } + readonly "api_key.updated"?: { + readonly "id"?: string + readonly "changes_requested"?: { readonly "scopes"?: ReadonlyArray } + } + readonly "api_key.deleted"?: { readonly "id"?: string } + readonly "checkpoint.permission.created"?: { + readonly "id"?: string + readonly "data"?: { readonly "project_id"?: string; readonly "fine_tuned_model_checkpoint"?: string } + } + readonly "checkpoint.permission.deleted"?: { readonly "id"?: string } + readonly "external_key.registered"?: { + readonly "id"?: string + readonly "data"?: { readonly [x: string]: Schema.Json } + } + readonly "external_key.removed"?: { readonly "id"?: string } + readonly "external_storage.registered"?: { + readonly "id"?: string + readonly "data"?: { readonly "provider"?: Provider; readonly "geography"?: string } + } + readonly "external_storage.removed"?: { readonly "id"?: string } + readonly "group.created"?: { readonly "id"?: string; readonly "data"?: { readonly "group_name"?: string } } + readonly "group.updated"?: { + readonly "id"?: string + readonly "changes_requested"?: { readonly "group_name"?: string } + } + readonly "group.deleted"?: { readonly "id"?: string } + readonly "scim.enabled"?: { readonly "id"?: string } + readonly "scim.disabled"?: { readonly "id"?: string } + readonly "invite.sent"?: { + readonly "id"?: string + readonly "data"?: { readonly "email"?: string; readonly "role"?: string } + } + readonly "invite.accepted"?: { readonly "id"?: string } + readonly "invite.deleted"?: { readonly "id"?: string } + readonly "ip_allowlist.created"?: { + readonly "id"?: string + readonly "name"?: string + readonly "allowed_ips"?: ReadonlyArray + } + readonly "ip_allowlist.updated"?: { readonly "id"?: string; readonly "allowed_ips"?: ReadonlyArray } + readonly "ip_allowlist.deleted"?: { + readonly "id"?: string + readonly "name"?: string + readonly "allowed_ips"?: ReadonlyArray + } + readonly "ip_allowlist.config.activated"?: { + readonly "configs"?: ReadonlyArray<{ readonly "id"?: string; readonly "name"?: string }> + } + readonly "ip_allowlist.config.deactivated"?: { + readonly "configs"?: ReadonlyArray<{ readonly "id"?: string; readonly "name"?: string }> + } + readonly "login.succeeded"?: { readonly [x: string]: Schema.Json } + readonly "login.failed"?: { readonly "error_code"?: string; readonly "error_message"?: string } + readonly "logout.succeeded"?: { readonly [x: string]: Schema.Json } + readonly "logout.failed"?: { readonly "error_code"?: string; readonly "error_message"?: string } + readonly "organization.updated"?: { + readonly "id"?: string + readonly "changes_requested"?: { + readonly "title"?: string + readonly "description"?: string + readonly "name"?: string + readonly "threads_ui_visibility"?: string + readonly "usage_dashboard_visibility"?: string + readonly "api_call_logging"?: string + readonly "api_call_logging_project_ids"?: string + } + } + readonly "project.created"?: { + readonly "id"?: string + readonly "data"?: { readonly "name"?: string; readonly "title"?: string } + } + readonly "project.updated"?: { readonly "id"?: string; readonly "changes_requested"?: { readonly "title"?: string } } + readonly "project.archived"?: { readonly "id"?: string } + readonly "project.deleted"?: { readonly "id"?: string } + readonly "rate_limit.updated"?: { + readonly "id"?: string + readonly "changes_requested"?: { + readonly "max_requests_per_1_minute"?: number + readonly "max_tokens_per_1_minute"?: number + readonly "max_images_per_1_minute"?: number + readonly "max_audio_megabytes_per_1_minute"?: number + readonly "max_requests_per_1_day"?: number + readonly "batch_1_day_max_input_tokens"?: number + } + } + readonly "rate_limit.deleted"?: { readonly "id"?: string } + readonly "role.created"?: { + readonly "id"?: string + readonly "role_name"?: string + readonly "permissions"?: ReadonlyArray + readonly "resource_type"?: string + readonly "resource_id"?: string + } + readonly "role.updated"?: { + readonly "id"?: string + readonly "changes_requested"?: { + readonly "role_name"?: string + readonly "resource_id"?: string + readonly "resource_type"?: string + readonly "permissions_added"?: ReadonlyArray + readonly "permissions_removed"?: ReadonlyArray + readonly "description"?: string + readonly "metadata"?: { readonly [x: string]: Schema.Json } + } + } + readonly "role.deleted"?: { readonly "id"?: string } + readonly "role.assignment.created"?: { + readonly "id"?: string + readonly "principal_id"?: string + readonly "principal_type"?: string + readonly "resource_id"?: string + readonly "resource_type"?: string + } + readonly "role.assignment.deleted"?: { + readonly "id"?: string + readonly "principal_id"?: string + readonly "principal_type"?: string + readonly "resource_id"?: string + readonly "resource_type"?: string + } + readonly "role.bound_to_resource"?: { + readonly "id"?: string + readonly "role_id"?: string + readonly "resource_id"?: string + readonly "resource_type"?: string + readonly "permissions"?: ReadonlyArray + readonly "workspace_id"?: string + readonly "connector_id"?: string + readonly "connector_name"?: string + readonly "enabled"?: boolean + readonly "source"?: + | "role_toggle" + | "role_connector_update" + | "role_delete" + | "workspace_permissions" + | "connector_publish" + } + readonly "role.unbound_from_resource"?: { + readonly "id"?: string + readonly "role_id"?: string + readonly "resource_id"?: string + readonly "resource_type"?: string + readonly "permissions"?: ReadonlyArray + readonly "workspace_id"?: string + readonly "connector_id"?: string + readonly "connector_name"?: string + readonly "enabled"?: boolean + readonly "source"?: + | "role_toggle" + | "role_connector_update" + | "role_delete" + | "workspace_permissions" + | "connector_publish" + } + readonly "service_account.created"?: { readonly "id"?: string; readonly "data"?: { readonly "role"?: string } } + readonly "service_account.updated"?: { + readonly "id"?: string + readonly "changes_requested"?: { readonly "role"?: string } + } + readonly "service_account.deleted"?: { readonly "id"?: string } + readonly "workload_identity_provider.created"?: { + readonly "id"?: string + readonly "data"?: { readonly [x: string]: Schema.Json } + } + readonly "workload_identity_provider.updated"?: { + readonly "id"?: string + readonly "changes_requested"?: { readonly [x: string]: Schema.Json } + } + readonly "workload_identity_provider.deleted"?: { readonly "id"?: string; readonly "name"?: string } + readonly "workload_identity_provider_mapping.created"?: { + readonly "id"?: string + readonly "identity_provider_id"?: string + readonly "data"?: { readonly [x: string]: Schema.Json } + } + readonly "workload_identity_provider_mapping.updated"?: { + readonly "id"?: string + readonly "identity_provider_id"?: string + readonly "changes_requested"?: { readonly [x: string]: Schema.Json } + } + readonly "workload_identity_provider_mapping.deleted"?: { + readonly "id"?: string + readonly "identity_provider_id"?: string + readonly "project_id"?: string + readonly "service_account_id"?: string + } + readonly "user.added"?: { readonly "id"?: string; readonly "data"?: { readonly "role"?: string } } + readonly "user.updated"?: { readonly "id"?: string; readonly "changes_requested"?: { readonly "role"?: string } } + readonly "user.deleted"?: { readonly "id"?: string } + readonly "certificate.created"?: { readonly "id"?: string; readonly "name"?: string } + readonly "certificate.updated"?: { readonly "id"?: string; readonly "name"?: string } + readonly "certificate.deleted"?: { readonly "id"?: string; readonly "name"?: string; readonly "certificate"?: string } + readonly "certificates.activated"?: { + readonly "certificates"?: ReadonlyArray<{ readonly "id"?: string; readonly "name"?: string }> + } + readonly "certificates.deactivated"?: { + readonly "certificates"?: ReadonlyArray<{ readonly "id"?: string; readonly "name"?: string }> + } +} +export const AuditLog = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of this log." }), + "type": AuditLogEventType, + "effective_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of the event.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "project": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The project title." })) + }).annotate({ + "description": + "The project that the action was scoped to. Absent for actions not scoped to projects. Note that any admin actions taken via Admin API keys are associated with the default project." + }) + ), + "actor": Schema.optionalKey(Schema.Union([AuditLogActor, Schema.Null])), + "api_key.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The tracking ID of the API key." })), + "data": Schema.optionalKey( + Schema.Struct({ + "scopes": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "A list of scopes allowed for the API key, e.g. `[\"api.model.request\"]`" + }) + ) + }).annotate({ "description": "The payload used to create the API key." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "api_key.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The tracking ID of the API key." })), + "changes_requested": Schema.optionalKey( + Schema.Struct({ + "scopes": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "A list of scopes allowed for the API key, e.g. `[\"api.model.request\"]`" + }) + ) + }).annotate({ "description": "The payload used to update the API key." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "api_key.deleted": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The tracking ID of the API key." })) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "checkpoint.permission.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the checkpoint permission." })), + "data": Schema.optionalKey( + Schema.Struct({ + "project_id": Schema.optionalKey( + Schema.String.annotate({ + "description": "The ID of the project that the checkpoint permission was created for." + }) + ), + "fine_tuned_model_checkpoint": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the fine-tuned model checkpoint." }) + ) + }).annotate({ "description": "The payload used to create the checkpoint permission." }) + ) + }).annotate({ + "description": "The project and fine-tuned model checkpoint that the checkpoint permission was created for." + }) + ), + "checkpoint.permission.deleted": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the checkpoint permission." })) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "external_key.registered": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the external key configuration." })), + "data": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The configuration for the external key." + }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "external_key.removed": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the external key configuration." })) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "external_storage.registered": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the external storage configuration." }) + ), + "data": Schema.optionalKey( + Schema.Struct({ + "provider": Schema.optionalKey( + Schema.suspend((): Schema.Codec => Provider).annotate({ + "description": "The external storage provider configuration." + }) + ), + "geography": Schema.optionalKey( + Schema.String.annotate({ "description": "The OpenAI geography derived from the storage region." }) + ) + }).annotate({ "description": "The configuration for the external storage." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "external_storage.removed": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the external storage configuration." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "group.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the group." })), + "data": Schema.optionalKey( + Schema.Struct({ + "group_name": Schema.optionalKey(Schema.String.annotate({ "description": "The group name." })) + }).annotate({ "description": "Information about the created group." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "group.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the group." })), + "changes_requested": Schema.optionalKey( + Schema.Struct({ + "group_name": Schema.optionalKey(Schema.String.annotate({ "description": "The updated group name." })) + }).annotate({ "description": "The payload used to update the group." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "group.deleted": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the group." })) }) + .annotate({ "description": "The details for events with this `type`." }) + ), + "scim.enabled": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the SCIM was enabled for." })) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "scim.disabled": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the SCIM was disabled for." })) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "invite.sent": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the invite." })), + "data": Schema.optionalKey( + Schema.Struct({ + "email": Schema.optionalKey( + Schema.String.annotate({ "description": "The email invited to the organization." }) + ), + "role": Schema.optionalKey( + Schema.String.annotate({ + "description": "The role the email was invited to be. Is either `owner` or `member`." + }) + ) + }).annotate({ "description": "The payload used to create the invite." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "invite.accepted": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the invite." })) }) + .annotate({ "description": "The details for events with this `type`." }) + ), + "invite.deleted": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the invite." })) }) + .annotate({ "description": "The details for events with this `type`." }) + ), + "ip_allowlist.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." })), + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the IP allowlist configuration." }) + ), + "allowed_ips": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "The IP addresses or CIDR ranges included in the configuration." + }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "ip_allowlist.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." })), + "allowed_ips": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "The updated set of IP addresses or CIDR ranges in the configuration." + }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "ip_allowlist.deleted": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." })), + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the IP allowlist configuration." }) + ), + "allowed_ips": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "The IP addresses or CIDR ranges that were in the configuration." + }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "ip_allowlist.config.activated": Schema.optionalKey( + Schema.Struct({ + "configs": Schema.optionalKey( + Schema.Array( + Schema.Struct({ + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." }) + ), + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the IP allowlist configuration." }) + ) + }) + ).annotate({ "description": "The configurations that were activated." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "ip_allowlist.config.deactivated": Schema.optionalKey( + Schema.Struct({ + "configs": Schema.optionalKey( + Schema.Array( + Schema.Struct({ + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the IP allowlist configuration." }) + ), + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the IP allowlist configuration." }) + ) + }) + ).annotate({ "description": "The configurations that were deactivated." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "login.succeeded": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "This event has no additional fields beyond the standard audit log attributes." + }) + ), + "login.failed": Schema.optionalKey( + Schema.Struct({ + "error_code": Schema.optionalKey(Schema.String.annotate({ "description": "The error code of the failure." })), + "error_message": Schema.optionalKey( + Schema.String.annotate({ "description": "The error message of the failure." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "logout.succeeded": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "This event has no additional fields beyond the standard audit log attributes." + }) + ), + "logout.failed": Schema.optionalKey( + Schema.Struct({ + "error_code": Schema.optionalKey(Schema.String.annotate({ "description": "The error code of the failure." })), + "error_message": Schema.optionalKey( + Schema.String.annotate({ "description": "The error message of the failure." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "organization.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The organization ID." })), + "changes_requested": Schema.optionalKey( + Schema.Struct({ + "title": Schema.optionalKey(Schema.String.annotate({ "description": "The organization title." })), + "description": Schema.optionalKey(Schema.String.annotate({ "description": "The organization description." })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The organization name." })), + "threads_ui_visibility": Schema.optionalKey( + Schema.String.annotate({ + "description": + "Visibility of the threads page which shows messages created with the Assistants API and Playground. One of `ANY_ROLE`, `OWNERS`, or `NONE`." + }) + ), + "usage_dashboard_visibility": Schema.optionalKey( + Schema.String.annotate({ + "description": + "Visibility of the usage dashboard which shows activity and costs for your organization. One of `ANY_ROLE` or `OWNERS`." + }) + ), + "api_call_logging": Schema.optionalKey( + Schema.String.annotate({ + "description": + "How your organization logs data from supported API calls. One of `disabled`, `enabled_per_call`, `enabled_for_all_projects`, or `enabled_for_selected_projects`" + }) + ), + "api_call_logging_project_ids": Schema.optionalKey( + Schema.String.annotate({ + "description": "The list of project ids if api_call_logging is set to `enabled_for_selected_projects`" + }) + ) + }).annotate({ "description": "The payload used to update the organization settings." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "project.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), + "data": Schema.optionalKey( + Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The project name." })), + "title": Schema.optionalKey( + Schema.String.annotate({ "description": "The title of the project as seen on the dashboard." }) + ) + }).annotate({ "description": "The payload used to create the project." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "project.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), + "changes_requested": Schema.optionalKey( + Schema.Struct({ + "title": Schema.optionalKey( + Schema.String.annotate({ "description": "The title of the project as seen on the dashboard." }) + ) + }).annotate({ "description": "The payload used to update the project." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "project.archived": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })) }).annotate({ + "description": "The details for events with this `type`." + }) + ), + "project.deleted": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })) }).annotate({ + "description": "The details for events with this `type`." + }) + ), + "rate_limit.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The rate limit ID" })), + "changes_requested": Schema.optionalKey( + Schema.Struct({ + "max_requests_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum requests per minute." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "max_tokens_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum tokens per minute." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "max_images_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum images per minute. Only relevant for certain models." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "max_audio_megabytes_per_1_minute": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum audio megabytes per minute. Only relevant for certain models." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "max_requests_per_1_day": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum requests per day. Only relevant for certain models." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "batch_1_day_max_input_tokens": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The maximum batch input tokens per day. Only relevant for certain models." + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ) + }).annotate({ "description": "The payload used to update the rate limits." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "rate_limit.deleted": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The rate limit ID" })) }) + .annotate({ "description": "The details for events with this `type`." }) + ), + "role.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The role ID." })), + "role_name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the role." })), + "permissions": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ "description": "The permissions granted by the role." }) + ), + "resource_type": Schema.optionalKey( + Schema.String.annotate({ "description": "The type of resource the role belongs to." }) + ), + "resource_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The resource the role is scoped to." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "role.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The role ID." })), + "changes_requested": Schema.optionalKey( + Schema.Struct({ + "role_name": Schema.optionalKey( + Schema.String.annotate({ "description": "The updated role name, when provided." }) + ), + "resource_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The resource the role is scoped to." }) + ), + "resource_type": Schema.optionalKey( + Schema.String.annotate({ "description": "The type of resource the role belongs to." }) + ), + "permissions_added": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ "description": "The permissions added to the role." }) + ), + "permissions_removed": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ "description": "The permissions removed from the role." }) + ), + "description": Schema.optionalKey( + Schema.String.annotate({ "description": "The updated role description, when provided." }) + ), + "metadata": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Additional metadata stored on the role." + }) + ) + }).annotate({ "description": "The payload used to update the role." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "role.deleted": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The role ID." })) }).annotate({ + "description": "The details for events with this `type`." + }) + ), + "role.assignment.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The identifier of the role assignment." })), + "principal_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The principal (user or group) that received the role." }) + ), + "principal_type": Schema.optionalKey( + Schema.String.annotate({ "description": "The type of principal (user or group) that received the role." }) + ), + "resource_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The resource the role assignment is scoped to." }) + ), + "resource_type": Schema.optionalKey( + Schema.String.annotate({ "description": "The type of resource the role assignment is scoped to." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "role.assignment.deleted": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The identifier of the role assignment." })), + "principal_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The principal (user or group) that had the role removed." }) + ), + "principal_type": Schema.optionalKey( + Schema.String.annotate({ "description": "The type of principal (user or group) that had the role removed." }) + ), + "resource_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The resource the role assignment was scoped to." }) + ), + "resource_type": Schema.optionalKey( + Schema.String.annotate({ "description": "The type of resource the role assignment was scoped to." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "role.bound_to_resource": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The ID of the resource the role was bound to. ChatGPT workspace connector resources use `__`." + }) + ), + "role_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the role that was bound to the resource." }) + ), + "resource_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the resource the role was bound to." }) + ), + "resource_type": Schema.optionalKey( + Schema.String.annotate({ "description": "The type of resource the role was bound to." }) + ), + "permissions": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ "description": "The permissions granted to the role for the resource." }) + ), + "workspace_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The workspace ID for a ChatGPT workspace connector resource." }) + ), + "connector_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The connector ID for a ChatGPT workspace connector resource." }) + ), + "connector_name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The connector display name for a ChatGPT workspace connector resource, or the connector ID when the display name could not be resolved." + }) + ), + "enabled": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the connector is enabled for the role." }) + ), + "source": Schema.optionalKey( + Schema.Literals([ + "role_toggle", + "role_connector_update", + "role_delete", + "workspace_permissions", + "connector_publish" + ]).annotate({ "description": "The connector role mutation path that produced the event." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "role.unbound_from_resource": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The ID of the resource the role was unbound from. ChatGPT workspace connector resources use `__`." + }) + ), + "role_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the role that was unbound from the resource." }) + ), + "resource_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The ID of the resource the role was unbound from." }) + ), + "resource_type": Schema.optionalKey( + Schema.String.annotate({ "description": "The type of resource the role was unbound from." }) + ), + "permissions": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": "The permissions remaining for the role after the change." + }) + ), + "workspace_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The workspace ID for a ChatGPT workspace connector resource." }) + ), + "connector_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The connector ID for a ChatGPT workspace connector resource." }) + ), + "connector_name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The connector display name for a ChatGPT workspace connector resource, or the connector ID when the display name could not be resolved." + }) + ), + "enabled": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the connector is enabled for the role." }) + ), + "source": Schema.optionalKey( + Schema.Literals([ + "role_toggle", + "role_connector_update", + "role_delete", + "workspace_permissions", + "connector_publish" + ]).annotate({ "description": "The connector role mutation path that produced the event." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "service_account.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The service account ID." })), + "data": Schema.optionalKey( + Schema.Struct({ + "role": Schema.optionalKey( + Schema.String.annotate({ "description": "The role of the service account. Is either `owner` or `member`." }) + ) + }).annotate({ "description": "The payload used to create the service account." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "service_account.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The service account ID." })), + "changes_requested": Schema.optionalKey( + Schema.Struct({ + "role": Schema.optionalKey( + Schema.String.annotate({ "description": "The role of the service account. Is either `owner` or `member`." }) + ) + }).annotate({ "description": "The payload used to updated the service account." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "service_account.deleted": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The service account ID." })) }) + .annotate({ "description": "The details for events with this `type`." }) + ), + "workload_identity_provider.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The workload identity provider ID." })), + "data": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The payload used to create the workload identity provider." + }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "workload_identity_provider.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The workload identity provider ID." })), + "changes_requested": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The payload used to update the workload identity provider." + }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "workload_identity_provider.deleted": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The workload identity provider ID." })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The workload identity provider name." })) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "workload_identity_provider_mapping.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The workload identity provider mapping ID." })), + "identity_provider_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The workload identity provider ID." }) + ), + "data": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The payload used to create the workload identity provider mapping." + }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "workload_identity_provider_mapping.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The workload identity provider mapping ID." })), + "identity_provider_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The workload identity provider ID." }) + ), + "changes_requested": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "The payload used to update the workload identity provider mapping." + }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "workload_identity_provider_mapping.deleted": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The workload identity provider mapping ID." })), + "identity_provider_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The workload identity provider ID." }) + ), + "project_id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), + "service_account_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The mapped service account ID." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "user.added": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The user ID." })), + "data": Schema.optionalKey( + Schema.Struct({ + "role": Schema.optionalKey( + Schema.String.annotate({ "description": "The role of the user. Is either `owner` or `member`." }) + ) + }).annotate({ "description": "The payload used to add the user to the project." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "user.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The project ID." })), + "changes_requested": Schema.optionalKey( + Schema.Struct({ + "role": Schema.optionalKey( + Schema.String.annotate({ "description": "The role of the user. Is either `owner` or `member`." }) + ) + }).annotate({ "description": "The payload used to update the user." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "user.deleted": Schema.optionalKey( + Schema.Struct({ "id": Schema.optionalKey(Schema.String.annotate({ "description": "The user ID." })) }).annotate({ + "description": "The details for events with this `type`." + }) + ), + "certificate.created": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "certificate.updated": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "certificate.deleted": Schema.optionalKey( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })), + "certificate": Schema.optionalKey( + Schema.String.annotate({ "description": "The certificate content in PEM format." }) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "certificates.activated": Schema.optionalKey( + Schema.Struct({ + "certificates": Schema.optionalKey( + Schema.Array( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })) + }) + ) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ), + "certificates.deactivated": Schema.optionalKey( + Schema.Struct({ + "certificates": Schema.optionalKey( + Schema.Array( + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The certificate ID." })), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the certificate." })) + }) + ) + ) + }).annotate({ "description": "The details for events with this `type`." }) + ) +}).annotate({ + "description": "A log of a user action or configuration change within this organization.", + "identifier": "AuditLog" +}) +export type CreateThreadAndRunRequest = { + readonly "assistant_id": string + readonly "thread"?: CreateThreadRequest + readonly "model"?: + | string + | "gpt-5" + | "gpt-5-mini" + | "gpt-5-nano" + | "gpt-5-2025-08-07" + | "gpt-5-mini-2025-08-07" + | "gpt-5-nano-2025-08-07" + | "gpt-4.1" + | "gpt-4.1-mini" + | "gpt-4.1-nano" + | "gpt-4.1-2025-04-14" + | "gpt-4.1-mini-2025-04-14" + | "gpt-4.1-nano-2025-04-14" + | "gpt-4o" + | "gpt-4o-2024-11-20" + | "gpt-4o-2024-08-06" + | "gpt-4o-2024-05-13" + | "gpt-4o-mini" + | "gpt-4o-mini-2024-07-18" + | "gpt-4.5-preview" + | "gpt-4.5-preview-2025-02-27" + | "gpt-4-turbo" + | "gpt-4-turbo-2024-04-09" + | "gpt-4-0125-preview" + | "gpt-4-turbo-preview" + | "gpt-4-1106-preview" + | "gpt-4-vision-preview" + | "gpt-4" + | "gpt-4-0314" + | "gpt-4-0613" + | "gpt-4-32k" + | "gpt-4-32k-0314" + | "gpt-4-32k-0613" + | "gpt-3.5-turbo" + | "gpt-3.5-turbo-16k" + | "gpt-3.5-turbo-0613" + | "gpt-3.5-turbo-1106" + | "gpt-3.5-turbo-0125" + | "gpt-3.5-turbo-16k-0613" + | null + readonly "instructions"?: string | null + readonly "tools"?: ReadonlyArray | null + readonly "tool_resources"?: + | { + readonly "code_interpreter"?: { readonly "file_ids"?: ReadonlyArray } + readonly "file_search"?: { readonly "vector_store_ids"?: ReadonlyArray } + } & { readonly [x: string]: Schema.Json } + | null + readonly "metadata"?: Metadata + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "stream"?: boolean | null + readonly "max_prompt_tokens"?: number | null + readonly "max_completion_tokens"?: number | null + readonly "truncation_strategy"?: TruncationObject | null + readonly "tool_choice"?: AssistantsApiToolChoiceOption | null + readonly "parallel_tool_calls"?: ParallelToolCalls + readonly "response_format"?: AssistantsApiResponseFormatOption | null +} +export const CreateThreadAndRunRequest = Schema.Struct({ + "assistant_id": Schema.String.annotate({ + "description": + "The ID of the [assistant](https://developers.openai.com/api/docs/assistants/migration) to use to execute this run." + }), + "thread": Schema.optionalKey(CreateThreadRequest), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-5", + "gpt-5-mini", + "gpt-5-nano", + "gpt-5-2025-08-07", + "gpt-5-mini-2025-08-07", + "gpt-5-nano-2025-08-07", + "gpt-4.1", + "gpt-4.1-mini", + "gpt-4.1-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "gpt-4o", + "gpt-4o-2024-11-20", + "gpt-4o-2024-08-06", + "gpt-4o-2024-05-13", + "gpt-4o-mini", + "gpt-4o-mini-2024-07-18", + "gpt-4.5-preview", + "gpt-4.5-preview-2025-02-27", + "gpt-4-turbo", + "gpt-4-turbo-2024-04-09", + "gpt-4-0125-preview", + "gpt-4-turbo-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-4", + "gpt-4-0314", + "gpt-4-0613", + "gpt-4-32k", + "gpt-4-32k-0314", + "gpt-4-32k-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k", + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo-1106", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-16k-0613" + ]), + Schema.Null + ]).annotate({ + "description": + "The ID of the [Model](https://developers.openai.com/api/reference/resources/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used." + }) + ), + "instructions": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis." + }) + ), + "tools": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.Union([AssistantToolsCode, AssistantToolsFileSearch, AssistantToolsFunction], { mode: "oneOf" }) + ).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })), + Schema.Null + ]).annotate({ + "description": + "Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis." + }) + ), + "tool_resources": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "code_interpreter": Schema.optionalKey(Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [file](https://developers.openai.com/api/reference/resources/files) IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool.\n" + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })) + ) + })), + "file_search": Schema.optionalKey(Schema.Struct({ + "vector_store_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "The ID of the [vector store](https://developers.openai.com/api/reference/resources/vector_stores) attached to this assistant. There can be a maximum of 1 vector store attached to the assistant.\n" + }).check(Schema.isMaxLength(1).annotate({ "expected": "a value with a length of at most 1" })) + ) + })) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ + "description": + "A set of resources that are used by the assistant's tools. The resources are specific to the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the `file_search` tool requires a list of vector store IDs.\n" + }) + ), + "metadata": Schema.optionalKey(Metadata), + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]).annotate({ + "description": + "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n" + }) + ), + "top_p": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + Schema.Null + ]).annotate({ + "description": + "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or temperature but not both.\n" + }) + ), + "stream": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": + "If `true`, returns a stream of events that happen during the Run as server-sent events, terminating when the Run enters a terminal state with a `data: [DONE]` message.\n" + }) + ), + "max_prompt_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(256).annotate({ "expected": "a value greater than or equal to 256" }) + ), + Schema.Null + ]).annotate({ + "description": + "The maximum number of prompt tokens that may be used over the course of the run. The run will make a best effort to use only the number of prompt tokens specified, across multiple turns of the run. If the run exceeds the number of prompt tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info.\n" + }) + ), + "max_completion_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(256).annotate({ "expected": "a value greater than or equal to 256" }) + ), + Schema.Null + ]).annotate({ + "description": + "The maximum number of completion tokens that may be used over the course of the run. The run will make a best effort to use only the number of completion tokens specified, across multiple turns of the run. If the run exceeds the number of completion tokens specified, the run will end with status `incomplete`. See `incomplete_details` for more info.\n" + }) + ), + "truncation_strategy": Schema.optionalKey(Schema.Union([TruncationObject, Schema.Null])), + "tool_choice": Schema.optionalKey(Schema.Union([AssistantsApiToolChoiceOption, Schema.Null])), + "parallel_tool_calls": Schema.optionalKey(ParallelToolCalls), + "response_format": Schema.optionalKey(Schema.Union([AssistantsApiResponseFormatOption, Schema.Null])) +}).annotate({ "identifier": "CreateThreadAndRunRequest" }) +export type RunStepDeltaObject = { + readonly "id": string + readonly "object": "thread.run.step.delta" + readonly "delta": { + readonly "step_details"?: RunStepDeltaStepDetailsMessageCreationObject | RunStepDeltaStepDetailsToolCallsObject + } +} +export const RunStepDeltaObject = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The identifier of the run step, which can be referenced in API endpoints." + }), + "object": Schema.Literal("thread.run.step.delta").annotate({ + "description": "The object type, which is always `thread.run.step.delta`." + }), + "delta": Schema.Struct({ + "step_details": Schema.optionalKey( + Schema.Union([RunStepDeltaStepDetailsMessageCreationObject, RunStepDeltaStepDetailsToolCallsObject], { + mode: "oneOf" + }).annotate({ "description": "The details of the run step." }) + ) + }).annotate({ "description": "The delta containing the fields that have changed on the run step." }) +}).annotate({ + "title": "Run step delta object", + "description": "Represents a run step delta i.e. any changed fields on a run step during streaming.\n", + "identifier": "RunStepDeltaObject" +}) +export type ListMessagesResponse = + | null + | string + | number + | boolean + | { + readonly "object": string + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean + } & { readonly [x: string]: Schema.Json } + | ReadonlyArray +export const ListMessagesResponse = Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.StructWithRest( + Schema.Struct({ + "object": Schema.String, + "data": Schema.Array(MessageObject), + "first_id": Schema.String, + "last_id": Schema.String, + "has_more": Schema.Boolean + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Array(Schema.Json.annotate({ "expected": "JSON value" })) +]).annotate({ "identifier": "ListMessagesResponse" }) +export type MessageStreamEvent = + | { readonly "event": "thread.message.created"; readonly "data": MessageObject } + | { readonly "event": "thread.message.in_progress"; readonly "data": MessageObject } + | { readonly "event": "thread.message.delta"; readonly "data": MessageDeltaObject } + | { readonly "event": "thread.message.completed"; readonly "data": MessageObject } + | { readonly "event": "thread.message.incomplete"; readonly "data": MessageObject } +export const MessageStreamEvent = Schema.Union([ + Schema.Struct({ "event": Schema.Literal("thread.message.created"), "data": MessageObject }).annotate({ + "description": "Occurs when a [message](https://developers.openai.com/api/docs/assistants/migration) is created." + }), + Schema.Struct({ "event": Schema.Literal("thread.message.in_progress"), "data": MessageObject }).annotate({ + "description": + "Occurs when a [message](https://developers.openai.com/api/docs/assistants/migration) moves to an `in_progress` state." + }), + Schema.Struct({ "event": Schema.Literal("thread.message.delta"), "data": MessageDeltaObject }).annotate({ + "description": + "Occurs when parts of a [Message](https://developers.openai.com/api/docs/assistants/migration) are being streamed." + }), + Schema.Struct({ "event": Schema.Literal("thread.message.completed"), "data": MessageObject }).annotate({ + "description": "Occurs when a [message](https://developers.openai.com/api/docs/assistants/migration) is completed." + }), + Schema.Struct({ "event": Schema.Literal("thread.message.incomplete"), "data": MessageObject }).annotate({ + "description": + "Occurs when a [message](https://developers.openai.com/api/docs/assistants/migration) ends before it is completed." + }) +], { mode: "oneOf" }).annotate({ "identifier": "MessageStreamEvent" }) +export type CreateVectorStoreFileRequest = { + readonly "file_id": string + readonly "chunking_strategy"?: ChunkingStrategyRequestParam + readonly "attributes"?: VectorStoreFileAttributes +} +export const CreateVectorStoreFileRequest = Schema.Struct({ + "file_id": Schema.String.annotate({ + "description": + "A [File](https://developers.openai.com/api/reference/resources/files) ID that the vector store should use. Useful for tools like `file_search` that can access files. For multi-file ingestion, we recommend [`file_batches`](https://developers.openai.com/api/reference/resources/vector_stores/subresources/file_batches/methods/create) to minimize per-vector-store write requests." + }), + "chunking_strategy": Schema.optionalKey(ChunkingStrategyRequestParam), + "attributes": Schema.optionalKey(VectorStoreFileAttributes) +}).annotate({ "identifier": "CreateVectorStoreFileRequest" }) +export type ListVectorStoreFilesResponse = + | null + | string + | number + | boolean + | { + readonly "object": string + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean + } & { readonly [x: string]: Schema.Json } + | ReadonlyArray +export const ListVectorStoreFilesResponse = Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.StructWithRest( + Schema.Struct({ + "object": Schema.String, + "data": Schema.Array(VectorStoreFileObject), + "first_id": Schema.String, + "last_id": Schema.String, + "has_more": Schema.Boolean + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Array(Schema.Json.annotate({ "expected": "JSON value" })) +]).annotate({ "identifier": "ListVectorStoreFilesResponse" }) +export type PublicDecisionsUsageResponseResource = { + readonly "object": "page" + readonly "has_more": boolean + readonly "next_page": string | null + readonly "data": ReadonlyArray +} +export const PublicDecisionsUsageResponseResource = Schema.Struct({ + "object": Schema.Literal("page"), + "has_more": Schema.Boolean, + "next_page": Schema.Union([Schema.String, Schema.Null]), + "data": Schema.Array(DecisionsUsageBucket) +}).annotate({ "identifier": "PublicDecisionsUsageResponseResource" }) +export type AssistantMessageItem = { + readonly "id": string + readonly "object": "chatkit.thread_item" + readonly "created_at": number + readonly "thread_id": string + readonly "type": "chatkit.assistant_message" + readonly "content": ReadonlyArray +} +export const AssistantMessageItem = Schema.Struct({ + "id": Schema.String.annotate({ "description": "Identifier of the thread item." }), + "object": Schema.Literal("chatkit.thread_item").annotate({ + "description": "Type discriminator that is always `chatkit.thread_item`." + }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) for when the item was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "thread_id": Schema.String.annotate({ "description": "Identifier of the parent thread." }), + "type": Schema.Literal("chatkit.assistant_message").annotate({ + "description": "Type discriminator that is always `chatkit.assistant_message`." + }), + "content": Schema.Array(ResponseOutputText).annotate({ "description": "Ordered assistant response segments." }) +}).annotate({ + "title": "Assistant message", + "description": "Assistant-authored message within a thread.", + "identifier": "AssistantMessageItem" +}) +export type DecisionInputContent = string | DecisionInputContentParts +export const DecisionInputContent = Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.suspend((): Schema.Codec => DecisionInputContentParts).annotate({ + "title": "Parts" + }) +], { mode: "oneOf" }).annotate({ + "description": "Text evidence or an ordered list of text and image parts.", + "identifier": "DecisionInputContent" +}) +export type QuestionParam = QuestionParamPredicate | QuestionParamChoice | QuestionParamScore +export const QuestionParam = Schema.Union([QuestionParamPredicate, QuestionParamChoice, QuestionParamScore], { + mode: "oneOf" +}).annotate({ + "description": "A question about the request's input, with an optional correlation name.", + "identifier": "QuestionParam" +}) +export type AnswerResource = + | AnswerResourcePredicate + | AnswerResourceChoice + | AnswerResourceScore + | AnswerResourceRefusal +export const AnswerResource = Schema.Union([ + AnswerResourcePredicate, + AnswerResourceChoice, + AnswerResourceScore, + AnswerResourceRefusal +], { mode: "oneOf" }).annotate({ + "description": "A completed question always includes its name, including null when unnamed.", + "identifier": "AnswerResource" +}) +export type AgentEnvironmentListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const AgentEnvironmentListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(PublicEnvironmentResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "AgentEnvironmentListResource" +}) +export type HostedSkillParam = HostedSkillParamSkillReference | HostedSkillParamInline +export const HostedSkillParam = Schema.Union([HostedSkillParamSkillReference, HostedSkillParamInline], { + mode: "oneOf" +}).annotate({ "description": "A skill installed in an OpenAI-hosted environment.", "identifier": "HostedSkillParam" }) +export type HostedPluginParam = HostedPluginParamInline +export const HostedPluginParam = Schema.Union([HostedPluginParamInline], { mode: "oneOf" }).annotate({ + "description": "A plugin installed in an OpenAI-hosted environment.", + "identifier": "HostedPluginParam" +}) +export type SessionEventAgentSessionSubagentCreated = { + readonly "type": "agent.session.subagent.created" + readonly "event_id": string + readonly "subagent": SubagentResource +} +export const SessionEventAgentSessionSubagentCreated = Schema.Struct({ + "type": Schema.Literal("agent.session.subagent.created").annotate({ + "description": "The type of the object. Always `agent.session.subagent.created`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "subagent": Schema.suspend((): Schema.Codec => SubagentResource).annotate({ + "description": "The subagent that was created." + }) +}).annotate({ + "description": "Emitted when a subagent is created.", + "identifier": "SessionEventAgentSessionSubagentCreated" +}) +export type SessionEventAgentSessionSubagentActive = { + readonly "type": "agent.session.subagent.active" + readonly "event_id": string + readonly "subagent": SubagentResource +} +export const SessionEventAgentSessionSubagentActive = Schema.Struct({ + "type": Schema.Literal("agent.session.subagent.active").annotate({ + "description": "The type of the object. Always `agent.session.subagent.active`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "subagent": Schema.suspend((): Schema.Codec => SubagentResource).annotate({ + "description": "The subagent that resumed." + }) +}).annotate({ + "description": "Emitted when a closed subagent successfully resumes.", + "identifier": "SessionEventAgentSessionSubagentActive" +}) +export type SessionEventAgentSessionSubagentClosed = { + readonly "type": "agent.session.subagent.closed" + readonly "event_id": string + readonly "subagent": SubagentResource +} +export const SessionEventAgentSessionSubagentClosed = Schema.Struct({ + "type": Schema.Literal("agent.session.subagent.closed").annotate({ + "description": "The type of the object. Always `agent.session.subagent.closed`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "subagent": Schema.suspend((): Schema.Codec => SubagentResource).annotate({ + "description": "The subagent that was closed." + }) +}).annotate({ + "description": "Emitted when a subagent is closed.", + "identifier": "SessionEventAgentSessionSubagentClosed" +}) +export type FunctionCallOutputItemResource = { + readonly "id": string + readonly "turn_id": string + readonly "type": "function_call_output" + readonly "call_id": string + readonly "status": FunctionCallStatusResource + readonly "output": FunctionCallOutputResource | null + readonly "error": string | null +} +export const FunctionCallOutputItemResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the function call output item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that contains this item." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "type": Schema.Literal("function_call_output").annotate({ + "description": "The item type. Always `function_call_output`." + }), + "call_id": Schema.String.annotate({ "description": "The ID of the function call that produced this output." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "status": Schema.suspend((): Schema.Codec => FunctionCallStatusResource).annotate({ + "description": "The status of the function call." + }), + "output": Schema.Union([FunctionCallOutputResource, Schema.Null]).annotate({ + "description": "The function result, if the call succeeded." + }), + "error": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The error message, if the call failed." }) +}).annotate({ + "description": "The result supplied for a function call.", + "identifier": "FunctionCallOutputItemResource" +}) +export type BrowserAuthenticationRequestItemResource = { + readonly "turn_id": string + readonly "request_id": string + readonly "request": BrowserAuthenticationHistoryRequestKindResource + readonly "id": string + readonly "type": "computer_use_approval_request" +} +export const BrowserAuthenticationRequestItemResource = Schema.Struct({ + "turn_id": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "request_id": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "request": BrowserAuthenticationHistoryRequestKindResource, + "id": Schema.String.annotate({ "description": "The stable history item ID." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "type": Schema.Literal("computer_use_approval_request").annotate({ + "description": "The item type. Always computer_use_approval_request." + }) +}).annotate({ + "description": "A credential-free history record of the emitted login request.", + "identifier": "BrowserAuthenticationRequestItemResource" +}) +export type SessionRequiredActionResourceComputerUseApprovalRequest = { + readonly "type": "computer_use_approval_request" + readonly "turn_id": string + readonly "request_id": string + readonly "request": ComputerUseApprovalRequestKindResource +} +export const SessionRequiredActionResourceComputerUseApprovalRequest = Schema.Struct({ + "type": Schema.Literal("computer_use_approval_request").annotate({ + "description": "The type of the object. Always `computer_use_approval_request`." + }), + "turn_id": Schema.String.annotate({ "description": "The turn that requested approval." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "request_id": Schema.String.annotate({ "description": "The registered request ID to echo when responding." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "request": Schema.suspend((): Schema.Codec => + ComputerUseApprovalRequestKindResource + ).annotate({ "description": "The information needed to render the request." }) +}).annotate({ + "description": "Respond to a computer-use request.", + "identifier": "SessionRequiredActionResourceComputerUseApprovalRequest" +}) +export type SessionTurnListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const SessionTurnListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(TurnResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "SessionTurnListResource" +}) +export type SessionEventAgentSessionTurnCreated = { + readonly "type": "agent.session.turn.created" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string + readonly "turn": TurnResource +} +export const SessionEventAgentSessionTurnCreated = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.created").annotate({ + "description": "The type of the object. Always `agent.session.turn.created`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn": Schema.suspend((): Schema.Codec => TurnResource).annotate({ + "description": "The turn at the time it was created." + }) +}).annotate({ "description": "Emitted when a turn is created.", "identifier": "SessionEventAgentSessionTurnCreated" }) +export type SessionEventAgentSessionTurnInProgress = { + readonly "type": "agent.session.turn.in_progress" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string + readonly "turn": TurnResource +} +export const SessionEventAgentSessionTurnInProgress = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.in_progress").annotate({ + "description": "The type of the object. Always `agent.session.turn.in_progress`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn": Schema.suspend((): Schema.Codec => TurnResource).annotate({ + "description": "The turn at the time it started running." + }) +}).annotate({ + "description": "Emitted when a turn starts running.", + "identifier": "SessionEventAgentSessionTurnInProgress" +}) +export type SessionEventAgentSessionTurnCompleted = { + readonly "type": "agent.session.turn.completed" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string + readonly "turn": TurnResource + readonly "usage": TokenUsageResource | null +} +export const SessionEventAgentSessionTurnCompleted = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.completed").annotate({ + "description": "The type of the object. Always `agent.session.turn.completed`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn": Schema.suspend((): Schema.Codec => TurnResource).annotate({ + "description": "The completed turn." + }), + "usage": Schema.Union([TokenUsageResource, Schema.Null]).annotate({ + "description": "Token usage by the root agent during the turn, when available." + }) +}).annotate({ "description": "Emitted when a turn completes.", "identifier": "SessionEventAgentSessionTurnCompleted" }) +export type SessionEventAgentSessionTurnFailed = { + readonly "type": "agent.session.turn.failed" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string + readonly "turn": TurnResource + readonly "usage": TokenUsageResource | null +} +export const SessionEventAgentSessionTurnFailed = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.failed").annotate({ + "description": "The type of the object. Always `agent.session.turn.failed`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn": Schema.suspend((): Schema.Codec => TurnResource).annotate({ + "description": "The failed turn." + }), + "usage": Schema.Union([TokenUsageResource, Schema.Null]).annotate({ + "description": "Token usage by the root agent during the turn, when available." + }) +}).annotate({ "description": "Emitted when a turn fails.", "identifier": "SessionEventAgentSessionTurnFailed" }) +export type SessionEventAgentSessionTurnCancelled = { + readonly "type": "agent.session.turn.cancelled" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string + readonly "turn": TurnResource + readonly "usage": TokenUsageResource | null +} +export const SessionEventAgentSessionTurnCancelled = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.cancelled").annotate({ + "description": "The type of the object. Always `agent.session.turn.cancelled`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn": Schema.suspend((): Schema.Codec => TurnResource).annotate({ + "description": "The cancelled turn." + }), + "usage": Schema.Union([TokenUsageResource, Schema.Null]).annotate({ + "description": "Token usage by the root agent during the turn, when available." + }) +}).annotate({ + "description": "Emitted when a turn is cancelled.", + "identifier": "SessionEventAgentSessionTurnCancelled" +}) +export type PersistedAgentToolResource = + | PersistedAgentToolResourceFunction + | PersistedAgentToolResourceToolSearch + | PersistedAgentToolResourceProgrammaticToolCalling + | PersistedAgentToolResourceMcp + | PersistedAgentToolResourceWebSearch + | PersistedAgentToolResourceComputerUse +export const PersistedAgentToolResource = Schema.Union([ + PersistedAgentToolResourceFunction, + PersistedAgentToolResourceToolSearch, + PersistedAgentToolResourceProgrammaticToolCalling, + PersistedAgentToolResourceMcp, + PersistedAgentToolResourceWebSearch, + PersistedAgentToolResourceComputerUse +], { mode: "oneOf" }).annotate({ + "description": "A credential-free tool available to a reusable agent.", + "identifier": "PersistedAgentToolResource" +}) +export type UpdateAgentSessionParams = { + readonly "spend_control"?: SessionSpendControlParam | null + readonly "agent"?: UpdateSessionAgentParam + readonly "metadata"?: { readonly [x: string]: string } | null +} +export const UpdateAgentSessionParams = Schema.Struct({ + "spend_control": Schema.optionalKey( + Schema.Union([SessionSpendControlParam, Schema.Null]).annotate({ + "description": "Omit to retain the limit; null or a null limit removes it without resetting spend." + }) + ), + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => UpdateSessionAgentParam).annotate({ + "description": "Model settings for subsequent turns. Omitted fields stay unchanged." + }) + ), + "metadata": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ + "description": + "Replaces all metadata. Omit to leave unchanged, or pass null or {} to clear it. Up to 16 string key-value pairs, with keys up to 64 and values up to 512 characters." + }) + ) +}).annotate({ "description": "Fields to update on an existing session.", "identifier": "UpdateAgentSessionParams" }) +export type PersistedAgentToolConfigParam = + | PersistedAgentToolConfigParamFunction + | PersistedAgentToolConfigParamToolSearch + | PersistedAgentToolConfigParamProgrammaticToolCalling + | PersistedAgentToolConfigParamMcp + | PersistedAgentToolConfigParamWebSearch + | PersistedAgentToolConfigParamComputerUse +export const PersistedAgentToolConfigParam = Schema.Union([ + PersistedAgentToolConfigParamFunction, + PersistedAgentToolConfigParamToolSearch, + PersistedAgentToolConfigParamProgrammaticToolCalling, + PersistedAgentToolConfigParamMcp, + PersistedAgentToolConfigParamWebSearch, + PersistedAgentToolConfigParamComputerUse +], { mode: "oneOf" }).annotate({ + "description": "A tool that can be stored on a reusable agent without session credentials.", + "identifier": "PersistedAgentToolConfigParam" +}) +export type EnvironmentResource = + | EnvironmentResourceNone + | EnvironmentResourceOpenaiHosted + | EnvironmentResourceSelfHosted +export const EnvironmentResource = Schema.Union([ + EnvironmentResourceNone, + EnvironmentResourceOpenaiHosted, + EnvironmentResourceSelfHosted +], { mode: "oneOf" }).annotate({ + "description": "The execution environment for a session.", + "identifier": "EnvironmentResource" +}) +export type EnvironmentTemplateListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const EnvironmentTemplateListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(EnvironmentTemplateResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "EnvironmentTemplateListResource" +}) +export type AgentToolResource = + | AgentToolResourceFunction + | AgentToolResourceProgrammaticToolCalling + | AgentToolResourceMcp + | AgentToolResourceWebSearch + | AgentToolResourceComputerUse +export const AgentToolResource = Schema.Union([ + AgentToolResourceFunction, + AgentToolResourceProgrammaticToolCalling, + AgentToolResourceMcp, + AgentToolResourceWebSearch, + AgentToolResourceComputerUse +], { mode: "oneOf" }).annotate({ "description": "A tool available to the agent.", "identifier": "AgentToolResource" }) +export type AgentToolConfigParam = + | AgentToolConfigParamFunction + | AgentToolConfigParamToolSearch + | AgentToolConfigParamProgrammaticToolCalling + | AgentToolConfigParamMcp + | AgentToolConfigParamWebSearch + | AgentToolConfigParamComputerUse +export const AgentToolConfigParam = Schema.Union([ + AgentToolConfigParamFunction, + AgentToolConfigParamToolSearch, + AgentToolConfigParamProgrammaticToolCalling, + AgentToolConfigParamMcp, + AgentToolConfigParamWebSearch, + AgentToolConfigParamComputerUse +], { mode: "oneOf" }).annotate({ + "description": "A tool available to the agent.", + "identifier": "AgentToolConfigParam" +}) +export type CreateSessionInputParam = string | ReadonlyArray +export const CreateSessionInputParam = Schema.Union([ + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + Schema.Array(InputMessageParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" })) +], { mode: "oneOf" }).annotate({ + "description": "Initial input submitted when creating a session.", + "identifier": "CreateSessionInputParam" +}) +export type SessionInputParamAgentSessionInputMessage = { + readonly "type": "agent.session.input.message" + readonly "input": ReadonlyArray +} +export const SessionInputParamAgentSessionInputMessage = Schema.Struct({ + "type": Schema.Literal("agent.session.input.message").annotate({ + "description": "The type of the object. Always `agent.session.input.message`." + }), + "input": Schema.Array(InputMessageParam).annotate({ "description": "The user messages to add to the session." }) + .check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ) +}).annotate({ + "description": "Adds one or more user messages and starts a turn.", + "identifier": "SessionInputParamAgentSessionInputMessage" +}) +export type SessionInputParamAgentSessionInputToolResult = { + readonly "type": "agent.session.input.tool_result" + readonly "turn_id": string + readonly "call_id": string + readonly "success": boolean + readonly "output"?: FunctionCallOutputParam | null + readonly "error"?: string | null +} +export const SessionInputParamAgentSessionInputToolResult = Schema.Struct({ + "type": Schema.Literal("agent.session.input.tool_result").annotate({ + "description": "The type of the object. Always `agent.session.input.tool_result`." + }), + "turn_id": Schema.String.annotate({ "description": "The ID of the turn that requested the function call." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "call_id": Schema.String.annotate({ "description": "The ID of the function call." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "success": Schema.Boolean.annotate({ "description": "Whether the function call succeeded." }), + "output": Schema.optionalKey( + Schema.Union([FunctionCallOutputParam, Schema.Null]).annotate({ + "description": "The function result when the call succeeded." + }) + ), + "error": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "The error message when the call failed." }) + ) +}).annotate({ + "description": "Submits the result of a function call.", + "identifier": "SessionInputParamAgentSessionInputToolResult" +}) +export type SessionInputParamAgentSessionInputComputerUseApprovalRequestResult = { + readonly "type": "agent.session.input.computer_use_approval_request_result" + readonly "request_id": string + readonly "response": ComputerUseApprovalResponseParam +} +export const SessionInputParamAgentSessionInputComputerUseApprovalRequestResult = Schema.Struct({ + "type": Schema.Literal("agent.session.input.computer_use_approval_request_result").annotate({ + "description": "The type of the object. Always `agent.session.input.computer_use_approval_request_result`." + }), + "request_id": Schema.String.annotate({ "description": "The registered request ID from the required action." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "response": Schema.suspend((): Schema.Codec => ComputerUseApprovalResponseParam) + .annotate({ "description": "The response for this request type." }) +}).annotate({ + "description": "Responds to a pending Computer Use approval request.", + "identifier": "SessionInputParamAgentSessionInputComputerUseApprovalRequestResult" +}) +export type VaultCredentialAuthResourceMcpOauth = { + readonly "type": "mcp_oauth" + readonly "mcp_server_url": string + readonly "expires_at": string | null + readonly "refresh": McpOauthRefreshResource | null +} +export const VaultCredentialAuthResourceMcpOauth = Schema.Struct({ + "type": Schema.Literal("mcp_oauth").annotate({ "description": "The type of the object. Always `mcp_oauth`." }), + "mcp_server_url": Schema.String.annotate({ "description": "The HTTPS MCP server URL authorized by this credential." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + "expires_at": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "When the OAuth access token expires, as an RFC 3339 timestamp, if known." }), + "refresh": Schema.Union([McpOauthRefreshResource, Schema.Null]).annotate({ + "description": "Public refresh metadata without refresh tokens or OAuth client secrets." + }) +}).annotate({ + "description": "Public metadata for an OAuth credential; tokens and client secrets are never returned.", + "identifier": "VaultCredentialAuthResourceMcpOauth" +}) +export type CreateVaultCredentialAuthParamMcpOauth = { + readonly "type": "mcp_oauth" + readonly "mcp_server_url": string + readonly "access_token": string + readonly "expires_at"?: string | null + readonly "refresh"?: CreateMcpOauthRefreshParam | null +} +export const CreateVaultCredentialAuthParamMcpOauth = Schema.Struct({ + "type": Schema.Literal("mcp_oauth").annotate({ "description": "The type of the object. Always `mcp_oauth`." }), + "mcp_server_url": Schema.String.annotate({ "description": "The HTTPS MCP server URL authorized by this credential." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "access_token": Schema.String.annotate({ + "description": "A write-only OAuth access token; never returned by credential resources." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "expires_at": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "When the OAuth access token expires, as an RFC 3339 timestamp, if known." }) + ), + "refresh": Schema.optionalKey( + Schema.Union([CreateMcpOauthRefreshParam, Schema.Null]).annotate({ + "description": "Optional refresh configuration for an HTTPS OAuth token endpoint." + }) + ) +}).annotate({ + "description": "An OAuth credential for an HTTPS MCP destination.", + "identifier": "CreateVaultCredentialAuthParamMcpOauth" +}) +export type RotateVaultCredentialAuthParamMcpOauth = { + readonly "type": "mcp_oauth" + readonly "access_token"?: string | null + readonly "expires_at"?: string | null + readonly "refresh"?: RotateMcpOauthRefreshParam | null +} +export const RotateVaultCredentialAuthParamMcpOauth = Schema.Struct({ + "type": Schema.Literal("mcp_oauth").annotate({ "description": "The type of the object. Always `mcp_oauth`." }), + "access_token": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ "description": "A write-only replacement OAuth access token." }) + ), + "expires_at": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "The replacement expiry as an RFC 3339 timestamp, or `null` to clear it. Omitting this field preserves the expiry unless a new access token is supplied, in which case the expiry is cleared." + }) + ), + "refresh": Schema.optionalKey( + Schema.Union([RotateMcpOauthRefreshParam, Schema.Null]).annotate({ + "description": "Optional write-only refresh-token and client-secret updates." + }) + ) +}).annotate({ + "description": "Rotate an OAuth credential for an HTTPS MCP destination.", + "identifier": "RotateVaultCredentialAuthParamMcpOauth" +}) +export type BetaResponseTextParam = { + readonly "format"?: BetaTextResponseFormatConfiguration + readonly "verbosity"?: BetaVerbosity +} +export const BetaResponseTextParam = Schema.Struct({ + "format": Schema.optionalKey(BetaTextResponseFormatConfiguration), + "verbosity": Schema.optionalKey(BetaVerbosity) +}).annotate({ + "description": + "Configuration options for a text response from the model. Can be plain\ntext or structured JSON data. Learn more:\n- [Text inputs and outputs](https://developers.openai.com/api/docs/guides/text)\n- [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs)\n", + "identifier": "BetaResponseTextParam" +}) +export type BetaCodeInterpreterTool = { + readonly "type": "code_interpreter" + readonly "container": string | BetaAutoCodeInterpreterToolParam + readonly "allowed_callers"?: ReadonlyArray | null +} +export const BetaCodeInterpreterTool = Schema.Struct({ + "type": Schema.Literal("code_interpreter").annotate({ + "description": "The type of the code interpreter tool. Always `code_interpreter`.\n" + }), + "container": Schema.Union([ + Schema.String.annotate({ "description": "The container ID." }), + BetaAutoCodeInterpreterToolParam + ], { mode: "oneOf" }).annotate({ + "description": + "The code interpreter container. Can be a container ID or an object that\nspecifies uploaded file IDs to make available to your code, along with an\noptional `memory_limit` setting.\n" + }), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaCallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ + "title": "Code interpreter", + "description": "A tool that runs Python code to help generate a response to a prompt.\n", + "identifier": "BetaCodeInterpreterTool" +}) +export type BetaFunctionShellToolParam = { + readonly "type": "shell" + readonly "environment"?: BetaContainerAutoParam | BetaLocalEnvironmentParam | BetaContainerReferenceParam | null + readonly "allowed_callers"?: ReadonlyArray | null +} +export const BetaFunctionShellToolParam = Schema.Struct({ + "type": Schema.Literal("shell").annotate({ "description": "The type of the shell tool. Always `shell`." }), + "environment": Schema.optionalKey( + Schema.Union([ + Schema.Union([BetaContainerAutoParam, BetaLocalEnvironmentParam, BetaContainerReferenceParam], { mode: "oneOf" }), + Schema.Null + ]) + ), + "allowed_callers": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaCallableToolAllowedCaller).annotate({ "description": "The tool invocation context(s)." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Null + ]) + ) +}).annotate({ + "title": "Shell tool", + "description": "A tool that allows the model to execute shell commands.", + "identifier": "BetaFunctionShellToolParam" +}) +export type BetaNamespaceToolParam = { + readonly "type": "namespace" + readonly "name": string + readonly "description": string + readonly "tools": ReadonlyArray +} +export const BetaNamespaceToolParam = Schema.Struct({ + "type": Schema.Literal("namespace").annotate({ "description": "The type of the tool. Always `namespace`." }), + "name": Schema.String.annotate({ "description": "The namespace name used in tool calls (for example, `crm`)." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "description": Schema.String.annotate({ "description": "A description of the namespace shown to the model." }), + "tools": Schema.Array( + Schema.Union([BetaFunctionToolParam, BetaCustomToolParam], { mode: "oneOf" }).annotate({ + "description": "A function or custom tool that belongs to a namespace." + }) + ).annotate({ "description": "The function/custom tools available inside this namespace." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ) +}).annotate({ + "title": "Namespace", + "description": "Groups function/custom tools under a shared namespace.", + "identifier": "BetaNamespaceToolParam" +}) +export type BetaToolSearchOutputNamespaceToolParam = { + readonly "type": "namespace" + readonly "name": string + readonly "description": string + readonly "tools": ReadonlyArray +} +export const BetaToolSearchOutputNamespaceToolParam = Schema.Struct({ + "type": Schema.Literal("namespace").annotate({ "description": "The type of the tool. Always `namespace`." }), + "name": Schema.String.annotate({ "description": "The namespace name used in tool calls (for example, `crm`)." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "description": Schema.String.annotate({ "description": "A description of the namespace shown to the model." }), + "tools": Schema.Array( + Schema.Union([BetaToolSearchOutputFunctionToolParam, BetaCustomToolParam], { mode: "oneOf" }).annotate({ + "description": "A function or custom tool loaded into a namespace by tool search." + }) + ).annotate({ "description": "The function/custom tools loaded inside this namespace." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ) +}).annotate({ + "title": "Namespace", + "description": "Groups function/custom tools under a shared namespace.", + "identifier": "BetaToolSearchOutputNamespaceToolParam" +}) +export type BetaPrompt = { + readonly "id": string + readonly "version"?: string | null + readonly "variables"?: BetaResponsePromptVariables +} | null +export const BetaPrompt = Schema.Union([ + Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique identifier of the prompt template to use." }), + "version": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Optional version of the prompt template." }), Schema.Null]) + ), + "variables": Schema.optionalKey(BetaResponsePromptVariables) + }).annotate({ + "description": + "Reference to a prompt template and its variables.\n[Learn more](https://developers.openai.com/api/docs/guides/text?api-mode=responses#version-prompts-in-code).\n" + }), + Schema.Null +]).annotate({ "identifier": "BetaPrompt" }) +export type BetaInputMessageContentList = ReadonlyArray +export const BetaInputMessageContentList = Schema.Array(BetaInputContent).annotate({ + "title": "Input item content list", + "description": "A list of one or many input items to the model, containing different content \ntypes.\n", + "identifier": "BetaInputMessageContentList" +}) +export type BetaFunctionToolCallOutputResource = { + readonly "agent"?: BetaAgentTag | null + readonly "id": string + readonly "type": "function_call_output" + readonly "call_id"?: string + readonly "name"?: string + readonly "namespace"?: string + readonly "caller"?: BetaToolCallCallerParam | null + readonly "output": string | ReadonlyArray + readonly "status": "in_progress" | "completed" | "incomplete" + readonly "created_by"?: string +} +export const BetaFunctionToolCallOutputResource = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "id": Schema.String.annotate({ "description": "The unique ID of the function call tool output.\n" }), + "type": Schema.Literal("function_call_output").annotate({ + "description": "The type of the function tool call output. Always `function_call_output`.\n" + }), + "call_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the function tool call generated by the model.\n" }) + ), + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the tool that produced the output.\n" }) + ), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the tool that produced the output.\n" }) + ), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the function call.\n" + }), + Schema.Array(BetaFunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the function call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the function call generated by your code.\nCan be a string or an list of output content.\n" + }), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "identifier": "BetaFunctionToolCallOutputResource" }) +export type BetaCustomToolCallOutputResource = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "custom_tool_call_output" + readonly "id": string + readonly "call_id": string + readonly "caller"?: BetaToolCallCallerParam | null + readonly "output": string | ReadonlyArray + readonly "status": BetaFunctionCallOutputStatusEnum + readonly "created_by"?: string +} +export const BetaCustomToolCallOutputResource = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("custom_tool_call_output").annotate({ + "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the custom tool call output item.\n" }), + "call_id": Schema.String.annotate({ + "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" + }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the custom tool call.\n" + }), + Schema.Array(BetaFunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the custom tool call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" + }), + "status": Schema.suspend((): Schema.Codec => BetaFunctionCallOutputStatusEnum) + .annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item.\n" }) + ) +}).annotate({ "title": "ResponseCustomToolCallOutputItem", "identifier": "BetaCustomToolCallOutputResource" }) +export type BetaFunctionToolCallOutput = { + readonly "agent"?: BetaAgentTag | null + readonly "id"?: string + readonly "type": "function_call_output" + readonly "call_id"?: string + readonly "name"?: string + readonly "namespace"?: string + readonly "caller"?: BetaToolCallCallerParam | null + readonly "output": string | ReadonlyArray + readonly "status"?: "in_progress" | "completed" | "incomplete" +} +export const BetaFunctionToolCallOutput = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "id": Schema.optionalKey( + Schema.String.annotate({ + "description": "The unique ID of the function tool call output. Populated when this item\nis returned via API.\n" + }) + ), + "type": Schema.Literal("function_call_output").annotate({ + "description": "The type of the function tool call output. Always `function_call_output`.\n" + }), + "call_id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the function tool call generated by the model.\n" }) + ), + "name": Schema.optionalKey( + Schema.String.annotate({ "description": "The name of the tool that produced the output.\n" }) + ), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the tool that produced the output.\n" }) + ), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the function call.\n" + }), + Schema.Array(BetaFunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the function call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the function call generated by your code.\nCan be a string or an list of output content.\n" + }), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ) +}).annotate({ + "title": "Function tool call output", + "description": "The output of a function tool call.\n", + "identifier": "BetaFunctionToolCallOutput" +}) +export type BetaCustomToolCallOutput = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "custom_tool_call_output" + readonly "id"?: string + readonly "call_id": string + readonly "caller"?: BetaToolCallCallerParam | null + readonly "output": string | ReadonlyArray +} +export const BetaCustomToolCallOutput = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("custom_tool_call_output").annotate({ + "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" + }), + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the custom tool call output in the OpenAI platform.\n" }) + ), + "call_id": Schema.String.annotate({ + "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" + }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the custom tool call.\n" + }), + Schema.Array(BetaFunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the custom tool call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" + }) +}).annotate({ + "title": "Custom tool call output", + "description": "The output of a custom tool call from your code, being sent back to the model.\n", + "identifier": "BetaCustomToolCallOutput" +}) +export type BetaOutputMessageContent = BetaOutputTextContent | BetaRefusalContent +export const BetaOutputMessageContent = Schema.Union([BetaOutputTextContent, BetaRefusalContent], { mode: "oneOf" }) + .annotate({ "identifier": "BetaOutputMessageContent" }) +export type BetaAgentMessage = { + readonly "agent"?: BetaAgentTag + readonly "type": "agent_message" + readonly "id": string + readonly "author": string + readonly "recipient": string + readonly "content": ReadonlyArray< + | BetaInputTextContent + | BetaOutputTextContent + | BetaTextContent + | BetaSummaryTextContent + | BetaReasoningTextContent + | BetaRefusalContent + | BetaInputImageContent + | BetaComputerScreenshotContent + | BetaInputFileContent + | BetaEncryptedContent + > +} +export const BetaAgentMessage = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("agent_message").annotate({ "description": "The type of the item. Always `agent_message`." }), + "id": Schema.String.annotate({ "description": "The unique ID of the agent message." }), + "author": Schema.String.annotate({ "description": "The sending agent identity." }), + "recipient": Schema.String.annotate({ "description": "The destination agent identity." }), + "content": Schema.Array( + Schema.Union([ + BetaInputTextContent, + BetaOutputTextContent, + BetaTextContent, + BetaSummaryTextContent, + BetaReasoningTextContent, + BetaRefusalContent, + BetaInputImageContent, + BetaComputerScreenshotContent, + BetaInputFileContent, + BetaEncryptedContent + ], { mode: "oneOf" }).annotate({ "description": "A content part that makes up an input or output item." }) + ).annotate({ "description": "Encrypted content sent between agents." }) +}).annotate({ "identifier": "BetaAgentMessage" }) +export type BetaMultiAgentCallOutput = { + readonly "agent"?: BetaAgentTag + readonly "type": "multi_agent_call_output" + readonly "id": string + readonly "call_id": string + readonly "action": BetaMultiAgentAction + readonly "output": ReadonlyArray +} +export const BetaMultiAgentCallOutput = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("multi_agent_call_output").annotate({ + "description": "The type of the multi-agent result. Always `multi_agent_call_output`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the multi-agent call output item." }), + "call_id": Schema.String.annotate({ "description": "The unique ID of the multi-agent call." }), + "action": Schema.suspend((): Schema.Codec => BetaMultiAgentAction).annotate({ + "description": "The multi-agent action that produced this result." + }), + "output": Schema.Array(BetaOutputTextContent).annotate({ + "description": "Text output returned by the multi-agent action." + }) +}).annotate({ "identifier": "BetaMultiAgentCallOutput" }) +export type BetaOutputContent = BetaOutputTextContent | BetaRefusalContent | BetaReasoningTextContent +export const BetaOutputContent = Schema.Union([BetaOutputTextContent, BetaRefusalContent, BetaReasoningTextContent], { + mode: "oneOf" +}).annotate({ "identifier": "BetaOutputContent" }) +export type BetaMessage = { + readonly "agent"?: BetaAgentTag + readonly "type": "message" + readonly "id": string + readonly "status": BetaMessageStatus + readonly "role": BetaMessageRole + readonly "content": ReadonlyArray< + | BetaInputTextContent + | BetaOutputTextContent + | BetaTextContent + | BetaSummaryTextContent + | BetaReasoningTextContent + | BetaRefusalContent + | BetaInputImageContent + | BetaComputerScreenshotContent + | BetaInputFileContent + | BetaEncryptedContent + > + readonly "phase"?: BetaMessagePhase_2 | null +} +export const BetaMessage = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("message").annotate({ "description": "The type of the message. Always set to `message`." }), + "id": Schema.String.annotate({ "description": "The unique ID of the message." }), + "status": Schema.suspend((): Schema.Codec => BetaMessageStatus).annotate({ + "description": + "The status of item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API." + }), + "role": Schema.suspend((): Schema.Codec => BetaMessageRole).annotate({ + "description": + "The role of the message. One of `unknown`, `user`, `assistant`, `system`, `critic`, `discriminator`, `developer`, or `tool`." + }), + "content": Schema.Array( + Schema.Union([ + BetaInputTextContent, + BetaOutputTextContent, + BetaTextContent, + BetaSummaryTextContent, + BetaReasoningTextContent, + BetaRefusalContent, + BetaInputImageContent, + BetaComputerScreenshotContent, + BetaInputFileContent, + BetaEncryptedContent + ], { mode: "oneOf" }).annotate({ "description": "A content part that makes up an input or output item." }) + ).annotate({ "description": "The content of the message" }), + "phase": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaMessagePhase_2).annotate({ + "description": + "Labels an `assistant` message as intermediate commentary (`commentary`) or the final answer (`final_answer`). For models like `gpt-5.3-codex` and beyond, when sending follow-up requests, preserve and resend phase on all assistant messages — dropping it can degrade performance. Not used for user messages." + }), + Schema.Null + ]) + ) +}).annotate({ "title": "Message", "description": "A message to or from the model.", "identifier": "BetaMessage" }) +export type BetaComputerActionList = ReadonlyArray +export const BetaComputerActionList = Schema.Array(BetaComputerAction).annotate({ + "title": "Computer Action List", + "description": + "Flattened batched actions for `computer_use`. Each action includes an\n`type` discriminator and action-specific fields.\n", + "identifier": "BetaComputerActionList" +}) +export type BetaModerationParam = { readonly "model": string; readonly "policy"?: BetaModerationPolicyParam | null } +export const BetaModerationParam = Schema.Struct({ + "model": Schema.String.annotate({ + "description": "The moderation model to use for moderated completions, e.g. 'omni-moderation-latest'." + }), + "policy": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaModerationPolicyParam).annotate({ + "description": "The policy to apply to moderated response input and output." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "Configuration for running moderation on the input and output of this response.", + "identifier": "BetaModerationParam" +}) +export type BetaErrorResponse = { readonly "error": BetaError } +export const BetaErrorResponse = Schema.Struct({ "error": BetaError }).annotate({ "identifier": "BetaErrorResponse" }) +export type RunStepObject = { + readonly "id": string + readonly "object": "thread.run.step" + readonly "created_at": number + readonly "assistant_id": string + readonly "thread_id": string + readonly "run_id": string + readonly "type": "message_creation" | "tool_calls" + readonly "status": "in_progress" | "cancelled" | "failed" | "completed" | "expired" + readonly "step_details": RunStepDetailsMessageCreationObject | RunStepDetailsToolCallsObject + readonly "last_error": { readonly "code": "server_error" | "rate_limit_exceeded"; readonly "message": string } | null + readonly "expired_at": number | null + readonly "cancelled_at": number | null + readonly "failed_at": number | null + readonly "completed_at": number | null + readonly "metadata": Metadata + readonly "usage": RunStepCompletionUsage +} +export const RunStepObject = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The identifier of the run step, which can be referenced in API endpoints." + }), + "object": Schema.Literal("thread.run.step").annotate({ + "description": "The object type, which is always `thread.run.step`." + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the run step was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "assistant_id": Schema.String.annotate({ + "description": + "The ID of the [assistant](https://developers.openai.com/api/docs/assistants/migration) associated with the run step." + }), + "thread_id": Schema.String.annotate({ + "description": "The ID of the [thread](https://developers.openai.com/api/docs/assistants/migration) that was run." + }), + "run_id": Schema.String.annotate({ + "description": + "The ID of the [run](https://developers.openai.com/api/docs/assistants/migration) that this run step is a part of." + }), + "type": Schema.Literals(["message_creation", "tool_calls"]).annotate({ + "description": "The type of run step, which can be either `message_creation` or `tool_calls`." + }), + "status": Schema.Literals(["in_progress", "cancelled", "failed", "completed", "expired"]).annotate({ + "description": + "The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, `completed`, or `expired`." + }), + "step_details": Schema.Union([RunStepDetailsMessageCreationObject, RunStepDetailsToolCallsObject], { mode: "oneOf" }) + .annotate({ "description": "The details of the run step." }), + "last_error": Schema.Union([ + Schema.Struct({ + "code": Schema.Literals(["server_error", "rate_limit_exceeded"]).annotate({ + "description": "One of `server_error` or `rate_limit_exceeded`." + }), + "message": Schema.String.annotate({ "description": "A human-readable description of the error." }) + }).annotate({ + "description": "The last error associated with this run step. Will be `null` if there are no errors." + }), + Schema.Null + ]), + "expired_at": Schema.Union([ + Schema.Number.annotate({ + "description": + "The Unix timestamp (in seconds) for when the run step expired. A step is considered expired if the parent run is expired.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "cancelled_at": Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the run step was cancelled.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "failed_at": Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the run step failed.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "completed_at": Schema.Union([ + Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the run step completed.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "metadata": Metadata, + "usage": RunStepCompletionUsage +}).annotate({ + "title": "Run steps", + "description": "Represents a step in execution of a run.\n", + "identifier": "RunStepObject" +}) +export type ListAssistantsResponse = { + readonly "object": string + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean +} +export const ListAssistantsResponse = Schema.Struct({ + "object": Schema.String, + "data": Schema.Array(AssistantObject), + "first_id": Schema.String, + "last_id": Schema.String, + "has_more": Schema.Boolean +}).annotate({ "identifier": "ListAssistantsResponse" }) +export type RunStreamEvent = + | { readonly "event": "thread.run.created"; readonly "data": RunObject } + | { readonly "event": "thread.run.queued"; readonly "data": RunObject } + | { readonly "event": "thread.run.in_progress"; readonly "data": RunObject } + | { readonly "event": "thread.run.requires_action"; readonly "data": RunObject } + | { readonly "event": "thread.run.completed"; readonly "data": RunObject } + | { readonly "event": "thread.run.incomplete"; readonly "data": RunObject } + | { readonly "event": "thread.run.failed"; readonly "data": RunObject } + | { readonly "event": "thread.run.cancelling"; readonly "data": RunObject } + | { readonly "event": "thread.run.cancelled"; readonly "data": RunObject } + | { readonly "event": "thread.run.expired"; readonly "data": RunObject } +export const RunStreamEvent = Schema.Union([ + Schema.Struct({ "event": Schema.Literal("thread.run.created"), "data": RunObject }).annotate({ + "description": "Occurs when a new [run](https://developers.openai.com/api/docs/assistants/migration) is created." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.queued"), "data": RunObject }).annotate({ + "description": + "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) moves to a `queued` status." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.in_progress"), "data": RunObject }).annotate({ + "description": + "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) moves to an `in_progress` status." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.requires_action"), "data": RunObject }).annotate({ + "description": + "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) moves to a `requires_action` status." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.completed"), "data": RunObject }).annotate({ + "description": "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) is completed." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.incomplete"), "data": RunObject }).annotate({ + "description": + "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) ends with status `incomplete`." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.failed"), "data": RunObject }).annotate({ + "description": "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) fails." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.cancelling"), "data": RunObject }).annotate({ + "description": + "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) moves to a `cancelling` status." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.cancelled"), "data": RunObject }).annotate({ + "description": "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) is cancelled." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.expired"), "data": RunObject }).annotate({ + "description": "Occurs when a [run](https://developers.openai.com/api/docs/assistants/migration) expires." + }) +], { mode: "oneOf" }).annotate({ "identifier": "RunStreamEvent" }) +export type ListRunsResponse = { + readonly "object": string + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean +} +export const ListRunsResponse = Schema.Struct({ + "object": Schema.String, + "data": Schema.Array(RunObject), + "first_id": Schema.String, + "last_id": Schema.String, + "has_more": Schema.Boolean +}).annotate({ "identifier": "ListRunsResponse" }) +export type VideoListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const VideoListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), + "data": Schema.Array(VideoResource).annotate({ "description": "A list of items" }), + "first_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the first item in the list." }), + Schema.Null + ]), + "last_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the last item in the list." }), + Schema.Null + ]), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) +}).annotate({ "identifier": "VideoListResource" }) +export type CreateChatCompletionResponse = { + readonly "id": string + readonly "choices": ReadonlyArray< + { + readonly "finish_reason": "stop" | "length" | "tool_calls" | "content_filter" | "function_call" + readonly "index": number + readonly "message": ChatCompletionResponseMessage + readonly "logprobs": { + readonly "content": ReadonlyArray | null + readonly "refusal": ReadonlyArray | null + } | null + } + > + readonly "created": number + readonly "model": string + readonly "metadata"?: Metadata + readonly "service_tier"?: ServiceTier + readonly "system_fingerprint"?: string + readonly "object": "chat.completion" + readonly "usage"?: CompletionUsage + readonly "moderation"?: ChatCompletionModeration | null +} +export const CreateChatCompletionResponse = Schema.Struct({ + "id": Schema.String.annotate({ "description": "A unique identifier for the chat completion." }), + "choices": Schema.Array(Schema.Struct({ + "finish_reason": Schema.Literals(["stop", "length", "tool_calls", "content_filter", "function_call"]).annotate({ + "description": + "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\n`content_filter` if content was omitted due to a flag from our content filters,\n`tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function.\nRead the [Model Spec](https://model-spec.openai.com/2025-12-18.html) for more.\n" + }), + "index": Schema.Number.annotate({ "description": "The index of the choice in the list of choices." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "message": ChatCompletionResponseMessage, + "logprobs": Schema.Union([ + Schema.Struct({ + "content": Schema.Union([ + Schema.Array(ChatCompletionTokenLogprob).annotate({ + "description": "A list of message content tokens with log probability information." + }), + Schema.Null + ]), + "refusal": Schema.Union([ + Schema.Array(ChatCompletionTokenLogprob).annotate({ + "description": "A list of message refusal tokens with log probability information." + }), + Schema.Null + ]) + }).annotate({ "description": "Log probability information for the choice." }), + Schema.Null + ]) + })).annotate({ "description": "A list of chat completion choices. Can be more than one if `n` is greater than 1." }), + "created": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) of when the chat completion was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "model": Schema.String.annotate({ "description": "The model used for the chat completion." }), + "metadata": Schema.optionalKey(Metadata), + "service_tier": Schema.optionalKey(ServiceTier), + "system_fingerprint": Schema.optionalKey( + Schema.String.annotate({ + "description": + "This fingerprint represents the backend configuration that the model runs with.\n\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" + }) + ), + "object": Schema.Literal("chat.completion").annotate({ + "description": "The object type, which is always `chat.completion`." + }), + "usage": Schema.optionalKey(CompletionUsage), + "moderation": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ChatCompletionModeration).annotate({ + "description": + "Moderation results for the request input and generated output, if moderated\ncompletions were requested.\n" + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "Represents a chat completion response returned by model, based on the provided input.", + "identifier": "CreateChatCompletionResponse" +}) +export type CreateChatCompletionStreamResponse = { + readonly "id": string + readonly "choices": ReadonlyArray< + { + readonly "delta": ChatCompletionStreamResponseDelta + readonly "logprobs"?: + | { + readonly "content": ReadonlyArray | null + readonly "refusal": ReadonlyArray | null + } & { readonly [x: string]: Schema.Json } + | null + readonly "finish_reason"?: "stop" | "length" | "tool_calls" | "content_filter" | "function_call" | null + readonly "index": number + } + > + readonly "created": number + readonly "model": string + readonly "obfuscation"?: string + readonly "service_tier"?: ServiceTier + readonly "system_fingerprint"?: string + readonly "object": "chat.completion.chunk" + readonly "usage"?: CompletionUsage | null + readonly "moderation"?: ChatCompletionModeration | null +} +export const CreateChatCompletionStreamResponse = Schema.Struct({ + "id": Schema.String.annotate({ + "description": "A unique identifier for the chat completion. Each chunk has the same ID." + }), + "choices": Schema.Array(Schema.Struct({ + "delta": ChatCompletionStreamResponseDelta, + "logprobs": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "content": Schema.Union([Schema.Array(ChatCompletionTokenLogprob), Schema.Null]).annotate({ + "description": "A list of message content tokens with log probability information." + }), + "refusal": Schema.Union([Schema.Array(ChatCompletionTokenLogprob), Schema.Null]).annotate({ + "description": "A list of message refusal tokens with log probability information." + }) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ "description": "Log probability information for the choice." }) + ), + "finish_reason": Schema.optionalKey( + Schema.Union([Schema.Literals(["stop", "length", "tool_calls", "content_filter", "function_call"]), Schema.Null]) + .annotate({ + "description": + "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\n`content_filter` if content was omitted due to a flag from our content filters,\n`tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function.\nOmitted from the final audio update containing only `delta.audio.expires_at`.\n" + }) + ), + "index": Schema.Number.annotate({ "description": "The index of the choice in the list of choices." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + })).annotate({ + "description": + "A list of chat completion choices. Can contain more than one elements if `n` is greater than 1. Can also be empty for the\nlast chunk if you set `stream_options: {\"include_usage\": true}`.\n" + }), + "created": Schema.Number.annotate({ + "description": + "The Unix timestamp (in seconds) of when the chat completion was created. Each chunk has the same timestamp.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "model": Schema.String.annotate({ "description": "The model to generate the completion." }), + "obfuscation": Schema.optionalKey( + Schema.String.annotate({ + "description": + "An obfuscation string added to normalize the size of streamed chunks as a\nmitigation to certain side-channel attacks. The field is included by\ndefault and omitted when `stream_options.include_obfuscation` is `false`.\n" + }) + ), + "service_tier": Schema.optionalKey(ServiceTier), + "system_fingerprint": Schema.optionalKey( + Schema.String.annotate({ + "description": + "This fingerprint represents the backend configuration that the model runs with.\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" + }) + ), + "object": Schema.Literal("chat.completion.chunk").annotate({ + "description": "The object type, which is always `chat.completion.chunk`." + }), + "usage": Schema.optionalKey( + Schema.Union([CompletionUsage, Schema.Null]).annotate({ + "description": + "An optional field that will only be present when you set\n`stream_options: {\"include_usage\": true}` in your request. When present, it\ncontains a null value **except for the last chunk** which contains the\ntoken usage statistics for the entire request.\n\n**NOTE:** If the stream is interrupted or cancelled, you may not\nreceive the final usage chunk which contains the total token usage for\nthe request.\n" + }) + ), + "moderation": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ChatCompletionModeration).annotate({ + "description": + "Moderation results for the request input and generated output. Present\non the moderation chunk when moderated completions are requested.\n" + }), + Schema.Null + ]) + ) +}).annotate({ + "description": + "Represents a streamed chunk of a chat completion response returned\nby the model, based on the provided input.\n[Learn more](https://developers.openai.com/api/docs/guides/streaming-responses).\n", + "identifier": "CreateChatCompletionStreamResponse" +}) +export type ChatCompletionRequestMessage = + | ChatCompletionRequestDeveloperMessage + | ChatCompletionRequestSystemMessage + | ChatCompletionRequestUserMessage + | ChatCompletionRequestAssistantMessage + | ChatCompletionRequestToolMessage + | ChatCompletionRequestFunctionMessage +export const ChatCompletionRequestMessage = Schema.Union([ + ChatCompletionRequestDeveloperMessage, + ChatCompletionRequestSystemMessage, + ChatCompletionRequestUserMessage, + ChatCompletionRequestAssistantMessage, + ChatCompletionRequestToolMessage, + ChatCompletionRequestFunctionMessage +], { mode: "oneOf" }).annotate({ "identifier": "ChatCompletionRequestMessage" }) +export type EvalItemContent = EvalItemContentItem | EvalItemContentArray +export const EvalItemContent = Schema.Union([EvalItemContentItem, EvalItemContentArray], { mode: "oneOf" }).annotate({ + "title": "Eval content", + "description": + "Inputs to the model - can contain template strings. Supports text, output text, input images, and input audio, either as a single item or an array of items.\n", + "identifier": "EvalItemContent" +}) +export type OutputMessage = { + readonly "id": string + readonly "type": "message" + readonly "role": "assistant" + readonly "content": ReadonlyArray + readonly "phase"?: MessagePhase | null + readonly "status": "in_progress" | "completed" | "incomplete" +} +export const OutputMessage = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the output message.\n" }), + "type": Schema.Literal("message").annotate({ "description": "The type of the output message. Always `message`.\n" }), + "role": Schema.Literal("assistant").annotate({ + "description": "The role of the output message. Always `assistant`.\n" + }), + "content": Schema.Array(OutputMessageContent).annotate({ "description": "The content of the output message.\n" }), + "phase": Schema.optionalKey(Schema.Union([MessagePhase, Schema.Null])), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" + }) +}).annotate({ + "title": "Output message", + "description": "An output message from the model.\n", + "identifier": "OutputMessage" +}) +export type ResponseContentPartAddedEvent = { + readonly "type": "response.content_part.added" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "part": OutputContent + readonly "sequence_number": number +} +export const ResponseContentPartAddedEvent = Schema.Struct({ + "type": Schema.Literal("response.content_part.added").annotate({ + "description": "The type of the event. Always `response.content_part.added`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the content part was added to.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the content part was added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ "description": "The index of the content part that was added.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "part": Schema.suspend((): Schema.Codec => OutputContent).annotate({ + "description": "The content part that was added.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a new content part is added.", + "identifier": "ResponseContentPartAddedEvent" +}) +export type ResponseContentPartDoneEvent = { + readonly "type": "response.content_part.done" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "sequence_number": number + readonly "part": OutputContent +} +export const ResponseContentPartDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.content_part.done").annotate({ + "description": "The type of the event. Always `response.content_part.done`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the content part was added to.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the content part was added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ "description": "The index of the content part that is done.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "part": Schema.suspend((): Schema.Codec => OutputContent).annotate({ + "description": "The content part that is done.\n" + }) +}).annotate({ "description": "Emitted when a content part is done.", "identifier": "ResponseContentPartDoneEvent" }) +export type EasyInputMessage = { + readonly "role": "user" | "assistant" | "system" | "developer" + readonly "content": string | InputMessageContentList + readonly "phase"?: MessagePhase | null + readonly "type"?: "message" +} +export const EasyInputMessage = Schema.Struct({ + "role": Schema.Literals(["user", "assistant", "system", "developer"]).annotate({ + "description": "The role of the message input. One of `user`, `assistant`, `system`, or\n`developer`.\n" + }), + "content": Schema.Union([ + Schema.String.annotate({ "title": "Text input", "description": "A text input to the model.\n" }), + InputMessageContentList + ], { mode: "oneOf" }).annotate({ + "description": + "Text, image, or audio input to the model, used to generate a response.\nCan also contain previous assistant responses.\n" + }), + "phase": Schema.optionalKey(Schema.Union([MessagePhase, Schema.Null])), + "type": Schema.optionalKey( + Schema.Literal("message").annotate({ "description": "The type of the message input. Always `message`.\n" }) + ) +}).annotate({ + "title": "Input message", + "description": + "A message input to the model with a role indicating instruction following\nhierarchy. Instructions given with the `developer` or `system` role take\nprecedence over instructions given with the `user` role. Messages with the\n`assistant` role are presumed to have been generated by the model in previous\ninteractions.\n", + "identifier": "EasyInputMessage" +}) +export type InputMessageResource = { + readonly "type": "message" + readonly "role": "user" | "system" | "developer" + readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "content": InputMessageContentList + readonly "id": string +} +export const InputMessageResource = Schema.Struct({ + "type": Schema.Literal("message").annotate({ + "description": "The type of the message input. Always set to `message`.\n" + }), + "role": Schema.Literals(["user", "system", "developer"]).annotate({ + "description": "The role of the message input. One of `user`, `system`, or `developer`.\n" + }), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ), + "content": InputMessageContentList, + "id": Schema.String.annotate({ "description": "The unique ID of the message input.\n" }) +}).annotate({ "identifier": "InputMessageResource" }) +export type RealtimeSessionCreateRequestGA = { + readonly "type": "realtime" + readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> + readonly "model"?: + | string + | "gpt-realtime" + | "gpt-realtime-1.5" + | "gpt-realtime-2" + | "gpt-realtime-2.1" + | "gpt-realtime-2.1-mini" + | "gpt-realtime-2025-08-28" + | "gpt-4o-realtime-preview" + | "gpt-4o-realtime-preview-2024-10-01" + | "gpt-4o-realtime-preview-2024-12-17" + | "gpt-4o-realtime-preview-2025-06-03" + | "gpt-4o-mini-realtime-preview" + | "gpt-4o-mini-realtime-preview-2024-12-17" + | "gpt-realtime-mini" + | "gpt-realtime-mini-2025-10-06" + | "gpt-realtime-mini-2025-12-15" + | "gpt-audio-1.5" + | "gpt-audio-mini" + | "gpt-audio-mini-2025-10-06" + | "gpt-audio-mini-2025-12-15" + readonly "instructions"?: string + readonly "audio"?: { + readonly "input"?: { + readonly "format"?: RealtimeAudioFormats + readonly "transcription"?: AudioTranscription + readonly "noise_reduction"?: + | null + | { readonly "type"?: NoiseReductionType } & { readonly [x: string]: Schema.Json } + readonly "turn_detection"?: RealtimeTurnDetection + } + readonly "output"?: { + readonly "format"?: RealtimeAudioFormats + readonly "voice"?: VoiceIdsOrCustomVoice + readonly "speed"?: number + } + } + readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> + readonly "tracing"?: "auto" | { + readonly "workflow_name"?: string + readonly "group_id"?: string + readonly "metadata"?: { readonly [x: string]: Schema.Json } + } | null + readonly "tools"?: ReadonlyArray + readonly "tool_choice"?: ToolChoiceOptions | ToolChoiceFunction | ToolChoiceMCP + readonly "parallel_tool_calls"?: boolean + readonly "reasoning"?: RealtimeReasoning + readonly "max_output_tokens"?: number | "inf" + readonly "truncation"?: RealtimeTruncation + readonly "prompt"?: Prompt +} +export const RealtimeSessionCreateRequestGA = Schema.Struct({ + "type": Schema.Literal("realtime").annotate({ + "description": "The type of session to create. Always `realtime` for the Realtime API.\n" + }), + "output_modalities": Schema.optionalKey( + Schema.Array(Schema.Literals(["text", "audio"])).annotate({ + "description": + "The set of modalities the model can respond with. It defaults to `[\"audio\"]`, indicating\nthat the model will respond with audio plus a transcript. `[\"text\"]` can be used to make\nthe model respond with text only. It is not possible to request both `text` and `audio` at the same time.\n" + }) + ), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-realtime", + "gpt-realtime-1.5", + "gpt-realtime-2", + "gpt-realtime-2.1", + "gpt-realtime-2.1-mini", + "gpt-realtime-2025-08-28", + "gpt-4o-realtime-preview", + "gpt-4o-realtime-preview-2024-10-01", + "gpt-4o-realtime-preview-2024-12-17", + "gpt-4o-realtime-preview-2025-06-03", + "gpt-4o-mini-realtime-preview", + "gpt-4o-mini-realtime-preview-2024-12-17", + "gpt-realtime-mini", + "gpt-realtime-mini-2025-10-06", + "gpt-realtime-mini-2025-12-15", + "gpt-audio-1.5", + "gpt-audio-mini", + "gpt-audio-mini-2025-10-06", + "gpt-audio-mini-2025-12-15" + ]) + ]).annotate({ "description": "The Realtime model used for this session.\n" }) + ), + "instructions": Schema.optionalKey(Schema.String.annotate({ + "description": + "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\n\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" + })), + "audio": Schema.optionalKey( + Schema.Struct({ + "input": Schema.optionalKey(Schema.Struct({ + "format": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RealtimeAudioFormats).annotate({ + "description": "The format of the input audio." + }) + ), + "transcription": Schema.optionalKey( + Schema.suspend((): Schema.Codec => AudioTranscription).annotate({ + "description": + "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" + }) + ), + "noise_reduction": Schema.optionalKey( + Schema.Union([ + Schema.Null, + Schema.StructWithRest(Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }), [ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) + ]) + ]).annotate({ + "description": + "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" + }) + ), + "turn_detection": Schema.optionalKey(RealtimeTurnDetection) + })), + "output": Schema.optionalKey(Schema.Struct({ + "format": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RealtimeAudioFormats).annotate({ + "description": "The format of the output audio." + }) + ), + "voice": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VoiceIdsOrCustomVoice).annotate({ + "description": + "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`,\n`marin`, and `cedar`. You may also provide a custom voice object with\nan `id`, for example `{ \"id\": \"voice_1234\" }`. Voice cannot be changed\nduring the session once the model has responded with audio at least once.\nCustom voices must be created from audio samples.\nWe recommend `marin` and `cedar` for best quality.\n" + }) + ), + "speed": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The speed of the model's spoken response as a multiple of the original speed.\n1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress.\n\nThis parameter is a post-processing adjustment to the audio after it is generated, it's\nalso possible to prompt the model to speak faster or slower.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0.25).annotate({ "expected": "a value greater than or equal to 0.25" }) + ).check(Schema.isLessThanOrEqualTo(1.5).annotate({ "expected": "a value less than or equal to 1.5" })) + ) + })) + }).annotate({ "description": "Configuration for input and output audio.\n" }) + ), + "include": Schema.optionalKey( + Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")).annotate({ + "description": + "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" + }) + ), + "tracing": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto").annotate({ + "title": "auto", + "description": "Enables tracing and sets default values for tracing configuration options. Always `auto`.\n" + }), + Schema.Struct({ + "workflow_name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The name of the workflow to attach to this trace. This is used to\nname the trace in the Traces Dashboard.\n" + }) + ), + "group_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The group id to attach to this trace to enable filtering and\ngrouping in the Traces Dashboard.\n" + }) + ), + "metadata": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "The arbitrary metadata to attach to this trace to enable\nfiltering in the Traces Dashboard.\n" + }) + ) + }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }), + Schema.Null + ], { mode: "oneOf" }).annotate({ + "title": "Tracing Configuration", + "description": + "Realtime API can write session traces to the [Traces Dashboard](https://platform.openai.com/logs?api=traces). Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" + }) + ), + "tools": Schema.optionalKey( + Schema.Array(Schema.Union([RealtimeFunctionTool, MCPTool], { mode: "oneOf" })).annotate({ + "description": "Tools available to the model." + }) + ), + "tool_choice": Schema.optionalKey( + Schema.Union([ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMCP], { mode: "oneOf" }).annotate({ + "description": + "How the model chooses tools. Provide one of the string modes or force a specific\nfunction/MCP tool.\n" + }) + ), + "parallel_tool_calls": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Whether the model may call multiple tools in parallel. Only supported by\nreasoning Realtime models such as `gpt-realtime-2`.\n" + }) + ), + "reasoning": Schema.optionalKey(RealtimeReasoning), + "max_output_tokens": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Literal("inf")], { + mode: "oneOf" + }).annotate({ + "description": + "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" + }) + ), + "truncation": Schema.optionalKey(RealtimeTruncation), + "prompt": Schema.optionalKey(Prompt) +}).annotate({ + "title": "Realtime session configuration", + "description": "Realtime session object configuration.", + "identifier": "RealtimeSessionCreateRequestGA" +}) +export type RealtimeSessionCreateResponseGA = { + readonly "type": "realtime" + readonly "id": string + readonly "object": "realtime.session" + readonly "expires_at"?: number + readonly "output_modalities"?: ReadonlyArray<"text" | "audio"> + readonly "model"?: + | string + | "gpt-realtime" + | "gpt-realtime-1.5" + | "gpt-realtime-2" + | "gpt-realtime-2.1" + | "gpt-realtime-2.1-mini" + | "gpt-realtime-2025-08-28" + | "gpt-4o-realtime-preview" + | "gpt-4o-realtime-preview-2024-10-01" + | "gpt-4o-realtime-preview-2024-12-17" + | "gpt-4o-realtime-preview-2025-06-03" + | "gpt-4o-mini-realtime-preview" + | "gpt-4o-mini-realtime-preview-2024-12-17" + | "gpt-realtime-mini" + | "gpt-realtime-mini-2025-10-06" + | "gpt-realtime-mini-2025-12-15" + | "gpt-audio-1.5" + | "gpt-audio-mini" + | "gpt-audio-mini-2025-10-06" + | "gpt-audio-mini-2025-12-15" + readonly "instructions"?: string + readonly "audio"?: { + readonly "input"?: { + readonly "format"?: RealtimeAudioFormats + readonly "transcription"?: AudioTranscriptionResponse | null + readonly "noise_reduction"?: + | { readonly "type"?: NoiseReductionType } & { readonly [x: string]: Schema.Json } + | null + readonly "turn_detection"?: RealtimeTurnDetection + } + readonly "output"?: { + readonly "format"?: RealtimeAudioFormats + readonly "voice"?: VoiceIdsShared + readonly "speed"?: number + } + } + readonly "include"?: ReadonlyArray<"item.input_audio_transcription.logprobs"> | null + readonly "tracing"?: "auto" | { + readonly "workflow_name"?: string + readonly "group_id"?: string + readonly "metadata"?: { readonly [x: string]: Schema.Json } + } | null + readonly "tools"?: ReadonlyArray + readonly "tool_choice"?: ToolChoiceOptions | ToolChoiceFunction | ToolChoiceMCP + readonly "reasoning"?: RealtimeReasoning + readonly "max_output_tokens"?: number | "inf" + readonly "truncation"?: RealtimeTruncation + readonly "prompt"?: Prompt +} +export const RealtimeSessionCreateResponseGA = Schema.Struct({ + "type": Schema.Literal("realtime").annotate({ + "description": "The type of session to create. Always `realtime` for the Realtime API.\n" + }), + "id": Schema.String.annotate({ + "description": "Unique identifier for the session that looks like `sess_1234567890abcdef`.\n" + }), + "object": Schema.Literal("realtime.session").annotate({ + "description": "The object type. Always `realtime.session`." + }), + "expires_at": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Expiration timestamp for the session, in seconds since epoch.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "output_modalities": Schema.optionalKey( + Schema.Array(Schema.Literals(["text", "audio"])).annotate({ + "description": + "The set of modalities the model can respond with. It defaults to `[\"audio\"]`, indicating\nthat the model will respond with audio plus a transcript. `[\"text\"]` can be used to make\nthe model respond with text only. It is not possible to request both `text` and `audio` at the same time.\n" + }) + ), + "model": Schema.optionalKey( + Schema.Union([ + Schema.String, + Schema.Literals([ + "gpt-realtime", + "gpt-realtime-1.5", + "gpt-realtime-2", + "gpt-realtime-2.1", + "gpt-realtime-2.1-mini", + "gpt-realtime-2025-08-28", + "gpt-4o-realtime-preview", + "gpt-4o-realtime-preview-2024-10-01", + "gpt-4o-realtime-preview-2024-12-17", + "gpt-4o-realtime-preview-2025-06-03", + "gpt-4o-mini-realtime-preview", + "gpt-4o-mini-realtime-preview-2024-12-17", + "gpt-realtime-mini", + "gpt-realtime-mini-2025-10-06", + "gpt-realtime-mini-2025-12-15", + "gpt-audio-1.5", + "gpt-audio-mini", + "gpt-audio-mini-2025-10-06", + "gpt-audio-mini-2025-12-15" + ]) + ]).annotate({ "description": "The Realtime model used for this session.\n" }) + ), + "instructions": Schema.optionalKey(Schema.String.annotate({ + "description": + "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\n\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" + })), + "audio": Schema.optionalKey( + Schema.Struct({ + "input": Schema.optionalKey(Schema.Struct({ + "format": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RealtimeAudioFormats).annotate({ + "description": "The format of the input audio." + }) + ), + "transcription": Schema.optionalKey( + Schema.Union([AudioTranscriptionResponse, Schema.Null]).annotate({ + "description": + "Configuration for input audio transcription, defaults to off and can be set to `null` to turn off once on. Input audio transcription is not native to the model, since the model consumes audio directly. Transcription runs asynchronously through [the /audio/transcriptions endpoint](https://developers.openai.com/api/reference/resources/audio/subresources/transcriptions/methods/create) and should be treated as guidance of input audio content rather than precisely what the model heard. The client can optionally set the language and prompt for transcription, these offer additional guidance to the transcription service.\n" + }) + ), + "noise_reduction": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest(Schema.Struct({ "type": Schema.optionalKey(NoiseReductionType) }), [ + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })) + ]), + Schema.Null + ]).annotate({ + "description": + "Configuration for input audio noise reduction. This can be set to `null` to turn off.\nNoise reduction filters audio added to the input audio buffer before it is sent to VAD and the model.\nFiltering the audio can improve VAD and turn detection accuracy (reducing false positives) and model performance by improving perception of the input audio.\n" + }) + ), + "turn_detection": Schema.optionalKey(RealtimeTurnDetection) + })), + "output": Schema.optionalKey(Schema.Struct({ + "format": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RealtimeAudioFormats).annotate({ + "description": "The format of the output audio." + }) + ), + "voice": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VoiceIdsShared).annotate({ + "description": + "The voice the model uses to respond. Voice cannot be changed during the\nsession once the model has responded with audio at least once. Current\nvoice options are `alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`,\n`shimmer`, `verse`, `marin`, and `cedar`. We recommend `marin` and `cedar` for\nbest quality.\n" + }) + ), + "speed": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The speed of the model's spoken response as a multiple of the original speed.\n1.0 is the default speed. 0.25 is the minimum speed. 1.5 is the maximum speed. This value can only be changed in between model turns, not while a response is in progress.\n\nThis parameter is a post-processing adjustment to the audio after it is generated, it's\nalso possible to prompt the model to speak faster or slower.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0.25).annotate({ "expected": "a value greater than or equal to 0.25" }) + ).check(Schema.isLessThanOrEqualTo(1.5).annotate({ "expected": "a value less than or equal to 1.5" })) + ) + })) + }).annotate({ "description": "Configuration for input and output audio.\n" }) + ), + "include": Schema.optionalKey( + Schema.Union([Schema.Array(Schema.Literal("item.input_audio_transcription.logprobs")), Schema.Null]).annotate({ + "description": + "Additional fields to include in server outputs.\n\n`item.input_audio_transcription.logprobs`: Include logprobs for input audio transcription.\n" + }) + ), + "tracing": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.Literal("auto").annotate({ + "title": "auto", + "description": "Enables tracing and sets default values for tracing configuration options. Always `auto`.\n" + }), + Schema.Struct({ + "workflow_name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The name of the workflow to attach to this trace. This is used to\nname the trace in the Traces Dashboard.\n" + }) + ), + "group_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The group id to attach to this trace to enable filtering and\ngrouping in the Traces Dashboard.\n" + }) + ), + "metadata": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "The arbitrary metadata to attach to this trace to enable\nfiltering in the Traces Dashboard.\n" + }) + ) + }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) + ], { mode: "oneOf" }).annotate({ + "title": "Tracing Configuration", + "description": + "Realtime API can write session traces to the [Traces Dashboard](https://platform.openai.com/logs?api=traces). Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" + }), + Schema.Null + ]) + ), + "tools": Schema.optionalKey( + Schema.Array(Schema.Union([RealtimeFunctionTool, MCPTool], { mode: "oneOf" })).annotate({ + "description": "Tools available to the model." + }) + ), + "tool_choice": Schema.optionalKey( + Schema.Union([ToolChoiceOptions, ToolChoiceFunction, ToolChoiceMCP], { mode: "oneOf" }).annotate({ + "description": + "How the model chooses tools. Provide one of the string modes or force a specific\nfunction/MCP tool.\n" + }) + ), + "reasoning": Schema.optionalKey(RealtimeReasoning), + "max_output_tokens": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Literal("inf")], { + mode: "oneOf" + }).annotate({ + "description": + "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" + }) + ), + "truncation": Schema.optionalKey(RealtimeTruncation), + "prompt": Schema.optionalKey(Prompt) +}).annotate({ + "title": "Realtime session configuration object", + "description": "A Realtime session configuration object.\n", + "identifier": "RealtimeSessionCreateResponseGA" +}) +export type RealtimeSessionCreateRequest = { + readonly "client_secret": { readonly "value": string; readonly "expires_at": number } + readonly "modalities"?: ReadonlyArray<"text" | "audio"> + readonly "instructions"?: string + readonly "voice"?: VoiceIdsOrCustomVoice + readonly "input_audio_format"?: string + readonly "output_audio_format"?: string + readonly "input_audio_transcription"?: { readonly "model"?: string } + readonly "speed"?: number + readonly "tracing"?: "auto" | { + readonly "workflow_name"?: string + readonly "group_id"?: string + readonly "metadata"?: { readonly [x: string]: Schema.Json } + } + readonly "turn_detection"?: { + readonly "type"?: string + readonly "threshold"?: number + readonly "prefix_padding_ms"?: number + readonly "silence_duration_ms"?: number + } + readonly "tools"?: ReadonlyArray< + { + readonly "type"?: "function" + readonly "name"?: string + readonly "description"?: string + readonly "parameters"?: { readonly [x: string]: Schema.Json } + } + > + readonly "tool_choice"?: string + readonly "temperature"?: number + readonly "max_response_output_tokens"?: number | "inf" + readonly "truncation"?: RealtimeTruncation + readonly "prompt"?: Prompt +} +export const RealtimeSessionCreateRequest = Schema.Struct({ + "client_secret": Schema.Struct({ + "value": Schema.String.annotate({ + "description": + "Ephemeral key usable in client environments to authenticate connections\nto the Realtime API. Use this in client-side environments rather than\na standard API token, which should only be used server-side.\n" + }), + "expires_at": Schema.Number.annotate({ + "description": "Timestamp for when the token expires. Currently, all tokens expire\nafter one minute.\n", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + }).annotate({ "description": "Ephemeral key returned by the API." }), + "modalities": Schema.optionalKey( + Schema.Array(Schema.Literals(["text", "audio"])).annotate({ + "description": "The set of modalities the model can respond with. To disable audio,\nset this to [\"text\"].\n" + }) + ), + "instructions": Schema.optionalKey(Schema.String.annotate({ + "description": + "The default system instructions (i.e. system message) prepended to model calls. This field allows the client to guide the model on desired responses. The model can be instructed on response content and format, (e.g. \"be extremely succinct\", \"act friendly\", \"here are examples of good responses\") and on audio behavior (e.g. \"talk quickly\", \"inject emotion into your voice\", \"laugh frequently\"). The instructions are not guaranteed to be followed by the model, but they provide guidance to the model on the desired behavior.\nNote that the server sets default instructions which will be used if this field is not set and are visible in the `session.created` event at the start of the session.\n" + })), + "voice": Schema.optionalKey( + Schema.suspend((): Schema.Codec => VoiceIdsOrCustomVoice).annotate({ + "description": + "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `sage`, `shimmer`, `verse`,\n`marin`, and `cedar`. You may also provide a custom voice object with an\n`id`, for example `{ \"id\": \"voice_1234\" }`. Voice cannot be changed during\nthe session once the model has responded with audio at least once.\nCustom voices must be created from audio samples.\n" + }) + ), + "input_audio_format": Schema.optionalKey( + Schema.String.annotate({ + "description": "The format of input audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\n" + }) + ), + "output_audio_format": Schema.optionalKey( + Schema.String.annotate({ + "description": "The format of output audio. Options are `pcm16`, `g711_ulaw`, or `g711_alaw`.\n" + }) + ), + "input_audio_transcription": Schema.optionalKey( + Schema.Struct({ + "model": Schema.optionalKey(Schema.String.annotate({ "description": "The model to use for transcription.\n" })) + }).annotate({ + "description": + "Configuration for input audio transcription, defaults to off and can be\nset to `null` to turn off once on. Input audio transcription is not native\nto the model, since the model consumes audio directly. Transcription runs\nasynchronously and should be treated as rough guidance\nrather than the representation understood by the model.\n" + }) + ), + "speed": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The speed of the model's spoken response. 1.0 is the default speed. 0.25 is\nthe minimum speed. 1.5 is the maximum speed. This value can only be changed\nin between model turns, not while a response is in progress.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0.25).annotate({ "expected": "a value greater than or equal to 0.25" }) + ).check(Schema.isLessThanOrEqualTo(1.5).annotate({ "expected": "a value less than or equal to 1.5" })) + ), + "tracing": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto").annotate({ "description": "Default tracing mode for the session.\n" }), + Schema.Struct({ + "workflow_name": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The name of the workflow to attach to this trace. This is used to\nname the trace in the traces dashboard.\n" + }) + ), + "group_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The group id to attach to this trace to enable filtering and\ngrouping in the traces dashboard.\n" + }) + ), + "metadata": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": + "The arbitrary metadata to attach to this trace to enable\nfiltering in the traces dashboard.\n" + }) + ) + }).annotate({ "title": "Tracing Configuration", "description": "Granular configuration for tracing.\n" }) + ], { mode: "oneOf" }).annotate({ + "title": "Tracing Configuration", + "description": + "Configuration options for tracing. Set to null to disable tracing. Once\ntracing is enabled for a session, the configuration cannot be modified.\n\n`auto` will create a trace for the session with default values for the\nworkflow name, group id, and metadata.\n" + }) + ), + "turn_detection": Schema.optionalKey( + Schema.Struct({ + "type": Schema.optionalKey( + Schema.String.annotate({ "description": "Type of turn detection, only `server_vad` is currently supported.\n" }) + ), + "threshold": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Activation threshold for VAD (0.0 to 1.0), this defaults to 0.5. A\nhigher threshold will require louder audio to activate the model, and\nthus might perform better in noisy environments.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "prefix_padding_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Amount of audio to include before the VAD detected speech (in\nmilliseconds). Defaults to 300ms.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ), + "silence_duration_ms": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "Duration of silence to detect speech stop (in milliseconds). Defaults\nto 500ms. With shorter values the model will respond more quickly,\nbut may jump in on short pauses from the user.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) + ) + }).annotate({ + "description": + "Configuration for turn detection. Can be set to `null` to turn off. Server\nVAD means that the model will detect the start and end of speech based on\naudio volume and respond at the end of user speech.\n" + }) + ), + "tools": Schema.optionalKey( + Schema.Array(Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("function").annotate({ "description": "The type of the tool, i.e. `function`." }) + ), + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the function." })), + "description": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The description of the function, including guidance on when and how\nto call it, and guidance about what to tell the user when calling\n(if anything).\n" + }) + ), + "parameters": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ + "description": "Parameters of the function in JSON Schema." + }) + ) + })).annotate({ "description": "Tools (functions) available to the model." }) + ), + "tool_choice": Schema.optionalKey( + Schema.String.annotate({ + "description": "How the model chooses tools. Options are `auto`, `none`, `required`, or\nspecify a function.\n" + }) + ), + "temperature": Schema.optionalKey( + Schema.Number.annotate({ + "description": "Sampling temperature for the model, limited to [0.6, 1.2]. Defaults to 0.8.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "max_response_output_tokens": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Literal("inf")], { + mode: "oneOf" + }).annotate({ + "description": + "Maximum number of output tokens for a single assistant response,\ninclusive of tool calls. Provide an integer between 1 and 4096 to\nlimit output tokens, or `inf` for the maximum available tokens for a\ngiven model. Defaults to `inf`.\n" + }) + ), + "truncation": Schema.optionalKey(RealtimeTruncation), + "prompt": Schema.optionalKey(Prompt) +}).annotate({ + "description": "A new Realtime session configuration, with an ephemeral key. Default TTL\nfor keys is one minute.\n", + "identifier": "RealtimeSessionCreateRequest" +}) +export type ComputerToolCall = { + readonly "type": "computer_call" + readonly "id": string + readonly "call_id": string + readonly "action"?: ComputerAction + readonly "actions"?: ComputerActionList + readonly "pending_safety_checks": ReadonlyArray + readonly "status": "in_progress" | "completed" | "incomplete" +} +export const ComputerToolCall = Schema.Struct({ + "type": Schema.Literal("computer_call").annotate({ + "description": "The type of the computer call. Always `computer_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the computer call." }), + "call_id": Schema.String.annotate({ + "description": "An identifier used when responding to the tool call with output.\n" + }), + "action": Schema.optionalKey(ComputerAction), + "actions": Schema.optionalKey(ComputerActionList), + "pending_safety_checks": Schema.Array(ComputerCallSafetyCheckParam).annotate({ + "description": "The pending safety checks for the computer call.\n" + }), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) +}).annotate({ + "title": "Computer tool call", + "description": + "A tool call to a computer use tool. See the\n[computer use guide](https://developers.openai.com/api/docs/guides/tools-computer-use) for more information.\n", + "identifier": "ComputerToolCall" +}) +export type Tool = + | FunctionTool + | FileSearchTool + | ComputerTool + | ComputerUsePreviewTool + | WebSearchTool + | MCPTool + | CodeInterpreterTool + | ProgrammaticToolCallingParam + | ImageGenTool + | LocalShellToolParam + | FunctionShellToolParam + | CustomToolParam + | NamespaceToolParam + | ToolSearchToolParam + | WebSearchPreviewTool + | ApplyPatchToolParam +export const Tool = Schema.Union([ + FunctionTool, + FileSearchTool, + ComputerTool, + ComputerUsePreviewTool, + WebSearchTool, + MCPTool, + CodeInterpreterTool, + ProgrammaticToolCallingParam, + ImageGenTool, + LocalShellToolParam, + FunctionShellToolParam, + CustomToolParam, + NamespaceToolParam, + ToolSearchToolParam, + WebSearchPreviewTool, + ApplyPatchToolParam +], { mode: "oneOf" }).annotate({ + "description": "A tool that can be used to generate a response.\n", + "identifier": "Tool" +}) +export type ToolSearchOutputTool = + | FunctionTool + | FileSearchTool + | ComputerTool + | ComputerUsePreviewTool + | WebSearchTool + | MCPTool + | CodeInterpreterTool + | ProgrammaticToolCallingParam + | ImageGenTool + | LocalShellToolParam + | FunctionShellToolParam + | CustomToolParam + | ToolSearchOutputNamespaceToolParam + | ToolSearchToolParam + | WebSearchPreviewTool + | ApplyPatchToolParam +export const ToolSearchOutputTool = Schema.Union([ + FunctionTool, + FileSearchTool, + ComputerTool, + ComputerUsePreviewTool, + WebSearchTool, + MCPTool, + CodeInterpreterTool, + ProgrammaticToolCallingParam, + ImageGenTool, + LocalShellToolParam, + FunctionShellToolParam, + CustomToolParam, + ToolSearchOutputNamespaceToolParam, + ToolSearchToolParam, + WebSearchPreviewTool, + ApplyPatchToolParam +], { mode: "oneOf" }).annotate({ + "description": "A tool definition returned by a tool search output.\n", + "identifier": "ToolSearchOutputTool" +}) +export type LiveResponsesDelegationSettingsInputParam = { + readonly "model": string + readonly "instructions"?: string | null + readonly "max_output_tokens"?: number | null + readonly "service_tier"?: LiveResponsesServiceTier | null + readonly "reasoning"?: LiveDelegationReasoningInputParam | null + readonly "text"?: LiveDelegationTextInputParam | null + readonly "tools"?: ReadonlyArray< + | LiveFunctionToolInputParam + | LiveWebSearchToolInputParam + | LiveFileSearchToolInputParam + | LiveCodeInterpreterToolInputParam + | LiveHostedShellToolInputParam + | LiveImageGenerationToolInputParam + | LiveMCPToolInputParam + | LiveCustomToolInputParam + | LiveNamespaceToolInputParam + | LiveToolSearchToolInputParam + | LiveProgrammaticToolInputParam + | LiveComputerToolInputParam + | LiveApplyPatchToolInputParam + > + readonly "tool_choice"?: + | LiveToolChoiceEnum + | LiveFunctionToolChoiceParam + | LiveMCPToolChoiceParam + | LiveSpecificFileSearchParam + | LiveSpecificWebSearchParam + | LiveSpecificWebSearchPreviewParam + | LiveSpecificImageGenParam + | LiveSpecificComputerParam + | LiveSpecificCodeInterpreterParam + | LiveSpecificProgrammaticToolCallingParam + | LiveSpecificFunctionShellParam + | LiveSpecificCustomToolParam + | LiveSpecificApplyPatchParam + | LiveAllowedToolsChoiceParam + readonly "parallel_tool_calls"?: boolean | null +} +export const LiveResponsesDelegationSettingsInputParam = Schema.Struct({ + "model": Schema.String.annotate({ "description": "The model used for server-owned Responses delegations." }), + "instructions": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "Instructions for the delegated Responses model, separate from Live instructions. See [backend prompting](https://developers.openai.com/api/docs/guides/live-delegation#start-with-your-existing-backend-prompt)." + }), + Schema.Null + ]) + ), + "max_output_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "Maximum number of output tokens for each delegated response." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(16).annotate({ "expected": "a value greater than or equal to 16" })), + Schema.Null + ]) + ), + "service_tier": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveResponsesServiceTier).annotate({ + "description": "Service tier for delegated Responses requests." + }), + Schema.Null + ]) + ), + "reasoning": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveDelegationReasoningInputParam).annotate( + { "description": "Reasoning settings passed to each delegated Responses request." } + ), + Schema.Null + ]) + ), + "text": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveDelegationTextInputParam).annotate({ + "description": "Text generation settings passed to each delegated Responses request." + }), + Schema.Null + ]) + ), + "tools": Schema.optionalKey( + Schema.Array( + Schema.Union([ + LiveFunctionToolInputParam, + LiveWebSearchToolInputParam, + LiveFileSearchToolInputParam, + LiveCodeInterpreterToolInputParam, + LiveHostedShellToolInputParam, + LiveImageGenerationToolInputParam, + LiveMCPToolInputParam, + LiveCustomToolInputParam, + LiveNamespaceToolInputParam, + LiveToolSearchToolInputParam, + LiveProgrammaticToolInputParam, + LiveComputerToolInputParam, + LiveApplyPatchToolInputParam + ], { mode: "oneOf" }) + ).annotate({ + "description": "Tools available to the Responses backend while it handles tasks delegated by the Live model." + }) + ), + "tool_choice": Schema.optionalKey( + Schema.Union([ + LiveToolChoiceEnum, + Schema.Union([ + LiveFunctionToolChoiceParam, + LiveMCPToolChoiceParam, + LiveSpecificFileSearchParam, + LiveSpecificWebSearchParam, + LiveSpecificWebSearchPreviewParam, + LiveSpecificImageGenParam, + LiveSpecificComputerParam, + LiveSpecificCodeInterpreterParam, + LiveSpecificProgrammaticToolCallingParam, + LiveSpecificFunctionShellParam, + LiveSpecificCustomToolParam, + LiveSpecificApplyPatchParam + ], { mode: "oneOf" }), + LiveAllowedToolsChoiceParam + ], { mode: "oneOf" }).annotate({ + "description": "Controls which tool the Responses backend uses when handling a task delegated by the Live model." + }) + ), + "parallel_tool_calls": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": "Whether the delegated Responses model may request multiple tool calls in a single response." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": "Model, prompt, and tool settings for tasks delegated by the Live session to a Responses backend.", + "identifier": "LiveResponsesDelegationSettingsInputParam" +}) +export type LiveResponsesDelegationSettingsUpdateInputParam = { + readonly "model"?: string + readonly "instructions"?: string | null + readonly "max_output_tokens"?: number | null + readonly "service_tier"?: LiveResponsesServiceTier | null + readonly "reasoning"?: LiveDelegationReasoningInputParam | null + readonly "text"?: LiveDelegationTextInputParam | null + readonly "tools"?: ReadonlyArray< + | LiveFunctionToolInputParam + | LiveWebSearchToolInputParam + | LiveFileSearchToolInputParam + | LiveCodeInterpreterToolInputParam + | LiveHostedShellToolInputParam + | LiveImageGenerationToolInputParam + | LiveMCPToolInputParam + | LiveCustomToolInputParam + | LiveNamespaceToolInputParam + | LiveToolSearchToolInputParam + | LiveProgrammaticToolInputParam + | LiveComputerToolInputParam + | LiveApplyPatchToolInputParam + > + readonly "tool_choice"?: + | LiveToolChoiceEnum + | LiveFunctionToolChoiceParam + | LiveMCPToolChoiceParam + | LiveSpecificFileSearchParam + | LiveSpecificWebSearchParam + | LiveSpecificWebSearchPreviewParam + | LiveSpecificImageGenParam + | LiveSpecificComputerParam + | LiveSpecificCodeInterpreterParam + | LiveSpecificProgrammaticToolCallingParam + | LiveSpecificFunctionShellParam + | LiveSpecificCustomToolParam + | LiveSpecificApplyPatchParam + | LiveAllowedToolsChoiceParam + readonly "parallel_tool_calls"?: boolean | null +} +export const LiveResponsesDelegationSettingsUpdateInputParam = Schema.Struct({ + "model": Schema.optionalKey( + Schema.String.annotate({ + "description": + "The Responses backend model to use for subsequent delegated requests. Omit to keep the current backend model." + }) + ), + "instructions": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "Instructions for the delegated Responses model, separate from Live instructions. See [backend prompting](https://developers.openai.com/api/docs/guides/live-delegation#start-with-your-existing-backend-prompt)." + }), + Schema.Null + ]) + ), + "max_output_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "Maximum number of output tokens for each delegated response." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ).check(Schema.isGreaterThanOrEqualTo(16).annotate({ "expected": "a value greater than or equal to 16" })), + Schema.Null + ]) + ), + "service_tier": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveResponsesServiceTier).annotate({ + "description": "Service tier for delegated Responses requests." + }), + Schema.Null + ]) + ), + "reasoning": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveDelegationReasoningInputParam).annotate( + { "description": "Reasoning settings passed to each delegated Responses request." } + ), + Schema.Null + ]) + ), + "text": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => LiveDelegationTextInputParam).annotate({ + "description": "Text generation settings passed to each delegated Responses request." + }), + Schema.Null + ]) + ), + "tools": Schema.optionalKey( + Schema.Array( + Schema.Union([ + LiveFunctionToolInputParam, + LiveWebSearchToolInputParam, + LiveFileSearchToolInputParam, + LiveCodeInterpreterToolInputParam, + LiveHostedShellToolInputParam, + LiveImageGenerationToolInputParam, + LiveMCPToolInputParam, + LiveCustomToolInputParam, + LiveNamespaceToolInputParam, + LiveToolSearchToolInputParam, + LiveProgrammaticToolInputParam, + LiveComputerToolInputParam, + LiveApplyPatchToolInputParam + ], { mode: "oneOf" }) + ).annotate({ + "description": "Tools available to the Responses backend while it handles tasks delegated by the Live model." + }) + ), + "tool_choice": Schema.optionalKey( + Schema.Union([ + LiveToolChoiceEnum, + Schema.Union([ + LiveFunctionToolChoiceParam, + LiveMCPToolChoiceParam, + LiveSpecificFileSearchParam, + LiveSpecificWebSearchParam, + LiveSpecificWebSearchPreviewParam, + LiveSpecificImageGenParam, + LiveSpecificComputerParam, + LiveSpecificCodeInterpreterParam, + LiveSpecificProgrammaticToolCallingParam, + LiveSpecificFunctionShellParam, + LiveSpecificCustomToolParam, + LiveSpecificApplyPatchParam + ], { mode: "oneOf" }), + LiveAllowedToolsChoiceParam + ], { mode: "oneOf" }).annotate({ + "description": "Controls which tool the Responses backend uses when handling a task delegated by the Live model." + }) + ), + "parallel_tool_calls": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": "Whether the delegated Responses model may request multiple tool calls in a single response." + }), + Schema.Null + ]) + ) +}).annotate({ + "description": + "Updates to the Responses backend of an existing Live session. Omitted settings retain their current values.", + "identifier": "LiveResponsesDelegationSettingsUpdateInputParam" +}) +export type ListAuditLogsResponse = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id"?: string | null + readonly "last_id"?: string | null + readonly "has_more": boolean +} +export const ListAuditLogsResponse = Schema.Struct({ + "object": Schema.Literal("list"), + "data": Schema.Array(AuditLog), + "first_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "last_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "has_more": Schema.Boolean +}).annotate({ "identifier": "ListAuditLogsResponse" }) +export type CreateVectorStoreFileBatchRequest = { + readonly "file_ids": ReadonlyArray + readonly "files"?: ReadonlyArray + readonly "chunking_strategy"?: ChunkingStrategyRequestParam + readonly "attributes"?: VectorStoreFileAttributes +} | { + readonly "file_ids"?: ReadonlyArray + readonly "files": ReadonlyArray + readonly "chunking_strategy"?: ChunkingStrategyRequestParam + readonly "attributes"?: VectorStoreFileAttributes +} +export const CreateVectorStoreFileBatchRequest = Schema.Union([ + Schema.Struct({ + "file_ids": Schema.Array(Schema.String).annotate({ + "description": + "A list of [File](https://developers.openai.com/api/reference/resources/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied to all files in the batch. The maximum batch size is 2000 files. This endpoint is recommended for multi-file ingestion and helps reduce per-vector-store write request pressure. Mutually exclusive with `files`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "files": Schema.optionalKey( + Schema.Array(CreateVectorStoreFileRequest).annotate({ + "description": + "A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must be specified for each file. The maximum batch size is 2000 files. This endpoint is recommended for multi-file ingestion and helps reduce per-vector-store write request pressure. Mutually exclusive with `file_ids`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ) + ), + "chunking_strategy": Schema.optionalKey(ChunkingStrategyRequestParam), + "attributes": Schema.optionalKey(VectorStoreFileAttributes) + }), + Schema.Struct({ + "file_ids": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of [File](https://developers.openai.com/api/reference/resources/files) IDs that the vector store should use. Useful for tools like `file_search` that can access files. If `attributes` or `chunking_strategy` are provided, they will be applied to all files in the batch. The maximum batch size is 2000 files. This endpoint is recommended for multi-file ingestion and helps reduce per-vector-store write request pressure. Mutually exclusive with `files`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ) + ), + "files": Schema.Array(CreateVectorStoreFileRequest).annotate({ + "description": + "A list of objects that each include a `file_id` plus optional `attributes` or `chunking_strategy`. Use this when you need to override metadata for specific files. The global `attributes` or `chunking_strategy` will be ignored and must be specified for each file. The maximum batch size is 2000 files. This endpoint is recommended for multi-file ingestion and helps reduce per-vector-store write request pressure. Mutually exclusive with `file_ids`." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "chunking_strategy": Schema.optionalKey(ChunkingStrategyRequestParam), + "attributes": Schema.optionalKey(VectorStoreFileAttributes) + }) +]).annotate({ "identifier": "CreateVectorStoreFileBatchRequest" }) +export type ThreadItem = + | UserMessageItem + | AssistantMessageItem + | WidgetMessageItem + | ClientToolCallItem + | TaskItem + | TaskGroupItem +export const ThreadItem = Schema.Union([ + UserMessageItem, + AssistantMessageItem, + WidgetMessageItem, + ClientToolCallItem, + TaskItem, + TaskGroupItem +], { mode: "oneOf" }).annotate({ "title": "The thread item", "identifier": "ThreadItem" }) +export type DecisionInputMessage = { + readonly "role": "user" + readonly "content": DecisionInputContent + readonly "type"?: "message" +} +export const DecisionInputMessage = Schema.Struct({ + "role": Schema.Literal("user"), + "content": DecisionInputContent, + "type": Schema.optionalKey(Schema.Literal("message")) +}).annotate({ "description": "A user message containing text or images.", "identifier": "DecisionInputMessage" }) +export type DecisionResponse = { + readonly "model": string + readonly "answers": ReadonlyArray + readonly "usage": ResponseUsageResource +} +export const DecisionResponse = Schema.Struct({ + "model": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "answers": Schema.Array(AnswerResource).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "usage": ResponseUsageResource +}).annotate({ "identifier": "DecisionResponse" }) +export type CreateEnvironmentParamOpenaiHosted = { + readonly "type": "openai_hosted" + readonly "packages"?: EnvironmentPackagesParam | null + readonly "setup_commands"?: ReadonlyArray | null + readonly "network"?: NetworkPolicyParam | null + readonly "desktop"?: DesktopParam | null + readonly "env"?: { readonly [x: string]: string } | null + readonly "capability_directories"?: ReadonlyArray | null + readonly "skills"?: ReadonlyArray | null + readonly "plugins"?: ReadonlyArray | null + readonly "files"?: ReadonlyArray | null + readonly "environment_template_id"?: string +} +export const CreateEnvironmentParamOpenaiHosted = Schema.Struct({ + "type": Schema.Literal("openai_hosted").annotate({ + "description": "The type of the object. Always `openai_hosted`." + }), + "packages": Schema.optionalKey( + Schema.Union([EnvironmentPackagesParam, Schema.Null]).annotate({ + "description": "Packages to install in the environment. Defaults to empty package lists." + }) + ), + "setup_commands": Schema.optionalKey( + Schema.Union([ + Schema.Array(SetupCommandParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16).annotate({ "expected": "a value with a length of at most 16" })), + Schema.Null + ]).annotate({ "description": "Ordered, confidential setup commands. Command bodies are never returned." }) + ), + "network": Schema.optionalKey( + Schema.Union([NetworkPolicyParam, Schema.Null]).annotate({ + "description": + "Network access policy for the environment. If omitted, the API version determines whether network access is enabled or disabled." + }) + ), + "desktop": Schema.optionalKey( + Schema.Union([DesktopParam, Schema.Null]).annotate({ + "description": "Desktop provisioning. Omission or null inherits the template setting, or defaults to disabled." + }) + ), + "env": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ "description": "Environment variables made available to the agent." }) + ), + "capability_directories": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ + "description": "Directories that contain capabilities exposed to the agent. Defaults to an empty list." + }) + ), + "skills": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedSkillParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" })), + Schema.Null + ]).annotate({ + "description": "Skills referenced by ID or provided as inline ZIP archives. Defaults to an empty list." + }) + ), + "plugins": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedPluginParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(32).annotate({ "expected": "a value with a length of at most 32" })), + Schema.Null + ]).annotate({ "description": "Plugins provided as inline ZIP archives. Defaults to an empty list." }) + ), + "files": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedEnvironmentFileParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })), + Schema.Null + ]).annotate({ "description": "Files available before the agent starts. Defaults to an empty list." }) + ), + "environment_template_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A reusable hosted template applied before inline configuration. Omitted fields inherit the template; network overrides cannot broaden its policy." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ) + ) +}).annotate({ + "description": "Provision an OpenAI-hosted environment from inline configuration or a template.", + "identifier": "CreateEnvironmentParamOpenaiHosted" +}) +export type CreateEnvironmentTemplateParams = { + readonly "packages"?: EnvironmentPackagesParam | null + readonly "setup_commands"?: ReadonlyArray | null + readonly "network"?: NetworkPolicyParam | null + readonly "desktop"?: DesktopParam | null + readonly "env"?: { readonly [x: string]: string } | null + readonly "capability_directories"?: ReadonlyArray | null + readonly "skills"?: ReadonlyArray | null + readonly "plugins"?: ReadonlyArray | null + readonly "files"?: ReadonlyArray | null + readonly "name"?: string | null +} +export const CreateEnvironmentTemplateParams = Schema.Struct({ + "packages": Schema.optionalKey( + Schema.Union([EnvironmentPackagesParam, Schema.Null]).annotate({ + "description": "Packages to install in the environment. Defaults to empty package lists." + }) + ), + "setup_commands": Schema.optionalKey( + Schema.Union([ + Schema.Array(SetupCommandParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16).annotate({ "expected": "a value with a length of at most 16" })), + Schema.Null + ]).annotate({ "description": "Ordered, confidential setup commands. Command bodies are never returned." }) + ), + "network": Schema.optionalKey( + Schema.Union([NetworkPolicyParam, Schema.Null]).annotate({ + "description": + "Network access policy for the environment. If omitted, the API version determines whether network access is enabled or disabled." + }) + ), + "desktop": Schema.optionalKey( + Schema.Union([DesktopParam, Schema.Null]).annotate({ + "description": "Desktop provisioning. Omission or null inherits the template setting, or defaults to disabled." + }) + ), + "env": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ "description": "Environment variables made available to the agent." }) + ), + "capability_directories": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ + "description": "Directories that contain capabilities exposed to the agent. Defaults to an empty list." + }) + ), + "skills": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedSkillParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" })), + Schema.Null + ]).annotate({ + "description": "Skills referenced by ID or provided as inline ZIP archives. Defaults to an empty list." + }) + ), + "plugins": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedPluginParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(32).annotate({ "expected": "a value with a length of at most 32" })), + Schema.Null + ]).annotate({ "description": "Plugins provided as inline ZIP archives. Defaults to an empty list." }) + ), + "files": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedEnvironmentFileParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })), + Schema.Null + ]).annotate({ "description": "Files available before the agent starts. Defaults to an empty list." }) + ), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ), + Schema.Null + ]).annotate({ "description": "An optional human-readable display name for the template." }) + ) +}).annotate({ + "description": "Parameters for creating a reusable, project-scoped OpenAI-hosted environment template.", + "identifier": "CreateEnvironmentTemplateParams" +}) +export type UpdateEnvironmentTemplateParams = { + readonly "name"?: string | null + readonly "packages"?: EnvironmentPackagesParam | null + readonly "setup_commands"?: ReadonlyArray | null + readonly "network"?: NetworkPolicyParam | null + readonly "desktop"?: DesktopParam | null + readonly "env"?: { readonly [x: string]: string } | null + readonly "capability_directories"?: ReadonlyArray | null + readonly "skills"?: ReadonlyArray | null + readonly "plugins"?: ReadonlyArray | null + readonly "files"?: ReadonlyArray | null +} +export const UpdateEnvironmentTemplateParams = Schema.Struct({ + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ), + Schema.Null + ]).annotate({ "description": "A replacement human-readable display name, or `null` to clear the name." }) + ), + "packages": Schema.optionalKey( + Schema.Union([EnvironmentPackagesParam, Schema.Null]).annotate({ + "description": "Packages installed before the runtime network policy applies." + }) + ), + "setup_commands": Schema.optionalKey( + Schema.Union([ + Schema.Array(SetupCommandParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16).annotate({ "expected": "a value with a length of at most 16" })), + Schema.Null + ]).annotate({ "description": "Replacement confidential setup commands, never included in returned resources." }) + ), + "network": Schema.optionalKey( + Schema.Union([NetworkPolicyParam, Schema.Null]).annotate({ + "description": + "Network access available after setup completes. Omit to preserve the current policy, or pass `null` to reset to the default policy." + }) + ), + "desktop": Schema.optionalKey( + Schema.Union([DesktopParam, Schema.Null]).annotate({ + "description": "Replacement desktop configuration, or null to disable the desktop." + }) + ), + "env": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ "description": "Replacement confidential environment values." }) + ), + "capability_directories": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "Directories that expose capabilities to the agent." }) + ), + "skills": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedSkillParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" })), + Schema.Null + ]).annotate({ "description": "Replacement skill configuration installed for each new session." }) + ), + "plugins": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedPluginParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(32).annotate({ "expected": "a value with a length of at most 32" })), + Schema.Null + ]).annotate({ "description": "Replacement plugin configuration installed for each new session." }) + ), + "files": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedEnvironmentFileParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })), + Schema.Null + ]).annotate({ "description": "Replacement file configuration materialized for each new session." }) + ) +}).annotate({ + "description": "Fields to replace on an existing reusable OpenAI-hosted environment template.", + "identifier": "UpdateEnvironmentTemplateParams" +}) +export type EnvironmentParamOpenaiHosted = { + readonly "type": "openai_hosted" + readonly "packages"?: EnvironmentPackagesParam | null + readonly "setup_commands"?: ReadonlyArray | null + readonly "network"?: NetworkPolicyParam | null + readonly "desktop"?: DesktopParam | null + readonly "env"?: { readonly [x: string]: string } | null + readonly "capability_directories"?: ReadonlyArray | null + readonly "skills"?: ReadonlyArray | null + readonly "plugins"?: ReadonlyArray | null + readonly "files"?: ReadonlyArray | null + readonly "environment_id"?: never + readonly "environment_template_id"?: string + readonly "container_size"?: ContainerSizeParam +} | { + readonly "type": "openai_hosted" + readonly "packages"?: never + readonly "setup_commands"?: never + readonly "network"?: never + readonly "desktop"?: never + readonly "env"?: never + readonly "capability_directories"?: never + readonly "skills"?: never + readonly "plugins"?: never + readonly "files"?: never + readonly "environment_id"?: string + readonly "environment_template_id"?: never + readonly "container_size"?: never +} +export const EnvironmentParamOpenaiHosted = Schema.Union([ + Schema.Struct({ + "type": Schema.Literal("openai_hosted").annotate({ + "description": "The type of the object. Always `openai_hosted`." + }), + "packages": Schema.optionalKey( + Schema.Union([EnvironmentPackagesParam, Schema.Null]).annotate({ + "description": "Packages to install in the environment. Defaults to empty package lists." + }) + ), + "setup_commands": Schema.optionalKey( + Schema.Union([ + Schema.Array(SetupCommandParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16).annotate({ "expected": "a value with a length of at most 16" })), + Schema.Null + ]).annotate({ "description": "Ordered, confidential setup commands. Command bodies are never returned." }) + ), + "network": Schema.optionalKey( + Schema.Union([NetworkPolicyParam, Schema.Null]).annotate({ + "description": + "Network access policy for the environment. If omitted, the API version determines whether network access is enabled or disabled." + }) + ), + "desktop": Schema.optionalKey( + Schema.Union([DesktopParam, Schema.Null]).annotate({ + "description": "Desktop provisioning. Omission or null inherits the template setting, or defaults to disabled." + }) + ), + "env": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(1024).annotate({ "expected": "a value with at most 1024 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ "description": "Environment variables made available to the agent." }) + ), + "capability_directories": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ + "description": "Directories that contain capabilities exposed to the agent. Defaults to an empty list." + }) + ), + "skills": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedSkillParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" })), + Schema.Null + ]).annotate({ + "description": "Skills referenced by ID or provided as inline ZIP archives. Defaults to an empty list." + }) + ), + "plugins": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedPluginParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(32).annotate({ "expected": "a value with a length of at most 32" })), + Schema.Null + ]).annotate({ "description": "Plugins provided as inline ZIP archives. Defaults to an empty list." }) + ), + "files": Schema.optionalKey( + Schema.Union([ + Schema.Array(HostedEnvironmentFileParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(50).annotate({ "expected": "a value with a length of at most 50" })), + Schema.Null + ]).annotate({ "description": "Files available before the agent starts. Defaults to an empty list." }) + ), + "environment_id": Schema.optionalKey(Schema.Never), + "environment_template_id": Schema.optionalKey( + Schema.String.annotate({ + "description": + "A reusable hosted template applied before inline session configuration. Omitted fields inherit the template; network overrides cannot broaden its policy." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ) + ), + "container_size": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ContainerSizeParam).annotate({ + "description": "The hosted container size. Omission selects the medium tier." + }) + ) + }), + Schema.Struct({ + "type": Schema.Literal("openai_hosted").annotate({ + "description": "The type of the object. Always `openai_hosted`." + }), + "packages": Schema.optionalKey(Schema.Never), + "setup_commands": Schema.optionalKey(Schema.Never), + "network": Schema.optionalKey(Schema.Never), + "desktop": Schema.optionalKey(Schema.Never), + "env": Schema.optionalKey(Schema.Never), + "capability_directories": Schema.optionalKey(Schema.Never), + "skills": Schema.optionalKey(Schema.Never), + "plugins": Schema.optionalKey(Schema.Never), + "files": Schema.optionalKey(Schema.Never), + "environment_id": Schema.optionalKey( + Schema.String.annotate({ + "description": "An existing prewarmed environment. Cannot be combined with a template or inline configuration." + }).check(Schema.isMinCodePoints(9).annotate({ "expected": "a string with at least 9 code points" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ) + ), + "environment_template_id": Schema.optionalKey(Schema.Never), + "container_size": Schema.optionalKey(Schema.Never) + }) +]).annotate({ + "description": "An existing OpenAI-hosted environment or new inline/template-based hosted configuration.", + "identifier": "EnvironmentParamOpenaiHosted" +}) +export type SessionTurnItemResource = + | MessageItemResource + | ReasoningItemResource + | FunctionCallItemResource + | FunctionCallOutputItemResource + | AgentMessageItemResource + | McpCallItemResource + | ComputerUseCallItemResource + | BrowserAuthenticationRequestItemResource + | ComputerUseApprovalRequestResultItemResource + | WebSearchCallItemResource + | CommandExecutionItemResource + | CreateSubagentCallItemResource + | SendSubagentInputCallItemResource + | ResumeSubagentCallItemResource + | WaitForSubagentsCallItemResource + | InterruptSubagentCallItemResource + | CloseSubagentCallItemResource +export const SessionTurnItemResource = Schema.Union([ + MessageItemResource, + ReasoningItemResource, + FunctionCallItemResource, + FunctionCallOutputItemResource, + AgentMessageItemResource, + McpCallItemResource, + ComputerUseCallItemResource, + BrowserAuthenticationRequestItemResource, + ComputerUseApprovalRequestResultItemResource, + WebSearchCallItemResource, + CommandExecutionItemResource, + CreateSubagentCallItemResource, + SendSubagentInputCallItemResource, + ResumeSubagentCallItemResource, + WaitForSubagentsCallItemResource, + InterruptSubagentCallItemResource, + CloseSubagentCallItemResource +], { mode: "oneOf" }).annotate({ + "description": "An item associated with a session turn.", + "identifier": "SessionTurnItemResource" +}) +export type AgentOutputItemResource = + | AssistantMessageItemResource + | ReasoningItemResource + | FunctionCallItemResource + | McpCallItemResource + | ComputerUseCallItemResource + | BrowserAuthenticationRequestItemResource + | WebSearchCallItemResource + | CommandExecutionItemResource + | CreateSubagentCallItemResource + | SendSubagentInputCallItemResource + | ResumeSubagentCallItemResource + | WaitForSubagentsCallItemResource + | InterruptSubagentCallItemResource + | CloseSubagentCallItemResource +export const AgentOutputItemResource = Schema.Union([ + AssistantMessageItemResource, + ReasoningItemResource, + FunctionCallItemResource, + McpCallItemResource, + ComputerUseCallItemResource, + BrowserAuthenticationRequestItemResource, + WebSearchCallItemResource, + CommandExecutionItemResource, + CreateSubagentCallItemResource, + SendSubagentInputCallItemResource, + ResumeSubagentCallItemResource, + WaitForSubagentsCallItemResource, + InterruptSubagentCallItemResource, + CloseSubagentCallItemResource +], { mode: "oneOf" }).annotate({ + "description": "An output item produced by an agent.", + "identifier": "AgentOutputItemResource" +}) +export type SessionRequiredActionResource = + | SessionRequiredActionResourceComputerUseApprovalRequest + | SessionRequiredActionResourceFunctionCall + | SessionRequiredActionResourceEnvironmentConnection +export const SessionRequiredActionResource = Schema.Union([ + SessionRequiredActionResourceComputerUseApprovalRequest, + SessionRequiredActionResourceFunctionCall, + SessionRequiredActionResourceEnvironmentConnection +], { mode: "oneOf" }).annotate({ + "description": "An action that must be completed before a session can continue.", + "identifier": "SessionRequiredActionResource" +}) +export type AgentResource = { + readonly "id": string + readonly "object": "agent" + readonly "created_at": number + readonly "updated_at": number + readonly "name": string | null + readonly "metadata": { readonly [x: string]: string } + readonly "model": string + readonly "reasoning": ReasoningResource + readonly "text": TextResource + readonly "service_tier": ServiceTierResource + readonly "instructions": string | null + readonly "tools": ReadonlyArray + readonly "multi_agent": MultiAgentConfigResource +} +export const AgentResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the reusable agent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("agent").annotate({ "description": "The object type. Always `agent`." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the agent was created.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "updated_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the agent was last updated.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "A human-readable name for the agent, or null if it is unnamed." }), + "metadata": Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Custom string key-value pairs attached to the agent." }).check( + Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + "model": Schema.String.annotate({ "description": "The requested model name used for inference." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "reasoning": Schema.suspend((): Schema.Codec => ReasoningResource).annotate({ + "description": "The resolved reasoning configuration, including the model default for an omitted effort." + }), + "text": Schema.suspend((): Schema.Codec => TextResource).annotate({ + "description": "The resolved configuration for text generated by the agent." + }), + "service_tier": Schema.suspend((): Schema.Codec => ServiceTierResource).annotate({ + "description": "The resolved service-tier policy used for model requests." + }), + "instructions": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "Custom instructions appended to the agent's default base instructions." }), + "tools": Schema.Array(PersistedAgentToolResource).annotate({ "description": "Tools available to the agent." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "multi_agent": Schema.suspend((): Schema.Codec => MultiAgentConfigResource).annotate({ + "description": "The resolved configuration for creating and coordinating subagents." + }) +}).annotate({ "description": "A reusable agent scoped to the caller's project.", "identifier": "AgentResource" }) +export type CreateAgentParams = { + readonly "metadata"?: { readonly [x: string]: string } | null + readonly "name"?: string | null + readonly "model": string + readonly "reasoning"?: ReasoningParam | null + readonly "text"?: TextParam | null + readonly "service_tier"?: ServiceTierParam | null + readonly "instructions"?: string | null + readonly "tools"?: ReadonlyArray | null + readonly "multi_agent"?: MultiAgentConfigCurrentParam | null +} +export const CreateAgentParams = Schema.Struct({ + "metadata": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ + "description": + "Up to 16 string key-value pairs, with keys up to 64 and values up to 512 characters. Omission or null defaults to an empty map." + }) + ), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ]).annotate({ "description": "A human-readable name for the agent. Omission or null leaves the agent unnamed." }) + ), + "model": Schema.String.annotate({ + "description": "The model to use for the agent. The requested model name is preserved." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "reasoning": Schema.optionalKey( + Schema.Union([ReasoningParam, Schema.Null]).annotate({ + "description": "Configuration for model reasoning. Omission uses the model's default effort." + }) + ), + "text": Schema.optionalKey( + Schema.Union([TextParam, Schema.Null]).annotate({ + "description": "Configuration for generated text. Defaults to the `text` format and medium verbosity." + }) + ), + "service_tier": Schema.optionalKey( + Schema.Union([ServiceTierParam, Schema.Null]).annotate({ + "description": "The service tier used for model requests. Defaults to `auto`." + }) + ), + "instructions": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "Additional instructions appended to the agent's default base instructions. Omit or set to null to add no custom instructions." + }) + ), + "tools": Schema.optionalKey( + Schema.Union([ + Schema.Array(PersistedAgentToolConfigParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + Schema.Null + ]).annotate({ + "description": + "Tools available to the agent. Defaults to an empty list. The tool list must fit within 3 MiB (3,145,728 bytes) of compact UTF-8 JSON." + }) + ), + "multi_agent": Schema.optionalKey( + Schema.Union([MultiAgentConfigCurrentParam, Schema.Null]).annotate({ + "description": "Configuration for creating and coordinating subagents. Subagent tools are disabled by default." + }) + ) +}).annotate({ "description": "Parameters for creating a reusable agent.", "identifier": "CreateAgentParams" }) +export type UpdateAgentParams = { + readonly "model"?: string + readonly "reasoning"?: ReasoningParam | null + readonly "text"?: TextParam | null + readonly "service_tier"?: ServiceTierParam | null + readonly "instructions"?: string | null + readonly "multi_agent"?: MultiAgentConfigCurrentParam | null + readonly "metadata"?: { readonly [x: string]: string } | null + readonly "name"?: string | null + readonly "tools"?: ReadonlyArray | null +} +export const UpdateAgentParams = Schema.Struct({ + "model": Schema.optionalKey( + Schema.String.annotate({ "description": "The model to use for the agent. The requested model name is preserved." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ) + ), + "reasoning": Schema.optionalKey( + Schema.Union([ReasoningParam, Schema.Null]).annotate({ + "description": + "Configuration for model reasoning. Omit to keep the current settings; pass `null` to reset to the model's default effort." + }) + ), + "text": Schema.optionalKey( + Schema.Union([TextParam, Schema.Null]).annotate({ "description": "Configuration for text generated by the agent." }) + ), + "service_tier": Schema.optionalKey( + Schema.Union([ServiceTierParam, Schema.Null]).annotate({ + "description": "The service tier used for model requests." + }) + ), + "instructions": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "Additional instructions appended to the agent's default base instructions. Omit to leave unchanged." + }) + ), + "multi_agent": Schema.optionalKey( + Schema.Union([MultiAgentConfigCurrentParam, Schema.Null]).annotate({ + "description": "Configuration for creating and coordinating subagents." + }) + ), + "metadata": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ + "description": + "Replaces all metadata. Omit to leave unchanged, or pass null or {} to clear it. Up to 16 string key-value pairs, with keys up to 64 and values up to 512 characters." + }) + ), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ]).annotate({ "description": "A replacement name. Omit to leave unchanged, or pass null to clear it." }) + ), + "tools": Schema.optionalKey( + Schema.Union([ + Schema.Array(PersistedAgentToolConfigParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + Schema.Null + ]).annotate({ + "description": + "Replaces the tool list. Omit to leave it unchanged, or pass null to clear it. The replacement must fit within 3 MiB (3,145,728 bytes) of compact UTF-8 JSON." + }) + ) +}).annotate({ "description": "Fields to replace on an existing reusable agent.", "identifier": "UpdateAgentParams" }) +export type SessionAgentResource = { + readonly "id": string + readonly "name": string | null + readonly "model": string + readonly "reasoning": ReasoningResource + readonly "text": TextResource + readonly "service_tier": ServiceTierResource + readonly "instructions": string | null + readonly "tools": ReadonlyArray + readonly "multi_agent": MultiAgentConfigResource +} +export const SessionAgentResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the agent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "name": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The reusable agent's name when the session was created, or null if no name was saved. Later changes to the agent's name do not affect this value." + }), + "model": Schema.String.annotate({ "description": "The model used by the agent." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "reasoning": Schema.suspend((): Schema.Codec => ReasoningResource).annotate({ + "description": "The agent's reasoning configuration." + }), + "text": Schema.suspend((): Schema.Codec => TextResource).annotate({ + "description": "Configuration for text generated by the agent." + }), + "service_tier": Schema.suspend((): Schema.Codec => ServiceTierResource).annotate({ + "description": "The effective service-tier policy for model requests. Defaults to `auto`." + }), + "instructions": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "Custom instructions appended to the agent's default base instructions." }), + "tools": Schema.Array(AgentToolResource).annotate({ "description": "Tools available to the agent." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "multi_agent": Schema.suspend((): Schema.Codec => MultiAgentConfigResource).annotate({ + "description": "Configuration for creating and coordinating subagents." + }) +}).annotate({ "description": "The effective agent configuration for a session.", "identifier": "SessionAgentResource" }) +export type SessionAgentConfigParam = { + readonly "model"?: string + readonly "reasoning"?: ReasoningParam | null + readonly "text"?: TextParam | null + readonly "service_tier"?: ServiceTierParam | null + readonly "instructions"?: string | null + readonly "multi_agent"?: MultiAgentConfigCurrentParam | null + readonly "tools"?: ReadonlyArray | null +} +export const SessionAgentConfigParam = Schema.Struct({ + "model": Schema.optionalKey( + Schema.String.annotate({ "description": "The model to use for the agent. The requested model name is preserved." }) + .check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ) + ), + "reasoning": Schema.optionalKey( + Schema.Union([ReasoningParam, Schema.Null]).annotate({ + "description": + "Configuration for model reasoning. Omit to keep the current settings; pass `null` to reset to the model's default effort." + }) + ), + "text": Schema.optionalKey( + Schema.Union([TextParam, Schema.Null]).annotate({ "description": "Configuration for text generated by the agent." }) + ), + "service_tier": Schema.optionalKey( + Schema.Union([ServiceTierParam, Schema.Null]).annotate({ + "description": "The service tier used for model requests." + }) + ), + "instructions": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]).annotate({ + "description": + "Additional instructions appended to the agent's default base instructions. Omit to leave unchanged." + }) + ), + "multi_agent": Schema.optionalKey( + Schema.Union([MultiAgentConfigCurrentParam, Schema.Null]).annotate({ + "description": "Configuration for creating and coordinating subagents." + }) + ), + "tools": Schema.optionalKey( + Schema.Union([ + Schema.Array(AgentToolConfigParam).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" })), + Schema.Null + ]).annotate({ + "description": + "Tools available to the agent. Omit to inherit, or pass null to clear them. The resolved tool list must fit within 3 MiB (3,145,728 bytes) of compact UTF-8 JSON." + }) + ) +}).annotate({ + "description": + "Agent configuration for a session. Omitted fields inherit from `agent_id` when supplied. Supplied objects and arrays replace the whole field; null resets nullable fields.", + "identifier": "SessionAgentConfigParam" +}) +export type SessionInputParam = + | SessionInputParamAgentSessionInputComputerUseApprovalRequestResult + | SessionInputParamAgentSessionInputMessage + | SessionInputParamAgentSessionInputCancel + | SessionInputParamAgentSessionInputToolResult +export const SessionInputParam = Schema.Union([ + SessionInputParamAgentSessionInputComputerUseApprovalRequestResult, + SessionInputParamAgentSessionInputMessage, + SessionInputParamAgentSessionInputCancel, + SessionInputParamAgentSessionInputToolResult +], { mode: "oneOf" }).annotate({ + "description": "Input submitted to an existing session.", + "identifier": "SessionInputParam" +}) +export type VaultCredentialAuthResource = + | VaultCredentialAuthResourceMcpOauth + | VaultCredentialAuthResourceStaticBearer + | VaultCredentialAuthResourceEnvironmentVariable +export const VaultCredentialAuthResource = Schema.Union([ + VaultCredentialAuthResourceMcpOauth, + VaultCredentialAuthResourceStaticBearer, + VaultCredentialAuthResourceEnvironmentVariable +], { mode: "oneOf" }).annotate({ + "description": "The authentication configuration of a vault credential, excluding secrets.", + "identifier": "VaultCredentialAuthResource" +}) +export type CreateVaultCredentialAuthParam = + | CreateVaultCredentialAuthParamMcpOauth + | CreateVaultCredentialAuthParamStaticBearer + | CreateVaultCredentialAuthParamEnvironmentVariable +export const CreateVaultCredentialAuthParam = Schema.Union([ + CreateVaultCredentialAuthParamMcpOauth, + CreateVaultCredentialAuthParamStaticBearer, + CreateVaultCredentialAuthParamEnvironmentVariable +], { mode: "oneOf" }).annotate({ + "description": "Authentication credentials for an MCP server or an OpenAI-hosted environment.", + "identifier": "CreateVaultCredentialAuthParam" +}) +export type RotateVaultCredentialAuthParam = + | RotateVaultCredentialAuthParamMcpOauth + | RotateVaultCredentialAuthParamStaticBearer + | RotateVaultCredentialAuthParamEnvironmentVariable +export const RotateVaultCredentialAuthParam = Schema.Union([ + RotateVaultCredentialAuthParamMcpOauth, + RotateVaultCredentialAuthParamStaticBearer, + RotateVaultCredentialAuthParamEnvironmentVariable +], { mode: "oneOf" }).annotate({ + "description": + "Updates to a vault credential without changing its authentication method or destination configuration.", + "identifier": "RotateVaultCredentialAuthParam" +}) +export type BetaTool = + | BetaFunctionTool + | BetaFileSearchTool + | BetaComputerTool + | BetaComputerUsePreviewTool + | BetaWebSearchTool + | BetaMCPTool + | BetaCodeInterpreterTool + | BetaProgrammaticToolCallingParam + | BetaImageGenTool + | BetaLocalShellToolParam + | BetaFunctionShellToolParam + | BetaCustomToolParam + | BetaNamespaceToolParam + | BetaToolSearchToolParam + | BetaWebSearchPreviewTool + | BetaApplyPatchToolParam +export const BetaTool = Schema.Union([ + BetaFunctionTool, + BetaFileSearchTool, + BetaComputerTool, + BetaComputerUsePreviewTool, + BetaWebSearchTool, + BetaMCPTool, + BetaCodeInterpreterTool, + BetaProgrammaticToolCallingParam, + BetaImageGenTool, + BetaLocalShellToolParam, + BetaFunctionShellToolParam, + BetaCustomToolParam, + BetaNamespaceToolParam, + BetaToolSearchToolParam, + BetaWebSearchPreviewTool, + BetaApplyPatchToolParam +], { mode: "oneOf" }).annotate({ + "description": "A tool that can be used to generate a response.\n", + "identifier": "BetaTool" +}) +export type BetaToolSearchOutputTool = + | BetaFunctionTool + | BetaFileSearchTool + | BetaComputerTool + | BetaComputerUsePreviewTool + | BetaWebSearchTool + | BetaMCPTool + | BetaCodeInterpreterTool + | BetaProgrammaticToolCallingParam + | BetaImageGenTool + | BetaLocalShellToolParam + | BetaFunctionShellToolParam + | BetaCustomToolParam + | BetaToolSearchOutputNamespaceToolParam + | BetaToolSearchToolParam + | BetaWebSearchPreviewTool + | BetaApplyPatchToolParam +export const BetaToolSearchOutputTool = Schema.Union([ + BetaFunctionTool, + BetaFileSearchTool, + BetaComputerTool, + BetaComputerUsePreviewTool, + BetaWebSearchTool, + BetaMCPTool, + BetaCodeInterpreterTool, + BetaProgrammaticToolCallingParam, + BetaImageGenTool, + BetaLocalShellToolParam, + BetaFunctionShellToolParam, + BetaCustomToolParam, + BetaToolSearchOutputNamespaceToolParam, + BetaToolSearchToolParam, + BetaWebSearchPreviewTool, + BetaApplyPatchToolParam +], { mode: "oneOf" }).annotate({ + "description": "A tool definition returned by a tool search output.\n", + "identifier": "BetaToolSearchOutputTool" +}) +export type BetaEasyInputMessage = { + readonly "role": "user" | "assistant" | "system" | "developer" + readonly "content": string | BetaInputMessageContentList + readonly "phase"?: BetaMessagePhase | null + readonly "type"?: "message" +} +export const BetaEasyInputMessage = Schema.Struct({ + "role": Schema.Literals(["user", "assistant", "system", "developer"]).annotate({ + "description": "The role of the message input. One of `user`, `assistant`, `system`, or\n`developer`.\n" + }), + "content": Schema.Union([ + Schema.String.annotate({ "title": "Text input", "description": "A text input to the model.\n" }), + BetaInputMessageContentList + ], { mode: "oneOf" }).annotate({ + "description": + "Text, image, or audio input to the model, used to generate a response.\nCan also contain previous assistant responses.\n" + }), + "phase": Schema.optionalKey(Schema.Union([BetaMessagePhase, Schema.Null])), + "type": Schema.optionalKey( + Schema.Literal("message").annotate({ "description": "The type of the message input. Always `message`.\n" }) + ) +}).annotate({ + "title": "Input message", + "description": + "A message input to the model with a role indicating instruction following\nhierarchy. Instructions given with the `developer` or `system` role take\nprecedence over instructions given with the `user` role. Messages with the\n`assistant` role are presumed to have been generated by the model in previous\ninteractions.\n", + "identifier": "BetaEasyInputMessage" +}) +export type BetaInputMessageResource = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "message" + readonly "role": "user" | "system" | "developer" + readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "content": BetaInputMessageContentList + readonly "id": string +} +export const BetaInputMessageResource = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("message").annotate({ + "description": "The type of the message input. Always set to `message`.\n" + }), + "role": Schema.Literals(["user", "system", "developer"]).annotate({ + "description": "The role of the message input. One of `user`, `system`, or `developer`.\n" + }), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ), + "content": BetaInputMessageContentList, + "id": Schema.String.annotate({ "description": "The unique ID of the message input.\n" }) +}).annotate({ "identifier": "BetaInputMessageResource" }) +export type BetaOutputMessage = { + readonly "agent"?: BetaAgentTag | null + readonly "id": string + readonly "type": "message" + readonly "role": "assistant" + readonly "content": ReadonlyArray + readonly "phase"?: BetaMessagePhase | null + readonly "status": "in_progress" | "completed" | "incomplete" +} +export const BetaOutputMessage = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "id": Schema.String.annotate({ "description": "The unique ID of the output message.\n" }), + "type": Schema.Literal("message").annotate({ "description": "The type of the output message. Always `message`.\n" }), + "role": Schema.Literal("assistant").annotate({ + "description": "The role of the output message. Always `assistant`.\n" + }), + "content": Schema.Array(BetaOutputMessageContent).annotate({ "description": "The content of the output message.\n" }), + "phase": Schema.optionalKey(Schema.Union([BetaMessagePhase, Schema.Null])), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" + }) +}).annotate({ + "title": "Output message", + "description": "An output message from the model.\n", + "identifier": "BetaOutputMessage" +}) +export type BetaResponseContentPartAddedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.content_part.added" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "part": BetaOutputContent + readonly "sequence_number": number +} +export const BetaResponseContentPartAddedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.content_part.added").annotate({ + "description": "The type of the event. Always `response.content_part.added`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the content part was added to.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the content part was added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ "description": "The index of the content part that was added.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "part": Schema.suspend((): Schema.Codec => BetaOutputContent).annotate({ + "description": "The content part that was added.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when a new content part is added.", + "identifier": "BetaResponseContentPartAddedEvent" +}) +export type BetaResponseContentPartDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.content_part.done" + readonly "item_id": string + readonly "output_index": number + readonly "content_index": number + readonly "sequence_number": number + readonly "part": BetaOutputContent +} +export const BetaResponseContentPartDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.content_part.done").annotate({ + "description": "The type of the event. Always `response.content_part.done`.\n" + }), + "item_id": Schema.String.annotate({ + "description": "The ID of the output item that the content part was added to.\n" + }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item that the content part was added to.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "content_index": Schema.Number.annotate({ "description": "The index of the content part that is done.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "part": Schema.suspend((): Schema.Codec => BetaOutputContent).annotate({ + "description": "The content part that is done.\n" + }) +}).annotate({ "description": "Emitted when a content part is done.", "identifier": "BetaResponseContentPartDoneEvent" }) +export type BetaComputerToolCall = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "computer_call" + readonly "id": string + readonly "call_id": string + readonly "action"?: BetaComputerAction + readonly "actions"?: BetaComputerActionList + readonly "pending_safety_checks": ReadonlyArray + readonly "status": "in_progress" | "completed" | "incomplete" +} +export const BetaComputerToolCall = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("computer_call").annotate({ + "description": "The type of the computer call. Always `computer_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the computer call." }), + "call_id": Schema.String.annotate({ + "description": "An identifier used when responding to the tool call with output.\n" + }), + "action": Schema.optionalKey(BetaComputerAction), + "actions": Schema.optionalKey(BetaComputerActionList), + "pending_safety_checks": Schema.Array(BetaComputerCallSafetyCheckParam).annotate({ + "description": "The pending safety checks for the computer call.\n" + }), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) +}).annotate({ + "title": "Computer tool call", + "description": + "A tool call to a computer use tool. See the\n[computer use guide](https://developers.openai.com/api/docs/guides/tools-computer-use) for more information.\n", + "identifier": "BetaComputerToolCall" +}) +export type RunStepStreamEvent = + | { readonly "event": "thread.run.step.created"; readonly "data": RunStepObject } + | { readonly "event": "thread.run.step.in_progress"; readonly "data": RunStepObject } + | { readonly "event": "thread.run.step.delta"; readonly "data": RunStepDeltaObject } + | { readonly "event": "thread.run.step.completed"; readonly "data": RunStepObject } + | { readonly "event": "thread.run.step.failed"; readonly "data": RunStepObject } + | { readonly "event": "thread.run.step.cancelled"; readonly "data": RunStepObject } + | { readonly "event": "thread.run.step.expired"; readonly "data": RunStepObject } +export const RunStepStreamEvent = Schema.Union([ + Schema.Struct({ "event": Schema.Literal("thread.run.step.created"), "data": RunStepObject }).annotate({ + "description": "Occurs when a [run step](https://developers.openai.com/api/docs/assistants/migration) is created." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.step.in_progress"), "data": RunStepObject }).annotate({ + "description": + "Occurs when a [run step](https://developers.openai.com/api/docs/assistants/migration) moves to an `in_progress` state." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.step.delta"), "data": RunStepDeltaObject }).annotate({ + "description": + "Occurs when parts of a [run step](https://developers.openai.com/api/docs/assistants/migration) are being streamed." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.step.completed"), "data": RunStepObject }).annotate({ + "description": "Occurs when a [run step](https://developers.openai.com/api/docs/assistants/migration) is completed." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.step.failed"), "data": RunStepObject }).annotate({ + "description": "Occurs when a [run step](https://developers.openai.com/api/docs/assistants/migration) fails." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.step.cancelled"), "data": RunStepObject }).annotate({ + "description": "Occurs when a [run step](https://developers.openai.com/api/docs/assistants/migration) is cancelled." + }), + Schema.Struct({ "event": Schema.Literal("thread.run.step.expired"), "data": RunStepObject }).annotate({ + "description": "Occurs when a [run step](https://developers.openai.com/api/docs/assistants/migration) expires." + }) +], { mode: "oneOf" }).annotate({ "identifier": "RunStepStreamEvent" }) +export type ListRunStepsResponse = + | null + | string + | number + | boolean + | { + readonly "object": string + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean + } & { readonly [x: string]: Schema.Json } + | ReadonlyArray +export const ListRunStepsResponse = Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.StructWithRest( + Schema.Struct({ + "object": Schema.String, + "data": Schema.Array(RunStepObject), + "first_id": Schema.String, + "last_id": Schema.String, + "has_more": Schema.Boolean + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Array(Schema.Json.annotate({ "expected": "JSON value" })) +]).annotate({ "identifier": "ListRunStepsResponse" }) +export type ChatCompletionList = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const ChatCompletionList = Schema.Struct({ + "object": Schema.Literal("list").annotate({ + "description": "The type of this object. It is always set to \"list\".\n" + }), + "data": Schema.Array(CreateChatCompletionResponse).annotate({ + "description": "An array of chat completion objects.\n" + }), + "first_id": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The identifier of the first chat completion in the data array." + }), + "last_id": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The identifier of the last chat completion in the data array." + }), + "has_more": Schema.Boolean.annotate({ "description": "Indicates whether there are more Chat Completions available." }) +}).annotate({ + "title": "ChatCompletionList", + "description": "An object representing a list of Chat Completions.\n", + "identifier": "ChatCompletionList" +}) +export type CreateChatCompletionRequest = { + readonly "metadata"?: Metadata + readonly "top_logprobs"?: number + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "user"?: string | null + readonly "safety_identifier"?: string | null + readonly "prompt_cache_key"?: string | null + readonly "prompt_cache_retention"?: "in_memory" | "24h" | null + readonly "prompt_cache_options"?: PromptCacheOptionsParam + readonly "messages": ReadonlyArray + readonly "model": ModelIdsShared + readonly "service_tier"?: ServiceTier + readonly "modalities"?: ResponseModalities + readonly "verbosity"?: Verbosity + readonly "reasoning_effort"?: ReasoningEffort + readonly "max_completion_tokens"?: number | null + readonly "frequency_penalty"?: number | null + readonly "presence_penalty"?: number | null + readonly "web_search_options"?: { + readonly "user_location"?: + | { readonly "type": "approximate"; readonly "approximate": WebSearchLocation } & { + readonly [x: string]: Schema.Json + } + | null + readonly "search_context_size"?: WebSearchContextSize + } + readonly "response_format"?: ResponseFormatText | ResponseFormatJsonSchema | ResponseFormatJsonObject + readonly "audio"?: + | { readonly "voice": VoiceIdsOrCustomVoice; readonly "format": "wav" | "aac" | "mp3" | "flac" | "opus" | "pcm16" } + & { readonly [x: string]: Schema.Json } + | null + readonly "store"?: boolean | null + readonly "moderation"?: ModerationParam | null + readonly "stream"?: boolean | null + readonly "stop"?: StopConfiguration + readonly "logit_bias"?: { readonly [x: string]: number } | null + readonly "logprobs"?: boolean | null + readonly "max_tokens"?: number | null + readonly "n"?: number | null + readonly "prediction"?: PredictionContent | null + readonly "seed"?: number | null + readonly "stream_options"?: ChatCompletionStreamOptions + readonly "tools"?: ReadonlyArray + readonly "tool_choice"?: ChatCompletionToolChoiceOption + readonly "parallel_tool_calls"?: ParallelToolCalls + readonly "function_call"?: "none" | "auto" | ChatCompletionFunctionCallOption + readonly "functions"?: ReadonlyArray +} +export const CreateChatCompletionRequest = Schema.Struct({ + "metadata": Schema.optionalKey(Metadata), + "top_logprobs": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" })).check( + Schema.makeFilterGroup([ + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }), + Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" }) + ]).annotate({ + "description": + "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" + }) + ).check( + Schema.makeFilterGroup([ + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }), + Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" }) + ]).annotate({ + "description": + "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n`logprobs` must be set to `true` if this parameter is used.\n" + }) + ) + ), + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]) + ), + "top_p": Schema.optionalKey(Schema.Union([ + Schema.Number.annotate({ + "description": + "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + Schema.Null + ])), + "user": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }) + ), + "safety_identifier": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 128 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ])), + "prompt_cache_key": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching).\n" + }), + Schema.Null + ]) + ), + "prompt_cache_retention": Schema.optionalKey(Schema.Union([ + Schema.Literals(["in_memory", "24h"]).annotate({ + "description": + "Deprecated. Use `prompt_cache_options.ttl` instead.\n\nThe retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-retention).\nThis field expresses a maximum retention policy, while\n`prompt_cache_options.ttl` expresses a minimum cache lifetime. The two\nfields are independent and do not interact.\nFor `gpt-5.5`, `gpt-5.5-pro`, and future models, only `24h` is supported.\n\nFor older models that support both `in_memory` and `24h`, the default depends on your organization's data retention policy:\n - Organizations without ZDR enabled default to `24h`.\n - Organizations with ZDR enabled default to `in_memory` when `prompt_cache_retention` is not specified.\n" + }), + Schema.Null + ])), + "prompt_cache_options": Schema.optionalKey(PromptCacheOptionsParam), + "messages": Schema.Array(ChatCompletionRequestMessage).annotate({ + "description": + "A list of messages comprising the conversation so far. Depending on the\n[model](https://developers.openai.com/api/docs/models) you use, different message types (modalities) are\nsupported, like [text](https://developers.openai.com/api/docs/guides/text),\n[images](https://developers.openai.com/api/docs/guides/images-vision), and [audio](https://developers.openai.com/api/docs/guides/audio).\n" + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + "model": Schema.suspend((): Schema.Codec => ModelIdsShared).annotate({ + "description": + "Model ID used to generate the response, like `gpt-6-astra` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models)\nto browse and compare available models.\n" + }), + "service_tier": Schema.optionalKey(ServiceTier), + "modalities": Schema.optionalKey(ResponseModalities), + "verbosity": Schema.optionalKey(Verbosity), + "reasoning_effort": Schema.optionalKey(ReasoningEffort), + "max_completion_tokens": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": + "An upper bound for the number of tokens that can be generated for a completion, including visible output tokens and [reasoning tokens](https://developers.openai.com/api/docs/guides/reasoning).\n" + }) + ), + "frequency_penalty": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(-2).annotate({ "expected": "a value greater than or equal to -2" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]).annotate({ + "description": + "Number between -2.0 and 2.0. Positive values penalize new tokens based on\ntheir existing frequency in the text so far, decreasing the model's\nlikelihood to repeat the same line verbatim.\n" + }) + ), + "presence_penalty": Schema.optionalKey( + Schema.Union([ + Schema.Finite.check( + Schema.isGreaterThanOrEqualTo(-2).annotate({ "expected": "a value greater than or equal to -2" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]).annotate({ + "description": + "Number between -2.0 and 2.0. Positive values penalize new tokens based on\nwhether they appear in the text so far, increasing the model's likelihood\nto talk about new topics.\n" + }) + ), + "web_search_options": Schema.optionalKey( + Schema.Struct({ + "user_location": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "type": Schema.Literal("approximate").annotate({ + "description": "The type of location approximation. Always `approximate`.\n" + }), + "approximate": WebSearchLocation + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ "description": "Approximate location parameters for the search.\n" }) + ), + "search_context_size": Schema.optionalKey(WebSearchContextSize) + }).annotate({ + "title": "Web search", + "description": + "This tool searches the web for relevant results to use in a response.\nLearn more about the [web search tool](https://developers.openai.com/api/docs/guides/tools-web-search).\n" + }) + ), + "response_format": Schema.optionalKey( + Schema.Union([ResponseFormatText, ResponseFormatJsonSchema, ResponseFormatJsonObject], { mode: "oneOf" }).annotate({ + "description": + "An object specifying the format that the model must output.\n\nSetting to `{ \"type\": \"json_schema\", \"json_schema\": {...} }` enables\nStructured Outputs which ensures the model will match your supplied JSON\nschema. Learn more in the [Structured Outputs\nguide](https://developers.openai.com/api/docs/guides/structured-outputs).\n\nSetting to `{ \"type\": \"json_object\" }` enables the older JSON mode, which\nensures the message the model generates is valid JSON. Using `json_schema`\nis preferred for models that support it.\n" + }) + ), + "audio": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "voice": Schema.suspend((): Schema.Codec => VoiceIdsOrCustomVoice).annotate({ + "description": + "The voice the model uses to respond. Supported built-in voices are\n`alloy`, `ash`, `ballad`, `coral`, `echo`, `fable`, `nova`, `onyx`,\n`sage`, `shimmer`, `marin`, and `cedar`. You may also provide a\ncustom voice object with an `id`, for example `{ \"id\": \"voice_1234\" }`.\nCustom voices must be created from audio samples.\n" + }), + "format": Schema.Literals(["wav", "aac", "mp3", "flac", "opus", "pcm16"]).annotate({ + "description": + "Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`,\n`opus`, or `pcm16`.\n" + }) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ + "description": + "Parameters for audio output. Required when audio output is requested with\n`modalities: [\"audio\"]`. [Learn more](https://developers.openai.com/api/docs/guides/audio).\n" + }) + ), + "store": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": + "Whether or not to store the output of this chat completion request for\nuse in our [model distillation](https://developers.openai.com/api/docs/guides/supervised-fine-tuning#distilling-from-a-larger-model) or\n[evals](https://developers.openai.com/api/docs/guides/evals) products.\n\nSupports text and image inputs. Note: image inputs over 8MB will be dropped.\n" + }) + ), + "moderation": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ModerationParam).annotate({ + "description": "Configuration for running moderation on the request input and generated output.\n" + }), + Schema.Null + ]) + ), + "stream": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": + "If set to true, the model response data will be streamed to the client\nas it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).\nSee the [Streaming section below](https://developers.openai.com/api/reference/resources/chat/subresources/completions/streaming-events)\nfor more information, along with the [streaming responses](https://developers.openai.com/api/docs/guides/streaming-responses)\nguide for more information on how to handle the streaming events.\n" + }) + ), + "stop": Schema.optionalKey(StopConfiguration), + "logit_bias": Schema.optionalKey( + Schema.Union([ + Schema.Record(Schema.String, Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), + Schema.Null + ]).annotate({ + "description": + "Modify the likelihood of specified tokens appearing in the completion.\n\nAccepts a JSON object that maps tokens (specified by their token ID in the\ntokenizer) to an associated bias value from -100 to 100. Mathematically,\nthe bias is added to the logits generated by the model prior to sampling.\nThe exact effect will vary per model, but values between -1 and 1 should\ndecrease or increase likelihood of selection; values like -100 or 100\nshould result in a ban or exclusive selection of the relevant token.\n" + }) + ), + "logprobs": Schema.optionalKey( + Schema.Union([Schema.Boolean, Schema.Null]).annotate({ + "description": + "Whether to return log probabilities of the output tokens or not. If true,\nreturns the log probabilities of each output token returned in the\n`content` of `message`.\n" + }) + ), + "max_tokens": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]).annotate({ + "description": + "The maximum number of [tokens](https://platform.openai.com/tokenizer) that can be generated in the\nchat completion. This value can be used to control\n[costs](https://openai.com/api/pricing/) for text generated via API.\n\nThis value is now deprecated in favor of `max_completion_tokens`, and is\nnot compatible with [o-series models](https://developers.openai.com/api/docs/guides/reasoning).\n" + }) + ), + "n": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(128).annotate({ "expected": "a value less than or equal to 128" })), + Schema.Null + ]).annotate({ + "description": + "How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs." + }) + ), + "prediction": Schema.optionalKey( + Schema.Union([PredictionContent, Schema.Null]).annotate({ + "description": + "Configuration for a [Predicted Output](https://developers.openai.com/api/docs/guides/predicted-outputs),\nwhich can greatly improve response times when large parts of the model\nresponse are known ahead of time. This is most common when you are\nregenerating a file with only minor changes to most of the content.\n" + }) + ), + "seed": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(-9223372036854776000).annotate({ + "expected": "a value greater than or equal to -9223372036854776000" + }) + ).check( + Schema.isLessThanOrEqualTo(9223372036854776000).annotate({ + "expected": "a value less than or equal to 9223372036854776000" + }) + ), + Schema.Null + ]).annotate({ + "description": + "This feature is in Beta.\nIf specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result.\nDeterminism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend.\n", + "format": "int64" + }) + ), + "stream_options": Schema.optionalKey(ChatCompletionStreamOptions), + "tools": Schema.optionalKey( + Schema.Array(Schema.Union([ChatCompletionTool, CustomToolChatCompletions], { mode: "oneOf" })).annotate({ + "description": + "A list of tools the model may call. You can provide either\n[custom tools](https://developers.openai.com/api/docs/guides/function-calling#custom-tools) or\n[function tools](https://developers.openai.com/api/docs/guides/function-calling).\n" + }) + ), + "tool_choice": Schema.optionalKey(ChatCompletionToolChoiceOption), + "parallel_tool_calls": Schema.optionalKey(ParallelToolCalls), + "function_call": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["none", "auto"]).annotate({ + "description": + "`none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function.\n" + }), + ChatCompletionFunctionCallOption + ], { mode: "oneOf" }).annotate({ + "description": + "Deprecated in favor of `tool_choice`.\n\nControls which (if any) function is called by the model.\n\n`none` means the model will not call a function and instead generates a\nmessage.\n\n`auto` means the model can pick between generating a message or calling a\nfunction.\n\nSpecifying a particular function via `{\"name\": \"my_function\"}` forces the\nmodel to call that function.\n\n`none` is the default when no functions are present. `auto` is the default\nif functions are present.\n" + }) + ), + "functions": Schema.optionalKey( + Schema.Array(ChatCompletionFunctions).annotate({ + "description": "Deprecated in favor of `tools`.\n\nA list of functions the model may generate JSON inputs for.\n" + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxLength(128).annotate({ "expected": "a value with a length of at most 128" }) + ) + ) +}).annotate({ "identifier": "CreateChatCompletionRequest" }) +export type EvalItem = { + readonly "role": "user" | "assistant" | "system" | "developer" + readonly "content": EvalItemContent + readonly "type"?: "message" +} +export const EvalItem = Schema.Struct({ + "role": Schema.Literals(["user", "assistant", "system", "developer"]).annotate({ + "description": "The role of the message input. One of `user`, `assistant`, `system`, or\n`developer`.\n" + }), + "content": EvalItemContent, + "type": Schema.optionalKey( + Schema.Literal("message").annotate({ "description": "The type of the message input. Always `message`.\n" }) + ) +}).annotate({ + "title": "Eval message object", + "description": + "A message input to the model with a role indicating instruction following\nhierarchy. Instructions given with the `developer` or `system` role take\nprecedence over instructions given with the `user` role. Messages with the\n`assistant` role are presumed to have been generated by the model in previous\ninteractions.\n", + "identifier": "EvalItem" +}) +export type RealtimeCallCreateRequest = { readonly "sdp": string; readonly "session"?: RealtimeSessionCreateRequestGA } +export const RealtimeCallCreateRequest = Schema.Struct({ + "sdp": Schema.String.annotate({ + "description": "WebRTC Session Description Protocol (SDP) offer generated by the caller." + }), + "session": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RealtimeSessionCreateRequestGA).annotate({ + "title": "Session configuration", + "description": + "Optional session configuration to apply before the realtime session is\ncreated. Use the same parameters you would send in a [`create client secret`](https://developers.openai.com/api/reference/resources/realtime/subresources/client_secrets/methods/create)\nrequest." + }) + ) +}).annotate({ + "title": "Realtime call creation request", + "description": + "Parameters required to initiate a realtime call and receive the SDP answer\nneeded to complete a WebRTC peer connection. Provide an SDP offer generated\nby your client and optionally configure the session that will answer the call.", + "identifier": "RealtimeCallCreateRequest" +}) +export type RealtimeCreateClientSecretRequest = { + readonly "expires_after"?: { readonly "anchor"?: "created_at"; readonly "seconds"?: number } + readonly "session"?: RealtimeSessionCreateRequestGA | RealtimeTranscriptionSessionCreateRequestGA +} +export const RealtimeCreateClientSecretRequest = Schema.Struct({ + "expires_after": Schema.optionalKey( + Schema.Struct({ + "anchor": Schema.optionalKey( + Schema.Literal("created_at").annotate({ + "description": + "The anchor point for the client secret expiration, meaning that `seconds` will be added to the `created_at` time of the client secret to produce an expiration timestamp. Only `created_at` is currently supported.\n" + }) + ), + "seconds": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "The number of seconds from the anchor point to the expiration. Select a value between `10` and `7200` (2 hours). This default to 600 seconds (10 minutes) if not specified.\n", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(10).annotate({ "expected": "a value greater than or equal to 10" }) + ).check(Schema.isLessThanOrEqualTo(7200).annotate({ "expected": "a value less than or equal to 7200" })) + ) + }).annotate({ + "title": "Client secret expiration", + "description": + "Configuration for the client secret expiration. Expiration refers to the time after which\na client secret will no longer be valid for creating sessions. The session itself may\ncontinue after that time once started. A secret can be used to create multiple sessions\nuntil it expires.\n" + }) + ), + "session": Schema.optionalKey( + Schema.Union([RealtimeSessionCreateRequestGA, RealtimeTranscriptionSessionCreateRequestGA], { mode: "oneOf" }) + .annotate({ + "title": "Session configuration", + "description": + "Session configuration to use for the client secret. Choose either a realtime\nsession or a transcription session.\n" + }) + ) +}).annotate({ + "title": "Realtime client secret creation request", + "description": + "Create a session and client secret for the Realtime API. The request can specify\neither a realtime or a transcription session configuration.\n[Learn more about the Realtime API](https://developers.openai.com/api/docs/guides/realtime).\n", + "identifier": "RealtimeCreateClientSecretRequest" +}) +export type RealtimeCreateClientSecretResponse = { + readonly "value": string + readonly "expires_at": number + readonly "session": RealtimeSessionCreateResponseGA | RealtimeTranscriptionSessionCreateResponseGA +} +export const RealtimeCreateClientSecretResponse = Schema.Struct({ + "value": Schema.String.annotate({ "description": "The generated client secret value." }), + "expires_at": Schema.Number.annotate({ + "description": "Expiration timestamp for the client secret, in seconds since epoch.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "session": Schema.Union([RealtimeSessionCreateResponseGA, RealtimeTranscriptionSessionCreateResponseGA], { + mode: "oneOf" + }).annotate({ + "title": "Session configuration", + "description": "The session configuration for either a realtime or transcription session.\n" + }) +}).annotate({ + "title": "Realtime session and client secret", + "description": "Response from creating a session and client secret for the Realtime API.\n", + "identifier": "RealtimeCreateClientSecretResponse" +}) +export type ToolSearchOutput = { + readonly "type": "tool_search_output" + readonly "id": string + readonly "call_id": string | null + readonly "execution": ToolSearchExecutionType + readonly "tools": ReadonlyArray + readonly "status": FunctionCallOutputStatusEnum + readonly "created_by"?: string +} +export const ToolSearchOutput = Schema.Struct({ + "type": Schema.Literal("tool_search_output").annotate({ + "description": "The type of the item. Always `tool_search_output`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the tool search output item." }), + "call_id": Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }), + Schema.Null + ]), + "execution": Schema.suspend((): Schema.Codec => ToolSearchExecutionType).annotate({ + "description": "Whether tool search was executed by the server or by the client." + }), + "tools": Schema.Array(Tool).annotate({ "description": "The loaded tool definitions returned by tool search." }), + "status": Schema.suspend((): Schema.Codec => FunctionCallOutputStatusEnum).annotate({ + "description": "The status of the tool search output item that was recorded." + }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ "identifier": "ToolSearchOutput" }) +export type AdditionalTools = { + readonly "type": "additional_tools" + readonly "id": string + readonly "role": MessageRole + readonly "tools": ReadonlyArray +} +export const AdditionalTools = Schema.Struct({ + "type": Schema.Literal("additional_tools").annotate({ + "description": "The type of the item. Always `additional_tools`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the additional tools item." }), + "role": Schema.suspend((): Schema.Codec => MessageRole).annotate({ + "description": "The role that provided the additional tools." + }), + "tools": Schema.Array(Tool).annotate({ + "description": "The additional tool definitions made available at this item." + }) +}).annotate({ "identifier": "AdditionalTools" }) +export type ToolsArray = ReadonlyArray +export const ToolsArray = Schema.Array(Tool).annotate({ + "description": + "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](https://developers.openai.com/api/docs/guides/tools-web-search)\n or [file search](https://developers.openai.com/api/docs/guides/tools-file-search). Learn more about\n [built-in tools](https://developers.openai.com/api/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](https://developers.openai.com/api/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](https://developers.openai.com/api/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n", + "identifier": "ToolsArray" +}) +export type InputItem = + | EasyInputMessage + | { + readonly "type"?: "message" + readonly "role": "user" | "system" | "developer" + readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "content": InputMessageContentList + } + | { + readonly "id": string + readonly "type": "message" + readonly "role": "assistant" + readonly "content": ReadonlyArray + readonly "phase"?: MessagePhase | null + readonly "status": "in_progress" | "completed" | "incomplete" + } + | { + readonly "id": string + readonly "type": "file_search_call" + readonly "status": "in_progress" | "searching" | "completed" | "incomplete" | "failed" + readonly "queries": ReadonlyArray + readonly "results"?: + | ReadonlyArray< + { + readonly "file_id"?: string + readonly "text"?: string + readonly "filename"?: string + readonly "attributes"?: VectorStoreFileAttributes + readonly "score"?: number + } + > + | null + } + | { + readonly "type": "computer_call" + readonly "id": string + readonly "call_id": string + readonly "action"?: ComputerAction + readonly "actions"?: ComputerActionList + readonly "pending_safety_checks": ReadonlyArray + readonly "status": "in_progress" | "completed" | "incomplete" + } + | { + readonly "id"?: string | null + readonly "call_id": string + readonly "type": "computer_call_output" + readonly "output": ComputerScreenshotImage + readonly "acknowledged_safety_checks"?: ReadonlyArray | null + readonly "status"?: FunctionCallItemStatus | null + } + | { + readonly "id": string + readonly "type": "web_search_call" + readonly "status": WebSearchCallStatus + readonly "action"?: WebSearchActionSearch | WebSearchActionOpenPage | WebSearchActionFind + } + | { + readonly "id"?: string + readonly "type": "function_call" + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "arguments": string + readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "async"?: boolean + } + | { + readonly "id"?: string | null + readonly "call_id"?: string | null + readonly "type": "function_call_output" + readonly "output": + | string + | ReadonlyArray + readonly "name"?: string | null + readonly "namespace"?: string | null + readonly "caller"?: ToolCallCallerParam | null + readonly "status"?: FunctionCallItemStatus | null + } + | { + readonly "id"?: string | null + readonly "call_id"?: string | null + readonly "type": "tool_search_call" + readonly "execution"?: ToolSearchExecutionType + readonly "arguments": EmptyModelParam + readonly "status"?: FunctionCallItemStatus | null + } + | { + readonly "id"?: string | null + readonly "call_id"?: string | null + readonly "type": "tool_search_output" + readonly "execution"?: ToolSearchExecutionType + readonly "tools": ReadonlyArray + readonly "status"?: FunctionCallItemStatus | null + } + | { + readonly "id"?: string | null + readonly "type": "additional_tools" + readonly "role": "developer" + readonly "tools": ReadonlyArray + } + | { + readonly "id"?: string | null + readonly "type": "configuration_update" + readonly "reasoning"?: { readonly "effort"?: ReasoningEffort } + } + | { + readonly "type": "reasoning" + readonly "id": string + readonly "encrypted_content"?: string | null + readonly "summary": ReadonlyArray + readonly "content"?: ReadonlyArray + readonly "status"?: "in_progress" | "completed" | "incomplete" + } + | { readonly "id"?: string | null; readonly "type": "compaction"; readonly "encrypted_content": string } + | { + readonly "type": "image_generation_call" + readonly "id": string + readonly "status": "in_progress" | "completed" | "generating" | "failed" + readonly "result": string | null + readonly "size"?: string | "1024x1024" | "1024x1536" | "1536x1024" | null + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" | null + readonly "action"?: ImageGenActionEnum | null + readonly "background"?: ImageBackground | null + readonly "output_format"?: ImageOutputFormat | null + readonly "revised_prompt"?: string | null + } + | { + readonly "type": "code_interpreter_call" + readonly "id": string + readonly "status": "in_progress" | "completed" | "incomplete" | "interpreting" | "failed" + readonly "container_id": string + readonly "code": string | null + readonly "outputs": ReadonlyArray | null + } + | { + readonly "type": "local_shell_call" + readonly "id": string + readonly "call_id": string + readonly "action": LocalShellExecAction + readonly "status": "in_progress" | "completed" | "incomplete" + } + | { + readonly "type": "local_shell_call_output" + readonly "id": string + readonly "output": string readonly "status"?: "in_progress" | "completed" | "incomplete" | null + readonly "call_id": Schema.Json + } + | { + readonly "id"?: string | null + readonly "call_id": string + readonly "caller"?: ToolCallCallerParam | null + readonly "type": "shell_call" + readonly "action": FunctionShellActionParam + readonly "status"?: FunctionShellCallItemStatus | null + readonly "environment"?: LocalEnvironmentParam | ContainerReferenceParam | null + } + | { + readonly "id"?: string | null + readonly "call_id": string + readonly "caller"?: ToolCallCallerParam | null + readonly "type": "shell_call_output" + readonly "output": ReadonlyArray + readonly "status"?: FunctionShellCallItemStatus | null + readonly "max_output_length"?: number | null + } + | { + readonly "type": "apply_patch_call" + readonly "id"?: string | null + readonly "call_id": string + readonly "caller"?: ToolCallCallerParam | null + readonly "status": ApplyPatchCallStatusParam + readonly "operation": ApplyPatchOperationParam + } + | { + readonly "type": "apply_patch_call_output" + readonly "id"?: string | null + readonly "call_id": string + readonly "caller"?: ToolCallCallerParam | null + readonly "status": ApplyPatchCallOutputStatusParam + readonly "output"?: string | null + } + | { + readonly "type": "mcp_list_tools" + readonly "id": string + readonly "server_label": string + readonly "tools": ReadonlyArray + readonly "error"?: string | null + } + | { + readonly "type": "mcp_approval_request" + readonly "id": string + readonly "server_label": string + readonly "name": string + readonly "arguments": string + } + | { + readonly "type": "mcp_approval_response" + readonly "id"?: string | null + readonly "approval_request_id": string + readonly "approve": boolean + readonly "reason"?: string | null + readonly "request_id": Schema.Json + } + | { + readonly "type": "mcp_call" + readonly "id": string + readonly "server_label": string + readonly "name": string + readonly "arguments": string + readonly "output"?: string | null + readonly "error"?: MCPToolCallError | null + readonly "status"?: MCPToolCallStatus + readonly "approval_request_id"?: string | null + } + | { + readonly "type": "custom_tool_call_output" + readonly "id"?: string + readonly "call_id": string + readonly "caller"?: ToolCallCallerParam | null + readonly "output": string | ReadonlyArray + } + | { + readonly "type": "custom_tool_call" + readonly "id"?: string + readonly "call_id": string + readonly "caller"?: ToolCallCaller | null + readonly "namespace"?: string + readonly "name": string + readonly "input": string + readonly "async"?: boolean + } + | CompactionTriggerItemParam + | ItemReferenceParam + | ProgramItemParam + | ProgramOutputItemParam +export const InputItem = Schema.Union([ + EasyInputMessage, + Schema.Union([ + Schema.Struct({ + "type": Schema.optionalKey( + Schema.Literal("message").annotate({ + "description": "The type of the message input. Always set to `message`.\n" + }) + ), + "role": Schema.Literals(["user", "system", "developer"]).annotate({ + "description": "The role of the message input. One of `user`, `system`, or `developer`.\n" + }), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ), + "content": InputMessageContentList + }).annotate({ + "title": "Input message", + "description": + "A message input to the model with a role indicating instruction following\nhierarchy. Instructions given with the `developer` or `system` role take\nprecedence over instructions given with the `user` role.\n" + }), + Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the output message.\n" }), + "type": Schema.Literal("message").annotate({ + "description": "The type of the output message. Always `message`.\n" + }), + "role": Schema.Literal("assistant").annotate({ + "description": "The role of the output message. Always `assistant`.\n" + }), + "content": Schema.Array(OutputMessageContent).annotate({ "description": "The content of the output message.\n" }), + "phase": Schema.optionalKey(Schema.Union([MessagePhase, Schema.Null])), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" + }) + }).annotate({ "title": "Output message", "description": "An output message from the model.\n" }), + Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the file search tool call.\n" }), + "type": Schema.Literal("file_search_call").annotate({ + "description": "The type of the file search tool call. Always `file_search_call`.\n" + }), + "status": Schema.Literals(["in_progress", "searching", "completed", "incomplete", "failed"]).annotate({ + "description": + "The status of the file search tool call. One of `in_progress`,\n`searching`, `incomplete` or `failed`,\n" + }), + "queries": Schema.Array(Schema.String).annotate({ "description": "The queries used to search for files.\n" }), + "results": Schema.optionalKey(Schema.Union([ + Schema.Array(Schema.Struct({ + "file_id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the file.\n" })), + "text": Schema.optionalKey( + Schema.String.annotate({ "description": "The text that was retrieved from the file.\n" }) + ), + "filename": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the file.\n" })), + "attributes": Schema.optionalKey(VectorStoreFileAttributes), + "score": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The relevance score of the file - a value between 0 and 1.\n", + "format": "float" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ) + })).annotate({ "description": "The results of the file search tool call.\n" }), + Schema.Null + ])) + }).annotate({ + "title": "File search tool call", + "description": + "The results of a file search tool call. See the\n[file search guide](https://developers.openai.com/api/docs/guides/tools-file-search) for more information.\n" + }), + Schema.Struct({ + "type": Schema.Literal("computer_call").annotate({ + "description": "The type of the computer call. Always `computer_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the computer call." }), + "call_id": Schema.String.annotate({ + "description": "An identifier used when responding to the tool call with output.\n" + }), + "action": Schema.optionalKey(ComputerAction), + "actions": Schema.optionalKey(ComputerActionList), + "pending_safety_checks": Schema.Array(ComputerCallSafetyCheckParam).annotate({ + "description": "The pending safety checks for the computer call.\n" + }), + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + }).annotate({ + "title": "Computer tool call", + "description": + "A tool call to a computer use tool. See the\n[computer use guide](https://developers.openai.com/api/docs/guides/tools-computer-use) for more information.\n" + }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The ID of the computer tool call output." }), + Schema.Null + ]) + ), + "call_id": Schema.String.annotate({ "description": "The ID of the computer tool call that produced the output." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + "type": Schema.Literal("computer_call_output").annotate({ + "description": "The type of the computer tool call output. Always `computer_call_output`." + }), + "output": ComputerScreenshotImage, + "acknowledged_safety_checks": Schema.optionalKey( + Schema.Union([ + Schema.Array(ComputerCallSafetyCheckParam).annotate({ + "description": "The safety checks reported by the API that have been acknowledged by the developer." + }), + Schema.Null + ]) + ), + "status": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => FunctionCallItemStatus).annotate({ + "description": + "The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API." + }), + Schema.Null + ]) + ) + }).annotate({ "title": "Computer tool call output", "description": "The output of a computer tool call." }), + Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique ID of the web search tool call.\n" }), + "type": Schema.Literal("web_search_call").annotate({ + "description": "The type of the web search tool call. Always `web_search_call`.\n" + }), + "status": Schema.suspend((): Schema.Codec => WebSearchCallStatus).annotate({ + "description": "The status of the web search tool call.\n" + }), + "action": Schema.optionalKey( + Schema.Union([WebSearchActionSearch, WebSearchActionOpenPage, WebSearchActionFind], { mode: "oneOf" }).annotate( + { + "description": + "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" + } + ) + ) + }).annotate({ + "title": "Web search tool call", + "description": + "The results of a web search tool call. See the\n[web search guide](https://developers.openai.com/api/docs/guides/tools-web-search) for more information.\n" + }), + Schema.Struct({ + "id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the function tool call.\n" })), + "type": Schema.Literal("function_call").annotate({ + "description": "The type of the function tool call. Always `function_call`.\n" + }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the function tool call generated by the model.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the function to run.\n" }) + ), + "name": Schema.String.annotate({ "description": "The name of the function to run.\n" }), + "arguments": Schema.String.annotate({ + "description": "A JSON string of the arguments to pass to the function.\n" + }), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the function tool call runs asynchronously.\n" }) + ) + }).annotate({ + "title": "Function tool call", + "description": + "A tool call to run a function. See the\n[function calling guide](https://developers.openai.com/api/docs/guides/function-calling) for more information.\n" + }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The unique ID of the function tool call output. Populated when this item is returned via API." + }), + Schema.Null + ]) + ), + "call_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the function tool call generated by the model." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + Schema.Null + ]) + ), + "type": Schema.Literal("function_call_output").annotate({ + "description": "The type of the function tool call output. Always `function_call_output`." + }), + "output": Schema.Union([ + Schema.String.annotate({ "description": "A JSON string of the output of the function tool call." }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.Array( + Schema.Union([InputTextContentParam, InputImageContentParamAutoParam, InputFileContentParam], { + mode: "oneOf" + }).annotate({ "description": "A piece of message content, such as text, an image, or a file." }) + ).annotate({ "description": "An array of content outputs (text, image, file) for the function tool call." }) + ], { mode: "oneOf" }).annotate({ "description": "Text, image, or file output of the function tool call." }), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The name of the tool that produced the output." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ]) + ), + "namespace": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The namespace of the tool that produced the output." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })).check( + Schema.isPattern(new RegExp("^[a-zA-Z0-9_-]+$", "u")).annotate({ + "expected": "a string matching the RegExp ^[a-zA-Z0-9_-]+$" + }) + ), + Schema.Null + ]) + ), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => FunctionCallItemStatus).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API." + }), + Schema.Null + ]) + ) + }).annotate({ "title": "Function tool call output", "description": "The output of a function tool call." }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of this tool search call." }), + Schema.Null + ]) + ), + "call_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + Schema.Null + ]) + ), + "type": Schema.Literal("tool_search_call").annotate({ + "description": "The item type. Always `tool_search_call`." + }), + "execution": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ToolSearchExecutionType).annotate({ + "description": "Whether tool search was executed by the server or by the client." + }) + ), + "arguments": Schema.suspend((): Schema.Codec => EmptyModelParam).annotate({ + "description": "The arguments supplied to the tool search call." + }), + "status": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => FunctionCallItemStatus).annotate({ + "description": "The status of the tool search call." + }), + Schema.Null + ]) + ) + }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of this tool search output." }), + Schema.Null + ]) + ), + "call_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + Schema.Null + ]) + ), + "type": Schema.Literal("tool_search_output").annotate({ + "description": "The item type. Always `tool_search_output`." + }), + "execution": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ToolSearchExecutionType).annotate({ + "description": "Whether tool search was executed by the server or by the client." + }) + ), + "tools": Schema.Array(ToolSearchOutputTool).annotate({ + "description": "The loaded tool definitions returned by the tool search output." + }), + "status": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => FunctionCallItemStatus).annotate({ + "description": "The status of the tool search output." + }), + Schema.Null + ]) + ) + }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of this additional tools item." }), + Schema.Null + ]) + ), + "type": Schema.Literal("additional_tools").annotate({ + "description": "The item type. Always `additional_tools`." + }), + "role": Schema.Literal("developer").annotate({ + "description": "The role that provided the additional tools. Only `developer` is supported." + }), + "tools": Schema.Array(Tool).annotate({ "description": "A list of additional tools made available at this item." }) + }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the configuration update item." }), + Schema.Null + ]) + ), + "type": Schema.Literal("configuration_update").annotate({ + "description": "The item type. Always `configuration_update`." + }), + "reasoning": Schema.optionalKey( + Schema.Struct({ + "effort": Schema.optionalKey( + Schema.suspend((): Schema.Codec => ReasoningEffort).annotate({ + "description": + "The reasoning effort to use for subsequent responses until another\nconfiguration update replaces it.\n" + }) + ) + }).annotate({ "description": "Updates to reasoning configuration. Only effort is supported." }) + ) + }).annotate({ + "description": + "An update to the conversation's response configuration. The configuration\nremains in effect for subsequent responses until it is replaced by another\nconfiguration update.\n" + }), + Schema.Struct({ + "type": Schema.Literal("reasoning").annotate({ "description": "The type of the object. Always `reasoning`.\n" }), + "id": Schema.String.annotate({ "description": "The unique identifier of the reasoning content.\n" }), + "encrypted_content": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "The encrypted content of the reasoning item. This is populated by default\nfor reasoning items returned by `POST /v1/responses` and WebSocket\n`response.create` requests.\n\nWhen streaming, use the completed reasoning item and its\n`encrypted_content` from the `response.output_item.done` event in\nsubsequent requests. The `encrypted_content` in\n`response.output_item.added` may be incomplete. This is especially\nimportant when `store` is `false` or when using Zero Data Retention.\n" + }), + Schema.Null + ])), + "summary": Schema.Array(SummaryTextContent).annotate({ "description": "Reasoning summary content.\n" }), + "content": Schema.optionalKey( + Schema.Array(ReasoningTextContent).annotate({ "description": "Reasoning text content.\n" }) + ), + "status": Schema.optionalKey( + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": + "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" + }) + ) + }).annotate({ + "title": "Reasoning", + "description": + "A description of the chain of thought used by a reasoning model while generating\na response. Be sure to include these items in your `input` to the Responses API\nfor subsequent turns of a conversation if you are manually\n[managing context](https://developers.openai.com/api/docs/guides/conversation-state).\n" + }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The ID of the compaction item." }), Schema.Null]) + ), + "type": Schema.Literal("compaction").annotate({ "description": "The type of the item. Always `compaction`." }), + "encrypted_content": Schema.String.annotate({ "description": "The encrypted content of the compaction summary." }) + .check( + Schema.isMaxCodePoints(104857600).annotate({ "expected": "a string with at most 104857600 code points" }) + ) + }).annotate({ + "title": "Compaction item", + "description": + "A compaction item generated by the [`v1/responses/compact` API](https://developers.openai.com/api/reference/resources/responses/methods/compact)." + }), + Schema.Struct({ + "type": Schema.Literal("image_generation_call").annotate({ + "description": "The type of the image generation call. Always `image_generation_call`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the image generation call." }), + "status": Schema.Literals(["in_progress", "completed", "generating", "failed"]).annotate({ + "description": "The status of the image generation call." + }), + "result": Schema.Union([ + Schema.String.annotate({ "description": "The generated image encoded in base64." }), + Schema.Null + ]), + "size": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." + }), + Schema.Null + ]) + ), + "quality": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": + "The quality of the image generated by the image generation tool call. One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`." + }), + Schema.Null + ]) + ), + "action": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ImageGenActionEnum).annotate({ + "description": "The action used for image generation." + }), + Schema.Null + ]) + ), + "background": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ImageBackground).annotate({ + "description": "The background setting used for generation." + }), + Schema.Null + ]) + ), + "output_format": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ImageOutputFormat).annotate({ + "description": "The output format used for generation." + }), + Schema.Null + ]) + ), + "revised_prompt": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The prompt that was used after any model prompt rewriting." }), + Schema.Null + ]) + ) + }).annotate({ "title": "Image generation call", "description": "An image generation request made by the model." }), + Schema.Struct({ + "type": Schema.Literal("code_interpreter_call").annotate({ + "description": "The type of the code interpreter tool call. Always `code_interpreter_call`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the code interpreter tool call.\n" }), + "status": Schema.Literals(["in_progress", "completed", "incomplete", "interpreting", "failed"]).annotate({ + "description": + "The status of the code interpreter tool call. Valid values are `in_progress`, `completed`, `incomplete`, `interpreting`, and `failed`.\n" + }), + "container_id": Schema.String.annotate({ "description": "The ID of the container used to run the code.\n" }), + "code": Schema.Union([ + Schema.String.annotate({ "description": "The code to run, or null if not available.\n" }), + Schema.Null + ]), + "outputs": Schema.Union([ + Schema.Array(Schema.Union([CodeInterpreterOutputLogs, CodeInterpreterOutputImage], { mode: "oneOf" })).annotate( + { + "description": + "The outputs generated by the code interpreter, such as logs or images.\nCan be null if no outputs are available.\n" + } + ), + Schema.Null + ]) + }).annotate({ "title": "Code interpreter tool call", "description": "A tool call to run code.\n" }), + Schema.Struct({ + "type": Schema.Literal("local_shell_call").annotate({ + "description": "The type of the local shell call. Always `local_shell_call`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the local shell call.\n" }), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the local shell tool call generated by the model.\n" + }), + "action": LocalShellExecAction, + "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": "The status of the local shell call.\n" + }) + }).annotate({ "title": "Local shell call", "description": "A tool call to run a command on the local shell.\n" }), + Schema.Struct({ + "type": Schema.Literal("local_shell_call_output").annotate({ + "description": "The type of the local shell tool call output. Always `local_shell_call_output`.\n" + }), + "id": Schema.String.annotate({ + "description": "The unique ID of the local shell tool call generated by the model.\n" + }), + "output": Schema.String.annotate({ + "description": "A JSON string of the output of the local shell tool call.\n" + }), + "status": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + "description": "The status of the item. One of `in_progress`, `completed`, or `incomplete`.\n" + }), + Schema.Null + ]) + ), + "call_id": Schema.Json.annotate({ "expected": "JSON value" }) + }).annotate({ "title": "Local shell call output", "description": "The output of a local shell tool call.\n" }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "The unique ID of the shell tool call. Populated when this item is returned via API." + }), + Schema.Null + ]) + ), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the shell tool call generated by the model." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "type": Schema.Literal("shell_call").annotate({ "description": "The type of the item. Always `shell_call`." }), + "action": Schema.suspend((): Schema.Codec => FunctionShellActionParam).annotate({ + "description": "The shell commands and limits that describe how to run the tool call." + }), + "status": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => FunctionShellCallItemStatus).annotate({ + "description": "The status of the shell call. One of `in_progress`, `completed`, or `incomplete`." + }), + Schema.Null + ]) + ), + "environment": Schema.optionalKey( + Schema.Union([ + Schema.Union([LocalEnvironmentParam, ContainerReferenceParam], { mode: "oneOf" }).annotate({ + "description": "The environment to execute the shell commands in." + }), + Schema.Null + ]) + ) + }).annotate({ + "title": "Shell tool call", + "description": "A tool representing a request to execute one or more shell commands." + }), + Schema.Struct({ + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "The unique ID of the shell tool call output. Populated when this item is returned via API." + }), + Schema.Null + ]) + ), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the shell tool call generated by the model." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "type": Schema.Literal("shell_call_output").annotate({ + "description": "The type of the item. Always `shell_call_output`." + }), + "output": Schema.Array(FunctionShellCallOutputContentParam).annotate({ + "description": "Captured chunks of stdout and stderr output, along with their associated outcomes." + }), + "status": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => FunctionShellCallItemStatus).annotate({ + "description": "The status of the shell call output." + }), + Schema.Null + ]) + ), + "max_output_length": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The maximum number of UTF-8 characters captured for this shell call's combined output." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ) + }).annotate({ + "title": "Shell tool call output", + "description": "The streamed output items emitted by a shell tool call." + }), + Schema.Struct({ + "type": Schema.Literal("apply_patch_call").annotate({ + "description": "The type of the item. Always `apply_patch_call`." + }), + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call. Populated when this item is returned via API." + }), + Schema.Null + ]) + ), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call generated by the model." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.suspend((): Schema.Codec => ApplyPatchCallStatusParam).annotate({ + "description": "The status of the apply patch tool call. One of `in_progress` or `completed`." + }), + "operation": Schema.suspend((): Schema.Codec => ApplyPatchOperationParam).annotate({ + "description": "The specific create, delete, or update instruction for the apply_patch tool call." + }) + }).annotate({ + "title": "Apply patch tool call", + "description": "A tool call representing a request to create, delete, or update files using diff patches." + }), + Schema.Struct({ + "type": Schema.Literal("apply_patch_call_output").annotate({ + "description": "The type of the item. Always `apply_patch_call_output`." + }), + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The unique ID of the apply patch tool call output. Populated when this item is returned via API." + }), + Schema.Null + ]) + ), + "call_id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call generated by the model." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), + "status": Schema.suspend((): Schema.Codec => ApplyPatchCallOutputStatusParam) + .annotate({ "description": "The status of the apply patch tool call output. One of `completed` or `failed`." }), + "output": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": "Optional human-readable log text from the apply patch tool (e.g., patch results or errors)." + }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.Null + ]) + ) + }).annotate({ + "title": "Apply patch tool call output", + "description": "The streamed output emitted by an apply patch tool call." + }), + Schema.Struct({ + "type": Schema.Literal("mcp_list_tools").annotate({ + "description": "The type of the item. Always `mcp_list_tools`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the list.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server.\n" }), + "tools": Schema.Array(MCPListToolsTool).annotate({ "description": "The tools available on the server.\n" }), + "error": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Error message if the server could not list tools.\n" }), + Schema.Null + ]) + ) + }).annotate({ "title": "MCP list tools", "description": "A list of tools available on an MCP server.\n" }), + Schema.Struct({ + "type": Schema.Literal("mcp_approval_request").annotate({ + "description": "The type of the item. Always `mcp_approval_request`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the approval request.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server making the request.\n" }), + "name": Schema.String.annotate({ "description": "The name of the tool to run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of arguments for the tool.\n" }) + }).annotate({ + "title": "MCP approval request", + "description": "A request for human approval of a tool invocation.\n" + }), + Schema.Struct({ + "type": Schema.Literal("mcp_approval_response").annotate({ + "description": "The type of the item. Always `mcp_approval_response`.\n" + }), + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the approval response\n" }), + Schema.Null + ]) + ), + "approval_request_id": Schema.String.annotate({ + "description": "The ID of the approval request being answered.\n" + }), + "approve": Schema.Boolean.annotate({ "description": "Whether the request was approved.\n" }), + "reason": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Optional reason for the decision.\n" }), Schema.Null]) + ), + "request_id": Schema.Json.annotate({ "expected": "JSON value" }) + }).annotate({ "title": "MCP approval response", "description": "A response to an MCP approval request.\n" }), + Schema.Struct({ + "type": Schema.Literal("mcp_call").annotate({ "description": "The type of the item. Always `mcp_call`.\n" }), + "id": Schema.String.annotate({ "description": "The unique ID of the tool call.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server running the tool.\n" }), + "name": Schema.String.annotate({ "description": "The name of the tool that was run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments passed to the tool.\n" }), + "output": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The output from the tool call.\n" }), Schema.Null]) + ), + "error": Schema.optionalKey( + Schema.Union([MCPToolCallError, Schema.Null]).annotate({ + "description": "The error from the tool call, if any." + }) + ), + "status": Schema.optionalKey( + Schema.suspend((): Schema.Codec => MCPToolCallStatus).annotate({ + "description": + "The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`.\n" + }) + ), + "approval_request_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "Unique identifier for the MCP tool call approval request.\nInclude this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call.\n" + }), + Schema.Null + ]) + ) + }).annotate({ "title": "MCP tool call", "description": "An invocation of a tool on an MCP server.\n" }), + Schema.Struct({ + "type": Schema.Literal("custom_tool_call_output").annotate({ + "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" + }), + "id": Schema.optionalKey( + Schema.String.annotate({ + "description": "The unique ID of the custom tool call output in the OpenAI platform.\n" + }) + ), + "call_id": Schema.String.annotate({ + "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ + Schema.String.annotate({ + "title": "string output", + "description": "A string of the output of the custom tool call.\n" + }), + Schema.Array(FunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the custom tool call.\n" + }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" + }) + }).annotate({ + "title": "Custom tool call output", + "description": "The output of a custom tool call from your code, being sent back to the model.\n" + }), + Schema.Struct({ + "type": Schema.Literal("custom_tool_call").annotate({ + "description": "The type of the custom tool call. Always `custom_tool_call`.\n" + }), + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the custom tool call in the OpenAI platform.\n" }) + ), + "call_id": Schema.String.annotate({ + "description": "An identifier used to map this custom tool call to a tool call output.\n" + }), + "caller": Schema.optionalKey(Schema.Union([ToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) + ), + "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), + "input": Schema.String.annotate({ + "description": "The input for the custom tool call generated by the model.\n" + }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the custom tool call runs asynchronously.\n" }) + ) + }).annotate({ "title": "Custom tool call", "description": "A call to a custom tool created by the model.\n" }) + ], { mode: "oneOf" }).annotate({ + "description": + "An item representing part of the context for the response to be\ngenerated by the model. Can contain text, images, and audio inputs,\nas well as previous assistant responses and tool call outputs.\n", + "title": "Item" + }), + CompactionTriggerItemParam, + ItemReferenceParam, + ProgramItemParam, + ProgramOutputItemParam +], { mode: "oneOf" }).annotate({ "identifier": "InputItem" }) +export type LiveResponsesDelegationParam = { + readonly "type": "responses" + readonly "responses": LiveResponsesDelegationSettingsInputParam +} +export const LiveResponsesDelegationParam = Schema.Struct({ + "type": Schema.Literal("responses").annotate({ + "description": "The delegation owner. Always `responses` for tasks handled by the Responses API." + }), + "responses": Schema.suspend((): Schema.Codec => + LiveResponsesDelegationSettingsInputParam + ).annotate({ + "description": "Backend model, prompt, and tools used when the Live session delegates a task to Responses." + }) +}).annotate({ + "description": "Delegate tasks to a Responses model managed by the Live session.", + "identifier": "LiveResponsesDelegationParam" +}) +export type LiveResponsesDelegationUpdateParam = { + readonly "type": "responses" + readonly "responses"?: LiveResponsesDelegationSettingsUpdateInputParam +} +export const LiveResponsesDelegationUpdateParam = Schema.Struct({ + "type": Schema.Literal("responses").annotate({ + "description": "The delegation owner. Always `responses` for tasks handled by the Responses API." + }), + "responses": Schema.optionalKey( + Schema.suspend((): Schema.Codec => + LiveResponsesDelegationSettingsUpdateInputParam + ).annotate({ "description": "Responses backend settings to update. Omitted settings keep their existing values." }) + ) +}).annotate({ + "description": "Update the Responses backend for an existing Live session without changing delegation ownership.", + "identifier": "LiveResponsesDelegationUpdateParam" +}) +export type ThreadItemListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const ThreadItemListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), + "data": Schema.Array(ThreadItem).annotate({ "description": "A list of items" }), + "first_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the first item in the list." }), + Schema.Null + ]), + "last_id": Schema.Union([ + Schema.String.annotate({ "description": "The ID of the last item in the list." }), + Schema.Null + ]), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }) +}).annotate({ + "title": "Thread Items", + "description": "A paginated list of thread items rendered for the ChatKit API.", + "identifier": "ThreadItemListResource" +}) +export type DecisionInput = string | ReadonlyArray +export const DecisionInput = Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.Array(Schema.Union([DecisionInputMessage], { mode: "oneOf" })).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(131072).annotate({ "expected": "a value with a length of at most 131072" })) +], { mode: "oneOf" }).annotate({ + "description": + "The text or images to evaluate for every question. Provide a text string or user messages containing text and images. Images can be base64 data URLs or publicly accessible HTTP(S) URLs; at most 128 images are allowed across all messages in one request. Files, audio, tools, and item references are not supported.", + "identifier": "DecisionInput" +}) +export type CreateEnvironmentParam = CreateEnvironmentParamOpenaiHosted +export const CreateEnvironmentParam = Schema.Union([CreateEnvironmentParamOpenaiHosted], { mode: "oneOf" }).annotate({ + "description": "Configuration for a new prewarmed OpenAI-hosted environment.", + "identifier": "CreateEnvironmentParam" +}) +export type EnvironmentParam = EnvironmentParamNone | EnvironmentParamOpenaiHosted | EnvironmentParamSelfHosted +export const EnvironmentParam = Schema.Union([ + EnvironmentParamNone, + EnvironmentParamOpenaiHosted, + EnvironmentParamSelfHosted +], { mode: "oneOf" }).annotate({ + "description": "The execution environment and optional reusable template for a session.", + "identifier": "EnvironmentParam" +}) +export type SessionItemListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const SessionItemListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(SessionTurnItemResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of messages, reasoning, and tool calls from a session's item history.", + "identifier": "SessionItemListResource" +}) +export type SessionEventAgentSessionTurnItemAdded = { + readonly "type": "agent.session.turn.item.added" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "output_index": number | null + readonly "item": SessionTurnItemResource +} +export const SessionEventAgentSessionTurnItemAdded = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.item.added").annotate({ + "description": "The type of the object. Always `agent.session.turn.item.added`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "output_index": Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check( + Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" }) + ), + Schema.Null + ]).annotate({ + "description": "The index of the item in the turn output, when the item is agent output.", + "format": "int64" + }), + "item": Schema.suspend((): Schema.Codec => SessionTurnItemResource).annotate({ + "description": "The item that was added." + }) +}).annotate({ + "description": "Emitted when an item is added to a turn.", + "identifier": "SessionEventAgentSessionTurnItemAdded" +}) +export type SessionEventAgentSessionTurnItemDone = { + readonly "type": "agent.session.turn.item.done" + readonly "event_id": string + readonly "session_id": string + readonly "turn_id": string | null + readonly "output_index": number + readonly "item": AgentOutputItemResource +} +export const SessionEventAgentSessionTurnItemDone = Schema.Struct({ + "type": Schema.Literal("agent.session.turn.item.done").annotate({ + "description": "The type of the object. Always `agent.session.turn.item.done`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session_id": Schema.String.annotate({ "description": "The ID of the session associated with the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "turn_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the turn associated with the event, when applicable." }), + "output_index": Schema.Number.annotate({ + "description": "The index of the output item in the turn output.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(4294967295).annotate({ "expected": "a value less than or equal to 4294967295" })), + "item": Schema.suspend((): Schema.Codec => AgentOutputItemResource).annotate({ + "description": "The completed output item." + }) +}).annotate({ + "description": "Emitted when an output item is complete.", + "identifier": "SessionEventAgentSessionTurnItemDone" +}) +export type AgentListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const AgentListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(AgentResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "AgentListResource" +}) +export type SessionResource = { + readonly "spend_control"?: SessionSpendControlResource + readonly "metadata": { readonly [x: string]: string } + readonly "id": string + readonly "object": "agent.session" + readonly "created_at": number + readonly "last_active_at": number + readonly "status": SessionStatusResource + readonly "required_actions": ReadonlyArray + readonly "error": string | null + readonly "agent": SessionAgentResource + readonly "environment": EnvironmentResource + readonly "vault_ids": ReadonlyArray + readonly "usage": TokenUsageResource | null +} +export const SessionResource = Schema.Struct({ + "spend_control": Schema.optionalKey( + Schema.suspend((): Schema.Codec => SessionSpendControlResource).annotate({ + "description": + "Configured spending limit and best-effort consumption, in USD cents. Unlimited sessions omit this object." + }) + ), + "metadata": Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Custom string key-value pairs attached to the session." }).check( + Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + "id": Schema.String.annotate({ "description": "The ID of the session." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("agent.session").annotate({ "description": "The object type. Always `agent.session`." }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the session was created.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "last_active_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the session was last active.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "status": Schema.suspend((): Schema.Codec => SessionStatusResource).annotate({ + "description": "The current status of the session." + }), + "required_actions": Schema.Array(SessionRequiredActionResource).annotate({ + "description": "Actions that must be completed before the session can continue." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "error": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The error that caused the session to fail, if any." }), + "agent": Schema.suspend((): Schema.Codec => SessionAgentResource).annotate({ + "description": "The agent running in the session." + }), + "environment": Schema.suspend((): Schema.Codec => EnvironmentResource).annotate({ + "description": "The execution environment for the session." + }), + "vault_ids": Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "The IDs of vaults made available to the session." }).check( + Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" }) + ).check(Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" })), + "usage": Schema.Union([TokenUsageResource, Schema.Null]).annotate({ + "description": "Best-effort token usage for the session, or null if unknown. Recorded usage may change." + }) +}).annotate({ "description": "A Managed Agents session.", "identifier": "SessionResource" }) +export type CreateSessionEventsParams = { readonly "events": ReadonlyArray } +export const CreateSessionEventsParams = Schema.Struct({ + "events": Schema.Array(SessionInputParam).annotate({ "description": "The input events to submit to the session." }) + .check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ) +}).annotate({ + "description": "Input events submitted to an existing session.", + "identifier": "CreateSessionEventsParams" +}) +export type VaultCredentialResource = { + readonly "id": string + readonly "object": "vault.credential" + readonly "vault_id": string + readonly "name": string + readonly "auth": VaultCredentialAuthResource + readonly "metadata": { readonly [x: string]: string } + readonly "created_at": number + readonly "updated_at": number +} +export const VaultCredentialResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The ID of the credential." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "object": Schema.Literal("vault.credential").annotate({ + "description": "The object type. Always `vault.credential`." + }), + "vault_id": Schema.String.annotate({ "description": "The ID of the vault containing this credential." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "name": Schema.String.annotate({ "description": "The human-readable name of the credential." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "auth": Schema.suspend((): Schema.Codec => VaultCredentialAuthResource).annotate({ + "description": "The authentication method and non-secret configuration of the credential." + }), + "metadata": Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "description": "Application-defined key-value pairs associated with this credential." }).check( + Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the credential was created.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "updated_at": Schema.Number.annotate({ + "description": "The Unix timestamp, in seconds, when the credential was last updated.", + "format": "int64" + }).check(Schema.isInt().annotate({ "expected": "an integer" })) +}).annotate({ + "description": "Metadata for a stored credential. Secret values are never returned.", + "identifier": "VaultCredentialResource" +}) +export type CreateVaultCredentialParams = { + readonly "name": string + readonly "auth": CreateVaultCredentialAuthParam + readonly "metadata"?: { readonly [x: string]: string } +} +export const CreateVaultCredentialParams = Schema.Struct({ + "name": Schema.String.annotate({ + "description": "The name is trimmed before storage. It must contain 1 to 256 UTF-8 bytes after trimming." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" }) + ), + "auth": Schema.suspend((): Schema.Codec => CreateVaultCredentialAuthParam).annotate({ + "description": "The authentication method and write-only secret values to store." + }), + "metadata": Schema.optionalKey( + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).annotate({ + "description": + "Up to 16 string key-value pairs, with keys up to 64 and values up to 512 characters. Defaults to an empty map." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) + ) +}).annotate({ + "description": "Parameters for storing a credential for an MCP server or an OpenAI-hosted environment.", + "identifier": "CreateVaultCredentialParams" +}) +export type RotateVaultCredentialParams = { + readonly "auth"?: RotateVaultCredentialAuthParam + readonly "metadata"?: { readonly [x: string]: string } +} +export const RotateVaultCredentialParams = Schema.Struct({ + "auth": Schema.optionalKey( + Schema.suspend((): Schema.Codec => RotateVaultCredentialAuthParam).annotate({ + "description": "Replacement values for the credential's existing authentication method." + }) + ), + "metadata": Schema.optionalKey( + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).annotate({ + "description": + "Replaces all metadata. Omit to preserve it, or pass {} to clear it. Up to 16 string key-value pairs, with keys up to 64 and values up to 512 characters." + }).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) + ) +}).annotate({ + "description": + "Metadata, secret, expiry, and OAuth refresh scope updates for an existing vault credential. Supply at least one of `auth` or `metadata`." +}).check( + Schema.isMinProperties(1).annotate({ + "expected": "a value with at least 1 entry", + "identifier": "RotateVaultCredentialParams" + }) +) +export type BetaToolsArray = ReadonlyArray +export const BetaToolsArray = Schema.Array(BetaTool).annotate({ + "description": + "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](https://developers.openai.com/api/docs/guides/tools-web-search)\n or [file search](https://developers.openai.com/api/docs/guides/tools-file-search). Learn more about\n [built-in tools](https://developers.openai.com/api/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](https://developers.openai.com/api/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](https://developers.openai.com/api/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n", + "identifier": "BetaToolsArray" +}) +export type BetaToolSearchOutput = { + readonly "agent"?: BetaAgentTag + readonly "type": "tool_search_output" + readonly "id": string + readonly "call_id": string | null + readonly "execution": BetaToolSearchExecutionType + readonly "tools": ReadonlyArray + readonly "status": BetaFunctionCallOutputStatusEnum + readonly "created_by"?: string +} +export const BetaToolSearchOutput = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("tool_search_output").annotate({ + "description": "The type of the item. Always `tool_search_output`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the tool search output item." }), + "call_id": Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }), + Schema.Null + ]), + "execution": Schema.suspend((): Schema.Codec => BetaToolSearchExecutionType).annotate({ + "description": "Whether tool search was executed by the server or by the client." + }), + "tools": Schema.Array(BetaTool).annotate({ "description": "The loaded tool definitions returned by tool search." }), + "status": Schema.suspend((): Schema.Codec => BetaFunctionCallOutputStatusEnum) + .annotate({ "description": "The status of the tool search output item that was recorded." }), + "created_by": Schema.optionalKey( + Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) + ) +}).annotate({ "identifier": "BetaToolSearchOutput" }) +export type BetaAdditionalTools = { + readonly "agent"?: BetaAgentTag + readonly "type": "additional_tools" + readonly "id": string + readonly "role": BetaMessageRole + readonly "tools": ReadonlyArray +} +export const BetaAdditionalTools = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }) + ), + "type": Schema.Literal("additional_tools").annotate({ + "description": "The type of the item. Always `additional_tools`." + }), + "id": Schema.String.annotate({ "description": "The unique ID of the additional tools item." }), + "role": Schema.suspend((): Schema.Codec => BetaMessageRole).annotate({ + "description": "The role that provided the additional tools." + }), + "tools": Schema.Array(BetaTool).annotate({ + "description": "The additional tool definitions made available at this item." + }) +}).annotate({ "identifier": "BetaAdditionalTools" }) +export type BetaInputItem = + | BetaEasyInputMessage + | { + readonly "agent"?: BetaAgentTag | null + readonly "type"?: "message" + readonly "role": "user" | "system" | "developer" + readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "content": BetaInputMessageContentList + } + | { + readonly "agent"?: BetaAgentTag | null + readonly "id": string + readonly "type": "message" + readonly "role": "assistant" + readonly "content": ReadonlyArray + readonly "phase"?: BetaMessagePhase | null + readonly "status": "in_progress" | "completed" | "incomplete" + } + | { + readonly "agent"?: BetaAgentTag | null + readonly "id": string + readonly "type": "file_search_call" + readonly "status": "in_progress" | "searching" | "completed" | "incomplete" | "failed" + readonly "queries": ReadonlyArray + readonly "results"?: + | ReadonlyArray< + { + readonly "file_id"?: string + readonly "text"?: string + readonly "filename"?: string + readonly "attributes"?: BetaVectorStoreFileAttributes + readonly "score"?: number + } + > + | null + } + | { + readonly "agent"?: BetaAgentTag | null + readonly "type": "computer_call" + readonly "id": string + readonly "call_id": string + readonly "action"?: BetaComputerAction + readonly "actions"?: BetaComputerActionList + readonly "pending_safety_checks": ReadonlyArray + readonly "status": "in_progress" | "completed" | "incomplete" + } + | { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id"?: string | null + readonly "call_id": string + readonly "type": "computer_call_output" + readonly "output": BetaComputerScreenshotImage + readonly "acknowledged_safety_checks"?: ReadonlyArray | null + readonly "status"?: BetaFunctionCallItemStatus | null } | { + readonly "agent"?: BetaAgentTag | null readonly "id": string readonly "type": "web_search_call" - readonly "status": "in_progress" | "searching" | "completed" | "failed" | "incomplete" - readonly "action"?: - | { - readonly "type": "search" - readonly "query"?: string - readonly "queries"?: ReadonlyArray - readonly "sources"?: ReadonlyArray< - { readonly "type": "url"; readonly "url": string } | { readonly "type": "api"; readonly "name": string } - > - } - | { readonly "type": "open_page"; readonly "url"?: string | null } - | { readonly "type": "find_in_page"; readonly "url": string; readonly "pattern": string } + readonly "status": BetaWebSearchCallStatus + readonly "action"?: BetaWebSearchActionSearch | BetaWebSearchActionOpenPage | BetaWebSearchActionFind } | { + readonly "agent"?: BetaAgentTag | null readonly "id"?: string readonly "type": "function_call" readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null readonly "namespace"?: string readonly "name": string readonly "arguments": string readonly "status"?: "in_progress" | "completed" | "incomplete" + readonly "async"?: boolean } | { + readonly "agent"?: Beta_AgentTagParam | null readonly "id"?: string | null - readonly "call_id": string + readonly "call_id"?: string | null readonly "type": "function_call_output" readonly "output": | string - | ReadonlyArray - readonly "status"?: "in_progress" | "completed" | "incomplete" | null + | ReadonlyArray + readonly "name"?: string | null + readonly "namespace"?: string | null + readonly "caller"?: BetaToolCallCallerParam | null + readonly "status"?: BetaFunctionCallItemStatus | null + } + | { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id"?: string | null + readonly "type": "agent_message" + readonly "author": string + readonly "recipient": string + readonly "content": ReadonlyArray< + BetaInputTextContentParam | BetaInputImageContentParamAutoParam | BetaEncryptedContentParam + > + } + | { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id"?: string | null + readonly "call_id": string + readonly "type": "multi_agent_call" + readonly "action": BetaMultiAgentAction1 + readonly "arguments": string + } + | { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id"?: string | null + readonly "call_id": string + readonly "type": "multi_agent_call_output" + readonly "action": BetaMultiAgentAction1 + readonly "output": ReadonlyArray } | { + readonly "agent"?: Beta_AgentTagParam | null readonly "id"?: string | null readonly "call_id"?: string | null readonly "type": "tool_search_call" - readonly "execution"?: "server" | "client" - readonly "arguments": {} - readonly "status"?: "in_progress" | "completed" | "incomplete" | null + readonly "execution"?: BetaToolSearchExecutionType + readonly "arguments": BetaEmptyModelParam + readonly "status"?: BetaFunctionCallItemStatus | null } | { + readonly "agent"?: Beta_AgentTagParam | null readonly "id"?: string | null readonly "call_id"?: string | null readonly "type": "tool_search_output" - readonly "execution"?: "server" | "client" - readonly "tools": ReadonlyArray - readonly "status"?: "in_progress" | "completed" | "incomplete" | null + readonly "execution"?: BetaToolSearchExecutionType + readonly "tools": ReadonlyArray + readonly "status"?: BetaFunctionCallItemStatus | null + } + | { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id"?: string | null + readonly "type": "additional_tools" + readonly "role": "developer" + readonly "tools": ReadonlyArray + } + | { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id"?: string | null + readonly "type": "configuration_update" + readonly "reasoning"?: { readonly "effort"?: BetaReasoningEffort } } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "reasoning" readonly "id": string readonly "encrypted_content"?: string | null - readonly "summary": ReadonlyArray - readonly "content"?: ReadonlyArray + readonly "summary": ReadonlyArray + readonly "content"?: ReadonlyArray readonly "status"?: "in_progress" | "completed" | "incomplete" } - | { readonly "id"?: string | null; readonly "type": "compaction"; readonly "encrypted_content": string } | { + readonly "agent"?: Beta_AgentTagParam | null + readonly "id"?: string | null + readonly "type": "compaction" + readonly "encrypted_content": string + } + | { + readonly "agent"?: BetaAgentTag | null readonly "type": "image_generation_call" readonly "id": string readonly "status": "in_progress" | "completed" | "generating" | "failed" readonly "result": string | null + readonly "size"?: string | "1024x1024" | "1024x1536" | "1536x1024" | null + readonly "quality"?: "low" | "medium" | "high" | "xhigh" | "max" | "auto" | null + readonly "action"?: BetaImageGenActionEnum | null + readonly "background"?: BetaImageBackground | null + readonly "output_format"?: BetaImageOutputFormat | null + readonly "revised_prompt"?: string | null } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "code_interpreter_call" readonly "id": string readonly "status": "in_progress" | "completed" | "incomplete" | "interpreting" | "failed" readonly "container_id": string readonly "code": string | null - readonly "outputs": ReadonlyArray | null + readonly "outputs": ReadonlyArray | null } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "local_shell_call" readonly "id": string readonly "call_id": string - readonly "action": LocalShellExecAction + readonly "action": BetaLocalShellExecAction readonly "status": "in_progress" | "completed" | "incomplete" } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "local_shell_call_output" readonly "id": string readonly "output": string readonly "status"?: "in_progress" | "completed" | "incomplete" | null - readonly "call_id": unknown + readonly "call_id": Schema.Json } | { + readonly "agent"?: Beta_AgentTagParam | null readonly "id"?: string | null readonly "call_id": string + readonly "caller"?: BetaToolCallCallerParam | null readonly "type": "shell_call" - readonly "action": { - readonly "commands": ReadonlyArray - readonly "timeout_ms"?: number | null - readonly "max_output_length"?: number | null - } - readonly "status"?: "in_progress" | "completed" | "incomplete" | null - readonly "environment"?: LocalEnvironmentParam | ContainerReferenceParam | null + readonly "action": BetaFunctionShellActionParam + readonly "status"?: BetaFunctionShellCallItemStatus | null + readonly "environment"?: BetaLocalEnvironmentParam | BetaContainerReferenceParam | null } | { + readonly "agent"?: Beta_AgentTagParam | null readonly "id"?: string | null readonly "call_id": string + readonly "caller"?: BetaToolCallCallerParam | null readonly "type": "shell_call_output" - readonly "output": ReadonlyArray - readonly "status"?: "in_progress" | "completed" | "incomplete" | null + readonly "output": ReadonlyArray + readonly "status"?: BetaFunctionShellCallItemStatus | null readonly "max_output_length"?: number | null } | { + readonly "agent"?: Beta_AgentTagParam | null readonly "type": "apply_patch_call" readonly "id"?: string | null readonly "call_id": string - readonly "status": "in_progress" | "completed" - readonly "operation": - | ApplyPatchCreateFileOperationParam - | ApplyPatchDeleteFileOperationParam - | ApplyPatchUpdateFileOperationParam + readonly "caller"?: BetaToolCallCallerParam | null + readonly "status": BetaApplyPatchCallStatusParam + readonly "operation": BetaApplyPatchOperationParam } | { + readonly "agent"?: Beta_AgentTagParam | null readonly "type": "apply_patch_call_output" readonly "id"?: string | null readonly "call_id": string - readonly "status": "completed" | "failed" + readonly "caller"?: BetaToolCallCallerParam | null + readonly "status": BetaApplyPatchCallOutputStatusParam readonly "output"?: string | null } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "mcp_list_tools" readonly "id": string readonly "server_label": string - readonly "tools": ReadonlyArray + readonly "tools": ReadonlyArray readonly "error"?: string | null } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "mcp_approval_request" readonly "id": string readonly "server_label": string @@ -22914,44 +40696,56 @@ export type InputItem = readonly "arguments": string } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "mcp_approval_response" readonly "id"?: string | null readonly "approval_request_id": string readonly "approve": boolean readonly "reason"?: string | null - readonly "request_id": unknown + readonly "request_id": Schema.Json } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "mcp_call" readonly "id": string readonly "server_label": string readonly "name": string readonly "arguments": string readonly "output"?: string | null - readonly "error"?: string | null - readonly "status"?: "in_progress" | "completed" | "incomplete" | "calling" | "failed" + readonly "error"?: BetaMCPToolCallError | null + readonly "status"?: BetaMCPToolCallStatus readonly "approval_request_id"?: string | null } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "custom_tool_call_output" readonly "id"?: string readonly "call_id": string - readonly "output": string | ReadonlyArray + readonly "caller"?: BetaToolCallCallerParam | null + readonly "output": string | ReadonlyArray } | { + readonly "agent"?: BetaAgentTag | null readonly "type": "custom_tool_call" readonly "id"?: string readonly "call_id": string + readonly "caller"?: BetaToolCallCaller | null readonly "namespace"?: string readonly "name": string readonly "input": string + readonly "async"?: boolean } - | CompactionTriggerItemParam - | ItemReferenceParam -export const InputItem = Schema.Union([ - EasyInputMessage, + | BetaCompactionTriggerItemParam + | BetaItemReferenceParam + | BetaProgramItemParam + | BetaProgramOutputItemParam +export const BetaInputItem = Schema.Union([ + BetaEasyInputMessage, Schema.Union([ Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), "type": Schema.optionalKey( Schema.Literal("message").annotate({ "description": "The type of the message input. Always set to `message`.\n" @@ -22966,9 +40760,16 @@ export const InputItem = Schema.Union([ "The status of item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" }) ), - "content": InputMessageContentList - }).annotate({ "title": "Input message", "description": "Content item used to generate a response.\n" }), + "content": BetaInputMessageContentList + }).annotate({ + "title": "Input message", + "description": + "A message input to the model with a role indicating instruction following\nhierarchy. Instructions given with the `developer` or `system` role take\nprecedence over instructions given with the `user` role.\n" + }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), "id": Schema.String.annotate({ "description": "The unique ID of the output message.\n" }), "type": Schema.Literal("message").annotate({ "description": "The type of the output message. Always `message`.\n" @@ -22976,14 +40777,19 @@ export const InputItem = Schema.Union([ "role": Schema.Literal("assistant").annotate({ "description": "The role of the output message. Always `assistant`.\n" }), - "content": Schema.Array(OutputMessageContent).annotate({ "description": "The content of the output message.\n" }), - "phase": Schema.optionalKey(Schema.Union([MessagePhase, Schema.Null])), + "content": Schema.Array(BetaOutputMessageContent).annotate({ + "description": "The content of the output message.\n" + }), + "phase": Schema.optionalKey(Schema.Union([BetaMessagePhase, Schema.Null])), "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ "description": "The status of the message input. One of `in_progress`, `completed`, or\n`incomplete`. Populated when input items are returned via API.\n" }) - }).annotate({ "title": "Output message", "description": "Content item used to generate a response.\n" }), + }).annotate({ "title": "Output message", "description": "An output message from the model.\n" }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), "id": Schema.String.annotate({ "description": "The unique ID of the file search tool call.\n" }), "type": Schema.Literal("file_search_call").annotate({ "description": "The type of the file search tool call. Always `file_search_call`.\n" @@ -23000,18 +40806,25 @@ export const InputItem = Schema.Union([ Schema.String.annotate({ "description": "The text that was retrieved from the file.\n" }) ), "filename": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the file.\n" })), - "attributes": Schema.optionalKey(VectorStoreFileAttributes), + "attributes": Schema.optionalKey(BetaVectorStoreFileAttributes), "score": Schema.optionalKey( Schema.Number.annotate({ "description": "The relevance score of the file - a value between 0 and 1.\n", "format": "float" - }).check(Schema.isFinite()) + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) ) })).annotate({ "description": "The results of the file search tool call.\n" }), Schema.Null ])) - }).annotate({ "title": "File search tool call", "description": "Content item used to generate a response.\n" }), + }).annotate({ + "title": "File search tool call", + "description": + "The results of a file search tool call. See the\n[file search guide](https://developers.openai.com/api/docs/guides/tools-file-search) for more information.\n" + }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), "type": Schema.Literal("computer_call").annotate({ "description": "The type of the computer call. Always `computer_call`." }), @@ -23019,17 +40832,29 @@ export const InputItem = Schema.Union([ "call_id": Schema.String.annotate({ "description": "An identifier used when responding to the tool call with output.\n" }), - "action": Schema.optionalKey(ComputerAction), - "actions": Schema.optionalKey(ComputerActionList), - "pending_safety_checks": Schema.Array(ComputerCallSafetyCheckParam).annotate({ + "action": Schema.optionalKey(BetaComputerAction), + "actions": Schema.optionalKey(BetaComputerActionList), + "pending_safety_checks": Schema.Array(BetaComputerCallSafetyCheckParam).annotate({ "description": "The pending safety checks for the computer call.\n" }), "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ "description": "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" }) - }).annotate({ "title": "Computer tool call", "description": "Content item used to generate a response.\n" }), + }).annotate({ + "title": "Computer tool call", + "description": + "A tool call to a computer use tool. See the\n[computer use guide](https://developers.openai.com/api/docs/guides/tools-computer-use) for more information.\n" + }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), "id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": "The ID of the computer tool call output." }), @@ -23037,14 +40862,16 @@ export const InputItem = Schema.Union([ ]) ), "call_id": Schema.String.annotate({ "description": "The ID of the computer tool call that produced the output." }) - .check(Schema.isMinLength(1)).check(Schema.isMaxLength(64)), + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), "type": Schema.Literal("computer_call_output").annotate({ "description": "The type of the computer tool call output. Always `computer_call_output`." }), - "output": ComputerScreenshotImage, + "output": BetaComputerScreenshotImage, "acknowledged_safety_checks": Schema.optionalKey( Schema.Union([ - Schema.Array(ComputerCallSafetyCheckParam).annotate({ + Schema.Array(BetaComputerCallSafetyCheckParam).annotate({ "description": "The safety checks reported by the API that have been acknowledged by the developer." }), Schema.Null @@ -23052,81 +40879,42 @@ export const InputItem = Schema.Union([ ), "status": Schema.optionalKey( Schema.Union([ - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + Schema.suspend((): Schema.Codec => BetaFunctionCallItemStatus).annotate({ "description": "The status of the message input. One of `in_progress`, `completed`, or `incomplete`. Populated when input items are returned via API." }), Schema.Null - ]) - ) - }).annotate({ "title": "Computer tool call output", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique ID of the web search tool call.\n" }), - "type": Schema.Literal("web_search_call").annotate({ - "description": "The type of the web search tool call. Always `web_search_call`.\n" - }), - "status": Schema.Literals(["in_progress", "searching", "completed", "failed", "incomplete"]).annotate({ - "description": "The status of the web search tool call.\n" - }), - "action": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("search").annotate({ "description": "The action type.\n" }), - "query": Schema.optionalKey(Schema.String.annotate({ "description": "[DEPRECATED] The search query.\n" })), - "queries": Schema.optionalKey( - Schema.Array(Schema.String.annotate({ "description": "A search query.\n" })).annotate({ - "title": "Search queries", - "description": "The search queries.\n" - }) - ), - "sources": Schema.optionalKey( - Schema.Array( - Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("url").annotate({ "description": "The type of source. Always `url`.\n" }), - "url": Schema.String.annotate({ "description": "The URL of the source.\n", "format": "uri" }) - }).annotate({ "title": "Web search source", "description": "A source used in the search.\n" }), - Schema.Struct({ - "type": Schema.Literal("api").annotate({ "description": "The type of source. Always `api`.\n" }), - "name": Schema.String.annotate({ - "description": - "The name of the API source, such as `oai-weather`, `oai-sports`, or `oai-finance`.\n" - }) - }).annotate({ "title": "Web search API source", "description": "An API source used in the search.\n" }) - ]) - ).annotate({ "title": "Web search sources", "description": "The sources used in the search.\n" }) - ) - }).annotate({ - "title": "Search action", - "description": - "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" - }), - Schema.Struct({ - "type": Schema.Literal("open_page").annotate({ "description": "The action type. Always `open_page`.\n" }), - "url": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "format": "uri" }), Schema.Null]).annotate({ - "description": "The URL opened by the model.\n" - }) - ) - }).annotate({ - "title": "Open page action", - "description": - "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" - }), - Schema.Struct({ - "type": Schema.Literal("find_in_page").annotate({ "description": "The action type.\n" }), - "url": Schema.String.annotate({ - "description": "The URL of the page searched for the pattern.\n", - "format": "uri" - }), - "pattern": Schema.String.annotate({ "description": "The pattern or text to search for within the page.\n" }) + ]) + ) + }).annotate({ "title": "Computer tool call output", "description": "The output of a computer tool call." }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "id": Schema.String.annotate({ "description": "The unique ID of the web search tool call.\n" }), + "type": Schema.Literal("web_search_call").annotate({ + "description": "The type of the web search tool call. Always `web_search_call`.\n" + }), + "status": Schema.suspend((): Schema.Codec => BetaWebSearchCallStatus).annotate({ + "description": "The status of the web search tool call.\n" + }), + "action": Schema.optionalKey( + Schema.Union([BetaWebSearchActionSearch, BetaWebSearchActionOpenPage, BetaWebSearchActionFind], { + mode: "oneOf" }).annotate({ - "title": "Find action", "description": "An object describing the specific action taken in this web search call.\nIncludes details on how the model used the web (search, open_page, find_in_page).\n" }) - ], { mode: "oneOf" })) - }).annotate({ "title": "Web search tool call", "description": "Content item used to generate a response.\n" }), + ) + }).annotate({ + "title": "Web search tool call", + "description": + "The results of a web search tool call. See the\n[web search guide](https://developers.openai.com/api/docs/guides/tools-web-search) for more information.\n" + }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), "id": Schema.optionalKey(Schema.String.annotate({ "description": "The unique ID of the function tool call.\n" })), "type": Schema.Literal("function_call").annotate({ "description": "The type of the function tool call. Always `function_call`.\n" @@ -23134,6 +40922,7 @@ export const InputItem = Schema.Union([ "call_id": Schema.String.annotate({ "description": "The unique ID of the function tool call generated by the model.\n" }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCaller, Schema.Null])), "namespace": Schema.optionalKey( Schema.String.annotate({ "description": "The namespace of the function to run.\n" }) ), @@ -23146,9 +40935,24 @@ export const InputItem = Schema.Union([ "description": "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" }) + ), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the function tool call runs asynchronously.\n" }) ) - }).annotate({ "title": "Function tool call", "description": "Content item used to generate a response.\n" }), + }).annotate({ + "title": "Function tool call", + "description": + "A tool call to run a function. See the\n[function calling guide](https://developers.openai.com/api/docs/guides/function-calling) for more information.\n" + }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), "id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ @@ -23158,33 +40962,153 @@ export const InputItem = Schema.Union([ Schema.Null ]) ), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the function tool call generated by the model." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(64)), + "call_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the function tool call generated by the model." }) + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + Schema.Null + ]) + ), "type": Schema.Literal("function_call_output").annotate({ "description": "The type of the function tool call output. Always `function_call_output`." }), "output": Schema.Union([ Schema.String.annotate({ "description": "A JSON string of the output of the function tool call." }).check( - Schema.isMaxLength(10485760) + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) ), Schema.Array( - Schema.Union([InputTextContentParam, InputImageContentParamAutoParam, InputFileContentParam], { + Schema.Union([BetaInputTextContentParam, BetaInputImageContentParamAutoParam, BetaInputFileContentParam], { mode: "oneOf" }).annotate({ "description": "A piece of message content, such as text, an image, or a file." }) ).annotate({ "description": "An array of content outputs (text, image, file) for the function tool call." }) ], { mode: "oneOf" }).annotate({ "description": "Text, image, or file output of the function tool call." }), + "name": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The name of the tool that produced the output." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ]) + ), + "namespace": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The namespace of the tool that produced the output." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })).check( + Schema.isPattern(new RegExp("^[a-zA-Z0-9_-]+$", "u")).annotate({ + "expected": "a string matching the RegExp ^[a-zA-Z0-9_-]+$" + }) + ), + Schema.Null + ]) + ), + "caller": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) + ), "status": Schema.optionalKey( Schema.Union([ - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + Schema.suspend((): Schema.Codec => BetaFunctionCallItemStatus).annotate({ "description": "The status of the item. One of `in_progress`, `completed`, or `incomplete`. Populated when items are returned via API." }), Schema.Null ]) ) - }).annotate({ "title": "Function tool call output", "description": "Content item used to generate a response.\n" }), + }).annotate({ "title": "Function tool call output", "description": "The output of a function tool call." }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of this agent message item." }), + Schema.Null + ]) + ), + "type": Schema.Literal("agent_message").annotate({ "description": "The item type. Always `agent_message`." }), + "author": Schema.String.annotate({ "description": "The sending agent identity." }), + "recipient": Schema.String.annotate({ "description": "The destination agent identity." }), + "content": Schema.Array( + Schema.Union([BetaInputTextContentParam, BetaInputImageContentParamAutoParam, BetaEncryptedContentParam], { + mode: "oneOf" + }).annotate({ "description": "A plaintext, image, or encrypted agent message content part." }) + ).annotate({ "description": "Plaintext, image, or encrypted content sent between agents." }) + }).annotate({ "title": "Agent message", "description": "A message routed between agents." }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of this multi-agent call." }), + Schema.Null + ]) + ), + "call_id": Schema.String.annotate({ "description": "The unique ID linking this call to its output." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "type": Schema.Literal("multi_agent_call").annotate({ + "description": "The item type. Always `multi_agent_call`." + }), + "action": Schema.suspend((): Schema.Codec => BetaMultiAgentAction1).annotate({ + "description": "The multi-agent action that was executed." + }), + "arguments": Schema.String.annotate({ "description": "The action arguments as a JSON string." }) + }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of this multi-agent call output." }), + Schema.Null + ]) + ), + "call_id": Schema.String.annotate({ "description": "The unique ID of the multi-agent call." }).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })), + "type": Schema.Literal("multi_agent_call_output").annotate({ + "description": "The item type. Always `multi_agent_call_output`." + }), + "action": Schema.suspend((): Schema.Codec => BetaMultiAgentAction1).annotate({ + "description": "The multi-agent action that produced this result." + }), + "output": Schema.Array(BetaOutputTextContentParam).annotate({ + "description": "Text output returned by the multi-agent action." + }) + }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), "id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": "The unique ID of this tool search call." }), @@ -23194,7 +41118,9 @@ export const InputItem = Schema.Union([ "call_id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }) - .check(Schema.isMinLength(1)).check(Schema.isMaxLength(64)), + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), Schema.Null ]) ), @@ -23202,21 +41128,31 @@ export const InputItem = Schema.Union([ "description": "The item type. Always `tool_search_call`." }), "execution": Schema.optionalKey( - Schema.Literals(["server", "client"]).annotate({ + Schema.suspend((): Schema.Codec => BetaToolSearchExecutionType).annotate({ "description": "Whether tool search was executed by the server or by the client." }) ), - "arguments": Schema.Struct({}).annotate({ "description": "The arguments supplied to the tool search call." }), + "arguments": Schema.suspend((): Schema.Codec => BetaEmptyModelParam).annotate({ + "description": "The arguments supplied to the tool search call." + }), "status": Schema.optionalKey( Schema.Union([ - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + Schema.suspend((): Schema.Codec => BetaFunctionCallItemStatus).annotate({ "description": "The status of the tool search call." }), Schema.Null ]) ) - }).annotate({ "description": "Content item used to generate a response.\n" }), + }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), "id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": "The unique ID of this tool search output." }), @@ -23226,7 +41162,9 @@ export const InputItem = Schema.Union([ "call_id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }) - .check(Schema.isMinLength(1)).check(Schema.isMaxLength(64)), + .check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), Schema.Null ]) ), @@ -23234,37 +41172,95 @@ export const InputItem = Schema.Union([ "description": "The item type. Always `tool_search_output`." }), "execution": Schema.optionalKey( - Schema.Literals(["server", "client"]).annotate({ + Schema.suspend((): Schema.Codec => BetaToolSearchExecutionType).annotate({ "description": "Whether tool search was executed by the server or by the client." }) ), - "tools": Schema.Array(Tool).annotate({ + "tools": Schema.Array(BetaToolSearchOutputTool).annotate({ "description": "The loaded tool definitions returned by the tool search output." }), "status": Schema.optionalKey( Schema.Union([ - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ + Schema.suspend((): Schema.Codec => BetaFunctionCallItemStatus).annotate({ "description": "The status of the tool search output." }), Schema.Null ]) ) - }).annotate({ "description": "Content item used to generate a response.\n" }), + }), Schema.Struct({ - "type": Schema.Literal("reasoning").annotate({ "description": "The type of the object. Always `reasoning`.\n" }), - "id": Schema.String.annotate({ "description": "The unique identifier of the reasoning content.\n" }), - "encrypted_content": Schema.optionalKey( + "agent": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ - "description": - "The encrypted content of the reasoning item - populated when a response is\ngenerated with `reasoning.encrypted_content` in the `include` parameter.\n" + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." }), Schema.Null ]) ), - "summary": Schema.Array(SummaryTextContent).annotate({ "description": "Reasoning summary content.\n" }), + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of this additional tools item." }), + Schema.Null + ]) + ), + "type": Schema.Literal("additional_tools").annotate({ + "description": "The item type. Always `additional_tools`." + }), + "role": Schema.Literal("developer").annotate({ + "description": "The role that provided the additional tools. Only `developer` is supported." + }), + "tools": Schema.Array(BetaTool).annotate({ + "description": "A list of additional tools made available at this item." + }) + }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), + "id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The unique ID of the configuration update item." }), + Schema.Null + ]) + ), + "type": Schema.Literal("configuration_update").annotate({ + "description": "The item type. Always `configuration_update`." + }), + "reasoning": Schema.optionalKey( + Schema.Struct({ + "effort": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaReasoningEffort).annotate({ + "description": + "The reasoning effort to use for subsequent responses until another\nconfiguration update replaces it.\n" + }) + ) + }).annotate({ "description": "Updates to reasoning configuration. Only effort is supported." }) + ) + }).annotate({ + "description": + "An update to the conversation's response configuration. The configuration\nremains in effect for subsequent responses until it is replaced by another\nconfiguration update.\n" + }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("reasoning").annotate({ "description": "The type of the object. Always `reasoning`.\n" }), + "id": Schema.String.annotate({ "description": "The unique identifier of the reasoning content.\n" }), + "encrypted_content": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "The encrypted content of the reasoning item. This is populated by default\nfor reasoning items returned by `POST /v1/responses` and WebSocket\n`response.create` requests.\n\nWhen streaming, use the completed reasoning item and its\n`encrypted_content` from the `response.output_item.done` event in\nsubsequent requests. The `encrypted_content` in\n`response.output_item.added` may be incomplete. This is especially\nimportant when `store` is `false` or when using Zero Data Retention.\n" + }), + Schema.Null + ])), + "summary": Schema.Array(BetaSummaryTextContent).annotate({ "description": "Reasoning summary content.\n" }), "content": Schema.optionalKey( - Schema.Array(ReasoningTextContent).annotate({ "description": "Reasoning text content.\n" }) + Schema.Array(BetaReasoningTextContent).annotate({ "description": "Reasoning text content.\n" }) ), "status": Schema.optionalKey( Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ @@ -23272,29 +41268,105 @@ export const InputItem = Schema.Union([ "The status of the item. One of `in_progress`, `completed`, or\n`incomplete`. Populated when items are returned via API.\n" }) ) - }).annotate({ "title": "Reasoning", "description": "Content item used to generate a response.\n" }), + }).annotate({ + "title": "Reasoning", + "description": + "A description of the chain of thought used by a reasoning model while generating\na response. Be sure to include these items in your `input` to the Responses API\nfor subsequent turns of a conversation if you are manually\n[managing context](https://developers.openai.com/api/docs/guides/conversation-state).\n" + }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), "id": Schema.optionalKey( Schema.Union([Schema.String.annotate({ "description": "The ID of the compaction item." }), Schema.Null]) ), "type": Schema.Literal("compaction").annotate({ "description": "The type of the item. Always `compaction`." }), "encrypted_content": Schema.String.annotate({ "description": "The encrypted content of the compaction summary." }) - .check(Schema.isMaxLength(10485760)) - }).annotate({ "title": "Compaction item", "description": "Content item used to generate a response.\n" }), + .check( + Schema.isMaxCodePoints(104857600).annotate({ "expected": "a string with at most 104857600 code points" }) + ) + }).annotate({ + "title": "Compaction item", + "description": + "A compaction item generated by the [`v1/responses/compact` API](https://developers.openai.com/api/reference/resources/responses/methods/compact)." + }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaAgentTag).annotate({ + "description": "The agent that produced this item." + }), + Schema.Null + ]) + ), "type": Schema.Literal("image_generation_call").annotate({ - "description": "The type of the image generation call. Always `image_generation_call`.\n" + "description": "The type of the image generation call. Always `image_generation_call`." }), - "id": Schema.String.annotate({ "description": "The unique ID of the image generation call.\n" }), + "id": Schema.String.annotate({ "description": "The unique ID of the image generation call." }), "status": Schema.Literals(["in_progress", "completed", "generating", "failed"]).annotate({ - "description": "The status of the image generation call.\n" + "description": "The status of the image generation call." }), "result": Schema.Union([ - Schema.String.annotate({ "description": "The generated image encoded in base64.\n" }), + Schema.String.annotate({ "description": "The generated image encoded in base64." }), Schema.Null - ]) - }).annotate({ "title": "Image generation call", "description": "Content item used to generate a response.\n" }), + ]), + "size": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.String, Schema.Literals(["1024x1024", "1024x1536", "1536x1024"])]).annotate({ + "description": "The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`." + }), + Schema.Null + ]) + ), + "quality": Schema.optionalKey( + Schema.Union([ + Schema.Literals(["low", "medium", "high", "xhigh", "max", "auto"]).annotate({ + "description": + "The quality of the image generated by the image generation tool call. One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`." + }), + Schema.Null + ]) + ), + "action": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaImageGenActionEnum).annotate({ + "description": "The action used for image generation." + }), + Schema.Null + ]) + ), + "background": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaImageBackground).annotate({ + "description": "The background setting used for generation." + }), + Schema.Null + ]) + ), + "output_format": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaImageOutputFormat).annotate({ + "description": "The output format used for generation." + }), + Schema.Null + ]) + ), + "revised_prompt": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "The prompt that was used after any model prompt rewriting." }), + Schema.Null + ]) + ) + }).annotate({ "title": "Image generation call", "description": "An image generation request made by the model." }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), "type": Schema.Literal("code_interpreter_call").annotate({ "description": "The type of the code interpreter tool call. Always `code_interpreter_call`.\n" }), @@ -23309,19 +41381,18 @@ export const InputItem = Schema.Union([ Schema.Null ]), "outputs": Schema.Union([ - Schema.Array(Schema.Union([CodeInterpreterOutputLogs, CodeInterpreterOutputImage], { mode: "oneOf" })).annotate( - { + Schema.Array(Schema.Union([BetaCodeInterpreterOutputLogs, BetaCodeInterpreterOutputImage], { mode: "oneOf" })) + .annotate({ "description": "The outputs generated by the code interpreter, such as logs or images.\nCan be null if no outputs are available.\n" - } - ), + }), Schema.Null ]) - }).annotate({ - "title": "Code interpreter tool call", - "description": "Content item used to generate a response.\n" - }), + }).annotate({ "title": "Code interpreter tool call", "description": "A tool call to run code.\n" }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), "type": Schema.Literal("local_shell_call").annotate({ "description": "The type of the local shell call. Always `local_shell_call`.\n" }), @@ -23329,952 +41400,413 @@ export const InputItem = Schema.Union([ "call_id": Schema.String.annotate({ "description": "The unique ID of the local shell tool call generated by the model.\n" }), - "action": LocalShellExecAction, + "action": BetaLocalShellExecAction, "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ "description": "The status of the local shell call.\n" }) - }).annotate({ "title": "Local shell call", "description": "Content item used to generate a response.\n" }), + }).annotate({ "title": "Local shell call", "description": "A tool call to run a command on the local shell.\n" }), Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), "type": Schema.Literal("local_shell_call_output").annotate({ "description": "The type of the local shell tool call output. Always `local_shell_call_output`.\n" }), - "id": Schema.String.annotate({ - "description": "The unique ID of the local shell tool call generated by the model.\n" - }), - "output": Schema.String.annotate({ - "description": "A JSON string of the output of the local shell tool call.\n" - }), - "status": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": "The status of the item. One of `in_progress`, `completed`, or `incomplete`.\n" - }), - Schema.Null - ]) - ), - "call_id": Schema.Unknown - }).annotate({ "title": "Local shell call output", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ - "id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "The unique ID of the shell tool call. Populated when this item is returned via API." - }), - Schema.Null - ]) - ), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the shell tool call generated by the model." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(64)), - "type": Schema.Literal("shell_call").annotate({ "description": "The type of the item. Always `shell_call`." }), - "action": Schema.Struct({ - "commands": Schema.Array(Schema.String).annotate({ - "description": "Ordered shell commands for the execution environment to run." - }), - "timeout_ms": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "Maximum wall-clock time in milliseconds to allow the shell commands to run." - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "max_output_length": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "Maximum number of UTF-8 characters to capture from combined stdout and stderr output." - }).check(Schema.isInt()), - Schema.Null - ]) - ) - }).annotate({ - "title": "Shell action", - "description": "The shell commands and limits that describe how to run the tool call." - }), + "id": Schema.String.annotate({ + "description": "The unique ID of the local shell tool call generated by the model.\n" + }), + "output": Schema.String.annotate({ + "description": "A JSON string of the output of the local shell tool call.\n" + }), "status": Schema.optionalKey( Schema.Union([ Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "title": "Shell call status", - "description": "The status of the shell call. One of `in_progress`, `completed`, or `incomplete`." + "description": "The status of the item. One of `in_progress`, `completed`, or `incomplete`.\n" }), Schema.Null ]) ), - "environment": Schema.optionalKey( + "call_id": Schema.Json.annotate({ "expected": "JSON value" }) + }).annotate({ "title": "Local shell call output", "description": "The output of a local shell tool call.\n" }), + Schema.Struct({ + "agent": Schema.optionalKey( Schema.Union([ - Schema.Union([LocalEnvironmentParam, ContainerReferenceParam], { mode: "oneOf" }).annotate({ - "description": "The environment to execute the shell commands in." + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." }), Schema.Null ]) - ) - }).annotate({ "title": "Shell tool call", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ + ), "id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ - "description": "The unique ID of the shell tool call output. Populated when this item is returned via API." + "description": "The unique ID of the shell tool call. Populated when this item is returned via API." }), Schema.Null ]) ), "call_id": Schema.String.annotate({ "description": "The unique ID of the shell tool call generated by the model." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(64)), - "type": Schema.Literal("shell_call_output").annotate({ - "description": "The type of the item. Always `shell_call_output`." - }), - "output": Schema.Array(FunctionShellCallOutputContentParam).annotate({ - "description": "Captured chunks of stdout and stderr output, along with their associated outcomes." - }), - "status": Schema.optionalKey( + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + "caller": Schema.optionalKey( Schema.Union([ - Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "title": "Shell call status", - "description": "The status of the shell call output." + Schema.suspend((): Schema.Codec => BetaToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." }), Schema.Null ]) ), - "max_output_length": Schema.optionalKey( + "type": Schema.Literal("shell_call").annotate({ "description": "The type of the item. Always `shell_call`." }), + "action": Schema.suspend((): Schema.Codec => BetaFunctionShellActionParam).annotate( + { "description": "The shell commands and limits that describe how to run the tool call." } + ), + "status": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ - "description": "The maximum number of UTF-8 characters captured for this shell call's combined output." - }).check(Schema.isInt()), + Schema.suspend((): Schema.Codec => BetaFunctionShellCallItemStatus).annotate( + { "description": "The status of the shell call. One of `in_progress`, `completed`, or `incomplete`." } + ), + Schema.Null + ]) + ), + "environment": Schema.optionalKey( + Schema.Union([ + Schema.Union([BetaLocalEnvironmentParam, BetaContainerReferenceParam], { mode: "oneOf" }).annotate({ + "description": "The environment to execute the shell commands in." + }), Schema.Null ]) ) - }).annotate({ "title": "Shell tool call output", "description": "Content item used to generate a response.\n" }), + }).annotate({ + "title": "Shell tool call", + "description": "A tool representing a request to execute one or more shell commands." + }), Schema.Struct({ - "type": Schema.Literal("apply_patch_call").annotate({ - "description": "The type of the item. Always `apply_patch_call`." - }), - "id": Schema.optionalKey( + "agent": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ - "description": "The unique ID of the apply patch tool call. Populated when this item is returned via API." + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." }), Schema.Null ]) ), - "call_id": Schema.String.annotate({ - "description": "The unique ID of the apply patch tool call generated by the model." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(64)), - "status": Schema.Literals(["in_progress", "completed"]).annotate({ - "title": "Apply patch call status", - "description": "The status of the apply patch tool call. One of `in_progress` or `completed`." - }), - "operation": Schema.Union([ - ApplyPatchCreateFileOperationParam, - ApplyPatchDeleteFileOperationParam, - ApplyPatchUpdateFileOperationParam - ], { mode: "oneOf" }).annotate({ - "title": "Apply patch operation", - "description": "The specific create, delete, or update instruction for the apply_patch tool call." - }) - }).annotate({ "title": "Apply patch tool call", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ - "type": Schema.Literal("apply_patch_call_output").annotate({ - "description": "The type of the item. Always `apply_patch_call_output`." - }), "id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ - "description": - "The unique ID of the apply patch tool call output. Populated when this item is returned via API." + "description": "The unique ID of the shell tool call output. Populated when this item is returned via API." }), Schema.Null ]) ), "call_id": Schema.String.annotate({ - "description": "The unique ID of the apply patch tool call generated by the model." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(64)), - "status": Schema.Literals(["completed", "failed"]).annotate({ - "title": "Apply patch call output status", - "description": "The status of the apply patch tool call output. One of `completed` or `failed`." - }), - "output": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": "Optional human-readable log text from the apply patch tool (e.g., patch results or errors)." - }).check(Schema.isMaxLength(10485760)), - Schema.Null - ]) - ) - }).annotate({ - "title": "Apply patch tool call output", - "description": "Content item used to generate a response.\n" - }), - Schema.Struct({ - "type": Schema.Literal("mcp_list_tools").annotate({ - "description": "The type of the item. Always `mcp_list_tools`.\n" - }), - "id": Schema.String.annotate({ "description": "The unique ID of the list.\n" }), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server.\n" }), - "tools": Schema.Array(MCPListToolsTool).annotate({ "description": "The tools available on the server.\n" }), - "error": Schema.optionalKey( + "description": "The unique ID of the shell tool call generated by the model." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + "caller": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ "description": "Error message if the server could not list tools.\n" }), + Schema.suspend((): Schema.Codec => BetaToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), Schema.Null ]) - ) - }).annotate({ "title": "MCP list tools", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ - "type": Schema.Literal("mcp_approval_request").annotate({ - "description": "The type of the item. Always `mcp_approval_request`.\n" + ), + "type": Schema.Literal("shell_call_output").annotate({ + "description": "The type of the item. Always `shell_call_output`." }), - "id": Schema.String.annotate({ "description": "The unique ID of the approval request.\n" }), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server making the request.\n" }), - "name": Schema.String.annotate({ "description": "The name of the tool to run.\n" }), - "arguments": Schema.String.annotate({ "description": "A JSON string of arguments for the tool.\n" }) - }).annotate({ "title": "MCP approval request", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ - "type": Schema.Literal("mcp_approval_response").annotate({ - "description": "The type of the item. Always `mcp_approval_response`.\n" + "output": Schema.Array(BetaFunctionShellCallOutputContentParam).annotate({ + "description": "Captured chunks of stdout and stderr output, along with their associated outcomes." }), - "id": Schema.optionalKey( + "status": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ "description": "The unique ID of the approval response\n" }), + Schema.suspend((): Schema.Codec => BetaFunctionShellCallItemStatus).annotate( + { "description": "The status of the shell call output." } + ), Schema.Null ]) ), - "approval_request_id": Schema.String.annotate({ - "description": "The ID of the approval request being answered.\n" - }), - "approve": Schema.Boolean.annotate({ "description": "Whether the request was approved.\n" }), - "reason": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "Optional reason for the decision.\n" }), Schema.Null]) - ), - "request_id": Schema.Unknown - }).annotate({ "title": "MCP approval response", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ - "type": Schema.Literal("mcp_call").annotate({ "description": "The type of the item. Always `mcp_call`.\n" }), - "id": Schema.String.annotate({ "description": "The unique ID of the tool call.\n" }), - "server_label": Schema.String.annotate({ "description": "The label of the MCP server running the tool.\n" }), - "name": Schema.String.annotate({ "description": "The name of the tool that was run.\n" }), - "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments passed to the tool.\n" }), - "output": Schema.optionalKey( - Schema.Union([Schema.String.annotate({ "description": "The output from the tool call.\n" }), Schema.Null]) - ), - "error": Schema.optionalKey( + "max_output_length": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ "description": "The error from the tool call, if any.\n" }), + Schema.Number.annotate({ + "description": "The maximum number of UTF-8 characters captured for this shell call's combined output." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) - ), - "status": Schema.optionalKey( - Schema.Literals(["in_progress", "completed", "incomplete", "calling", "failed"]).annotate({ - "description": - "The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`.\n" - }) - ), - "approval_request_id": Schema.optionalKey( + ) + }).annotate({ + "title": "Shell tool call output", + "description": "The streamed output items emitted by a shell tool call." + }), + Schema.Struct({ + "agent": Schema.optionalKey( Schema.Union([ - Schema.String.annotate({ - "description": - "Unique identifier for the MCP tool call approval request.\nInclude this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call.\n" + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." }), Schema.Null ]) - ) - }).annotate({ "title": "MCP tool call", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ - "type": Schema.Literal("custom_tool_call_output").annotate({ - "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" - }), - "id": Schema.optionalKey( - Schema.String.annotate({ - "description": "The unique ID of the custom tool call output in the OpenAI platform.\n" - }) - ), - "call_id": Schema.String.annotate({ - "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" - }), - "output": Schema.Union([ - Schema.String.annotate({ - "title": "string output", - "description": "A string of the output of the custom tool call.\n" - }), - Schema.Array(FunctionAndCustomToolCallOutput).annotate({ - "title": "output content list", - "description": "Text, image, or file output of the custom tool call.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" - }) - }).annotate({ "title": "Custom tool call output", "description": "Content item used to generate a response.\n" }), - Schema.Struct({ - "type": Schema.Literal("custom_tool_call").annotate({ - "description": "The type of the custom tool call. Always `custom_tool_call`.\n" - }), - "id": Schema.optionalKey( - Schema.String.annotate({ "description": "The unique ID of the custom tool call in the OpenAI platform.\n" }) - ), - "call_id": Schema.String.annotate({ - "description": "An identifier used to map this custom tool call to a tool call output.\n" - }), - "namespace": Schema.optionalKey( - Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) ), - "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), - "input": Schema.String.annotate({ "description": "The input for the custom tool call generated by the model.\n" }) - }).annotate({ "title": "Custom tool call", "description": "Content item used to generate a response.\n" }) - ], { mode: "oneOf" }).annotate({ - "title": "Item", - "description": - "An item representing part of the context for the response to be\ngenerated by the model. Can contain text, images, and audio inputs,\nas well as previous assistant responses and tool call outputs.\n" - }), - CompactionTriggerItemParam, - ItemReferenceParam -], { mode: "oneOf" }) -export type ToolsArray = ReadonlyArray -export const ToolsArray = Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n" -}) -export type ToolSearchOutput = { - readonly "type": "tool_search_output" - readonly "id": string - readonly "call_id": string | null - readonly "execution": "server" | "client" - readonly "tools": ReadonlyArray - readonly "status": "in_progress" | "completed" | "incomplete" - readonly "created_by"?: string -} -export const ToolSearchOutput = Schema.Struct({ - "type": Schema.Literal("tool_search_output").annotate({ - "description": "The type of the item. Always `tool_search_output`." - }), - "id": Schema.String.annotate({ "description": "The unique ID of the tool search output item." }), - "call_id": Schema.Union([ - Schema.String.annotate({ "description": "The unique ID of the tool search call generated by the model." }), - Schema.Null - ]), - "execution": Schema.Literals(["server", "client"]).annotate({ - "description": "Whether tool search was executed by the server or by the client." - }), - "tools": Schema.Array(Tool).annotate({ "description": "The loaded tool definitions returned by tool search." }), - "status": Schema.Literals(["in_progress", "completed", "incomplete"]).annotate({ - "description": "The status of the tool search output item that was recorded." - }), - "created_by": Schema.optionalKey( - Schema.String.annotate({ "description": "The identifier of the actor that created the item." }) - ) -}) -export type CreateEvalLabelModelGrader = { - readonly "type": "label_model" - readonly "name": string - readonly "model": string - readonly "input": ReadonlyArray - readonly "labels": ReadonlyArray - readonly "passing_labels": ReadonlyArray -} -export const CreateEvalLabelModelGrader = Schema.Struct({ - "type": Schema.Literal("label_model").annotate({ "description": "The object type, which is always `label_model`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "model": Schema.String.annotate({ - "description": "The model to use for the evaluation. Must support structured outputs." - }), - "input": Schema.Array(CreateEvalItem).annotate({ - "description": - "A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." - }), - "labels": Schema.Array(Schema.String).annotate({ - "description": "The labels to classify to each item in the evaluation." - }), - "passing_labels": Schema.Array(Schema.String).annotate({ - "description": "The labels that indicate a passing result. Must be a subset of labels." - }) -}).annotate({ - "title": "LabelModelGrader", - "description": "A LabelModelGrader object which uses a model to assign labels to each item\nin the evaluation.\n" -}) -export type CreateEvalRunRequest = { - readonly "name"?: string - readonly "metadata"?: Metadata - readonly "data_source": { - readonly "type": "jsonl" - readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource - } | { - readonly "type": "completions" - readonly "input_messages"?: { - readonly "type": "template" - readonly "template": ReadonlyArray - } | { readonly "type": "item_reference"; readonly "item_reference": string } - readonly "sampling_params"?: { - readonly "reasoning_effort"?: ReasoningEffort - readonly "temperature"?: number - readonly "max_completion_tokens"?: number - readonly "top_p"?: number - readonly "seed"?: number - readonly "response_format"?: ResponseFormatText | ResponseFormatJsonSchema | ResponseFormatJsonObject - readonly "tools"?: ReadonlyArray - } - readonly "model"?: string - readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource | EvalStoredCompletionsSource - } | { - readonly "type": "responses" - readonly "input_messages"?: { - readonly "type": "template" - readonly "template": ReadonlyArray<{ readonly "role": string; readonly "content": string } | EvalItem> - } | { readonly "type": "item_reference"; readonly "item_reference": string } - readonly "sampling_params"?: { - readonly "reasoning_effort"?: ReasoningEffort - readonly "temperature"?: number - readonly "max_completion_tokens"?: number - readonly "top_p"?: number - readonly "seed"?: number - readonly "tools"?: ReadonlyArray - readonly "text"?: { readonly "format"?: TextResponseFormatConfiguration } - } - readonly "model"?: string - readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource | EvalResponsesSource - } -} -export const CreateEvalRunRequest = Schema.Struct({ - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the run." })), - "metadata": Schema.optionalKey(Metadata), - "data_source": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("jsonl").annotate({ "description": "The type of data source. Always `jsonl`." }), - "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource], { mode: "oneOf" }).annotate({ - "description": "Determines what populates the `item` namespace in the data source." - }) - }).annotate({ "title": "JsonlRunDataSource", "description": "Details about the run's data source." }), - Schema.Struct({ - "type": Schema.Literal("completions").annotate({ - "description": "The type of run data source. Always `completions`." + "type": Schema.Literal("apply_patch_call").annotate({ + "description": "The type of the item. Always `apply_patch_call`." }), - "input_messages": Schema.optionalKey( + "id": Schema.optionalKey( Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("template").annotate({ - "description": "The type of input messages. Always `template`." - }), - "template": Schema.Array(Schema.Union([EasyInputMessage, EvalItem], { mode: "oneOf" })).annotate({ - "description": - "A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." - }) - }).annotate({ "title": "TemplateInputMessages" }), - Schema.Struct({ - "type": Schema.Literal("item_reference").annotate({ - "description": "The type of input messages. Always `item_reference`." - }), - "item_reference": Schema.String.annotate({ - "description": "A reference to a variable in the `item` namespace. Ie, \"item.input_trajectory\"" - }) - }).annotate({ "title": "ItemReferenceInputMessages" }) - ], { mode: "oneOf" }).annotate({ - "description": - "Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace." - }) + Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call. Populated when this item is returned via API." + }), + Schema.Null + ]) ), - "sampling_params": Schema.optionalKey(Schema.Struct({ - "reasoning_effort": Schema.optionalKey(ReasoningEffort), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs." }).check( - Schema.isFinite() - ) - ), - "max_completion_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum number of tokens in the generated output." }).check( - Schema.isInt() - ) - ), - "top_p": Schema.optionalKey( - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens." - }).check(Schema.isFinite()) - ), - "seed": Schema.optionalKey( - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling." }) - .check(Schema.isInt()) - ), - "response_format": Schema.optionalKey( - Schema.Union([ResponseFormatText, ResponseFormatJsonSchema, ResponseFormatJsonObject], { mode: "oneOf" }) - .annotate({ - "description": - "An object specifying the format that the model must output.\n\nSetting to `{ \"type\": \"json_schema\", \"json_schema\": {...} }` enables\nStructured Outputs which ensures the model will match your supplied JSON\nschema. Learn more in the [Structured Outputs\nguide](/docs/guides/structured-outputs).\n\nSetting to `{ \"type\": \"json_object\" }` enables the older JSON mode, which\nensures the message the model generates is valid JSON. Using `json_schema`\nis preferred for models that support it.\n" - }) - ), - "tools": Schema.optionalKey( - Schema.Array(ChatCompletionTool).annotate({ - "description": - "A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. A max of 128 functions are supported.\n" - }) - ) - })), - "model": Schema.optionalKey( - Schema.String.annotate({ - "description": "The name of the model to use for generating completions (e.g. \"o3-mini\")." - }) + "call_id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call generated by the model." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) ), - "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource, EvalStoredCompletionsSource], { - mode: "oneOf" - }).annotate({ "description": "Determines what populates the `item` namespace in this run's data source." }) - }).annotate({ "title": "CompletionsRunDataSource", "description": "Details about the run's data source." }), - Schema.Struct({ - "type": Schema.Literal("responses").annotate({ - "description": "The type of run data source. Always `responses`." - }), - "input_messages": Schema.optionalKey( + "caller": Schema.optionalKey( Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("template").annotate({ - "description": "The type of input messages. Always `template`." - }), - "template": Schema.Array( - Schema.Union([ - Schema.Struct({ - "role": Schema.String.annotate({ - "description": "The role of the message (e.g. \"system\", \"assistant\", \"user\")." - }), - "content": Schema.String.annotate({ "description": "The content of the message." }) - }).annotate({ "title": "ChatMessage" }), - EvalItem - ], { mode: "oneOf" }) - ).annotate({ - "description": - "A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." - }) - }).annotate({ "title": "InputMessagesTemplate" }), - Schema.Struct({ - "type": Schema.Literal("item_reference").annotate({ - "description": "The type of input messages. Always `item_reference`." - }), - "item_reference": Schema.String.annotate({ - "description": "A reference to a variable in the `item` namespace. Ie, \"item.name\"" - }) - }).annotate({ "title": "InputMessagesItemReference" }) - ], { mode: "oneOf" }).annotate({ - "description": - "Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace." - }) + Schema.suspend((): Schema.Codec => BetaToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), + Schema.Null + ]) ), - "sampling_params": Schema.optionalKey(Schema.Struct({ - "reasoning_effort": Schema.optionalKey(ReasoningEffort), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs." }).check( - Schema.isFinite() - ) - ), - "max_completion_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum number of tokens in the generated output." }).check( - Schema.isInt() - ) - ), - "top_p": Schema.optionalKey( - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens." - }).check(Schema.isFinite()) - ), - "seed": Schema.optionalKey( - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling." }) - .check(Schema.isInt()) - ), - "tools": Schema.optionalKey( - Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nThe two categories of tools you can provide the model are:\n\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code. Learn more about\n [function calling](/docs/guides/function-calling).\n" - }) - ), - "text": Schema.optionalKey( - Schema.Struct({ "format": Schema.optionalKey(TextResponseFormatConfiguration) }).annotate({ - "description": - "Configuration options for a text response from the model. Can be plain\ntext or structured JSON data. Learn more:\n- [Text inputs and outputs](/docs/guides/text)\n- [Structured Outputs](/docs/guides/structured-outputs)\n" - }) - ) - })), - "model": Schema.optionalKey( - Schema.String.annotate({ - "description": "The name of the model to use for generating completions (e.g. \"o3-mini\")." + "status": Schema.suspend((): Schema.Codec => BetaApplyPatchCallStatusParam) + .annotate({ "description": "The status of the apply patch tool call. One of `in_progress` or `completed`." }), + "operation": Schema.suspend((): Schema.Codec => BetaApplyPatchOperationParam) + .annotate({ + "description": "The specific create, delete, or update instruction for the apply_patch tool call." }) - ), - "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource, EvalResponsesSource], { - mode: "oneOf" - }).annotate({ "description": "Determines what populates the `item` namespace in this run's data source." }) - }).annotate({ "title": "ResponsesRunDataSource", "description": "Details about the run's data source." }) - ], { mode: "oneOf" }) -}).annotate({ "title": "CreateEvalRunRequest" }) -export type EvalGraderLabelModel = { - readonly "type": "label_model" - readonly "name": string - readonly "model": string - readonly "input": ReadonlyArray - readonly "labels": ReadonlyArray - readonly "passing_labels": ReadonlyArray -} -export const EvalGraderLabelModel = Schema.Struct({ - "type": Schema.Literal("label_model").annotate({ "description": "The object type, which is always `label_model`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "model": Schema.String.annotate({ - "description": "The model to use for the evaluation. Must support structured outputs." - }), - "input": Schema.Array(EvalItem), - "labels": Schema.Array(Schema.String).annotate({ - "description": "The labels to assign to each item in the evaluation." - }), - "passing_labels": Schema.Array(Schema.String).annotate({ - "description": "The labels that indicate a passing result. Must be a subset of labels." - }) -}).annotate({ - "title": "LabelModelGrader", - "description": "A LabelModelGrader object which uses a model to assign labels to each item\nin the evaluation.\n" -}) -export type EvalGraderScoreModel = { - readonly "type": "score_model" - readonly "name": string - readonly "model": string - readonly "sampling_params"?: { - readonly "seed"?: number | null - readonly "top_p"?: number | null - readonly "temperature"?: number | null - readonly "max_completions_tokens"?: number | null - readonly "reasoning_effort"?: ReasoningEffort - } - readonly "input": ReadonlyArray - readonly "range"?: ReadonlyArray - readonly "pass_threshold"?: number -} -export const EvalGraderScoreModel = Schema.Struct({ - "type": Schema.Literal("score_model").annotate({ "description": "The object type, which is always `score_model`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "model": Schema.String.annotate({ "description": "The model to use for the evaluation." }), - "sampling_params": Schema.optionalKey( + }).annotate({ + "title": "Apply patch tool call", + "description": "A tool call representing a request to create, delete, or update files using diff patches." + }), Schema.Struct({ - "seed": Schema.optionalKey( + "agent": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling.\n" }) - .check(Schema.isInt()), + Schema.suspend((): Schema.Codec => Beta_AgentTagParam).annotate({ + "description": "The agent that produced this item." + }), Schema.Null ]) ), - "top_p": Schema.optionalKey( + "type": Schema.Literal("apply_patch_call_output").annotate({ + "description": "The type of the item. Always `apply_patch_call_output`." + }), + "id": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens.\n" - }).check(Schema.isFinite()), + Schema.String.annotate({ + "description": + "The unique ID of the apply patch tool call output. Populated when this item is returned via API." + }), Schema.Null ]) ), - "temperature": Schema.optionalKey( + "call_id": Schema.String.annotate({ + "description": "The unique ID of the apply patch tool call generated by the model." + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + "caller": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs.\n" }) - .check(Schema.isFinite()), + Schema.suspend((): Schema.Codec => BetaToolCallCallerParam).annotate({ + "description": "The execution context that produced this tool call." + }), Schema.Null ]) ), - "max_completions_tokens": Schema.optionalKey( + "status": Schema.suspend((): Schema.Codec => + BetaApplyPatchCallOutputStatusParam + ).annotate({ "description": "The status of the apply patch tool call output. One of `completed` or `failed`." }), + "output": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ - "description": "The maximum number of tokens the grader model may generate in its response.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), + Schema.String.annotate({ + "description": "Optional human-readable log text from the apply patch tool (e.g., patch results or errors)." + }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), Schema.Null ]) + ) + }).annotate({ + "title": "Apply patch tool call output", + "description": "The streamed output emitted by an apply patch tool call." + }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) ), - "reasoning_effort": Schema.optionalKey(ReasoningEffort) - }).annotate({ "description": "The sampling parameters for the model." }) - ), - "input": Schema.Array(EvalItem).annotate({ - "description": - "The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings.\n" - }), - "range": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isFinite())).annotate({ - "description": "The range of the score. Defaults to `[0, 1]`." - }) - ), - "pass_threshold": Schema.optionalKey( - Schema.Number.annotate({ "description": "The threshold for the score." }).check(Schema.isFinite()) - ) -}).annotate({ - "title": "ScoreModelGrader", - "description": "A ScoreModelGrader object that uses a model to assign a score to the input.\n" -}) -export type EvalRun = { - readonly "object": "eval.run" - readonly "id": string - readonly "eval_id": string - readonly "status": string - readonly "model": string - readonly "name": string - readonly "created_at": number - readonly "report_url": string - readonly "result_counts": { - readonly "total": number - readonly "errored": number - readonly "failed": number - readonly "passed": number - } - readonly "per_model_usage": ReadonlyArray< - { - readonly "model_name": string - readonly "invocation_count": number - readonly "prompt_tokens": number - readonly "completion_tokens": number - readonly "total_tokens": number - readonly "cached_tokens": number - } - > - readonly "per_testing_criteria_results": ReadonlyArray< - { readonly "testing_criteria": string; readonly "passed": number; readonly "failed": number } - > - readonly "data_source": { - readonly "type": "jsonl" - readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource - } | { - readonly "type": "completions" - readonly "input_messages"?: { - readonly "type": "template" - readonly "template": ReadonlyArray - } | { readonly "type": "item_reference"; readonly "item_reference": string } - readonly "sampling_params"?: { - readonly "reasoning_effort"?: ReasoningEffort - readonly "temperature"?: number - readonly "max_completion_tokens"?: number - readonly "top_p"?: number - readonly "seed"?: number - readonly "response_format"?: ResponseFormatText | ResponseFormatJsonSchema | ResponseFormatJsonObject - readonly "tools"?: ReadonlyArray - } - readonly "model"?: string - readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource | EvalStoredCompletionsSource - } | { - readonly "type": "responses" - readonly "input_messages"?: { - readonly "type": "template" - readonly "template": ReadonlyArray<{ readonly "role": string; readonly "content": string } | EvalItem> - } | { readonly "type": "item_reference"; readonly "item_reference": string } - readonly "sampling_params"?: { - readonly "reasoning_effort"?: ReasoningEffort - readonly "temperature"?: number - readonly "max_completion_tokens"?: number - readonly "top_p"?: number - readonly "seed"?: number - readonly "tools"?: ReadonlyArray - readonly "text"?: { readonly "format"?: TextResponseFormatConfiguration } - } - readonly "model"?: string - readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource | EvalResponsesSource - } - readonly "metadata": Metadata - readonly "error": EvalApiError -} -export const EvalRun = Schema.Struct({ - "object": Schema.Literal("eval.run").annotate({ "description": "The type of the object. Always \"eval.run\"." }), - "id": Schema.String.annotate({ "description": "Unique identifier for the evaluation run." }), - "eval_id": Schema.String.annotate({ "description": "The identifier of the associated evaluation." }), - "status": Schema.String.annotate({ "description": "The status of the evaluation run." }), - "model": Schema.String.annotate({ "description": "The model that is evaluated, if applicable." }), - "name": Schema.String.annotate({ "description": "The name of the evaluation run." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the evaluation run was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "report_url": Schema.String.annotate({ - "description": "The URL to the rendered evaluation run report on the UI dashboard.", - "format": "uri" - }), - "result_counts": Schema.Struct({ - "total": Schema.Number.annotate({ "description": "Total number of executed output items." }).check(Schema.isInt()), - "errored": Schema.Number.annotate({ "description": "Number of output items that resulted in an error." }).check( - Schema.isInt() - ), - "failed": Schema.Number.annotate({ "description": "Number of output items that failed to pass the evaluation." }) - .check(Schema.isInt()), - "passed": Schema.Number.annotate({ "description": "Number of output items that passed the evaluation." }).check( - Schema.isInt() - ) - }).annotate({ "description": "Counters summarizing the outcomes of the evaluation run." }), - "per_model_usage": Schema.Array(Schema.Struct({ - "model_name": Schema.String.annotate({ "description": "The name of the model." }), - "invocation_count": Schema.Number.annotate({ "description": "The number of invocations." }).check(Schema.isInt()), - "prompt_tokens": Schema.Number.annotate({ "description": "The number of prompt tokens used." }).check( - Schema.isInt() - ), - "completion_tokens": Schema.Number.annotate({ "description": "The number of completion tokens generated." }).check( - Schema.isInt() - ), - "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check(Schema.isInt()), - "cached_tokens": Schema.Number.annotate({ "description": "The number of tokens retrieved from cache." }).check( - Schema.isInt() - ) - })).annotate({ "description": "Usage statistics for each model during the evaluation run." }), - "per_testing_criteria_results": Schema.Array(Schema.Struct({ - "testing_criteria": Schema.String.annotate({ "description": "A description of the testing criteria." }), - "passed": Schema.Number.annotate({ "description": "Number of tests passed for this criteria." }).check( - Schema.isInt() - ), - "failed": Schema.Number.annotate({ "description": "Number of tests failed for this criteria." }).check( - Schema.isInt() - ) - })).annotate({ "description": "Results per testing criteria applied during the evaluation run." }), - "data_source": Schema.Union([ + "type": Schema.Literal("mcp_list_tools").annotate({ + "description": "The type of the item. Always `mcp_list_tools`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the list.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server.\n" }), + "tools": Schema.Array(BetaMCPListToolsTool).annotate({ "description": "The tools available on the server.\n" }), + "error": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Error message if the server could not list tools.\n" }), + Schema.Null + ]) + ) + }).annotate({ "title": "MCP list tools", "description": "A list of tools available on an MCP server.\n" }), Schema.Struct({ - "type": Schema.Literal("jsonl").annotate({ "description": "The type of data source. Always `jsonl`." }), - "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource], { mode: "oneOf" }).annotate({ - "description": "Determines what populates the `item` namespace in the data source." - }) - }).annotate({ "title": "JsonlRunDataSource", "description": "Information about the run's data source." }), + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("mcp_approval_request").annotate({ + "description": "The type of the item. Always `mcp_approval_request`.\n" + }), + "id": Schema.String.annotate({ "description": "The unique ID of the approval request.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server making the request.\n" }), + "name": Schema.String.annotate({ "description": "The name of the tool to run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of arguments for the tool.\n" }) + }).annotate({ + "title": "MCP approval request", + "description": "A request for human approval of a tool invocation.\n" + }), Schema.Struct({ - "type": Schema.Literal("completions").annotate({ - "description": "The type of run data source. Always `completions`." + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("mcp_approval_response").annotate({ + "description": "The type of the item. Always `mcp_approval_response`.\n" }), - "input_messages": Schema.optionalKey( + "id": Schema.optionalKey( Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("template").annotate({ - "description": "The type of input messages. Always `template`." - }), - "template": Schema.Array(Schema.Union([EasyInputMessage, EvalItem], { mode: "oneOf" })).annotate({ - "description": - "A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." - }) - }).annotate({ "title": "TemplateInputMessages" }), - Schema.Struct({ - "type": Schema.Literal("item_reference").annotate({ - "description": "The type of input messages. Always `item_reference`." - }), - "item_reference": Schema.String.annotate({ - "description": "A reference to a variable in the `item` namespace. Ie, \"item.input_trajectory\"" - }) - }).annotate({ "title": "ItemReferenceInputMessages" }) - ], { mode: "oneOf" }).annotate({ - "description": - "Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace." + Schema.String.annotate({ "description": "The unique ID of the approval response\n" }), + Schema.Null + ]) + ), + "approval_request_id": Schema.String.annotate({ + "description": "The ID of the approval request being answered.\n" + }), + "approve": Schema.Boolean.annotate({ "description": "Whether the request was approved.\n" }), + "reason": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "Optional reason for the decision.\n" }), Schema.Null]) + ), + "request_id": Schema.Json.annotate({ "expected": "JSON value" }) + }).annotate({ "title": "MCP approval response", "description": "A response to an MCP approval request.\n" }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("mcp_call").annotate({ "description": "The type of the item. Always `mcp_call`.\n" }), + "id": Schema.String.annotate({ "description": "The unique ID of the tool call.\n" }), + "server_label": Schema.String.annotate({ "description": "The label of the MCP server running the tool.\n" }), + "name": Schema.String.annotate({ "description": "The name of the tool that was run.\n" }), + "arguments": Schema.String.annotate({ "description": "A JSON string of the arguments passed to the tool.\n" }), + "output": Schema.optionalKey( + Schema.Union([Schema.String.annotate({ "description": "The output from the tool call.\n" }), Schema.Null]) + ), + "error": Schema.optionalKey( + Schema.Union([BetaMCPToolCallError, Schema.Null]).annotate({ + "description": "The error from the tool call, if any." }) ), - "sampling_params": Schema.optionalKey(Schema.Struct({ - "reasoning_effort": Schema.optionalKey(ReasoningEffort), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs." }).check( - Schema.isFinite() - ) - ), - "max_completion_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum number of tokens in the generated output." }).check( - Schema.isInt() - ) - ), - "top_p": Schema.optionalKey( - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens." - }).check(Schema.isFinite()) - ), - "seed": Schema.optionalKey( - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling." }) - .check(Schema.isInt()) - ), - "response_format": Schema.optionalKey( - Schema.Union([ResponseFormatText, ResponseFormatJsonSchema, ResponseFormatJsonObject], { mode: "oneOf" }) - .annotate({ - "description": - "An object specifying the format that the model must output.\n\nSetting to `{ \"type\": \"json_schema\", \"json_schema\": {...} }` enables\nStructured Outputs which ensures the model will match your supplied JSON\nschema. Learn more in the [Structured Outputs\nguide](/docs/guides/structured-outputs).\n\nSetting to `{ \"type\": \"json_object\" }` enables the older JSON mode, which\nensures the message the model generates is valid JSON. Using `json_schema`\nis preferred for models that support it.\n" - }) - ), - "tools": Schema.optionalKey( - Schema.Array(ChatCompletionTool).annotate({ - "description": - "A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. A max of 128 functions are supported.\n" - }) - ) - })), - "model": Schema.optionalKey( - Schema.String.annotate({ - "description": "The name of the model to use for generating completions (e.g. \"o3-mini\")." + "status": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaMCPToolCallStatus).annotate({ + "description": + "The status of the tool call. One of `in_progress`, `completed`, `incomplete`, `calling`, or `failed`.\n" }) ), - "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource, EvalStoredCompletionsSource], { - mode: "oneOf" - }).annotate({ "description": "Determines what populates the `item` namespace in this run's data source." }) - }).annotate({ "title": "CompletionsRunDataSource", "description": "Information about the run's data source." }), + "approval_request_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "Unique identifier for the MCP tool call approval request.\nInclude this value in a subsequent `mcp_approval_response` input to approve or reject the corresponding tool call.\n" + }), + Schema.Null + ]) + ) + }).annotate({ "title": "MCP tool call", "description": "An invocation of a tool on an MCP server.\n" }), Schema.Struct({ - "type": Schema.Literal("responses").annotate({ - "description": "The type of run data source. Always `responses`." + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) + ), + "type": Schema.Literal("custom_tool_call_output").annotate({ + "description": "The type of the custom tool call output. Always `custom_tool_call_output`.\n" }), - "input_messages": Schema.optionalKey( - Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("template").annotate({ - "description": "The type of input messages. Always `template`." - }), - "template": Schema.Array( - Schema.Union([ - Schema.Struct({ - "role": Schema.String.annotate({ - "description": "The role of the message (e.g. \"system\", \"assistant\", \"user\")." - }), - "content": Schema.String.annotate({ "description": "The content of the message." }) - }).annotate({ "title": "ChatMessage" }), - EvalItem - ], { mode: "oneOf" }) - ).annotate({ - "description": - "A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." - }) - }).annotate({ "title": "InputMessagesTemplate" }), - Schema.Struct({ - "type": Schema.Literal("item_reference").annotate({ - "description": "The type of input messages. Always `item_reference`." - }), - "item_reference": Schema.String.annotate({ - "description": "A reference to a variable in the `item` namespace. Ie, \"item.name\"" - }) - }).annotate({ "title": "InputMessagesItemReference" }) - ], { mode: "oneOf" }).annotate({ - "description": - "Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace." + "id": Schema.optionalKey( + Schema.String.annotate({ + "description": "The unique ID of the custom tool call output in the OpenAI platform.\n" }) ), - "sampling_params": Schema.optionalKey(Schema.Struct({ - "reasoning_effort": Schema.optionalKey(ReasoningEffort), - "temperature": Schema.optionalKey( - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs." }).check( - Schema.isFinite() - ) - ), - "max_completion_tokens": Schema.optionalKey( - Schema.Number.annotate({ "description": "The maximum number of tokens in the generated output." }).check( - Schema.isInt() - ) - ), - "top_p": Schema.optionalKey( - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens." - }).check(Schema.isFinite()) - ), - "seed": Schema.optionalKey( - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling." }) - .check(Schema.isInt()) - ), - "tools": Schema.optionalKey( - Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nThe two categories of tools you can provide the model are:\n\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code. Learn more about\n [function calling](/docs/guides/function-calling).\n" - }) - ), - "text": Schema.optionalKey( - Schema.Struct({ "format": Schema.optionalKey(TextResponseFormatConfiguration) }).annotate({ - "description": - "Configuration options for a text response from the model. Can be plain\ntext or structured JSON data. Learn more:\n- [Text inputs and outputs](/docs/guides/text)\n- [Structured Outputs](/docs/guides/structured-outputs)\n" - }) - ) - })), - "model": Schema.optionalKey( + "call_id": Schema.String.annotate({ + "description": "The call ID, used to map this custom tool call output to a custom tool call.\n" + }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCallerParam, Schema.Null])), + "output": Schema.Union([ Schema.String.annotate({ - "description": "The name of the model to use for generating completions (e.g. \"o3-mini\")." + "title": "string output", + "description": "A string of the output of the custom tool call.\n" + }), + Schema.Array(BetaFunctionAndCustomToolCallOutput).annotate({ + "title": "output content list", + "description": "Text, image, or file output of the custom tool call.\n" }) + ], { mode: "oneOf" }).annotate({ + "description": + "The output from the custom tool call generated by your code.\nCan be a string or an list of output content.\n" + }) + }).annotate({ + "title": "Custom tool call output", + "description": "The output of a custom tool call from your code, being sent back to the model.\n" + }), + Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ "description": "The agent that produced this item." }) ), - "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource, EvalResponsesSource], { - mode: "oneOf" - }).annotate({ "description": "Determines what populates the `item` namespace in this run's data source." }) - }).annotate({ "title": "ResponsesRunDataSource", "description": "Information about the run's data source." }) - ], { mode: "oneOf" }), - "metadata": Metadata, - "error": EvalApiError -}).annotate({ "title": "EvalRun", "description": "A schema representing an evaluation run.\n" }) -export type GraderLabelModel = { + "type": Schema.Literal("custom_tool_call").annotate({ + "description": "The type of the custom tool call. Always `custom_tool_call`.\n" + }), + "id": Schema.optionalKey( + Schema.String.annotate({ "description": "The unique ID of the custom tool call in the OpenAI platform.\n" }) + ), + "call_id": Schema.String.annotate({ + "description": "An identifier used to map this custom tool call to a tool call output.\n" + }), + "caller": Schema.optionalKey(Schema.Union([BetaToolCallCaller, Schema.Null])), + "namespace": Schema.optionalKey( + Schema.String.annotate({ "description": "The namespace of the custom tool being called.\n" }) + ), + "name": Schema.String.annotate({ "description": "The name of the custom tool being called.\n" }), + "input": Schema.String.annotate({ + "description": "The input for the custom tool call generated by the model.\n" + }), + "async": Schema.optionalKey( + Schema.Boolean.annotate({ "description": "Whether the custom tool call runs asynchronously.\n" }) + ) + }).annotate({ "title": "Custom tool call", "description": "A call to a custom tool created by the model.\n" }) + ], { mode: "oneOf" }).annotate({ + "description": + "An item representing part of the context for the response to be\ngenerated by the model. Can contain text, images, and audio inputs,\nas well as previous assistant responses and tool call outputs.\n", + "title": "Item" + }), + BetaCompactionTriggerItemParam, + BetaItemReferenceParam, + BetaProgramItemParam, + BetaProgramOutputItemParam +], { mode: "oneOf" }).annotate({ "identifier": "BetaInputItem" }) +export type AssistantStreamEvent = + | ThreadStreamEvent + | RunStreamEvent + | RunStepStreamEvent + | MessageStreamEvent + | ErrorEvent + | DoneEvent +export const AssistantStreamEvent = Schema.Union([ + ThreadStreamEvent, + RunStreamEvent, + RunStepStreamEvent, + MessageStreamEvent, + ErrorEvent, + DoneEvent +], { mode: "oneOf" }).annotate({ + "description": + "Represents an event emitted when streaming a Run.\n\nEach event in a server-sent events stream has an `event` and `data` property:\n\n```\nevent: thread.created\ndata: {\"id\": \"thread_123\", \"object\": \"thread\", ...}\n```\n\nWe emit events whenever a new object is created, transitions to a new state, or is being\nstreamed in parts (deltas). For example, we emit `thread.run.created` when a new run\nis created, `thread.run.completed` when a run completes, and so on. When an Assistant chooses\nto create a message during a run, we emit a `thread.message.created event`, a\n`thread.message.in_progress` event, many `thread.message.delta` events, and finally a\n`thread.message.completed` event.\n\nWe may add additional events over time, so we recommend handling unknown events gracefully\nin your code. See the [Assistants API quickstart](https://developers.openai.com/api/docs/assistants/migration) to learn how to\nintegrate the Assistants API with streaming.\n", + "identifier": "AssistantStreamEvent" +}) +export type EvalGraderLabelModel = { readonly "type": "label_model" readonly "name": string readonly "model": string @@ -24282,7 +41814,7 @@ export type GraderLabelModel = { readonly "labels": ReadonlyArray readonly "passing_labels": ReadonlyArray } -export const GraderLabelModel = Schema.Struct({ +export const EvalGraderLabelModel = Schema.Struct({ "type": Schema.Literal("label_model").annotate({ "description": "The object type, which is always `label_model`." }), "name": Schema.String.annotate({ "description": "The name of the grader." }), "model": Schema.String.annotate({ @@ -24297,9 +41829,10 @@ export const GraderLabelModel = Schema.Struct({ }) }).annotate({ "title": "LabelModelGrader", - "description": "A LabelModelGrader object which uses a model to assign labels to each item\nin the evaluation.\n" + "description": "A LabelModelGrader object which uses a model to assign labels to each item\nin the evaluation.\n", + "identifier": "EvalGraderLabelModel" }) -export type GraderScoreModel = { +export type EvalGraderScoreModel = { readonly "type": "score_model" readonly "name": string readonly "model": string @@ -24312,8 +41845,9 @@ export type GraderScoreModel = { } readonly "input": ReadonlyArray readonly "range"?: ReadonlyArray + readonly "pass_threshold"?: number } -export const GraderScoreModel = Schema.Struct({ +export const EvalGraderScoreModel = Schema.Struct({ "type": Schema.Literal("score_model").annotate({ "description": "The object type, which is always `score_model`." }), "name": Schema.String.annotate({ "description": "The name of the grader." }), "model": Schema.String.annotate({ "description": "The model to use for the evaluation." }), @@ -24322,7 +41856,7 @@ export const GraderScoreModel = Schema.Struct({ "seed": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling.\n" }) - .check(Schema.isInt()), + .check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ), @@ -24330,14 +41864,14 @@ export const GraderScoreModel = Schema.Struct({ Schema.Union([ Schema.Number.annotate({ "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens.\n" - }).check(Schema.isFinite()), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), Schema.Null ]) ), "temperature": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs.\n" }) - .check(Schema.isFinite()), + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), Schema.Null ]) ), @@ -24345,7 +41879,9 @@ export const GraderScoreModel = Schema.Struct({ Schema.Union([ Schema.Number.annotate({ "description": "The maximum number of tokens the grader model may generate in its response.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ), Schema.Null ]) ), @@ -24357,253 +41893,321 @@ export const GraderScoreModel = Schema.Struct({ "The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings.\n" }), "range": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isFinite())).annotate({ - "description": "The range of the score. Defaults to `[0, 1]`." + Schema.Array(Schema.Finite).annotate({ + "description": "The service requires two numbers for the score range. Defaults to `[0, 1]`.\n" }) + ), + "pass_threshold": Schema.optionalKey( + Schema.Number.annotate({ "description": "The threshold for the score." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) ) -}).annotate({ - "title": "ScoreModelGrader", - "description": "A ScoreModelGrader object that uses a model to assign a score to the input.\n" -}) -export type InputParam = string | ReadonlyArray -export const InputParam = Schema.Union([ - Schema.String.annotate({ - "title": "Text input", - "description": "A text input to the model, equivalent to a text input with the\n`user` role.\n" - }), - Schema.Array(InputItem).annotate({ - "title": "Input item list", - "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" - }) +}).annotate({ "title": "ScoreModelGrader", "identifier": "EvalGraderScoreModel" }) +export type CreateEvalItem = { readonly "role": string; readonly "content": string } | EvalItem +export const CreateEvalItem = Schema.Union([ + Schema.Struct({ + "role": Schema.String.annotate({ + "description": "The role of the message (e.g. \"system\", \"assistant\", \"user\")." + }), + "content": Schema.String.annotate({ "description": "The content of the message." }) + }).annotate({ "title": "SimpleInputMessage" }), + EvalItem ], { mode: "oneOf" }).annotate({ + "title": "CreateEvalItem", "description": - "Text, image, or file inputs to the model, used to generate a response.\n\nLearn more:\n- [Text inputs and outputs](/docs/guides/text)\n- [Image inputs](/docs/guides/images)\n- [File inputs](/docs/guides/pdf-files)\n- [Conversation state](/docs/guides/conversation-state)\n- [Function calling](/docs/guides/function-calling)\n" -}) -export type CreateConversationBody = { - readonly "metadata"?: {} | null | null - readonly "items"?: ReadonlyArray | null -} -export const CreateConversationBody = Schema.Struct({ - "metadata": Schema.optionalKey(Schema.Union([ - Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard.\n Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters." - }), - Schema.Null - ])), - "items": Schema.optionalKey( - Schema.Union([ - Schema.Array(InputItem).annotate({ - "description": "Initial items to include in the conversation context. You may add up to 20 items at a time." - }).check(Schema.isMaxLength(20)), - Schema.Null - ]) - ) + "A chat message that makes up the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}.", + "identifier": "CreateEvalItem" }) -export type TokenCountsBody = { - readonly "model"?: string | null - readonly "input"?: string | ReadonlyArray | null - readonly "previous_response_id"?: string | null - readonly "tools"?: ReadonlyArray | null - readonly "text"?: ResponseTextParam | null - readonly "reasoning"?: { - readonly "effort"?: ReasoningEffort - readonly "summary"?: "auto" | "concise" | "detailed" | null - readonly "generate_summary"?: "auto" | "concise" | "detailed" | null - } | null - readonly "truncation"?: "auto" | "disabled" - readonly "instructions"?: string | null - readonly "conversation"?: ConversationParam | null - readonly "tool_choice"?: - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam - | null - readonly "parallel_tool_calls"?: boolean | null +export type CreateEvalCompletionsRunDataSource = { + readonly "type": "completions" + readonly "input_messages"?: { + readonly "type": "template" + readonly "template": ReadonlyArray + } | { readonly "type": "item_reference"; readonly "item_reference": string } + readonly "sampling_params"?: { + readonly "reasoning_effort"?: ReasoningEffort + readonly "temperature"?: number + readonly "max_completion_tokens"?: number + readonly "top_p"?: number + readonly "seed"?: number + readonly "response_format"?: ResponseFormatText | ResponseFormatJsonSchema | ResponseFormatJsonObject + readonly "tools"?: ReadonlyArray + } + readonly "model"?: string + readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource | EvalStoredCompletionsSource } -export const TokenCountsBody = Schema.Struct({ - "model": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](/docs/models) to browse and compare available models." - }), - Schema.Null - ]) - ), - "input": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.String.annotate({ - "description": "A text input to the model, equivalent to a text input with the `user` role." - }).check(Schema.isMaxLength(10485760)), - Schema.Array(InputItem).annotate({ - "description": "A list of one or many input items to the model, containing different content types." - }) - ], { mode: "oneOf" }).annotate({ - "description": "Text, image, or file inputs to the model, used to generate a response" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`." - }), - Schema.Null - ]) - ), - "tools": Schema.optionalKey( +export const CreateEvalCompletionsRunDataSource = Schema.Struct({ + "type": Schema.Literal("completions").annotate({ + "description": "The type of run data source. Always `completions`." + }), + "input_messages": Schema.optionalKey( Schema.Union([ - Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter." - }), - Schema.Null - ]) - ), - "text": Schema.optionalKey(Schema.Union([ResponseTextParam, Schema.Null])), - "reasoning": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "effort": Schema.optionalKey(ReasoningEffort), - "summary": Schema.optionalKey(Schema.Union([ - Schema.Literals(["auto", "concise", "detailed"]).annotate({ + Schema.Struct({ + "type": Schema.Literal("template").annotate({ + "description": "The type of input messages. Always `template`." + }), + "template": Schema.Array(Schema.Union([EasyInputMessage, EvalItem], { mode: "oneOf" })).annotate({ "description": - "A summary of the reasoning performed by the model. This can be\nuseful for debugging and understanding the model's reasoning process.\nOne of `auto`, `concise`, or `detailed`.\n\n`concise` is supported for `computer-use-preview` models and all reasoning models after `gpt-5`.\n" + "A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." + }) + }).annotate({ "title": "TemplateInputMessages" }), + Schema.Struct({ + "type": Schema.Literal("item_reference").annotate({ + "description": "The type of input messages. Always `item_reference`." }), - Schema.Null - ])), - "generate_summary": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["auto", "concise", "detailed"]).annotate({ - "description": - "**Deprecated:** use `summary` instead.\n\nA summary of the reasoning performed by the model. This can be\nuseful for debugging and understanding the model's reasoning process.\nOne of `auto`, `concise`, or `detailed`.\n" - }), - Schema.Null - ]) - ) - }).annotate({ - "title": "Reasoning", - "description": - "**gpt-5 and o-series models only** Configuration options for [reasoning models](https://platform.openai.com/docs/guides/reasoning)." - }), - Schema.Null - ])), - "truncation": Schema.optionalKey( - Schema.Literals(["auto", "disabled"]).annotate({ + "item_reference": Schema.String.annotate({ + "description": "A reference to a variable in the `item` namespace. Ie, \"item.input_trajectory\"" + }) + }).annotate({ "title": "ItemReferenceInputMessages" }) + ], { mode: "oneOf" }).annotate({ "description": - "The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error." + "Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace." }) ), - "instructions": Schema.optionalKey(Schema.Union([ + "sampling_params": Schema.optionalKey(Schema.Struct({ + "reasoning_effort": Schema.optionalKey(ReasoningEffort), + "temperature": Schema.optionalKey( + Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) + ), + "max_completion_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum number of tokens in the generated output." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "top_p": Schema.optionalKey( + Schema.Number.annotate({ + "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "seed": Schema.optionalKey( + Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "response_format": Schema.optionalKey( + Schema.Union([ResponseFormatText, ResponseFormatJsonSchema, ResponseFormatJsonObject], { mode: "oneOf" }) + .annotate({ + "description": + "An object specifying the format that the model must output.\n\nSetting to `{ \"type\": \"json_schema\", \"json_schema\": {...} }` enables\nStructured Outputs which ensures the model will match your supplied JSON\nschema. Learn more in the [Structured Outputs\nguide](https://developers.openai.com/api/docs/guides/structured-outputs).\n\nSetting to `{ \"type\": \"json_object\" }` enables the older JSON mode, which\nensures the message the model generates is valid JSON. Using `json_schema`\nis preferred for models that support it.\n" + }) + ), + "tools": Schema.optionalKey( + Schema.Array(ChatCompletionTool).annotate({ + "description": + "A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. A max of 128 functions are supported.\n" + }) + ) + })), + "model": Schema.optionalKey( Schema.String.annotate({ - "description": - "A system (or developer) message inserted into the model's context.\nWhen used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses." - }), - Schema.Null - ])), - "conversation": Schema.optionalKey(Schema.Union([ConversationParam, Schema.Null])), - "tool_choice": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam - ], { mode: "oneOf" }).annotate({ "description": "Controls which tool the model should use, if any." }), - Schema.Null - ]) + "description": "The name of the model to use for generating completions (e.g. \"o3-mini\")." + }) ), - "parallel_tool_calls": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ "description": "Whether to allow the model to run tool calls in parallel." }), - Schema.Null - ]) - ) + "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource, EvalStoredCompletionsSource], { + mode: "oneOf" + }).annotate({ "description": "Determines what populates the `item` namespace in this run's data source." }) +}).annotate({ + "title": "CompletionsRunDataSource", + "description": "A CompletionsRunDataSource object describing a model sampling configuration.\n", + "identifier": "CreateEvalCompletionsRunDataSource" }) -export type CompactResponseMethodPublicBody = { - readonly "model": ModelIdsCompaction - readonly "input"?: string | ReadonlyArray | null - readonly "previous_response_id"?: string | null - readonly "instructions"?: string | null - readonly "prompt_cache_key"?: string | null - readonly "prompt_cache_retention"?: "in_memory" | "in-memory" | "24h" | null - readonly "service_tier"?: "auto" | "default" | "flex" | "priority" | null +export type CreateEvalResponsesRunDataSource = { + readonly "type": "responses" + readonly "input_messages"?: { + readonly "type": "template" + readonly "template": ReadonlyArray<{ readonly "role": string; readonly "content": string } | EvalItem> + } | { readonly "type": "item_reference"; readonly "item_reference": string } + readonly "sampling_params"?: { + readonly "reasoning_effort"?: ReasoningEffort + readonly "temperature"?: number + readonly "max_completion_tokens"?: number + readonly "top_p"?: number + readonly "seed"?: number + readonly "tools"?: ReadonlyArray + readonly "text"?: { readonly "format"?: TextResponseFormatConfiguration } + } + readonly "model"?: string + readonly "source": EvalJsonlFileContentSource | EvalJsonlFileIdSource | EvalResponsesSource } -export const CompactResponseMethodPublicBody = Schema.Struct({ - "model": ModelIdsCompaction, - "input": Schema.optionalKey( +export const CreateEvalResponsesRunDataSource = Schema.Struct({ + "type": Schema.Literal("responses").annotate({ "description": "The type of run data source. Always `responses`." }), + "input_messages": Schema.optionalKey( Schema.Union([ - Schema.Union([ - Schema.String.annotate({ - "description": "A text input to the model, equivalent to a text input with the `user` role." - }).check(Schema.isMaxLength(10485760)), - Schema.Array(InputItem).annotate({ - "description": "A list of one or many input items to the model, containing different content types." + Schema.Struct({ + "type": Schema.Literal("template").annotate({ + "description": "The type of input messages. Always `template`." + }), + "template": Schema.Array( + Schema.Union([ + Schema.Struct({ + "role": Schema.String.annotate({ + "description": "The role of the message (e.g. \"system\", \"assistant\", \"user\")." + }), + "content": Schema.String.annotate({ "description": "The content of the message." }) + }).annotate({ "title": "ChatMessage" }), + EvalItem + ], { mode: "oneOf" }) + ).annotate({ + "description": + "A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." }) - ], { mode: "oneOf" }).annotate({ - "description": "Text, image, or file inputs to the model, used to generate a response" - }), - Schema.Null - ]) + }).annotate({ "title": "InputMessagesTemplate" }), + Schema.Struct({ + "type": Schema.Literal("item_reference").annotate({ + "description": "The type of input messages. Always `item_reference`." + }), + "item_reference": Schema.String.annotate({ + "description": "A reference to a variable in the `item` namespace. Ie, \"item.name\"" + }) + }).annotate({ "title": "InputMessagesItemReference" }) + ], { mode: "oneOf" }).annotate({ + "description": + "Used when sampling from a model. Dictates the structure of the messages passed into the model. Can either be a reference to a prebuilt trajectory (ie, `item.input_trajectory`), or a template with variable references to the `item` namespace." + }) ), - "previous_response_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ + "sampling_params": Schema.optionalKey(Schema.Struct({ + "reasoning_effort": Schema.optionalKey(ReasoningEffort), + "temperature": Schema.optionalKey( + Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs." }).check( + Schema.isFinite().annotate({ "expected": "a finite number" }) + ) + ), + "max_completion_tokens": Schema.optionalKey( + Schema.Number.annotate({ "description": "The maximum number of tokens in the generated output." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "top_p": Schema.optionalKey( + Schema.Number.annotate({ + "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens." + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })) + ), + "seed": Schema.optionalKey( + Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + ), + "tools": Schema.optionalKey( + Schema.Array(Tool).annotate({ "description": - "The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`." - }), - Schema.Null - ]) - ), - "instructions": Schema.optionalKey(Schema.Union([ + "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nThe two categories of tools you can provide the model are:\n\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](https://developers.openai.com/api/docs/guides/tools-web-search)\n or [file search](https://developers.openai.com/api/docs/guides/tools-file-search). Learn more about\n [built-in tools](https://developers.openai.com/api/docs/guides/tools).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code. Learn more about\n [function calling](https://developers.openai.com/api/docs/guides/function-calling).\n" + }) + ), + "text": Schema.optionalKey( + Schema.Struct({ "format": Schema.optionalKey(TextResponseFormatConfiguration) }).annotate({ + "description": + "Configuration options for a text response from the model. Can be plain\ntext or structured JSON data. Learn more:\n- [Text inputs and outputs](https://developers.openai.com/api/docs/guides/text)\n- [Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs)\n" + }) + ) + })), + "model": Schema.optionalKey( Schema.String.annotate({ - "description": - "A system (or developer) message inserted into the model's context.\nWhen used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses." - }), - Schema.Null - ])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ "description": "A key to use when reading from or writing to the prompt cache." }).check( - Schema.isMaxLength(64) - ), - Schema.Null - ]) + "description": "The name of the model to use for generating completions (e.g. \"o3-mini\")." + }) ), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in-memory", "24h"]).annotate({ - "description": "How long to retain a prompt cache entry created by this request." - }), - Schema.Null - ]) + "source": Schema.Union([EvalJsonlFileContentSource, EvalJsonlFileIdSource, EvalResponsesSource], { mode: "oneOf" }) + .annotate({ "description": "Determines what populates the `item` namespace in this run's data source." }) +}).annotate({ + "title": "ResponsesRunDataSource", + "description": "A ResponsesRunDataSource object describing a model sampling configuration.\n", + "identifier": "CreateEvalResponsesRunDataSource" +}) +export type GraderScoreModel = { + readonly "type": "score_model" + readonly "name": string + readonly "model": string + readonly "sampling_params"?: { + readonly "seed"?: number | null + readonly "top_p"?: number | null + readonly "temperature"?: number | null + readonly "max_completions_tokens"?: number | null + readonly "reasoning_effort"?: ReasoningEffort + } + readonly "input": ReadonlyArray + readonly "range"?: ReadonlyArray +} +export const GraderScoreModel = Schema.Struct({ + "type": Schema.Literal("score_model").annotate({ "description": "The object type, which is always `score_model`." }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "model": Schema.String.annotate({ "description": "The model to use for the evaluation." }), + "sampling_params": Schema.optionalKey( + Schema.Struct({ + "seed": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling.\n" }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ), + "top_p": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + Schema.Null + ]) + ), + "temperature": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs.\n" }) + .check(Schema.isFinite().annotate({ "expected": "a finite number" })), + Schema.Null + ]) + ), + "max_completions_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": "The maximum number of tokens the grader model may generate in its response.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ), + Schema.Null + ]) + ), + "reasoning_effort": Schema.optionalKey(ReasoningEffort) + }).annotate({ "description": "The sampling parameters for the model." }) ), - "service_tier": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["auto", "default", "flex", "priority"]).annotate({ - "description": "The service tier to use for this request." - }), - Schema.Null - ]) + "input": Schema.Array(EvalItem).annotate({ + "description": + "The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings.\n" + }), + "range": Schema.optionalKey( + Schema.Array(Schema.Finite).annotate({ + "description": "The service requires two numbers for the score range. Defaults to `[0, 1]`.\n" + }) ) +}).annotate({ + "title": "ScoreModelGrader", + "description": "A ScoreModelGrader object that uses a model to assign a score to the input.\n", + "identifier": "GraderScoreModel" +}) +export type GraderLabelModel = { + readonly "type": "label_model" + readonly "name": string + readonly "model": string + readonly "input": ReadonlyArray + readonly "labels": ReadonlyArray + readonly "passing_labels": ReadonlyArray +} +export const GraderLabelModel = Schema.Struct({ + "type": Schema.Literal("label_model").annotate({ "description": "The object type, which is always `label_model`." }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "model": Schema.String.annotate({ + "description": "The model to use for the evaluation. Must support structured outputs." + }), + "input": Schema.Array(EvalItem), + "labels": Schema.Array(Schema.String).annotate({ + "description": "The labels to assign to each item in the evaluation." + }), + "passing_labels": Schema.Array(Schema.String).annotate({ + "description": "The labels that indicate a passing result. Must be a subset of labels." + }) +}).annotate({ + "title": "LabelModelGrader", + "description": "A LabelModelGrader object which uses a model to assign labels to each item\nin the evaluation.\n", + "identifier": "GraderLabelModel" }) export type ConversationItem = | Message @@ -24616,7 +42220,11 @@ export type ConversationItem = | ComputerToolCallOutputResource | ToolSearchCall | ToolSearchOutput + | AdditionalTools + | ResponseConfigurationUpdate | ReasoningItem + | Program + | ProgramOutput | CompactionBody | CodeInterpreterToolCall | LocalShellToolCall @@ -24637,13 +42245,81 @@ export const ConversationItem = Schema.Union([ FunctionToolCallOutputResource, FileSearchToolCall, WebSearchToolCall, - ImageGenToolCall, + ImageGenToolCall, + ComputerToolCall, + ComputerToolCallOutputResource, + ToolSearchCall, + ToolSearchOutput, + AdditionalTools, + ResponseConfigurationUpdate, + ReasoningItem, + Program, + ProgramOutput, + CompactionBody, + CodeInterpreterToolCall, + LocalShellToolCall, + LocalShellToolCallOutput, + FunctionShellCall, + FunctionShellCallOutput, + ApplyPatchToolCall, + ApplyPatchToolCallOutput, + MCPListTools, + MCPApprovalRequest, + MCPApprovalResponseResource, + MCPToolCall, + CustomToolCall, + CustomToolCallOutput +], { mode: "oneOf" }).annotate({ + "title": "Conversation item", + "description": + "A single item within a conversation. The set of possible types are the same as the `output` type of a [Response object](https://developers.openai.com/api/reference/resources/responses#%28resource%29%20responses%20%3E%20%28model%29%20response%20%3E%20%28schema%29%20%3E%20%28property%29%20output).", + "identifier": "ConversationItem" +}) +export type OutputItem = + | OutputMessage + | FileSearchToolCall + | FunctionToolCall + | FunctionToolCallOutputResource + | WebSearchToolCall + | ComputerToolCall + | ComputerToolCallOutputResource + | ReasoningItem + | Program + | ProgramOutput + | ToolSearchCall + | ToolSearchOutput + | AdditionalTools + | CompactionBody + | ImageGenToolCall + | CodeInterpreterToolCall + | LocalShellToolCall + | LocalShellToolCallOutput + | FunctionShellCall + | FunctionShellCallOutput + | ApplyPatchToolCall + | ApplyPatchToolCallOutput + | MCPToolCall + | MCPListTools + | MCPApprovalRequest + | MCPApprovalResponseResource + | CustomToolCall + | CustomToolCallOutputResource +export const OutputItem = Schema.Union([ + OutputMessage, + FileSearchToolCall, + FunctionToolCall, + FunctionToolCallOutputResource, + WebSearchToolCall, ComputerToolCall, ComputerToolCallOutputResource, + ReasoningItem, + Program, + ProgramOutput, ToolSearchCall, ToolSearchOutput, - ReasoningItem, + AdditionalTools, CompactionBody, + ImageGenToolCall, CodeInterpreterToolCall, LocalShellToolCall, LocalShellToolCallOutput, @@ -24651,17 +42327,13 @@ export const ConversationItem = Schema.Union([ FunctionShellCallOutput, ApplyPatchToolCall, ApplyPatchToolCallOutput, + MCPToolCall, MCPListTools, MCPApprovalRequest, MCPApprovalResponseResource, - MCPToolCall, CustomToolCall, - CustomToolCallOutput -], { mode: "oneOf" }).annotate({ - "title": "Conversation item", - "description": - "A single item within a conversation. The set of possible types are the same as the `output` type of a [Response object](/docs/api-reference/responses/object#responses/object-output)." -}) + CustomToolCallOutputResource +], { mode: "oneOf" }).annotate({ "identifier": "OutputItem" }) export type ItemResource = | InputMessageResource | OutputMessage @@ -24673,7 +42345,11 @@ export type ItemResource = | FunctionToolCallOutputResource | ToolSearchCall | ToolSearchOutput + | AdditionalTools + | ResponseConfigurationUpdate | ReasoningItem + | Program + | ProgramOutput | CompactionBody | ImageGenToolCall | CodeInterpreterToolCall @@ -24700,7 +42376,11 @@ export const ItemResource = Schema.Union([ FunctionToolCallOutputResource, ToolSearchCall, ToolSearchOutput, + AdditionalTools, + ResponseConfigurationUpdate, ReasoningItem, + Program, + ProgramOutput, CompactionBody, ImageGenToolCall, CodeInterpreterToolCall, @@ -24716,20 +42396,26 @@ export const ItemResource = Schema.Union([ MCPToolCall, CustomToolCallResource, CustomToolCallOutputResource -], { mode: "oneOf" }).annotate({ "description": "Content item used to generate a response.\n" }) -export type OutputItem = - | OutputMessage - | FileSearchToolCall +], { mode: "oneOf" }).annotate({ + "description": "Content item used to generate a response.\n", + "identifier": "ItemResource" +}) +export type ItemField = + | Message + | Program + | ProgramOutput | FunctionToolCall - | FunctionToolCallOutputResource + | ToolSearchCall + | ToolSearchOutput + | AdditionalTools + | FunctionToolCallOutput + | FileSearchToolCall | WebSearchToolCall + | ImageGenToolCall | ComputerToolCall | ComputerToolCallOutputResource | ReasoningItem - | ToolSearchCall - | ToolSearchOutput | CompactionBody - | ImageGenToolCall | CodeInterpreterToolCall | LocalShellToolCall | LocalShellToolCallOutput @@ -24737,25 +42423,28 @@ export type OutputItem = | FunctionShellCallOutput | ApplyPatchToolCall | ApplyPatchToolCallOutput - | MCPToolCall | MCPListTools | MCPApprovalRequest | MCPApprovalResponseResource + | MCPToolCall | CustomToolCall - | CustomToolCallOutputResource -export const OutputItem = Schema.Union([ - OutputMessage, - FileSearchToolCall, + | CustomToolCallOutput +export const ItemField = Schema.Union([ + Message, + Program, + ProgramOutput, FunctionToolCall, - FunctionToolCallOutputResource, + ToolSearchCall, + ToolSearchOutput, + AdditionalTools, + FunctionToolCallOutput, + FileSearchToolCall, WebSearchToolCall, + ImageGenToolCall, ComputerToolCall, ComputerToolCallOutputResource, ReasoningItem, - ToolSearchCall, - ToolSearchOutput, CompactionBody, - ImageGenToolCall, CodeInterpreterToolCall, LocalShellToolCall, LocalShellToolCallOutput, @@ -24763,283 +42452,918 @@ export const OutputItem = Schema.Union([ FunctionShellCallOutput, ApplyPatchToolCall, ApplyPatchToolCallOutput, - MCPToolCall, MCPListTools, MCPApprovalRequest, MCPApprovalResponseResource, + MCPToolCall, CustomToolCall, - CustomToolCallOutputResource -], { mode: "oneOf" }) -export type ResponseOutputItemAddedEvent = { - readonly "type": "response.output_item.added" - readonly "output_index": number - readonly "sequence_number": number - readonly "item": - | OutputMessage - | FileSearchToolCall - | FunctionToolCall - | FunctionToolCallOutputResource - | WebSearchToolCall - | ComputerToolCall - | ComputerToolCallOutputResource - | ReasoningItem - | ToolSearchCall - | ToolSearchOutput - | CompactionBody - | ImageGenToolCall - | CodeInterpreterToolCall - | LocalShellToolCall - | LocalShellToolCallOutput - | FunctionShellCall - | FunctionShellCallOutput - | ApplyPatchToolCall - | ApplyPatchToolCallOutput - | MCPToolCall - | MCPListTools - | MCPApprovalRequest - | MCPApprovalResponseResource - | CustomToolCall - | CustomToolCallOutputResource + CustomToolCallOutput +], { mode: "oneOf" }).annotate({ + "description": "An item representing a message, tool call, tool output, reasoning, or other response element.", + "identifier": "ItemField" +}) +export type InputParam = string | ReadonlyArray +export const InputParam = Schema.Union([ + Schema.String.annotate({ + "title": "Text input", + "description": "A text input to the model, equivalent to a text input with the\n`user` role.\n" + }), + Schema.Array(InputItem).annotate({ + "title": "Input item list", + "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" + }) +], { mode: "oneOf" }).annotate({ + "description": + "Text, image, or file inputs to the model, used to generate a response.\n\nLearn more:\n- [Text inputs and outputs](https://developers.openai.com/api/docs/guides/text)\n- [Image inputs](https://developers.openai.com/api/docs/guides/images-vision)\n- [File inputs](https://developers.openai.com/api/docs/guides/file-inputs)\n- [Conversation state](https://developers.openai.com/api/docs/guides/conversation-state)\n- [Function calling](https://developers.openai.com/api/docs/guides/function-calling)\n", + "identifier": "InputParam" +}) +export type CreateConversationBody = { + readonly "metadata"?: Metadata | null + readonly "items"?: ReadonlyArray | null +} +export const CreateConversationBody = Schema.Struct({ + "metadata": Schema.optionalKey(Schema.Union([ + Schema.suspend((): Schema.Codec => Metadata).annotate({ + "description": + "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format, and querying for objects via API or the dashboard.\n Keys are strings with a maximum length of 64 characters. Values are strings with a maximum length of 512 characters." + }), + Schema.Null + ])), + "items": Schema.optionalKey( + Schema.Union([ + Schema.Array(InputItem).annotate({ + "description": "Initial items to include in the conversation context. You may add up to 20 items at a time." + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })), + Schema.Null + ]) + ) +}).annotate({ "identifier": "CreateConversationBody" }) +export type TokenCountsBody = { + readonly "model"?: string | null + readonly "input"?: string | ReadonlyArray | null + readonly "previous_response_id"?: string | null + readonly "tools"?: ReadonlyArray | null + readonly "text"?: ResponseTextParam | null + readonly "reasoning"?: Reasoning | null + readonly "truncation"?: TruncationEnum + readonly "instructions"?: string | null + readonly "personality"?: PersonalityEnum + readonly "conversation"?: ConversationParam | null + readonly "tool_choice"?: ToolChoiceParam | null + readonly "parallel_tool_calls"?: boolean | null +} +export const TokenCountsBody = Schema.Struct({ + "model": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models) to browse and compare available models." + }), + Schema.Null + ])), + "input": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.String.annotate({ + "description": "A text input to the model, equivalent to a text input with the `user` role." + }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.Array(InputItem).annotate({ + "description": "A list of one or many input items to the model, containing different content types." + }).check(Schema.isMaxLength(131072).annotate({ "expected": "a value with a length of at most 131072" })) + ], { mode: "oneOf" }).annotate({ + "description": "Text, image, or file inputs to the model, used to generate a response" + }), + Schema.Null + ]) + ), + "previous_response_id": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://developers.openai.com/api/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`." + }), + Schema.Null + ])), + "tools": Schema.optionalKey( + Schema.Union([ + Schema.Array(Tool).annotate({ + "description": + "An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter." + }), + Schema.Null + ]) + ), + "text": Schema.optionalKey(Schema.Union([ResponseTextParam, Schema.Null])), + "reasoning": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Reasoning).annotate({ + "description": + "**gpt-5 and o-series models only** Configuration options for [reasoning models](https://developers.openai.com/api/docs/guides/reasoning)." + }), + Schema.Null + ]) + ), + "truncation": Schema.optionalKey( + Schema.suspend((): Schema.Codec => TruncationEnum).annotate({ + "description": + "The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error." + }) + ), + "instructions": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "A system (or developer) message inserted into the model's context.\nWhen used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses." + }), + Schema.Null + ])), + "personality": Schema.optionalKey( + Schema.suspend((): Schema.Codec => PersonalityEnum).annotate({ + "description": + "A model-owned style preset to apply to this request. Omit this parameter to use the model's default style. Supported values may expand over time. Values must be at most 64 characters." + }) + ), + "conversation": Schema.optionalKey(Schema.Union([ConversationParam, Schema.Null])), + "tool_choice": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ToolChoiceParam).annotate({ + "description": "Controls which tool the model should use, if any." + }), + Schema.Null + ]) + ), + "parallel_tool_calls": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ "description": "Whether to allow the model to run tool calls in parallel." }), + Schema.Null + ]) + ) +}).annotate({ "identifier": "TokenCountsBody" }) +export type CompactResponseMethodPublicBody = { + readonly "model": ModelIdsCompaction + readonly "input"?: string | ReadonlyArray | null + readonly "previous_response_id"?: string | null + readonly "instructions"?: string | null + readonly "prompt_cache_key"?: string | null + readonly "prompt_cache_retention"?: PromptCacheRetentionEnum | null + readonly "prompt_cache_options"?: PromptCacheOptionsParam | null + readonly "service_tier"?: ServiceTierEnum | null +} +export const CompactResponseMethodPublicBody = Schema.Struct({ + "model": ModelIdsCompaction, + "input": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.String.annotate({ + "description": "A text input to the model, equivalent to a text input with the `user` role." + }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.Array(InputItem).annotate({ + "description": "A list of one or many input items to the model, containing different content types." + }).check(Schema.isMaxLength(131072).annotate({ "expected": "a value with a length of at most 131072" })) + ], { mode: "oneOf" }).annotate({ + "description": "Text, image, or file inputs to the model, used to generate a response" + }), + Schema.Null + ]) + ), + "previous_response_id": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://developers.openai.com/api/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`." + }), + Schema.Null + ])), + "instructions": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "A system (or developer) message inserted into the model's context.\nWhen used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses." + }), + Schema.Null + ])), + "prompt_cache_key": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "A key to use when reading from or writing to the prompt cache." }).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + Schema.Null + ]) + ), + "prompt_cache_retention": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => PromptCacheRetentionEnum).annotate({ + "description": "How long to retain a prompt cache entry created by this request." + }), + Schema.Null + ]) + ), + "prompt_cache_options": Schema.optionalKey(Schema.Union([PromptCacheOptionsParam, Schema.Null])), + "service_tier": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ServiceTierEnum).annotate({ + "description": + "Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://developers.openai.com/api/docs/guides/flex-processing)', then the request will be processed with the Flex Processing service tier. - To opt-in to [Fast mode](https://developers.openai.com/api/docs/guides/fast-mode) at the request level, include the `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat Completions. For models with a dedicated Fast tier, either value resolves to `service_tier=fast`; for other models, either value resolves to `service_tier=priority`. - When not set, the default behavior is 'auto'.\n When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter." + }), + Schema.Null + ]) + ) +}).annotate({ "identifier": "CompactResponseMethodPublicBody" }) +export type Delegation = LiveClientDelegationParam | LiveResponsesDelegationParam | null +export const Delegation = Schema.Union([ + Schema.Union([LiveClientDelegationParam, LiveResponsesDelegationParam], { mode: "oneOf" }).annotate({ + "description": + "Who handles tasks delegated by the Live model. Omitted or null selects your application; use `responses` to let the API manage a Responses backend." + }), + Schema.Null +]).annotate({ "identifier": "delegation" }) +export type LiveMediaSessionForkParams = { + readonly "store"?: Properties_store + readonly "delegation"?: LiveResponsesDelegationUpdateParam + readonly "client"?: LiveClientConfigParam +} +export const LiveMediaSessionForkParams = Schema.Struct({ + "store": Schema.optionalKey(Properties_store), + "delegation": Schema.optionalKey(LiveResponsesDelegationUpdateParam), + "client": Schema.optionalKey(LiveClientConfigParam) +}).annotate({ + "description": + "Optional overrides for a stored Live session. Omitted settings are inherited. The model, voice, frontend instructions, and prior conversation come from the stored session. WebRTC negotiates its audio format; audio.format is only supported on WebSocket forks.", + "identifier": "LiveMediaSessionForkParams" +}) +export type DecisionRequest = { + readonly "model": string + readonly "input": DecisionInput + readonly "questions": ReadonlyArray + readonly "safety_identifier"?: string | null +} +export const DecisionRequest = Schema.Struct({ + "model": Schema.String.check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ).check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + "input": DecisionInput, + "questions": Schema.Array(QuestionParam).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ).check(Schema.isMaxLength(200).annotate({ "expected": "a value with a length of at most 200" })), + "safety_identifier": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ]).annotate({ + "description": + "Opaque caller-provided end-user identifier, scoped by the verified org. Match Responses' limit; this is never the authenticated user identity." + }) + ) +}).annotate({ "identifier": "DecisionRequest" }) +export type CreateAgentEnvironmentParams = { + readonly "environment": CreateEnvironmentParam + readonly "vault_ids"?: ReadonlyArray | null +} +export const CreateAgentEnvironmentParams = Schema.Struct({ + "environment": Schema.suspend((): Schema.Codec => CreateEnvironmentParam).annotate({ + "description": "The required hosting type and its configuration." + }), + "vault_ids": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(10).annotate({ "expected": "a value with a length of at most 10" }) + ), + Schema.Null + ]).annotate({ "description": "The IDs of up to 10 vaults made available to an OpenAI-hosted environment." }) + ) +}).annotate({ + "description": "Parameters for creating an execution environment before its sessions.", + "identifier": "CreateAgentEnvironmentParams" +}) +export type CreateAgentSessionParams = { + readonly "spend_control"?: SessionSpendControlParam | null + readonly "metadata"?: { readonly [x: string]: string } | null + readonly "agent"?: SessionAgentConfigParam + readonly "agent_id"?: string + readonly "environment": EnvironmentParam + readonly "vault_ids"?: ReadonlyArray | null + readonly "input"?: CreateSessionInputParam | null + readonly "stream"?: boolean +} +export const CreateAgentSessionParams = Schema.Struct({ + "spend_control": Schema.optionalKey( + Schema.Union([SessionSpendControlParam, Schema.Null]).annotate({ + "description": "Optional spending limit in USD cents. Omission or null creates an unlimited session." + }) + ), + "metadata": Schema.optionalKey( + Schema.Union([ + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ), + Schema.Null + ]).annotate({ + "description": + "Up to 16 string key-value pairs, with keys up to 64 and values up to 512 characters. Omission or null defaults to an empty map." + }) + ), + "agent": Schema.optionalKey( + Schema.suspend((): Schema.Codec => SessionAgentConfigParam).annotate({ + "description": + "Agent configuration. With `agent_id`, supplied fields override the saved agent for this session. Without `agent_id`, `model` is required." + }) + ), + "agent_id": Schema.optionalKey( + Schema.String.annotate({ + "description": "The ID of a saved reusable agent. Omit `agent` to use its configuration unchanged." + }).check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ) + ), + "environment": Schema.suspend((): Schema.Codec => EnvironmentParam).annotate({ + "description": "An inline execution environment or a reference to an environment template." + }), + "vault_ids": Schema.optionalKey( + Schema.Union([ + Schema.Array( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(16384).annotate({ "expected": "a value with a length of at most 16384" }) + ), + Schema.Null + ]).annotate({ "description": "The IDs of vaults made available to the session." }) + ), + "input": Schema.optionalKey( + Schema.Union([CreateSessionInputParam, Schema.Null]).annotate({ + "description": + "Initial input to submit when the session is created. A string is shorthand for a single user message. Required when `environment.type` is `none`, or when `stream` is `true` for an environment that is not `self_hosted`; optional for self-hosted and non-streaming execution environments." + }) + ), + "stream": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": "Whether to stream session events as server-sent events. Defaults to `false`." + }) + ) +}).annotate({ + "description": "Parameters for creating a Managed Agents session.", + "identifier": "CreateAgentSessionParams" +}) +export type SessionListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean } -export const ResponseOutputItemAddedEvent = Schema.Struct({ - "type": Schema.Literal("response.output_item.added").annotate({ - "description": "The type of the event. Always `response.output_item.added`.\n" +export const SessionListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(SessionResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item that was added.\n" }).check( - Schema.isInt() + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "SessionListResource" +}) +export type SessionEventAgentSessionCreated = { + readonly "type": "agent.session.created" + readonly "event_id": string + readonly "session": SessionResource +} +export const SessionEventAgentSessionCreated = Schema.Struct({ + "type": Schema.Literal("agent.session.created").annotate({ + "description": "The type of the object. Always `agent.session.created`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) ), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() - ), - "item": Schema.Union([ - OutputMessage, - FileSearchToolCall, - FunctionToolCall, - FunctionToolCallOutputResource, - WebSearchToolCall, - ComputerToolCall, - ComputerToolCallOutputResource, - ReasoningItem, - ToolSearchCall, - ToolSearchOutput, - CompactionBody, - ImageGenToolCall, - CodeInterpreterToolCall, - LocalShellToolCall, - LocalShellToolCallOutput, - FunctionShellCall, - FunctionShellCallOutput, - ApplyPatchToolCall, - ApplyPatchToolCallOutput, - MCPToolCall, - MCPListTools, - MCPApprovalRequest, - MCPApprovalResponseResource, - CustomToolCall, - CustomToolCallOutputResource - ], { mode: "oneOf" }).annotate({ "description": "The output item that was added.\n" }) -}).annotate({ "description": "Emitted when a new output item is added." }) -export type ResponseOutputItemDoneEvent = { - readonly "type": "response.output_item.done" - readonly "output_index": number - readonly "sequence_number": number - readonly "item": - | OutputMessage - | FileSearchToolCall - | FunctionToolCall - | FunctionToolCallOutputResource - | WebSearchToolCall - | ComputerToolCall - | ComputerToolCallOutputResource - | ReasoningItem - | ToolSearchCall - | ToolSearchOutput - | CompactionBody - | ImageGenToolCall - | CodeInterpreterToolCall - | LocalShellToolCall - | LocalShellToolCallOutput - | FunctionShellCall - | FunctionShellCallOutput - | ApplyPatchToolCall - | ApplyPatchToolCallOutput - | MCPToolCall - | MCPListTools - | MCPApprovalRequest - | MCPApprovalResponseResource - | CustomToolCall - | CustomToolCallOutputResource + "session": Schema.suspend((): Schema.Codec => SessionResource).annotate({ + "description": "The session that was created." + }) +}).annotate({ "description": "Emitted when a session is created.", "identifier": "SessionEventAgentSessionCreated" }) +export type SessionEventAgentSessionIdle = { + readonly "type": "agent.session.idle" + readonly "event_id": string + readonly "session": SessionResource } -export const ResponseOutputItemDoneEvent = Schema.Struct({ - "type": Schema.Literal("response.output_item.done").annotate({ - "description": "The type of the event. Always `response.output_item.done`.\n" +export const SessionEventAgentSessionIdle = Schema.Struct({ + "type": Schema.Literal("agent.session.idle").annotate({ + "description": "The type of the object. Always `agent.session.idle`." }), - "output_index": Schema.Number.annotate({ "description": "The index of the output item that was marked done.\n" }) - .check(Schema.isInt()), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( - Schema.isInt() - ), - "item": Schema.Union([ - OutputMessage, - FileSearchToolCall, - FunctionToolCall, - FunctionToolCallOutputResource, - WebSearchToolCall, - ComputerToolCall, - ComputerToolCallOutputResource, - ReasoningItem, - ToolSearchCall, - ToolSearchOutput, - CompactionBody, - ImageGenToolCall, - CodeInterpreterToolCall, - LocalShellToolCall, - LocalShellToolCallOutput, - FunctionShellCall, - FunctionShellCallOutput, - ApplyPatchToolCall, - ApplyPatchToolCallOutput, - MCPToolCall, - MCPListTools, - MCPApprovalRequest, - MCPApprovalResponseResource, - CustomToolCall, - CustomToolCallOutputResource - ], { mode: "oneOf" }).annotate({ "description": "The output item that was marked done.\n" }) -}).annotate({ "description": "Emitted when an output item is marked done." }) -export type ItemField = - | Message - | FunctionToolCall - | ToolSearchCall - | ToolSearchOutput - | FunctionToolCallOutput - | FileSearchToolCall - | WebSearchToolCall - | ImageGenToolCall - | ComputerToolCall - | ComputerToolCallOutputResource - | ReasoningItem - | CompactionBody - | CodeInterpreterToolCall - | LocalShellToolCall - | LocalShellToolCallOutput - | FunctionShellCall - | FunctionShellCallOutput - | ApplyPatchToolCall - | ApplyPatchToolCallOutput - | MCPListTools - | MCPApprovalRequest - | MCPApprovalResponseResource - | MCPToolCall - | CustomToolCall - | CustomToolCallOutput -export const ItemField = Schema.Union([ - Message, - FunctionToolCall, - ToolSearchCall, - ToolSearchOutput, - FunctionToolCallOutput, - FileSearchToolCall, - WebSearchToolCall, - ImageGenToolCall, - ComputerToolCall, - ComputerToolCallOutputResource, - ReasoningItem, - CompactionBody, - CodeInterpreterToolCall, - LocalShellToolCall, - LocalShellToolCallOutput, - FunctionShellCall, - FunctionShellCallOutput, - ApplyPatchToolCall, - ApplyPatchToolCallOutput, - MCPListTools, - MCPApprovalRequest, - MCPApprovalResponseResource, - MCPToolCall, - CustomToolCall, - CustomToolCallOutput + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session": Schema.suspend((): Schema.Codec => SessionResource).annotate({ + "description": "The session that became idle." + }) +}).annotate({ "description": "Emitted when a session becomes idle.", "identifier": "SessionEventAgentSessionIdle" }) +export type SessionEventAgentSessionInProgress = { + readonly "type": "agent.session.in_progress" + readonly "event_id": string + readonly "session": SessionResource +} +export const SessionEventAgentSessionInProgress = Schema.Struct({ + "type": Schema.Literal("agent.session.in_progress").annotate({ + "description": "The type of the object. Always `agent.session.in_progress`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session": Schema.suspend((): Schema.Codec => SessionResource).annotate({ + "description": "The session that started processing." + }) +}).annotate({ + "description": "Emitted when a session starts processing a turn.", + "identifier": "SessionEventAgentSessionInProgress" +}) +export type SessionEventAgentSessionRequiresAction = { + readonly "type": "agent.session.requires_action" + readonly "event_id": string + readonly "session": SessionResource +} +export const SessionEventAgentSessionRequiresAction = Schema.Struct({ + "type": Schema.Literal("agent.session.requires_action").annotate({ + "description": "The type of the object. Always `agent.session.requires_action`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session": Schema.suspend((): Schema.Codec => SessionResource).annotate({ + "description": "The session and its current required actions." + }) +}).annotate({ + "description": "Emitted when a session is waiting for one or more required actions.", + "identifier": "SessionEventAgentSessionRequiresAction" +}) +export type SessionEventAgentSessionFailed = { + readonly "type": "agent.session.failed" + readonly "event_id": string + readonly "session": SessionResource +} +export const SessionEventAgentSessionFailed = Schema.Struct({ + "type": Schema.Literal("agent.session.failed").annotate({ + "description": "The type of the object. Always `agent.session.failed`." + }), + "event_id": Schema.String.annotate({ "description": "The unique ID of the event." }).check( + Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" }) + ), + "session": Schema.suspend((): Schema.Codec => SessionResource).annotate({ + "description": "The failed session." + }) +}).annotate({ "description": "Emitted when a session fails.", "identifier": "SessionEventAgentSessionFailed" }) +export type VaultCredentialListResource = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const VaultCredentialListResource = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(VaultCredentialResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ + "description": "A page of Agents API resources, with IDs for retrieving additional pages.", + "identifier": "VaultCredentialListResource" +}) +export type BetaOutputItem = + | BetaOutputMessage + | BetaFileSearchToolCall + | BetaFunctionToolCall + | BetaFunctionToolCallOutputResource + | BetaAgentMessage + | BetaMultiAgentCall + | BetaMultiAgentCallOutput + | BetaWebSearchToolCall + | BetaComputerToolCall + | BetaComputerToolCallOutputResource + | BetaReasoningItem + | BetaProgram + | BetaProgramOutput + | BetaToolSearchCall + | BetaToolSearchOutput + | BetaAdditionalTools + | BetaCompactionBody + | BetaImageGenToolCall + | BetaCodeInterpreterToolCall + | BetaLocalShellToolCall + | BetaLocalShellToolCallOutput + | BetaFunctionShellCall + | BetaFunctionShellCallOutput + | BetaApplyPatchToolCall + | BetaApplyPatchToolCallOutput + | BetaMCPToolCall + | BetaMCPListTools + | BetaMCPApprovalRequest + | BetaMCPApprovalResponseResource + | BetaCustomToolCall + | BetaCustomToolCallOutputResource +export const BetaOutputItem = Schema.Union([ + BetaOutputMessage, + BetaFileSearchToolCall, + BetaFunctionToolCall, + BetaFunctionToolCallOutputResource, + BetaAgentMessage, + BetaMultiAgentCall, + BetaMultiAgentCallOutput, + BetaWebSearchToolCall, + BetaComputerToolCall, + BetaComputerToolCallOutputResource, + BetaReasoningItem, + BetaProgram, + BetaProgramOutput, + BetaToolSearchCall, + BetaToolSearchOutput, + BetaAdditionalTools, + BetaCompactionBody, + BetaImageGenToolCall, + BetaCodeInterpreterToolCall, + BetaLocalShellToolCall, + BetaLocalShellToolCallOutput, + BetaFunctionShellCall, + BetaFunctionShellCallOutput, + BetaApplyPatchToolCall, + BetaApplyPatchToolCallOutput, + BetaMCPToolCall, + BetaMCPListTools, + BetaMCPApprovalRequest, + BetaMCPApprovalResponseResource, + BetaCustomToolCall, + BetaCustomToolCallOutputResource +], { mode: "oneOf" }).annotate({ "identifier": "BetaOutputItem" }) +export type BetaItemField = + | BetaMessage + | BetaProgram + | BetaProgramOutput + | BetaFunctionToolCall + | BetaMultiAgentCall + | BetaMultiAgentCallOutput + | BetaToolSearchCall + | BetaToolSearchOutput + | BetaAdditionalTools + | BetaAgentMessage + | BetaFunctionToolCallOutput + | BetaFileSearchToolCall + | BetaWebSearchToolCall + | BetaImageGenToolCall + | BetaComputerToolCall + | BetaComputerToolCallOutputResource + | BetaReasoningItem + | BetaCompactionBody + | BetaCodeInterpreterToolCall + | BetaLocalShellToolCall + | BetaLocalShellToolCallOutput + | BetaFunctionShellCall + | BetaFunctionShellCallOutput + | BetaApplyPatchToolCall + | BetaApplyPatchToolCallOutput + | BetaMCPListTools + | BetaMCPApprovalRequest + | BetaMCPApprovalResponseResource + | BetaMCPToolCall + | BetaCustomToolCall + | BetaCustomToolCallOutput +export const BetaItemField = Schema.Union([ + BetaMessage, + BetaProgram, + BetaProgramOutput, + BetaFunctionToolCall, + BetaMultiAgentCall, + BetaMultiAgentCallOutput, + BetaToolSearchCall, + BetaToolSearchOutput, + BetaAdditionalTools, + BetaAgentMessage, + BetaFunctionToolCallOutput, + BetaFileSearchToolCall, + BetaWebSearchToolCall, + BetaImageGenToolCall, + BetaComputerToolCall, + BetaComputerToolCallOutputResource, + BetaReasoningItem, + BetaCompactionBody, + BetaCodeInterpreterToolCall, + BetaLocalShellToolCall, + BetaLocalShellToolCallOutput, + BetaFunctionShellCall, + BetaFunctionShellCallOutput, + BetaApplyPatchToolCall, + BetaApplyPatchToolCallOutput, + BetaMCPListTools, + BetaMCPApprovalRequest, + BetaMCPApprovalResponseResource, + BetaMCPToolCall, + BetaCustomToolCall, + BetaCustomToolCallOutput ], { mode: "oneOf" }).annotate({ - "description": "An item representing a message, tool call, tool output, reasoning, or other response element." + "description": "An item representing a message, tool call, tool output, reasoning, or other response element.", + "identifier": "BetaItemField" }) -export type CreateEvalRequest = { - readonly "name"?: string - readonly "metadata"?: Metadata - readonly "data_source_config": - | { readonly "type": "custom"; readonly "item_schema": {}; readonly "include_sample_schema"?: boolean } - | { readonly "type": "logs"; readonly "metadata"?: {} } - | { readonly "type": "stored_completions"; readonly "metadata"?: {} } - readonly "testing_criteria": ReadonlyArray< - | CreateEvalLabelModelGrader - | EvalGraderStringCheck - | EvalGraderTextSimilarity - | EvalGraderPython - | EvalGraderScoreModel - > +export type BetaItemResource = + | BetaInputMessageResource + | BetaOutputMessage + | BetaFileSearchToolCall + | BetaComputerToolCall + | BetaComputerToolCallOutputResource + | BetaWebSearchToolCall + | BetaFunctionToolCallResource + | BetaFunctionToolCallOutputResource + | BetaAgentMessage + | BetaMultiAgentCall + | BetaMultiAgentCallOutput + | BetaToolSearchCall + | BetaToolSearchOutput + | BetaAdditionalTools + | BetaResponseConfigurationUpdate + | BetaReasoningItem + | BetaProgram + | BetaProgramOutput + | BetaCompactionBody + | BetaImageGenToolCall + | BetaCodeInterpreterToolCall + | BetaLocalShellToolCall + | BetaLocalShellToolCallOutput + | BetaFunctionShellCall + | BetaFunctionShellCallOutput + | BetaApplyPatchToolCall + | BetaApplyPatchToolCallOutput + | BetaMCPListTools + | BetaMCPApprovalRequest + | BetaMCPApprovalResponseResource + | BetaMCPToolCall + | BetaCustomToolCallResource + | BetaCustomToolCallOutputResource +export const BetaItemResource = Schema.Union([ + BetaInputMessageResource, + BetaOutputMessage, + BetaFileSearchToolCall, + BetaComputerToolCall, + BetaComputerToolCallOutputResource, + BetaWebSearchToolCall, + BetaFunctionToolCallResource, + BetaFunctionToolCallOutputResource, + BetaAgentMessage, + BetaMultiAgentCall, + BetaMultiAgentCallOutput, + BetaToolSearchCall, + BetaToolSearchOutput, + BetaAdditionalTools, + BetaResponseConfigurationUpdate, + BetaReasoningItem, + BetaProgram, + BetaProgramOutput, + BetaCompactionBody, + BetaImageGenToolCall, + BetaCodeInterpreterToolCall, + BetaLocalShellToolCall, + BetaLocalShellToolCallOutput, + BetaFunctionShellCall, + BetaFunctionShellCallOutput, + BetaApplyPatchToolCall, + BetaApplyPatchToolCallOutput, + BetaMCPListTools, + BetaMCPApprovalRequest, + BetaMCPApprovalResponseResource, + BetaMCPToolCall, + BetaCustomToolCallResource, + BetaCustomToolCallOutputResource +], { mode: "oneOf" }).annotate({ + "description": "Content item used to generate a response.\n", + "identifier": "BetaItemResource" +}) +export type BetaInputParam = string | ReadonlyArray +export const BetaInputParam = Schema.Union([ + Schema.String.annotate({ + "title": "Text input", + "description": "A text input to the model, equivalent to a text input with the\n`user` role.\n" + }), + Schema.Array(BetaInputItem).annotate({ + "title": "Input item list", + "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" + }) +], { mode: "oneOf" }).annotate({ + "description": + "Text, image, or file inputs to the model, used to generate a response.\n\nLearn more:\n- [Text inputs and outputs](https://developers.openai.com/api/docs/guides/text)\n- [Image inputs](https://developers.openai.com/api/docs/guides/images-vision)\n- [File inputs](https://developers.openai.com/api/docs/guides/file-inputs)\n- [Conversation state](https://developers.openai.com/api/docs/guides/conversation-state)\n- [Function calling](https://developers.openai.com/api/docs/guides/function-calling)\n", + "identifier": "BetaInputParam" +}) +export type BetaCompactResponseMethodPublicBody = { + readonly "model": BetaModelIdsCompaction + readonly "input"?: string | ReadonlyArray | null + readonly "previous_response_id"?: string | null + readonly "instructions"?: string | null + readonly "prompt_cache_key"?: string | null + readonly "prompt_cache_retention"?: BetaPromptCacheRetentionEnum | null + readonly "prompt_cache_options"?: BetaPromptCacheOptionsParam | null + readonly "service_tier"?: BetaServiceTierEnum | null } -export const CreateEvalRequest = Schema.Struct({ - "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the evaluation." })), - "metadata": Schema.optionalKey(Metadata), - "data_source_config": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("custom").annotate({ "description": "The type of data source. Always `custom`." }), - "item_schema": Schema.Struct({}).annotate({ "description": "The json schema for each row in the data source." }), - "include_sample_schema": Schema.optionalKey( - Schema.Boolean.annotate({ - "description": - "Whether the eval should expect you to populate the sample namespace (ie, by generating responses off of your data source)" - }) - ) - }).annotate({ - "title": "CustomDataSourceConfig", +export const BetaCompactResponseMethodPublicBody = Schema.Struct({ + "model": BetaModelIdsCompaction, + "input": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.String.annotate({ + "description": "A text input to the model, equivalent to a text input with the `user` role." + }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.Array(BetaInputItem).annotate({ + "description": "A list of one or many input items to the model, containing different content types." + }).check(Schema.isMaxLength(131072).annotate({ "expected": "a value with a length of at most 131072" })) + ], { mode: "oneOf" }).annotate({ + "description": "Text, image, or file inputs to the model, used to generate a response" + }), + Schema.Null + ]) + ), + "previous_response_id": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ "description": - "The configuration for the data source used for the evaluation runs. Dictates the schema of the data used in the evaluation." + "The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://developers.openai.com/api/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`." }), - Schema.Struct({ - "type": Schema.Literal("logs").annotate({ "description": "The type of data source. Always `logs`." }), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ "description": "Metadata filters for the logs data source." }) - ) - }).annotate({ - "title": "LogsDataSourceConfig", + Schema.Null + ])), + "instructions": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "A system (or developer) message inserted into the model's context.\nWhen used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses." + }), + Schema.Null + ])), + "prompt_cache_key": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "A key to use when reading from or writing to the prompt cache." }).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + Schema.Null + ]) + ), + "prompt_cache_retention": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaPromptCacheRetentionEnum).annotate({ + "description": "How long to retain a prompt cache entry created by this request." + }), + Schema.Null + ]) + ), + "prompt_cache_options": Schema.optionalKey(Schema.Union([BetaPromptCacheOptionsParam, Schema.Null])), + "service_tier": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaServiceTierEnum).annotate({ + "description": + "Specifies the processing type used for serving the request. - If set to 'auto', then the request will be processed with the service tier configured in the Project settings. Unless otherwise configured, the Project will use 'default'. - If set to 'default', then the request will be processed with the standard pricing and performance for the selected model. - If set to '[flex](https://developers.openai.com/api/docs/guides/flex-processing)', then the request will be processed with the Flex Processing service tier. - To opt-in to [Fast mode](https://developers.openai.com/api/docs/guides/fast-mode) at the request level, include the `service_tier=fast` or `service_tier=priority` parameter for Responses or Chat Completions. For models with a dedicated Fast tier, either value resolves to `service_tier=fast`; for other models, either value resolves to `service_tier=priority`. - When not set, the default behavior is 'auto'.\n When the `service_tier` parameter is set, the response body will include the `service_tier` value based on the processing mode actually used to serve the request. This response value may be different from the value set in the parameter." + }), + Schema.Null + ]) + ) +}).annotate({ "identifier": "BetaCompactResponseMethodPublicBody" }) +export type BetaTokenCountsBody = { + readonly "model"?: string | null + readonly "input"?: string | ReadonlyArray | null + readonly "previous_response_id"?: string | null + readonly "tools"?: ReadonlyArray | null + readonly "text"?: BetaResponseTextParam | null + readonly "reasoning"?: BetaReasoning | null + readonly "truncation"?: BetaTruncationEnum + readonly "instructions"?: string | null + readonly "personality"?: BetaPersonalityEnum + readonly "conversation"?: BetaConversationParam | null + readonly "tool_choice"?: BetaToolChoiceParam | null + readonly "parallel_tool_calls"?: boolean | null +} +export const BetaTokenCountsBody = Schema.Struct({ + "model": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI offers a wide range of models with different capabilities, performance characteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models) to browse and compare available models." + }), + Schema.Null + ])), + "input": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.String.annotate({ + "description": "A text input to the model, equivalent to a text input with the `user` role." + }).check( + Schema.isMaxCodePoints(10485760).annotate({ "expected": "a string with at most 10485760 code points" }) + ), + Schema.Array(BetaInputItem).annotate({ + "description": "A list of one or many input items to the model, containing different content types." + }).check(Schema.isMaxLength(131072).annotate({ "expected": "a value with a length of at most 131072" })) + ], { mode: "oneOf" }).annotate({ + "description": "Text, image, or file inputs to the model, used to generate a response" + }), + Schema.Null + ]) + ), + "previous_response_id": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ "description": - "The configuration for the data source used for the evaluation runs. Dictates the schema of the data used in the evaluation." + "The unique ID of the previous response to the model. Use this to create multi-turn conversations. Learn more about [conversation state](https://developers.openai.com/api/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`." }), - Schema.Struct({ - "type": Schema.Literal("stored_completions").annotate({ - "description": "The type of data source. Always `stored_completions`." + Schema.Null + ])), + "tools": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaTool).annotate({ + "description": + "An array of tools the model may call while generating a response. You can specify which tool to use by setting the `tool_choice` parameter." }), - "metadata": Schema.optionalKey( - Schema.Struct({}).annotate({ "description": "Metadata filters for the stored completions data source." }) - ) - }).annotate({ - "title": "StoredCompletionsDataSourceConfig", + Schema.Null + ]) + ), + "text": Schema.optionalKey(Schema.Union([BetaResponseTextParam, Schema.Null])), + "reasoning": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaReasoning).annotate({ + "description": + "**gpt-5 and o-series models only** Configuration options for [reasoning models](https://developers.openai.com/api/docs/guides/reasoning)." + }), + Schema.Null + ]) + ), + "truncation": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaTruncationEnum).annotate({ "description": - "The configuration for the data source used for the evaluation runs. Dictates the schema of the data used in the evaluation." + "The truncation strategy to use for the model response. - `auto`: If the input to this Response exceeds the model's context window size, the model will truncate the response to fit the context window by dropping items from the beginning of the conversation. - `disabled` (default): If the input size will exceed the context window size for a model, the request will fail with a 400 error." }) - ], { mode: "oneOf" }), - "testing_criteria": Schema.Array( + ), + "instructions": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "A system (or developer) message inserted into the model's context.\nWhen used along with `previous_response_id`, the instructions from a previous response will not be carried over to the next response. This makes it simple to swap out system (or developer) messages in new responses." + }), + Schema.Null + ])), + "personality": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaPersonalityEnum).annotate({ + "description": + "A model-owned style preset to apply to this request. Omit this parameter to use the model's default style. Supported values may expand over time. Values must be at most 64 characters." + }) + ), + "conversation": Schema.optionalKey(Schema.Union([BetaConversationParam, Schema.Null])), + "tool_choice": Schema.optionalKey( Schema.Union([ - CreateEvalLabelModelGrader, - EvalGraderStringCheck, - EvalGraderTextSimilarity, - EvalGraderPython, - EvalGraderScoreModel - ], { mode: "oneOf" }) - ).annotate({ - "description": - "A list of graders for all eval runs in this group. Graders can reference variables in the data source using double curly braces notation, like `{{item.variable_name}}`. To reference the model's output, use the `sample` namespace (ie, `{{sample.output_text}}`)." - }) -}).annotate({ "title": "CreateEvalRequest" }) + Schema.suspend((): Schema.Codec => BetaToolChoiceParam).annotate({ + "description": "Controls which tool the model should use, if any." + }), + Schema.Null + ]) + ), + "parallel_tool_calls": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ "description": "Whether to allow the model to run tool calls in parallel." }), + Schema.Null + ]) + ) +}).annotate({ "identifier": "BetaTokenCountsBody" }) export type Eval = { readonly "object": "eval" readonly "id": string readonly "name": string - readonly "data_source_config": { readonly "type": "custom"; readonly "schema": {} } | { - readonly "type": "logs" - readonly "metadata"?: Metadata - readonly "schema": {} - } | { readonly "type": "stored_completions"; readonly "metadata"?: Metadata; readonly "schema": {} } + readonly "data_source_config": + | EvalCustomDataSourceConfig + | EvalLogsDataSourceConfig + | EvalStoredCompletionsDataSourceConfig readonly "testing_criteria": ReadonlyArray< EvalGraderLabelModel | EvalGraderStringCheck | EvalGraderTextSimilarity | EvalGraderPython | EvalGraderScoreModel > @@ -25051,41 +43375,10 @@ export const Eval = Schema.Struct({ "id": Schema.String.annotate({ "description": "Unique identifier for the evaluation." }), "name": Schema.String.annotate({ "description": "The name of the evaluation." }), "data_source_config": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("custom").annotate({ "description": "The type of data source. Always `custom`." }), - "schema": Schema.Struct({}).annotate({ - "description": - "The json schema for the run data source items.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n" - }) - }).annotate({ - "title": "CustomDataSourceConfig", - "description": "Configuration of data sources used in runs of the evaluation." - }), - Schema.Struct({ - "type": Schema.Literal("logs").annotate({ "description": "The type of data source. Always `logs`." }), - "metadata": Schema.optionalKey(Metadata), - "schema": Schema.Struct({}).annotate({ - "description": - "The json schema for the run data source items.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n" - }) - }).annotate({ - "title": "LogsDataSourceConfig", - "description": "Configuration of data sources used in runs of the evaluation." - }), - Schema.Struct({ - "type": Schema.Literal("stored_completions").annotate({ - "description": "The type of data source. Always `stored_completions`." - }), - "metadata": Schema.optionalKey(Metadata), - "schema": Schema.Struct({}).annotate({ - "description": - "The json schema for the run data source items.\nLearn how to build JSON schemas [here](https://json-schema.org/).\n" - }) - }).annotate({ - "title": "StoredCompletionsDataSourceConfig", - "description": "Configuration of data sources used in runs of the evaluation." - }) - ], { mode: "oneOf" }), + EvalCustomDataSourceConfig, + EvalLogsDataSourceConfig, + EvalStoredCompletionsDataSourceConfig + ], { mode: "oneOf" }).annotate({ "description": "Configuration of data sources used in runs of the evaluation." }), "testing_criteria": Schema.Array( Schema.Union([ EvalGraderLabelModel, @@ -25098,820 +43391,331 @@ export const Eval = Schema.Struct({ "created_at": Schema.Number.annotate({ "description": "The Unix timestamp (in seconds) for when the eval was created.", "format": "unixtime" - }).check(Schema.isInt()), + }).check(Schema.isInt().annotate({ "expected": "an integer" })), "metadata": Metadata }).annotate({ "title": "Eval", "description": - "An Eval object with a data source config and testing criteria.\nAn Eval represents a task to be done for your LLM integration.\nLike:\n - Improve the quality of my chatbot\n - See how well my chatbot handles customer support\n - Check if o4-mini is better at my usecase than gpt-4o\n" + "An Eval object with a data source config and testing criteria.\nAn Eval represents a task to be done for your LLM integration.\nLike:\n - Improve the quality of my chatbot\n - See how well my chatbot handles customer support\n - Check if o4-mini is better at my usecase than gpt-6-astra\n", + "identifier": "Eval" }) -export type EvalRunList = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean -} -export const EvalRunList = Schema.Struct({ - "object": Schema.Literal("list").annotate({ - "description": "The type of this object. It is always set to \"list\".\n" - }), - "data": Schema.Array(EvalRun).annotate({ "description": "An array of eval run objects.\n" }), - "first_id": Schema.String.annotate({ "description": "The identifier of the first eval run in the data array." }), - "last_id": Schema.String.annotate({ "description": "The identifier of the last eval run in the data array." }), - "has_more": Schema.Boolean.annotate({ "description": "Indicates whether there are more evals available." }) -}).annotate({ "title": "EvalRunList", "description": "An object representing a list of runs for an evaluation.\n" }) -export type FineTuneReinforcementMethod = { - readonly "grader": - | { - readonly "type": "string_check" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "operation": "eq" | "ne" | "like" | "ilike" - } - | { - readonly "type": "text_similarity" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "evaluation_metric": - | "cosine" - | "fuzzy_match" - | "bleu" - | "gleu" - | "meteor" - | "rouge_1" - | "rouge_2" - | "rouge_3" - | "rouge_4" - | "rouge_5" - | "rouge_l" - } - | { readonly "type": "python"; readonly "name": string; readonly "source": string; readonly "image_tag"?: string } - | { - readonly "type": "score_model" - readonly "name": string - readonly "model": string - readonly "sampling_params"?: { - readonly "seed"?: number | null - readonly "top_p"?: number | null - readonly "temperature"?: number | null - readonly "max_completions_tokens"?: number | null - readonly "reasoning_effort"?: ReasoningEffort - } - readonly "input": ReadonlyArray - readonly "range"?: ReadonlyArray - } - | { - readonly "type": "multi" - readonly "name": string - readonly "graders": GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderLabelModel - readonly "calculate_output": string - } - readonly "hyperparameters"?: FineTuneReinforcementHyperparameters -} -export const FineTuneReinforcementMethod = Schema.Struct({ - "grader": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("string_check").annotate({ - "description": "The object type, which is always `string_check`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The input text. This may include template strings." }), - "reference": Schema.String.annotate({ "description": "The reference text. This may include template strings." }), - "operation": Schema.Literals(["eq", "ne", "like", "ilike"]).annotate({ - "description": "The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`." - }) - }).annotate({ "title": "StringCheckGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("text_similarity").annotate({ "description": "The type of grader." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The text being graded." }), - "reference": Schema.String.annotate({ "description": "The text being graded against." }), - "evaluation_metric": Schema.Literals([ - "cosine", - "fuzzy_match", - "bleu", - "gleu", - "meteor", - "rouge_1", - "rouge_2", - "rouge_3", - "rouge_4", - "rouge_5", - "rouge_l" - ]).annotate({ - "description": - "The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, \n`gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, \nor `rouge_l`.\n" - }) - }).annotate({ "title": "TextSimilarityGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("python").annotate({ "description": "The object type, which is always `python`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "source": Schema.String.annotate({ "description": "The source code of the python script." }), - "image_tag": Schema.optionalKey( - Schema.String.annotate({ "description": "The image tag to use for the python script." }) - ) - }).annotate({ "title": "PythonGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("score_model").annotate({ - "description": "The object type, which is always `score_model`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "model": Schema.String.annotate({ "description": "The model to use for the evaluation." }), - "sampling_params": Schema.optionalKey( - Schema.Struct({ - "seed": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling.\n" }) - .check(Schema.isInt()), - Schema.Null - ]) - ), - "top_p": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens.\n" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs.\n" }) - .check(Schema.isFinite()), - Schema.Null - ]) - ), - "max_completions_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The maximum number of tokens the grader model may generate in its response.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), - Schema.Null - ]) - ), - "reasoning_effort": Schema.optionalKey(ReasoningEffort) - }).annotate({ "description": "The sampling parameters for the model." }) - ), - "input": Schema.Array(EvalItem).annotate({ - "description": - "The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings.\n" - }), - "range": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isFinite())).annotate({ - "description": "The range of the score. Defaults to `[0, 1]`." - }) - ) - }).annotate({ "title": "ScoreModelGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("multi").annotate({ "description": "The object type, which is always `multi`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "graders": Schema.Union([ - GraderStringCheck, - GraderTextSimilarity, - GraderPython, - GraderScoreModel, - GraderLabelModel - ], { mode: "oneOf" }), - "calculate_output": Schema.String.annotate({ - "description": "A formula to calculate the output based on grader results." - }) - }).annotate({ "title": "MultiGrader", "description": "The grader used for the fine-tuning job." }) - ], { mode: "oneOf" }), - "hyperparameters": Schema.optionalKey(FineTuneReinforcementHyperparameters) -}).annotate({ "description": "Configuration for the reinforcement fine-tuning method." }) -export type RunGraderRequest = { - readonly "grader": - | { - readonly "type": "string_check" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "operation": "eq" | "ne" | "like" | "ilike" - } - | { - readonly "type": "text_similarity" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "evaluation_metric": - | "cosine" - | "fuzzy_match" - | "bleu" - | "gleu" - | "meteor" - | "rouge_1" - | "rouge_2" - | "rouge_3" - | "rouge_4" - | "rouge_5" - | "rouge_l" - } - | { readonly "type": "python"; readonly "name": string; readonly "source": string; readonly "image_tag"?: string } - | { - readonly "type": "score_model" - readonly "name": string - readonly "model": string - readonly "sampling_params"?: { - readonly "seed"?: number | null - readonly "top_p"?: number | null - readonly "temperature"?: number | null - readonly "max_completions_tokens"?: number | null - readonly "reasoning_effort"?: ReasoningEffort - } - readonly "input": ReadonlyArray - readonly "range"?: ReadonlyArray - } - | { - readonly "type": "multi" - readonly "name": string - readonly "graders": GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderLabelModel - readonly "calculate_output": string - } - readonly "item"?: {} - readonly "model_sample": string -} -export const RunGraderRequest = Schema.Struct({ - "grader": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("string_check").annotate({ - "description": "The object type, which is always `string_check`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The input text. This may include template strings." }), - "reference": Schema.String.annotate({ "description": "The reference text. This may include template strings." }), - "operation": Schema.Literals(["eq", "ne", "like", "ilike"]).annotate({ - "description": "The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`." - }) - }).annotate({ "title": "StringCheckGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("text_similarity").annotate({ "description": "The type of grader." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The text being graded." }), - "reference": Schema.String.annotate({ "description": "The text being graded against." }), - "evaluation_metric": Schema.Literals([ - "cosine", - "fuzzy_match", - "bleu", - "gleu", - "meteor", - "rouge_1", - "rouge_2", - "rouge_3", - "rouge_4", - "rouge_5", - "rouge_l" - ]).annotate({ - "description": - "The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, \n`gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, \nor `rouge_l`.\n" - }) - }).annotate({ "title": "TextSimilarityGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("python").annotate({ "description": "The object type, which is always `python`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "source": Schema.String.annotate({ "description": "The source code of the python script." }), - "image_tag": Schema.optionalKey( - Schema.String.annotate({ "description": "The image tag to use for the python script." }) - ) - }).annotate({ "title": "PythonGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("score_model").annotate({ - "description": "The object type, which is always `score_model`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "model": Schema.String.annotate({ "description": "The model to use for the evaluation." }), - "sampling_params": Schema.optionalKey( - Schema.Struct({ - "seed": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling.\n" }) - .check(Schema.isInt()), - Schema.Null - ]) - ), - "top_p": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens.\n" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs.\n" }) - .check(Schema.isFinite()), - Schema.Null - ]) - ), - "max_completions_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The maximum number of tokens the grader model may generate in its response.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), - Schema.Null - ]) - ), - "reasoning_effort": Schema.optionalKey(ReasoningEffort) - }).annotate({ "description": "The sampling parameters for the model." }) - ), - "input": Schema.Array(EvalItem).annotate({ - "description": - "The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings.\n" - }), - "range": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isFinite())).annotate({ - "description": "The range of the score. Defaults to `[0, 1]`." - }) - ) - }).annotate({ "title": "ScoreModelGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("multi").annotate({ "description": "The object type, which is always `multi`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "graders": Schema.Union([ - GraderStringCheck, - GraderTextSimilarity, - GraderPython, - GraderScoreModel, - GraderLabelModel - ], { mode: "oneOf" }), - "calculate_output": Schema.String.annotate({ - "description": "A formula to calculate the output based on grader results." - }) - }).annotate({ "title": "MultiGrader", "description": "The grader used for the fine-tuning job." }) - ], { mode: "oneOf" }), - "item": Schema.optionalKey( - Schema.Struct({}).annotate({ - "description": - "The dataset item provided to the grader. This will be used to populate \nthe `item` namespace. See [the guide](/docs/guides/graders) for more details. \n" - }) - ), - "model_sample": Schema.String.annotate({ - "description": - "The model sample to be evaluated. This value will be used to populate \nthe `sample` namespace. See [the guide](/docs/guides/graders) for more details.\nThe `output_json` variable will be populated if the model sample is a \nvalid JSON string.\n \n" - }) -}).annotate({ "title": "RunGraderRequest" }) -export type ValidateGraderRequest = { - readonly "grader": - | { - readonly "type": "string_check" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "operation": "eq" | "ne" | "like" | "ilike" - } - | { - readonly "type": "text_similarity" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "evaluation_metric": - | "cosine" - | "fuzzy_match" - | "bleu" - | "gleu" - | "meteor" - | "rouge_1" - | "rouge_2" - | "rouge_3" - | "rouge_4" - | "rouge_5" - | "rouge_l" - } - | { readonly "type": "python"; readonly "name": string; readonly "source": string; readonly "image_tag"?: string } - | { - readonly "type": "score_model" - readonly "name": string - readonly "model": string - readonly "sampling_params"?: { - readonly "seed"?: number | null - readonly "top_p"?: number | null - readonly "temperature"?: number | null - readonly "max_completions_tokens"?: number | null - readonly "reasoning_effort"?: ReasoningEffort - } - readonly "input": ReadonlyArray - readonly "range"?: ReadonlyArray - } - | { - readonly "type": "multi" - readonly "name": string - readonly "graders": GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderLabelModel - readonly "calculate_output": string - } +export type CreateEvalLabelModelGrader = { + readonly "type": "label_model" + readonly "name": string + readonly "model": string + readonly "input": ReadonlyArray + readonly "labels": ReadonlyArray + readonly "passing_labels": ReadonlyArray } -export const ValidateGraderRequest = Schema.Struct({ - "grader": Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("string_check").annotate({ - "description": "The object type, which is always `string_check`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The input text. This may include template strings." }), - "reference": Schema.String.annotate({ "description": "The reference text. This may include template strings." }), - "operation": Schema.Literals(["eq", "ne", "like", "ilike"]).annotate({ - "description": "The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`." - }) - }).annotate({ "title": "StringCheckGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("text_similarity").annotate({ "description": "The type of grader." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The text being graded." }), - "reference": Schema.String.annotate({ "description": "The text being graded against." }), - "evaluation_metric": Schema.Literals([ - "cosine", - "fuzzy_match", - "bleu", - "gleu", - "meteor", - "rouge_1", - "rouge_2", - "rouge_3", - "rouge_4", - "rouge_5", - "rouge_l" - ]).annotate({ - "description": - "The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, \n`gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, \nor `rouge_l`.\n" - }) - }).annotate({ "title": "TextSimilarityGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("python").annotate({ "description": "The object type, which is always `python`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "source": Schema.String.annotate({ "description": "The source code of the python script." }), - "image_tag": Schema.optionalKey( - Schema.String.annotate({ "description": "The image tag to use for the python script." }) - ) - }).annotate({ "title": "PythonGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("score_model").annotate({ - "description": "The object type, which is always `score_model`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "model": Schema.String.annotate({ "description": "The model to use for the evaluation." }), - "sampling_params": Schema.optionalKey( - Schema.Struct({ - "seed": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling.\n" }) - .check(Schema.isInt()), - Schema.Null - ]) - ), - "top_p": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens.\n" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs.\n" }) - .check(Schema.isFinite()), - Schema.Null - ]) - ), - "max_completions_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The maximum number of tokens the grader model may generate in its response.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), - Schema.Null - ]) - ), - "reasoning_effort": Schema.optionalKey(ReasoningEffort) - }).annotate({ "description": "The sampling parameters for the model." }) - ), - "input": Schema.Array(EvalItem).annotate({ - "description": - "The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings.\n" - }), - "range": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isFinite())).annotate({ - "description": "The range of the score. Defaults to `[0, 1]`." - }) - ) - }).annotate({ "title": "ScoreModelGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("multi").annotate({ "description": "The object type, which is always `multi`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "graders": Schema.Union([ - GraderStringCheck, - GraderTextSimilarity, - GraderPython, - GraderScoreModel, - GraderLabelModel - ], { mode: "oneOf" }), - "calculate_output": Schema.String.annotate({ - "description": "A formula to calculate the output based on grader results." - }) - }).annotate({ "title": "MultiGrader", "description": "The grader used for the fine-tuning job." }) - ], { mode: "oneOf" }) -}).annotate({ "title": "ValidateGraderRequest" }) -export type ValidateGraderResponse = { - readonly "grader"?: - | { - readonly "type": "string_check" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "operation": "eq" | "ne" | "like" | "ilike" - } - | { - readonly "type": "text_similarity" - readonly "name": string - readonly "input": string - readonly "reference": string - readonly "evaluation_metric": - | "cosine" - | "fuzzy_match" - | "bleu" - | "gleu" - | "meteor" - | "rouge_1" - | "rouge_2" - | "rouge_3" - | "rouge_4" - | "rouge_5" - | "rouge_l" - } - | { readonly "type": "python"; readonly "name": string; readonly "source": string; readonly "image_tag"?: string } - | { - readonly "type": "score_model" - readonly "name": string - readonly "model": string - readonly "sampling_params"?: { - readonly "seed"?: number | null - readonly "top_p"?: number | null - readonly "temperature"?: number | null - readonly "max_completions_tokens"?: number | null - readonly "reasoning_effort"?: ReasoningEffort +export const CreateEvalLabelModelGrader = Schema.Struct({ + "type": Schema.Literal("label_model").annotate({ "description": "The object type, which is always `label_model`." }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "model": Schema.String.annotate({ + "description": "The model to use for the evaluation. Must support structured outputs." + }), + "input": Schema.Array(CreateEvalItem).annotate({ + "description": + "A list of chat messages forming the prompt or context. May include variable references to the `item` namespace, ie {{item.name}}." + }), + "labels": Schema.Array(Schema.String).annotate({ + "description": "The labels to classify to each item in the evaluation." + }), + "passing_labels": Schema.Array(Schema.String).annotate({ + "description": "The labels that indicate a passing result. Must be a subset of labels." + }) +}).annotate({ + "title": "LabelModelGrader", + "description": "A LabelModelGrader object which uses a model to assign labels to each item\nin the evaluation.\n", + "identifier": "CreateEvalLabelModelGrader" +}) +export type EvalRun = { + readonly "object": "eval.run" + readonly "id": string + readonly "eval_id": string + readonly "status": string + readonly "model": string | null + readonly "name": string | null + readonly "created_at": number + readonly "report_url": string + readonly "result_counts": { + readonly "total": number + readonly "errored": number + readonly "failed": number + readonly "passed": number + } + readonly "per_model_usage": + | ReadonlyArray< + { + readonly "model_name": string + readonly "invocation_count": number + readonly "prompt_tokens": number + readonly "completion_tokens": number + readonly "total_tokens": number + readonly "cached_tokens": number } - readonly "input": ReadonlyArray - readonly "range"?: ReadonlyArray - } - | { - readonly "type": "multi" - readonly "name": string - readonly "graders": GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderLabelModel - readonly "calculate_output": string - } + > + | null + readonly "per_testing_criteria_results": + | ReadonlyArray<{ readonly "testing_criteria": string; readonly "passed": number; readonly "failed": number }> + | null + readonly "data_source": + | CreateEvalJsonlRunDataSource + | CreateEvalCompletionsRunDataSource + | CreateEvalResponsesRunDataSource + readonly "metadata": Metadata + readonly "error": EvalApiError | null } -export const ValidateGraderResponse = Schema.Struct({ - "grader": Schema.optionalKey(Schema.Union([ - Schema.Struct({ - "type": Schema.Literal("string_check").annotate({ - "description": "The object type, which is always `string_check`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The input text. This may include template strings." }), - "reference": Schema.String.annotate({ "description": "The reference text. This may include template strings." }), - "operation": Schema.Literals(["eq", "ne", "like", "ilike"]).annotate({ - "description": "The string check operation to perform. One of `eq`, `ne`, `like`, or `ilike`." - }) - }).annotate({ "title": "StringCheckGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("text_similarity").annotate({ "description": "The type of grader." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "input": Schema.String.annotate({ "description": "The text being graded." }), - "reference": Schema.String.annotate({ "description": "The text being graded against." }), - "evaluation_metric": Schema.Literals([ - "cosine", - "fuzzy_match", - "bleu", - "gleu", - "meteor", - "rouge_1", - "rouge_2", - "rouge_3", - "rouge_4", - "rouge_5", - "rouge_l" - ]).annotate({ - "description": - "The evaluation metric to use. One of `cosine`, `fuzzy_match`, `bleu`, \n`gleu`, `meteor`, `rouge_1`, `rouge_2`, `rouge_3`, `rouge_4`, `rouge_5`, \nor `rouge_l`.\n" - }) - }).annotate({ "title": "TextSimilarityGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("python").annotate({ "description": "The object type, which is always `python`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "source": Schema.String.annotate({ "description": "The source code of the python script." }), - "image_tag": Schema.optionalKey( - Schema.String.annotate({ "description": "The image tag to use for the python script." }) +export const EvalRun = Schema.Struct({ + "object": Schema.Literal("eval.run").annotate({ "description": "The type of the object. Always \"eval.run\"." }), + "id": Schema.String.annotate({ "description": "Unique identifier for the evaluation run." }), + "eval_id": Schema.String.annotate({ "description": "The identifier of the associated evaluation." }), + "status": Schema.String.annotate({ "description": "The status of the evaluation run." }), + "model": Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "The model that is evaluated, if applicable." + }), + "name": Schema.Union([Schema.String, Schema.Null]).annotate({ "description": "The name of the evaluation run." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the evaluation run was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "report_url": Schema.String.annotate({ + "description": "The URL to the rendered evaluation run report on the UI dashboard.", + "format": "uri" + }), + "result_counts": Schema.Struct({ + "total": Schema.Number.annotate({ "description": "Total number of executed output items." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "errored": Schema.Number.annotate({ "description": "Number of output items that resulted in an error." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "failed": Schema.Number.annotate({ "description": "Number of output items that failed to pass the evaluation." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "passed": Schema.Number.annotate({ "description": "Number of output items that passed the evaluation." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) + }).annotate({ "description": "Counters summarizing the outcomes of the evaluation run." }), + "per_model_usage": Schema.Union([ + Schema.Array(Schema.Struct({ + "model_name": Schema.String.annotate({ "description": "The name of the model." }), + "invocation_count": Schema.Number.annotate({ "description": "The number of invocations." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "prompt_tokens": Schema.Number.annotate({ "description": "The number of prompt tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "completion_tokens": Schema.Number.annotate({ "description": "The number of completion tokens generated." }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "cached_tokens": Schema.Number.annotate({ "description": "The number of tokens retrieved from cache." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) - }).annotate({ "title": "PythonGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("score_model").annotate({ - "description": "The object type, which is always `score_model`." - }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "model": Schema.String.annotate({ "description": "The model to use for the evaluation." }), - "sampling_params": Schema.optionalKey( - Schema.Struct({ - "seed": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "A seed value to initialize the randomness, during sampling.\n" }) - .check(Schema.isInt()), - Schema.Null - ]) - ), - "top_p": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "An alternative to temperature for nucleus sampling; 1.0 includes all tokens.\n" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ "description": "A higher temperature increases randomness in the outputs.\n" }) - .check(Schema.isFinite()), - Schema.Null - ]) - ), - "max_completions_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": "The maximum number of tokens the grader model may generate in its response.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)), - Schema.Null - ]) - ), - "reasoning_effort": Schema.optionalKey(ReasoningEffort) - }).annotate({ "description": "The sampling parameters for the model." }) + })), + Schema.Null + ]).annotate({ "description": "Usage statistics for each model during the evaluation run." }), + "per_testing_criteria_results": Schema.Union([ + Schema.Array(Schema.Struct({ + "testing_criteria": Schema.String.annotate({ "description": "A description of the testing criteria." }), + "passed": Schema.Number.annotate({ "description": "Number of tests passed for this criteria." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ), - "input": Schema.Array(EvalItem).annotate({ - "description": - "The input messages evaluated by the grader. Supports text, output text, input image, and input audio content blocks, and may include template strings.\n" - }), - "range": Schema.optionalKey( - Schema.Array(Schema.Number.check(Schema.isFinite())).annotate({ - "description": "The range of the score. Defaults to `[0, 1]`." - }) + "failed": Schema.Number.annotate({ "description": "Number of tests failed for this criteria." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) - }).annotate({ "title": "ScoreModelGrader", "description": "The grader used for the fine-tuning job." }), - Schema.Struct({ - "type": Schema.Literal("multi").annotate({ "description": "The object type, which is always `multi`." }), - "name": Schema.String.annotate({ "description": "The name of the grader." }), - "graders": Schema.Union([ - GraderStringCheck, - GraderTextSimilarity, - GraderPython, - GraderScoreModel, - GraderLabelModel - ], { mode: "oneOf" }), - "calculate_output": Schema.String.annotate({ - "description": "A formula to calculate the output based on grader results." - }) - }).annotate({ "title": "MultiGrader", "description": "The grader used for the fine-tuning job." }) - ], { mode: "oneOf" })) -}).annotate({ "title": "ValidateGraderResponse" }) -export type CreateResponse = { + })), + Schema.Null + ]).annotate({ "description": "Results per testing criteria applied during the evaluation run." }), + "data_source": Schema.Union([ + CreateEvalJsonlRunDataSource, + CreateEvalCompletionsRunDataSource, + CreateEvalResponsesRunDataSource + ], { mode: "oneOf" }).annotate({ "description": "Information about the run's data source." }), + "metadata": Metadata, + "error": Schema.Union([EvalApiError, Schema.Null]) +}).annotate({ + "title": "EvalRun", + "description": "A schema representing an evaluation run.\n", + "identifier": "EvalRun" +}) +export type CreateEvalRunRequest = { + readonly "name"?: string readonly "metadata"?: Metadata - readonly "top_logprobs"?: number - readonly "temperature"?: number | null - readonly "top_p"?: number | null + readonly "data_source": + | CreateEvalJsonlRunDataSource + | CreateEvalCompletionsRunDataSource + | CreateEvalResponsesRunDataSource +} +export const CreateEvalRunRequest = Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the run." })), + "metadata": Schema.optionalKey(Metadata), + "data_source": Schema.Union([ + CreateEvalJsonlRunDataSource, + CreateEvalCompletionsRunDataSource, + CreateEvalResponsesRunDataSource + ], { mode: "oneOf" }).annotate({ "description": "Details about the run's data source." }) +}).annotate({ "title": "CreateEvalRunRequest", "identifier": "CreateEvalRunRequest" }) +export type GraderMulti = { + readonly "type": "multi" + readonly "name": string + readonly "graders": { + readonly [x: string]: GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderLabelModel + } + readonly "calculate_output": string +} +export const GraderMulti = Schema.Struct({ + "type": Schema.Literal("multi").annotate({ "description": "The object type, which is always `multi`." }), + "name": Schema.String.annotate({ "description": "The name of the grader." }), + "graders": Schema.Record( + Schema.String, + Schema.Union([GraderStringCheck, GraderTextSimilarity, GraderPython, GraderScoreModel, GraderLabelModel], { + mode: "oneOf" + }) + ).check(Schema.isMinProperties(1).annotate({ "expected": "a value with at least 1 entry" })), + "calculate_output": Schema.String.annotate({ + "description": "A formula to calculate the output based on grader results." + }) +}).annotate({ + "title": "MultiGrader", + "description": "A MultiGrader object combines the output of multiple graders to produce a single score.", + "identifier": "GraderMulti" +}) +export type ConversationItemList = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "first_id": string + readonly "last_id": string +} +export const ConversationItemList = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), + "data": Schema.Array(ConversationItem).annotate({ "description": "A list of conversation items." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }), + "first_id": Schema.String.annotate({ "description": "The ID of the first item in the list." }), + "last_id": Schema.String.annotate({ "description": "The ID of the last item in the list." }) +}).annotate({ + "title": "The conversation item list", + "description": "A list of Conversation items.", + "identifier": "ConversationItemList" +}) +export type Response = { + readonly "metadata": Metadata + readonly "top_logprobs"?: number | null + readonly "temperature": number | null + readonly "top_p": number | null readonly "user"?: string | null - readonly "safety_identifier"?: string + readonly "safety_identifier"?: string | null readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null + readonly "prompt_cache_retention"?: "in_memory" | "24h" | null readonly "previous_response_id"?: string | null - readonly "model"?: - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null + readonly "model": ModelIdsResponses readonly "background"?: boolean | null readonly "max_tool_calls"?: number | null readonly "text"?: ResponseTextParam - readonly "tools"?: ToolsArray - readonly "tool_choice"?: ToolChoiceParam + readonly "tools": ToolsArray + readonly "tool_choice": ToolChoiceParam readonly "prompt"?: Prompt + readonly "service_tier"?: ServiceTierResponses readonly "truncation"?: "auto" | "disabled" | null - readonly "input"?: InputParam - readonly "include"?: ReadonlyArray | null - readonly "parallel_tool_calls"?: boolean | null - readonly "store"?: boolean | null - readonly "instructions"?: string | null - readonly "stream"?: boolean | null - readonly "stream_options"?: ResponseStreamOptions - readonly "conversation"?: ConversationParam | null - readonly "context_management"?: ReadonlyArray | null + readonly "id": string + readonly "object": "response" + readonly "status"?: "completed" | "failed" | "in_progress" | "cancelled" | "queued" | "incomplete" + readonly "access_programs"?: AccessProgramsBody | null + readonly "created_at": number + readonly "completed_at"?: number | null + readonly "error": ResponseError + readonly "incomplete_details": { + readonly "reason"?: "max_output_tokens" | "max_messages" | "content_filter" | "steered" + } | null + readonly "output": ReadonlyArray + readonly "reasoning"?: Reasoning | null + readonly "instructions": string | ReadonlyArray | null + readonly "output_text"?: string | null + readonly "usage"?: ResponseUsage | null + readonly "prompt_cache_options"?: PromptCacheOptions + readonly "prompt_cache_diagnostics"?: PromptCacheDiagnostics + readonly "moderation"?: Moderation | null + readonly "parallel_tool_calls": boolean + readonly "conversation"?: ResponseConversation | null readonly "max_output_tokens"?: number | null } -export const CreateResponse = Schema.Struct({ - "metadata": Schema.optionalKey(Metadata), +export const Response = Schema.Struct({ + "metadata": Metadata, "top_logprobs": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(20)], { - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }) - ) - ]) - ), - "temperature": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" })), Schema.Null ]) ), - "top_p": Schema.optionalKey(Schema.Union([ + "temperature": Schema.Union([ + Schema.Number.annotate({ + "description": + "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), + Schema.Null + ]), + "top_p": Schema.Union([ Schema.Number.annotate({ "description": "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), Schema.Null - ])), + ]), "user": Schema.optionalKey( Schema.Union([Schema.String, Schema.Null]).annotate({ "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" + "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" }) ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ + "safety_identifier": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) - ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( + "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 128 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ])), + "prompt_cache_key": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" + "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching).\n" }), Schema.Null ]) ), - "model": Schema.optionalKey( - Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ + "prompt_cache_retention": Schema.optionalKey(Schema.Union([ + Schema.Literals(["in_memory", "24h"]).annotate({ "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" - }) - ), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), + "Deprecated. Use `prompt_cache_options.ttl` instead.\n\nThe retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-retention).\nThis field expresses a maximum retention policy, while\n`prompt_cache_options.ttl` expresses a minimum cache lifetime. The two\nfields are independent and do not interact.\nFor `gpt-5.5`, `gpt-5.5-pro`, and future models, only `24h` is supported.\n\nFor older models that support both `in_memory` and `24h`, the default depends on your organization's data retention policy:\n - Organizations without ZDR enabled default to `24h`.\n - Organizations with ZDR enabled default to `in_memory` when `prompt_cache_retention` is not specified.\n" + }), + Schema.Null + ])), + "previous_response_id": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](https://developers.openai.com/api/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" + }), + Schema.Null + ])), + "model": Schema.suspend((): Schema.Codec => ModelIdsResponses).annotate({ + "description": + "Model ID used to generate the response, like `gpt-6-astra`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models)\nto browse and compare available models.\n" + }), "background": Schema.optionalKey( Schema.Union([ Schema.Boolean.annotate({ - "description": "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" + "description": + "Whether to run the model response in the background.\n[Learn more](https://developers.openai.com/api/docs/guides/background).\n" }), Schema.Null ]) @@ -25921,14 +43725,15 @@ export const CreateResponse = Schema.Struct({ Schema.Number.annotate({ "description": "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ), "text": Schema.optionalKey(ResponseTextParam), - "tools": Schema.optionalKey(ToolsArray), - "tool_choice": Schema.optionalKey(ToolChoiceParam), + "tools": ToolsArray, + "tool_choice": ToolChoiceParam, "prompt": Schema.optionalKey(Prompt), + "service_tier": Schema.optionalKey(ServiceTierResponses), "truncation": Schema.optionalKey(Schema.Union([ Schema.Literals(["auto", "disabled"]).annotate({ "description": @@ -25936,133 +43741,241 @@ export const CreateResponse = Schema.Struct({ }), Schema.Null ])), - "input": Schema.optionalKey(InputParam), - "include": Schema.optionalKey(Schema.Union([ - Schema.Array(IncludeEnum).annotate({ + "id": Schema.String.annotate({ "description": "Unique identifier for this Response.\n" }), + "object": Schema.Literal("response").annotate({ + "description": "The object type of this resource - always set to `response`.\n" + }), + "status": Schema.optionalKey( + Schema.Literals(["completed", "failed", "in_progress", "cancelled", "queued", "incomplete"]).annotate({ "description": - "Specify additional output data to include in the model response. Currently supported values are:\n- `web_search_call.action.sources`: Include the sources of the web search tool call.\n- `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items.\n- `computer_call_output.output.image_url`: Include image urls from the computer call output.\n- `file_search_call.results`: Include the search results of the file search tool call.\n- `message.input_image.image_url`: Include image urls from the input message.\n- `message.output_text.logprobs`: Include logprobs with assistant messages.\n- `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program)." - }), - Schema.Null - ])), - "parallel_tool_calls": Schema.optionalKey( + "The status of the response generation. One of `completed`, `failed`,\n`in_progress`, `cancelled`, `queued`, or `incomplete`.\n" + }) + ), + "access_programs": Schema.optionalKey(Schema.Union([AccessProgramsBody, Schema.Null])), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) of when this Response was created.\n", + "format": "unixtime" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), + "completed_at": Schema.optionalKey( Schema.Union([ - Schema.Boolean.annotate({ "description": "Whether to allow the model to run tool calls in parallel.\n" }), + Schema.Number.annotate({ + "description": + "Unix timestamp (in seconds) of when this Response was completed.\nOnly present when the status is `completed`.\n", + "format": "unixtime" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), Schema.Null ]) ), - "store": Schema.optionalKey( + "error": ResponseError, + "incomplete_details": Schema.Union([ + Schema.Struct({ + "reason": Schema.optionalKey( + Schema.Literals(["max_output_tokens", "max_messages", "content_filter", "steered"]).annotate({ + "description": + "The reason why the response is incomplete. `steered` means\nthe response stopped at a safe output boundary after a\nWebSocket `response.steer` event. The server can then create\na successor response automatically with the queued input.\n" + }) + ) + }).annotate({ "description": "Details about why the response is incomplete.\n" }), + Schema.Null + ]), + "output": Schema.Array(OutputItem).annotate({ + "description": + "An array of content items generated by the model.\n\n- The length and order of items in the `output` array is dependent\n on the model's response.\n- Rather than accessing the first item in the `output` array and\n assuming it's an `assistant` message with the content generated by\n the model, you might consider using the `output_text` property where\n supported in SDKs.\n" + }), + "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), + "instructions": Schema.Union([ Schema.Union([ - Schema.Boolean.annotate({ - "description": "Whether to store the generated model response for later retrieval via\nAPI.\n" + Schema.String.annotate({ + "description": "A text input to the model, equivalent to a text input with the\n`developer` role.\n" }), - Schema.Null - ]) - ), - "instructions": Schema.optionalKey(Schema.Union([ - Schema.String.annotate({ + Schema.Array(InputItem).annotate({ + "title": "Input item list", + "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" + }) + ], { mode: "oneOf" }).annotate({ "description": "A system (or developer) message inserted into the model's context.\n\nWhen using along with `previous_response_id`, the instructions from a previous\nresponse will not be carried over to the next response. This makes it simple\nto swap out system (or developer) messages in new responses.\n" }), Schema.Null - ])), - "stream": Schema.optionalKey(Schema.Union([ - Schema.Boolean.annotate({ - "description": - "If set to true, the model response data will be streamed to the client\nas it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).\nSee the [Streaming section below](/docs/api-reference/responses-streaming)\nfor more information.\n" - }), - Schema.Null - ])), - "stream_options": Schema.optionalKey(ResponseStreamOptions), - "conversation": Schema.optionalKey(Schema.Union([ConversationParam, Schema.Null])), - "context_management": Schema.optionalKey( + ]), + "output_text": Schema.optionalKey( Schema.Union([ - Schema.Array(ContextManagementParam).annotate({ - "description": "Context management configuration for this request.\n" - }).check(Schema.isMinLength(1)), + Schema.String.annotate({ + "description": + "SDK-only convenience property that contains the aggregated text output\nfrom all `output_text` items in the `output` array, if any are present.\nSupported in the Python and JavaScript SDKs.\n" + }), + Schema.Null + ]) + ), + "usage": Schema.optionalKey(Schema.Union([ResponseUsage, Schema.Null])), + "prompt_cache_options": Schema.optionalKey(PromptCacheOptions), + "prompt_cache_diagnostics": Schema.optionalKey(PromptCacheDiagnostics), + "moderation": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => Moderation).annotate({ + "description": + "Moderation results for the response input and output, if moderated completions were requested.\n" + }), Schema.Null ]) ), + "parallel_tool_calls": Schema.Boolean.annotate({ + "description": "Whether to allow the model to run tool calls in parallel.\n" + }), + "conversation": Schema.optionalKey(Schema.Union([ResponseConversation, Schema.Null])), "max_output_tokens": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(16)), + "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://developers.openai.com/api/docs/guides/reasoning).\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ) +}).annotate({ "title": "The response object", "identifier": "Response" }) +export type ResponseOutputItemAddedEvent = { + readonly "type": "response.output_item.added" + readonly "output_index": number + readonly "sequence_number": number + readonly "item": OutputItem +} +export const ResponseOutputItemAddedEvent = Schema.Struct({ + "type": Schema.Literal("response.output_item.added").annotate({ + "description": "The type of the event. Always `response.output_item.added`.\n" + }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was added.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item": Schema.suspend((): Schema.Codec => OutputItem).annotate({ + "description": + "The output item that was added. For reasoning items, `encrypted_content`\nmay be incomplete while the item is in progress. Use the reasoning item\nfrom the corresponding `response.output_item.done` event when passing it\nas input to a subsequent request.\n" + }) +}).annotate({ "description": "Emitted when a new output item is added.", "identifier": "ResponseOutputItemAddedEvent" }) +export type ResponseOutputItemDoneEvent = { + readonly "type": "response.output_item.done" + readonly "output_index": number + readonly "sequence_number": number + readonly "item": OutputItem +} +export const ResponseOutputItemDoneEvent = Schema.Struct({ + "type": Schema.Literal("response.output_item.done").annotate({ + "description": "The type of the event. Always `response.output_item.done`.\n" + }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was marked done.\n" }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item": Schema.suspend((): Schema.Codec => OutputItem).annotate({ + "description": "The output item that was marked done.\n" + }) +}).annotate({ + "description": "Emitted when an output item is marked done.", + "identifier": "ResponseOutputItemDoneEvent" }) -export type ResponsesClientEventResponseCreate = { - readonly "type": "response.create" +export type ResponseItemList = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "first_id": string + readonly "last_id": string +} +export const ResponseItemList = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), + "data": Schema.Array(ItemResource).annotate({ "description": "A list of items used to generate this response." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }), + "first_id": Schema.String.annotate({ "description": "The ID of the first item in the list." }), + "last_id": Schema.String.annotate({ "description": "The ID of the last item in the list." }) +}).annotate({ "description": "A list of Response items.", "identifier": "ResponseItemList" }) +export type CompactResource = { + readonly "id": string + readonly "object": "response.compaction" + readonly "output": ReadonlyArray + readonly "created_at": number + readonly "usage": ResponseUsage +} +export const CompactResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique identifier for the compacted response." }), + "object": Schema.Literal("response.compaction").annotate({ + "description": "The object type. Always `response.compaction`." + }), + "output": Schema.Array(ItemField).annotate({ "description": "The compacted list of output items." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the compacted conversation was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "usage": Schema.suspend((): Schema.Codec => ResponseUsage).annotate({ + "description": "Token accounting for the compaction pass, including cached, reasoning, and total tokens." + }) +}).annotate({ "title": "The compacted response object", "identifier": "CompactResource" }) +export type CreateResponse = { readonly "metadata"?: Metadata readonly "top_logprobs"?: number readonly "temperature"?: number | null readonly "top_p"?: number | null readonly "user"?: string | null - readonly "safety_identifier"?: string + readonly "safety_identifier"?: string | null readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null + readonly "prompt_cache_retention"?: "in_memory" | "24h" | null + readonly "prompt_cache_options"?: { + readonly "ttl"?: PromptCacheTTLEnum + readonly "mode"?: PromptCacheModeEnum + readonly "prewarm"?: boolean + readonly "comparison_response_id"?: string | null + } readonly "previous_response_id"?: string | null - readonly "model"?: - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null + readonly "model"?: ModelIdsResponses readonly "background"?: boolean | null readonly "max_tool_calls"?: number | null readonly "text"?: ResponseTextParam readonly "tools"?: ToolsArray readonly "tool_choice"?: ToolChoiceParam readonly "prompt"?: Prompt + readonly "access_programs"?: AccessProgramsParam + readonly "service_tier"?: ServiceTierResponses readonly "truncation"?: "auto" | "disabled" | null + readonly "reasoning"?: Reasoning | null readonly "input"?: InputParam readonly "include"?: ReadonlyArray | null readonly "parallel_tool_calls"?: boolean | null readonly "store"?: boolean | null readonly "instructions"?: string | null + readonly "moderation"?: ModerationParam | null readonly "stream"?: boolean | null readonly "stream_options"?: ResponseStreamOptions readonly "conversation"?: ConversationParam | null readonly "context_management"?: ReadonlyArray | null readonly "max_output_tokens"?: number | null } -export const ResponsesClientEventResponseCreate = Schema.Struct({ - "type": Schema.Literal("response.create").annotate({ - "description": "The type of the client event. Always `response.create`.\n" - }), +export const CreateResponse = Schema.Struct({ "metadata": Schema.optionalKey(Metadata), "top_logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ + Schema.Number.annotate({ + "description": + "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" })).check( + Schema.makeFilterGroup([ + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }), + Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" }) + ]).annotate({ "description": "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)).check( - Schema.makeFilterGroup([Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(20)], { - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }) - ) - ]) + }) + ) ), "temperature": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), Schema.Null ]) ), @@ -26070,73 +43983,87 @@ export const ResponsesClientEventResponseCreate = Schema.Struct({ Schema.Number.annotate({ "description": "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), Schema.Null ])), "user": Schema.optionalKey( Schema.Union([Schema.String, Schema.Null]).annotate({ "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" + "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" }) ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ + "safety_identifier": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) - ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( + "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 128 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ])), + "prompt_cache_key": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" + "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching).\n" }), Schema.Null ]) ), + "prompt_cache_retention": Schema.optionalKey(Schema.Union([ + Schema.Literals(["in_memory", "24h"]).annotate({ + "description": + "Deprecated. Use `prompt_cache_options.ttl` instead.\n\nThe retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-retention).\nThis field expresses a maximum retention policy, while\n`prompt_cache_options.ttl` expresses a minimum cache lifetime. The two\nfields are independent and do not interact.\nFor `gpt-5.5`, `gpt-5.5-pro`, and future models, only `24h` is supported.\n\nFor older models that support both `in_memory` and `24h`, the default depends on your organization's data retention policy:\n - Organizations without ZDR enabled default to `24h`.\n - Organizations with ZDR enabled default to `in_memory` when `prompt_cache_retention` is not specified.\n" + }), + Schema.Null + ])), + "prompt_cache_options": Schema.optionalKey(Schema.Struct({ + "ttl": Schema.optionalKey( + Schema.suspend((): Schema.Codec => PromptCacheTTLEnum).annotate({ + "description": + "The minimum lifetime applied to every implicit and explicit cache breakpoint written by the request. Defaults to `30m`, which is currently the only supported value. The backend may retain cache entries for longer." + }) + ), + "mode": Schema.optionalKey( + Schema.suspend((): Schema.Codec => PromptCacheModeEnum).annotate({ + "description": + "Controls whether OpenAI automatically creates an implicit cache breakpoint. Defaults to `implicit`. With `implicit`, OpenAI creates one implicit breakpoint and writes up to the latest three explicit breakpoints in the request. With `explicit`, OpenAI does not create an implicit breakpoint and writes up to the latest four explicit breakpoints. If there are no explicit breakpoints, the request does not use prompt caching." + }) + ), + "prewarm": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Prepares the prompt cache without generating output. Defaults to `false`. When set to `true`, overrides the `generate` field to `false`." + }) + ), + "comparison_response_id": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "The ID of a response to compare when diagnosing prompt cache reuse. Supplying this field requests prompt cache diagnostics when the feature is enabled." + }), + Schema.Null + ]) + ) + })), + "previous_response_id": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](https://developers.openai.com/api/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" + }), + Schema.Null + ])), "model": Schema.optionalKey( - Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ + Schema.suspend((): Schema.Codec => ModelIdsResponses).annotate({ "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" + "Model ID used to generate the response, like `gpt-6-astra`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models)\nto browse and compare available models.\n" }) ), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), "background": Schema.optionalKey( Schema.Union([ Schema.Boolean.annotate({ - "description": "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" + "description": + "Whether to run the model response in the background.\n[Learn more](https://developers.openai.com/api/docs/guides/background).\n" }), Schema.Null ]) @@ -26146,7 +44073,7 @@ export const ResponsesClientEventResponseCreate = Schema.Struct({ Schema.Number.annotate({ "description": "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ), @@ -26154,6 +44081,8 @@ export const ResponsesClientEventResponseCreate = Schema.Struct({ "tools": Schema.optionalKey(ToolsArray), "tool_choice": Schema.optionalKey(ToolChoiceParam), "prompt": Schema.optionalKey(Prompt), + "access_programs": Schema.optionalKey(AccessProgramsParam), + "service_tier": Schema.optionalKey(ServiceTierResponses), "truncation": Schema.optionalKey(Schema.Union([ Schema.Literals(["auto", "disabled"]).annotate({ "description": @@ -26161,6 +44090,7 @@ export const ResponsesClientEventResponseCreate = Schema.Struct({ }), Schema.Null ])), + "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), "input": Schema.optionalKey(InputParam), "include": Schema.optionalKey(Schema.Union([ Schema.Array(IncludeEnum).annotate({ @@ -26175,14 +44105,13 @@ export const ResponsesClientEventResponseCreate = Schema.Struct({ Schema.Null ]) ), - "store": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": "Whether to store the generated model response for later retrieval via\nAPI.\n" - }), - Schema.Null - ]) - ), + "store": Schema.optionalKey(Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to store the generated model response for later retrieval via\nAPI.\nDefaults to true when omitted.\nIf set to true, response data will be stored for at least 30 days, subject to the [data retention exceptions](https://developers.openai.com/api/docs/guides/your-data#v1responses).\n" + }), + Schema.Null + ])), "instructions": Schema.optionalKey(Schema.Union([ Schema.String.annotate({ "description": @@ -26190,10 +44119,18 @@ export const ResponsesClientEventResponseCreate = Schema.Struct({ }), Schema.Null ])), + "moderation": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => ModerationParam).annotate({ + "description": "Configuration for running moderation on the input and output of this response.\n" + }), + Schema.Null + ]) + ), "stream": Schema.optionalKey(Schema.Union([ Schema.Boolean.annotate({ "description": - "If set to true, the model response data will be streamed to the client\nas it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).\nSee the [Streaming section below](/docs/api-reference/responses-streaming)\nfor more information.\n" + "If set to true, the model response data will be streamed to the client\nas it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).\nSee the [Streaming section below](https://developers.openai.com/api/reference/resources/responses/streaming-events)\nfor more information.\n" }), Schema.Null ])), @@ -26203,7 +44140,7 @@ export const ResponsesClientEventResponseCreate = Schema.Struct({ Schema.Union([ Schema.Array(ContextManagementParam).annotate({ "description": "Context management configuration for this request.\n" - }).check(Schema.isMinLength(1)), + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), Schema.Null ]) ), @@ -26211,115 +44148,214 @@ export const ResponsesClientEventResponseCreate = Schema.Struct({ Schema.Union([ Schema.Number.annotate({ "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(16)), + "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://developers.openai.com/api/docs/guides/reasoning).\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(16).annotate({ "expected": "a value greater than or equal to 16" }) + ), Schema.Null ]) ) +}).annotate({ "identifier": "CreateResponse" }) +export type LiveMediaSessionCreateParams = { + readonly "model": ModelIdsLive + readonly "instructions"?: Instructions + readonly "audio"?: LiveMediaSessionAudioParam + readonly "delegation"?: Delegation + readonly "store"?: Store + readonly "input"?: Input + readonly "client"?: LiveClientConfigParam +} +export const LiveMediaSessionCreateParams = Schema.Struct({ + "model": ModelIdsLive, + "instructions": Schema.optionalKey(Instructions), + "audio": Schema.optionalKey( + Schema.suspend((): Schema.Codec => LiveMediaSessionAudioParam).annotate({ + "description": "Startup audio configuration. WebRTC and SIP negotiate their audio format on the media transport." + }) + ), + "delegation": Schema.optionalKey(Delegation), + "store": Schema.optionalKey(Store), + "input": Schema.optionalKey(Input), + "client": Schema.optionalKey(LiveClientConfigParam) }).annotate({ "description": - "Client event for creating a response over a persistent WebSocket connection.\nThis payload uses the same top-level fields as `POST /v1/responses`.\n\nNotes:\n- `stream` is implicit over WebSocket and should not be sent.\n- `background` is not supported over WebSocket.\n" + "Startup configuration for a Live media session. Follow the [Live prompting guide](https://developers.openai.com/api/docs/guides/live-prompting) when writing frontend instructions and the backend prompt under delegation.responses.instructions.", + "identifier": "LiveMediaSessionCreateParams" }) -export type ConversationItemList = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "first_id": string - readonly "last_id": string -} -export const ConversationItemList = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), - "data": Schema.Array(ConversationItem).annotate({ "description": "A list of conversation items." }), - "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }), - "first_id": Schema.String.annotate({ "description": "The ID of the first item in the list." }), - "last_id": Schema.String.annotate({ "description": "The ID of the last item in the list." }) -}).annotate({ "title": "The conversation item list", "description": "A list of Conversation items." }) -export type ResponseItemList = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "has_more": boolean - readonly "first_id": string - readonly "last_id": string -} -export const ResponseItemList = Schema.Struct({ - "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), - "data": Schema.Array(ItemResource).annotate({ "description": "A list of items used to generate this response." }), - "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }), - "first_id": Schema.String.annotate({ "description": "The ID of the first item in the list." }), - "last_id": Schema.String.annotate({ "description": "The ID of the last item in the list." }) -}).annotate({ "description": "A list of Response items." }) -export type Response = { - readonly "metadata": {} | null +export type LiveCallAcceptSession = { + readonly "model": string | "gpt-live-1" + readonly "instructions"?: Instructions + readonly "audio"?: LiveMediaSessionAudioParam + readonly "delegation"?: Delegation + readonly "store"?: Store + readonly "input"?: Input + readonly "type": "live" +} +export const LiveCallAcceptSession = Schema.Struct({ + "model": Schema.Union([ + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" }) + ), + Schema.Literal("gpt-live-1") + ]).annotate({ "description": "The Live model to use for the accepted call." }), + "instructions": Schema.optionalKey(Instructions), + "audio": Schema.optionalKey( + Schema.suspend((): Schema.Codec => LiveMediaSessionAudioParam).annotate({ + "description": + "Startup audio output configuration. SIP negotiates the media format; audio.format is only accepted for primary WebSockets. Voice cannot change after startup." + }) + ), + "delegation": Schema.optionalKey(Delegation), + "store": Schema.optionalKey(Store), + "input": Schema.optionalKey(Input), + "type": Schema.Literal("live").annotate({ "description": "The session type. Always `live`." }) +}).annotate({ + "description": + "Startup configuration for accepting an incoming Live SIP call. Follow the [Live prompting guide](https://developers.openai.com/api/docs/guides/live-prompting) when writing frontend and backend instructions.", + "identifier": "LiveCallAcceptSession" +}) +export type LiveForkRequest = { + readonly "session"?: LiveMediaSessionForkParams + readonly "transport": LiveWebRTCTransport +} +export const LiveForkRequest = Schema.Struct({ + "session": Schema.optionalKey( + Schema.suspend((): Schema.Codec => LiveMediaSessionForkParams).annotate({ + "description": + "Optional configuration overrides for the new Live session. Omit this object or send an empty object to inherit the stored session's settings." + }) + ), + "transport": Schema.suspend((): Schema.Codec => LiveWebRTCTransport).annotate({ + "description": "WebRTC transport with an SDP offer for the new connection to the forked session." + }) +}).annotate({ + "description": + "Fork a stored Live session onto a new WebRTC connection. Omit session or send an empty object to inherit its configuration.", + "identifier": "LiveForkRequest" +}) +export type SessionEvent = + | SessionEventError + | SessionEventAgentSessionEnvironmentReady + | SessionEventAgentSessionEnvironmentSuspended + | SessionEventAgentSessionEnvironmentExpired + | SessionEventAgentSessionEnvironmentReset + | SessionEventAgentOutputCommandExecutionOutputDelta + | SessionEventAgentSessionCreated + | SessionEventAgentSessionTurnCreated + | SessionEventAgentSessionTurnInProgress + | SessionEventAgentSessionTurnCompleted + | SessionEventAgentSessionTurnFailed + | SessionEventAgentSessionTurnCancelled + | SessionEventAgentSessionTurnItemAdded + | SessionEventAgentSessionIdle + | SessionEventAgentSessionInProgress + | SessionEventAgentSessionRequiresAction + | SessionEventAgentSessionFailed + | SessionEventAgentSessionEnvironmentPending + | SessionEventAgentSessionEnvironmentConnected + | SessionEventAgentSessionEnvironmentDisconnected + | SessionEventAgentSessionEnvironmentFailed + | SessionEventAgentSessionSubagentCreated + | SessionEventAgentSessionSubagentActive + | SessionEventAgentSessionSubagentClosed + | SessionEventAgentSessionTurnItemDone + | SessionEventAgentSessionTurnContentPartAdded + | SessionEventAgentSessionTurnContentPartDone + | SessionEventAgentSessionTurnOutputTextDelta + | SessionEventAgentSessionTurnOutputTextDone + | SessionEventAgentSessionTurnReasoningSummaryPartAdded + | SessionEventAgentSessionTurnReasoningSummaryPartDone + | SessionEventAgentSessionTurnReasoningSummaryTextDelta + | SessionEventAgentSessionTurnReasoningSummaryTextDone +export const SessionEvent = Schema.Union([ + SessionEventError, + SessionEventAgentSessionEnvironmentReady, + SessionEventAgentSessionEnvironmentSuspended, + SessionEventAgentSessionEnvironmentExpired, + SessionEventAgentSessionEnvironmentReset, + SessionEventAgentOutputCommandExecutionOutputDelta, + SessionEventAgentSessionCreated, + SessionEventAgentSessionTurnCreated, + SessionEventAgentSessionTurnInProgress, + SessionEventAgentSessionTurnCompleted, + SessionEventAgentSessionTurnFailed, + SessionEventAgentSessionTurnCancelled, + SessionEventAgentSessionTurnItemAdded, + SessionEventAgentSessionIdle, + SessionEventAgentSessionInProgress, + SessionEventAgentSessionRequiresAction, + SessionEventAgentSessionFailed, + SessionEventAgentSessionEnvironmentPending, + SessionEventAgentSessionEnvironmentConnected, + SessionEventAgentSessionEnvironmentDisconnected, + SessionEventAgentSessionEnvironmentFailed, + SessionEventAgentSessionSubagentCreated, + SessionEventAgentSessionSubagentActive, + SessionEventAgentSessionSubagentClosed, + SessionEventAgentSessionTurnItemDone, + SessionEventAgentSessionTurnContentPartAdded, + SessionEventAgentSessionTurnContentPartDone, + SessionEventAgentSessionTurnOutputTextDelta, + SessionEventAgentSessionTurnOutputTextDone, + SessionEventAgentSessionTurnReasoningSummaryPartAdded, + SessionEventAgentSessionTurnReasoningSummaryPartDone, + SessionEventAgentSessionTurnReasoningSummaryTextDelta, + SessionEventAgentSessionTurnReasoningSummaryTextDone +], { mode: "oneOf" }).annotate({ + "description": "An event emitted by a Managed Agents session.", + "identifier": "SessionEvent" +}) +export type BetaResponse = { + readonly "metadata": BetaMetadata readonly "top_logprobs"?: number | null readonly "temperature": number | null readonly "top_p": number | null readonly "user"?: string | null - readonly "safety_identifier"?: string + readonly "safety_identifier"?: string | null readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null + readonly "prompt_cache_retention"?: "in_memory" | "24h" | null readonly "previous_response_id"?: string | null - readonly "model": - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null + readonly "model": BetaModelIdsResponses readonly "background"?: boolean | null readonly "max_tool_calls"?: number | null - readonly "text"?: ResponseTextParam - readonly "tools": ReadonlyArray - readonly "tool_choice": - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam - readonly "prompt"?: Prompt + readonly "text"?: BetaResponseTextParam + readonly "tools": BetaToolsArray + readonly "tool_choice": BetaToolChoiceParam + readonly "prompt"?: BetaPrompt + readonly "service_tier"?: BetaServiceTierResponses readonly "truncation"?: "auto" | "disabled" | null readonly "id": string readonly "object": "response" readonly "status"?: "completed" | "failed" | "in_progress" | "cancelled" | "queued" | "incomplete" + readonly "access_programs": BetaAccessProgramsBody | null readonly "created_at": number readonly "completed_at"?: number | null - readonly "error": ResponseError - readonly "incomplete_details": { readonly "reason"?: "max_output_tokens" | "content_filter" } | null - readonly "output": ReadonlyArray - readonly "instructions": string | ReadonlyArray | null + readonly "error": BetaResponseError + readonly "incomplete_details": { + readonly "reason"?: "max_output_tokens" | "max_messages" | "content_filter" | "steered" + } | null + readonly "output": ReadonlyArray + readonly "reasoning"?: BetaReasoning | null + readonly "instructions": string | ReadonlyArray | null readonly "output_text"?: string | null - readonly "usage"?: ResponseUsage | null + readonly "usage"?: BetaResponseUsage | null + readonly "prompt_cache_options"?: BetaPromptCacheOptions + readonly "prompt_cache_diagnostics"?: BetaPromptCacheDiagnostics + readonly "moderation"?: BetaModeration | null readonly "parallel_tool_calls": boolean - readonly "conversation"?: Conversation_2 | null + readonly "conversation"?: BetaResponseConversation | null readonly "max_output_tokens"?: number | null } -export const Response = Schema.Struct({ - "metadata": Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]), +export const BetaResponse = Schema.Struct({ + "metadata": BetaMetadata, "top_logprobs": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)), + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" })), Schema.Null ]) ), @@ -26327,78 +44363,65 @@ export const Response = Schema.Struct({ Schema.Number.annotate({ "description": "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), Schema.Null ]), "top_p": Schema.Union([ Schema.Number.annotate({ "description": "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), Schema.Null ]), "user": Schema.optionalKey( Schema.Union([Schema.String, Schema.Null]).annotate({ "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" + "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" }) ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ + "safety_identifier": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) - ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( + "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 128 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ])), + "prompt_cache_key": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" + "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching).\n" }), Schema.Null ]) ), - "model": Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ + "prompt_cache_retention": Schema.optionalKey(Schema.Union([ + Schema.Literals(["in_memory", "24h"]).annotate({ + "description": + "Deprecated. Use `prompt_cache_options.ttl` instead.\n\nThe retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-retention).\nThis field expresses a maximum retention policy, while\n`prompt_cache_options.ttl` expresses a minimum cache lifetime. The two\nfields are independent and do not interact.\nFor `gpt-5.5`, `gpt-5.5-pro`, and future models, only `24h` is supported.\n\nFor older models that support both `in_memory` and `24h`, the default depends on your organization's data retention policy:\n - Organizations without ZDR enabled default to `24h`.\n - Organizations with ZDR enabled default to `in_memory` when `prompt_cache_retention` is not specified.\n" + }), + Schema.Null + ])), + "previous_response_id": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](https://developers.openai.com/api/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" + }), + Schema.Null + ])), + "model": Schema.suspend((): Schema.Codec => BetaModelIdsResponses).annotate({ "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" + "Model ID used to generate the response, like `gpt-6-astra`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models)\nto browse and compare available models.\n" }), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), "background": Schema.optionalKey( Schema.Union([ Schema.Boolean.annotate({ - "description": "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" + "description": + "Whether to run the model response in the background.\n[Learn more](https://developers.openai.com/api/docs/guides/background).\n" }), Schema.Null ]) @@ -26408,29 +44431,15 @@ export const Response = Schema.Struct({ Schema.Number.annotate({ "description": "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ), - "text": Schema.optionalKey(ResponseTextParam), - "tools": Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n" - }), - "tool_choice": Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam - ], { mode: "oneOf" }).annotate({ - "description": - "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n" - }), - "prompt": Schema.optionalKey(Prompt), + "text": Schema.optionalKey(BetaResponseTextParam), + "tools": BetaToolsArray, + "tool_choice": BetaToolChoiceParam, + "prompt": Schema.optionalKey(BetaPrompt), + "service_tier": Schema.optionalKey(BetaServiceTierResponses), "truncation": Schema.optionalKey(Schema.Union([ Schema.Literals(["auto", "disabled"]).annotate({ "description": @@ -26448,41 +44457,44 @@ export const Response = Schema.Struct({ "The status of the response generation. One of `completed`, `failed`,\n`in_progress`, `cancelled`, `queued`, or `incomplete`.\n" }) ), + "access_programs": Schema.Union([BetaAccessProgramsBody, Schema.Null]), "created_at": Schema.Number.annotate({ "description": "Unix timestamp (in seconds) of when this Response was created.\n", "format": "unixtime" - }).check(Schema.isFinite()), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), "completed_at": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": "Unix timestamp (in seconds) of when this Response was completed.\nOnly present when the status is `completed`.\n", "format": "unixtime" - }).check(Schema.isFinite()), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })), Schema.Null ]) ), - "error": ResponseError, + "error": BetaResponseError, "incomplete_details": Schema.Union([ Schema.Struct({ "reason": Schema.optionalKey( - Schema.Literals(["max_output_tokens", "content_filter"]).annotate({ - "description": "The reason why the response is incomplete." + Schema.Literals(["max_output_tokens", "max_messages", "content_filter", "steered"]).annotate({ + "description": + "The reason why the response is incomplete. `steered` means\nthe response stopped at a safe output boundary after a\nWebSocket `response.steer` event. The server can then create\na successor response automatically with the queued input.\n" }) ) }).annotate({ "description": "Details about why the response is incomplete.\n" }), Schema.Null ]), - "output": Schema.Array(OutputItem).annotate({ + "output": Schema.Array(BetaOutputItem).annotate({ "description": "An array of content items generated by the model.\n\n- The length and order of items in the `output` array is dependent\n on the model's response.\n- Rather than accessing the first item in the `output` array and\n assuming it's an `assistant` message with the content generated by\n the model, you might consider using the `output_text` property where\n supported in SDKs.\n" }), + "reasoning": Schema.optionalKey(Schema.Union([BetaReasoning, Schema.Null])), "instructions": Schema.Union([ Schema.Union([ Schema.String.annotate({ "description": "A text input to the model, equivalent to a text input with the\n`developer` role.\n" }), - Schema.Array(InputItem).annotate({ + Schema.Array(BetaInputItem).annotate({ "title": "Input item list", "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" }) @@ -26501,1768 +44513,791 @@ export const Response = Schema.Struct({ Schema.Null ]) ), - "usage": Schema.optionalKey(Schema.Union([ResponseUsage, Schema.Null])), + "usage": Schema.optionalKey(Schema.Union([BetaResponseUsage, Schema.Null])), + "prompt_cache_options": Schema.optionalKey(BetaPromptCacheOptions), + "prompt_cache_diagnostics": Schema.optionalKey(BetaPromptCacheDiagnostics), + "moderation": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaModeration).annotate({ + "description": + "Moderation results for the response input and output, if moderated completions were requested.\n" + }), + Schema.Null + ]) + ), "parallel_tool_calls": Schema.Boolean.annotate({ "description": "Whether to allow the model to run tool calls in parallel.\n" }), - "conversation": Schema.optionalKey(Schema.Union([Conversation_2, Schema.Null])), + "conversation": Schema.optionalKey(Schema.Union([BetaResponseConversation, Schema.Null])), "max_output_tokens": Schema.optionalKey( Schema.Union([ Schema.Number.annotate({ "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()), + "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://developers.openai.com/api/docs/guides/reasoning).\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null ]) ) -}).annotate({ "title": "The response object" }) -export type ResponseCompletedEvent = { - readonly "type": "response.completed" - readonly "response": { - readonly "metadata": {} | null - readonly "top_logprobs"?: number | null - readonly "temperature": number | null - readonly "top_p": number | null - readonly "user"?: string | null - readonly "safety_identifier"?: string - readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null - readonly "previous_response_id"?: string | null - readonly "model": - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null - readonly "background"?: boolean | null - readonly "max_tool_calls"?: number | null - readonly "text"?: ResponseTextParam - readonly "tools": ReadonlyArray - readonly "tool_choice": - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam - readonly "prompt"?: Prompt - readonly "truncation"?: "auto" | "disabled" | null - readonly "id": string - readonly "object": "response" - readonly "status"?: "completed" | "failed" | "in_progress" | "cancelled" | "queued" | "incomplete" - readonly "created_at": number - readonly "completed_at"?: number | null - readonly "error": ResponseError - readonly "incomplete_details": { readonly "reason"?: "max_output_tokens" | "content_filter" } | null - readonly "output": ReadonlyArray - readonly "instructions": string | ReadonlyArray | null - readonly "output_text"?: string | null - readonly "usage"?: ResponseUsage | null - readonly "parallel_tool_calls": boolean - readonly "conversation"?: Conversation_2 | null - readonly "max_output_tokens"?: number | null - } +}).annotate({ "title": "The response object", "identifier": "BetaResponse" }) +export type BetaResponseOutputItemAddedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.output_item.added" + readonly "output_index": number readonly "sequence_number": number + readonly "item": BetaOutputItem } -export const ResponseCompletedEvent = Schema.Struct({ - "type": Schema.Literal("response.completed").annotate({ - "description": "The type of the event. Always `response.completed`.\n" +export const BetaResponseOutputItemAddedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.output_item.added").annotate({ + "description": "The type of the event. Always `response.output_item.added`.\n" }), - "response": Schema.Struct({ - "metadata": Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]), - "top_logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)), - Schema.Null - ]) - ), - "temperature": Schema.Union([ - Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), - Schema.Null - ]), - "top_p": Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - Schema.Null - ]), - "user": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }) - ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) - ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" - }), - Schema.Null - ]) - ), - "model": Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ - "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" - }), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), - "background": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" - }), - Schema.Null - ]) - ), - "max_tool_calls": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "text": Schema.optionalKey(ResponseTextParam), - "tools": Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n" - }), - "tool_choice": Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam - ], { mode: "oneOf" }).annotate({ - "description": - "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n" - }), - "prompt": Schema.optionalKey(Prompt), - "truncation": Schema.optionalKey(Schema.Union([ - Schema.Literals(["auto", "disabled"]).annotate({ - "description": - "The truncation strategy to use for the model response.\n- `auto`: If the input to this Response exceeds\n the model's context window size, the model will truncate the\n response to fit the context window by dropping items from the beginning of the conversation.\n- `disabled` (default): If the input size will exceed the context window\n size for a model, the request will fail with a 400 error.\n" - }), - Schema.Null - ])), - "id": Schema.String.annotate({ "description": "Unique identifier for this Response.\n" }), - "object": Schema.Literal("response").annotate({ - "description": "The object type of this resource - always set to `response`.\n" - }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "failed", "in_progress", "cancelled", "queued", "incomplete"]).annotate({ - "description": - "The status of the response generation. One of `completed`, `failed`,\n`in_progress`, `cancelled`, `queued`, or `incomplete`.\n" - }) - ), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) of when this Response was created.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - "completed_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "Unix timestamp (in seconds) of when this Response was completed.\nOnly present when the status is `completed`.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "error": ResponseError, - "incomplete_details": Schema.Union([ - Schema.Struct({ - "reason": Schema.optionalKey( - Schema.Literals(["max_output_tokens", "content_filter"]).annotate({ - "description": "The reason why the response is incomplete." - }) - ) - }).annotate({ "description": "Details about why the response is incomplete.\n" }), - Schema.Null - ]), - "output": Schema.Array(OutputItem).annotate({ - "description": - "An array of content items generated by the model.\n\n- The length and order of items in the `output` array is dependent\n on the model's response.\n- Rather than accessing the first item in the `output` array and\n assuming it's an `assistant` message with the content generated by\n the model, you might consider using the `output_text` property where\n supported in SDKs.\n" - }), - "instructions": Schema.Union([ - Schema.Union([ - Schema.String.annotate({ - "description": "A text input to the model, equivalent to a text input with the\n`developer` role.\n" - }), - Schema.Array(InputItem).annotate({ - "title": "Input item list", - "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "A system (or developer) message inserted into the model's context.\n\nWhen using along with `previous_response_id`, the instructions from a previous\nresponse will not be carried over to the next response. This makes it simple\nto swap out system (or developer) messages in new responses.\n" - }), - Schema.Null - ]), - "output_text": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "SDK-only convenience property that contains the aggregated text output\nfrom all `output_text` items in the `output` array, if any are present.\nSupported in the Python and JavaScript SDKs.\n" - }), - Schema.Null - ]) - ), - "usage": Schema.optionalKey(Schema.Union([ResponseUsage, Schema.Null])), - "parallel_tool_calls": Schema.Boolean.annotate({ - "description": "Whether to allow the model to run tool calls in parallel.\n" - }), - "conversation": Schema.optionalKey(Schema.Union([Conversation_2, Schema.Null])), - "max_output_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ) - }).annotate({ "title": "The response object", "description": "Properties of the completed response.\n" }), - "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( - Schema.isInt() - ) -}).annotate({ "description": "Emitted when the model response is complete." }) -export type ResponseCreatedEvent = { - readonly "type": "response.created" - readonly "response": { - readonly "metadata": {} | null - readonly "top_logprobs"?: number | null - readonly "temperature": number | null - readonly "top_p": number | null - readonly "user"?: string | null - readonly "safety_identifier"?: string - readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null - readonly "previous_response_id"?: string | null - readonly "model": - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null - readonly "background"?: boolean | null - readonly "max_tool_calls"?: number | null - readonly "text"?: ResponseTextParam - readonly "tools": ReadonlyArray - readonly "tool_choice": - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam - readonly "prompt"?: Prompt - readonly "truncation"?: "auto" | "disabled" | null - readonly "id": string - readonly "object": "response" - readonly "status"?: "completed" | "failed" | "in_progress" | "cancelled" | "queued" | "incomplete" - readonly "created_at": number - readonly "completed_at"?: number | null - readonly "error": ResponseError - readonly "incomplete_details": { readonly "reason"?: "max_output_tokens" | "content_filter" } | null - readonly "output": ReadonlyArray - readonly "instructions": string | ReadonlyArray | null - readonly "output_text"?: string | null - readonly "usage"?: ResponseUsage | null - readonly "parallel_tool_calls": boolean - readonly "conversation"?: Conversation_2 | null - readonly "max_output_tokens"?: number | null + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was added.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item": Schema.suspend((): Schema.Codec => BetaOutputItem).annotate({ + "description": + "The output item that was added. For reasoning items, `encrypted_content`\nmay be incomplete while the item is in progress. Use the reasoning item\nfrom the corresponding `response.output_item.done` event when passing it\nas input to a subsequent request.\n" + }) +}).annotate({ + "description": "Emitted when a new output item is added.", + "identifier": "BetaResponseOutputItemAddedEvent" +}) +export type BetaResponseOutputItemDoneEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.output_item.done" + readonly "output_index": number + readonly "sequence_number": number + readonly "item": BetaOutputItem +} +export const BetaResponseOutputItemDoneEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.output_item.done").annotate({ + "description": "The type of the event. Always `response.output_item.done`.\n" + }), + "output_index": Schema.Number.annotate({ "description": "The index of the output item that was marked done.\n" }) + .check(Schema.isInt().annotate({ "expected": "an integer" })), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event.\n" }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "item": Schema.suspend((): Schema.Codec => BetaOutputItem).annotate({ + "description": "The output item that was marked done.\n" + }) +}).annotate({ + "description": "Emitted when an output item is marked done.", + "identifier": "BetaResponseOutputItemDoneEvent" +}) +export type BetaCompactResource = { + readonly "id": string + readonly "object": "response.compaction" + readonly "output": ReadonlyArray + readonly "created_at": number + readonly "usage": BetaResponseUsage +} +export const BetaCompactResource = Schema.Struct({ + "id": Schema.String.annotate({ "description": "The unique identifier for the compacted response." }), + "object": Schema.Literal("response.compaction").annotate({ + "description": "The object type. Always `response.compaction`." + }), + "output": Schema.Array(BetaItemField).annotate({ "description": "The compacted list of output items." }), + "created_at": Schema.Number.annotate({ + "description": "Unix timestamp (in seconds) when the compacted conversation was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "usage": Schema.suspend((): Schema.Codec => BetaResponseUsage).annotate({ + "description": "Token accounting for the compaction pass, including cached, reasoning, and total tokens." + }) +}).annotate({ "title": "The compacted response object", "identifier": "BetaCompactResource" }) +export type BetaResponseItemList = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "has_more": boolean + readonly "first_id": string + readonly "last_id": string +} +export const BetaResponseItemList = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The type of object returned, must be `list`." }), + "data": Schema.Array(BetaItemResource).annotate({ "description": "A list of items used to generate this response." }), + "has_more": Schema.Boolean.annotate({ "description": "Whether there are more items available." }), + "first_id": Schema.String.annotate({ "description": "The ID of the first item in the list." }), + "last_id": Schema.String.annotate({ "description": "The ID of the last item in the list." }) +}).annotate({ "description": "A list of Response items.", "identifier": "BetaResponseItemList" }) +export type BetaCreateResponse = { + readonly "metadata"?: BetaMetadata + readonly "top_logprobs"?: number + readonly "temperature"?: number | null + readonly "top_p"?: number | null + readonly "user"?: string | null + readonly "safety_identifier"?: string | null + readonly "prompt_cache_key"?: string | null + readonly "prompt_cache_retention"?: "in_memory" | "24h" | null + readonly "prompt_cache_options"?: { + readonly "ttl"?: BetaPromptCacheTTLEnum + readonly "mode"?: BetaPromptCacheModeEnum + readonly "prewarm"?: boolean + readonly "comparison_response_id"?: string | null } - readonly "sequence_number": number + readonly "previous_response_id"?: string | null + readonly "model"?: BetaModelIdsResponses + readonly "background"?: boolean | null + readonly "max_tool_calls"?: number | null + readonly "text"?: BetaResponseTextParam + readonly "tools"?: BetaToolsArray + readonly "tool_choice"?: BetaToolChoiceParam + readonly "prompt"?: BetaPrompt + readonly "access_programs"?: BetaAccessProgramsParam + readonly "service_tier"?: BetaServiceTierResponses + readonly "truncation"?: "auto" | "disabled" | null + readonly "reasoning"?: BetaReasoning | null + readonly "input"?: BetaInputParam + readonly "include"?: ReadonlyArray | null + readonly "parallel_tool_calls"?: boolean | null + readonly "store"?: boolean | null + readonly "instructions"?: string | null + readonly "moderation"?: BetaModerationParam | null + readonly "stream"?: boolean | null + readonly "stream_options"?: BetaResponseStreamOptions + readonly "conversation"?: BetaConversationParam | null + readonly "context_management"?: ReadonlyArray | null + readonly "max_output_tokens"?: number | null + readonly "multi_agent"?: BetaMultiAgentParam | null } -export const ResponseCreatedEvent = Schema.Struct({ - "type": Schema.Literal("response.created").annotate({ - "description": "The type of the event. Always `response.created`.\n" - }), - "response": Schema.Struct({ - "metadata": Schema.Union([ - Schema.Struct({}).annotate({ +export const BetaCreateResponse = Schema.Struct({ + "metadata": Schema.optionalKey(BetaMetadata), + "top_logprobs": Schema.optionalKey( + Schema.Number.annotate({ + "description": + "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" })).check( + Schema.makeFilterGroup([ + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }), + Schema.isLessThanOrEqualTo(20).annotate({ "expected": "a value less than or equal to 20" }) + ]).annotate({ "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]), - "top_logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)), - Schema.Null - ]) - ), - "temperature": Schema.Union([ + "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" + }) + ) + ), + "temperature": Schema.optionalKey( + Schema.Union([ Schema.Number.annotate({ "description": "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(2).annotate({ "expected": "a value less than or equal to 2" })), Schema.Null - ]), - "top_p": Schema.Union([ - Schema.Number.annotate({ + ]) + ), + "top_p": Schema.optionalKey(Schema.Union([ + Schema.Number.annotate({ + "description": + "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" + }).check(Schema.isFinite().annotate({ "expected": "a finite number" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1).annotate({ "expected": "a value less than or equal to 1" })), + Schema.Null + ])), + "user": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }) + ), + "safety_identifier": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 128 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](https://developers.openai.com/api/docs/guides/safety-best-practices#implement-safety-identifiers).\n" + }).check(Schema.isMaxCodePoints(128).annotate({ "expected": "a string with at most 128 code points" })), + Schema.Null + ])), + "prompt_cache_key": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": - "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), + "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching).\n" + }), Schema.Null - ]), - "user": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ + ]) + ), + "prompt_cache_retention": Schema.optionalKey(Schema.Union([ + Schema.Literals(["in_memory", "24h"]).annotate({ + "description": + "Deprecated. Use `prompt_cache_options.ttl` instead.\n\nThe retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](https://developers.openai.com/api/docs/guides/prompt-caching#prompt-cache-retention).\nThis field expresses a maximum retention policy, while\n`prompt_cache_options.ttl` expresses a minimum cache lifetime. The two\nfields are independent and do not interact.\nFor `gpt-5.5`, `gpt-5.5-pro`, and future models, only `24h` is supported.\n\nFor older models that support both `in_memory` and `24h`, the default depends on your organization's data retention policy:\n - Organizations without ZDR enabled default to `24h`.\n - Organizations with ZDR enabled default to `in_memory` when `prompt_cache_retention` is not specified.\n" + }), + Schema.Null + ])), + "prompt_cache_options": Schema.optionalKey(Schema.Struct({ + "ttl": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaPromptCacheTTLEnum).annotate({ "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" + "The minimum lifetime applied to every implicit and explicit cache breakpoint written by the request. Defaults to `30m`, which is currently the only supported value. The backend may retain cache entries for longer." }) ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ + "mode": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaPromptCacheModeEnum).annotate({ "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" + "Controls whether OpenAI automatically creates an implicit cache breakpoint. Defaults to `implicit`. With `implicit`, OpenAI creates one implicit breakpoint and writes up to the latest three explicit breakpoints in the request. With `explicit`, OpenAI does not create an implicit breakpoint and writes up to the latest four explicit breakpoints. If there are no explicit breakpoints, the request does not use prompt caching." }) ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) + "prewarm": Schema.optionalKey( + Schema.Boolean.annotate({ + "description": + "Prepares the prompt cache without generating output. Defaults to `false`. When set to `true`, overrides the `generate` field to `false`." + }) ), - "previous_response_id": Schema.optionalKey( + "comparison_response_id": Schema.optionalKey( Schema.Union([ Schema.String.annotate({ "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" + "The ID of a response to compare when diagnosing prompt cache reuse. Supplying this field requests prompt cache diagnostics when the feature is enabled." }), Schema.Null ]) - ), - "model": Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ + ) + })), + "previous_response_id": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" + "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](https://developers.openai.com/api/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" }), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), - "background": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" - }), - Schema.Null - ]) - ), - "max_tool_calls": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "text": Schema.optionalKey(ResponseTextParam), - "tools": Schema.Array(Tool).annotate({ + Schema.Null + ])), + "model": Schema.optionalKey( + Schema.suspend((): Schema.Codec => BetaModelIdsResponses).annotate({ + "description": + "Model ID used to generate the response, like `gpt-6-astra`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](https://developers.openai.com/api/docs/models)\nto browse and compare available models.\n" + }) + ), + "background": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to run the model response in the background.\n[Learn more](https://developers.openai.com/api/docs/guides/background).\n" + }), + Schema.Null + ]) + ), + "max_tool_calls": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ), + "text": Schema.optionalKey(BetaResponseTextParam), + "tools": Schema.optionalKey(BetaToolsArray), + "tool_choice": Schema.optionalKey(BetaToolChoiceParam), + "prompt": Schema.optionalKey(BetaPrompt), + "access_programs": Schema.optionalKey(BetaAccessProgramsParam), + "service_tier": Schema.optionalKey(BetaServiceTierResponses), + "truncation": Schema.optionalKey(Schema.Union([ + Schema.Literals(["auto", "disabled"]).annotate({ "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n" + "The truncation strategy to use for the model response.\n- `auto`: If the input to this Response exceeds\n the model's context window size, the model will truncate the\n response to fit the context window by dropping items from the beginning of the conversation.\n- `disabled` (default): If the input size will exceed the context window\n size for a model, the request will fail with a 400 error.\n" }), - "tool_choice": Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam - ], { mode: "oneOf" }).annotate({ + Schema.Null + ])), + "reasoning": Schema.optionalKey(Schema.Union([BetaReasoning, Schema.Null])), + "input": Schema.optionalKey(BetaInputParam), + "include": Schema.optionalKey(Schema.Union([ + Schema.Array(BetaIncludeEnum).annotate({ "description": - "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n" + "Specify additional output data to include in the model response. Currently supported values are:\n- `web_search_call.action.sources`: Include the sources of the web search tool call.\n- `code_interpreter_call.outputs`: Includes the outputs of python code execution in code interpreter tool call items.\n- `computer_call_output.output.image_url`: Include image urls from the computer call output.\n- `file_search_call.results`: Include the search results of the file search tool call.\n- `message.input_image.image_url`: Include image urls from the input message.\n- `message.output_text.logprobs`: Include logprobs with assistant messages.\n- `reasoning.encrypted_content`: Includes an encrypted version of reasoning tokens in reasoning item outputs. This enables reasoning items to be used in multi-turn conversations when using the Responses API statelessly (like when the `store` parameter is set to `false`, or when an organization is enrolled in the zero data retention program)." }), - "prompt": Schema.optionalKey(Prompt), - "truncation": Schema.optionalKey(Schema.Union([ - Schema.Literals(["auto", "disabled"]).annotate({ - "description": - "The truncation strategy to use for the model response.\n- `auto`: If the input to this Response exceeds\n the model's context window size, the model will truncate the\n response to fit the context window by dropping items from the beginning of the conversation.\n- `disabled` (default): If the input size will exceed the context window\n size for a model, the request will fail with a 400 error.\n" + Schema.Null + ])), + "parallel_tool_calls": Schema.optionalKey( + Schema.Union([ + Schema.Boolean.annotate({ "description": "Whether to allow the model to run tool calls in parallel.\n" }), + Schema.Null + ]) + ), + "store": Schema.optionalKey(Schema.Union([ + Schema.Boolean.annotate({ + "description": + "Whether to store the generated model response for later retrieval via\nAPI.\nDefaults to true when omitted.\nIf set to true, response data will be stored for at least 30 days, subject to the [data retention exceptions](https://developers.openai.com/api/docs/guides/your-data#v1responses).\n" + }), + Schema.Null + ])), + "instructions": Schema.optionalKey(Schema.Union([ + Schema.String.annotate({ + "description": + "A system (or developer) message inserted into the model's context.\n\nWhen using along with `previous_response_id`, the instructions from a previous\nresponse will not be carried over to the next response. This makes it simple\nto swap out system (or developer) messages in new responses.\n" + }), + Schema.Null + ])), + "moderation": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaModerationParam).annotate({ + "description": "Configuration for running moderation on the input and output of this response.\n" }), Schema.Null - ])), - "id": Schema.String.annotate({ "description": "Unique identifier for this Response.\n" }), - "object": Schema.Literal("response").annotate({ - "description": "The object type of this resource - always set to `response`.\n" + ]) + ), + "stream": Schema.optionalKey(Schema.Union([ + Schema.Boolean.annotate({ + "description": + "If set to true, the model response data will be streamed to the client\nas it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).\nSee the [Streaming section below](https://developers.openai.com/api/reference/resources/responses/streaming-events)\nfor more information.\n" }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "failed", "in_progress", "cancelled", "queued", "incomplete"]).annotate({ + Schema.Null + ])), + "stream_options": Schema.optionalKey(BetaResponseStreamOptions), + "conversation": Schema.optionalKey(Schema.Union([BetaConversationParam, Schema.Null])), + "context_management": Schema.optionalKey( + Schema.Union([ + Schema.Array(BetaContextManagementParam).annotate({ + "description": "Context management configuration for this request.\n" + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), + Schema.Null + ]) + ), + "max_output_tokens": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ "description": - "The status of the response generation. One of `completed`, `failed`,\n`in_progress`, `cancelled`, `queued`, or `incomplete`.\n" - }) - ), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) of when this Response was created.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - "completed_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "Unix timestamp (in seconds) of when this Response was completed.\nOnly present when the status is `completed`.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "error": ResponseError, - "incomplete_details": Schema.Union([ - Schema.Struct({ - "reason": Schema.optionalKey( - Schema.Literals(["max_output_tokens", "content_filter"]).annotate({ - "description": "The reason why the response is incomplete." - }) - ) - }).annotate({ "description": "Details about why the response is incomplete.\n" }), + "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](https://developers.openai.com/api/docs/guides/reasoning).\n" + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(16).annotate({ "expected": "a value greater than or equal to 16" }) + ), Schema.Null - ]), - "output": Schema.Array(OutputItem).annotate({ + ]) + ), + "multi_agent": Schema.optionalKey( + Schema.Union([ + Schema.suspend((): Schema.Codec => BetaMultiAgentParam).annotate({ + "description": "Configuration for server-hosted multi-agent execution." + }), + Schema.Null + ]) + ) +}).annotate({ "identifier": "BetaCreateResponse" }) +export type EvalList = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean +} +export const EvalList = Schema.Struct({ + "object": Schema.Literal("list").annotate({ + "description": "The type of this object. It is always set to \"list\".\n" + }), + "data": Schema.Array(Eval).annotate({ "description": "An array of eval objects.\n" }), + "first_id": Schema.String.annotate({ "description": "The identifier of the first eval in the data array." }), + "last_id": Schema.String.annotate({ "description": "The identifier of the last eval in the data array." }), + "has_more": Schema.Boolean.annotate({ "description": "Indicates whether there are more evals available." }) +}).annotate({ + "title": "EvalList", + "description": "An object representing a list of evals.\n", + "identifier": "EvalList" +}) +export type CreateEvalRequest = { + readonly "name"?: string + readonly "metadata"?: Metadata + readonly "data_source_config": + | CreateEvalCustomDataSourceConfig + | CreateEvalLogsDataSourceConfig + | CreateEvalStoredCompletionsDataSourceConfig + readonly "testing_criteria": ReadonlyArray< + | CreateEvalLabelModelGrader + | EvalGraderStringCheck + | EvalGraderTextSimilarity + | EvalGraderPython + | EvalGraderScoreModel + > +} +export const CreateEvalRequest = Schema.Struct({ + "name": Schema.optionalKey(Schema.String.annotate({ "description": "The name of the evaluation." })), + "metadata": Schema.optionalKey(Metadata), + "data_source_config": Schema.Union([ + CreateEvalCustomDataSourceConfig, + CreateEvalLogsDataSourceConfig, + CreateEvalStoredCompletionsDataSourceConfig + ], { mode: "oneOf" }).annotate({ + "description": + "The configuration for the data source used for the evaluation runs. Dictates the schema of the data used in the evaluation." + }), + "testing_criteria": Schema.Array( + Schema.Union([ + CreateEvalLabelModelGrader, + EvalGraderStringCheck, + EvalGraderTextSimilarity, + EvalGraderPython, + EvalGraderScoreModel + ], { mode: "oneOf" }) + ).annotate({ + "description": + "A list of graders for all eval runs in this group. Graders can reference variables in the data source using double curly braces notation, like `{{item.variable_name}}`. To reference the model's output, use the `sample` namespace (ie, `{{sample.output_text}}`)." + }) +}).annotate({ "title": "CreateEvalRequest", "identifier": "CreateEvalRequest" }) +export type EvalRunList = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string + readonly "last_id": string + readonly "has_more": boolean +} +export const EvalRunList = Schema.Struct({ + "object": Schema.Literal("list").annotate({ + "description": "The type of this object. It is always set to \"list\".\n" + }), + "data": Schema.Array(EvalRun).annotate({ "description": "An array of eval run objects.\n" }), + "first_id": Schema.String.annotate({ "description": "The identifier of the first eval run in the data array." }), + "last_id": Schema.String.annotate({ "description": "The identifier of the last eval run in the data array." }), + "has_more": Schema.Boolean.annotate({ "description": "Indicates whether there are more evals available." }) +}).annotate({ + "title": "EvalRunList", + "description": "An object representing a list of runs for an evaluation.\n", + "identifier": "EvalRunList" +}) +export type RunGraderRequest = { + readonly "grader": GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderMulti + readonly "item"?: { readonly [x: string]: Schema.Json } + readonly "model_sample": string +} +export const RunGraderRequest = Schema.Struct({ + "grader": Schema.Union([GraderStringCheck, GraderTextSimilarity, GraderPython, GraderScoreModel, GraderMulti], { + mode: "oneOf" + }).annotate({ "description": "The grader used for the fine-tuning job." }), + "item": Schema.optionalKey( + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).annotate({ "description": - "An array of content items generated by the model.\n\n- The length and order of items in the `output` array is dependent\n on the model's response.\n- Rather than accessing the first item in the `output` array and\n assuming it's an `assistant` message with the content generated by\n the model, you might consider using the `output_text` property where\n supported in SDKs.\n" - }), - "instructions": Schema.Union([ - Schema.Union([ - Schema.String.annotate({ - "description": "A text input to the model, equivalent to a text input with the\n`developer` role.\n" - }), - Schema.Array(InputItem).annotate({ - "title": "Input item list", - "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "A system (or developer) message inserted into the model's context.\n\nWhen using along with `previous_response_id`, the instructions from a previous\nresponse will not be carried over to the next response. This makes it simple\nto swap out system (or developer) messages in new responses.\n" - }), - Schema.Null - ]), - "output_text": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "SDK-only convenience property that contains the aggregated text output\nfrom all `output_text` items in the `output` array, if any are present.\nSupported in the Python and JavaScript SDKs.\n" - }), - Schema.Null - ]) - ), - "usage": Schema.optionalKey(Schema.Union([ResponseUsage, Schema.Null])), - "parallel_tool_calls": Schema.Boolean.annotate({ - "description": "Whether to allow the model to run tool calls in parallel.\n" - }), - "conversation": Schema.optionalKey(Schema.Union([Conversation_2, Schema.Null])), - "max_output_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ) - }).annotate({ "title": "The response object", "description": "The response that was created.\n" }), + "The dataset item provided to the grader. This will be used to populate\nthe `item` namespace. See [the guide](https://developers.openai.com/api/docs/guides/graders) for more details.\n" + }) + ), + "model_sample": Schema.String.annotate({ + "description": + "The model sample to be evaluated. This value will be used to populate\nthe `sample` namespace. See [the guide](https://developers.openai.com/api/docs/guides/graders) for more details.\nThe `output_json` variable will be populated if the model sample is a\nvalid JSON string.\n" + }) +}).annotate({ "title": "RunGraderRequest", "identifier": "RunGraderRequest" }) +export type ValidateGraderRequest = { + readonly "grader": GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderMulti +} +export const ValidateGraderRequest = Schema.Struct({ + "grader": Schema.Union([GraderStringCheck, GraderTextSimilarity, GraderPython, GraderScoreModel, GraderMulti], { + mode: "oneOf" + }).annotate({ "description": "The grader used for the fine-tuning job." }) +}).annotate({ "title": "ValidateGraderRequest", "identifier": "ValidateGraderRequest" }) +export type ValidateGraderResponse = { + readonly "grader"?: GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderMulti +} +export const ValidateGraderResponse = Schema.Struct({ + "grader": Schema.optionalKey( + Schema.Union([GraderStringCheck, GraderTextSimilarity, GraderPython, GraderScoreModel, GraderMulti], { + mode: "oneOf" + }).annotate({ "description": "The grader used for the fine-tuning job." }) + ) +}).annotate({ "title": "ValidateGraderResponse", "identifier": "ValidateGraderResponse" }) +export type FineTuneReinforcementMethod = { + readonly "grader": GraderStringCheck | GraderTextSimilarity | GraderPython | GraderScoreModel | GraderMulti + readonly "hyperparameters"?: FineTuneReinforcementHyperparameters +} +export const FineTuneReinforcementMethod = Schema.Struct({ + "grader": Schema.Union([GraderStringCheck, GraderTextSimilarity, GraderPython, GraderScoreModel, GraderMulti], { + mode: "oneOf" + }).annotate({ "description": "The grader used for the fine-tuning job." }), + "hyperparameters": Schema.optionalKey(FineTuneReinforcementHyperparameters) +}).annotate({ + "description": "Configuration for the reinforcement fine-tuning method.", + "identifier": "FineTuneReinforcementMethod" +}) +export type ResponseCompletedEvent = { + readonly "type": "response.completed" + readonly "response": Response + readonly "sequence_number": number +} +export const ResponseCompletedEvent = Schema.Struct({ + "type": Schema.Literal("response.completed").annotate({ + "description": "The type of the event. Always `response.completed`.\n" + }), + "response": Schema.suspend((): Schema.Codec => Response).annotate({ + "description": "Properties of the completed response.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ "description": "Emitted when the model response is complete.", "identifier": "ResponseCompletedEvent" }) +export type ResponseCreatedEvent = { + readonly "type": "response.created" + readonly "response": Response + readonly "sequence_number": number +} +export const ResponseCreatedEvent = Schema.Struct({ + "type": Schema.Literal("response.created").annotate({ + "description": "The type of the event. Always `response.created`.\n" + }), + "response": Schema.suspend((): Schema.Codec => Response).annotate({ + "description": "The response that was created.\n" + }), "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( - Schema.isInt() + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "An event that is emitted when a response is created.\n", + "identifier": "ResponseCreatedEvent" +}) +export type ResponseInProgressEvent = { + readonly "type": "response.in_progress" + readonly "response": Response + readonly "sequence_number": number +} +export const ResponseInProgressEvent = Schema.Struct({ + "type": Schema.Literal("response.in_progress").annotate({ + "description": "The type of the event. Always `response.in_progress`.\n" + }), + "response": Schema.suspend((): Schema.Codec => Response).annotate({ + "description": "The response that is in progress.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "An event that is emitted when a response is created.\n" }) +}).annotate({ "description": "Emitted when the response is in progress.", "identifier": "ResponseInProgressEvent" }) export type ResponseFailedEvent = { readonly "type": "response.failed" readonly "sequence_number": number - readonly "response": { - readonly "metadata": {} | null - readonly "top_logprobs"?: number | null - readonly "temperature": number | null - readonly "top_p": number | null - readonly "user"?: string | null - readonly "safety_identifier"?: string - readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null - readonly "previous_response_id"?: string | null - readonly "model": - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null - readonly "background"?: boolean | null - readonly "max_tool_calls"?: number | null - readonly "text"?: ResponseTextParam - readonly "tools": ReadonlyArray - readonly "tool_choice": - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam - readonly "prompt"?: Prompt - readonly "truncation"?: "auto" | "disabled" | null - readonly "id": string - readonly "object": "response" - readonly "status"?: "completed" | "failed" | "in_progress" | "cancelled" | "queued" | "incomplete" - readonly "created_at": number - readonly "completed_at"?: number | null - readonly "error": ResponseError - readonly "incomplete_details": { readonly "reason"?: "max_output_tokens" | "content_filter" } | null - readonly "output": ReadonlyArray - readonly "instructions": string | ReadonlyArray | null - readonly "output_text"?: string | null - readonly "usage"?: ResponseUsage | null - readonly "parallel_tool_calls": boolean - readonly "conversation"?: Conversation_2 | null - readonly "max_output_tokens"?: number | null - } + readonly "response": Response } export const ResponseFailedEvent = Schema.Struct({ "type": Schema.Literal("response.failed").annotate({ "description": "The type of the event. Always `response.failed`.\n" }), "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + Schema.isInt().annotate({ "expected": "an integer" }) ), - "response": Schema.Struct({ - "metadata": Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]), - "top_logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)), - Schema.Null - ]) - ), - "temperature": Schema.Union([ - Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), - Schema.Null - ]), - "top_p": Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - Schema.Null - ]), - "user": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }) - ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) - ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" - }), - Schema.Null - ]) - ), - "model": Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ - "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" - }), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), - "background": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" - }), - Schema.Null - ]) - ), - "max_tool_calls": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "text": Schema.optionalKey(ResponseTextParam), - "tools": Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n" - }), - "tool_choice": Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam - ], { mode: "oneOf" }).annotate({ - "description": - "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n" - }), - "prompt": Schema.optionalKey(Prompt), - "truncation": Schema.optionalKey(Schema.Union([ - Schema.Literals(["auto", "disabled"]).annotate({ - "description": - "The truncation strategy to use for the model response.\n- `auto`: If the input to this Response exceeds\n the model's context window size, the model will truncate the\n response to fit the context window by dropping items from the beginning of the conversation.\n- `disabled` (default): If the input size will exceed the context window\n size for a model, the request will fail with a 400 error.\n" - }), - Schema.Null - ])), - "id": Schema.String.annotate({ "description": "Unique identifier for this Response.\n" }), - "object": Schema.Literal("response").annotate({ - "description": "The object type of this resource - always set to `response`.\n" - }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "failed", "in_progress", "cancelled", "queued", "incomplete"]).annotate({ - "description": - "The status of the response generation. One of `completed`, `failed`,\n`in_progress`, `cancelled`, `queued`, or `incomplete`.\n" - }) - ), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) of when this Response was created.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - "completed_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "Unix timestamp (in seconds) of when this Response was completed.\nOnly present when the status is `completed`.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "error": ResponseError, - "incomplete_details": Schema.Union([ - Schema.Struct({ - "reason": Schema.optionalKey( - Schema.Literals(["max_output_tokens", "content_filter"]).annotate({ - "description": "The reason why the response is incomplete." - }) - ) - }).annotate({ "description": "Details about why the response is incomplete.\n" }), - Schema.Null - ]), - "output": Schema.Array(OutputItem).annotate({ - "description": - "An array of content items generated by the model.\n\n- The length and order of items in the `output` array is dependent\n on the model's response.\n- Rather than accessing the first item in the `output` array and\n assuming it's an `assistant` message with the content generated by\n the model, you might consider using the `output_text` property where\n supported in SDKs.\n" - }), - "instructions": Schema.Union([ - Schema.Union([ - Schema.String.annotate({ - "description": "A text input to the model, equivalent to a text input with the\n`developer` role.\n" - }), - Schema.Array(InputItem).annotate({ - "title": "Input item list", - "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "A system (or developer) message inserted into the model's context.\n\nWhen using along with `previous_response_id`, the instructions from a previous\nresponse will not be carried over to the next response. This makes it simple\nto swap out system (or developer) messages in new responses.\n" - }), - Schema.Null - ]), - "output_text": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "SDK-only convenience property that contains the aggregated text output\nfrom all `output_text` items in the `output` array, if any are present.\nSupported in the Python and JavaScript SDKs.\n" - }), - Schema.Null - ]) - ), - "usage": Schema.optionalKey(Schema.Union([ResponseUsage, Schema.Null])), - "parallel_tool_calls": Schema.Boolean.annotate({ - "description": "Whether to allow the model to run tool calls in parallel.\n" - }), - "conversation": Schema.optionalKey(Schema.Union([Conversation_2, Schema.Null])), - "max_output_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ) - }).annotate({ "title": "The response object", "description": "The response that failed.\n" }) -}).annotate({ "description": "An event that is emitted when a response fails.\n" }) -export type ResponseInProgressEvent = { + "response": Schema.suspend((): Schema.Codec => Response).annotate({ + "description": "The response that failed.\n" + }) +}).annotate({ "description": "An event that is emitted when a response fails.\n", "identifier": "ResponseFailedEvent" }) +export type ResponseIncompleteEvent = { + readonly "type": "response.incomplete" + readonly "response": Response + readonly "sequence_number": number +} +export const ResponseIncompleteEvent = Schema.Struct({ + "type": Schema.Literal("response.incomplete").annotate({ + "description": "The type of the event. Always `response.incomplete`.\n" + }), + "response": Schema.suspend((): Schema.Codec => Response).annotate({ + "description": "The response that was incomplete.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": + "An event that is emitted when a response finishes as incomplete.\n\nOver WebSocket, steering can finish a response with\n`response.incomplete_details.reason` set to `steered`, followed automatically\nby a successor `response.created` that commits the queued steering input.\n", + "identifier": "ResponseIncompleteEvent" +}) +export type ResponseQueuedEvent = { + readonly "type": "response.queued" + readonly "response": Response + readonly "sequence_number": number +} +export const ResponseQueuedEvent = Schema.Struct({ + "type": Schema.Literal("response.queued").annotate({ + "description": "The type of the event. Always 'response.queued'." + }), + "response": Schema.suspend((): Schema.Codec => Response).annotate({ + "description": "The full response object that is queued." + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "title": "ResponseQueuedEvent", + "description": "Emitted when a response is queued and waiting to be processed.\n", + "identifier": "ResponseQueuedEvent" +}) +export type LiveSessionCreateRequest = { + readonly "session": LiveMediaSessionCreateParams + readonly "transport": LiveWebRTCTransport | LiveSIPTransport +} +export const LiveSessionCreateRequest = Schema.Struct({ + "session": Schema.suspend((): Schema.Codec => LiveMediaSessionCreateParams).annotate({ + "description": "Startup configuration for the Live session." + }), + "transport": Schema.Union([LiveWebRTCTransport, LiveSIPTransport], { mode: "oneOf" }).annotate({ + "description": + "WebRTC transport with an SDP offer, or SIP transport with a destination and per-call trunk credentials." + }) +}).annotate({ + "description": + "Create a Live session with a WebRTC SDP offer or place an outbound SIP call. Follow the [Live prompting guide](https://developers.openai.com/api/docs/guides/live-prompting) before choosing frontend and backend instructions. The request starts the session; do not send session.start again on the data channel or sideband.", + "identifier": "LiveSessionCreateRequest" +}) +export type LiveCallAcceptRequest = { readonly "session": LiveCallAcceptSession } +export const LiveCallAcceptRequest = Schema.Struct({ + "session": Schema.suspend((): Schema.Codec => LiveCallAcceptSession).annotate({ + "description": "Model and startup configuration for the Live session that answers the incoming SIP call." + }) +}).annotate({ + "description": "Accept an incoming SIP call with Live startup configuration.", + "identifier": "LiveCallAcceptRequest" +}) +export type BetaResponseCompletedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.completed" + readonly "response": BetaResponse + readonly "sequence_number": number +} +export const BetaResponseCompletedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.completed").annotate({ + "description": "The type of the event. Always `response.completed`.\n" + }), + "response": Schema.suspend((): Schema.Codec => BetaResponse).annotate({ + "description": "Properties of the completed response.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "Emitted when the model response is complete.", + "identifier": "BetaResponseCompletedEvent" +}) +export type BetaResponseCreatedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.created" + readonly "response": BetaResponse + readonly "sequence_number": number +} +export const BetaResponseCreatedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.created").annotate({ + "description": "The type of the event. Always `response.created`.\n" + }), + "response": Schema.suspend((): Schema.Codec => BetaResponse).annotate({ + "description": "The response that was created.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) +}).annotate({ + "description": "An event that is emitted when a response is created.\n", + "identifier": "BetaResponseCreatedEvent" +}) +export type BetaResponseInProgressEvent = { + readonly "agent"?: BetaAgentTag | null readonly "type": "response.in_progress" - readonly "response": { - readonly "metadata": {} | null - readonly "top_logprobs"?: number | null - readonly "temperature": number | null - readonly "top_p": number | null - readonly "user"?: string | null - readonly "safety_identifier"?: string - readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null - readonly "previous_response_id"?: string | null - readonly "model": - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null - readonly "background"?: boolean | null - readonly "max_tool_calls"?: number | null - readonly "text"?: ResponseTextParam - readonly "tools": ReadonlyArray - readonly "tool_choice": - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam - readonly "prompt"?: Prompt - readonly "truncation"?: "auto" | "disabled" | null - readonly "id": string - readonly "object": "response" - readonly "status"?: "completed" | "failed" | "in_progress" | "cancelled" | "queued" | "incomplete" - readonly "created_at": number - readonly "completed_at"?: number | null - readonly "error": ResponseError - readonly "incomplete_details": { readonly "reason"?: "max_output_tokens" | "content_filter" } | null - readonly "output": ReadonlyArray - readonly "instructions": string | ReadonlyArray | null - readonly "output_text"?: string | null - readonly "usage"?: ResponseUsage | null - readonly "parallel_tool_calls": boolean - readonly "conversation"?: Conversation_2 | null - readonly "max_output_tokens"?: number | null - } + readonly "response": BetaResponse readonly "sequence_number": number } -export const ResponseInProgressEvent = Schema.Struct({ +export const BetaResponseInProgressEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), "type": Schema.Literal("response.in_progress").annotate({ "description": "The type of the event. Always `response.in_progress`.\n" }), - "response": Schema.Struct({ - "metadata": Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]), - "top_logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)), - Schema.Null - ]) - ), - "temperature": Schema.Union([ - Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), - Schema.Null - ]), - "top_p": Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - Schema.Null - ]), - "user": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }) - ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) - ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" - }), - Schema.Null - ]) - ), - "model": Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ - "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" - }), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), - "background": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" - }), - Schema.Null - ]) - ), - "max_tool_calls": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "text": Schema.optionalKey(ResponseTextParam), - "tools": Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n" - }), - "tool_choice": Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam - ], { mode: "oneOf" }).annotate({ - "description": - "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n" - }), - "prompt": Schema.optionalKey(Prompt), - "truncation": Schema.optionalKey(Schema.Union([ - Schema.Literals(["auto", "disabled"]).annotate({ - "description": - "The truncation strategy to use for the model response.\n- `auto`: If the input to this Response exceeds\n the model's context window size, the model will truncate the\n response to fit the context window by dropping items from the beginning of the conversation.\n- `disabled` (default): If the input size will exceed the context window\n size for a model, the request will fail with a 400 error.\n" - }), - Schema.Null - ])), - "id": Schema.String.annotate({ "description": "Unique identifier for this Response.\n" }), - "object": Schema.Literal("response").annotate({ - "description": "The object type of this resource - always set to `response`.\n" - }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "failed", "in_progress", "cancelled", "queued", "incomplete"]).annotate({ - "description": - "The status of the response generation. One of `completed`, `failed`,\n`in_progress`, `cancelled`, `queued`, or `incomplete`.\n" - }) - ), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) of when this Response was created.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - "completed_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "Unix timestamp (in seconds) of when this Response was completed.\nOnly present when the status is `completed`.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "error": ResponseError, - "incomplete_details": Schema.Union([ - Schema.Struct({ - "reason": Schema.optionalKey( - Schema.Literals(["max_output_tokens", "content_filter"]).annotate({ - "description": "The reason why the response is incomplete." - }) - ) - }).annotate({ "description": "Details about why the response is incomplete.\n" }), - Schema.Null - ]), - "output": Schema.Array(OutputItem).annotate({ - "description": - "An array of content items generated by the model.\n\n- The length and order of items in the `output` array is dependent\n on the model's response.\n- Rather than accessing the first item in the `output` array and\n assuming it's an `assistant` message with the content generated by\n the model, you might consider using the `output_text` property where\n supported in SDKs.\n" - }), - "instructions": Schema.Union([ - Schema.Union([ - Schema.String.annotate({ - "description": "A text input to the model, equivalent to a text input with the\n`developer` role.\n" - }), - Schema.Array(InputItem).annotate({ - "title": "Input item list", - "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "A system (or developer) message inserted into the model's context.\n\nWhen using along with `previous_response_id`, the instructions from a previous\nresponse will not be carried over to the next response. This makes it simple\nto swap out system (or developer) messages in new responses.\n" - }), - Schema.Null - ]), - "output_text": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "SDK-only convenience property that contains the aggregated text output\nfrom all `output_text` items in the `output` array, if any are present.\nSupported in the Python and JavaScript SDKs.\n" - }), - Schema.Null - ]) - ), - "usage": Schema.optionalKey(Schema.Union([ResponseUsage, Schema.Null])), - "parallel_tool_calls": Schema.Boolean.annotate({ - "description": "Whether to allow the model to run tool calls in parallel.\n" - }), - "conversation": Schema.optionalKey(Schema.Union([Conversation_2, Schema.Null])), - "max_output_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ) - }).annotate({ "title": "The response object", "description": "The response that is in progress.\n" }), + "response": Schema.suspend((): Schema.Codec => BetaResponse).annotate({ + "description": "The response that is in progress.\n" + }), "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "Emitted when the response is in progress." }) -export type ResponseIncompleteEvent = { +}).annotate({ "description": "Emitted when the response is in progress.", "identifier": "BetaResponseInProgressEvent" }) +export type BetaResponseFailedEvent = { + readonly "agent"?: BetaAgentTag | null + readonly "type": "response.failed" + readonly "sequence_number": number + readonly "response": BetaResponse +} +export const BetaResponseFailedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), + "type": Schema.Literal("response.failed").annotate({ + "description": "The type of the event. Always `response.failed`.\n" + }), + "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ), + "response": Schema.suspend((): Schema.Codec => BetaResponse).annotate({ + "description": "The response that failed.\n" + }) +}).annotate({ + "description": "An event that is emitted when a response fails.\n", + "identifier": "BetaResponseFailedEvent" +}) +export type BetaResponseIncompleteEvent = { + readonly "agent"?: BetaAgentTag | null readonly "type": "response.incomplete" - readonly "response": { - readonly "metadata": {} | null - readonly "top_logprobs"?: number | null - readonly "temperature": number | null - readonly "top_p": number | null - readonly "user"?: string | null - readonly "safety_identifier"?: string - readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null - readonly "previous_response_id"?: string | null - readonly "model": - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null - readonly "background"?: boolean | null - readonly "max_tool_calls"?: number | null - readonly "text"?: ResponseTextParam - readonly "tools": ReadonlyArray - readonly "tool_choice": - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam - readonly "prompt"?: Prompt - readonly "truncation"?: "auto" | "disabled" | null - readonly "id": string - readonly "object": "response" - readonly "status"?: "completed" | "failed" | "in_progress" | "cancelled" | "queued" | "incomplete" - readonly "created_at": number - readonly "completed_at"?: number | null - readonly "error": ResponseError - readonly "incomplete_details": { readonly "reason"?: "max_output_tokens" | "content_filter" } | null - readonly "output": ReadonlyArray - readonly "instructions": string | ReadonlyArray | null - readonly "output_text"?: string | null - readonly "usage"?: ResponseUsage | null - readonly "parallel_tool_calls": boolean - readonly "conversation"?: Conversation_2 | null - readonly "max_output_tokens"?: number | null - } + readonly "response": BetaResponse readonly "sequence_number": number } -export const ResponseIncompleteEvent = Schema.Struct({ +export const BetaResponseIncompleteEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), "type": Schema.Literal("response.incomplete").annotate({ "description": "The type of the event. Always `response.incomplete`.\n" }), - "response": Schema.Struct({ - "metadata": Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]), - "top_logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)), - Schema.Null - ]) - ), - "temperature": Schema.Union([ - Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), - Schema.Null - ]), - "top_p": Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - Schema.Null - ]), - "user": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }) - ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) - ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" - }), - Schema.Null - ]) - ), - "model": Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ - "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" - }), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), - "background": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" - }), - Schema.Null - ]) - ), - "max_tool_calls": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "text": Schema.optionalKey(ResponseTextParam), - "tools": Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n" - }), - "tool_choice": Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam - ], { mode: "oneOf" }).annotate({ - "description": - "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n" - }), - "prompt": Schema.optionalKey(Prompt), - "truncation": Schema.optionalKey(Schema.Union([ - Schema.Literals(["auto", "disabled"]).annotate({ - "description": - "The truncation strategy to use for the model response.\n- `auto`: If the input to this Response exceeds\n the model's context window size, the model will truncate the\n response to fit the context window by dropping items from the beginning of the conversation.\n- `disabled` (default): If the input size will exceed the context window\n size for a model, the request will fail with a 400 error.\n" - }), - Schema.Null - ])), - "id": Schema.String.annotate({ "description": "Unique identifier for this Response.\n" }), - "object": Schema.Literal("response").annotate({ - "description": "The object type of this resource - always set to `response`.\n" - }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "failed", "in_progress", "cancelled", "queued", "incomplete"]).annotate({ - "description": - "The status of the response generation. One of `completed`, `failed`,\n`in_progress`, `cancelled`, `queued`, or `incomplete`.\n" - }) - ), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) of when this Response was created.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - "completed_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "Unix timestamp (in seconds) of when this Response was completed.\nOnly present when the status is `completed`.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "error": ResponseError, - "incomplete_details": Schema.Union([ - Schema.Struct({ - "reason": Schema.optionalKey( - Schema.Literals(["max_output_tokens", "content_filter"]).annotate({ - "description": "The reason why the response is incomplete." - }) - ) - }).annotate({ "description": "Details about why the response is incomplete.\n" }), - Schema.Null - ]), - "output": Schema.Array(OutputItem).annotate({ - "description": - "An array of content items generated by the model.\n\n- The length and order of items in the `output` array is dependent\n on the model's response.\n- Rather than accessing the first item in the `output` array and\n assuming it's an `assistant` message with the content generated by\n the model, you might consider using the `output_text` property where\n supported in SDKs.\n" - }), - "instructions": Schema.Union([ - Schema.Union([ - Schema.String.annotate({ - "description": "A text input to the model, equivalent to a text input with the\n`developer` role.\n" - }), - Schema.Array(InputItem).annotate({ - "title": "Input item list", - "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "A system (or developer) message inserted into the model's context.\n\nWhen using along with `previous_response_id`, the instructions from a previous\nresponse will not be carried over to the next response. This makes it simple\nto swap out system (or developer) messages in new responses.\n" - }), - Schema.Null - ]), - "output_text": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "SDK-only convenience property that contains the aggregated text output\nfrom all `output_text` items in the `output` array, if any are present.\nSupported in the Python and JavaScript SDKs.\n" - }), - Schema.Null - ]) - ), - "usage": Schema.optionalKey(Schema.Union([ResponseUsage, Schema.Null])), - "parallel_tool_calls": Schema.Boolean.annotate({ - "description": "Whether to allow the model to run tool calls in parallel.\n" - }), - "conversation": Schema.optionalKey(Schema.Union([Conversation_2, Schema.Null])), - "max_output_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ) - }).annotate({ "title": "The response object", "description": "The response that was incomplete.\n" }), + "response": Schema.suspend((): Schema.Codec => BetaResponse).annotate({ + "description": "The response that was incomplete.\n" + }), "sequence_number": Schema.Number.annotate({ "description": "The sequence number of this event." }).check( - Schema.isInt() + Schema.isInt().annotate({ "expected": "an integer" }) ) -}).annotate({ "description": "An event that is emitted when a response finishes as incomplete.\n" }) -export type ResponseQueuedEvent = { +}).annotate({ + "description": + "An event that is emitted when a response finishes as incomplete.\n\nOver WebSocket, steering can finish a response with\n`response.incomplete_details.reason` set to `steered`, followed automatically\nby a successor `response.created` that commits the queued steering input.\n", + "identifier": "BetaResponseIncompleteEvent" +}) +export type BetaResponseQueuedEvent = { + readonly "agent"?: BetaAgentTag | null readonly "type": "response.queued" - readonly "response": { - readonly "metadata": {} | null - readonly "top_logprobs"?: number | null - readonly "temperature": number | null - readonly "top_p": number | null - readonly "user"?: string | null - readonly "safety_identifier"?: string - readonly "prompt_cache_key"?: string | null - readonly "service_tier"?: ServiceTier - readonly "prompt_cache_retention"?: "in_memory" | "in_memory" | "24h" | null - readonly "previous_response_id"?: string | null - readonly "model": - | ModelIdsShared - | "o1-pro" - | "o1-pro-2025-03-19" - | "o3-pro" - | "o3-pro-2025-06-10" - | "o3-deep-research" - | "o3-deep-research-2025-06-26" - | "o4-mini-deep-research" - | "o4-mini-deep-research-2025-06-26" - | "computer-use-preview" - | "computer-use-preview-2025-03-11" - | "gpt-5-codex" - | "gpt-5-pro" - | "gpt-5-pro-2025-10-06" - | "gpt-5.1-codex-max" - readonly "reasoning"?: Reasoning | null - readonly "background"?: boolean | null - readonly "max_tool_calls"?: number | null - readonly "text"?: ResponseTextParam - readonly "tools": ReadonlyArray - readonly "tool_choice": - | ToolChoiceOptions - | ToolChoiceAllowed - | ToolChoiceTypes - | ToolChoiceFunction - | ToolChoiceMCP - | ToolChoiceCustom - | SpecificApplyPatchParam - | SpecificFunctionShellParam - readonly "prompt"?: Prompt - readonly "truncation"?: "auto" | "disabled" | null - readonly "id": string - readonly "object": "response" - readonly "status"?: "completed" | "failed" | "in_progress" | "cancelled" | "queued" | "incomplete" - readonly "created_at": number - readonly "completed_at"?: number | null - readonly "error": ResponseError - readonly "incomplete_details": { readonly "reason"?: "max_output_tokens" | "content_filter" } | null - readonly "output": ReadonlyArray - readonly "instructions": string | ReadonlyArray | null - readonly "output_text"?: string | null - readonly "usage"?: ResponseUsage | null - readonly "parallel_tool_calls": boolean - readonly "conversation"?: Conversation_2 | null - readonly "max_output_tokens"?: number | null - } + readonly "response": BetaResponse readonly "sequence_number": number } -export const ResponseQueuedEvent = Schema.Struct({ +export const BetaResponseQueuedEvent = Schema.Struct({ + "agent": Schema.optionalKey( + Schema.Union([BetaAgentTag, Schema.Null]).annotate({ + "description": "The agent that owns this multi-agent streaming event." + }) + ), "type": Schema.Literal("response.queued").annotate({ "description": "The type of the event. Always 'response.queued'." }), - "response": Schema.Struct({ - "metadata": Schema.Union([ - Schema.Struct({}).annotate({ - "description": - "Set of 16 key-value pairs that can be attached to an object. This can be\nuseful for storing additional information about the object in a structured\nformat, and querying for objects via API or the dashboard.\n\nKeys are strings with a maximum length of 64 characters. Values are strings\nwith a maximum length of 512 characters.\n" - }), - Schema.Null - ]), - "top_logprobs": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An integer between 0 and 20 specifying the maximum number of most likely\ntokens to return at each token position, each with an associated log\nprobability. In some cases, the number of returned tokens may be fewer than\nrequested.\n" - }).check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(20)), - Schema.Null - ]) - ), - "temperature": Schema.Union([ - Schema.Number.annotate({ - "description": - "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\nWe generally recommend altering this or `top_p` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(2)), - Schema.Null - ]), - "top_p": Schema.Union([ - Schema.Number.annotate({ - "description": - "An alternative to sampling with temperature, called nucleus sampling,\nwhere the model considers the results of the tokens with top_p probability\nmass. So 0.1 means only the tokens comprising the top 10% probability mass\nare considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }).check(Schema.isFinite()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1)), - Schema.Null - ]), - "user": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "This field is being replaced by `safety_identifier` and `prompt_cache_key`. Use `prompt_cache_key` instead to maintain caching optimizations.\nA stable identifier for your end-users.\nUsed to boost cache hit rates by better bucketing similar requests and to help OpenAI detect and prevent abuse. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }) - ), - "safety_identifier": Schema.optionalKey(Schema.Union([Schema.String.check(Schema.isMaxLength(64, { - "description": - "A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies.\nThe IDs should be a string that uniquely identifies each user, with a maximum length of 64 characters. We recommend hashing their username or email address, in order to avoid sending us any identifying information. [Learn more](/docs/guides/safety-best-practices#safety-identifiers).\n" - }))])), - "prompt_cache_key": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "Used by OpenAI to cache responses for similar requests to optimize your cache hit rates. Replaces the `user` field. [Learn more](/docs/guides/prompt-caching).\n" - }) - ), - "service_tier": Schema.optionalKey(ServiceTier), - "prompt_cache_retention": Schema.optionalKey( - Schema.Union([ - Schema.Literals(["in_memory", "in_memory", "24h"]).annotate({ - "description": - "The retention policy for the prompt cache. Set to `24h` to enable extended prompt caching, which keeps cached prefixes active for longer, up to a maximum of 24 hours. [Learn more](/docs/guides/prompt-caching#prompt-cache-retention).\n" - }), - Schema.Null - ]) - ), - "previous_response_id": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "The unique ID of the previous response to the model. Use this to\ncreate multi-turn conversations. Learn more about\n[conversation state](/docs/guides/conversation-state). Cannot be used in conjunction with `conversation`.\n" - }), - Schema.Null - ]) - ), - "model": Schema.Union([ - ModelIdsShared, - Schema.Literals([ - "o1-pro", - "o1-pro-2025-03-19", - "o3-pro", - "o3-pro-2025-06-10", - "o3-deep-research", - "o3-deep-research-2025-06-26", - "o4-mini-deep-research", - "o4-mini-deep-research-2025-06-26", - "computer-use-preview", - "computer-use-preview-2025-03-11", - "gpt-5-codex", - "gpt-5-pro", - "gpt-5-pro-2025-10-06", - "gpt-5.1-codex-max" - ]).annotate({ "title": "ResponsesOnlyModel" }) - ]).annotate({ - "description": - "Model ID used to generate the response, like `gpt-4o` or `o3`. OpenAI\noffers a wide range of models with different capabilities, performance\ncharacteristics, and price points. Refer to the [model guide](/docs/models)\nto browse and compare available models.\n" - }), - "reasoning": Schema.optionalKey(Schema.Union([Reasoning, Schema.Null])), - "background": Schema.optionalKey( - Schema.Union([ - Schema.Boolean.annotate({ - "description": - "Whether to run the model response in the background.\n[Learn more](/docs/guides/background).\n" - }), - Schema.Null - ]) - ), - "max_tool_calls": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "The maximum number of total calls to built-in tools that can be processed in a response. This maximum number applies across all built-in tool calls, not per individual tool. Any further attempts to call a tool by the model will be ignored.\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ), - "text": Schema.optionalKey(ResponseTextParam), - "tools": Schema.Array(Tool).annotate({ - "description": - "An array of tools the model may call while generating a response. You\ncan specify which tool to use by setting the `tool_choice` parameter.\n\nWe support the following categories of tools:\n- **Built-in tools**: Tools that are provided by OpenAI that extend the\n model's capabilities, like [web search](/docs/guides/tools-web-search)\n or [file search](/docs/guides/tools-file-search). Learn more about\n [built-in tools](/docs/guides/tools).\n- **MCP Tools**: Integrations with third-party systems via custom MCP servers\n or predefined connectors such as Google Drive and SharePoint. Learn more about\n [MCP Tools](/docs/guides/tools-connectors-mcp).\n- **Function calls (custom tools)**: Functions that are defined by you,\n enabling the model to call your own code with strongly typed arguments\n and outputs. Learn more about\n [function calling](/docs/guides/function-calling). You can also use\n custom tools to call your own code.\n" - }), - "tool_choice": Schema.Union([ - ToolChoiceOptions, - ToolChoiceAllowed, - ToolChoiceTypes, - ToolChoiceFunction, - ToolChoiceMCP, - ToolChoiceCustom, - SpecificApplyPatchParam, - SpecificFunctionShellParam - ], { mode: "oneOf" }).annotate({ - "description": - "How the model should select which tool (or tools) to use when generating\na response. See the `tools` parameter to see how to specify which tools\nthe model can call.\n" - }), - "prompt": Schema.optionalKey(Prompt), - "truncation": Schema.optionalKey(Schema.Union([ - Schema.Literals(["auto", "disabled"]).annotate({ - "description": - "The truncation strategy to use for the model response.\n- `auto`: If the input to this Response exceeds\n the model's context window size, the model will truncate the\n response to fit the context window by dropping items from the beginning of the conversation.\n- `disabled` (default): If the input size will exceed the context window\n size for a model, the request will fail with a 400 error.\n" - }), - Schema.Null - ])), - "id": Schema.String.annotate({ "description": "Unique identifier for this Response.\n" }), - "object": Schema.Literal("response").annotate({ - "description": "The object type of this resource - always set to `response`.\n" - }), - "status": Schema.optionalKey( - Schema.Literals(["completed", "failed", "in_progress", "cancelled", "queued", "incomplete"]).annotate({ - "description": - "The status of the response generation. One of `completed`, `failed`,\n`in_progress`, `cancelled`, `queued`, or `incomplete`.\n" - }) - ), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) of when this Response was created.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - "completed_at": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "Unix timestamp (in seconds) of when this Response was completed.\nOnly present when the status is `completed`.\n", - "format": "unixtime" - }).check(Schema.isFinite()), - Schema.Null - ]) - ), - "error": ResponseError, - "incomplete_details": Schema.Union([ - Schema.Struct({ - "reason": Schema.optionalKey( - Schema.Literals(["max_output_tokens", "content_filter"]).annotate({ - "description": "The reason why the response is incomplete." - }) - ) - }).annotate({ "description": "Details about why the response is incomplete.\n" }), - Schema.Null - ]), - "output": Schema.Array(OutputItem).annotate({ - "description": - "An array of content items generated by the model.\n\n- The length and order of items in the `output` array is dependent\n on the model's response.\n- Rather than accessing the first item in the `output` array and\n assuming it's an `assistant` message with the content generated by\n the model, you might consider using the `output_text` property where\n supported in SDKs.\n" - }), - "instructions": Schema.Union([ - Schema.Union([ - Schema.String.annotate({ - "description": "A text input to the model, equivalent to a text input with the\n`developer` role.\n" - }), - Schema.Array(InputItem).annotate({ - "title": "Input item list", - "description": "A list of one or many input items to the model, containing\ndifferent content types.\n" - }) - ], { mode: "oneOf" }).annotate({ - "description": - "A system (or developer) message inserted into the model's context.\n\nWhen using along with `previous_response_id`, the instructions from a previous\nresponse will not be carried over to the next response. This makes it simple\nto swap out system (or developer) messages in new responses.\n" - }), - Schema.Null - ]), - "output_text": Schema.optionalKey( - Schema.Union([ - Schema.String.annotate({ - "description": - "SDK-only convenience property that contains the aggregated text output\nfrom all `output_text` items in the `output` array, if any are present.\nSupported in the Python and JavaScript SDKs.\n" - }), - Schema.Null - ]) - ), - "usage": Schema.optionalKey(Schema.Union([ResponseUsage, Schema.Null])), - "parallel_tool_calls": Schema.Boolean.annotate({ - "description": "Whether to allow the model to run tool calls in parallel.\n" - }), - "conversation": Schema.optionalKey(Schema.Union([Conversation_2, Schema.Null])), - "max_output_tokens": Schema.optionalKey( - Schema.Union([ - Schema.Number.annotate({ - "description": - "An upper bound for the number of tokens that can be generated for a response, including visible output tokens and [reasoning tokens](/docs/guides/reasoning).\n" - }).check(Schema.isInt()), - Schema.Null - ]) - ) - }).annotate({ "title": "The response object", "description": "The full response object that is queued." }), + "response": Schema.suspend((): Schema.Codec => BetaResponse).annotate({ + "description": "The full response object that is queued." + }), "sequence_number": Schema.Number.annotate({ "description": "The sequence number for this event." }).check( - Schema.isInt() + Schema.isInt().annotate({ "expected": "an integer" }) ) }).annotate({ "title": "ResponseQueuedEvent", - "description": "Emitted when a response is queued and waiting to be processed.\n" + "description": "Emitted when a response is queued and waiting to be processed.\n", + "identifier": "BetaResponseQueuedEvent" }) -export type CompactResource = { - readonly "id": string - readonly "object": "response.compaction" - readonly "output": ReadonlyArray - readonly "created_at": number - readonly "usage": { - readonly "input_tokens": number - readonly "input_tokens_details": { readonly "cached_tokens": number } - readonly "output_tokens": number - readonly "output_tokens_details": { readonly "reasoning_tokens": number } - readonly "total_tokens": number - } -} -export const CompactResource = Schema.Struct({ - "id": Schema.String.annotate({ "description": "The unique identifier for the compacted response." }), - "object": Schema.Literal("response.compaction").annotate({ - "description": "The object type. Always `response.compaction`." - }), - "output": Schema.Array(ItemField).annotate({ "description": "The compacted list of output items." }), - "created_at": Schema.Number.annotate({ - "description": "Unix timestamp (in seconds) when the compacted conversation was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "usage": Schema.Struct({ - "input_tokens": Schema.Number.annotate({ "description": "The number of input tokens." }).check(Schema.isInt()), - "input_tokens_details": Schema.Struct({ - "cached_tokens": Schema.Number.annotate({ - "description": - "The number of tokens that were retrieved from the cache. \n[More on prompt caching](/docs/guides/prompt-caching).\n" - }).check(Schema.isInt()) - }).annotate({ "description": "A detailed breakdown of the input tokens." }), - "output_tokens": Schema.Number.annotate({ "description": "The number of output tokens." }).check(Schema.isInt()), - "output_tokens_details": Schema.Struct({ - "reasoning_tokens": Schema.Number.annotate({ "description": "The number of reasoning tokens." }).check( - Schema.isInt() - ) - }).annotate({ "description": "A detailed breakdown of the output tokens." }), - "total_tokens": Schema.Number.annotate({ "description": "The total number of tokens used." }).check(Schema.isInt()) - }).annotate({ - "description": "Token accounting for the compaction pass, including cached, reasoning, and total tokens." - }) -}).annotate({ "title": "The compacted response object" }) -export type EvalList = { - readonly "object": "list" - readonly "data": ReadonlyArray - readonly "first_id": string - readonly "last_id": string - readonly "has_more": boolean -} -export const EvalList = Schema.Struct({ - "object": Schema.Literal("list").annotate({ - "description": "The type of this object. It is always set to \"list\".\n" - }), - "data": Schema.Array(Eval).annotate({ "description": "An array of eval objects.\n" }), - "first_id": Schema.String.annotate({ "description": "The identifier of the first eval in the data array." }), - "last_id": Schema.String.annotate({ "description": "The identifier of the last eval in the data array." }), - "has_more": Schema.Boolean.annotate({ "description": "Indicates whether there are more evals available." }) -}).annotate({ "title": "EvalList", "description": "An object representing a list of evals.\n" }) export type FineTuneMethod = { readonly "type": "supervised" | "dpo" | "reinforcement" readonly "supervised"?: FineTuneSupervisedMethod @@ -28276,7 +45311,7 @@ export const FineTuneMethod = Schema.Struct({ "supervised": Schema.optionalKey(FineTuneSupervisedMethod), "dpo": Schema.optionalKey(FineTuneDPOMethod), "reinforcement": Schema.optionalKey(FineTuneReinforcementMethod) -}).annotate({ "description": "The method used for fine-tuning." }) +}).annotate({ "description": "The method used for fine-tuning.", "identifier": "FineTuneMethod" }) export type ResponseStreamEvent = | ResponseAudioDeltaEvent | ResponseAudioDoneEvent @@ -28287,6 +45322,7 @@ export type ResponseStreamEvent = | ResponseCodeInterpreterCallCompletedEvent | ResponseCodeInterpreterCallInProgressEvent | ResponseCodeInterpreterCallInterpretingEvent + | ResponseCompactionCompactingStreamingEvent | ResponseCompletedEvent | ResponseContentPartAddedEvent | ResponseContentPartDoneEvent @@ -28297,6 +45333,11 @@ export type ResponseStreamEvent = | ResponseFileSearchCallSearchingEvent | ResponseFunctionCallArgumentsDeltaEvent | ResponseFunctionCallArgumentsDoneEvent + | ResponseShellCallCommandAddedStreamingEvent + | ResponseShellCallCommandDeltaStreamingEvent + | ResponseShellCallCommandDoneStreamingEvent + | ResponseShellCallOutputContentDeltaStreamingEvent + | ResponseShellCallOutputContentDoneStreamingEvent | ResponseInProgressEvent | ResponseFailedEvent | ResponseIncompleteEvent @@ -28344,6 +45385,7 @@ export const ResponseStreamEvent = Schema.Union([ ResponseCodeInterpreterCallCompletedEvent, ResponseCodeInterpreterCallInProgressEvent, ResponseCodeInterpreterCallInterpretingEvent, + ResponseCompactionCompactingStreamingEvent, ResponseCompletedEvent, ResponseContentPartAddedEvent, ResponseContentPartDoneEvent, @@ -28354,6 +45396,11 @@ export const ResponseStreamEvent = Schema.Union([ ResponseFileSearchCallSearchingEvent, ResponseFunctionCallArgumentsDeltaEvent, ResponseFunctionCallArgumentsDoneEvent, + ResponseShellCallCommandAddedStreamingEvent, + ResponseShellCallCommandDeltaStreamingEvent, + ResponseShellCallCommandDoneStreamingEvent, + ResponseShellCallOutputContentDeltaStreamingEvent, + ResponseShellCallOutputContentDoneStreamingEvent, ResponseInProgressEvent, ResponseFailedEvent, ResponseIncompleteEvent, @@ -28391,7 +45438,530 @@ export const ResponseStreamEvent = Schema.Union([ ResponseKeepAliveEvent, ResponseApplyPatchCallOperationDiffDeltaEvent, ResponseApplyPatchCallOperationDiffDoneEvent -]) +]).annotate({ "description": "Event emitted while a response is streamed.", "identifier": "ResponseStreamEvent" }) +export type BetaResponseStreamEvent = + | BetaResponseAudioDeltaEvent + | BetaResponseAudioDoneEvent + | BetaResponseAudioTranscriptDeltaEvent + | BetaResponseAudioTranscriptDoneEvent + | BetaResponseCodeInterpreterCallCodeDeltaEvent + | BetaResponseCodeInterpreterCallCodeDoneEvent + | BetaResponseCodeInterpreterCallCompletedEvent + | BetaResponseCodeInterpreterCallInProgressEvent + | BetaResponseCodeInterpreterCallInterpretingEvent + | BetaResponseCompactionCompactingStreamingEvent + | BetaResponseCompletedEvent + | BetaResponseContentPartAddedEvent + | BetaResponseContentPartDoneEvent + | BetaResponseCreatedEvent + | BetaResponseErrorEvent + | BetaResponseFileSearchCallCompletedEvent + | BetaResponseFileSearchCallInProgressEvent + | BetaResponseFileSearchCallSearchingEvent + | BetaResponseFunctionCallArgumentsDeltaEvent + | BetaResponseFunctionCallArgumentsDoneEvent + | BetaResponseShellCallCommandAddedStreamingEvent + | BetaResponseShellCallCommandDeltaStreamingEvent + | BetaResponseShellCallCommandDoneStreamingEvent + | BetaResponseShellCallOutputContentDeltaStreamingEvent + | BetaResponseShellCallOutputContentDoneStreamingEvent + | BetaResponseInProgressEvent + | BetaResponseFailedEvent + | BetaResponseIncompleteEvent + | BetaResponseOutputItemAddedEvent + | BetaResponseOutputItemDoneEvent + | BetaResponseReasoningSummaryPartAddedEvent + | BetaResponseReasoningSummaryPartDoneEvent + | BetaResponseReasoningSummaryTextDeltaEvent + | BetaResponseReasoningSummaryTextDoneEvent + | BetaResponseReasoningTextDeltaEvent + | BetaResponseReasoningTextDoneEvent + | BetaResponseRefusalDeltaEvent + | BetaResponseRefusalDoneEvent + | BetaResponseTextDeltaEvent + | BetaResponseTextDoneEvent + | BetaResponseWebSearchCallCompletedEvent + | BetaResponseWebSearchCallInProgressEvent + | BetaResponseWebSearchCallSearchingEvent + | BetaResponseImageGenCallCompletedEvent + | BetaResponseImageGenCallGeneratingEvent + | BetaResponseImageGenCallInProgressEvent + | BetaResponseImageGenCallPartialImageEvent + | BetaResponseMCPCallArgumentsDeltaEvent + | BetaResponseMCPCallArgumentsDoneEvent + | BetaResponseMCPCallCompletedEvent + | BetaResponseMCPCallFailedEvent + | BetaResponseMCPCallInProgressEvent + | BetaResponseMCPListToolsCompletedEvent + | BetaResponseMCPListToolsFailedEvent + | BetaResponseMCPListToolsInProgressEvent + | BetaResponseOutputTextAnnotationAddedEvent + | BetaResponseQueuedEvent + | BetaResponseCustomToolCallInputDeltaEvent + | BetaResponseCustomToolCallInputDoneEvent +export const BetaResponseStreamEvent = Schema.Union([ + BetaResponseAudioDeltaEvent, + BetaResponseAudioDoneEvent, + BetaResponseAudioTranscriptDeltaEvent, + BetaResponseAudioTranscriptDoneEvent, + BetaResponseCodeInterpreterCallCodeDeltaEvent, + BetaResponseCodeInterpreterCallCodeDoneEvent, + BetaResponseCodeInterpreterCallCompletedEvent, + BetaResponseCodeInterpreterCallInProgressEvent, + BetaResponseCodeInterpreterCallInterpretingEvent, + BetaResponseCompactionCompactingStreamingEvent, + BetaResponseCompletedEvent, + BetaResponseContentPartAddedEvent, + BetaResponseContentPartDoneEvent, + BetaResponseCreatedEvent, + BetaResponseErrorEvent, + BetaResponseFileSearchCallCompletedEvent, + BetaResponseFileSearchCallInProgressEvent, + BetaResponseFileSearchCallSearchingEvent, + BetaResponseFunctionCallArgumentsDeltaEvent, + BetaResponseFunctionCallArgumentsDoneEvent, + BetaResponseShellCallCommandAddedStreamingEvent, + BetaResponseShellCallCommandDeltaStreamingEvent, + BetaResponseShellCallCommandDoneStreamingEvent, + BetaResponseShellCallOutputContentDeltaStreamingEvent, + BetaResponseShellCallOutputContentDoneStreamingEvent, + BetaResponseInProgressEvent, + BetaResponseFailedEvent, + BetaResponseIncompleteEvent, + BetaResponseOutputItemAddedEvent, + BetaResponseOutputItemDoneEvent, + BetaResponseReasoningSummaryPartAddedEvent, + BetaResponseReasoningSummaryPartDoneEvent, + BetaResponseReasoningSummaryTextDeltaEvent, + BetaResponseReasoningSummaryTextDoneEvent, + BetaResponseReasoningTextDeltaEvent, + BetaResponseReasoningTextDoneEvent, + BetaResponseRefusalDeltaEvent, + BetaResponseRefusalDoneEvent, + BetaResponseTextDeltaEvent, + BetaResponseTextDoneEvent, + BetaResponseWebSearchCallCompletedEvent, + BetaResponseWebSearchCallInProgressEvent, + BetaResponseWebSearchCallSearchingEvent, + BetaResponseImageGenCallCompletedEvent, + BetaResponseImageGenCallGeneratingEvent, + BetaResponseImageGenCallInProgressEvent, + BetaResponseImageGenCallPartialImageEvent, + BetaResponseMCPCallArgumentsDeltaEvent, + BetaResponseMCPCallArgumentsDoneEvent, + BetaResponseMCPCallCompletedEvent, + BetaResponseMCPCallFailedEvent, + BetaResponseMCPCallInProgressEvent, + BetaResponseMCPListToolsCompletedEvent, + BetaResponseMCPListToolsFailedEvent, + BetaResponseMCPListToolsInProgressEvent, + BetaResponseOutputTextAnnotationAddedEvent, + BetaResponseQueuedEvent, + BetaResponseCustomToolCallInputDeltaEvent, + BetaResponseCustomToolCallInputDoneEvent +]).annotate({ "description": "Event emitted while a response is streamed.", "identifier": "BetaResponseStreamEvent" }) +export type FineTuningJob = { + readonly "id": string + readonly "created_at": number + readonly "error": { readonly "code": string; readonly "message": string; readonly "param": string | null } | null | { + readonly [x: string]: Schema.Json + } + readonly "fine_tuned_model": string | null + readonly "finished_at": number | null + readonly "hyperparameters"?: + | { + readonly "batch_size"?: "auto" | number | null + readonly "learning_rate_multiplier"?: "auto" | number + readonly "n_epochs"?: "auto" | number + } & { readonly [x: string]: Schema.Json } + | null + readonly "model": string + readonly "object": "fine_tuning.job" + readonly "organization_id": string + readonly "result_files": ReadonlyArray + readonly "status": + | "validating_files" + | "queued" + | "running" + | "succeeded" + | "failed" + | "cancelled" + | "pausing" + | "paused" + readonly "trained_tokens": number | null + readonly "training_file": string + readonly "validation_file": string | null + readonly "integrations"?: ReadonlyArray | null + readonly "seed": number | null + readonly "estimated_finish"?: number | null + readonly "method": { + readonly "type": "dpo" | "reinforcement" + readonly "supervised"?: FineTuneSupervisedMethod + readonly "dpo"?: FineTuneDPOMethod + readonly "reinforcement"?: FineTuneReinforcementMethod + } + readonly "metadata"?: Metadata +} | { + readonly "id": string + readonly "created_at": number + readonly "error": { readonly "code": string; readonly "message": string; readonly "param": string | null } | null | { + readonly [x: string]: Schema.Json + } + readonly "fine_tuned_model": string | null + readonly "finished_at": number | null + readonly "hyperparameters": + | { + readonly "batch_size"?: "auto" | number | null + readonly "learning_rate_multiplier"?: "auto" | number + readonly "n_epochs"?: "auto" | number + } & { readonly [x: string]: Schema.Json } + | null + readonly "model": string + readonly "object": "fine_tuning.job" + readonly "organization_id": string + readonly "result_files": ReadonlyArray + readonly "status": + | "validating_files" + | "queued" + | "running" + | "succeeded" + | "failed" + | "cancelled" + | "pausing" + | "paused" + readonly "trained_tokens": number | null + readonly "training_file": string + readonly "validation_file": string | null + readonly "integrations"?: ReadonlyArray | null + readonly "seed": number | null + readonly "estimated_finish"?: number | null + readonly "method"?: FineTuneMethod | null + readonly "metadata"?: Metadata +} +export const FineTuningJob = Schema.Union([ + Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The object identifier, which can be referenced in the API endpoints." + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the fine-tuning job was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "error": Schema.Union([ + Schema.Struct({ + "code": Schema.String.annotate({ "description": "A machine-readable error code." }), + "message": Schema.String.annotate({ "description": "A human-readable error message." }), + "param": Schema.Union([ + Schema.String.annotate({ + "description": + "The parameter that was invalid, usually `training_file` or `validation_file`. This field will be null if the failure was not parameter-specific." + }), + Schema.Null + ]) + }).annotate({ + "description": + "For fine-tuning jobs that have `failed`, this will contain more information on the cause of the failure." + }), + Schema.Null, + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).check( + Schema.isMaxProperties(0).annotate({ "expected": "a value with at most 0 entries" }) + ) + ]), + "fine_tuned_model": Schema.Union([ + Schema.String.annotate({ + "description": + "The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running." + }), + Schema.Null + ]), + "finished_at": Schema.Union([ + Schema.Number.annotate({ + "description": + "The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the fine-tuning job is still running.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "hyperparameters": Schema.optionalKey( + Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "batch_size": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(256).annotate({ "expected": "a value less than or equal to 256" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Number of examples in each batch. A larger batch size means that model parameters\nare updated less frequently, but with lower variance.\n" + }), + Schema.Null + ]) + ), + "learning_rate_multiplier": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Finite.check(Schema.isGreaterThan(0).annotate({ "expected": "a value greater than 0" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid\noverfitting.\n" + }) + ), + "n_epochs": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(50).annotate({ "expected": "a value less than or equal to 50" })) + ], { mode: "oneOf" }).annotate({ + "description": + "The number of epochs to train the model for. An epoch refers to one full cycle\nthrough the training dataset.\n" + }) + ) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ + "description": + "The hyperparameters used for the fine-tuning job. This value will only be returned when running `supervised` jobs." + }) + ), + "model": Schema.String.annotate({ "description": "The base model that is being fine-tuned." }), + "object": Schema.Literal("fine_tuning.job").annotate({ + "description": "The object type, which is always \"fine_tuning.job\"." + }), + "organization_id": Schema.String.annotate({ "description": "The organization that owns the fine-tuning job." }), + "result_files": Schema.Array(Schema.String).annotate({ + "description": + "The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](https://developers.openai.com/api/reference/resources/files/methods/content)." + }), + "status": Schema.Literals([ + "validating_files", + "queued", + "running", + "succeeded", + "failed", + "cancelled", + "pausing", + "paused" + ]).annotate({ + "description": + "The current status of the fine-tuning job, which can be `validating_files`, `queued`, `running`, `pausing`, `paused`, `succeeded`, `failed`, or `cancelled`." + }), + "trained_tokens": Schema.Union([ + Schema.Number.annotate({ + "description": + "The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "training_file": Schema.String.annotate({ + "description": + "The file ID used for training. You can retrieve the training data with the [Files API](https://developers.openai.com/api/reference/resources/files/methods/content)." + }), + "validation_file": Schema.Union([ + Schema.String.annotate({ + "description": + "The file ID used for validation. You can retrieve the validation results with the [Files API](https://developers.openai.com/api/reference/resources/files/methods/content)." + }), + Schema.Null + ]), + "integrations": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.Union([FineTuningIntegration], { mode: "oneOf" })).annotate({ + "description": "A list of integrations to enable for this fine-tuning job." + }).check(Schema.isMaxLength(5).annotate({ "expected": "a value with a length of at most 5" })), + Schema.Null + ]) + ), + "seed": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ "description": "The seed used for the fine-tuning job." }), + "estimated_finish": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "The Unix timestamp (in seconds) for when the fine-tuning job is estimated to finish. The value will be null if the fine-tuning job is not running.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ), + "method": Schema.Union([ + Schema.Struct({ + "type": Schema.Union([ + Schema.Literal("dpo").annotate({ + "description": "The type of method. Is either `supervised`, `dpo`, or `reinforcement`." + }), + Schema.Literal("reinforcement").annotate({ + "description": "The type of method. Is either `supervised`, `dpo`, or `reinforcement`." + }) + ]), + "supervised": Schema.optionalKey(FineTuneSupervisedMethod), + "dpo": Schema.optionalKey(FineTuneDPOMethod), + "reinforcement": Schema.optionalKey(FineTuneReinforcementMethod) + }).annotate({ "description": "The method used for fine-tuning." }) + ]), + "metadata": Schema.optionalKey(Metadata) + }), + Schema.Struct({ + "id": Schema.String.annotate({ + "description": "The object identifier, which can be referenced in the API endpoints." + }), + "created_at": Schema.Number.annotate({ + "description": "The Unix timestamp (in seconds) for when the fine-tuning job was created.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + "error": Schema.Union([ + Schema.Struct({ + "code": Schema.String.annotate({ "description": "A machine-readable error code." }), + "message": Schema.String.annotate({ "description": "A human-readable error message." }), + "param": Schema.Union([ + Schema.String.annotate({ + "description": + "The parameter that was invalid, usually `training_file` or `validation_file`. This field will be null if the failure was not parameter-specific." + }), + Schema.Null + ]) + }).annotate({ + "description": + "For fine-tuning jobs that have `failed`, this will contain more information on the cause of the failure." + }), + Schema.Null, + Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" })).check( + Schema.isMaxProperties(0).annotate({ "expected": "a value with at most 0 entries" }) + ) + ]), + "fine_tuned_model": Schema.Union([ + Schema.String.annotate({ + "description": + "The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running." + }), + Schema.Null + ]), + "finished_at": Schema.Union([ + Schema.Number.annotate({ + "description": + "The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the fine-tuning job is still running.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "hyperparameters": Schema.Union([ + Schema.StructWithRest( + Schema.Struct({ + "batch_size": Schema.optionalKey( + Schema.Union([ + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(256).annotate({ "expected": "a value less than or equal to 256" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Number of examples in each batch. A larger batch size means that model parameters\nare updated less frequently, but with lower variance.\n" + }), + Schema.Null + ]) + ), + "learning_rate_multiplier": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Finite.check(Schema.isGreaterThan(0).annotate({ "expected": "a value greater than 0" })) + ], { mode: "oneOf" }).annotate({ + "description": + "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid\noverfitting.\n" + }) + ), + "n_epochs": Schema.optionalKey( + Schema.Union([ + Schema.Literal("auto"), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(50).annotate({ "expected": "a value less than or equal to 50" })) + ], { mode: "oneOf" }).annotate({ + "description": + "The number of epochs to train the model for. An epoch refers to one full cycle\nthrough the training dataset.\n" + }) + ) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Null + ]).annotate({ + "description": + "The hyperparameters used for the fine-tuning job. This value will only be returned when running `supervised` jobs." + }), + "model": Schema.String.annotate({ "description": "The base model that is being fine-tuned." }), + "object": Schema.Literal("fine_tuning.job").annotate({ + "description": "The object type, which is always \"fine_tuning.job\"." + }), + "organization_id": Schema.String.annotate({ "description": "The organization that owns the fine-tuning job." }), + "result_files": Schema.Array(Schema.String).annotate({ + "description": + "The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](https://developers.openai.com/api/reference/resources/files/methods/content)." + }), + "status": Schema.Literals([ + "validating_files", + "queued", + "running", + "succeeded", + "failed", + "cancelled", + "pausing", + "paused" + ]).annotate({ + "description": + "The current status of the fine-tuning job, which can be `validating_files`, `queued`, `running`, `pausing`, `paused`, `succeeded`, `failed`, or `cancelled`." + }), + "trained_tokens": Schema.Union([ + Schema.Number.annotate({ + "description": + "The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running." + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]), + "training_file": Schema.String.annotate({ + "description": + "The file ID used for training. You can retrieve the training data with the [Files API](https://developers.openai.com/api/reference/resources/files/methods/content)." + }), + "validation_file": Schema.Union([ + Schema.String.annotate({ + "description": + "The file ID used for validation. You can retrieve the validation results with the [Files API](https://developers.openai.com/api/reference/resources/files/methods/content)." + }), + Schema.Null + ]), + "integrations": Schema.optionalKey( + Schema.Union([ + Schema.Array(Schema.Union([FineTuningIntegration], { mode: "oneOf" })).annotate({ + "description": "A list of integrations to enable for this fine-tuning job." + }).check(Schema.isMaxLength(5).annotate({ "expected": "a value with a length of at most 5" })), + Schema.Null + ]) + ), + "seed": Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + .annotate({ "description": "The seed used for the fine-tuning job." }), + "estimated_finish": Schema.optionalKey( + Schema.Union([ + Schema.Number.annotate({ + "description": + "The Unix timestamp (in seconds) for when the fine-tuning job is estimated to finish. The value will be null if the fine-tuning job is not running.", + "format": "unixtime" + }).check(Schema.isInt().annotate({ "expected": "an integer" })), + Schema.Null + ]) + ), + "method": Schema.optionalKey(Schema.Union([FineTuneMethod, Schema.Null])), + "metadata": Schema.optionalKey(Metadata) + }) +]).annotate({ + "title": "FineTuningJob", + "description": "The `fine_tuning.job` object represents a fine-tuning job that has been created through the API.\n", + "identifier": "FineTuningJob" +}) export type CreateFineTuningJobRequest = { readonly "model": string | "babbage-002" | "davinci-002" | "gpt-3.5-turbo" | "gpt-4o-mini" readonly "training_file": string @@ -28400,20 +45970,22 @@ export type CreateFineTuningJobRequest = { readonly "learning_rate_multiplier"?: "auto" | number readonly "n_epochs"?: "auto" | number } - readonly "suffix"?: string + readonly "suffix"?: string | null readonly "validation_file"?: string | null - readonly "integrations"?: ReadonlyArray< - { - readonly "type": "wandb" - readonly "wandb": { - readonly "project": string - readonly "name"?: string | null - readonly "entity"?: string | null - readonly "tags"?: ReadonlyArray + readonly "integrations"?: + | ReadonlyArray< + { + readonly "type": "wandb" + readonly "wandb": { + readonly "project": string + readonly "name"?: string | null + readonly "entity"?: string | null + readonly "tags"?: ReadonlyArray + } } - } - > - readonly "seed"?: number + > + | null + readonly "seed"?: number | null readonly "method"?: FineTuneMethod readonly "metadata"?: Metadata } @@ -28423,29 +45995,30 @@ export const CreateFineTuningJobRequest = Schema.Struct({ Schema.Literals(["babbage-002", "davinci-002", "gpt-3.5-turbo", "gpt-4o-mini"]) ]).annotate({ "description": - "The name of the model to fine-tune. You can select one of the\n[supported models](/docs/guides/fine-tuning#which-models-can-be-fine-tuned).\n" + "The name of the model to fine-tune. You can select one of the\n[supported models](https://developers.openai.com/api/docs/guides/model-optimization#fine-tuning-methods).\n" }), "training_file": Schema.String.annotate({ "description": - "The ID of an uploaded file that contains training data.\n\nSee [upload file](/docs/api-reference/files/create) for how to upload a file.\n\nYour dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`.\n\nThe contents of the file should differ depending on if the model uses the [chat](/docs/api-reference/fine-tuning/chat-input), [completions](/docs/api-reference/fine-tuning/completions-input) format, or if the fine-tuning method uses the [preference](/docs/api-reference/fine-tuning/preference-input) format.\n\nSee the [fine-tuning guide](/docs/guides/model-optimization) for more details.\n" + "The ID of an uploaded file that contains training data.\n\nSee [upload file](https://developers.openai.com/api/reference/resources/files/methods/create) for how to upload a file.\n\nYour dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`.\n\nThe contents of the file should differ depending on if the model uses the [chat](https://developers.openai.com/api/docs/guides/supervised-fine-tuning#formatting-your-data), [completions](https://developers.openai.com/api/docs/guides/supervised-fine-tuning#formatting-your-data) format, or if the fine-tuning method uses the [preference](https://developers.openai.com/api/docs/guides/direct-preference-optimization) format.\n\nSee the [fine-tuning guide](https://developers.openai.com/api/docs/guides/model-optimization) for more details.\n" }), "hyperparameters": Schema.optionalKey( Schema.Struct({ "batch_size": Schema.optionalKey( Schema.Union([ Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check( - Schema.isLessThanOrEqualTo(256) - ) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(256).annotate({ "expected": "a value less than or equal to 256" })) ], { mode: "oneOf" }).annotate({ "description": "Number of examples in each batch. A larger batch size means that model parameters\nare updated less frequently, but with lower variance.\n" }) ), "learning_rate_multiplier": Schema.optionalKey( - Schema.Union([Schema.Literal("auto"), Schema.Number.check(Schema.isFinite()).check(Schema.isGreaterThan(0))], { - mode: "oneOf" - }).annotate({ + Schema.Union([ + Schema.Literal("auto"), + Schema.Finite.check(Schema.isGreaterThan(0).annotate({ "expected": "a value greater than 0" })) + ], { mode: "oneOf" }).annotate({ "description": "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid\noverfitting.\n" }) @@ -28453,9 +46026,9 @@ export const CreateFineTuningJobRequest = Schema.Struct({ "n_epochs": Schema.optionalKey( Schema.Union([ Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check( - Schema.isLessThanOrEqualTo(50) - ) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(50).annotate({ "expected": "a value less than or equal to 50" })) ], { mode: "oneOf" }).annotate({ "description": "The number of epochs to train the model for. An epoch refers to one full cycle\nthrough the training dataset.\n" @@ -28463,234 +46036,78 @@ export const CreateFineTuningJobRequest = Schema.Struct({ ) }).annotate({ "description": - "The hyperparameters used for the fine-tuning job.\nThis value is now deprecated in favor of `method`, and should be passed in under the `method` parameter.\n" - }) - ), - "suffix": Schema.optionalKey( - Schema.Union([ - Schema.String.check( - Schema.makeFilterGroup([Schema.isMinLength(1), Schema.isMaxLength(64)], { - "description": - "A string of up to 64 characters that will be added to your fine-tuned model name.\n\nFor example, a `suffix` of \"custom-model-name\" would produce a model name like `ft:gpt-4o-mini:openai:custom-model-name:7p4lURel`.\n" - }) - ) - ]) - ), - "validation_file": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "The ID of an uploaded file that contains validation data.\n\nIf you provide this file, the data is used to generate validation\nmetrics periodically during fine-tuning. These metrics can be viewed in\nthe fine-tuning results file.\nThe same data should not be present in both train and validation files.\n\nYour dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`.\n\nSee the [fine-tuning guide](/docs/guides/model-optimization) for more details.\n" - }) - ), - "integrations": Schema.optionalKey(Schema.Union([ - Schema.Array(Schema.Struct({ - "type": Schema.Literal("wandb").annotate({ - "description": - "The type of integration to enable. Currently, only \"wandb\" (Weights and Biases) is supported.\n" - }), - "wandb": Schema.Struct({ - "project": Schema.String.annotate({ - "description": "The name of the project that the new run will be created under.\n" - }), - "name": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": "A display name to set for the run. If not set, we will use the Job ID as the name.\n" - }) - ), - "entity": Schema.optionalKey( - Schema.Union([Schema.String, Schema.Null]).annotate({ - "description": - "The entity to use for the run. This allows you to set the team or username of the WandB user that you would\nlike associated with the run. If not set, the default entity for the registered WandB API key is used.\n" - }) - ), - "tags": Schema.optionalKey( - Schema.Array(Schema.String).annotate({ - "description": - "A list of tags to be attached to the newly created run. These tags are passed through directly to WandB. Some\ndefault tags are generated by OpenAI: \"openai/finetune\", \"openai/{base-model}\", \"openai/{ftjob-abcdef}\".\n" - }) - ) - }).annotate({ - "description": - "The settings for your integration with Weights and Biases. This payload specifies the project that\nmetrics will be sent to. Optionally, you can set an explicit display name for your run, add tags\nto your run, and set a default entity (team, username, etc) to be associated with your run.\n" - }) - })).annotate({ "description": "A list of integrations to enable for your fine-tuning job." }) - ])), - "seed": Schema.optionalKey( - Schema.Union([ - Schema.Number.check(Schema.isInt()).check( - Schema.makeFilterGroup([ - Schema.isFinite(), - Schema.isGreaterThanOrEqualTo(0), - Schema.isLessThanOrEqualTo(2147483647) - ], { - "description": - "The seed controls the reproducibility of the job. Passing in the same seed and job parameters should produce the same results, but may differ in rare cases.\nIf a seed is not specified, one will be generated for you.\n" - }) - ) - ]) - ), - "method": Schema.optionalKey(FineTuneMethod), - "metadata": Schema.optionalKey(Metadata) -}) -export type FineTuningJob = { - readonly "id": string - readonly "created_at": number - readonly "error": { readonly "code": string; readonly "message": string; readonly "param": string | null } | null - readonly "fine_tuned_model": string | null - readonly "finished_at": number | null - readonly "hyperparameters": { - readonly "batch_size"?: "auto" | number | null - readonly "learning_rate_multiplier"?: "auto" | number - readonly "n_epochs"?: "auto" | number - } - readonly "model": string - readonly "object": "fine_tuning.job" - readonly "organization_id": string - readonly "result_files": ReadonlyArray - readonly "status": "validating_files" | "queued" | "running" | "succeeded" | "failed" | "cancelled" - readonly "trained_tokens": number | null - readonly "training_file": string - readonly "validation_file": string | null - readonly "integrations"?: ReadonlyArray | null - readonly "seed": number - readonly "estimated_finish"?: number | null - readonly "method"?: FineTuneMethod - readonly "metadata"?: Metadata -} -export const FineTuningJob = Schema.Struct({ - "id": Schema.String.annotate({ - "description": "The object identifier, which can be referenced in the API endpoints." - }), - "created_at": Schema.Number.annotate({ - "description": "The Unix timestamp (in seconds) for when the fine-tuning job was created.", - "format": "unixtime" - }).check(Schema.isInt()), - "error": Schema.Union([ - Schema.Struct({ - "code": Schema.String.annotate({ "description": "A machine-readable error code." }), - "message": Schema.String.annotate({ "description": "A human-readable error message." }), - "param": Schema.Union([ - Schema.String.annotate({ - "description": - "The parameter that was invalid, usually `training_file` or `validation_file`. This field will be null if the failure was not parameter-specific." - }), - Schema.Null - ]) - }).annotate({ - "description": - "For fine-tuning jobs that have `failed`, this will contain more information on the cause of the failure." - }), - Schema.Null - ]), - "fine_tuned_model": Schema.Union([ - Schema.String.annotate({ - "description": - "The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running." - }), - Schema.Null - ]), - "finished_at": Schema.Union([ - Schema.Number.annotate({ - "description": - "The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the fine-tuning job is still running.", - "format": "unixtime" - }).check(Schema.isInt()), - Schema.Null - ]), - "hyperparameters": Schema.Struct({ - "batch_size": Schema.optionalKey( - Schema.Union([ - Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check( - Schema.isLessThanOrEqualTo(256) - ) - ], { mode: "oneOf" }).annotate({ - "description": - "Number of examples in each batch. A larger batch size means that model parameters\nare updated less frequently, but with lower variance.\n" - }), - Schema.Null - ]) - ), - "learning_rate_multiplier": Schema.optionalKey( - Schema.Union([Schema.Literal("auto"), Schema.Number.check(Schema.isFinite()).check(Schema.isGreaterThan(0))], { - mode: "oneOf" - }).annotate({ - "description": - "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid\noverfitting.\n" - }) - ), - "n_epochs": Schema.optionalKey( - Schema.Union([ - Schema.Literal("auto"), - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(1)).check( - Schema.isLessThanOrEqualTo(50) - ) - ], { mode: "oneOf" }).annotate({ - "description": - "The number of epochs to train the model for. An epoch refers to one full cycle\nthrough the training dataset.\n" - }) - ) - }).annotate({ - "description": - "The hyperparameters used for the fine-tuning job. This value will only be returned when running `supervised` jobs." - }), - "model": Schema.String.annotate({ "description": "The base model that is being fine-tuned." }), - "object": Schema.Literal("fine_tuning.job").annotate({ - "description": "The object type, which is always \"fine_tuning.job\"." - }), - "organization_id": Schema.String.annotate({ "description": "The organization that owns the fine-tuning job." }), - "result_files": Schema.Array(Schema.String).annotate({ - "description": - "The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](/docs/api-reference/files/retrieve-contents)." - }), - "status": Schema.Literals(["validating_files", "queued", "running", "succeeded", "failed", "cancelled"]).annotate({ - "description": - "The current status of the fine-tuning job, which can be either `validating_files`, `queued`, `running`, `succeeded`, `failed`, or `cancelled`." - }), - "trained_tokens": Schema.Union([ - Schema.Number.annotate({ + "The hyperparameters used for the fine-tuning job.\nThis value is now deprecated in favor of `method`, and should be passed in under the `method` parameter.\n" + }) + ), + "suffix": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" }) + ), + Schema.Null + ]).annotate({ "description": - "The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running." - }).check(Schema.isInt()), - Schema.Null - ]), - "training_file": Schema.String.annotate({ - "description": - "The file ID used for training. You can retrieve the training data with the [Files API](/docs/api-reference/files/retrieve-contents)." - }), - "validation_file": Schema.Union([ - Schema.String.annotate({ + "A string of up to 64 characters that will be added to your fine-tuned model name.\n\nFor example, a `suffix` of \"custom-model-name\" would produce a model name like `ft:gpt-4o-mini:openai:custom-model-name:7p4lURel`.\n" + }) + ), + "validation_file": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ "description": - "The file ID used for validation. You can retrieve the validation results with the [Files API](/docs/api-reference/files/retrieve-contents)." - }), - Schema.Null - ]), + "The ID of an uploaded file that contains validation data.\n\nIf you provide this file, the data is used to generate validation\nmetrics periodically during fine-tuning. These metrics can be viewed in\nthe fine-tuning results file.\nThe same data should not be present in both train and validation files.\n\nYour dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`.\n\nSee the [fine-tuning guide](https://developers.openai.com/api/docs/guides/model-optimization) for more details.\n" + }) + ), "integrations": Schema.optionalKey( Schema.Union([ - Schema.Array(Schema.Union([FineTuningIntegration], { mode: "oneOf" })).annotate({ - "description": "A list of integrations to enable for this fine-tuning job." - }).check(Schema.isMaxLength(5)), + Schema.Array(Schema.Struct({ + "type": Schema.Union([Schema.Literal("wandb")], { mode: "oneOf" }).annotate({ + "description": + "The type of integration to enable. Currently, only \"wandb\" (Weights and Biases) is supported.\n" + }), + "wandb": Schema.Struct({ + "project": Schema.String.annotate({ + "description": "The name of the project that the new run will be created under.\n" + }), + "name": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": "A display name to set for the run. If not set, we will use the Job ID as the name.\n" + }) + ), + "entity": Schema.optionalKey( + Schema.Union([Schema.String, Schema.Null]).annotate({ + "description": + "The entity to use for the run. This allows you to set the team or username of the WandB user that you would\nlike associated with the run. If not set, the default entity for the registered WandB API key is used.\n" + }) + ), + "tags": Schema.optionalKey( + Schema.Array(Schema.String).annotate({ + "description": + "A list of tags to be attached to the newly created run. These tags are passed through directly to WandB. Some\ndefault tags are generated by OpenAI: \"openai/finetune\", \"openai/{base-model}\", \"openai/{ftjob-abcdef}\".\n" + }) + ) + }).annotate({ + "description": + "The settings for your integration with Weights and Biases. This payload specifies the project that\nmetrics will be sent to. Optionally, you can set an explicit display name for your run, add tags\nto your run, and set a default entity (team, username, etc) to be associated with your run.\n" + }) + })), Schema.Null - ]) + ]).annotate({ "description": "A list of integrations to enable for your fine-tuning job." }) ), - "seed": Schema.Number.annotate({ "description": "The seed used for the fine-tuning job." }).check(Schema.isInt()), - "estimated_finish": Schema.optionalKey( + "seed": Schema.optionalKey( Schema.Union([ - Schema.Number.annotate({ - "description": - "The Unix timestamp (in seconds) for when the fine-tuning job is estimated to finish. The value will be null if the fine-tuning job is not running.", - "format": "unixtime" - }).check(Schema.isInt()), + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check( + Schema.isLessThanOrEqualTo(2147483647).annotate({ "expected": "a value less than or equal to 2147483647" }) + ), Schema.Null - ]) + ]).annotate({ + "description": + "The seed controls the reproducibility of the job. Passing in the same seed and job parameters should produce the same results, but may differ in rare cases.\nIf a seed is not specified, one will be generated for you.\n" + }) ), "method": Schema.optionalKey(FineTuneMethod), "metadata": Schema.optionalKey(Metadata) -}).annotate({ - "title": "FineTuningJob", - "description": "The `fine_tuning.job` object represents a fine-tuning job that has been created through the API.\n" -}) +}).annotate({ "identifier": "CreateFineTuningJobRequest" }) export type ListPaginatedFineTuningJobsResponse = { readonly "data": ReadonlyArray readonly "has_more": boolean @@ -28700,6 +46117,31 @@ export const ListPaginatedFineTuningJobsResponse = Schema.Struct({ "data": Schema.Array(FineTuningJob), "has_more": Schema.Boolean, "object": Schema.Literal("list") +}).annotate({ "identifier": "ListPaginatedFineTuningJobsResponse" }) +// recursive definitions +const __recursive_CompoundFilter = Schema.Struct({ + "type": Schema.Literals(["and", "or"]).annotate({ "description": "Type of operation: `and` or `or`." }), + "filters": Schema.Array( + Schema.Union([ComparisonFilter, Schema.suspend((): Schema.Codec => CompoundFilter)], { + mode: "oneOf" + }) + ).annotate({ "description": "Array of filters to combine. Items can be `ComparisonFilter` or `CompoundFilter`." }) +}).annotate({ + "title": "Compound Filter", + "description": "Combine multiple filters using `and` or `or`.", + "identifier": "CompoundFilter" +}) +const __recursive_BetaCompoundFilter = Schema.Struct({ + "type": Schema.Literals(["and", "or"]).annotate({ "description": "Type of operation: `and` or `or`." }), + "filters": Schema.Array( + Schema.Union([BetaComparisonFilter, Schema.suspend((): Schema.Codec => BetaCompoundFilter)], { + mode: "oneOf" + }) + ).annotate({ "description": "Array of filters to combine. Items can be `ComparisonFilter` or `CompoundFilter`." }) +}).annotate({ + "title": "Compound Filter", + "description": "Combine multiple filters using `and` or `or`.", + "identifier": "BetaCompoundFilter" }) // schemas export type ListAssistantsParams = { @@ -28709,31 +46151,51 @@ export type ListAssistantsParams = { readonly "before"?: string } export const ListAssistantsParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String) }) export type ListAssistants200 = ListAssistantsResponse export const ListAssistants200 = ListAssistantsResponse +export type ListAssistants429 = ErrorResponse +export const ListAssistants429 = ErrorResponse export type CreateAssistantRequestJson = CreateAssistantRequest export const CreateAssistantRequestJson = CreateAssistantRequest export type CreateAssistant200 = AssistantObject export const CreateAssistant200 = AssistantObject +export type CreateAssistant429 = ErrorResponse +export const CreateAssistant429 = ErrorResponse export type GetAssistant200 = AssistantObject export const GetAssistant200 = AssistantObject +export type GetAssistant429 = ErrorResponse +export const GetAssistant429 = ErrorResponse export type ModifyAssistantRequestJson = ModifyAssistantRequest export const ModifyAssistantRequestJson = ModifyAssistantRequest export type ModifyAssistant200 = AssistantObject export const ModifyAssistant200 = AssistantObject +export type ModifyAssistant429 = ErrorResponse +export const ModifyAssistant429 = ErrorResponse export type DeleteAssistant200 = DeleteAssistantResponse export const DeleteAssistant200 = DeleteAssistantResponse +export type DeleteAssistant429 = ErrorResponse +export const DeleteAssistant429 = ErrorResponse export type CreateSpeechRequestJson = CreateSpeechRequest export const CreateSpeechRequestJson = CreateSpeechRequest export type CreateSpeech200Sse = CreateSpeechResponseStreamEvent export const CreateSpeech200Sse = CreateSpeechResponseStreamEvent -export type CreateTranscriptionRequestFormData = CreateTranscriptionRequest -export const CreateTranscriptionRequestFormData = CreateTranscriptionRequest +export type CreateSpeech400 = ErrorResponse +export const CreateSpeech400 = ErrorResponse +export type CreateSpeech401 = ErrorResponse +export const CreateSpeech401 = ErrorResponse +export type CreateSpeech429 = ErrorResponse +export const CreateSpeech429 = ErrorResponse +export type CreateSpeech500 = ErrorResponse +export const CreateSpeech500 = ErrorResponse +export type CreateSpeech503 = ErrorResponse +export const CreateSpeech503 = ErrorResponse +export type CreateTranscriptionRequestFormData = CreateTranscriptionRequestMultipart +export const CreateTranscriptionRequestFormData = CreateTranscriptionRequestMultipart export type CreateTranscription200 = | CreateTranscriptionResponseJson | CreateTranscriptionResponseDiarizedJson @@ -28742,91 +46204,136 @@ export const CreateTranscription200 = Schema.Union([ CreateTranscriptionResponseJson, CreateTranscriptionResponseDiarizedJson, CreateTranscriptionResponseVerboseJson -], { mode: "oneOf" }) +]) export type CreateTranscription200Sse = CreateTranscriptionResponseStreamEvent export const CreateTranscription200Sse = CreateTranscriptionResponseStreamEvent -export type CreateTranslationRequestFormData = CreateTranslationRequest -export const CreateTranslationRequestFormData = CreateTranslationRequest +export type CreateTranscription400 = ErrorResponse +export const CreateTranscription400 = ErrorResponse +export type CreateTranscription401 = ErrorResponse +export const CreateTranscription401 = ErrorResponse +export type CreateTranscription413 = ErrorResponse +export const CreateTranscription413 = ErrorResponse +export type CreateTranscription429 = ErrorResponse +export const CreateTranscription429 = ErrorResponse +export type CreateTranscription500 = ErrorResponse +export const CreateTranscription500 = ErrorResponse +export type CreateTranscription502 = ErrorResponse +export const CreateTranscription502 = ErrorResponse +export type CreateTranscription503 = ErrorResponse +export const CreateTranscription503 = ErrorResponse +export type CreateTranslationRequestFormData = CreateTranslationRequestMultipart +export const CreateTranslationRequestFormData = CreateTranslationRequestMultipart export type CreateTranslation200 = CreateTranslationResponseJson | CreateTranslationResponseVerboseJson export const CreateTranslation200 = Schema.Union( [CreateTranslationResponseJson, CreateTranslationResponseVerboseJson], { mode: "oneOf" } ) +export type CreateTranslation400 = ErrorResponse +export const CreateTranslation400 = ErrorResponse +export type CreateTranslation401 = ErrorResponse +export const CreateTranslation401 = ErrorResponse +export type CreateTranslation413 = ErrorResponse +export const CreateTranslation413 = ErrorResponse +export type CreateTranslation429 = ErrorResponse +export const CreateTranslation429 = ErrorResponse +export type CreateTranslation500 = ErrorResponse +export const CreateTranslation500 = ErrorResponse +export type CreateTranslation502 = ErrorResponse +export const CreateTranslation502 = ErrorResponse +export type CreateTranslation503 = ErrorResponse +export const CreateTranslation503 = ErrorResponse export type ListVoiceConsentsParams = { readonly "after"?: string; readonly "limit"?: number } export const ListVoiceConsentsParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())) + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))) }) export type ListVoiceConsents200 = VoiceConsentListResource export const ListVoiceConsents200 = VoiceConsentListResource -export type CreateVoiceConsentRequestFormData = CreateVoiceConsentRequest -export const CreateVoiceConsentRequestFormData = CreateVoiceConsentRequest +export type ListVoiceConsents400 = ErrorResponse +export const ListVoiceConsents400 = ErrorResponse +export type ListVoiceConsents404 = ErrorResponse +export const ListVoiceConsents404 = ErrorResponse +export type CreateVoiceConsentRequestFormData = CreateVoiceConsentRequestMultipart +export const CreateVoiceConsentRequestFormData = CreateVoiceConsentRequestMultipart export type CreateVoiceConsent200 = VoiceConsentResource export const CreateVoiceConsent200 = VoiceConsentResource +export type CreateVoiceConsent400 = ErrorResponse +export const CreateVoiceConsent400 = ErrorResponse +export type CreateVoiceConsent404 = ErrorResponse +export const CreateVoiceConsent404 = ErrorResponse export type GetVoiceConsent200 = VoiceConsentResource export const GetVoiceConsent200 = VoiceConsentResource +export type GetVoiceConsent400 = ErrorResponse +export const GetVoiceConsent400 = ErrorResponse +export type GetVoiceConsent404 = ErrorResponse +export const GetVoiceConsent404 = ErrorResponse export type UpdateVoiceConsentRequestJson = UpdateVoiceConsentRequest export const UpdateVoiceConsentRequestJson = UpdateVoiceConsentRequest export type UpdateVoiceConsent200 = VoiceConsentResource export const UpdateVoiceConsent200 = VoiceConsentResource +export type UpdateVoiceConsent400 = ErrorResponse +export const UpdateVoiceConsent400 = ErrorResponse +export type UpdateVoiceConsent404 = ErrorResponse +export const UpdateVoiceConsent404 = ErrorResponse export type DeleteVoiceConsent200 = VoiceConsentDeletedResource export const DeleteVoiceConsent200 = VoiceConsentDeletedResource -export type CreateVoiceRequestFormData = CreateVoiceRequest -export const CreateVoiceRequestFormData = CreateVoiceRequest +export type DeleteVoiceConsent400 = ErrorResponse +export const DeleteVoiceConsent400 = ErrorResponse +export type DeleteVoiceConsent404 = ErrorResponse +export const DeleteVoiceConsent404 = ErrorResponse +export type CreateVoiceRequestFormData = CreateVoiceRequestMultipart +export const CreateVoiceRequestFormData = CreateVoiceRequestMultipart export type CreateVoice200 = VoiceResource export const CreateVoice200 = VoiceResource +export type CreateVoice400 = ErrorResponse +export const CreateVoice400 = ErrorResponse +export type CreateVoice404 = ErrorResponse +export const CreateVoice404 = ErrorResponse +export type CreateVoice500 = ErrorResponse +export const CreateVoice500 = ErrorResponse export type ListBatchesParams = { readonly "after"?: string; readonly "limit"?: number } export const ListBatchesParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())) + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))) }) export type ListBatches200 = ListBatchesResponse export const ListBatches200 = ListBatchesResponse -export type CreateBatchRequestJson = { - readonly "input_file_id": string - readonly "endpoint": - | "/v1/responses" - | "/v1/chat/completions" - | "/v1/embeddings" - | "/v1/completions" - | "/v1/moderations" - | "/v1/images/generations" - | "/v1/images/edits" - | "/v1/videos" - readonly "completion_window": "24h" - readonly "metadata"?: Metadata - readonly "output_expires_after"?: BatchFileExpirationAfter -} -export const CreateBatchRequestJson = Schema.Struct({ - "input_file_id": Schema.String.annotate({ - "description": - "The ID of an uploaded file that contains requests for the new batch.\n\nSee [upload file](/docs/api-reference/files/create) for how to upload a file.\n\nYour input file must be formatted as a [JSONL file](/docs/api-reference/batch/request-input), and must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, and can be up to 200 MB in size.\n" - }), - "endpoint": Schema.Literals([ - "/v1/responses", - "/v1/chat/completions", - "/v1/embeddings", - "/v1/completions", - "/v1/moderations", - "/v1/images/generations", - "/v1/images/edits", - "/v1/videos" - ]).annotate({ - "description": - "The endpoint to be used for all requests in the batch. Currently `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, `/v1/completions`, `/v1/moderations`, `/v1/images/generations`, `/v1/images/edits`, and `/v1/videos` are supported. Note that `/v1/embeddings` batches are also restricted to a maximum of 50,000 embedding inputs across all requests in the batch." - }), - "completion_window": Schema.Literal("24h").annotate({ - "description": "The time frame within which the batch should be processed. Currently only `24h` is supported." - }), - "metadata": Schema.optionalKey(Metadata), - "output_expires_after": Schema.optionalKey(BatchFileExpirationAfter) -}) +export type ListBatches400 = ErrorResponse +export const ListBatches400 = ErrorResponse +export type ListBatches404 = ErrorResponse +export const ListBatches404 = ErrorResponse +export type ListBatches429 = ErrorResponse +export const ListBatches429 = ErrorResponse +export type CreateBatchRequestJson = CreateBatchRequest +export const CreateBatchRequestJson = CreateBatchRequest export type CreateBatch200 = Batch export const CreateBatch200 = Batch +export type CreateBatch400 = ErrorResponse +export const CreateBatch400 = ErrorResponse +export type CreateBatch429 = ErrorResponse +export const CreateBatch429 = ErrorResponse +export type CreateBatch500 = ErrorResponse +export const CreateBatch500 = ErrorResponse +export type CreateBatch503 = ErrorResponse +export const CreateBatch503 = ErrorResponse export type RetrieveBatch200 = Batch export const RetrieveBatch200 = Batch +export type RetrieveBatch400 = ErrorResponse +export const RetrieveBatch400 = ErrorResponse +export type RetrieveBatch404 = ErrorResponse +export const RetrieveBatch404 = ErrorResponse +export type RetrieveBatch429 = ErrorResponse +export const RetrieveBatch429 = ErrorResponse export type CancelBatch200 = Batch export const CancelBatch200 = Batch +export type CancelBatch400 = ErrorResponse +export const CancelBatch400 = ErrorResponse +export type CancelBatch404 = ErrorResponse +export const CancelBatch404 = ErrorResponse +export type CancelBatch409 = ErrorResponse +export const CancelBatch409 = ErrorResponse +export type CancelBatch429 = ErrorResponse +export const CancelBatch429 = ErrorResponse export type ListChatCompletionsParams = { readonly "model"?: string readonly "metadata"?: Metadata @@ -28838,25 +46345,63 @@ export const ListChatCompletionsParams = Schema.Struct({ "model": Schema.optionalKey(Schema.String), "metadata": Schema.optionalKey(Metadata), "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListChatCompletions200 = ChatCompletionList export const ListChatCompletions200 = ChatCompletionList +export type ListChatCompletions400 = ErrorResponse +export const ListChatCompletions400 = ErrorResponse +export type ListChatCompletions429 = ErrorResponse +export const ListChatCompletions429 = ErrorResponse +export type ListChatCompletions500 = ErrorResponse +export const ListChatCompletions500 = ErrorResponse export type CreateChatCompletionRequestJson = CreateChatCompletionRequest export const CreateChatCompletionRequestJson = CreateChatCompletionRequest export type CreateChatCompletion200 = CreateChatCompletionResponse export const CreateChatCompletion200 = CreateChatCompletionResponse export type CreateChatCompletion200Sse = CreateChatCompletionStreamResponse export const CreateChatCompletion200Sse = CreateChatCompletionStreamResponse +export type CreateChatCompletion400 = ErrorResponse +export const CreateChatCompletion400 = ErrorResponse +export type CreateChatCompletion401 = ErrorResponse +export const CreateChatCompletion401 = ErrorResponse +export type CreateChatCompletion404 = ErrorResponse +export const CreateChatCompletion404 = ErrorResponse +export type CreateChatCompletion429 = ErrorResponse +export const CreateChatCompletion429 = ErrorResponse +export type CreateChatCompletion500 = ErrorResponse +export const CreateChatCompletion500 = ErrorResponse +export type CreateChatCompletion503 = ErrorResponse +export const CreateChatCompletion503 = ErrorResponse export type GetChatCompletion200 = CreateChatCompletionResponse export const GetChatCompletion200 = CreateChatCompletionResponse +export type GetChatCompletion404 = ErrorResponse +export const GetChatCompletion404 = ErrorResponse +export type GetChatCompletion429 = ErrorResponse +export const GetChatCompletion429 = ErrorResponse +export type GetChatCompletion500 = ErrorResponse +export const GetChatCompletion500 = ErrorResponse export type UpdateChatCompletionRequestJson = { readonly "metadata": Metadata } export const UpdateChatCompletionRequestJson = Schema.Struct({ "metadata": Metadata }) export type UpdateChatCompletion200 = CreateChatCompletionResponse export const UpdateChatCompletion200 = CreateChatCompletionResponse +export type UpdateChatCompletion400 = ErrorResponse +export const UpdateChatCompletion400 = ErrorResponse +export type UpdateChatCompletion404 = ErrorResponse +export const UpdateChatCompletion404 = ErrorResponse +export type UpdateChatCompletion429 = ErrorResponse +export const UpdateChatCompletion429 = ErrorResponse +export type UpdateChatCompletion500 = ErrorResponse +export const UpdateChatCompletion500 = ErrorResponse export type DeleteChatCompletion200 = ChatCompletionDeleted export const DeleteChatCompletion200 = ChatCompletionDeleted +export type DeleteChatCompletion404 = ErrorResponse +export const DeleteChatCompletion404 = ErrorResponse +export type DeleteChatCompletion429 = ErrorResponse +export const DeleteChatCompletion429 = ErrorResponse +export type DeleteChatCompletion500 = ErrorResponse +export const DeleteChatCompletion500 = ErrorResponse export type GetChatCompletionMessagesParams = { readonly "after"?: string readonly "limit"?: number @@ -28864,15 +46409,35 @@ export type GetChatCompletionMessagesParams = { } export const GetChatCompletionMessagesParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type GetChatCompletionMessages200 = ChatCompletionMessageList export const GetChatCompletionMessages200 = ChatCompletionMessageList +export type GetChatCompletionMessages400 = ErrorResponse +export const GetChatCompletionMessages400 = ErrorResponse +export type GetChatCompletionMessages404 = ErrorResponse +export const GetChatCompletionMessages404 = ErrorResponse +export type GetChatCompletionMessages429 = ErrorResponse +export const GetChatCompletionMessages429 = ErrorResponse +export type GetChatCompletionMessages500 = ErrorResponse +export const GetChatCompletionMessages500 = ErrorResponse export type CreateCompletionRequestJson = CreateCompletionRequest export const CreateCompletionRequestJson = CreateCompletionRequest export type CreateCompletion200 = CreateCompletionResponse export const CreateCompletion200 = CreateCompletionResponse +export type CreateCompletion400 = ErrorResponse +export const CreateCompletion400 = ErrorResponse +export type CreateCompletion401 = ErrorResponse +export const CreateCompletion401 = ErrorResponse +export type CreateCompletion404 = ErrorResponse +export const CreateCompletion404 = ErrorResponse +export type CreateCompletion429 = ErrorResponse +export const CreateCompletion429 = ErrorResponse +export type CreateCompletion500 = ErrorResponse +export const CreateCompletion500 = ErrorResponse +export type CreateCompletion503 = ErrorResponse +export const CreateCompletion503 = ErrorResponse export type ListContainersParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -28880,39 +46445,97 @@ export type ListContainersParams = { readonly "name"?: string } export const ListContainersParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "name": Schema.optionalKey(Schema.String) }) export type ListContainers200 = ContainerListResource export const ListContainers200 = ContainerListResource +export type ListContainers404 = ErrorResponse +export const ListContainers404 = ErrorResponse +export type ListContainers429 = ErrorResponse +export const ListContainers429 = ErrorResponse export type CreateContainerRequestJson = CreateContainerBody export const CreateContainerRequestJson = CreateContainerBody export type CreateContainer200 = ContainerResource export const CreateContainer200 = ContainerResource +export type CreateContainer400 = ErrorResponse +export const CreateContainer400 = ErrorResponse +export type CreateContainer429 = ErrorResponse +export const CreateContainer429 = ErrorResponse export type RetrieveContainer200 = ContainerResource export const RetrieveContainer200 = ContainerResource +export type RetrieveContainer404 = ErrorResponse +export const RetrieveContainer404 = ErrorResponse +export type RetrieveContainer429 = ErrorResponse +export const RetrieveContainer429 = ErrorResponse +export type DeleteContainer200 = { + readonly "object": "container.deleted" + readonly "deleted": boolean + readonly "id": string +} +export const DeleteContainer200 = Schema.Struct({ + "object": Schema.Literal("container.deleted"), + "deleted": Schema.Boolean, + "id": Schema.String +}) +export type DeleteContainer404 = ErrorResponse +export const DeleteContainer404 = ErrorResponse +export type DeleteContainer429 = ErrorResponse +export const DeleteContainer429 = ErrorResponse export type ListContainerFilesParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" readonly "after"?: string } export const ListContainerFilesParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String) }) export type ListContainerFiles200 = ContainerFileListResource export const ListContainerFiles200 = ContainerFileListResource +export type ListContainerFiles404 = ErrorResponse +export const ListContainerFiles404 = ErrorResponse +export type ListContainerFiles429 = ErrorResponse +export const ListContainerFiles429 = ErrorResponse export type CreateContainerFileRequestJson = CreateContainerFileBody export const CreateContainerFileRequestJson = CreateContainerFileBody -export type CreateContainerFileRequestFormData = CreateContainerFileBody -export const CreateContainerFileRequestFormData = CreateContainerFileBody +export type CreateContainerFileRequestFormData = CreateContainerFileBodyMultipart +export const CreateContainerFileRequestFormData = CreateContainerFileBodyMultipart export type CreateContainerFile200 = ContainerFileResource export const CreateContainerFile200 = ContainerFileResource +export type CreateContainerFile400 = ErrorResponse +export const CreateContainerFile400 = ErrorResponse +export type CreateContainerFile404 = ErrorResponse +export const CreateContainerFile404 = ErrorResponse +export type CreateContainerFile429 = ErrorResponse +export const CreateContainerFile429 = ErrorResponse export type RetrieveContainerFile200 = ContainerFileResource export const RetrieveContainerFile200 = ContainerFileResource +export type RetrieveContainerFile404 = ErrorResponse +export const RetrieveContainerFile404 = ErrorResponse +export type RetrieveContainerFile429 = ErrorResponse +export const RetrieveContainerFile429 = ErrorResponse +export type DeleteContainerFile200 = { + readonly "object": "container.file.deleted" + readonly "deleted": boolean + readonly "id": string +} +export const DeleteContainerFile200 = Schema.Struct({ + "object": Schema.Literal("container.file.deleted"), + "deleted": Schema.Boolean, + "id": Schema.String +}) +export type DeleteContainerFile404 = ErrorResponse +export const DeleteContainerFile404 = ErrorResponse +export type DeleteContainerFile429 = ErrorResponse +export const DeleteContainerFile429 = ErrorResponse +export type RetrieveContainerFileContent404 = ErrorResponse +export const RetrieveContainerFileContent404 = ErrorResponse +export type RetrieveContainerFileContent429 = ErrorResponse +export const RetrieveContainerFileContent429 = ErrorResponse export type ListConversationItemsParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -28920,39 +46543,85 @@ export type ListConversationItemsParams = { readonly "include"?: ReadonlyArray } export const ListConversationItemsParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "include": Schema.optionalKey(Schema.Array(IncludeEnum)) }) export type ListConversationItems200 = ConversationItemList export const ListConversationItems200 = ConversationItemList +export type ListConversationItems400 = ErrorResponse +export const ListConversationItems400 = ErrorResponse +export type ListConversationItems404 = ErrorResponse +export const ListConversationItems404 = ErrorResponse +export type ListConversationItems429 = ErrorResponse +export const ListConversationItems429 = ErrorResponse export type CreateConversationItemsParams = { readonly "include"?: ReadonlyArray } export const CreateConversationItemsParams = Schema.Struct({ "include": Schema.optionalKey(Schema.Array(IncludeEnum)) }) -export type CreateConversationItemsRequestJson = { - readonly "items": ReadonlyArray - readonly [x: string]: unknown -} -export const CreateConversationItemsRequestJson = Schema.StructWithRest( - Schema.Struct({ - "items": Schema.Array(InputItem).annotate({ - "description": "The items to add to the conversation. You may add up to 20 items at a time.\n" - }).check(Schema.isMaxLength(20)) - }), - [Schema.Record(Schema.String, Schema.Unknown)] -) +export type CreateConversationItemsRequestJson = + | null + | string + | number + | boolean + | { readonly "items": ReadonlyArray } & { readonly [x: string]: Schema.Json } + | ReadonlyArray +export const CreateConversationItemsRequestJson = Schema.Union([ + Schema.Null, + Schema.String, + Schema.Finite, + Schema.Boolean, + Schema.StructWithRest( + Schema.Struct({ + "items": Schema.Array(InputItem).annotate({ + "description": "The items to add to the conversation. You may add up to 20 items at a time.\n" + }).check(Schema.isMaxLength(20).annotate({ "expected": "a value with a length of at most 20" })) + }), + [Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))] + ), + Schema.Array(Schema.Json.annotate({ "expected": "JSON value" })) +]) export type CreateConversationItems200 = ConversationItemList export const CreateConversationItems200 = ConversationItemList +export type CreateConversationItems400 = ErrorResponse +export const CreateConversationItems400 = ErrorResponse +export type CreateConversationItems404 = ErrorResponse +export const CreateConversationItems404 = ErrorResponse +export type CreateConversationItems429 = ErrorResponse +export const CreateConversationItems429 = ErrorResponse +export type CreateConversationItems500 = ErrorResponse +export const CreateConversationItems500 = ErrorResponse export type GetConversationItemParams = { readonly "include"?: ReadonlyArray } export const GetConversationItemParams = Schema.Struct({ "include": Schema.optionalKey(Schema.Array(IncludeEnum)) }) export type GetConversationItem200 = ConversationItem export const GetConversationItem200 = ConversationItem +export type GetConversationItem404 = ErrorResponse +export const GetConversationItem404 = ErrorResponse +export type GetConversationItem429 = ErrorResponse +export const GetConversationItem429 = ErrorResponse export type DeleteConversationItem200 = ConversationResource export const DeleteConversationItem200 = ConversationResource +export type DeleteConversationItem400 = ErrorResponse +export const DeleteConversationItem400 = ErrorResponse +export type DeleteConversationItem404 = ErrorResponse +export const DeleteConversationItem404 = ErrorResponse +export type DeleteConversationItem429 = ErrorResponse +export const DeleteConversationItem429 = ErrorResponse +export type DeleteConversationItem500 = ErrorResponse +export const DeleteConversationItem500 = ErrorResponse export type CreateEmbeddingRequestJson = CreateEmbeddingRequest export const CreateEmbeddingRequestJson = CreateEmbeddingRequest export type CreateEmbedding200 = CreateEmbeddingResponse export const CreateEmbedding200 = CreateEmbeddingResponse +export type CreateEmbedding400 = ErrorResponse +export const CreateEmbedding400 = ErrorResponse +export type CreateEmbedding401 = ErrorResponse +export const CreateEmbedding401 = ErrorResponse +export type CreateEmbedding429 = ErrorResponse +export const CreateEmbedding429 = ErrorResponse +export type CreateEmbedding500 = ErrorResponse +export const CreateEmbedding500 = ErrorResponse +export type CreateEmbedding503 = ErrorResponse +export const CreateEmbedding503 = ErrorResponse export type ListEvalsParams = { readonly "after"?: string readonly "limit"?: number @@ -28961,18 +46630,28 @@ export type ListEvalsParams = { } export const ListEvalsParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "order_by": Schema.optionalKey(Schema.Literals(["created_at", "updated_at"])) }) export type ListEvals200 = EvalList export const ListEvals200 = EvalList +export type ListEvals429 = ErrorResponse +export const ListEvals429 = ErrorResponse export type CreateEvalRequestJson = CreateEvalRequest export const CreateEvalRequestJson = CreateEvalRequest export type CreateEval201 = Eval export const CreateEval201 = Eval +export type CreateEval400 = ErrorResponse +export const CreateEval400 = ErrorResponse +export type CreateEval429 = ErrorResponse +export const CreateEval429 = ErrorResponse export type GetEval200 = Eval export const GetEval200 = Eval +export type GetEval404 = ErrorResponse +export const GetEval404 = ErrorResponse +export type GetEval429 = ErrorResponse +export const GetEval429 = ErrorResponse export type UpdateEvalRequestJson = { readonly "name"?: string; readonly "metadata"?: Metadata } export const UpdateEvalRequestJson = Schema.Struct({ "name": Schema.optionalKey(Schema.String.annotate({ "description": "Rename the evaluation." })), @@ -28980,14 +46659,24 @@ export const UpdateEvalRequestJson = Schema.Struct({ }) export type UpdateEval200 = Eval export const UpdateEval200 = Eval +export type UpdateEval400 = ErrorResponse +export const UpdateEval400 = ErrorResponse +export type UpdateEval404 = ErrorResponse +export const UpdateEval404 = ErrorResponse +export type UpdateEval429 = ErrorResponse +export const UpdateEval429 = ErrorResponse export type DeleteEval200 = { readonly "object": string; readonly "deleted": boolean; readonly "eval_id": string } export const DeleteEval200 = Schema.Struct({ "object": Schema.String, "deleted": Schema.Boolean, "eval_id": Schema.String }) -export type DeleteEval404 = Error -export const DeleteEval404 = Error +export type DeleteEval400 = ErrorResponse +export const DeleteEval400 = ErrorResponse +export type DeleteEval404 = ErrorResponse +export const DeleteEval404 = ErrorResponse +export type DeleteEval429 = ErrorResponse +export const DeleteEval429 = ErrorResponse export type GetEvalRunsParams = { readonly "after"?: string readonly "limit"?: number @@ -28996,30 +46685,54 @@ export type GetEvalRunsParams = { } export const GetEvalRunsParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "status": Schema.optionalKey(Schema.Literals(["queued", "in_progress", "completed", "canceled", "failed"])) }) export type GetEvalRuns200 = EvalRunList export const GetEvalRuns200 = EvalRunList +export type GetEvalRuns400 = ErrorResponse +export const GetEvalRuns400 = ErrorResponse +export type GetEvalRuns404 = ErrorResponse +export const GetEvalRuns404 = ErrorResponse +export type GetEvalRuns429 = ErrorResponse +export const GetEvalRuns429 = ErrorResponse export type CreateEvalRunRequestJson = CreateEvalRunRequest export const CreateEvalRunRequestJson = CreateEvalRunRequest export type CreateEvalRun201 = EvalRun export const CreateEvalRun201 = EvalRun -export type CreateEvalRun400 = Error -export const CreateEvalRun400 = Error +export type CreateEvalRun400 = ErrorResponse +export const CreateEvalRun400 = ErrorResponse +export type CreateEvalRun404 = ErrorResponse +export const CreateEvalRun404 = ErrorResponse +export type CreateEvalRun429 = ErrorResponse +export const CreateEvalRun429 = ErrorResponse +export type CreateEvalRun500 = ErrorResponse +export const CreateEvalRun500 = ErrorResponse export type GetEvalRun200 = EvalRun export const GetEvalRun200 = EvalRun -export type CancelEvalRun200 = EvalRun -export const CancelEvalRun200 = EvalRun +export type GetEvalRun400 = ErrorResponse +export const GetEvalRun400 = ErrorResponse +export type GetEvalRun404 = ErrorResponse +export const GetEvalRun404 = ErrorResponse +export type GetEvalRun429 = ErrorResponse +export const GetEvalRun429 = ErrorResponse export type DeleteEvalRun200 = { readonly "object"?: string; readonly "deleted"?: boolean; readonly "run_id"?: string } export const DeleteEvalRun200 = Schema.Struct({ "object": Schema.optionalKey(Schema.String), "deleted": Schema.optionalKey(Schema.Boolean), "run_id": Schema.optionalKey(Schema.String) }) -export type DeleteEvalRun404 = Error -export const DeleteEvalRun404 = Error +export type DeleteEvalRun400 = ErrorResponse +export const DeleteEvalRun400 = ErrorResponse +export type DeleteEvalRun404 = ErrorResponse +export const DeleteEvalRun404 = ErrorResponse +export type DeleteEvalRun429 = ErrorResponse +export const DeleteEvalRun429 = ErrorResponse +export type CancelEvalRun200 = EvalRun +export const CancelEvalRun200 = EvalRun +export type CancelEvalRun429 = ErrorResponse +export const CancelEvalRun429 = ErrorResponse export type GetEvalRunOutputItemsParams = { readonly "after"?: string readonly "limit"?: number @@ -29028,14 +46741,26 @@ export type GetEvalRunOutputItemsParams = { } export const GetEvalRunOutputItemsParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "status": Schema.optionalKey(Schema.Literals(["fail", "pass"])), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type GetEvalRunOutputItems200 = EvalRunOutputItemList export const GetEvalRunOutputItems200 = EvalRunOutputItemList +export type GetEvalRunOutputItems400 = ErrorResponse +export const GetEvalRunOutputItems400 = ErrorResponse +export type GetEvalRunOutputItems404 = ErrorResponse +export const GetEvalRunOutputItems404 = ErrorResponse +export type GetEvalRunOutputItems429 = ErrorResponse +export const GetEvalRunOutputItems429 = ErrorResponse export type GetEvalRunOutputItem200 = EvalRunOutputItem export const GetEvalRunOutputItem200 = EvalRunOutputItem +export type GetEvalRunOutputItem400 = ErrorResponse +export const GetEvalRunOutputItem400 = ErrorResponse +export type GetEvalRunOutputItem404 = ErrorResponse +export const GetEvalRunOutputItem404 = ErrorResponse +export type GetEvalRunOutputItem429 = ErrorResponse +export const GetEvalRunOutputItem429 = ErrorResponse export type ListFilesParams = { readonly "purpose"?: string readonly "limit"?: number @@ -29044,30 +46769,64 @@ export type ListFilesParams = { } export const ListFilesParams = Schema.Struct({ "purpose": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String) }) export type ListFiles200 = ListFilesResponse export const ListFiles200 = ListFilesResponse -export type CreateFileRequestFormData = CreateFileRequest -export const CreateFileRequestFormData = CreateFileRequest +export type ListFiles400 = ErrorResponse +export const ListFiles400 = ErrorResponse +export type ListFiles404 = ErrorResponse +export const ListFiles404 = ErrorResponse +export type ListFiles429 = ErrorResponse +export const ListFiles429 = ErrorResponse +export type CreateFileRequestFormData = CreateFileRequestMultipart +export const CreateFileRequestFormData = CreateFileRequestMultipart export type CreateFile200 = OpenAIFile export const CreateFile200 = OpenAIFile +export type CreateFile400 = ErrorResponse +export const CreateFile400 = ErrorResponse +export type CreateFile429 = ErrorResponse +export const CreateFile429 = ErrorResponse +export type CreateFile500 = ErrorResponse +export const CreateFile500 = ErrorResponse export type RetrieveFile200 = OpenAIFile export const RetrieveFile200 = OpenAIFile +export type RetrieveFile404 = ErrorResponse +export const RetrieveFile404 = ErrorResponse +export type RetrieveFile429 = ErrorResponse +export const RetrieveFile429 = ErrorResponse export type DeleteFile200 = DeleteFileResponse export const DeleteFile200 = DeleteFileResponse -export type DownloadFile200 = string -export const DownloadFile200 = Schema.String +export type DeleteFile404 = ErrorResponse +export const DeleteFile404 = ErrorResponse +export type DeleteFile429 = ErrorResponse +export const DeleteFile429 = ErrorResponse +export type DownloadFile400 = ErrorResponse +export const DownloadFile400 = ErrorResponse +export type DownloadFile404 = ErrorResponse +export const DownloadFile404 = ErrorResponse +export type DownloadFile429 = ErrorResponse +export const DownloadFile429 = ErrorResponse +export type DownloadFile500 = ErrorResponse +export const DownloadFile500 = ErrorResponse export type RunGraderRequestJson = RunGraderRequest export const RunGraderRequestJson = RunGraderRequest export type RunGrader200 = RunGraderResponse export const RunGrader200 = RunGraderResponse +export type RunGrader400 = ErrorResponse +export const RunGrader400 = ErrorResponse +export type RunGrader429 = ErrorResponse +export const RunGrader429 = ErrorResponse export type ValidateGraderRequestJson = ValidateGraderRequest export const ValidateGraderRequestJson = ValidateGraderRequest export type ValidateGrader200 = ValidateGraderResponse export const ValidateGrader200 = ValidateGraderResponse +export type ValidateGrader400 = ErrorResponse +export const ValidateGrader400 = ErrorResponse +export type ValidateGrader429 = ErrorResponse +export const ValidateGrader429 = ErrorResponse export type ListFineTuningCheckpointPermissionsParams = { readonly "project_id"?: string readonly "after"?: string @@ -29077,83 +46836,249 @@ export type ListFineTuningCheckpointPermissionsParams = { export const ListFineTuningCheckpointPermissionsParams = Schema.Struct({ "project_id": Schema.optionalKey(Schema.String), "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["ascending", "descending"])) }) export type ListFineTuningCheckpointPermissions200 = ListFineTuningCheckpointPermissionResponse export const ListFineTuningCheckpointPermissions200 = ListFineTuningCheckpointPermissionResponse +export type ListFineTuningCheckpointPermissions400 = ErrorResponse +export const ListFineTuningCheckpointPermissions400 = ErrorResponse +export type ListFineTuningCheckpointPermissions429 = ErrorResponse +export const ListFineTuningCheckpointPermissions429 = ErrorResponse export type CreateFineTuningCheckpointPermissionRequestJson = CreateFineTuningCheckpointPermissionRequest export const CreateFineTuningCheckpointPermissionRequestJson = CreateFineTuningCheckpointPermissionRequest export type CreateFineTuningCheckpointPermission200 = ListFineTuningCheckpointPermissionResponse export const CreateFineTuningCheckpointPermission200 = ListFineTuningCheckpointPermissionResponse +export type CreateFineTuningCheckpointPermission400 = ErrorResponse +export const CreateFineTuningCheckpointPermission400 = ErrorResponse +export type CreateFineTuningCheckpointPermission404 = ErrorResponse +export const CreateFineTuningCheckpointPermission404 = ErrorResponse +export type CreateFineTuningCheckpointPermission429 = ErrorResponse +export const CreateFineTuningCheckpointPermission429 = ErrorResponse export type DeleteFineTuningCheckpointPermission200 = DeleteFineTuningCheckpointPermissionResponse export const DeleteFineTuningCheckpointPermission200 = DeleteFineTuningCheckpointPermissionResponse +export type DeleteFineTuningCheckpointPermission400 = ErrorResponse +export const DeleteFineTuningCheckpointPermission400 = ErrorResponse +export type DeleteFineTuningCheckpointPermission404 = ErrorResponse +export const DeleteFineTuningCheckpointPermission404 = ErrorResponse +export type DeleteFineTuningCheckpointPermission429 = ErrorResponse +export const DeleteFineTuningCheckpointPermission429 = ErrorResponse export type ListPaginatedFineTuningJobsParams = { readonly "after"?: string readonly "limit"?: number - readonly "metadata"?: {} + readonly "metadata"?: { readonly [x: string]: string } | null } export const ListPaginatedFineTuningJobsParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), - "metadata": Schema.optionalKey(Schema.Union([Schema.Struct({})])) + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), + "metadata": Schema.optionalKey(Schema.Union([Schema.Record(Schema.String, Schema.String), Schema.Null])) }) export type ListPaginatedFineTuningJobs200 = ListPaginatedFineTuningJobsResponse export const ListPaginatedFineTuningJobs200 = ListPaginatedFineTuningJobsResponse +export type ListPaginatedFineTuningJobs400 = ErrorResponse +export const ListPaginatedFineTuningJobs400 = ErrorResponse +export type ListPaginatedFineTuningJobs429 = ErrorResponse +export const ListPaginatedFineTuningJobs429 = ErrorResponse export type CreateFineTuningJobRequestJson = CreateFineTuningJobRequest export const CreateFineTuningJobRequestJson = CreateFineTuningJobRequest export type CreateFineTuningJob200 = FineTuningJob export const CreateFineTuningJob200 = FineTuningJob +export type CreateFineTuningJob400 = ErrorResponse +export const CreateFineTuningJob400 = ErrorResponse +export type CreateFineTuningJob429 = ErrorResponse +export const CreateFineTuningJob429 = ErrorResponse export type RetrieveFineTuningJob200 = FineTuningJob export const RetrieveFineTuningJob200 = FineTuningJob +export type RetrieveFineTuningJob404 = ErrorResponse +export const RetrieveFineTuningJob404 = ErrorResponse +export type RetrieveFineTuningJob429 = ErrorResponse +export const RetrieveFineTuningJob429 = ErrorResponse export type CancelFineTuningJob200 = FineTuningJob export const CancelFineTuningJob200 = FineTuningJob +export type CancelFineTuningJob400 = ErrorResponse +export const CancelFineTuningJob400 = ErrorResponse +export type CancelFineTuningJob404 = ErrorResponse +export const CancelFineTuningJob404 = ErrorResponse +export type CancelFineTuningJob429 = ErrorResponse +export const CancelFineTuningJob429 = ErrorResponse export type ListFineTuningJobCheckpointsParams = { readonly "after"?: string; readonly "limit"?: number } export const ListFineTuningJobCheckpointsParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())) + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))) }) export type ListFineTuningJobCheckpoints200 = ListFineTuningJobCheckpointsResponse export const ListFineTuningJobCheckpoints200 = ListFineTuningJobCheckpointsResponse +export type ListFineTuningJobCheckpoints400 = ErrorResponse +export const ListFineTuningJobCheckpoints400 = ErrorResponse +export type ListFineTuningJobCheckpoints404 = ErrorResponse +export const ListFineTuningJobCheckpoints404 = ErrorResponse +export type ListFineTuningJobCheckpoints429 = ErrorResponse +export const ListFineTuningJobCheckpoints429 = ErrorResponse export type ListFineTuningEventsParams = { readonly "after"?: string; readonly "limit"?: number } export const ListFineTuningEventsParams = Schema.Struct({ "after": Schema.optionalKey(Schema.String), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())) + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))) }) export type ListFineTuningEvents200 = ListFineTuningJobEventsResponse export const ListFineTuningEvents200 = ListFineTuningJobEventsResponse +export type ListFineTuningEvents400 = ErrorResponse +export const ListFineTuningEvents400 = ErrorResponse +export type ListFineTuningEvents404 = ErrorResponse +export const ListFineTuningEvents404 = ErrorResponse +export type ListFineTuningEvents429 = ErrorResponse +export const ListFineTuningEvents429 = ErrorResponse export type PauseFineTuningJob200 = FineTuningJob export const PauseFineTuningJob200 = FineTuningJob +export type PauseFineTuningJob400 = ErrorResponse +export const PauseFineTuningJob400 = ErrorResponse +export type PauseFineTuningJob404 = ErrorResponse +export const PauseFineTuningJob404 = ErrorResponse +export type PauseFineTuningJob429 = ErrorResponse +export const PauseFineTuningJob429 = ErrorResponse export type ResumeFineTuningJob200 = FineTuningJob export const ResumeFineTuningJob200 = FineTuningJob +export type ResumeFineTuningJob400 = ErrorResponse +export const ResumeFineTuningJob400 = ErrorResponse +export type ResumeFineTuningJob404 = ErrorResponse +export const ResumeFineTuningJob404 = ErrorResponse +export type ResumeFineTuningJob429 = ErrorResponse +export const ResumeFineTuningJob429 = ErrorResponse export type CreateImageEditRequestJson = EditImageBodyJsonParam export const CreateImageEditRequestJson = EditImageBodyJsonParam -export type CreateImageEditRequestFormData = CreateImageEditRequest -export const CreateImageEditRequestFormData = CreateImageEditRequest +export type CreateImageEditRequestFormData = CreateImageEditRequestMultipart +export const CreateImageEditRequestFormData = CreateImageEditRequestMultipart export type CreateImageEdit200 = ImagesResponse export const CreateImageEdit200 = ImagesResponse export type CreateImageEdit200Sse = ImageEditStreamEvent export const CreateImageEdit200Sse = ImageEditStreamEvent +export type CreateImageEdit400 = ErrorResponse +export const CreateImageEdit400 = ErrorResponse +export type CreateImageEdit403 = ErrorResponse +export const CreateImageEdit403 = ErrorResponse +export type CreateImageEdit410 = ErrorResponse +export const CreateImageEdit410 = ErrorResponse +export type CreateImageEdit429 = ErrorResponse +export const CreateImageEdit429 = ErrorResponse +export type CreateImageEdit500 = ErrorResponse +export const CreateImageEdit500 = ErrorResponse +export type CreateImageEdit503 = ErrorResponse +export const CreateImageEdit503 = ErrorResponse export type CreateImageRequestJson = CreateImageRequest export const CreateImageRequestJson = CreateImageRequest export type CreateImage200 = ImagesResponse export const CreateImage200 = ImagesResponse export type CreateImage200Sse = ImageGenStreamEvent export const CreateImage200Sse = ImageGenStreamEvent -export type CreateImageVariationRequestFormData = CreateImageVariationRequest -export const CreateImageVariationRequestFormData = CreateImageVariationRequest +export type CreateImage400 = ErrorResponse +export const CreateImage400 = ErrorResponse +export type CreateImage403 = ErrorResponse +export const CreateImage403 = ErrorResponse +export type CreateImage410 = ErrorResponse +export const CreateImage410 = ErrorResponse +export type CreateImage429 = ErrorResponse +export const CreateImage429 = ErrorResponse +export type CreateImage500 = ErrorResponse +export const CreateImage500 = ErrorResponse +export type CreateImage503 = ErrorResponse +export const CreateImage503 = ErrorResponse +export type CreateImageVariationRequestFormData = CreateImageVariationRequestMultipart +export const CreateImageVariationRequestFormData = CreateImageVariationRequestMultipart export type CreateImageVariation200 = ImagesResponse export const CreateImageVariation200 = ImagesResponse +export type CreateImageVariation400 = ErrorResponse +export const CreateImageVariation400 = ErrorResponse +export type CreateImageVariation403 = ErrorResponse +export const CreateImageVariation403 = ErrorResponse +export type CreateImageVariation410 = ErrorResponse +export const CreateImageVariation410 = ErrorResponse +export type CreateImageVariation429 = ErrorResponse +export const CreateImageVariation429 = ErrorResponse +export type CreateImageVariation500 = ErrorResponse +export const CreateImageVariation500 = ErrorResponse +export type CreateLiveRequestJson = LiveSessionCreateRequest +export const CreateLiveRequestJson = LiveSessionCreateRequest +export type CreateLive201 = LiveSessionCreateResponse +export const CreateLive201 = LiveSessionCreateResponse +export type CreateLive400 = ErrorResponse +export const CreateLive400 = ErrorResponse +export type CreateLive413 = ErrorResponse +export const CreateLive413 = ErrorResponse +export type CreateLive429 = ErrorResponse +export const CreateLive429 = ErrorResponse +export type CreateLive503 = ErrorResponse +export const CreateLive503 = ErrorResponse +export type CreateLive504 = ErrorResponse +export const CreateLive504 = ErrorResponse +export type AcceptLiveSessionRequestJson = LiveCallAcceptRequest +export const AcceptLiveSessionRequestJson = LiveCallAcceptRequest +export type AcceptLiveSession400 = ErrorResponse +export const AcceptLiveSession400 = ErrorResponse +export type AcceptLiveSession404 = ErrorResponse +export const AcceptLiveSession404 = ErrorResponse +export type AcceptLiveSession409 = ErrorResponse +export const AcceptLiveSession409 = ErrorResponse +export type AcceptLiveSession429 = ErrorResponse +export const AcceptLiveSession429 = ErrorResponse +export type AcceptLiveSession503 = ErrorResponse +export const AcceptLiveSession503 = ErrorResponse +export type ForkLiveSessionRequestJson = LiveForkRequest +export const ForkLiveSessionRequestJson = LiveForkRequest +export type ForkLiveSession201 = LiveCreateResponse +export const ForkLiveSession201 = LiveCreateResponse +export type ForkLiveSession400 = ErrorResponse +export const ForkLiveSession400 = ErrorResponse +export type ForkLiveSession413 = ErrorResponse +export const ForkLiveSession413 = ErrorResponse +export type ForkLiveSession429 = ErrorResponse +export const ForkLiveSession429 = ErrorResponse +export type ForkLiveSession503 = ErrorResponse +export const ForkLiveSession503 = ErrorResponse +export type HangupLiveSession404 = ErrorResponse +export const HangupLiveSession404 = ErrorResponse +export type ReferLiveSessionRequestJson = LiveCallReferRequest +export const ReferLiveSessionRequestJson = LiveCallReferRequest +export type ReferLiveSession400 = ErrorResponse +export const ReferLiveSession400 = ErrorResponse +export type ReferLiveSession404 = ErrorResponse +export const ReferLiveSession404 = ErrorResponse +export type RejectLiveSessionRequestJson = LiveCallRejectRequest +export const RejectLiveSessionRequestJson = LiveCallRejectRequest +export type RejectLiveSession400 = ErrorResponse +export const RejectLiveSession400 = ErrorResponse +export type RejectLiveSession404 = ErrorResponse +export const RejectLiveSession404 = ErrorResponse +export type RejectLiveSession409 = ErrorResponse +export const RejectLiveSession409 = ErrorResponse export type ListModels200 = ListModelsResponse export const ListModels200 = ListModelsResponse +export type ListModels403 = PermissionErrorResponse +export const ListModels403 = PermissionErrorResponse export type RetrieveModel200 = Model export const RetrieveModel200 = Model +export type RetrieveModel403 = PermissionErrorResponse +export const RetrieveModel403 = PermissionErrorResponse +export type RetrieveModel404 = ErrorResponse +export const RetrieveModel404 = ErrorResponse export type DeleteModel200 = DeleteModelResponse export const DeleteModel200 = DeleteModelResponse +export type DeleteModel403 = PermissionErrorResponse +export const DeleteModel403 = PermissionErrorResponse +export type DeleteModel404 = ErrorResponse +export const DeleteModel404 = ErrorResponse export type CreateModerationRequestJson = CreateModerationRequest export const CreateModerationRequestJson = CreateModerationRequest export type CreateModeration200 = CreateModerationResponse export const CreateModeration200 = CreateModerationResponse +export type CreateModeration400 = ErrorResponse +export const CreateModeration400 = ErrorResponse +export type CreateModeration403 = ErrorResponse +export const CreateModeration403 = ErrorResponse +export type CreateModeration429 = ErrorResponse +export const CreateModeration429 = ErrorResponse +export type CreateModeration500 = ErrorResponse +export const CreateModeration500 = ErrorResponse +export type CreateModeration503 = ErrorResponse +export const CreateModeration503 = ErrorResponse export type AdminApiKeysListParams = { readonly "after"?: string | null readonly "order"?: "asc" | "desc" @@ -29171,17 +47096,42 @@ export const AdminApiKeysListParams = Schema.Struct({ }) ), "limit": Schema.optionalKey( - Schema.Number.annotate({ "description": "Maximum number of keys to return." }).check(Schema.isInt()) + Schema.Number.annotate({ "description": "Maximum number of keys to return." }).check( + Schema.isInt().annotate({ "expected": "an integer" }) + ) ) }) export type AdminApiKeysList200 = ApiKeyList export const AdminApiKeysList200 = ApiKeyList -export type AdminApiKeysCreateRequestJson = { readonly "name": string } -export const AdminApiKeysCreateRequestJson = Schema.Struct({ "name": Schema.String }) +export type AdminApiKeysList400 = ErrorResponse +export const AdminApiKeysList400 = ErrorResponse +export type AdminApiKeysList403 = PermissionErrorResponse +export const AdminApiKeysList403 = PermissionErrorResponse +export type AdminApiKeysCreateRequestJson = { readonly "name": string; readonly "expires_in_seconds"?: number } +export const AdminApiKeysCreateRequestJson = Schema.Struct({ + "name": Schema.String, + "expires_in_seconds": Schema.optionalKey( + Schema.Number.annotate({ + "description": "The number of seconds until the API key expires. Omit this field for a key that does not expire." + }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(31536000).annotate({ "expected": "a value less than or equal to 31536000" })) + ) +}) export type AdminApiKeysCreate200 = AdminApiKeyCreateResponse export const AdminApiKeysCreate200 = AdminApiKeyCreateResponse +export type AdminApiKeysCreate400 = ErrorResponse +export const AdminApiKeysCreate400 = ErrorResponse +export type AdminApiKeysCreate403 = PermissionErrorResponse +export const AdminApiKeysCreate403 = PermissionErrorResponse +export type AdminApiKeysCreate404 = ErrorResponse +export const AdminApiKeysCreate404 = ErrorResponse export type AdminApiKeysGet200 = AdminApiKey export const AdminApiKeysGet200 = AdminApiKey +export type AdminApiKeysGet403 = PermissionErrorResponse +export const AdminApiKeysGet403 = PermissionErrorResponse +export type AdminApiKeysGet404 = ErrorResponse +export const AdminApiKeysGet404 = ErrorResponse export type AdminApiKeysDelete200 = { readonly "id": string readonly "object": "organization.admin_api_key.deleted" @@ -29192,6 +47142,10 @@ export const AdminApiKeysDelete200 = Schema.Struct({ "object": Schema.Literal("organization.admin_api_key.deleted"), "deleted": Schema.Boolean }) +export type AdminApiKeysDelete403 = PermissionErrorResponse +export const AdminApiKeysDelete403 = PermissionErrorResponse +export type AdminApiKeysDelete404 = ErrorResponse +export const AdminApiKeysDelete404 = ErrorResponse export type ListAuditLogsParams = { readonly "effective_at[gt]"?: number readonly "effective_at[gte]"?: number @@ -29202,6 +47156,7 @@ export type ListAuditLogsParams = { readonly "actor_ids[]"?: ReadonlyArray readonly "actor_emails[]"?: ReadonlyArray readonly "resource_ids[]"?: ReadonlyArray + readonly "tenant_only"?: boolean readonly "limit"?: number readonly "after"?: string readonly "before"?: string @@ -29210,92 +47165,183 @@ export const ListAuditLogsParams = Schema.Struct({ "effective_at[gt]": Schema.optionalKey( Schema.Number.annotate({ "description": "Return only events whose `effective_at` (Unix seconds) is greater than this value." - }).check(Schema.isInt()) + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), "effective_at[gte]": Schema.optionalKey( Schema.Number.annotate({ "description": "Return only events whose `effective_at` (Unix seconds) is greater than or equal to this value." - }).check(Schema.isInt()) + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), "effective_at[lt]": Schema.optionalKey( Schema.Number.annotate({ "description": "Return only events whose `effective_at` (Unix seconds) is less than this value." - }).check(Schema.isInt()) + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), "effective_at[lte]": Schema.optionalKey( Schema.Number.annotate({ "description": "Return only events whose `effective_at` (Unix seconds) is less than or equal to this value." - }).check(Schema.isInt()) + }).check(Schema.isInt().annotate({ "expected": "an integer" })) ), "project_ids[]": Schema.optionalKey(Schema.Array(Schema.String)), "event_types[]": Schema.optionalKey(Schema.Array(AuditLogEventType)), "actor_ids[]": Schema.optionalKey(Schema.Array(Schema.String)), "actor_emails[]": Schema.optionalKey(Schema.Array(Schema.String)), "resource_ids[]": Schema.optionalKey(Schema.Array(Schema.String)), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "tenant_only": Schema.optionalKey(Schema.Boolean), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String) }) export type ListAuditLogs200 = ListAuditLogsResponse export const ListAuditLogs200 = ListAuditLogsResponse +export type ListAuditLogs400 = ErrorResponse +export const ListAuditLogs400 = ErrorResponse +export type ListAuditLogs404 = ErrorResponse +export const ListAuditLogs404 = ErrorResponse +export type ListAuditLogs429 = ErrorResponse +export const ListAuditLogs429 = ErrorResponse export type ListOrganizationCertificatesParams = { readonly "limit"?: number readonly "after"?: string readonly "order"?: "asc" | "desc" } export const ListOrganizationCertificatesParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListOrganizationCertificates200 = ListCertificatesResponse export const ListOrganizationCertificates200 = ListCertificatesResponse +export type ListOrganizationCertificates400 = ErrorResponse +export const ListOrganizationCertificates400 = ErrorResponse +export type ListOrganizationCertificates403 = PermissionErrorResponse +export const ListOrganizationCertificates403 = PermissionErrorResponse +export type ListOrganizationCertificates429 = ErrorResponse +export const ListOrganizationCertificates429 = ErrorResponse export type UploadCertificateRequestJson = UploadCertificateRequest export const UploadCertificateRequestJson = UploadCertificateRequest export type UploadCertificate200 = Certificate export const UploadCertificate200 = Certificate +export type UploadCertificate400 = ErrorResponse +export const UploadCertificate400 = ErrorResponse +export type UploadCertificate403 = PermissionErrorResponse +export const UploadCertificate403 = PermissionErrorResponse +export type UploadCertificate429 = ErrorResponse +export const UploadCertificate429 = ErrorResponse export type ActivateOrganizationCertificatesRequestJson = ToggleCertificatesRequest export const ActivateOrganizationCertificatesRequestJson = ToggleCertificatesRequest export type ActivateOrganizationCertificates200 = OrganizationCertificateActivationResponse export const ActivateOrganizationCertificates200 = OrganizationCertificateActivationResponse +export type ActivateOrganizationCertificates400 = ErrorResponse +export const ActivateOrganizationCertificates400 = ErrorResponse +export type ActivateOrganizationCertificates403 = PermissionErrorResponse +export const ActivateOrganizationCertificates403 = PermissionErrorResponse +export type ActivateOrganizationCertificates404 = ErrorResponse +export const ActivateOrganizationCertificates404 = ErrorResponse +export type ActivateOrganizationCertificates429 = ErrorResponse +export const ActivateOrganizationCertificates429 = ErrorResponse +export type ActivateOrganizationCertificates500 = ErrorResponse +export const ActivateOrganizationCertificates500 = ErrorResponse export type DeactivateOrganizationCertificatesRequestJson = ToggleCertificatesRequest export const DeactivateOrganizationCertificatesRequestJson = ToggleCertificatesRequest export type DeactivateOrganizationCertificates200 = OrganizationCertificateDeactivationResponse export const DeactivateOrganizationCertificates200 = OrganizationCertificateDeactivationResponse +export type DeactivateOrganizationCertificates400 = ErrorResponse +export const DeactivateOrganizationCertificates400 = ErrorResponse +export type DeactivateOrganizationCertificates403 = PermissionErrorResponse +export const DeactivateOrganizationCertificates403 = PermissionErrorResponse +export type DeactivateOrganizationCertificates404 = ErrorResponse +export const DeactivateOrganizationCertificates404 = ErrorResponse +export type DeactivateOrganizationCertificates429 = ErrorResponse +export const DeactivateOrganizationCertificates429 = ErrorResponse +export type DeactivateOrganizationCertificates500 = ErrorResponse +export const DeactivateOrganizationCertificates500 = ErrorResponse export type GetCertificateParams = { readonly "include"?: ReadonlyArray<"content"> } export const GetCertificateParams = Schema.Struct({ "include": Schema.optionalKey(Schema.Array(Schema.Literal("content"))) }) export type GetCertificate200 = Certificate export const GetCertificate200 = Certificate +export type GetCertificate400 = ErrorResponse +export const GetCertificate400 = ErrorResponse +export type GetCertificate403 = PermissionErrorResponse +export const GetCertificate403 = PermissionErrorResponse +export type GetCertificate404 = ErrorResponse +export const GetCertificate404 = ErrorResponse +export type GetCertificate429 = ErrorResponse +export const GetCertificate429 = ErrorResponse export type ModifyCertificateRequestJson = ModifyCertificateRequest export const ModifyCertificateRequestJson = ModifyCertificateRequest export type ModifyCertificate200 = Certificate export const ModifyCertificate200 = Certificate +export type ModifyCertificate400 = ErrorResponse +export const ModifyCertificate400 = ErrorResponse +export type ModifyCertificate403 = PermissionErrorResponse +export const ModifyCertificate403 = PermissionErrorResponse +export type ModifyCertificate404 = ErrorResponse +export const ModifyCertificate404 = ErrorResponse +export type ModifyCertificate429 = ErrorResponse +export const ModifyCertificate429 = ErrorResponse +export type ModifyCertificate500 = ErrorResponse +export const ModifyCertificate500 = ErrorResponse export type DeleteCertificate200 = DeleteCertificateResponse export const DeleteCertificate200 = DeleteCertificateResponse +export type DeleteCertificate400 = ErrorResponse +export const DeleteCertificate400 = ErrorResponse +export type DeleteCertificate403 = PermissionErrorResponse +export const DeleteCertificate403 = PermissionErrorResponse +export type DeleteCertificate404 = ErrorResponse +export const DeleteCertificate404 = ErrorResponse +export type DeleteCertificate429 = ErrorResponse +export const DeleteCertificate429 = ErrorResponse export type UsageCostsParams = { readonly "start_time": number readonly "end_time"?: number readonly "bucket_width"?: "1d" readonly "project_ids"?: ReadonlyArray readonly "api_key_ids"?: ReadonlyArray - readonly "group_by"?: ReadonlyArray<"project_id" | "line_item" | "api_key_id"> + readonly "line_items"?: ReadonlyArray + readonly "group_by"?: ReadonlyArray<"project_id" | "user_id" | "line_item" | "api_key_id" | "api_source"> readonly "limit"?: number readonly "page"?: string } export const UsageCostsParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literal("1d")), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "api_key_ids": Schema.optionalKey(Schema.Array(Schema.String)), - "group_by": Schema.optionalKey(Schema.Array(Schema.Literals(["project_id", "line_item", "api_key_id"]))), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "line_items": Schema.optionalKey(Schema.Array(Schema.String)), + "group_by": Schema.optionalKey( + Schema.Array(Schema.Literals(["project_id", "user_id", "line_item", "api_key_id", "api_source"])) + ), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageCosts200 = UsageResponse export const UsageCosts200 = UsageResponse +export type UsageCosts400 = ErrorResponse +export const UsageCosts400 = ErrorResponse +export type UsageCosts403 = PermissionErrorResponse +export const UsageCosts403 = PermissionErrorResponse +export type UsageCosts429 = ErrorResponse +export const UsageCosts429 = ErrorResponse +export type RetrieveOrganizationDataRetention200 = OrganizationDataRetention +export const RetrieveOrganizationDataRetention200 = OrganizationDataRetention +export type RetrieveOrganizationDataRetention403 = PermissionErrorResponse +export const RetrieveOrganizationDataRetention403 = PermissionErrorResponse +export type RetrieveOrganizationDataRetention404 = ErrorResponse +export const RetrieveOrganizationDataRetention404 = ErrorResponse +export type UpdateOrganizationDataRetentionRequestJson = UpdateOrganizationDataRetentionBody +export const UpdateOrganizationDataRetentionRequestJson = UpdateOrganizationDataRetentionBody +export type UpdateOrganizationDataRetention200 = OrganizationDataRetention +export const UpdateOrganizationDataRetention200 = OrganizationDataRetention +export type UpdateOrganizationDataRetention400 = ErrorResponse +export const UpdateOrganizationDataRetention400 = ErrorResponse +export type UpdateOrganizationDataRetention403 = PermissionErrorResponse +export const UpdateOrganizationDataRetention403 = PermissionErrorResponse +export type UpdateOrganizationDataRetention404 = ErrorResponse +export const UpdateOrganizationDataRetention404 = ErrorResponse export type ListGroupsParams = { readonly "limit"?: number readonly "after"?: string @@ -29303,23 +47349,75 @@ export type ListGroupsParams = { } export const ListGroupsParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1000)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1000).annotate({ "expected": "a value less than or equal to 1000" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListGroups200 = GroupListResource export const ListGroups200 = GroupListResource +export type ListGroups400 = ErrorResponse +export const ListGroups400 = ErrorResponse +export type ListGroups403 = PermissionErrorResponse +export const ListGroups403 = PermissionErrorResponse +export type ListGroups404 = ErrorResponse +export const ListGroups404 = ErrorResponse +export type ListGroups429 = ErrorResponse +export const ListGroups429 = ErrorResponse export type CreateGroupRequestJson = CreateGroupBody export const CreateGroupRequestJson = CreateGroupBody export type CreateGroup200 = GroupResponse export const CreateGroup200 = GroupResponse +export type CreateGroup400 = ErrorResponse +export const CreateGroup400 = ErrorResponse +export type CreateGroup403 = PermissionErrorResponse +export const CreateGroup403 = PermissionErrorResponse +export type CreateGroup404 = ErrorResponse +export const CreateGroup404 = ErrorResponse +export type CreateGroup422 = ErrorResponse +export const CreateGroup422 = ErrorResponse +export type CreateGroup429 = ErrorResponse +export const CreateGroup429 = ErrorResponse +export type CreateGroup500 = ErrorResponse +export const CreateGroup500 = ErrorResponse +export type RetrieveGroup200 = GroupResponse +export const RetrieveGroup200 = GroupResponse +export type RetrieveGroup400 = ErrorResponse +export const RetrieveGroup400 = ErrorResponse +export type RetrieveGroup403 = PermissionErrorResponse +export const RetrieveGroup403 = PermissionErrorResponse +export type RetrieveGroup404 = ErrorResponse +export const RetrieveGroup404 = ErrorResponse +export type RetrieveGroup429 = ErrorResponse +export const RetrieveGroup429 = ErrorResponse +export type RetrieveGroup500 = ErrorResponse +export const RetrieveGroup500 = ErrorResponse export type UpdateGroupRequestJson = UpdateGroupBody export const UpdateGroupRequestJson = UpdateGroupBody export type UpdateGroup200 = GroupResourceWithSuccess export const UpdateGroup200 = GroupResourceWithSuccess +export type UpdateGroup400 = ErrorResponse +export const UpdateGroup400 = ErrorResponse +export type UpdateGroup403 = PermissionErrorResponse +export const UpdateGroup403 = PermissionErrorResponse +export type UpdateGroup404 = ErrorResponse +export const UpdateGroup404 = ErrorResponse +export type UpdateGroup429 = ErrorResponse +export const UpdateGroup429 = ErrorResponse +export type UpdateGroup500 = ErrorResponse +export const UpdateGroup500 = ErrorResponse export type DeleteGroup200 = GroupDeletedResource export const DeleteGroup200 = GroupDeletedResource +export type DeleteGroup400 = ErrorResponse +export const DeleteGroup400 = ErrorResponse +export type DeleteGroup403 = PermissionErrorResponse +export const DeleteGroup403 = PermissionErrorResponse +export type DeleteGroup404 = ErrorResponse +export const DeleteGroup404 = ErrorResponse +export type DeleteGroup429 = ErrorResponse +export const DeleteGroup429 = ErrorResponse export type ListGroupRoleAssignmentsParams = { readonly "limit"?: number readonly "after"?: string @@ -29327,19 +47425,55 @@ export type ListGroupRoleAssignmentsParams = { } export const ListGroupRoleAssignmentsParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1000)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1000).annotate({ "expected": "a value less than or equal to 1000" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListGroupRoleAssignments200 = RoleListResource export const ListGroupRoleAssignments200 = RoleListResource +export type ListGroupRoleAssignments400 = ErrorResponse +export const ListGroupRoleAssignments400 = ErrorResponse +export type ListGroupRoleAssignments403 = PermissionErrorResponse +export const ListGroupRoleAssignments403 = PermissionErrorResponse +export type ListGroupRoleAssignments404 = ErrorResponse +export const ListGroupRoleAssignments404 = ErrorResponse +export type ListGroupRoleAssignments429 = ErrorResponse +export const ListGroupRoleAssignments429 = ErrorResponse export type AssignGroupRoleRequestJson = PublicAssignOrganizationGroupRoleBody export const AssignGroupRoleRequestJson = PublicAssignOrganizationGroupRoleBody export type AssignGroupRole200 = GroupRoleAssignment export const AssignGroupRole200 = GroupRoleAssignment +export type AssignGroupRole400 = ErrorResponse +export const AssignGroupRole400 = ErrorResponse +export type AssignGroupRole403 = PermissionErrorResponse +export const AssignGroupRole403 = PermissionErrorResponse +export type AssignGroupRole404 = ErrorResponse +export const AssignGroupRole404 = ErrorResponse +export type AssignGroupRole429 = ErrorResponse +export const AssignGroupRole429 = ErrorResponse +export type RetrieveGroupRole200 = AssignedRoleDetails +export const RetrieveGroupRole200 = AssignedRoleDetails +export type RetrieveGroupRole400 = ErrorResponse +export const RetrieveGroupRole400 = ErrorResponse +export type RetrieveGroupRole403 = PermissionErrorResponse +export const RetrieveGroupRole403 = PermissionErrorResponse +export type RetrieveGroupRole404 = ErrorResponse +export const RetrieveGroupRole404 = ErrorResponse +export type RetrieveGroupRole429 = ErrorResponse +export const RetrieveGroupRole429 = ErrorResponse export type UnassignGroupRole200 = DeletedRoleAssignmentResource export const UnassignGroupRole200 = DeletedRoleAssignmentResource +export type UnassignGroupRole400 = ErrorResponse +export const UnassignGroupRole400 = ErrorResponse +export type UnassignGroupRole403 = PermissionErrorResponse +export const UnassignGroupRole403 = PermissionErrorResponse +export type UnassignGroupRole404 = ErrorResponse +export const UnassignGroupRole404 = ErrorResponse +export type UnassignGroupRole429 = ErrorResponse +export const UnassignGroupRole429 = ErrorResponse export type ListGroupUsersParams = { readonly "limit"?: number readonly "after"?: string @@ -29347,93 +47481,276 @@ export type ListGroupUsersParams = { } export const ListGroupUsersParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1000)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1000).annotate({ "expected": "a value less than or equal to 1000" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListGroupUsers200 = UserListResource export const ListGroupUsers200 = UserListResource +export type ListGroupUsers400 = ErrorResponse +export const ListGroupUsers400 = ErrorResponse +export type ListGroupUsers403 = PermissionErrorResponse +export const ListGroupUsers403 = PermissionErrorResponse +export type ListGroupUsers404 = ErrorResponse +export const ListGroupUsers404 = ErrorResponse +export type ListGroupUsers429 = ErrorResponse +export const ListGroupUsers429 = ErrorResponse +export type ListGroupUsers502 = ErrorResponse +export const ListGroupUsers502 = ErrorResponse export type AddGroupUserRequestJson = CreateGroupUserBody export const AddGroupUserRequestJson = CreateGroupUserBody export type AddGroupUser200 = GroupUserAssignment export const AddGroupUser200 = GroupUserAssignment +export type AddGroupUser400 = ErrorResponse +export const AddGroupUser400 = ErrorResponse +export type AddGroupUser403 = PermissionErrorResponse +export const AddGroupUser403 = PermissionErrorResponse +export type AddGroupUser404 = ErrorResponse +export const AddGroupUser404 = ErrorResponse +export type AddGroupUser409 = ErrorResponse +export const AddGroupUser409 = ErrorResponse +export type AddGroupUser429 = ErrorResponse +export const AddGroupUser429 = ErrorResponse +export type RetrieveGroupUser200 = GroupMemberUser +export const RetrieveGroupUser200 = GroupMemberUser +export type RetrieveGroupUser400 = ErrorResponse +export const RetrieveGroupUser400 = ErrorResponse +export type RetrieveGroupUser403 = PermissionErrorResponse +export const RetrieveGroupUser403 = PermissionErrorResponse +export type RetrieveGroupUser404 = ErrorResponse +export const RetrieveGroupUser404 = ErrorResponse +export type RetrieveGroupUser429 = ErrorResponse +export const RetrieveGroupUser429 = ErrorResponse export type RemoveGroupUser200 = GroupUserDeletedResource export const RemoveGroupUser200 = GroupUserDeletedResource +export type RemoveGroupUser400 = ErrorResponse +export const RemoveGroupUser400 = ErrorResponse +export type RemoveGroupUser403 = PermissionErrorResponse +export const RemoveGroupUser403 = PermissionErrorResponse +export type RemoveGroupUser404 = ErrorResponse +export const RemoveGroupUser404 = ErrorResponse +export type RemoveGroupUser409 = ErrorResponse +export const RemoveGroupUser409 = ErrorResponse +export type RemoveGroupUser429 = ErrorResponse +export const RemoveGroupUser429 = ErrorResponse export type ListInvitesParams = { readonly "limit"?: number; readonly "after"?: string } export const ListInvitesParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String) }) export type ListInvites200 = InviteListResponse export const ListInvites200 = InviteListResponse +export type ListInvites400 = ErrorResponse +export const ListInvites400 = ErrorResponse +export type ListInvites403 = PermissionErrorResponse +export const ListInvites403 = PermissionErrorResponse +export type ListInvites404 = ErrorResponse +export const ListInvites404 = ErrorResponse +export type ListInvites429 = ErrorResponse +export const ListInvites429 = ErrorResponse export type InviteUserRequestJson = InviteRequest export const InviteUserRequestJson = InviteRequest export type InviteUser200 = Invite export const InviteUser200 = Invite +export type InviteUser201 = Invite +export const InviteUser201 = Invite +export type InviteUser400 = ErrorResponse +export const InviteUser400 = ErrorResponse +export type InviteUser403 = PermissionErrorResponse +export const InviteUser403 = PermissionErrorResponse +export type InviteUser429 = ErrorResponse +export const InviteUser429 = ErrorResponse export type RetrieveInvite200 = Invite export const RetrieveInvite200 = Invite +export type RetrieveInvite400 = ErrorResponse +export const RetrieveInvite400 = ErrorResponse +export type RetrieveInvite403 = PermissionErrorResponse +export const RetrieveInvite403 = PermissionErrorResponse +export type RetrieveInvite404 = ErrorResponse +export const RetrieveInvite404 = ErrorResponse +export type RetrieveInvite429 = ErrorResponse +export const RetrieveInvite429 = ErrorResponse +export type RetrieveInvite500 = ErrorResponse +export const RetrieveInvite500 = ErrorResponse export type DeleteInvite200 = InviteDeleteResponse export const DeleteInvite200 = InviteDeleteResponse +export type DeleteInvite400 = ErrorResponse +export const DeleteInvite400 = ErrorResponse +export type DeleteInvite403 = PermissionErrorResponse +export const DeleteInvite403 = PermissionErrorResponse +export type DeleteInvite404 = ErrorResponse +export const DeleteInvite404 = ErrorResponse +export type DeleteInvite429 = ErrorResponse +export const DeleteInvite429 = ErrorResponse export type ListProjectsParams = { readonly "limit"?: number readonly "after"?: string readonly "include_archived"?: boolean } export const ListProjectsParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String), "include_archived": Schema.optionalKey(Schema.Boolean) }) export type ListProjects200 = ProjectListResponse export const ListProjects200 = ProjectListResponse +export type ListProjects400 = ErrorResponse +export const ListProjects400 = ErrorResponse +export type ListProjects403 = PermissionErrorResponse +export const ListProjects403 = PermissionErrorResponse +export type ListProjects404 = ErrorResponse +export const ListProjects404 = ErrorResponse +export type ListProjects429 = ErrorResponse +export const ListProjects429 = ErrorResponse export type CreateProjectRequestJson = ProjectCreateRequest export const CreateProjectRequestJson = ProjectCreateRequest export type CreateProject200 = Project export const CreateProject200 = Project +export type CreateProject201 = Project +export const CreateProject201 = Project +export type CreateProject400 = ErrorResponse +export const CreateProject400 = ErrorResponse +export type CreateProject403 = PermissionErrorResponse +export const CreateProject403 = PermissionErrorResponse +export type CreateProject429 = ErrorResponse +export const CreateProject429 = ErrorResponse export type RetrieveProject200 = Project export const RetrieveProject200 = Project +export type RetrieveProject403 = PermissionErrorResponse +export const RetrieveProject403 = PermissionErrorResponse +export type RetrieveProject404 = ErrorResponse +export const RetrieveProject404 = ErrorResponse +export type RetrieveProject429 = ErrorResponse +export const RetrieveProject429 = ErrorResponse export type ModifyProjectRequestJson = ProjectUpdateRequest export const ModifyProjectRequestJson = ProjectUpdateRequest export type ModifyProject200 = Project export const ModifyProject200 = Project export type ModifyProject400 = ErrorResponse export const ModifyProject400 = ErrorResponse -export type ListProjectApiKeysParams = { readonly "limit"?: number; readonly "after"?: string } +export type ModifyProject403 = PermissionErrorResponse +export const ModifyProject403 = PermissionErrorResponse +export type ModifyProject404 = ErrorResponse +export const ModifyProject404 = ErrorResponse +export type ModifyProject429 = ErrorResponse +export const ModifyProject429 = ErrorResponse +export type ListProjectApiKeysParams = { + readonly "limit"?: number + readonly "after"?: string + readonly "owner_project_access"?: "active" | "inactive" | "any" +} export const ListProjectApiKeysParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), - "after": Schema.optionalKey(Schema.String) + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), + "after": Schema.optionalKey(Schema.String), + "owner_project_access": Schema.optionalKey(Schema.Literals(["active", "inactive", "any"])) }) export type ListProjectApiKeys200 = ProjectApiKeyListResponse export const ListProjectApiKeys200 = ProjectApiKeyListResponse +export type ListProjectApiKeys400 = ErrorResponse +export const ListProjectApiKeys400 = ErrorResponse +export type ListProjectApiKeys403 = PermissionErrorResponse +export const ListProjectApiKeys403 = PermissionErrorResponse +export type ListProjectApiKeys404 = ErrorResponse +export const ListProjectApiKeys404 = ErrorResponse +export type ListProjectApiKeys429 = ErrorResponse +export const ListProjectApiKeys429 = ErrorResponse export type RetrieveProjectApiKey200 = ProjectApiKey export const RetrieveProjectApiKey200 = ProjectApiKey +export type RetrieveProjectApiKey400 = ErrorResponse +export const RetrieveProjectApiKey400 = ErrorResponse +export type RetrieveProjectApiKey403 = PermissionErrorResponse +export const RetrieveProjectApiKey403 = PermissionErrorResponse +export type RetrieveProjectApiKey404 = ErrorResponse +export const RetrieveProjectApiKey404 = ErrorResponse +export type RetrieveProjectApiKey429 = ErrorResponse +export const RetrieveProjectApiKey429 = ErrorResponse export type DeleteProjectApiKey200 = ProjectApiKeyDeleteResponse export const DeleteProjectApiKey200 = ProjectApiKeyDeleteResponse export type DeleteProjectApiKey400 = ErrorResponse export const DeleteProjectApiKey400 = ErrorResponse +export type DeleteProjectApiKey403 = PermissionErrorResponse +export const DeleteProjectApiKey403 = PermissionErrorResponse +export type DeleteProjectApiKey404 = ErrorResponse +export const DeleteProjectApiKey404 = ErrorResponse +export type DeleteProjectApiKey429 = ErrorResponse +export const DeleteProjectApiKey429 = ErrorResponse export type ArchiveProject200 = Project export const ArchiveProject200 = Project +export type ArchiveProject400 = ErrorResponse +export const ArchiveProject400 = ErrorResponse +export type ArchiveProject403 = PermissionErrorResponse +export const ArchiveProject403 = PermissionErrorResponse +export type ArchiveProject404 = ErrorResponse +export const ArchiveProject404 = ErrorResponse +export type ArchiveProject429 = ErrorResponse +export const ArchiveProject429 = ErrorResponse export type ListProjectCertificatesParams = { readonly "limit"?: number readonly "after"?: string readonly "order"?: "asc" | "desc" } export const ListProjectCertificatesParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListProjectCertificates200 = ListProjectCertificatesResponse export const ListProjectCertificates200 = ListProjectCertificatesResponse +export type ListProjectCertificates400 = ErrorResponse +export const ListProjectCertificates400 = ErrorResponse +export type ListProjectCertificates403 = PermissionErrorResponse +export const ListProjectCertificates403 = PermissionErrorResponse +export type ListProjectCertificates429 = ErrorResponse +export const ListProjectCertificates429 = ErrorResponse export type ActivateProjectCertificatesRequestJson = ToggleCertificatesRequest export const ActivateProjectCertificatesRequestJson = ToggleCertificatesRequest export type ActivateProjectCertificates200 = OrganizationProjectCertificateActivationResponse export const ActivateProjectCertificates200 = OrganizationProjectCertificateActivationResponse +export type ActivateProjectCertificates400 = ErrorResponse +export const ActivateProjectCertificates400 = ErrorResponse +export type ActivateProjectCertificates403 = PermissionErrorResponse +export const ActivateProjectCertificates403 = PermissionErrorResponse +export type ActivateProjectCertificates404 = ErrorResponse +export const ActivateProjectCertificates404 = ErrorResponse +export type ActivateProjectCertificates429 = ErrorResponse +export const ActivateProjectCertificates429 = ErrorResponse +export type ActivateProjectCertificates500 = ErrorResponse +export const ActivateProjectCertificates500 = ErrorResponse export type DeactivateProjectCertificatesRequestJson = ToggleCertificatesRequest export const DeactivateProjectCertificatesRequestJson = ToggleCertificatesRequest export type DeactivateProjectCertificates200 = OrganizationProjectCertificateDeactivationResponse export const DeactivateProjectCertificates200 = OrganizationProjectCertificateDeactivationResponse +export type DeactivateProjectCertificates400 = ErrorResponse +export const DeactivateProjectCertificates400 = ErrorResponse +export type DeactivateProjectCertificates403 = PermissionErrorResponse +export const DeactivateProjectCertificates403 = PermissionErrorResponse +export type DeactivateProjectCertificates404 = ErrorResponse +export const DeactivateProjectCertificates404 = ErrorResponse +export type DeactivateProjectCertificates429 = ErrorResponse +export const DeactivateProjectCertificates429 = ErrorResponse +export type DeactivateProjectCertificates500 = ErrorResponse +export const DeactivateProjectCertificates500 = ErrorResponse +export type RetrieveProjectDataRetention200 = ProjectDataRetention +export const RetrieveProjectDataRetention200 = ProjectDataRetention +export type RetrieveProjectDataRetention400 = ErrorResponse +export const RetrieveProjectDataRetention400 = ErrorResponse +export type RetrieveProjectDataRetention403 = PermissionErrorResponse +export const RetrieveProjectDataRetention403 = PermissionErrorResponse +export type RetrieveProjectDataRetention404 = ErrorResponse +export const RetrieveProjectDataRetention404 = ErrorResponse +export type UpdateProjectDataRetentionRequestJson = UpdateProjectDataRetentionBody +export const UpdateProjectDataRetentionRequestJson = UpdateProjectDataRetentionBody +export type UpdateProjectDataRetention200 = ProjectDataRetention +export const UpdateProjectDataRetention200 = ProjectDataRetention +export type UpdateProjectDataRetention400 = ErrorResponse +export const UpdateProjectDataRetention400 = ErrorResponse +export type UpdateProjectDataRetention403 = PermissionErrorResponse +export const UpdateProjectDataRetention403 = PermissionErrorResponse +export type UpdateProjectDataRetention404 = ErrorResponse +export const UpdateProjectDataRetention404 = ErrorResponse export type ListProjectGroupsParams = { readonly "limit"?: number readonly "after"?: string @@ -29441,97 +47758,329 @@ export type ListProjectGroupsParams = { } export const ListProjectGroupsParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListProjectGroups200 = ProjectGroupListResource export const ListProjectGroups200 = ProjectGroupListResource +export type ListProjectGroups400 = ErrorResponse +export const ListProjectGroups400 = ErrorResponse +export type ListProjectGroups403 = PermissionErrorResponse +export const ListProjectGroups403 = PermissionErrorResponse +export type ListProjectGroups404 = ErrorResponse +export const ListProjectGroups404 = ErrorResponse +export type ListProjectGroups429 = ErrorResponse +export const ListProjectGroups429 = ErrorResponse export type AddProjectGroupRequestJson = InviteProjectGroupBody export const AddProjectGroupRequestJson = InviteProjectGroupBody export type AddProjectGroup200 = ProjectGroup export const AddProjectGroup200 = ProjectGroup +export type AddProjectGroup400 = ErrorResponse +export const AddProjectGroup400 = ErrorResponse +export type AddProjectGroup403 = PermissionErrorResponse +export const AddProjectGroup403 = PermissionErrorResponse +export type AddProjectGroup404 = ErrorResponse +export const AddProjectGroup404 = ErrorResponse +export type AddProjectGroup429 = ErrorResponse +export const AddProjectGroup429 = ErrorResponse +export type AddProjectGroup500 = ErrorResponse +export const AddProjectGroup500 = ErrorResponse +export type RetrieveProjectGroupParams = { readonly "group_type"?: "group" | "tenant_group" } +export const RetrieveProjectGroupParams = Schema.Struct({ + "group_type": Schema.optionalKey(Schema.Literals(["group", "tenant_group"])) +}) +export type RetrieveProjectGroup200 = ProjectGroup +export const RetrieveProjectGroup200 = ProjectGroup +export type RetrieveProjectGroup400 = ErrorResponse +export const RetrieveProjectGroup400 = ErrorResponse +export type RetrieveProjectGroup403 = PermissionErrorResponse +export const RetrieveProjectGroup403 = PermissionErrorResponse +export type RetrieveProjectGroup404 = ErrorResponse +export const RetrieveProjectGroup404 = ErrorResponse +export type RetrieveProjectGroup429 = ErrorResponse +export const RetrieveProjectGroup429 = ErrorResponse export type RemoveProjectGroup200 = ProjectGroupDeletedResource export const RemoveProjectGroup200 = ProjectGroupDeletedResource +export type RemoveProjectGroup400 = ErrorResponse +export const RemoveProjectGroup400 = ErrorResponse +export type RemoveProjectGroup403 = PermissionErrorResponse +export const RemoveProjectGroup403 = PermissionErrorResponse +export type RemoveProjectGroup404 = ErrorResponse +export const RemoveProjectGroup404 = ErrorResponse +export type RemoveProjectGroup429 = ErrorResponse +export const RemoveProjectGroup429 = ErrorResponse export type RetrieveProjectHostedToolPermissions200 = ProjectHostedToolPermissions export const RetrieveProjectHostedToolPermissions200 = ProjectHostedToolPermissions +export type RetrieveProjectHostedToolPermissions400 = ErrorResponse +export const RetrieveProjectHostedToolPermissions400 = ErrorResponse +export type RetrieveProjectHostedToolPermissions403 = PermissionErrorResponse +export const RetrieveProjectHostedToolPermissions403 = PermissionErrorResponse +export type RetrieveProjectHostedToolPermissions404 = ErrorResponse +export const RetrieveProjectHostedToolPermissions404 = ErrorResponse +export type RetrieveProjectHostedToolPermissions429 = ErrorResponse +export const RetrieveProjectHostedToolPermissions429 = ErrorResponse export type UpdateProjectHostedToolPermissionsRequestJson = ProjectHostedToolPermissionsUpdateRequest export const UpdateProjectHostedToolPermissionsRequestJson = ProjectHostedToolPermissionsUpdateRequest export type UpdateProjectHostedToolPermissions200 = ProjectHostedToolPermissions export const UpdateProjectHostedToolPermissions200 = ProjectHostedToolPermissions +export type UpdateProjectHostedToolPermissions400 = ErrorResponse +export const UpdateProjectHostedToolPermissions400 = ErrorResponse +export type UpdateProjectHostedToolPermissions403 = PermissionErrorResponse +export const UpdateProjectHostedToolPermissions403 = PermissionErrorResponse +export type UpdateProjectHostedToolPermissions404 = ErrorResponse +export const UpdateProjectHostedToolPermissions404 = ErrorResponse +export type UpdateProjectHostedToolPermissions409 = ErrorResponse +export const UpdateProjectHostedToolPermissions409 = ErrorResponse +export type UpdateProjectHostedToolPermissions429 = ErrorResponse +export const UpdateProjectHostedToolPermissions429 = ErrorResponse export type RetrieveProjectModelPermissions200 = ProjectModelPermissions export const RetrieveProjectModelPermissions200 = ProjectModelPermissions +export type RetrieveProjectModelPermissions400 = ErrorResponse +export const RetrieveProjectModelPermissions400 = ErrorResponse +export type RetrieveProjectModelPermissions403 = PermissionErrorResponse +export const RetrieveProjectModelPermissions403 = PermissionErrorResponse +export type RetrieveProjectModelPermissions404 = ErrorResponse +export const RetrieveProjectModelPermissions404 = ErrorResponse +export type RetrieveProjectModelPermissions429 = ErrorResponse +export const RetrieveProjectModelPermissions429 = ErrorResponse export type UpdateProjectModelPermissionsRequestJson = ProjectModelPermissionsUpdateRequest export const UpdateProjectModelPermissionsRequestJson = ProjectModelPermissionsUpdateRequest export type UpdateProjectModelPermissions200 = ProjectModelPermissions export const UpdateProjectModelPermissions200 = ProjectModelPermissions +export type UpdateProjectModelPermissions400 = ErrorResponse +export const UpdateProjectModelPermissions400 = ErrorResponse +export type UpdateProjectModelPermissions403 = PermissionErrorResponse +export const UpdateProjectModelPermissions403 = PermissionErrorResponse +export type UpdateProjectModelPermissions404 = ErrorResponse +export const UpdateProjectModelPermissions404 = ErrorResponse +export type UpdateProjectModelPermissions429 = ErrorResponse +export const UpdateProjectModelPermissions429 = ErrorResponse export type DeleteProjectModelPermissions200 = ProjectModelPermissionsDeleteResponse export const DeleteProjectModelPermissions200 = ProjectModelPermissionsDeleteResponse +export type DeleteProjectModelPermissions400 = ErrorResponse +export const DeleteProjectModelPermissions400 = ErrorResponse +export type DeleteProjectModelPermissions403 = PermissionErrorResponse +export const DeleteProjectModelPermissions403 = PermissionErrorResponse +export type DeleteProjectModelPermissions404 = ErrorResponse +export const DeleteProjectModelPermissions404 = ErrorResponse +export type DeleteProjectModelPermissions429 = ErrorResponse +export const DeleteProjectModelPermissions429 = ErrorResponse export type ListProjectRateLimitsParams = { readonly "limit"?: number readonly "after"?: string readonly "before"?: string } export const ListProjectRateLimitsParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String) }) export type ListProjectRateLimits200 = ProjectRateLimitListResponse export const ListProjectRateLimits200 = ProjectRateLimitListResponse +export type ListProjectRateLimits400 = ErrorResponse +export const ListProjectRateLimits400 = ErrorResponse +export type ListProjectRateLimits403 = PermissionErrorResponse +export const ListProjectRateLimits403 = PermissionErrorResponse +export type ListProjectRateLimits404 = ErrorResponse +export const ListProjectRateLimits404 = ErrorResponse export type UpdateProjectRateLimitsRequestJson = ProjectRateLimitUpdateRequest export const UpdateProjectRateLimitsRequestJson = ProjectRateLimitUpdateRequest export type UpdateProjectRateLimits200 = ProjectRateLimit export const UpdateProjectRateLimits200 = ProjectRateLimit export type UpdateProjectRateLimits400 = ErrorResponse export const UpdateProjectRateLimits400 = ErrorResponse +export type UpdateProjectRateLimits403 = PermissionErrorResponse +export const UpdateProjectRateLimits403 = PermissionErrorResponse +export type UpdateProjectRateLimits404 = ErrorResponse +export const UpdateProjectRateLimits404 = ErrorResponse export type ListProjectServiceAccountsParams = { readonly "limit"?: number; readonly "after"?: string } export const ListProjectServiceAccountsParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String) }) export type ListProjectServiceAccounts200 = ProjectServiceAccountListResponse export const ListProjectServiceAccounts200 = ProjectServiceAccountListResponse export type ListProjectServiceAccounts400 = ErrorResponse export const ListProjectServiceAccounts400 = ErrorResponse +export type ListProjectServiceAccounts403 = PermissionErrorResponse +export const ListProjectServiceAccounts403 = PermissionErrorResponse +export type ListProjectServiceAccounts404 = ErrorResponse +export const ListProjectServiceAccounts404 = ErrorResponse +export type ListProjectServiceAccounts429 = ErrorResponse +export const ListProjectServiceAccounts429 = ErrorResponse export type CreateProjectServiceAccountRequestJson = ProjectServiceAccountCreateRequest export const CreateProjectServiceAccountRequestJson = ProjectServiceAccountCreateRequest export type CreateProjectServiceAccount200 = ProjectServiceAccountCreateResponse export const CreateProjectServiceAccount200 = ProjectServiceAccountCreateResponse +export type CreateProjectServiceAccount201 = ProjectServiceAccountCreateResponse +export const CreateProjectServiceAccount201 = ProjectServiceAccountCreateResponse export type CreateProjectServiceAccount400 = ErrorResponse export const CreateProjectServiceAccount400 = ErrorResponse +export type CreateProjectServiceAccount403 = PermissionErrorResponse +export const CreateProjectServiceAccount403 = PermissionErrorResponse +export type CreateProjectServiceAccount404 = ErrorResponse +export const CreateProjectServiceAccount404 = ErrorResponse +export type CreateProjectServiceAccount429 = ErrorResponse +export const CreateProjectServiceAccount429 = ErrorResponse export type RetrieveProjectServiceAccount200 = ProjectServiceAccount export const RetrieveProjectServiceAccount200 = ProjectServiceAccount +export type RetrieveProjectServiceAccount400 = ErrorResponse +export const RetrieveProjectServiceAccount400 = ErrorResponse +export type RetrieveProjectServiceAccount403 = PermissionErrorResponse +export const RetrieveProjectServiceAccount403 = PermissionErrorResponse +export type RetrieveProjectServiceAccount404 = ErrorResponse +export const RetrieveProjectServiceAccount404 = ErrorResponse +export type RetrieveProjectServiceAccount429 = ErrorResponse +export const RetrieveProjectServiceAccount429 = ErrorResponse +export type UpdateProjectServiceAccountRequestJson = UpdateProjectServiceAccountBody +export const UpdateProjectServiceAccountRequestJson = UpdateProjectServiceAccountBody +export type UpdateProjectServiceAccount200 = ProjectServiceAccount +export const UpdateProjectServiceAccount200 = ProjectServiceAccount +export type UpdateProjectServiceAccount400 = ErrorResponse +export const UpdateProjectServiceAccount400 = ErrorResponse +export type UpdateProjectServiceAccount403 = PermissionErrorResponse +export const UpdateProjectServiceAccount403 = PermissionErrorResponse +export type UpdateProjectServiceAccount404 = ErrorResponse +export const UpdateProjectServiceAccount404 = ErrorResponse +export type UpdateProjectServiceAccount429 = ErrorResponse +export const UpdateProjectServiceAccount429 = ErrorResponse export type DeleteProjectServiceAccount200 = ProjectServiceAccountDeleteResponse export const DeleteProjectServiceAccount200 = ProjectServiceAccountDeleteResponse +export type DeleteProjectServiceAccount400 = ErrorResponse +export const DeleteProjectServiceAccount400 = ErrorResponse +export type DeleteProjectServiceAccount403 = PermissionErrorResponse +export const DeleteProjectServiceAccount403 = PermissionErrorResponse +export type DeleteProjectServiceAccount404 = ErrorResponse +export const DeleteProjectServiceAccount404 = ErrorResponse +export type DeleteProjectServiceAccount429 = ErrorResponse +export const DeleteProjectServiceAccount429 = ErrorResponse +export type ListProjectSpendAlertsParams = { + readonly "limit"?: number + readonly "order"?: "asc" | "desc" + readonly "after"?: string + readonly "before"?: string +} +export const ListProjectSpendAlertsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), + "after": Schema.optionalKey(Schema.String), + "before": Schema.optionalKey(Schema.String) +}) +export type ListProjectSpendAlerts200 = ProjectSpendAlertListResource +export const ListProjectSpendAlerts200 = ProjectSpendAlertListResource +export type ListProjectSpendAlerts400 = ErrorResponse +export const ListProjectSpendAlerts400 = ErrorResponse +export type ListProjectSpendAlerts403 = PermissionErrorResponse +export const ListProjectSpendAlerts403 = PermissionErrorResponse +export type ListProjectSpendAlerts404 = ErrorResponse +export const ListProjectSpendAlerts404 = ErrorResponse +export type CreateProjectSpendAlertRequestJson = CreateSpendAlertBody +export const CreateProjectSpendAlertRequestJson = CreateSpendAlertBody +export type CreateProjectSpendAlert200 = ProjectSpendAlert +export const CreateProjectSpendAlert200 = ProjectSpendAlert +export type CreateProjectSpendAlert400 = ErrorResponse +export const CreateProjectSpendAlert400 = ErrorResponse +export type CreateProjectSpendAlert403 = PermissionErrorResponse +export const CreateProjectSpendAlert403 = PermissionErrorResponse +export type CreateProjectSpendAlert404 = ErrorResponse +export const CreateProjectSpendAlert404 = ErrorResponse +export type RetrieveProjectSpendAlert200 = ProjectSpendAlert +export const RetrieveProjectSpendAlert200 = ProjectSpendAlert +export type RetrieveProjectSpendAlert400 = ErrorResponse +export const RetrieveProjectSpendAlert400 = ErrorResponse +export type RetrieveProjectSpendAlert403 = PermissionErrorResponse +export const RetrieveProjectSpendAlert403 = PermissionErrorResponse +export type RetrieveProjectSpendAlert404 = ErrorResponse +export const RetrieveProjectSpendAlert404 = ErrorResponse +export type UpdateProjectSpendAlertRequestJson = CreateSpendAlertBody +export const UpdateProjectSpendAlertRequestJson = CreateSpendAlertBody +export type UpdateProjectSpendAlert200 = ProjectSpendAlert +export const UpdateProjectSpendAlert200 = ProjectSpendAlert +export type UpdateProjectSpendAlert400 = ErrorResponse +export const UpdateProjectSpendAlert400 = ErrorResponse +export type UpdateProjectSpendAlert403 = PermissionErrorResponse +export const UpdateProjectSpendAlert403 = PermissionErrorResponse +export type UpdateProjectSpendAlert404 = ErrorResponse +export const UpdateProjectSpendAlert404 = ErrorResponse +export type DeleteProjectSpendAlert200 = ProjectSpendAlertDeletedResource +export const DeleteProjectSpendAlert200 = ProjectSpendAlertDeletedResource +export type DeleteProjectSpendAlert400 = ErrorResponse +export const DeleteProjectSpendAlert400 = ErrorResponse +export type DeleteProjectSpendAlert403 = PermissionErrorResponse +export const DeleteProjectSpendAlert403 = PermissionErrorResponse +export type DeleteProjectSpendAlert404 = ErrorResponse +export const DeleteProjectSpendAlert404 = ErrorResponse export type ListProjectUsersParams = { readonly "limit"?: number; readonly "after"?: string } export const ListProjectUsersParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String) }) export type ListProjectUsers200 = ProjectUserListResponse export const ListProjectUsers200 = ProjectUserListResponse export type ListProjectUsers400 = ErrorResponse export const ListProjectUsers400 = ErrorResponse +export type ListProjectUsers403 = PermissionErrorResponse +export const ListProjectUsers403 = PermissionErrorResponse +export type ListProjectUsers404 = ErrorResponse +export const ListProjectUsers404 = ErrorResponse +export type ListProjectUsers429 = ErrorResponse +export const ListProjectUsers429 = ErrorResponse export type CreateProjectUserRequestJson = ProjectUserCreateRequest export const CreateProjectUserRequestJson = ProjectUserCreateRequest export type CreateProjectUser200 = ProjectUser export const CreateProjectUser200 = ProjectUser +export type CreateProjectUser201 = ProjectUser +export const CreateProjectUser201 = ProjectUser export type CreateProjectUser400 = ErrorResponse export const CreateProjectUser400 = ErrorResponse +export type CreateProjectUser403 = PermissionErrorResponse +export const CreateProjectUser403 = PermissionErrorResponse +export type CreateProjectUser404 = ErrorResponse +export const CreateProjectUser404 = ErrorResponse +export type CreateProjectUser409 = ErrorResponse +export const CreateProjectUser409 = ErrorResponse +export type CreateProjectUser429 = ErrorResponse +export const CreateProjectUser429 = ErrorResponse export type RetrieveProjectUser200 = ProjectUser export const RetrieveProjectUser200 = ProjectUser +export type RetrieveProjectUser400 = ErrorResponse +export const RetrieveProjectUser400 = ErrorResponse +export type RetrieveProjectUser403 = PermissionErrorResponse +export const RetrieveProjectUser403 = PermissionErrorResponse +export type RetrieveProjectUser404 = ErrorResponse +export const RetrieveProjectUser404 = ErrorResponse +export type RetrieveProjectUser429 = ErrorResponse +export const RetrieveProjectUser429 = ErrorResponse export type ModifyProjectUserRequestJson = ProjectUserUpdateRequest export const ModifyProjectUserRequestJson = ProjectUserUpdateRequest export type ModifyProjectUser200 = ProjectUser export const ModifyProjectUser200 = ProjectUser export type ModifyProjectUser400 = ErrorResponse export const ModifyProjectUser400 = ErrorResponse +export type ModifyProjectUser403 = PermissionErrorResponse +export const ModifyProjectUser403 = PermissionErrorResponse +export type ModifyProjectUser404 = ErrorResponse +export const ModifyProjectUser404 = ErrorResponse +export type ModifyProjectUser429 = ErrorResponse +export const ModifyProjectUser429 = ErrorResponse export type DeleteProjectUser200 = ProjectUserDeleteResponse export const DeleteProjectUser200 = ProjectUserDeleteResponse export type DeleteProjectUser400 = ErrorResponse export const DeleteProjectUser400 = ErrorResponse +export type DeleteProjectUser403 = PermissionErrorResponse +export const DeleteProjectUser403 = PermissionErrorResponse +export type DeleteProjectUser404 = ErrorResponse +export const DeleteProjectUser404 = ErrorResponse +export type DeleteProjectUser429 = ErrorResponse +export const DeleteProjectUser429 = ErrorResponse export type ListRolesParams = { readonly "limit"?: number readonly "after"?: string @@ -29539,23 +48088,119 @@ export type ListRolesParams = { } export const ListRolesParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1000)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1000).annotate({ "expected": "a value less than or equal to 1000" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListRoles200 = PublicRoleListResource export const ListRoles200 = PublicRoleListResource +export type ListRoles400 = ErrorResponse +export const ListRoles400 = ErrorResponse +export type ListRoles403 = PermissionErrorResponse +export const ListRoles403 = PermissionErrorResponse +export type ListRoles404 = ErrorResponse +export const ListRoles404 = ErrorResponse +export type ListRoles429 = ErrorResponse +export const ListRoles429 = ErrorResponse export type CreateRoleRequestJson = PublicCreateOrganizationRoleBody export const CreateRoleRequestJson = PublicCreateOrganizationRoleBody export type CreateRole200 = Role export const CreateRole200 = Role +export type CreateRole400 = ErrorResponse +export const CreateRole400 = ErrorResponse +export type CreateRole403 = PermissionErrorResponse +export const CreateRole403 = PermissionErrorResponse +export type CreateRole404 = ErrorResponse +export const CreateRole404 = ErrorResponse +export type CreateRole429 = ErrorResponse +export const CreateRole429 = ErrorResponse +export type RetrieveRole200 = Role +export const RetrieveRole200 = Role +export type RetrieveRole403 = PermissionErrorResponse +export const RetrieveRole403 = PermissionErrorResponse +export type RetrieveRole404 = ErrorResponse +export const RetrieveRole404 = ErrorResponse +export type RetrieveRole429 = ErrorResponse +export const RetrieveRole429 = ErrorResponse export type UpdateRoleRequestJson = PublicUpdateOrganizationRoleBody export const UpdateRoleRequestJson = PublicUpdateOrganizationRoleBody export type UpdateRole200 = Role export const UpdateRole200 = Role +export type UpdateRole400 = ErrorResponse +export const UpdateRole400 = ErrorResponse +export type UpdateRole403 = PermissionErrorResponse +export const UpdateRole403 = PermissionErrorResponse +export type UpdateRole404 = ErrorResponse +export const UpdateRole404 = ErrorResponse +export type UpdateRole429 = ErrorResponse +export const UpdateRole429 = ErrorResponse export type DeleteRole200 = RoleDeletedResource export const DeleteRole200 = RoleDeletedResource +export type DeleteRole400 = ErrorResponse +export const DeleteRole400 = ErrorResponse +export type DeleteRole403 = PermissionErrorResponse +export const DeleteRole403 = PermissionErrorResponse +export type DeleteRole404 = ErrorResponse +export const DeleteRole404 = ErrorResponse +export type DeleteRole429 = ErrorResponse +export const DeleteRole429 = ErrorResponse +export type ListOrganizationSpendAlertsParams = { + readonly "limit"?: number + readonly "order"?: "asc" | "desc" + readonly "after"?: string + readonly "before"?: string +} +export const ListOrganizationSpendAlertsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), + "after": Schema.optionalKey(Schema.String), + "before": Schema.optionalKey(Schema.String) +}) +export type ListOrganizationSpendAlerts200 = OrganizationSpendAlertListResource +export const ListOrganizationSpendAlerts200 = OrganizationSpendAlertListResource +export type ListOrganizationSpendAlerts400 = ErrorResponse +export const ListOrganizationSpendAlerts400 = ErrorResponse +export type ListOrganizationSpendAlerts403 = PermissionErrorResponse +export const ListOrganizationSpendAlerts403 = PermissionErrorResponse +export type ListOrganizationSpendAlerts404 = ErrorResponse +export const ListOrganizationSpendAlerts404 = ErrorResponse +export type CreateOrganizationSpendAlertRequestJson = CreateSpendAlertBody +export const CreateOrganizationSpendAlertRequestJson = CreateSpendAlertBody +export type CreateOrganizationSpendAlert200 = OrganizationSpendAlert +export const CreateOrganizationSpendAlert200 = OrganizationSpendAlert +export type CreateOrganizationSpendAlert400 = ErrorResponse +export const CreateOrganizationSpendAlert400 = ErrorResponse +export type CreateOrganizationSpendAlert403 = PermissionErrorResponse +export const CreateOrganizationSpendAlert403 = PermissionErrorResponse +export type RetrieveOrganizationSpendAlert200 = OrganizationSpendAlert +export const RetrieveOrganizationSpendAlert200 = OrganizationSpendAlert +export type RetrieveOrganizationSpendAlert403 = PermissionErrorResponse +export const RetrieveOrganizationSpendAlert403 = PermissionErrorResponse +export type RetrieveOrganizationSpendAlert404 = ErrorResponse +export const RetrieveOrganizationSpendAlert404 = ErrorResponse +export type UpdateOrganizationSpendAlertRequestJson = CreateSpendAlertBody +export const UpdateOrganizationSpendAlertRequestJson = CreateSpendAlertBody +export type UpdateOrganizationSpendAlert200 = OrganizationSpendAlert +export const UpdateOrganizationSpendAlert200 = OrganizationSpendAlert +export type UpdateOrganizationSpendAlert400 = ErrorResponse +export const UpdateOrganizationSpendAlert400 = ErrorResponse +export type UpdateOrganizationSpendAlert403 = PermissionErrorResponse +export const UpdateOrganizationSpendAlert403 = PermissionErrorResponse +export type UpdateOrganizationSpendAlert404 = ErrorResponse +export const UpdateOrganizationSpendAlert404 = ErrorResponse +export type DeleteOrganizationSpendAlert200 = OrganizationSpendAlertDeletedResource +export const DeleteOrganizationSpendAlert200 = OrganizationSpendAlertDeletedResource +export type DeleteOrganizationSpendAlert403 = PermissionErrorResponse +export const DeleteOrganizationSpendAlert403 = PermissionErrorResponse +export type DeleteOrganizationSpendAlert404 = ErrorResponse +export const DeleteOrganizationSpendAlert404 = ErrorResponse export type UsageAudioSpeechesParams = { readonly "start_time": number readonly "end_time"?: number @@ -29569,19 +48214,25 @@ export type UsageAudioSpeechesParams = { readonly "page"?: string } export const UsageAudioSpeechesParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "user_ids": Schema.optionalKey(Schema.Array(Schema.String)), "api_key_ids": Schema.optionalKey(Schema.Array(Schema.String)), "models": Schema.optionalKey(Schema.Array(Schema.String)), "group_by": Schema.optionalKey(Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "model"]))), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageAudioSpeeches200 = UsageResponse export const UsageAudioSpeeches200 = UsageResponse +export type UsageAudioSpeeches400 = ErrorResponse +export const UsageAudioSpeeches400 = ErrorResponse +export type UsageAudioSpeeches403 = PermissionErrorResponse +export const UsageAudioSpeeches403 = PermissionErrorResponse +export type UsageAudioSpeeches429 = ErrorResponse +export const UsageAudioSpeeches429 = ErrorResponse export type UsageAudioTranscriptionsParams = { readonly "start_time": number readonly "end_time"?: number @@ -29595,19 +48246,25 @@ export type UsageAudioTranscriptionsParams = { readonly "page"?: string } export const UsageAudioTranscriptionsParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "user_ids": Schema.optionalKey(Schema.Array(Schema.String)), "api_key_ids": Schema.optionalKey(Schema.Array(Schema.String)), "models": Schema.optionalKey(Schema.Array(Schema.String)), "group_by": Schema.optionalKey(Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "model"]))), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageAudioTranscriptions200 = UsageResponse export const UsageAudioTranscriptions200 = UsageResponse +export type UsageAudioTranscriptions400 = ErrorResponse +export const UsageAudioTranscriptions400 = ErrorResponse +export type UsageAudioTranscriptions403 = PermissionErrorResponse +export const UsageAudioTranscriptions403 = PermissionErrorResponse +export type UsageAudioTranscriptions429 = ErrorResponse +export const UsageAudioTranscriptions429 = ErrorResponse export type UsageCodeInterpreterSessionsParams = { readonly "start_time": number readonly "end_time"?: number @@ -29618,16 +48275,22 @@ export type UsageCodeInterpreterSessionsParams = { readonly "page"?: string } export const UsageCodeInterpreterSessionsParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "group_by": Schema.optionalKey(Schema.Array(Schema.Literal("project_id"))), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageCodeInterpreterSessions200 = UsageResponse export const UsageCodeInterpreterSessions200 = UsageResponse +export type UsageCodeInterpreterSessions400 = ErrorResponse +export const UsageCodeInterpreterSessions400 = ErrorResponse +export type UsageCodeInterpreterSessions403 = PermissionErrorResponse +export const UsageCodeInterpreterSessions403 = PermissionErrorResponse +export type UsageCodeInterpreterSessions429 = ErrorResponse +export const UsageCodeInterpreterSessions429 = ErrorResponse export type UsageCompletionsParams = { readonly "start_time": number readonly "end_time"?: number @@ -29637,13 +48300,15 @@ export type UsageCompletionsParams = { readonly "api_key_ids"?: ReadonlyArray readonly "models"?: ReadonlyArray readonly "batch"?: boolean - readonly "group_by"?: ReadonlyArray<"project_id" | "user_id" | "api_key_id" | "model" | "batch" | "service_tier"> + readonly "group_by"?: ReadonlyArray< + "project_id" | "user_id" | "api_key_id" | "model" | "batch" | "service_tier" | "api_source" + > readonly "limit"?: number readonly "page"?: string } export const UsageCompletionsParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "user_ids": Schema.optionalKey(Schema.Array(Schema.String)), @@ -29651,13 +48316,21 @@ export const UsageCompletionsParams = Schema.Struct({ "models": Schema.optionalKey(Schema.Array(Schema.String)), "batch": Schema.optionalKey(Schema.Boolean), "group_by": Schema.optionalKey( - Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "model", "batch", "service_tier"])) + Schema.Array( + Schema.Literals(["project_id", "user_id", "api_key_id", "model", "batch", "service_tier", "api_source"]) + ) ), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageCompletions200 = UsageResponse export const UsageCompletions200 = UsageResponse +export type UsageCompletions400 = ErrorResponse +export const UsageCompletions400 = ErrorResponse +export type UsageCompletions403 = PermissionErrorResponse +export const UsageCompletions403 = PermissionErrorResponse +export type UsageCompletions429 = ErrorResponse +export const UsageCompletions429 = ErrorResponse export type UsageEmbeddingsParams = { readonly "start_time": number readonly "end_time"?: number @@ -29671,19 +48344,25 @@ export type UsageEmbeddingsParams = { readonly "page"?: string } export const UsageEmbeddingsParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "user_ids": Schema.optionalKey(Schema.Array(Schema.String)), "api_key_ids": Schema.optionalKey(Schema.Array(Schema.String)), "models": Schema.optionalKey(Schema.Array(Schema.String)), "group_by": Schema.optionalKey(Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "model"]))), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageEmbeddings200 = UsageResponse export const UsageEmbeddings200 = UsageResponse +export type UsageEmbeddings400 = ErrorResponse +export const UsageEmbeddings400 = ErrorResponse +export type UsageEmbeddings403 = PermissionErrorResponse +export const UsageEmbeddings403 = PermissionErrorResponse +export type UsageEmbeddings429 = ErrorResponse +export const UsageEmbeddings429 = ErrorResponse export type UsageFileSearchCallsParams = { readonly "start_time": number readonly "end_time"?: number @@ -29697,8 +48376,8 @@ export type UsageFileSearchCallsParams = { readonly "page"?: string } export const UsageFileSearchCallsParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "user_ids": Schema.optionalKey(Schema.Array(Schema.String)), @@ -29707,11 +48386,17 @@ export const UsageFileSearchCallsParams = Schema.Struct({ "group_by": Schema.optionalKey( Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "vector_store_id"])) ), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageFileSearchCalls200 = UsageResponse export const UsageFileSearchCalls200 = UsageResponse +export type UsageFileSearchCalls400 = ErrorResponse +export const UsageFileSearchCalls400 = ErrorResponse +export type UsageFileSearchCalls403 = PermissionErrorResponse +export const UsageFileSearchCalls403 = PermissionErrorResponse +export type UsageFileSearchCalls429 = ErrorResponse +export const UsageFileSearchCalls429 = ErrorResponse export type UsageImagesParams = { readonly "start_time": number readonly "end_time"?: number @@ -29727,8 +48412,8 @@ export type UsageImagesParams = { readonly "page"?: string } export const UsageImagesParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "sources": Schema.optionalKey(Schema.Array(Schema.Literals(["image.generation", "image.edit", "image.variation"]))), "sizes": Schema.optionalKey( @@ -29741,11 +48426,17 @@ export const UsageImagesParams = Schema.Struct({ "group_by": Schema.optionalKey( Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "model", "size", "source"])) ), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageImages200 = UsageResponse export const UsageImages200 = UsageResponse +export type UsageImages400 = ErrorResponse +export const UsageImages400 = ErrorResponse +export type UsageImages403 = PermissionErrorResponse +export const UsageImages403 = PermissionErrorResponse +export type UsageImages429 = ErrorResponse +export const UsageImages429 = ErrorResponse export type UsageModerationsParams = { readonly "start_time": number readonly "end_time"?: number @@ -29759,19 +48450,25 @@ export type UsageModerationsParams = { readonly "page"?: string } export const UsageModerationsParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "user_ids": Schema.optionalKey(Schema.Array(Schema.String)), "api_key_ids": Schema.optionalKey(Schema.Array(Schema.String)), "models": Schema.optionalKey(Schema.Array(Schema.String)), "group_by": Schema.optionalKey(Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "model"]))), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageModerations200 = UsageResponse export const UsageModerations200 = UsageResponse +export type UsageModerations400 = ErrorResponse +export const UsageModerations400 = ErrorResponse +export type UsageModerations403 = PermissionErrorResponse +export const UsageModerations403 = PermissionErrorResponse +export type UsageModerations429 = ErrorResponse +export const UsageModerations429 = ErrorResponse export type UsageVectorStoresParams = { readonly "start_time": number readonly "end_time"?: number @@ -29782,16 +48479,22 @@ export type UsageVectorStoresParams = { readonly "page"?: string } export const UsageVectorStoresParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "group_by": Schema.optionalKey(Schema.Array(Schema.Literal("project_id"))), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageVectorStores200 = UsageResponse export const UsageVectorStores200 = UsageResponse +export type UsageVectorStores400 = ErrorResponse +export const UsageVectorStores400 = ErrorResponse +export type UsageVectorStores403 = PermissionErrorResponse +export const UsageVectorStores403 = PermissionErrorResponse +export type UsageVectorStores429 = ErrorResponse +export const UsageVectorStores429 = ErrorResponse export type UsageWebSearchCallsParams = { readonly "start_time": number readonly "end_time"?: number @@ -29801,13 +48504,15 @@ export type UsageWebSearchCallsParams = { readonly "api_key_ids"?: ReadonlyArray readonly "models"?: ReadonlyArray readonly "context_levels"?: ReadonlyArray<"low" | "medium" | "high"> - readonly "group_by"?: ReadonlyArray<"project_id" | "user_id" | "api_key_id" | "model" | "context_level"> + readonly "group_by"?: ReadonlyArray< + "project_id" | "user_id" | "api_key_id" | "model" | "context_level" | "api_source" + > readonly "limit"?: number readonly "page"?: string } export const UsageWebSearchCallsParams = Schema.Struct({ - "start_time": Schema.Number.check(Schema.isInt()), - "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "bucket_width": Schema.optionalKey(Schema.Literals(["1m", "1h", "1d"])), "project_ids": Schema.optionalKey(Schema.Array(Schema.String)), "user_ids": Schema.optionalKey(Schema.Array(Schema.String)), @@ -29815,33 +48520,67 @@ export const UsageWebSearchCallsParams = Schema.Struct({ "models": Schema.optionalKey(Schema.Array(Schema.String)), "context_levels": Schema.optionalKey(Schema.Array(Schema.Literals(["low", "medium", "high"]))), "group_by": Schema.optionalKey( - Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "model", "context_level"])) + Schema.Array(Schema.Literals(["project_id", "user_id", "api_key_id", "model", "context_level", "api_source"])) ), - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "page": Schema.optionalKey(Schema.String) }) export type UsageWebSearchCalls200 = UsageResponse export const UsageWebSearchCalls200 = UsageResponse +export type UsageWebSearchCalls400 = ErrorResponse +export const UsageWebSearchCalls400 = ErrorResponse +export type UsageWebSearchCalls403 = PermissionErrorResponse +export const UsageWebSearchCalls403 = PermissionErrorResponse +export type UsageWebSearchCalls429 = ErrorResponse +export const UsageWebSearchCalls429 = ErrorResponse export type ListUsersParams = { readonly "limit"?: number readonly "after"?: string readonly "emails"?: ReadonlyArray } export const ListUsersParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "after": Schema.optionalKey(Schema.String), "emails": Schema.optionalKey(Schema.Array(Schema.String)) }) export type ListUsers200 = UserListResponse export const ListUsers200 = UserListResponse +export type ListUsers400 = ErrorResponse +export const ListUsers400 = ErrorResponse +export type ListUsers403 = PermissionErrorResponse +export const ListUsers403 = PermissionErrorResponse +export type ListUsers429 = ErrorResponse +export const ListUsers429 = ErrorResponse export type RetrieveUser200 = User export const RetrieveUser200 = User +export type RetrieveUser403 = PermissionErrorResponse +export const RetrieveUser403 = PermissionErrorResponse +export type RetrieveUser404 = ErrorResponse +export const RetrieveUser404 = ErrorResponse +export type RetrieveUser429 = ErrorResponse +export const RetrieveUser429 = ErrorResponse export type ModifyUserRequestJson = UserRoleUpdateRequest export const ModifyUserRequestJson = UserRoleUpdateRequest export type ModifyUser200 = User export const ModifyUser200 = User +export type ModifyUser400 = ErrorResponse +export const ModifyUser400 = ErrorResponse +export type ModifyUser403 = PermissionErrorResponse +export const ModifyUser403 = PermissionErrorResponse +export type ModifyUser404 = ErrorResponse +export const ModifyUser404 = ErrorResponse +export type ModifyUser429 = ErrorResponse +export const ModifyUser429 = ErrorResponse export type DeleteUser200 = UserDeleteResponse export const DeleteUser200 = UserDeleteResponse +export type DeleteUser400 = ErrorResponse +export const DeleteUser400 = ErrorResponse +export type DeleteUser403 = PermissionErrorResponse +export const DeleteUser403 = PermissionErrorResponse +export type DeleteUser404 = ErrorResponse +export const DeleteUser404 = ErrorResponse +export type DeleteUser429 = ErrorResponse +export const DeleteUser429 = ErrorResponse export type ListUserRoleAssignmentsParams = { readonly "limit"?: number readonly "after"?: string @@ -29849,19 +48588,55 @@ export type ListUserRoleAssignmentsParams = { } export const ListUserRoleAssignmentsParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1000)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1000).annotate({ "expected": "a value less than or equal to 1000" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListUserRoleAssignments200 = RoleListResource export const ListUserRoleAssignments200 = RoleListResource +export type ListUserRoleAssignments400 = ErrorResponse +export const ListUserRoleAssignments400 = ErrorResponse +export type ListUserRoleAssignments403 = PermissionErrorResponse +export const ListUserRoleAssignments403 = PermissionErrorResponse +export type ListUserRoleAssignments404 = ErrorResponse +export const ListUserRoleAssignments404 = ErrorResponse +export type ListUserRoleAssignments429 = ErrorResponse +export const ListUserRoleAssignments429 = ErrorResponse export type AssignUserRoleRequestJson = PublicAssignOrganizationGroupRoleBody export const AssignUserRoleRequestJson = PublicAssignOrganizationGroupRoleBody export type AssignUserRole200 = UserRoleAssignment export const AssignUserRole200 = UserRoleAssignment +export type AssignUserRole400 = ErrorResponse +export const AssignUserRole400 = ErrorResponse +export type AssignUserRole403 = PermissionErrorResponse +export const AssignUserRole403 = PermissionErrorResponse +export type AssignUserRole404 = ErrorResponse +export const AssignUserRole404 = ErrorResponse +export type AssignUserRole429 = ErrorResponse +export const AssignUserRole429 = ErrorResponse +export type RetrieveUserRole200 = AssignedRoleDetails +export const RetrieveUserRole200 = AssignedRoleDetails +export type RetrieveUserRole400 = ErrorResponse +export const RetrieveUserRole400 = ErrorResponse +export type RetrieveUserRole403 = PermissionErrorResponse +export const RetrieveUserRole403 = PermissionErrorResponse +export type RetrieveUserRole404 = ErrorResponse +export const RetrieveUserRole404 = ErrorResponse +export type RetrieveUserRole429 = ErrorResponse +export const RetrieveUserRole429 = ErrorResponse export type UnassignUserRole200 = DeletedRoleAssignmentResource export const UnassignUserRole200 = DeletedRoleAssignmentResource +export type UnassignUserRole400 = ErrorResponse +export const UnassignUserRole400 = ErrorResponse +export type UnassignUserRole403 = PermissionErrorResponse +export const UnassignUserRole403 = PermissionErrorResponse +export type UnassignUserRole404 = ErrorResponse +export const UnassignUserRole404 = ErrorResponse +export type UnassignUserRole429 = ErrorResponse +export const UnassignUserRole429 = ErrorResponse export type ListProjectGroupRoleAssignmentsParams = { readonly "limit"?: number readonly "after"?: string @@ -29869,19 +48644,55 @@ export type ListProjectGroupRoleAssignmentsParams = { } export const ListProjectGroupRoleAssignmentsParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1000)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1000).annotate({ "expected": "a value less than or equal to 1000" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListProjectGroupRoleAssignments200 = RoleListResource export const ListProjectGroupRoleAssignments200 = RoleListResource +export type ListProjectGroupRoleAssignments400 = ErrorResponse +export const ListProjectGroupRoleAssignments400 = ErrorResponse +export type ListProjectGroupRoleAssignments403 = PermissionErrorResponse +export const ListProjectGroupRoleAssignments403 = PermissionErrorResponse +export type ListProjectGroupRoleAssignments404 = ErrorResponse +export const ListProjectGroupRoleAssignments404 = ErrorResponse +export type ListProjectGroupRoleAssignments429 = ErrorResponse +export const ListProjectGroupRoleAssignments429 = ErrorResponse export type AssignProjectGroupRoleRequestJson = PublicAssignOrganizationGroupRoleBody export const AssignProjectGroupRoleRequestJson = PublicAssignOrganizationGroupRoleBody export type AssignProjectGroupRole200 = GroupRoleAssignment export const AssignProjectGroupRole200 = GroupRoleAssignment +export type AssignProjectGroupRole400 = ErrorResponse +export const AssignProjectGroupRole400 = ErrorResponse +export type AssignProjectGroupRole403 = PermissionErrorResponse +export const AssignProjectGroupRole403 = PermissionErrorResponse +export type AssignProjectGroupRole404 = ErrorResponse +export const AssignProjectGroupRole404 = ErrorResponse +export type AssignProjectGroupRole429 = ErrorResponse +export const AssignProjectGroupRole429 = ErrorResponse +export type RetrieveProjectGroupRole200 = AssignedRoleDetails +export const RetrieveProjectGroupRole200 = AssignedRoleDetails +export type RetrieveProjectGroupRole400 = ErrorResponse +export const RetrieveProjectGroupRole400 = ErrorResponse +export type RetrieveProjectGroupRole403 = PermissionErrorResponse +export const RetrieveProjectGroupRole403 = PermissionErrorResponse +export type RetrieveProjectGroupRole404 = ErrorResponse +export const RetrieveProjectGroupRole404 = ErrorResponse +export type RetrieveProjectGroupRole429 = ErrorResponse +export const RetrieveProjectGroupRole429 = ErrorResponse export type UnassignProjectGroupRole200 = DeletedRoleAssignmentResource export const UnassignProjectGroupRole200 = DeletedRoleAssignmentResource +export type UnassignProjectGroupRole400 = ErrorResponse +export const UnassignProjectGroupRole400 = ErrorResponse +export type UnassignProjectGroupRole403 = PermissionErrorResponse +export const UnassignProjectGroupRole403 = PermissionErrorResponse +export type UnassignProjectGroupRole404 = ErrorResponse +export const UnassignProjectGroupRole404 = ErrorResponse +export type UnassignProjectGroupRole429 = ErrorResponse +export const UnassignProjectGroupRole429 = ErrorResponse export type ListProjectRolesParams = { readonly "limit"?: number readonly "after"?: string @@ -29889,23 +48700,65 @@ export type ListProjectRolesParams = { } export const ListProjectRolesParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1000)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1000).annotate({ "expected": "a value less than or equal to 1000" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListProjectRoles200 = PublicRoleListResource export const ListProjectRoles200 = PublicRoleListResource +export type ListProjectRoles400 = ErrorResponse +export const ListProjectRoles400 = ErrorResponse +export type ListProjectRoles403 = PermissionErrorResponse +export const ListProjectRoles403 = PermissionErrorResponse +export type ListProjectRoles404 = ErrorResponse +export const ListProjectRoles404 = ErrorResponse +export type ListProjectRoles429 = ErrorResponse +export const ListProjectRoles429 = ErrorResponse export type CreateProjectRoleRequestJson = PublicCreateOrganizationRoleBody export const CreateProjectRoleRequestJson = PublicCreateOrganizationRoleBody export type CreateProjectRole200 = Role export const CreateProjectRole200 = Role +export type CreateProjectRole400 = ErrorResponse +export const CreateProjectRole400 = ErrorResponse +export type CreateProjectRole403 = PermissionErrorResponse +export const CreateProjectRole403 = PermissionErrorResponse +export type CreateProjectRole404 = ErrorResponse +export const CreateProjectRole404 = ErrorResponse +export type CreateProjectRole429 = ErrorResponse +export const CreateProjectRole429 = ErrorResponse +export type RetrieveProjectRole200 = Role +export const RetrieveProjectRole200 = Role +export type RetrieveProjectRole403 = PermissionErrorResponse +export const RetrieveProjectRole403 = PermissionErrorResponse +export type RetrieveProjectRole404 = ErrorResponse +export const RetrieveProjectRole404 = ErrorResponse +export type RetrieveProjectRole429 = ErrorResponse +export const RetrieveProjectRole429 = ErrorResponse export type UpdateProjectRoleRequestJson = PublicUpdateOrganizationRoleBody export const UpdateProjectRoleRequestJson = PublicUpdateOrganizationRoleBody export type UpdateProjectRole200 = Role export const UpdateProjectRole200 = Role +export type UpdateProjectRole400 = ErrorResponse +export const UpdateProjectRole400 = ErrorResponse +export type UpdateProjectRole403 = PermissionErrorResponse +export const UpdateProjectRole403 = PermissionErrorResponse +export type UpdateProjectRole404 = ErrorResponse +export const UpdateProjectRole404 = ErrorResponse +export type UpdateProjectRole429 = ErrorResponse +export const UpdateProjectRole429 = ErrorResponse export type DeleteProjectRole200 = RoleDeletedResource export const DeleteProjectRole200 = RoleDeletedResource +export type DeleteProjectRole400 = ErrorResponse +export const DeleteProjectRole400 = ErrorResponse +export type DeleteProjectRole403 = PermissionErrorResponse +export const DeleteProjectRole403 = PermissionErrorResponse +export type DeleteProjectRole404 = ErrorResponse +export const DeleteProjectRole404 = ErrorResponse +export type DeleteProjectRole429 = ErrorResponse +export const DeleteProjectRole429 = ErrorResponse export type ListProjectUserRoleAssignmentsParams = { readonly "limit"?: number readonly "after"?: string @@ -29913,31 +48766,85 @@ export type ListProjectUserRoleAssignmentsParams = { } export const ListProjectUserRoleAssignmentsParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(1000)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(1000).annotate({ "expected": "a value less than or equal to 1000" })) ), "after": Schema.optionalKey(Schema.String), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])) }) export type ListProjectUserRoleAssignments200 = RoleListResource export const ListProjectUserRoleAssignments200 = RoleListResource +export type ListProjectUserRoleAssignments400 = ErrorResponse +export const ListProjectUserRoleAssignments400 = ErrorResponse +export type ListProjectUserRoleAssignments403 = PermissionErrorResponse +export const ListProjectUserRoleAssignments403 = PermissionErrorResponse +export type ListProjectUserRoleAssignments404 = ErrorResponse +export const ListProjectUserRoleAssignments404 = ErrorResponse +export type ListProjectUserRoleAssignments429 = ErrorResponse +export const ListProjectUserRoleAssignments429 = ErrorResponse export type AssignProjectUserRoleRequestJson = PublicAssignOrganizationGroupRoleBody export const AssignProjectUserRoleRequestJson = PublicAssignOrganizationGroupRoleBody export type AssignProjectUserRole200 = UserRoleAssignment export const AssignProjectUserRole200 = UserRoleAssignment +export type AssignProjectUserRole400 = ErrorResponse +export const AssignProjectUserRole400 = ErrorResponse +export type AssignProjectUserRole403 = PermissionErrorResponse +export const AssignProjectUserRole403 = PermissionErrorResponse +export type AssignProjectUserRole404 = ErrorResponse +export const AssignProjectUserRole404 = ErrorResponse +export type AssignProjectUserRole429 = ErrorResponse +export const AssignProjectUserRole429 = ErrorResponse +export type RetrieveProjectUserRole200 = AssignedRoleDetails +export const RetrieveProjectUserRole200 = AssignedRoleDetails +export type RetrieveProjectUserRole400 = ErrorResponse +export const RetrieveProjectUserRole400 = ErrorResponse +export type RetrieveProjectUserRole403 = PermissionErrorResponse +export const RetrieveProjectUserRole403 = PermissionErrorResponse +export type RetrieveProjectUserRole404 = ErrorResponse +export const RetrieveProjectUserRole404 = ErrorResponse +export type RetrieveProjectUserRole429 = ErrorResponse +export const RetrieveProjectUserRole429 = ErrorResponse export type UnassignProjectUserRole200 = DeletedRoleAssignmentResource export const UnassignProjectUserRole200 = DeletedRoleAssignmentResource +export type UnassignProjectUserRole400 = ErrorResponse +export const UnassignProjectUserRole400 = ErrorResponse +export type UnassignProjectUserRole403 = PermissionErrorResponse +export const UnassignProjectUserRole403 = PermissionErrorResponse +export type UnassignProjectUserRole404 = ErrorResponse +export const UnassignProjectUserRole404 = ErrorResponse +export type UnassignProjectUserRole429 = ErrorResponse +export const UnassignProjectUserRole429 = ErrorResponse export type CreateRealtimeCallRequestFormData = RealtimeCallCreateRequest export const CreateRealtimeCallRequestFormData = RealtimeCallCreateRequest export type AcceptRealtimeCallRequestJson = RealtimeSessionCreateRequestGA export const AcceptRealtimeCallRequestJson = RealtimeSessionCreateRequestGA +export type AcceptRealtimeCall404 = ErrorResponse +export const AcceptRealtimeCall404 = ErrorResponse +export type AcceptRealtimeCall409 = ErrorResponse +export const AcceptRealtimeCall409 = ErrorResponse +export type HangupRealtimeCall404 = ErrorResponse +export const HangupRealtimeCall404 = ErrorResponse export type ReferRealtimeCallRequestJson = RealtimeCallReferRequest export const ReferRealtimeCallRequestJson = RealtimeCallReferRequest +export type ReferRealtimeCall404 = ErrorResponse +export const ReferRealtimeCall404 = ErrorResponse export type RejectRealtimeCallRequestJson = RealtimeCallRejectRequest export const RejectRealtimeCallRequestJson = RealtimeCallRejectRequest +export type RejectRealtimeCall404 = ErrorResponse +export const RejectRealtimeCall404 = ErrorResponse +export type RejectRealtimeCall409 = ErrorResponse +export const RejectRealtimeCall409 = ErrorResponse export type CreateRealtimeClientSecretRequestJson = RealtimeCreateClientSecretRequest export const CreateRealtimeClientSecretRequestJson = RealtimeCreateClientSecretRequest export type CreateRealtimeClientSecret200 = RealtimeCreateClientSecretResponse export const CreateRealtimeClientSecret200 = RealtimeCreateClientSecretResponse +export type CreateRealtimeClientSecret400 = ErrorResponse +export const CreateRealtimeClientSecret400 = ErrorResponse +export type CreateRealtimeClientSecret404 = ErrorResponse +export const CreateRealtimeClientSecret404 = ErrorResponse +export type CreateRealtimeClientSecret500 = ErrorResponse +export const CreateRealtimeClientSecret500 = ErrorResponse export type CreateRealtimeSessionRequestJson = RealtimeSessionCreateRequest export const CreateRealtimeSessionRequestJson = RealtimeSessionCreateRequest export type CreateRealtimeSession200 = RealtimeSessionCreateResponse @@ -29950,12 +48857,26 @@ export type CreateRealtimeTranslationClientSecretRequestJson = RealtimeTranslati export const CreateRealtimeTranslationClientSecretRequestJson = RealtimeTranslationClientSecretCreateRequest export type CreateRealtimeTranslationClientSecret200 = RealtimeTranslationClientSecretCreateResponse export const CreateRealtimeTranslationClientSecret200 = RealtimeTranslationClientSecretCreateResponse +export type CreateRealtimeTranslationClientSecret400 = ErrorResponse +export const CreateRealtimeTranslationClientSecret400 = ErrorResponse +export type CreateRealtimeTranslationClientSecret404 = ErrorResponse +export const CreateRealtimeTranslationClientSecret404 = ErrorResponse +export type CreateRealtimeTranslationClientSecret500 = ErrorResponse +export const CreateRealtimeTranslationClientSecret500 = ErrorResponse export type CreateResponseRequestJson = CreateResponse export const CreateResponseRequestJson = CreateResponse export type CreateResponse200 = Response export const CreateResponse200 = Response export type CreateResponse200Sse = ResponseStreamEvent export const CreateResponse200Sse = ResponseStreamEvent +export type CreateResponse400 = ErrorResponse +export const CreateResponse400 = ErrorResponse +export type CreateResponse404 = ErrorResponse +export const CreateResponse404 = ErrorResponse +export type CreateResponse429 = ErrorResponse +export const CreateResponse429 = ErrorResponse +export type CreateResponse503 = ErrorResponse +export const CreateResponse503 = ErrorResponse export type GetResponseParams = { readonly "include"?: ReadonlyArray readonly "stream"?: boolean @@ -29965,17 +48886,35 @@ export type GetResponseParams = { export const GetResponseParams = Schema.Struct({ "include": Schema.optionalKey(Schema.Array(IncludeEnum)), "stream": Schema.optionalKey(Schema.Boolean), - "starting_after": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "starting_after": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "include_obfuscation": Schema.optionalKey(Schema.Boolean) }) export type GetResponse200 = Response export const GetResponse200 = Response -export type DeleteResponse404 = Error -export const DeleteResponse404 = Error +export type GetResponse404 = ErrorResponse +export const GetResponse404 = ErrorResponse +export type GetResponse429 = ErrorResponse +export const GetResponse429 = ErrorResponse +export type DeleteResponse200 = { + readonly "object": "response.deleted" + readonly "deleted": boolean + readonly "id": string +} +export const DeleteResponse200 = Schema.Struct({ + "object": Schema.Literal("response.deleted"), + "deleted": Schema.Boolean, + "id": Schema.String +}) +export type DeleteResponse404 = ErrorResponse +export const DeleteResponse404 = ErrorResponse +export type DeleteResponse429 = ErrorResponse +export const DeleteResponse429 = ErrorResponse export type CancelResponse200 = Response export const CancelResponse200 = Response -export type CancelResponse404 = Error -export const CancelResponse404 = Error +export type CancelResponse404 = ErrorResponse +export const CancelResponse404 = ErrorResponse +export type CancelResponse429 = ErrorResponse +export const CancelResponse429 = ErrorResponse export type ListInputItemsParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -29983,29 +48922,45 @@ export type ListInputItemsParams = { readonly "include"?: ReadonlyArray } export const ListInputItemsParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "include": Schema.optionalKey(Schema.Array(IncludeEnum)) }) export type ListInputItems200 = ResponseItemList export const ListInputItems200 = ResponseItemList +export type ListInputItems404 = ErrorResponse +export const ListInputItems404 = ErrorResponse +export type ListInputItems429 = ErrorResponse +export const ListInputItems429 = ErrorResponse export type CreateThreadRequestJson = CreateThreadRequest export const CreateThreadRequestJson = CreateThreadRequest export type CreateThread200 = ThreadObject export const CreateThread200 = ThreadObject +export type CreateThread429 = ErrorResponse +export const CreateThread429 = ErrorResponse export type CreateThreadAndRunRequestJson = CreateThreadAndRunRequest export const CreateThreadAndRunRequestJson = CreateThreadAndRunRequest export type CreateThreadAndRun200 = RunObject export const CreateThreadAndRun200 = RunObject +export type CreateThreadAndRun200Sse = AssistantStreamEvent +export const CreateThreadAndRun200Sse = AssistantStreamEvent +export type CreateThreadAndRun429 = ErrorResponse +export const CreateThreadAndRun429 = ErrorResponse export type GetThread200 = ThreadObject export const GetThread200 = ThreadObject +export type GetThread429 = ErrorResponse +export const GetThread429 = ErrorResponse export type ModifyThreadRequestJson = ModifyThreadRequest export const ModifyThreadRequestJson = ModifyThreadRequest export type ModifyThread200 = ThreadObject export const ModifyThread200 = ThreadObject +export type ModifyThread429 = ErrorResponse +export const ModifyThread429 = ErrorResponse export type DeleteThread200 = DeleteThreadResponse export const DeleteThread200 = DeleteThreadResponse +export type DeleteThread429 = ErrorResponse +export const DeleteThread429 = ErrorResponse export type ListMessagesParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -30014,7 +48969,7 @@ export type ListMessagesParams = { readonly "run_id"?: string } export const ListMessagesParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String), @@ -30022,18 +48977,28 @@ export const ListMessagesParams = Schema.Struct({ }) export type ListMessages200 = ListMessagesResponse export const ListMessages200 = ListMessagesResponse +export type ListMessages429 = ErrorResponse +export const ListMessages429 = ErrorResponse export type CreateMessageRequestJson = CreateMessageRequest export const CreateMessageRequestJson = CreateMessageRequest export type CreateMessage200 = MessageObject export const CreateMessage200 = MessageObject +export type CreateMessage429 = ErrorResponse +export const CreateMessage429 = ErrorResponse export type GetMessage200 = MessageObject export const GetMessage200 = MessageObject +export type GetMessage429 = ErrorResponse +export const GetMessage429 = ErrorResponse export type ModifyMessageRequestJson = ModifyMessageRequest export const ModifyMessageRequestJson = ModifyMessageRequest export type ModifyMessage200 = MessageObject export const ModifyMessage200 = MessageObject +export type ModifyMessage429 = ErrorResponse +export const ModifyMessage429 = ErrorResponse export type DeleteMessage200 = DeleteMessageResponse export const DeleteMessage200 = DeleteMessageResponse +export type DeleteMessage429 = ErrorResponse +export const DeleteMessage429 = ErrorResponse export type ListRunsParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -30041,13 +49006,15 @@ export type ListRunsParams = { readonly "before"?: string } export const ListRunsParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String) }) export type ListRuns200 = ListRunsResponse export const ListRuns200 = ListRunsResponse +export type ListRuns429 = ErrorResponse +export const ListRuns429 = ErrorResponse export type CreateRunParams = { readonly "include[]"?: ReadonlyArray<"step_details.tool_calls[*].file_search.results[*].content"> } @@ -30060,14 +49027,24 @@ export type CreateRunRequestJson = CreateRunRequest export const CreateRunRequestJson = CreateRunRequest export type CreateRun200 = RunObject export const CreateRun200 = RunObject +export type CreateRun200Sse = AssistantStreamEvent +export const CreateRun200Sse = AssistantStreamEvent +export type CreateRun429 = ErrorResponse +export const CreateRun429 = ErrorResponse export type GetRun200 = RunObject export const GetRun200 = RunObject +export type GetRun429 = ErrorResponse +export const GetRun429 = ErrorResponse export type ModifyRunRequestJson = ModifyRunRequest export const ModifyRunRequestJson = ModifyRunRequest export type ModifyRun200 = RunObject export const ModifyRun200 = RunObject +export type ModifyRun429 = ErrorResponse +export const ModifyRun429 = ErrorResponse export type CancelRun200 = RunObject export const CancelRun200 = RunObject +export type CancelRun429 = ErrorResponse +export const CancelRun429 = ErrorResponse export type ListRunStepsParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -30076,7 +49053,7 @@ export type ListRunStepsParams = { readonly "include[]"?: ReadonlyArray<"step_details.tool_calls[*].file_search.results[*].content"> } export const ListRunStepsParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String), @@ -30086,6 +49063,8 @@ export const ListRunStepsParams = Schema.Struct({ }) export type ListRunSteps200 = ListRunStepsResponse export const ListRunSteps200 = ListRunStepsResponse +export type ListRunSteps429 = ErrorResponse +export const ListRunSteps429 = ErrorResponse export type GetRunStepParams = { readonly "include[]"?: ReadonlyArray<"step_details.tool_calls[*].file_search.results[*].content"> } @@ -30096,24 +49075,62 @@ export const GetRunStepParams = Schema.Struct({ }) export type GetRunStep200 = RunStepObject export const GetRunStep200 = RunStepObject +export type GetRunStep429 = ErrorResponse +export const GetRunStep429 = ErrorResponse export type SubmitToolOuputsToRunRequestJson = SubmitToolOutputsRunRequest export const SubmitToolOuputsToRunRequestJson = SubmitToolOutputsRunRequest export type SubmitToolOuputsToRun200 = RunObject export const SubmitToolOuputsToRun200 = RunObject +export type SubmitToolOuputsToRun200Sse = AssistantStreamEvent +export const SubmitToolOuputsToRun200Sse = AssistantStreamEvent +export type SubmitToolOuputsToRun429 = ErrorResponse +export const SubmitToolOuputsToRun429 = ErrorResponse export type CreateUploadRequestJson = CreateUploadRequest export const CreateUploadRequestJson = CreateUploadRequest export type CreateUpload200 = Upload export const CreateUpload200 = Upload +export type CreateUpload400 = ErrorResponse +export const CreateUpload400 = ErrorResponse +export type CreateUpload429 = ErrorResponse +export const CreateUpload429 = ErrorResponse export type CancelUpload200 = Upload export const CancelUpload200 = Upload +export type CancelUpload400 = ErrorResponse +export const CancelUpload400 = ErrorResponse +export type CancelUpload404 = ErrorResponse +export const CancelUpload404 = ErrorResponse +export type CancelUpload410 = ErrorResponse +export const CancelUpload410 = ErrorResponse +export type CancelUpload429 = ErrorResponse +export const CancelUpload429 = ErrorResponse export type CompleteUploadRequestJson = CompleteUploadRequest export const CompleteUploadRequestJson = CompleteUploadRequest export type CompleteUpload200 = Upload export const CompleteUpload200 = Upload -export type AddUploadPartRequestFormData = AddUploadPartRequest -export const AddUploadPartRequestFormData = AddUploadPartRequest +export type CompleteUpload400 = ErrorResponse +export const CompleteUpload400 = ErrorResponse +export type CompleteUpload404 = ErrorResponse +export const CompleteUpload404 = ErrorResponse +export type CompleteUpload410 = ErrorResponse +export const CompleteUpload410 = ErrorResponse +export type CompleteUpload429 = ErrorResponse +export const CompleteUpload429 = ErrorResponse +export type CompleteUpload500 = ErrorResponse +export const CompleteUpload500 = ErrorResponse +export type AddUploadPartRequestFormData = AddUploadPartRequestMultipart +export const AddUploadPartRequestFormData = AddUploadPartRequestMultipart export type AddUploadPart200 = UploadPart export const AddUploadPart200 = UploadPart +export type AddUploadPart400 = ErrorResponse +export const AddUploadPart400 = ErrorResponse +export type AddUploadPart404 = ErrorResponse +export const AddUploadPart404 = ErrorResponse +export type AddUploadPart410 = ErrorResponse +export const AddUploadPart410 = ErrorResponse +export type AddUploadPart429 = ErrorResponse +export const AddUploadPart429 = ErrorResponse +export type AddUploadPart500 = ErrorResponse +export const AddUploadPart500 = ErrorResponse export type ListVectorStoresParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -30121,33 +49138,85 @@ export type ListVectorStoresParams = { readonly "before"?: string } export const ListVectorStoresParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String) }) export type ListVectorStores200 = ListVectorStoresResponse export const ListVectorStores200 = ListVectorStoresResponse +export type ListVectorStores429 = ErrorResponse +export const ListVectorStores429 = ErrorResponse +export type ListVectorStores503 = ErrorResponse +export const ListVectorStores503 = ErrorResponse export type CreateVectorStoreRequestJson = CreateVectorStoreRequest export const CreateVectorStoreRequestJson = CreateVectorStoreRequest export type CreateVectorStore200 = VectorStoreObject export const CreateVectorStore200 = VectorStoreObject +export type CreateVectorStore400 = ErrorResponse +export const CreateVectorStore400 = ErrorResponse +export type CreateVectorStore404 = ErrorResponse +export const CreateVectorStore404 = ErrorResponse +export type CreateVectorStore429 = ErrorResponse +export const CreateVectorStore429 = ErrorResponse export type GetVectorStore200 = VectorStoreObject export const GetVectorStore200 = VectorStoreObject +export type GetVectorStore404 = ErrorResponse +export const GetVectorStore404 = ErrorResponse +export type GetVectorStore429 = ErrorResponse +export const GetVectorStore429 = ErrorResponse export type ModifyVectorStoreRequestJson = UpdateVectorStoreRequest export const ModifyVectorStoreRequestJson = UpdateVectorStoreRequest export type ModifyVectorStore200 = VectorStoreObject export const ModifyVectorStore200 = VectorStoreObject +export type ModifyVectorStore400 = ErrorResponse +export const ModifyVectorStore400 = ErrorResponse +export type ModifyVectorStore403 = ErrorResponse +export const ModifyVectorStore403 = ErrorResponse +export type ModifyVectorStore404 = ErrorResponse +export const ModifyVectorStore404 = ErrorResponse +export type ModifyVectorStore429 = ErrorResponse +export const ModifyVectorStore429 = ErrorResponse export type DeleteVectorStore200 = DeleteVectorStoreResponse export const DeleteVectorStore200 = DeleteVectorStoreResponse +export type DeleteVectorStore404 = ErrorResponse +export const DeleteVectorStore404 = ErrorResponse +export type DeleteVectorStore409 = ErrorResponse +export const DeleteVectorStore409 = ErrorResponse +export type DeleteVectorStore429 = ErrorResponse +export const DeleteVectorStore429 = ErrorResponse export type CreateVectorStoreFileBatchRequestJson = CreateVectorStoreFileBatchRequest export const CreateVectorStoreFileBatchRequestJson = CreateVectorStoreFileBatchRequest export type CreateVectorStoreFileBatch200 = VectorStoreFileBatchObject export const CreateVectorStoreFileBatch200 = VectorStoreFileBatchObject +export type CreateVectorStoreFileBatch400 = ErrorResponse +export const CreateVectorStoreFileBatch400 = ErrorResponse +export type CreateVectorStoreFileBatch404 = ErrorResponse +export const CreateVectorStoreFileBatch404 = ErrorResponse +export type CreateVectorStoreFileBatch409 = ErrorResponse +export const CreateVectorStoreFileBatch409 = ErrorResponse +export type CreateVectorStoreFileBatch429 = ErrorResponse +export const CreateVectorStoreFileBatch429 = ErrorResponse +export type CreateVectorStoreFileBatch500 = ErrorResponse +export const CreateVectorStoreFileBatch500 = ErrorResponse export type GetVectorStoreFileBatch200 = VectorStoreFileBatchObject export const GetVectorStoreFileBatch200 = VectorStoreFileBatchObject +export type GetVectorStoreFileBatch400 = ErrorResponse +export const GetVectorStoreFileBatch400 = ErrorResponse +export type GetVectorStoreFileBatch404 = ErrorResponse +export const GetVectorStoreFileBatch404 = ErrorResponse +export type GetVectorStoreFileBatch429 = ErrorResponse +export const GetVectorStoreFileBatch429 = ErrorResponse export type CancelVectorStoreFileBatch200 = VectorStoreFileBatchObject export const CancelVectorStoreFileBatch200 = VectorStoreFileBatchObject +export type CancelVectorStoreFileBatch400 = ErrorResponse +export const CancelVectorStoreFileBatch400 = ErrorResponse +export type CancelVectorStoreFileBatch404 = ErrorResponse +export const CancelVectorStoreFileBatch404 = ErrorResponse +export type CancelVectorStoreFileBatch409 = ErrorResponse +export const CancelVectorStoreFileBatch409 = ErrorResponse +export type CancelVectorStoreFileBatch429 = ErrorResponse +export const CancelVectorStoreFileBatch429 = ErrorResponse export type ListFilesInVectorStoreBatchParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -30156,7 +49225,7 @@ export type ListFilesInVectorStoreBatchParams = { readonly "filter"?: "in_progress" | "completed" | "failed" | "cancelled" } export const ListFilesInVectorStoreBatchParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String), @@ -30164,6 +49233,12 @@ export const ListFilesInVectorStoreBatchParams = Schema.Struct({ }) export type ListFilesInVectorStoreBatch200 = ListVectorStoreFilesResponse export const ListFilesInVectorStoreBatch200 = ListVectorStoreFilesResponse +export type ListFilesInVectorStoreBatch400 = ErrorResponse +export const ListFilesInVectorStoreBatch400 = ErrorResponse +export type ListFilesInVectorStoreBatch404 = ErrorResponse +export const ListFilesInVectorStoreBatch404 = ErrorResponse +export type ListFilesInVectorStoreBatch429 = ErrorResponse +export const ListFilesInVectorStoreBatch429 = ErrorResponse export type ListVectorStoreFilesParams = { readonly "limit"?: number readonly "order"?: "asc" | "desc" @@ -30172,48 +49247,391 @@ export type ListVectorStoreFilesParams = { readonly "filter"?: "in_progress" | "completed" | "failed" | "cancelled" } export const ListVectorStoreFilesParams = Schema.Struct({ - "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt())), + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), "after": Schema.optionalKey(Schema.String), "before": Schema.optionalKey(Schema.String), "filter": Schema.optionalKey(Schema.Literals(["in_progress", "completed", "failed", "cancelled"])) }) -export type ListVectorStoreFiles200 = ListVectorStoreFilesResponse -export const ListVectorStoreFiles200 = ListVectorStoreFilesResponse -export type CreateVectorStoreFileRequestJson = CreateVectorStoreFileRequest -export const CreateVectorStoreFileRequestJson = CreateVectorStoreFileRequest -export type CreateVectorStoreFile200 = VectorStoreFileObject -export const CreateVectorStoreFile200 = VectorStoreFileObject -export type GetVectorStoreFile200 = VectorStoreFileObject -export const GetVectorStoreFile200 = VectorStoreFileObject -export type UpdateVectorStoreFileAttributesRequestJson = UpdateVectorStoreFileAttributesRequest -export const UpdateVectorStoreFileAttributesRequestJson = UpdateVectorStoreFileAttributesRequest -export type UpdateVectorStoreFileAttributes200 = VectorStoreFileObject -export const UpdateVectorStoreFileAttributes200 = VectorStoreFileObject -export type DeleteVectorStoreFile200 = DeleteVectorStoreFileResponse -export const DeleteVectorStoreFile200 = DeleteVectorStoreFileResponse -export type RetrieveVectorStoreFileContent200 = VectorStoreFileContentResponse -export const RetrieveVectorStoreFileContent200 = VectorStoreFileContentResponse -export type SearchVectorStoreRequestJson = VectorStoreSearchRequest -export const SearchVectorStoreRequestJson = VectorStoreSearchRequest -export type SearchVectorStore200 = VectorStoreSearchResultsPage -export const SearchVectorStore200 = VectorStoreSearchResultsPage -export type CreateConversationRequestJson = CreateConversationBody -export const CreateConversationRequestJson = CreateConversationBody -export type CreateConversation200 = ConversationResource -export const CreateConversation200 = ConversationResource -export type GetConversation200 = ConversationResource -export const GetConversation200 = ConversationResource -export type UpdateConversationRequestJson = UpdateConversationBody -export const UpdateConversationRequestJson = UpdateConversationBody -export type UpdateConversation200 = ConversationResource -export const UpdateConversation200 = ConversationResource -export type DeleteConversation200 = DeletedConversationResource -export const DeleteConversation200 = DeletedConversationResource +export type ListVectorStoreFiles200 = ListVectorStoreFilesResponse +export const ListVectorStoreFiles200 = ListVectorStoreFilesResponse +export type ListVectorStoreFiles400 = ErrorResponse +export const ListVectorStoreFiles400 = ErrorResponse +export type ListVectorStoreFiles404 = ErrorResponse +export const ListVectorStoreFiles404 = ErrorResponse +export type ListVectorStoreFiles429 = ErrorResponse +export const ListVectorStoreFiles429 = ErrorResponse +export type CreateVectorStoreFileRequestJson = CreateVectorStoreFileRequest +export const CreateVectorStoreFileRequestJson = CreateVectorStoreFileRequest +export type CreateVectorStoreFile200 = VectorStoreFileObject +export const CreateVectorStoreFile200 = VectorStoreFileObject +export type CreateVectorStoreFile400 = ErrorResponse +export const CreateVectorStoreFile400 = ErrorResponse +export type CreateVectorStoreFile404 = ErrorResponse +export const CreateVectorStoreFile404 = ErrorResponse +export type CreateVectorStoreFile409 = ErrorResponse +export const CreateVectorStoreFile409 = ErrorResponse +export type CreateVectorStoreFile429 = ErrorResponse +export const CreateVectorStoreFile429 = ErrorResponse +export type CreateVectorStoreFile500 = ErrorResponse +export const CreateVectorStoreFile500 = ErrorResponse +export type GetVectorStoreFile200 = VectorStoreFileObject +export const GetVectorStoreFile200 = VectorStoreFileObject +export type GetVectorStoreFile404 = ErrorResponse +export const GetVectorStoreFile404 = ErrorResponse +export type GetVectorStoreFile429 = ErrorResponse +export const GetVectorStoreFile429 = ErrorResponse +export type GetVectorStoreFile500 = ErrorResponse +export const GetVectorStoreFile500 = ErrorResponse +export type UpdateVectorStoreFileAttributesRequestJson = UpdateVectorStoreFileAttributesRequest +export const UpdateVectorStoreFileAttributesRequestJson = UpdateVectorStoreFileAttributesRequest +export type UpdateVectorStoreFileAttributes200 = VectorStoreFileObject +export const UpdateVectorStoreFileAttributes200 = VectorStoreFileObject +export type UpdateVectorStoreFileAttributes400 = ErrorResponse +export const UpdateVectorStoreFileAttributes400 = ErrorResponse +export type UpdateVectorStoreFileAttributes404 = ErrorResponse +export const UpdateVectorStoreFileAttributes404 = ErrorResponse +export type UpdateVectorStoreFileAttributes409 = ErrorResponse +export const UpdateVectorStoreFileAttributes409 = ErrorResponse +export type UpdateVectorStoreFileAttributes429 = ErrorResponse +export const UpdateVectorStoreFileAttributes429 = ErrorResponse +export type UpdateVectorStoreFileAttributes500 = ErrorResponse +export const UpdateVectorStoreFileAttributes500 = ErrorResponse +export type DeleteVectorStoreFile200 = DeleteVectorStoreFileResponse +export const DeleteVectorStoreFile200 = DeleteVectorStoreFileResponse +export type DeleteVectorStoreFile400 = ErrorResponse +export const DeleteVectorStoreFile400 = ErrorResponse +export type DeleteVectorStoreFile404 = ErrorResponse +export const DeleteVectorStoreFile404 = ErrorResponse +export type DeleteVectorStoreFile409 = ErrorResponse +export const DeleteVectorStoreFile409 = ErrorResponse +export type DeleteVectorStoreFile429 = ErrorResponse +export const DeleteVectorStoreFile429 = ErrorResponse +export type DeleteVectorStoreFile500 = ErrorResponse +export const DeleteVectorStoreFile500 = ErrorResponse +export type RetrieveVectorStoreFileContent200 = VectorStoreFileContentResponse +export const RetrieveVectorStoreFileContent200 = VectorStoreFileContentResponse +export type RetrieveVectorStoreFileContent400 = ErrorResponse +export const RetrieveVectorStoreFileContent400 = ErrorResponse +export type RetrieveVectorStoreFileContent404 = ErrorResponse +export const RetrieveVectorStoreFileContent404 = ErrorResponse +export type RetrieveVectorStoreFileContent429 = ErrorResponse +export const RetrieveVectorStoreFileContent429 = ErrorResponse +export type RetrieveVectorStoreFileContent500 = ErrorResponse +export const RetrieveVectorStoreFileContent500 = ErrorResponse +export type SearchVectorStoreRequestJson = VectorStoreSearchRequest +export const SearchVectorStoreRequestJson = VectorStoreSearchRequest +export type SearchVectorStore200 = VectorStoreSearchResultsPage +export const SearchVectorStore200 = VectorStoreSearchResultsPage +export type SearchVectorStore400 = ErrorResponse +export const SearchVectorStore400 = ErrorResponse +export type SearchVectorStore404 = ErrorResponse +export const SearchVectorStore404 = ErrorResponse +export type SearchVectorStore429 = ErrorResponse +export const SearchVectorStore429 = ErrorResponse +export type CreateConversationRequestJson = CreateConversationBody +export const CreateConversationRequestJson = CreateConversationBody +export type CreateConversation200 = ConversationResource +export const CreateConversation200 = ConversationResource +export type CreateConversation400 = ErrorResponse +export const CreateConversation400 = ErrorResponse +export type CreateConversation429 = ErrorResponse +export const CreateConversation429 = ErrorResponse +export type CreateConversation500 = ErrorResponse +export const CreateConversation500 = ErrorResponse +export type GetConversation200 = ConversationResource +export const GetConversation200 = ConversationResource +export type GetConversation404 = ErrorResponse +export const GetConversation404 = ErrorResponse +export type GetConversation429 = ErrorResponse +export const GetConversation429 = ErrorResponse +export type UpdateConversationRequestJson = UpdateConversationBody +export const UpdateConversationRequestJson = UpdateConversationBody +export type UpdateConversation200 = ConversationResource +export const UpdateConversation200 = ConversationResource +export type UpdateConversation400 = ErrorResponse +export const UpdateConversation400 = ErrorResponse +export type UpdateConversation404 = ErrorResponse +export const UpdateConversation404 = ErrorResponse +export type UpdateConversation429 = ErrorResponse +export const UpdateConversation429 = ErrorResponse +export type UpdateConversation500 = ErrorResponse +export const UpdateConversation500 = ErrorResponse +export type DeleteConversation200 = DeletedConversationResource +export const DeleteConversation200 = DeletedConversationResource +export type DeleteConversation404 = ErrorResponse +export const DeleteConversation404 = ErrorResponse +export type DeleteConversation429 = ErrorResponse +export const DeleteConversation429 = ErrorResponse +export type Getsafetycase200 = SafetyCaseResource +export const Getsafetycase200 = SafetyCaseResource +export type Getsafetycase400 = ErrorResponse +export const Getsafetycase400 = ErrorResponse +export type Getsafetycase404 = ErrorResponse +export const Getsafetycase404 = ErrorResponse +export type Getsafetycase429 = ErrorResponse +export const Getsafetycase429 = ErrorResponse +export type Getsafetycase500 = ErrorResponse +export const Getsafetycase500 = ErrorResponse +export type Getsafetycase503 = ErrorResponse +export const Getsafetycase503 = ErrorResponse +export type Getprojectsafetyalert200 = SafetyAlertResource +export const Getprojectsafetyalert200 = SafetyAlertResource +export type Getprojectsafetyalert400 = ErrorResponse +export const Getprojectsafetyalert400 = ErrorResponse +export type Getprojectsafetyalert404 = ErrorResponse +export const Getprojectsafetyalert404 = ErrorResponse +export type Getprojectsafetyalert429 = ErrorResponse +export const Getprojectsafetyalert429 = ErrorResponse +export type Getprojectsafetyalert503 = ErrorResponse +export const Getprojectsafetyalert503 = ErrorResponse +export type DownloadLiveRecording400 = ErrorResponse +export const DownloadLiveRecording400 = ErrorResponse +export type DownloadLiveRecording404 = ErrorResponse +export const DownloadLiveRecording404 = ErrorResponse +export type DownloadLiveRecording429 = ErrorResponse +export const DownloadLiveRecording429 = ErrorResponse +export type DownloadLiveRecording500 = ErrorResponse +export const DownloadLiveRecording500 = ErrorResponse +export type DownloadLiveRecording503 = ErrorResponse +export const DownloadLiveRecording503 = ErrorResponse +export type OrganizationDecisionsusageParams = { + readonly "start_time": number + readonly "end_time"?: number | null + readonly "bucket_width"?: DecisionsUsageBucketWidth | null + readonly "limit"?: number | null + readonly "page"?: string | null + readonly "project_ids"?: ReadonlyArray | null + readonly "group_by"?: ReadonlyArray | null + readonly "user_ids"?: ReadonlyArray | null + readonly "api_key_ids"?: ReadonlyArray | null + readonly "models"?: ReadonlyArray | null + readonly "batch"?: boolean | null +} +export const OrganizationDecisionsusageParams = Schema.Struct({ + "start_time": Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), + "end_time": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + ), + "bucket_width": Schema.optionalKey( + Schema.Union([ + Schema.Union([DecisionsUsageBucketWidth], { mode: "oneOf" }).annotate({ + "description": + "Width of each time bucket in response. Currently `1m`, `1h` and `1d` are supported, default to `1d`." + }), + Schema.Null + ]) + ), + "limit": Schema.optionalKey( + Schema.Union([Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })), Schema.Null]) + ), + "page": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ + "description": + "A cursor for use in pagination. Corresponding to the `next_page` field from the previous response." + }), + Schema.Null + ]) + ), + "project_ids": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.Array(Schema.String)], { mode: "oneOf" }).annotate({ + "description": "Return only usage for these projects." + }), + Schema.Null + ]) + ), + "group_by": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.Array(DecisionsUsageGroupBy)], { mode: "oneOf" }).annotate({ + "description": + "Group the usage data by the specified fields. Support fields include `project_id`, `user_id`, `api_key_id`, `model`, `batch`, `service_tier`, `api_source` or any combination of them. When grouped by `api_source`, results use `agents_api` for attributed Agents API activity and `unlabeled` for all other activity. Without source grouping, `api_source` is null." + }), + Schema.Null + ]) + ), + "user_ids": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.Array(Schema.String)], { mode: "oneOf" }).annotate({ + "description": "Return only usage for these users." + }), + Schema.Null + ]) + ), + "api_key_ids": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.Array(Schema.String)], { mode: "oneOf" }).annotate({ + "description": "Return only usage for these API keys." + }), + Schema.Null + ]) + ), + "models": Schema.optionalKey( + Schema.Union([ + Schema.Union([Schema.Array(Schema.String)], { mode: "oneOf" }).annotate({ + "description": "Return only usage for these models." + }), + Schema.Null + ]) + ), + "batch": Schema.optionalKey(Schema.Union([Schema.Boolean, Schema.Null])) +}) +export type OrganizationDecisionsusage200 = PublicDecisionsUsageResponseResource +export const OrganizationDecisionsusage200 = PublicDecisionsUsageResponseResource +export type OrganizationDecisionsusage400 = DecisionsUsageErrorResponse +export const OrganizationDecisionsusage400 = DecisionsUsageErrorResponse +export type OrganizationDecisionsusage403 = DecisionsUsagePermissionErrorResponse +export const OrganizationDecisionsusage403 = DecisionsUsagePermissionErrorResponse +export type OrganizationDecisionsusage429 = ErrorResponse +export const OrganizationDecisionsusage429 = ErrorResponse +export type ListexternalstorageconfigurationsParams = { + readonly "project_id"?: string | null + readonly "after"?: string | null + readonly "order"?: ExternalStorageOrder + readonly "limit"?: number +} +export const ListexternalstorageconfigurationsParams = Schema.Struct({ + "project_id": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])), + "after": Schema.optionalKey( + Schema.Union([ + Schema.String.annotate({ "description": "Return external storage configurations after this ID." }), + Schema.Null + ]) + ), + "order": Schema.optionalKey(ExternalStorageOrder), + "limit": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ) +}) +export type Listexternalstorageconfigurations200 = ExternalStorageListResource +export const Listexternalstorageconfigurations200 = ExternalStorageListResource +export type Listexternalstorageconfigurations400 = ErrorResponse +export const Listexternalstorageconfigurations400 = ErrorResponse +export type Listexternalstorageconfigurations403 = ErrorResponse +export const Listexternalstorageconfigurations403 = ErrorResponse +export type Listexternalstorageconfigurations404 = ErrorResponse +export const Listexternalstorageconfigurations404 = ErrorResponse +export type CreateanexternalstorageconfigurationRequestJson = CreateExternalStorageBody +export const CreateanexternalstorageconfigurationRequestJson = CreateExternalStorageBody +export type Createanexternalstorageconfiguration200 = ExternalStorageResponse +export const Createanexternalstorageconfiguration200 = ExternalStorageResponse +export type Createanexternalstorageconfiguration400 = ErrorResponse +export const Createanexternalstorageconfiguration400 = ErrorResponse +export type Createanexternalstorageconfiguration403 = ErrorResponse +export const Createanexternalstorageconfiguration403 = ErrorResponse +export type Createanexternalstorageconfiguration404 = ErrorResponse +export const Createanexternalstorageconfiguration404 = ErrorResponse +export type Createanexternalstorageconfiguration503 = ErrorResponse +export const Createanexternalstorageconfiguration503 = ErrorResponse +export type Getanexternalstorageconfiguration200 = ExternalStorageResponse +export const Getanexternalstorageconfiguration200 = ExternalStorageResponse +export type Getanexternalstorageconfiguration400 = ErrorResponse +export const Getanexternalstorageconfiguration400 = ErrorResponse +export type Getanexternalstorageconfiguration403 = ErrorResponse +export const Getanexternalstorageconfiguration403 = ErrorResponse +export type Getanexternalstorageconfiguration404 = ErrorResponse +export const Getanexternalstorageconfiguration404 = ErrorResponse +export type Deleteanexternalstorageconfiguration200 = ExternalStorageDeletedResource +export const Deleteanexternalstorageconfiguration200 = ExternalStorageDeletedResource +export type Deleteanexternalstorageconfiguration400 = ErrorResponse +export const Deleteanexternalstorageconfiguration400 = ErrorResponse +export type Deleteanexternalstorageconfiguration403 = ErrorResponse +export const Deleteanexternalstorageconfiguration403 = ErrorResponse +export type Deleteanexternalstorageconfiguration404 = ErrorResponse +export const Deleteanexternalstorageconfiguration404 = ErrorResponse +export type Validateanexternalstorageconfiguration200 = ExternalStorageResponse +export const Validateanexternalstorageconfiguration200 = ExternalStorageResponse +export type Validateanexternalstorageconfiguration400 = ErrorResponse +export const Validateanexternalstorageconfiguration400 = ErrorResponse +export type Validateanexternalstorageconfiguration403 = ErrorResponse +export const Validateanexternalstorageconfiguration403 = ErrorResponse +export type Validateanexternalstorageconfiguration404 = ErrorResponse +export const Validateanexternalstorageconfiguration404 = ErrorResponse +export type Validateanexternalstorageconfiguration503 = ErrorResponse +export const Validateanexternalstorageconfiguration503 = ErrorResponse +export type Getorganizationspendlimit200 = OrganizationSpendLimitResource +export const Getorganizationspendlimit200 = OrganizationSpendLimitResource +export type Getorganizationspendlimit403 = PermissionErrorResponse +export const Getorganizationspendlimit403 = PermissionErrorResponse +export type Getorganizationspendlimit404 = ErrorResponse +export const Getorganizationspendlimit404 = ErrorResponse +export type UpdateorganizationspendlimitRequestJson = UpdateOrganizationSpendLimitBody +export const UpdateorganizationspendlimitRequestJson = UpdateOrganizationSpendLimitBody +export type Updateorganizationspendlimit200 = OrganizationSpendLimitResource +export const Updateorganizationspendlimit200 = OrganizationSpendLimitResource +export type Updateorganizationspendlimit400 = ErrorResponse +export const Updateorganizationspendlimit400 = ErrorResponse +export type Updateorganizationspendlimit403 = PermissionErrorResponse +export const Updateorganizationspendlimit403 = PermissionErrorResponse +export type Deleteorganizationspendlimit200 = OrganizationSpendLimitDeletedResource +export const Deleteorganizationspendlimit200 = OrganizationSpendLimitDeletedResource +export type Deleteorganizationspendlimit403 = PermissionErrorResponse +export const Deleteorganizationspendlimit403 = PermissionErrorResponse +export type Deleteorganizationspendlimit404 = ErrorResponse +export const Deleteorganizationspendlimit404 = ErrorResponse +export type Getprojectspendlimit200 = ProjectSpendLimitResource +export const Getprojectspendlimit200 = ProjectSpendLimitResource +export type Getprojectspendlimit400 = ErrorResponse +export const Getprojectspendlimit400 = ErrorResponse +export type Getprojectspendlimit403 = PermissionErrorResponse +export const Getprojectspendlimit403 = PermissionErrorResponse +export type Getprojectspendlimit404 = ErrorResponse +export const Getprojectspendlimit404 = ErrorResponse +export type UpdateprojectspendlimitRequestJson = UpdateProjectSpendLimitBody +export const UpdateprojectspendlimitRequestJson = UpdateProjectSpendLimitBody +export type Updateprojectspendlimit200 = ProjectSpendLimitResource +export const Updateprojectspendlimit200 = ProjectSpendLimitResource +export type Updateprojectspendlimit400 = ErrorResponse +export const Updateprojectspendlimit400 = ErrorResponse +export type Updateprojectspendlimit403 = PermissionErrorResponse +export const Updateprojectspendlimit403 = PermissionErrorResponse +export type Updateprojectspendlimit404 = ErrorResponse +export const Updateprojectspendlimit404 = ErrorResponse +export type Deleteprojectspendlimit200 = ProjectSpendLimitDeletedResource +export const Deleteprojectspendlimit200 = ProjectSpendLimitDeletedResource +export type Deleteprojectspendlimit400 = ErrorResponse +export const Deleteprojectspendlimit400 = ErrorResponse +export type Deleteprojectspendlimit403 = PermissionErrorResponse +export const Deleteprojectspendlimit403 = PermissionErrorResponse +export type Deleteprojectspendlimit404 = ErrorResponse +export const Deleteprojectspendlimit404 = ErrorResponse +export type CreateanAPIkeyforaserviceaccountRequestJson = CreateProjectServiceAccountApiKeyBody +export const CreateanAPIkeyforaserviceaccountRequestJson = CreateProjectServiceAccountApiKeyBody +export type CreateanAPIkeyforaserviceaccount200 = ServiceAccountApiKeyBody +export const CreateanAPIkeyforaserviceaccount200 = ServiceAccountApiKeyBody +export type CreateanAPIkeyforaserviceaccount400 = ErrorResponse +export const CreateanAPIkeyforaserviceaccount400 = ErrorResponse +export type CreateanAPIkeyforaserviceaccount403 = PermissionErrorResponse +export const CreateanAPIkeyforaserviceaccount403 = PermissionErrorResponse +export type CreateanAPIkeyforaserviceaccount404 = ErrorResponse +export const CreateanAPIkeyforaserviceaccount404 = ErrorResponse +export type CreateanAPIkeyforaserviceaccount409 = ErrorResponse +export const CreateanAPIkeyforaserviceaccount409 = ErrorResponse +export type CreateanAPIkeyforaserviceaccount429 = ErrorResponse +export const CreateanAPIkeyforaserviceaccount429 = ErrorResponse +export type CreatecontentprovenancecheckRequestFormData = CreateContentProvenanceBodyMultipart +export const CreatecontentprovenancecheckRequestFormData = CreateContentProvenanceBodyMultipart +export type Createcontentprovenancecheck200 = ProvenanceResource +export const Createcontentprovenancecheck200 = ProvenanceResource +export type Createcontentprovenancecheck400 = ErrorResponse +export const Createcontentprovenancecheck400 = ErrorResponse +export type Createcontentprovenancecheck404 = ErrorResponse +export const Createcontentprovenancecheck404 = ErrorResponse +export type Createcontentprovenancecheck429 = ErrorResponse +export const Createcontentprovenancecheck429 = ErrorResponse +export type Createcontentprovenancecheck500 = ErrorResponse +export const Createcontentprovenancecheck500 = ErrorResponse +export type Createcontentprovenancecheck503 = ErrorResponse +export const Createcontentprovenancecheck503 = ErrorResponse export type ListVideosParams = { readonly "limit"?: number; readonly "order"?: OrderEnum; readonly "after"?: string } export const ListVideosParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) ), "order": Schema.optionalKey(OrderEnum), "after": Schema.optionalKey( @@ -30222,60 +49640,140 @@ export const ListVideosParams = Schema.Struct({ }) export type ListVideos200 = VideoListResource export const ListVideos200 = VideoListResource +export type ListVideos400 = ErrorResponse +export const ListVideos400 = ErrorResponse +export type ListVideos404 = ErrorResponse +export const ListVideos404 = ErrorResponse export type CreateVideoRequestJson = CreateVideoJsonBody export const CreateVideoRequestJson = CreateVideoJsonBody -export type CreateVideoRequestFormData = CreateVideoMultipartBody -export const CreateVideoRequestFormData = CreateVideoMultipartBody +export type CreateVideoRequestFormData = CreateVideoMultipartBodyMultipart +export const CreateVideoRequestFormData = CreateVideoMultipartBodyMultipart export type CreateVideo200 = VideoResource export const CreateVideo200 = VideoResource -export type CreateVideoCharacterRequestFormData = CreateVideoCharacterBody -export const CreateVideoCharacterRequestFormData = CreateVideoCharacterBody +export type CreateVideo400 = ErrorResponse +export const CreateVideo400 = ErrorResponse +export type CreateVideo404 = ErrorResponse +export const CreateVideo404 = ErrorResponse +export type CreateVideo429 = ErrorResponse +export const CreateVideo429 = ErrorResponse +export type CreateVideo500 = ErrorResponse +export const CreateVideo500 = ErrorResponse +export type CreateVideo503 = ErrorResponse +export const CreateVideo503 = ErrorResponse +export type CreateVideoCharacterRequestFormData = CreateVideoCharacterBodyMultipart +export const CreateVideoCharacterRequestFormData = CreateVideoCharacterBodyMultipart export type CreateVideoCharacter200 = VideoCharacterResource export const CreateVideoCharacter200 = VideoCharacterResource +export type CreateVideoCharacter400 = ErrorResponse +export const CreateVideoCharacter400 = ErrorResponse +export type CreateVideoCharacter404 = ErrorResponse +export const CreateVideoCharacter404 = ErrorResponse +export type CreateVideoCharacter500 = ErrorResponse +export const CreateVideoCharacter500 = ErrorResponse +export type CreateVideoCharacter504 = ErrorResponse +export const CreateVideoCharacter504 = ErrorResponse export type GetVideoCharacter200 = VideoCharacterResource export const GetVideoCharacter200 = VideoCharacterResource +export type GetVideoCharacter400 = ErrorResponse +export const GetVideoCharacter400 = ErrorResponse +export type GetVideoCharacter404 = ErrorResponse +export const GetVideoCharacter404 = ErrorResponse export type CreateVideoEditRequestJson = CreateVideoEditJsonBody export const CreateVideoEditRequestJson = CreateVideoEditJsonBody -export type CreateVideoEditRequestFormData = CreateVideoEditMultipartBody -export const CreateVideoEditRequestFormData = CreateVideoEditMultipartBody +export type CreateVideoEditRequestFormData = CreateVideoEditMultipartBodyMultipart +export const CreateVideoEditRequestFormData = CreateVideoEditMultipartBodyMultipart export type CreateVideoEdit200 = VideoResource export const CreateVideoEdit200 = VideoResource +export type CreateVideoEdit400 = ErrorResponse +export const CreateVideoEdit400 = ErrorResponse +export type CreateVideoEdit404 = ErrorResponse +export const CreateVideoEdit404 = ErrorResponse +export type CreateVideoEdit429 = ErrorResponse +export const CreateVideoEdit429 = ErrorResponse +export type CreateVideoEdit500 = ErrorResponse +export const CreateVideoEdit500 = ErrorResponse +export type CreateVideoEdit503 = ErrorResponse +export const CreateVideoEdit503 = ErrorResponse export type CreateVideoExtendRequestJson = CreateVideoExtendJsonBody export const CreateVideoExtendRequestJson = CreateVideoExtendJsonBody -export type CreateVideoExtendRequestFormData = CreateVideoExtendMultipartBody -export const CreateVideoExtendRequestFormData = CreateVideoExtendMultipartBody +export type CreateVideoExtendRequestFormData = CreateVideoExtendMultipartBodyMultipart +export const CreateVideoExtendRequestFormData = CreateVideoExtendMultipartBodyMultipart export type CreateVideoExtend200 = VideoResource export const CreateVideoExtend200 = VideoResource +export type CreateVideoExtend400 = ErrorResponse +export const CreateVideoExtend400 = ErrorResponse +export type CreateVideoExtend404 = ErrorResponse +export const CreateVideoExtend404 = ErrorResponse +export type CreateVideoExtend429 = ErrorResponse +export const CreateVideoExtend429 = ErrorResponse +export type CreateVideoExtend500 = ErrorResponse +export const CreateVideoExtend500 = ErrorResponse +export type CreateVideoExtend503 = ErrorResponse +export const CreateVideoExtend503 = ErrorResponse export type GetVideo200 = VideoResource export const GetVideo200 = VideoResource +export type GetVideo400 = ErrorResponse +export const GetVideo400 = ErrorResponse +export type GetVideo404 = ErrorResponse +export const GetVideo404 = ErrorResponse export type DeleteVideo200 = DeletedVideoResource export const DeleteVideo200 = DeletedVideoResource +export type DeleteVideo400 = ErrorResponse +export const DeleteVideo400 = ErrorResponse +export type DeleteVideo404 = ErrorResponse +export const DeleteVideo404 = ErrorResponse +export type DeleteVideo500 = ErrorResponse +export const DeleteVideo500 = ErrorResponse export type RetrieveVideoContentParams = { readonly "variant"?: VideoContentVariant } export const RetrieveVideoContentParams = Schema.Struct({ "variant": Schema.optionalKey(VideoContentVariant) }) export type RetrieveVideoContent200 = string export const RetrieveVideoContent200 = Schema.String +export type RetrieveVideoContent400 = ErrorResponse +export const RetrieveVideoContent400 = ErrorResponse +export type RetrieveVideoContent404 = ErrorResponse +export const RetrieveVideoContent404 = ErrorResponse +export type RetrieveVideoContent500 = ErrorResponse +export const RetrieveVideoContent500 = ErrorResponse export type CreateVideoRemixRequestJson = CreateVideoRemixBody export const CreateVideoRemixRequestJson = CreateVideoRemixBody export type CreateVideoRemixRequestFormData = CreateVideoRemixBody export const CreateVideoRemixRequestFormData = CreateVideoRemixBody export type CreateVideoRemix200 = VideoResource export const CreateVideoRemix200 = VideoResource +export type CreateVideoRemix400 = ErrorResponse +export const CreateVideoRemix400 = ErrorResponse +export type CreateVideoRemix404 = ErrorResponse +export const CreateVideoRemix404 = ErrorResponse +export type CreateVideoRemix429 = ErrorResponse +export const CreateVideoRemix429 = ErrorResponse +export type CreateVideoRemix500 = ErrorResponse +export const CreateVideoRemix500 = ErrorResponse +export type CreateVideoRemix503 = ErrorResponse +export const CreateVideoRemix503 = ErrorResponse export type GetinputtokencountsRequestJson = TokenCountsBody export const GetinputtokencountsRequestJson = TokenCountsBody -export type GetinputtokencountsRequestFormUrlEncoded = TokenCountsBody -export const GetinputtokencountsRequestFormUrlEncoded = TokenCountsBody export type Getinputtokencounts200 = TokenCountsResource export const Getinputtokencounts200 = TokenCountsResource +export type Getinputtokencounts400 = ErrorResponse +export const Getinputtokencounts400 = ErrorResponse +export type Getinputtokencounts429 = ErrorResponse +export const Getinputtokencounts429 = ErrorResponse export type CompactconversationRequestJson = CompactResponseMethodPublicBody export const CompactconversationRequestJson = CompactResponseMethodPublicBody -export type CompactconversationRequestFormUrlEncoded = CompactResponseMethodPublicBody -export const CompactconversationRequestFormUrlEncoded = CompactResponseMethodPublicBody export type Compactconversation200 = CompactResource export const Compactconversation200 = CompactResource +export type Compactconversation400 = ErrorResponse +export const Compactconversation400 = ErrorResponse +export type Compactconversation429 = ErrorResponse +export const Compactconversation429 = ErrorResponse +export type Compactconversation503 = ErrorResponse +export const Compactconversation503 = ErrorResponse export type ListSkillsParams = { readonly "limit"?: number; readonly "order"?: OrderEnum; readonly "after"?: string } export const ListSkillsParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) ), "order": Schema.optionalKey(OrderEnum), "after": Schema.optionalKey( @@ -30284,24 +49782,50 @@ export const ListSkillsParams = Schema.Struct({ }) export type ListSkills200 = SkillListResource export const ListSkills200 = SkillListResource +export type ListSkills404 = ErrorResponse +export const ListSkills404 = ErrorResponse +export type ListSkills429 = ErrorResponse +export const ListSkills429 = ErrorResponse export type CreateSkillRequestJson = CreateSkillBody export const CreateSkillRequestJson = CreateSkillBody -export type CreateSkillRequestFormData = CreateSkillBody -export const CreateSkillRequestFormData = CreateSkillBody +export type CreateSkillRequestFormData = CreateSkillBodyMultipart +export const CreateSkillRequestFormData = CreateSkillBodyMultipart export type CreateSkill200 = SkillResource export const CreateSkill200 = SkillResource +export type CreateSkill400 = ErrorResponse +export const CreateSkill400 = ErrorResponse +export type CreateSkill429 = ErrorResponse +export const CreateSkill429 = ErrorResponse +export type CreateSkill500 = ErrorResponse +export const CreateSkill500 = ErrorResponse export type GetSkill200 = SkillResource export const GetSkill200 = SkillResource +export type GetSkill404 = ErrorResponse +export const GetSkill404 = ErrorResponse +export type GetSkill429 = ErrorResponse +export const GetSkill429 = ErrorResponse export type UpdateSkillDefaultVersionRequestJson = SetDefaultSkillVersionBody export const UpdateSkillDefaultVersionRequestJson = SetDefaultSkillVersionBody -export type UpdateSkillDefaultVersionRequestFormUrlEncoded = SetDefaultSkillVersionBody -export const UpdateSkillDefaultVersionRequestFormUrlEncoded = SetDefaultSkillVersionBody export type UpdateSkillDefaultVersion200 = SkillResource export const UpdateSkillDefaultVersion200 = SkillResource +export type UpdateSkillDefaultVersion400 = ErrorResponse +export const UpdateSkillDefaultVersion400 = ErrorResponse +export type UpdateSkillDefaultVersion404 = ErrorResponse +export const UpdateSkillDefaultVersion404 = ErrorResponse +export type UpdateSkillDefaultVersion429 = ErrorResponse +export const UpdateSkillDefaultVersion429 = ErrorResponse export type DeleteSkill200 = DeletedSkillResource export const DeleteSkill200 = DeletedSkillResource +export type DeleteSkill404 = ErrorResponse +export const DeleteSkill404 = ErrorResponse +export type DeleteSkill429 = ErrorResponse +export const DeleteSkill429 = ErrorResponse export type GetSkillContent200 = string export const GetSkillContent200 = Schema.String +export type GetSkillContent404 = ErrorResponse +export const GetSkillContent404 = ErrorResponse +export type GetSkillContent429 = ErrorResponse +export const GetSkillContent429 = ErrorResponse export type ListSkillVersionsParams = { readonly "limit"?: number readonly "order"?: OrderEnum @@ -30309,31 +49833,77 @@ export type ListSkillVersionsParams = { } export const ListSkillVersionsParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) ), "order": Schema.optionalKey(OrderEnum), "after": Schema.optionalKey(Schema.String) }) export type ListSkillVersions200 = SkillVersionListResource export const ListSkillVersions200 = SkillVersionListResource +export type ListSkillVersions400 = ErrorResponse +export const ListSkillVersions400 = ErrorResponse +export type ListSkillVersions404 = ErrorResponse +export const ListSkillVersions404 = ErrorResponse +export type ListSkillVersions429 = ErrorResponse +export const ListSkillVersions429 = ErrorResponse export type CreateSkillVersionRequestJson = CreateSkillVersionBody export const CreateSkillVersionRequestJson = CreateSkillVersionBody -export type CreateSkillVersionRequestFormData = CreateSkillVersionBody -export const CreateSkillVersionRequestFormData = CreateSkillVersionBody +export type CreateSkillVersionRequestFormData = CreateSkillVersionBodyMultipart +export const CreateSkillVersionRequestFormData = CreateSkillVersionBodyMultipart export type CreateSkillVersion200 = SkillVersionResource export const CreateSkillVersion200 = SkillVersionResource +export type CreateSkillVersion400 = ErrorResponse +export const CreateSkillVersion400 = ErrorResponse +export type CreateSkillVersion404 = ErrorResponse +export const CreateSkillVersion404 = ErrorResponse +export type CreateSkillVersion429 = ErrorResponse +export const CreateSkillVersion429 = ErrorResponse +export type CreateSkillVersion500 = ErrorResponse +export const CreateSkillVersion500 = ErrorResponse export type GetSkillVersion200 = SkillVersionResource export const GetSkillVersion200 = SkillVersionResource +export type GetSkillVersion400 = ErrorResponse +export const GetSkillVersion400 = ErrorResponse +export type GetSkillVersion404 = ErrorResponse +export const GetSkillVersion404 = ErrorResponse +export type GetSkillVersion429 = ErrorResponse +export const GetSkillVersion429 = ErrorResponse export type DeleteSkillVersion200 = DeletedSkillVersionResource export const DeleteSkillVersion200 = DeletedSkillVersionResource +export type DeleteSkillVersion400 = ErrorResponse +export const DeleteSkillVersion400 = ErrorResponse +export type DeleteSkillVersion404 = ErrorResponse +export const DeleteSkillVersion404 = ErrorResponse +export type DeleteSkillVersion429 = ErrorResponse +export const DeleteSkillVersion429 = ErrorResponse export type GetSkillVersionContent200 = string export const GetSkillVersionContent200 = Schema.String +export type GetSkillVersionContent400 = ErrorResponse +export const GetSkillVersionContent400 = ErrorResponse +export type GetSkillVersionContent404 = ErrorResponse +export const GetSkillVersionContent404 = ErrorResponse +export type GetSkillVersionContent429 = ErrorResponse +export const GetSkillVersionContent429 = ErrorResponse export type CancelChatSessionMethod200 = ChatSessionResource export const CancelChatSessionMethod200 = ChatSessionResource +export type CancelChatSessionMethod400 = ErrorResponse +export const CancelChatSessionMethod400 = ErrorResponse +export type CancelChatSessionMethod404 = ErrorResponse +export const CancelChatSessionMethod404 = ErrorResponse +export type CancelChatSessionMethod429 = ErrorResponse +export const CancelChatSessionMethod429 = ErrorResponse export type CreateChatSessionMethodRequestJson = CreateChatSessionBody export const CreateChatSessionMethodRequestJson = CreateChatSessionBody export type CreateChatSessionMethod200 = ChatSessionResource export const CreateChatSessionMethod200 = ChatSessionResource +export type CreateChatSessionMethod400 = ErrorResponse +export const CreateChatSessionMethod400 = ErrorResponse +export type CreateChatSessionMethod404 = ErrorResponse +export const CreateChatSessionMethod404 = ErrorResponse +export type CreateChatSessionMethod429 = ErrorResponse +export const CreateChatSessionMethod429 = ErrorResponse export type ListThreadItemsMethodParams = { readonly "limit"?: number readonly "order"?: OrderEnum @@ -30342,7 +49912,9 @@ export type ListThreadItemsMethodParams = { } export const ListThreadItemsMethodParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) ), "order": Schema.optionalKey(OrderEnum), "after": Schema.optionalKey( @@ -30358,10 +49930,28 @@ export const ListThreadItemsMethodParams = Schema.Struct({ }) export type ListThreadItemsMethod200 = ThreadItemListResource export const ListThreadItemsMethod200 = ThreadItemListResource +export type ListThreadItemsMethod400 = ErrorResponse +export const ListThreadItemsMethod400 = ErrorResponse +export type ListThreadItemsMethod404 = ErrorResponse +export const ListThreadItemsMethod404 = ErrorResponse +export type ListThreadItemsMethod429 = ErrorResponse +export const ListThreadItemsMethod429 = ErrorResponse export type GetThreadMethod200 = ThreadResource export const GetThreadMethod200 = ThreadResource +export type GetThreadMethod400 = ErrorResponse +export const GetThreadMethod400 = ErrorResponse +export type GetThreadMethod404 = ErrorResponse +export const GetThreadMethod404 = ErrorResponse +export type GetThreadMethod429 = ErrorResponse +export const GetThreadMethod429 = ErrorResponse export type DeleteThreadMethod200 = DeletedThreadResource export const DeleteThreadMethod200 = DeletedThreadResource +export type DeleteThreadMethod400 = ErrorResponse +export const DeleteThreadMethod400 = ErrorResponse +export type DeleteThreadMethod404 = ErrorResponse +export const DeleteThreadMethod404 = ErrorResponse +export type DeleteThreadMethod429 = ErrorResponse +export const DeleteThreadMethod429 = ErrorResponse export type ListThreadsMethodParams = { readonly "limit"?: number readonly "order"?: OrderEnum @@ -30371,7 +49961,9 @@ export type ListThreadsMethodParams = { } export const ListThreadsMethodParams = Schema.Struct({ "limit": Schema.optionalKey( - Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0)).check(Schema.isLessThanOrEqualTo(100)) + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(0).annotate({ "expected": "a value greater than or equal to 0" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) ), "order": Schema.optionalKey(OrderEnum), "after": Schema.optionalKey( @@ -30387,11 +49979,1368 @@ export const ListThreadsMethodParams = Schema.Struct({ "user": Schema.optionalKey( Schema.String.annotate({ "description": "Filter threads that belong to this user identifier. Defaults to null to return all users." - }).check(Schema.isMinLength(1)).check(Schema.isMaxLength(512)) + }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" }) + ) ) }) export type ListThreadsMethod200 = ThreadListResource export const ListThreadsMethod200 = ThreadListResource +export type ListThreadsMethod400 = ErrorResponse +export const ListThreadsMethod400 = ErrorResponse +export type ListThreadsMethod404 = ErrorResponse +export const ListThreadsMethod404 = ErrorResponse +export type ListThreadsMethod429 = ErrorResponse +export const ListThreadsMethod429 = ErrorResponse +export type CreateDecisionRequestJson = DecisionRequest +export const CreateDecisionRequestJson = DecisionRequest +export type CreateDecision200 = DecisionResponse +export const CreateDecision200 = DecisionResponse +export type ListAgentEnvironmentsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string + readonly "type"?: EnvironmentTypeParam +} +export const ListAgentEnvironmentsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "type": Schema.optionalKey(EnvironmentTypeParam) +}) +export type ListAgentEnvironments200 = AgentEnvironmentListResource +export const ListAgentEnvironments200 = Schema.suspend((): Schema.Codec => + AgentEnvironmentListResource +).annotate({ "description": "An ID-paginated list of owned environments." }) +export type ListAgentEnvironments400 = ErrorResponse_2 +export const ListAgentEnvironments400 = ErrorResponse_2 +export type ListAgentEnvironments401 = ErrorResponse_2 +export const ListAgentEnvironments401 = ErrorResponse_2 +export type ListAgentEnvironments403 = ErrorResponse_2 +export const ListAgentEnvironments403 = ErrorResponse_2 +export type ListAgentEnvironments404 = ErrorResponse_2 +export const ListAgentEnvironments404 = ErrorResponse_2 +export type ListAgentEnvironments409 = ErrorResponse_2 +export const ListAgentEnvironments409 = ErrorResponse_2 +export type ListAgentEnvironments500 = ErrorResponse_2 +export const ListAgentEnvironments500 = ErrorResponse_2 +export type ListAgentEnvironments503 = ErrorResponse_2 +export const ListAgentEnvironments503 = ErrorResponse_2 +export type CreateAgentEnvironmentParams2 = { readonly "Idempotency-Key"?: string } +export const CreateAgentEnvironmentParams2 = Schema.Struct({ + "Idempotency-Key": Schema.optionalKey( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ) + ) +}) +export type CreateAgentEnvironmentRequestJson = CreateAgentEnvironmentParams +export const CreateAgentEnvironmentRequestJson = CreateAgentEnvironmentParams +export type CreateAgentEnvironment201 = PublicEnvironmentResource +export const CreateAgentEnvironment201 = PublicEnvironmentResource +export type CreateAgentEnvironment400 = ErrorResponse_2 +export const CreateAgentEnvironment400 = ErrorResponse_2 +export type CreateAgentEnvironment401 = ErrorResponse_2 +export const CreateAgentEnvironment401 = ErrorResponse_2 +export type CreateAgentEnvironment403 = ErrorResponse_2 +export const CreateAgentEnvironment403 = ErrorResponse_2 +export type CreateAgentEnvironment404 = ErrorResponse_2 +export const CreateAgentEnvironment404 = ErrorResponse_2 +export type CreateAgentEnvironment409 = ErrorResponse_2 +export const CreateAgentEnvironment409 = ErrorResponse_2 +export type CreateAgentEnvironment429 = ErrorResponse_2 +export const CreateAgentEnvironment429 = ErrorResponse_2 +export type CreateAgentEnvironment500 = ErrorResponse_2 +export const CreateAgentEnvironment500 = ErrorResponse_2 +export type CreateAgentEnvironment503 = ErrorResponse_2 +export const CreateAgentEnvironment503 = ErrorResponse_2 +export type RetrieveAgentEnvironment200 = PublicEnvironmentResource +export const RetrieveAgentEnvironment200 = PublicEnvironmentResource +export type RetrieveAgentEnvironment400 = ErrorResponse_2 +export const RetrieveAgentEnvironment400 = ErrorResponse_2 +export type RetrieveAgentEnvironment401 = ErrorResponse_2 +export const RetrieveAgentEnvironment401 = ErrorResponse_2 +export type RetrieveAgentEnvironment403 = ErrorResponse_2 +export const RetrieveAgentEnvironment403 = ErrorResponse_2 +export type RetrieveAgentEnvironment404 = ErrorResponse_2 +export const RetrieveAgentEnvironment404 = ErrorResponse_2 +export type RetrieveAgentEnvironment409 = ErrorResponse_2 +export const RetrieveAgentEnvironment409 = ErrorResponse_2 +export type RetrieveAgentEnvironment500 = ErrorResponse_2 +export const RetrieveAgentEnvironment500 = ErrorResponse_2 +export type RetrieveAgentEnvironment503 = ErrorResponse_2 +export const RetrieveAgentEnvironment503 = ErrorResponse_2 +export type ListAgentEnvironmentFilesParams = { + readonly "path"?: string | null + readonly "limit"?: number | null + readonly "order"?: ListOrderParam + readonly "page"?: string +} +export const ListAgentEnvironmentFilesParams = Schema.Struct({ + "path": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]) + ), + "limit": Schema.optionalKey( + Schema.Union([ + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })), + Schema.Null + ]).annotate({ "format": "int64" }) + ), + "order": Schema.optionalKey(ListOrderParam), + "page": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentEnvironmentFiles200 = EnvironmentFileListResource +export const ListAgentEnvironmentFiles200 = EnvironmentFileListResource +export type ListAgentEnvironmentFiles400 = ErrorResponse_2 +export const ListAgentEnvironmentFiles400 = ErrorResponse_2 +export type ListAgentEnvironmentFiles401 = ErrorResponse_2 +export const ListAgentEnvironmentFiles401 = ErrorResponse_2 +export type ListAgentEnvironmentFiles403 = ErrorResponse_2 +export const ListAgentEnvironmentFiles403 = ErrorResponse_2 +export type ListAgentEnvironmentFiles404 = ErrorResponse_2 +export const ListAgentEnvironmentFiles404 = ErrorResponse_2 +export type ListAgentEnvironmentFiles409 = ErrorResponse_2 +export const ListAgentEnvironmentFiles409 = ErrorResponse_2 +export type ListAgentEnvironmentFiles500 = ErrorResponse_2 +export const ListAgentEnvironmentFiles500 = ErrorResponse_2 +export type ListAgentEnvironmentFiles503 = ErrorResponse_2 +export const ListAgentEnvironmentFiles503 = ErrorResponse_2 +export type CreateAgentEnvironmentFileRequestJson = HostedEnvironmentFileParam +export const CreateAgentEnvironmentFileRequestJson = HostedEnvironmentFileParam +export type CreateAgentEnvironmentFile201 = EnvironmentFileResource +export const CreateAgentEnvironmentFile201 = EnvironmentFileResource +export type CreateAgentEnvironmentFile400 = ErrorResponse_2 +export const CreateAgentEnvironmentFile400 = ErrorResponse_2 +export type CreateAgentEnvironmentFile401 = ErrorResponse_2 +export const CreateAgentEnvironmentFile401 = ErrorResponse_2 +export type CreateAgentEnvironmentFile403 = ErrorResponse_2 +export const CreateAgentEnvironmentFile403 = ErrorResponse_2 +export type CreateAgentEnvironmentFile404 = ErrorResponse_2 +export const CreateAgentEnvironmentFile404 = ErrorResponse_2 +export type CreateAgentEnvironmentFile409 = ErrorResponse_2 +export const CreateAgentEnvironmentFile409 = ErrorResponse_2 +export type CreateAgentEnvironmentFile429 = ErrorResponse_2 +export const CreateAgentEnvironmentFile429 = ErrorResponse_2 +export type CreateAgentEnvironmentFile500 = ErrorResponse_2 +export const CreateAgentEnvironmentFile500 = ErrorResponse_2 +export type CreateAgentEnvironmentFile503 = ErrorResponse_2 +export const CreateAgentEnvironmentFile503 = ErrorResponse_2 +export type ListAgentSessionSubagentsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentSessionSubagentsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessionSubagents200 = { + readonly "object": "list" + readonly "data": ReadonlyArray + readonly "first_id": string | null + readonly "last_id": string | null + readonly "has_more": boolean +} +export const ListAgentSessionSubagents200 = Schema.Struct({ + "object": Schema.Literal("list").annotate({ "description": "The object type, which is always `list`." }), + "data": Schema.Array(SubagentResource).annotate({ + "description": "The resources returned in this page, in the requested sort order." + }).check(Schema.isMinLength(0).annotate({ "expected": "a value with a length of at least 0" })).check( + Schema.isMaxLength(2000).annotate({ "expected": "a value with a length of at most 2000" }) + ), + "first_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ "description": "The ID of the first resource in `data`, or `null` if the page is empty." }), + "last_id": Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })), + Schema.Null + ]).annotate({ + "description": + "The ID of the last resource in `data`, or `null` if the page is empty. Pass this as `after` with the same order and filters." + }), + "has_more": Schema.Boolean.annotate({ + "description": "Whether there are more resources to retrieve after this page." + }) +}).annotate({ "description": "A page of Agents API resources, with IDs for retrieving additional pages." }) +export type ListAgentSessionSubagents400 = ErrorResponse_2 +export const ListAgentSessionSubagents400 = ErrorResponse_2 +export type ListAgentSessionSubagents401 = ErrorResponse_2 +export const ListAgentSessionSubagents401 = ErrorResponse_2 +export type ListAgentSessionSubagents403 = ErrorResponse_2 +export const ListAgentSessionSubagents403 = ErrorResponse_2 +export type ListAgentSessionSubagents404 = ErrorResponse_2 +export const ListAgentSessionSubagents404 = ErrorResponse_2 +export type ListAgentSessionSubagents409 = ErrorResponse_2 +export const ListAgentSessionSubagents409 = ErrorResponse_2 +export type ListAgentSessionSubagents500 = ErrorResponse_2 +export const ListAgentSessionSubagents500 = ErrorResponse_2 +export type ListAgentSessionSubagents503 = ErrorResponse_2 +export const ListAgentSessionSubagents503 = ErrorResponse_2 +export type RetrieveAgentSessionSubagent200 = SubagentResource +export const RetrieveAgentSessionSubagent200 = SubagentResource +export type RetrieveAgentSessionSubagent400 = ErrorResponse_2 +export const RetrieveAgentSessionSubagent400 = ErrorResponse_2 +export type RetrieveAgentSessionSubagent401 = ErrorResponse_2 +export const RetrieveAgentSessionSubagent401 = ErrorResponse_2 +export type RetrieveAgentSessionSubagent403 = ErrorResponse_2 +export const RetrieveAgentSessionSubagent403 = ErrorResponse_2 +export type RetrieveAgentSessionSubagent404 = ErrorResponse_2 +export const RetrieveAgentSessionSubagent404 = ErrorResponse_2 +export type RetrieveAgentSessionSubagent409 = ErrorResponse_2 +export const RetrieveAgentSessionSubagent409 = ErrorResponse_2 +export type RetrieveAgentSessionSubagent500 = ErrorResponse_2 +export const RetrieveAgentSessionSubagent500 = ErrorResponse_2 +export type RetrieveAgentSessionSubagent503 = ErrorResponse_2 +export const RetrieveAgentSessionSubagent503 = ErrorResponse_2 +export type ListAgentSessionSubagentItemsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentSessionSubagentItemsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessionSubagentItems200 = SessionItemListResource +export const ListAgentSessionSubagentItems200 = SessionItemListResource +export type ListAgentSessionSubagentItems400 = ErrorResponse_2 +export const ListAgentSessionSubagentItems400 = ErrorResponse_2 +export type ListAgentSessionSubagentItems401 = ErrorResponse_2 +export const ListAgentSessionSubagentItems401 = ErrorResponse_2 +export type ListAgentSessionSubagentItems403 = ErrorResponse_2 +export const ListAgentSessionSubagentItems403 = ErrorResponse_2 +export type ListAgentSessionSubagentItems404 = ErrorResponse_2 +export const ListAgentSessionSubagentItems404 = ErrorResponse_2 +export type ListAgentSessionSubagentItems409 = ErrorResponse_2 +export const ListAgentSessionSubagentItems409 = ErrorResponse_2 +export type ListAgentSessionSubagentItems500 = ErrorResponse_2 +export const ListAgentSessionSubagentItems500 = ErrorResponse_2 +export type ListAgentSessionSubagentItems503 = ErrorResponse_2 +export const ListAgentSessionSubagentItems503 = ErrorResponse_2 +export type ListAgentSessionSubagentTurnsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentSessionSubagentTurnsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessionSubagentTurns200 = SessionTurnListResource +export const ListAgentSessionSubagentTurns200 = Schema.suspend((): Schema.Codec => + SessionTurnListResource +).annotate({ "description": "A page of turns from an agent session or subagent." }) +export type ListAgentSessionSubagentTurns400 = ErrorResponse_2 +export const ListAgentSessionSubagentTurns400 = ErrorResponse_2 +export type ListAgentSessionSubagentTurns401 = ErrorResponse_2 +export const ListAgentSessionSubagentTurns401 = ErrorResponse_2 +export type ListAgentSessionSubagentTurns403 = ErrorResponse_2 +export const ListAgentSessionSubagentTurns403 = ErrorResponse_2 +export type ListAgentSessionSubagentTurns404 = ErrorResponse_2 +export const ListAgentSessionSubagentTurns404 = ErrorResponse_2 +export type ListAgentSessionSubagentTurns409 = ErrorResponse_2 +export const ListAgentSessionSubagentTurns409 = ErrorResponse_2 +export type ListAgentSessionSubagentTurns500 = ErrorResponse_2 +export const ListAgentSessionSubagentTurns500 = ErrorResponse_2 +export type ListAgentSessionSubagentTurns503 = ErrorResponse_2 +export const ListAgentSessionSubagentTurns503 = ErrorResponse_2 +export type RetrieveAgentSessionSubagentTurn200 = TurnResource +export const RetrieveAgentSessionSubagentTurn200 = TurnResource +export type RetrieveAgentSessionSubagentTurn400 = ErrorResponse_2 +export const RetrieveAgentSessionSubagentTurn400 = ErrorResponse_2 +export type RetrieveAgentSessionSubagentTurn401 = ErrorResponse_2 +export const RetrieveAgentSessionSubagentTurn401 = ErrorResponse_2 +export type RetrieveAgentSessionSubagentTurn403 = ErrorResponse_2 +export const RetrieveAgentSessionSubagentTurn403 = ErrorResponse_2 +export type RetrieveAgentSessionSubagentTurn404 = ErrorResponse_2 +export const RetrieveAgentSessionSubagentTurn404 = ErrorResponse_2 +export type RetrieveAgentSessionSubagentTurn409 = ErrorResponse_2 +export const RetrieveAgentSessionSubagentTurn409 = ErrorResponse_2 +export type RetrieveAgentSessionSubagentTurn500 = ErrorResponse_2 +export const RetrieveAgentSessionSubagentTurn500 = ErrorResponse_2 +export type RetrieveAgentSessionSubagentTurn503 = ErrorResponse_2 +export const RetrieveAgentSessionSubagentTurn503 = ErrorResponse_2 +export type ListAgentSessionSubagentTurnItemsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentSessionSubagentTurnItemsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessionSubagentTurnItems200 = SessionItemListResource +export const ListAgentSessionSubagentTurnItems200 = SessionItemListResource +export type ListAgentSessionSubagentTurnItems400 = ErrorResponse_2 +export const ListAgentSessionSubagentTurnItems400 = ErrorResponse_2 +export type ListAgentSessionSubagentTurnItems401 = ErrorResponse_2 +export const ListAgentSessionSubagentTurnItems401 = ErrorResponse_2 +export type ListAgentSessionSubagentTurnItems403 = ErrorResponse_2 +export const ListAgentSessionSubagentTurnItems403 = ErrorResponse_2 +export type ListAgentSessionSubagentTurnItems404 = ErrorResponse_2 +export const ListAgentSessionSubagentTurnItems404 = ErrorResponse_2 +export type ListAgentSessionSubagentTurnItems409 = ErrorResponse_2 +export const ListAgentSessionSubagentTurnItems409 = ErrorResponse_2 +export type ListAgentSessionSubagentTurnItems500 = ErrorResponse_2 +export const ListAgentSessionSubagentTurnItems500 = ErrorResponse_2 +export type ListAgentSessionSubagentTurnItems503 = ErrorResponse_2 +export const ListAgentSessionSubagentTurnItems503 = ErrorResponse_2 +export type ListAgentsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgents200 = AgentListResource +export const ListAgents200 = Schema.suspend((): Schema.Codec => AgentListResource).annotate({ + "description": "A page of reusable agents." +}) +export type ListAgents400 = ErrorResponse_2 +export const ListAgents400 = ErrorResponse_2 +export type ListAgents401 = ErrorResponse_2 +export const ListAgents401 = ErrorResponse_2 +export type ListAgents403 = ErrorResponse_2 +export const ListAgents403 = ErrorResponse_2 +export type ListAgents404 = ErrorResponse_2 +export const ListAgents404 = ErrorResponse_2 +export type ListAgents409 = ErrorResponse_2 +export const ListAgents409 = ErrorResponse_2 +export type ListAgents500 = ErrorResponse_2 +export const ListAgents500 = ErrorResponse_2 +export type ListAgents503 = ErrorResponse_2 +export const ListAgents503 = ErrorResponse_2 +export type CreateAgentRequestJson = CreateAgentParams +export const CreateAgentRequestJson = CreateAgentParams +export type CreateAgent201 = AgentResource +export const CreateAgent201 = AgentResource +export type CreateAgent400 = ErrorResponse_2 +export const CreateAgent400 = ErrorResponse_2 +export type CreateAgent401 = ErrorResponse_2 +export const CreateAgent401 = ErrorResponse_2 +export type CreateAgent403 = ErrorResponse_2 +export const CreateAgent403 = ErrorResponse_2 +export type CreateAgent404 = ErrorResponse_2 +export const CreateAgent404 = ErrorResponse_2 +export type CreateAgent409 = ErrorResponse_2 +export const CreateAgent409 = ErrorResponse_2 +export type CreateAgent500 = ErrorResponse_2 +export const CreateAgent500 = ErrorResponse_2 +export type CreateAgent503 = ErrorResponse_2 +export const CreateAgent503 = ErrorResponse_2 +export type RetrieveAgent200 = AgentResource +export const RetrieveAgent200 = AgentResource +export type RetrieveAgent400 = ErrorResponse_2 +export const RetrieveAgent400 = ErrorResponse_2 +export type RetrieveAgent401 = ErrorResponse_2 +export const RetrieveAgent401 = ErrorResponse_2 +export type RetrieveAgent403 = ErrorResponse_2 +export const RetrieveAgent403 = ErrorResponse_2 +export type RetrieveAgent404 = ErrorResponse_2 +export const RetrieveAgent404 = ErrorResponse_2 +export type RetrieveAgent409 = ErrorResponse_2 +export const RetrieveAgent409 = ErrorResponse_2 +export type RetrieveAgent500 = ErrorResponse_2 +export const RetrieveAgent500 = ErrorResponse_2 +export type RetrieveAgent503 = ErrorResponse_2 +export const RetrieveAgent503 = ErrorResponse_2 +export type UpdateAgentRequestJson = UpdateAgentParams +export const UpdateAgentRequestJson = UpdateAgentParams +export type UpdateAgent200 = AgentResource +export const UpdateAgent200 = AgentResource +export type UpdateAgent400 = ErrorResponse_2 +export const UpdateAgent400 = ErrorResponse_2 +export type UpdateAgent401 = ErrorResponse_2 +export const UpdateAgent401 = ErrorResponse_2 +export type UpdateAgent403 = ErrorResponse_2 +export const UpdateAgent403 = ErrorResponse_2 +export type UpdateAgent404 = ErrorResponse_2 +export const UpdateAgent404 = ErrorResponse_2 +export type UpdateAgent409 = ErrorResponse_2 +export const UpdateAgent409 = ErrorResponse_2 +export type UpdateAgent500 = ErrorResponse_2 +export const UpdateAgent500 = ErrorResponse_2 +export type UpdateAgent503 = ErrorResponse_2 +export const UpdateAgent503 = ErrorResponse_2 +export type DeleteAgent200 = DeletedAgentResource +export const DeleteAgent200 = DeletedAgentResource +export type DeleteAgent400 = ErrorResponse_2 +export const DeleteAgent400 = ErrorResponse_2 +export type DeleteAgent401 = ErrorResponse_2 +export const DeleteAgent401 = ErrorResponse_2 +export type DeleteAgent403 = ErrorResponse_2 +export const DeleteAgent403 = ErrorResponse_2 +export type DeleteAgent404 = ErrorResponse_2 +export const DeleteAgent404 = ErrorResponse_2 +export type DeleteAgent409 = ErrorResponse_2 +export const DeleteAgent409 = ErrorResponse_2 +export type DeleteAgent500 = ErrorResponse_2 +export const DeleteAgent500 = ErrorResponse_2 +export type DeleteAgent503 = ErrorResponse_2 +export const DeleteAgent503 = ErrorResponse_2 +export type ListAgentEnvironmentTemplatesParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentEnvironmentTemplatesParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentEnvironmentTemplates200 = EnvironmentTemplateListResource +export const ListAgentEnvironmentTemplates200 = Schema.suspend((): Schema.Codec => + EnvironmentTemplateListResource +).annotate({ "description": "A page of reusable environment templates." }) +export type ListAgentEnvironmentTemplates400 = ErrorResponse_2 +export const ListAgentEnvironmentTemplates400 = ErrorResponse_2 +export type ListAgentEnvironmentTemplates401 = ErrorResponse_2 +export const ListAgentEnvironmentTemplates401 = ErrorResponse_2 +export type ListAgentEnvironmentTemplates403 = ErrorResponse_2 +export const ListAgentEnvironmentTemplates403 = ErrorResponse_2 +export type ListAgentEnvironmentTemplates404 = ErrorResponse_2 +export const ListAgentEnvironmentTemplates404 = ErrorResponse_2 +export type ListAgentEnvironmentTemplates500 = ErrorResponse_2 +export const ListAgentEnvironmentTemplates500 = ErrorResponse_2 +export type ListAgentEnvironmentTemplates503 = ErrorResponse_2 +export const ListAgentEnvironmentTemplates503 = ErrorResponse_2 +export type CreateAgentEnvironmentTemplateRequestJson = CreateEnvironmentTemplateParams +export const CreateAgentEnvironmentTemplateRequestJson = CreateEnvironmentTemplateParams +export type CreateAgentEnvironmentTemplate201 = EnvironmentTemplateResource +export const CreateAgentEnvironmentTemplate201 = EnvironmentTemplateResource +export type CreateAgentEnvironmentTemplate400 = ErrorResponse_2 +export const CreateAgentEnvironmentTemplate400 = ErrorResponse_2 +export type CreateAgentEnvironmentTemplate401 = ErrorResponse_2 +export const CreateAgentEnvironmentTemplate401 = ErrorResponse_2 +export type CreateAgentEnvironmentTemplate403 = ErrorResponse_2 +export const CreateAgentEnvironmentTemplate403 = ErrorResponse_2 +export type CreateAgentEnvironmentTemplate404 = ErrorResponse_2 +export const CreateAgentEnvironmentTemplate404 = ErrorResponse_2 +export type CreateAgentEnvironmentTemplate500 = ErrorResponse_2 +export const CreateAgentEnvironmentTemplate500 = ErrorResponse_2 +export type CreateAgentEnvironmentTemplate503 = ErrorResponse_2 +export const CreateAgentEnvironmentTemplate503 = ErrorResponse_2 +export type RetrieveAgentEnvironmentTemplate200 = EnvironmentTemplateResource +export const RetrieveAgentEnvironmentTemplate200 = EnvironmentTemplateResource +export type RetrieveAgentEnvironmentTemplate400 = ErrorResponse_2 +export const RetrieveAgentEnvironmentTemplate400 = ErrorResponse_2 +export type RetrieveAgentEnvironmentTemplate401 = ErrorResponse_2 +export const RetrieveAgentEnvironmentTemplate401 = ErrorResponse_2 +export type RetrieveAgentEnvironmentTemplate403 = ErrorResponse_2 +export const RetrieveAgentEnvironmentTemplate403 = ErrorResponse_2 +export type RetrieveAgentEnvironmentTemplate404 = ErrorResponse_2 +export const RetrieveAgentEnvironmentTemplate404 = ErrorResponse_2 +export type RetrieveAgentEnvironmentTemplate500 = ErrorResponse_2 +export const RetrieveAgentEnvironmentTemplate500 = ErrorResponse_2 +export type RetrieveAgentEnvironmentTemplate503 = ErrorResponse_2 +export const RetrieveAgentEnvironmentTemplate503 = ErrorResponse_2 +export type UpdateAgentEnvironmentTemplateRequestJson = UpdateEnvironmentTemplateParams +export const UpdateAgentEnvironmentTemplateRequestJson = UpdateEnvironmentTemplateParams +export type UpdateAgentEnvironmentTemplate200 = EnvironmentTemplateResource +export const UpdateAgentEnvironmentTemplate200 = EnvironmentTemplateResource +export type UpdateAgentEnvironmentTemplate400 = ErrorResponse_2 +export const UpdateAgentEnvironmentTemplate400 = ErrorResponse_2 +export type UpdateAgentEnvironmentTemplate401 = ErrorResponse_2 +export const UpdateAgentEnvironmentTemplate401 = ErrorResponse_2 +export type UpdateAgentEnvironmentTemplate403 = ErrorResponse_2 +export const UpdateAgentEnvironmentTemplate403 = ErrorResponse_2 +export type UpdateAgentEnvironmentTemplate404 = ErrorResponse_2 +export const UpdateAgentEnvironmentTemplate404 = ErrorResponse_2 +export type UpdateAgentEnvironmentTemplate409 = ErrorResponse_2 +export const UpdateAgentEnvironmentTemplate409 = ErrorResponse_2 +export type UpdateAgentEnvironmentTemplate500 = ErrorResponse_2 +export const UpdateAgentEnvironmentTemplate500 = ErrorResponse_2 +export type UpdateAgentEnvironmentTemplate503 = ErrorResponse_2 +export const UpdateAgentEnvironmentTemplate503 = ErrorResponse_2 +export type DeleteAgentEnvironmentTemplate200 = DeletedEnvironmentTemplateResource +export const DeleteAgentEnvironmentTemplate200 = DeletedEnvironmentTemplateResource +export type DeleteAgentEnvironmentTemplate400 = ErrorResponse_2 +export const DeleteAgentEnvironmentTemplate400 = ErrorResponse_2 +export type DeleteAgentEnvironmentTemplate401 = ErrorResponse_2 +export const DeleteAgentEnvironmentTemplate401 = ErrorResponse_2 +export type DeleteAgentEnvironmentTemplate403 = ErrorResponse_2 +export const DeleteAgentEnvironmentTemplate403 = ErrorResponse_2 +export type DeleteAgentEnvironmentTemplate404 = ErrorResponse_2 +export const DeleteAgentEnvironmentTemplate404 = ErrorResponse_2 +export type DeleteAgentEnvironmentTemplate409 = ErrorResponse_2 +export const DeleteAgentEnvironmentTemplate409 = ErrorResponse_2 +export type DeleteAgentEnvironmentTemplate500 = ErrorResponse_2 +export const DeleteAgentEnvironmentTemplate500 = ErrorResponse_2 +export type DeleteAgentEnvironmentTemplate503 = ErrorResponse_2 +export const DeleteAgentEnvironmentTemplate503 = ErrorResponse_2 +export type ListAgentSessionsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string + readonly "agent_id"?: string +} +export const ListAgentSessionsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "agent_id": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessions200 = SessionListResource +export const ListAgentSessions200 = Schema.suspend((): Schema.Codec => SessionListResource) + .annotate({ "description": "A paginated list of sessions." }) +export type ListAgentSessions400 = ErrorResponse_2 +export const ListAgentSessions400 = ErrorResponse_2 +export type ListAgentSessions401 = ErrorResponse_2 +export const ListAgentSessions401 = ErrorResponse_2 +export type ListAgentSessions403 = ErrorResponse_2 +export const ListAgentSessions403 = ErrorResponse_2 +export type ListAgentSessions404 = ErrorResponse_2 +export const ListAgentSessions404 = ErrorResponse_2 +export type ListAgentSessions409 = ErrorResponse_2 +export const ListAgentSessions409 = ErrorResponse_2 +export type ListAgentSessions500 = ErrorResponse_2 +export const ListAgentSessions500 = ErrorResponse_2 +export type ListAgentSessions503 = ErrorResponse_2 +export const ListAgentSessions503 = ErrorResponse_2 +export type CreateAgentSessionRequestJson = CreateAgentSessionParams +export const CreateAgentSessionRequestJson = CreateAgentSessionParams +export type CreateAgentSession201 = SessionResource +export const CreateAgentSession201 = SessionResource +export type CreateAgentSession201Sse = SessionEvent +export const CreateAgentSession201Sse = SessionEvent +export type CreateAgentSession400 = ErrorResponse_2 +export const CreateAgentSession400 = ErrorResponse_2 +export type CreateAgentSession401 = ErrorResponse_2 +export const CreateAgentSession401 = ErrorResponse_2 +export type CreateAgentSession403 = ErrorResponse_2 +export const CreateAgentSession403 = ErrorResponse_2 +export type CreateAgentSession404 = ErrorResponse_2 +export const CreateAgentSession404 = ErrorResponse_2 +export type CreateAgentSession409 = ErrorResponse_2 +export const CreateAgentSession409 = ErrorResponse_2 +export type CreateAgentSession429 = ErrorResponse_2 +export const CreateAgentSession429 = ErrorResponse_2 +export type CreateAgentSession500 = ErrorResponse_2 +export const CreateAgentSession500 = ErrorResponse_2 +export type CreateAgentSession503 = ErrorResponse_2 +export const CreateAgentSession503 = ErrorResponse_2 +export type RetrieveAgentSession200 = SessionResource +export const RetrieveAgentSession200 = SessionResource +export type RetrieveAgentSession400 = ErrorResponse_2 +export const RetrieveAgentSession400 = ErrorResponse_2 +export type RetrieveAgentSession401 = ErrorResponse_2 +export const RetrieveAgentSession401 = ErrorResponse_2 +export type RetrieveAgentSession403 = ErrorResponse_2 +export const RetrieveAgentSession403 = ErrorResponse_2 +export type RetrieveAgentSession404 = ErrorResponse_2 +export const RetrieveAgentSession404 = ErrorResponse_2 +export type RetrieveAgentSession409 = ErrorResponse_2 +export const RetrieveAgentSession409 = ErrorResponse_2 +export type RetrieveAgentSession500 = ErrorResponse_2 +export const RetrieveAgentSession500 = ErrorResponse_2 +export type RetrieveAgentSession503 = ErrorResponse_2 +export const RetrieveAgentSession503 = ErrorResponse_2 +export type UpdateAgentSessionRequestJson = UpdateAgentSessionParams +export const UpdateAgentSessionRequestJson = UpdateAgentSessionParams +export type UpdateAgentSession200 = SessionResource +export const UpdateAgentSession200 = SessionResource +export type UpdateAgentSession400 = ErrorResponse_2 +export const UpdateAgentSession400 = ErrorResponse_2 +export type UpdateAgentSession401 = ErrorResponse_2 +export const UpdateAgentSession401 = ErrorResponse_2 +export type UpdateAgentSession403 = ErrorResponse_2 +export const UpdateAgentSession403 = ErrorResponse_2 +export type UpdateAgentSession404 = ErrorResponse_2 +export const UpdateAgentSession404 = ErrorResponse_2 +export type UpdateAgentSession409 = ErrorResponse_2 +export const UpdateAgentSession409 = ErrorResponse_2 +export type UpdateAgentSession500 = ErrorResponse_2 +export const UpdateAgentSession500 = ErrorResponse_2 +export type UpdateAgentSession503 = ErrorResponse_2 +export const UpdateAgentSession503 = ErrorResponse_2 +export type DeleteAgentSession200 = DeletedSessionResource +export const DeleteAgentSession200 = DeletedSessionResource +export type DeleteAgentSession400 = ErrorResponse_2 +export const DeleteAgentSession400 = ErrorResponse_2 +export type DeleteAgentSession401 = ErrorResponse_2 +export const DeleteAgentSession401 = ErrorResponse_2 +export type DeleteAgentSession403 = ErrorResponse_2 +export const DeleteAgentSession403 = ErrorResponse_2 +export type DeleteAgentSession404 = ErrorResponse_2 +export const DeleteAgentSession404 = ErrorResponse_2 +export type DeleteAgentSession409 = ErrorResponse_2 +export const DeleteAgentSession409 = ErrorResponse_2 +export type DeleteAgentSession500 = ErrorResponse_2 +export const DeleteAgentSession500 = ErrorResponse_2 +export type DeleteAgentSession503 = ErrorResponse_2 +export const DeleteAgentSession503 = ErrorResponse_2 +export type ListAgentSessionArtifactsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string + readonly "environment_id"?: string | null +} +export const ListAgentSessionArtifactsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "environment_id": Schema.optionalKey( + Schema.Union([ + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })), + Schema.Null + ]) + ) +}) +export type ListAgentSessionArtifacts200 = SessionArtifactListResource +export const ListAgentSessionArtifacts200 = Schema.suspend((): Schema.Codec => + SessionArtifactListResource +).annotate({ "description": "A page of durable artifacts published by a session." }) +export type ListAgentSessionArtifacts400 = ErrorResponse_2 +export const ListAgentSessionArtifacts400 = ErrorResponse_2 +export type ListAgentSessionArtifacts401 = ErrorResponse_2 +export const ListAgentSessionArtifacts401 = ErrorResponse_2 +export type ListAgentSessionArtifacts403 = ErrorResponse_2 +export const ListAgentSessionArtifacts403 = ErrorResponse_2 +export type ListAgentSessionArtifacts404 = ErrorResponse_2 +export const ListAgentSessionArtifacts404 = ErrorResponse_2 +export type ListAgentSessionArtifacts409 = ErrorResponse_2 +export const ListAgentSessionArtifacts409 = ErrorResponse_2 +export type ListAgentSessionArtifacts500 = ErrorResponse_2 +export const ListAgentSessionArtifacts500 = ErrorResponse_2 +export type ListAgentSessionArtifacts503 = ErrorResponse_2 +export const ListAgentSessionArtifacts503 = ErrorResponse_2 +export type RetrieveAgentSessionArtifact200 = SessionArtifactResource +export const RetrieveAgentSessionArtifact200 = SessionArtifactResource +export type RetrieveAgentSessionArtifact400 = ErrorResponse_2 +export const RetrieveAgentSessionArtifact400 = ErrorResponse_2 +export type RetrieveAgentSessionArtifact401 = ErrorResponse_2 +export const RetrieveAgentSessionArtifact401 = ErrorResponse_2 +export type RetrieveAgentSessionArtifact403 = ErrorResponse_2 +export const RetrieveAgentSessionArtifact403 = ErrorResponse_2 +export type RetrieveAgentSessionArtifact404 = ErrorResponse_2 +export const RetrieveAgentSessionArtifact404 = ErrorResponse_2 +export type RetrieveAgentSessionArtifact409 = ErrorResponse_2 +export const RetrieveAgentSessionArtifact409 = ErrorResponse_2 +export type RetrieveAgentSessionArtifact500 = ErrorResponse_2 +export const RetrieveAgentSessionArtifact500 = ErrorResponse_2 +export type RetrieveAgentSessionArtifact503 = ErrorResponse_2 +export const RetrieveAgentSessionArtifact503 = ErrorResponse_2 +export type DeleteAgentSessionArtifact200 = DeletedSessionArtifactResource +export const DeleteAgentSessionArtifact200 = DeletedSessionArtifactResource +export type DeleteAgentSessionArtifact400 = ErrorResponse_2 +export const DeleteAgentSessionArtifact400 = ErrorResponse_2 +export type DeleteAgentSessionArtifact401 = ErrorResponse_2 +export const DeleteAgentSessionArtifact401 = ErrorResponse_2 +export type DeleteAgentSessionArtifact403 = ErrorResponse_2 +export const DeleteAgentSessionArtifact403 = ErrorResponse_2 +export type DeleteAgentSessionArtifact404 = ErrorResponse_2 +export const DeleteAgentSessionArtifact404 = ErrorResponse_2 +export type DeleteAgentSessionArtifact409 = ErrorResponse_2 +export const DeleteAgentSessionArtifact409 = ErrorResponse_2 +export type DeleteAgentSessionArtifact500 = ErrorResponse_2 +export const DeleteAgentSessionArtifact500 = ErrorResponse_2 +export type DeleteAgentSessionArtifact503 = ErrorResponse_2 +export const DeleteAgentSessionArtifact503 = ErrorResponse_2 +export type RetrieveAgentSessionArtifactContent400 = ErrorResponse_2 +export const RetrieveAgentSessionArtifactContent400 = ErrorResponse_2 +export type RetrieveAgentSessionArtifactContent401 = ErrorResponse_2 +export const RetrieveAgentSessionArtifactContent401 = ErrorResponse_2 +export type RetrieveAgentSessionArtifactContent403 = ErrorResponse_2 +export const RetrieveAgentSessionArtifactContent403 = ErrorResponse_2 +export type RetrieveAgentSessionArtifactContent404 = ErrorResponse_2 +export const RetrieveAgentSessionArtifactContent404 = ErrorResponse_2 +export type RetrieveAgentSessionArtifactContent409 = ErrorResponse_2 +export const RetrieveAgentSessionArtifactContent409 = ErrorResponse_2 +export type RetrieveAgentSessionArtifactContent500 = ErrorResponse_2 +export const RetrieveAgentSessionArtifactContent500 = ErrorResponse_2 +export type RetrieveAgentSessionArtifactContent503 = ErrorResponse_2 +export const RetrieveAgentSessionArtifactContent503 = ErrorResponse_2 +export type ListAgentSessionEvents200Sse = SessionEvent +export const ListAgentSessionEvents200Sse = SessionEvent +export type ListAgentSessionEvents400 = ErrorResponse_2 +export const ListAgentSessionEvents400 = ErrorResponse_2 +export type ListAgentSessionEvents401 = ErrorResponse_2 +export const ListAgentSessionEvents401 = ErrorResponse_2 +export type ListAgentSessionEvents403 = ErrorResponse_2 +export const ListAgentSessionEvents403 = ErrorResponse_2 +export type ListAgentSessionEvents404 = ErrorResponse_2 +export const ListAgentSessionEvents404 = ErrorResponse_2 +export type ListAgentSessionEvents409 = ErrorResponse_2 +export const ListAgentSessionEvents409 = ErrorResponse_2 +export type ListAgentSessionEvents500 = ErrorResponse_2 +export const ListAgentSessionEvents500 = ErrorResponse_2 +export type ListAgentSessionEvents503 = ErrorResponse_2 +export const ListAgentSessionEvents503 = ErrorResponse_2 +export type CreateAgentSessionEventsParams = { readonly "Idempotency-Key"?: string } +export const CreateAgentSessionEventsParams = Schema.Struct({ + "Idempotency-Key": Schema.optionalKey( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check( + Schema.isMaxCodePoints(256).annotate({ "expected": "a string with at most 256 code points" }) + ) + ) +}) +export type CreateAgentSessionEventsRequestJson = CreateSessionEventsParams +export const CreateAgentSessionEventsRequestJson = CreateSessionEventsParams +export type CreateAgentSessionEvents400 = ErrorResponse_2 +export const CreateAgentSessionEvents400 = ErrorResponse_2 +export type CreateAgentSessionEvents401 = ErrorResponse_2 +export const CreateAgentSessionEvents401 = ErrorResponse_2 +export type CreateAgentSessionEvents403 = ErrorResponse_2 +export const CreateAgentSessionEvents403 = ErrorResponse_2 +export type CreateAgentSessionEvents404 = ErrorResponse_2 +export const CreateAgentSessionEvents404 = ErrorResponse_2 +export type CreateAgentSessionEvents409 = ErrorResponse_2 +export const CreateAgentSessionEvents409 = ErrorResponse_2 +export type CreateAgentSessionEvents500 = ErrorResponse_2 +export const CreateAgentSessionEvents500 = ErrorResponse_2 +export type CreateAgentSessionEvents503 = ErrorResponse_2 +export const CreateAgentSessionEvents503 = ErrorResponse_2 +export type ListAgentSessionItemsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentSessionItemsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessionItems200 = SessionItemListResource +export const ListAgentSessionItems200 = SessionItemListResource +export type ListAgentSessionItems400 = ErrorResponse_2 +export const ListAgentSessionItems400 = ErrorResponse_2 +export type ListAgentSessionItems401 = ErrorResponse_2 +export const ListAgentSessionItems401 = ErrorResponse_2 +export type ListAgentSessionItems403 = ErrorResponse_2 +export const ListAgentSessionItems403 = ErrorResponse_2 +export type ListAgentSessionItems404 = ErrorResponse_2 +export const ListAgentSessionItems404 = ErrorResponse_2 +export type ListAgentSessionItems409 = ErrorResponse_2 +export const ListAgentSessionItems409 = ErrorResponse_2 +export type ListAgentSessionItems500 = ErrorResponse_2 +export const ListAgentSessionItems500 = ErrorResponse_2 +export type ListAgentSessionItems503 = ErrorResponse_2 +export const ListAgentSessionItems503 = ErrorResponse_2 +export type ListAgentSessionTracesParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentSessionTracesParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessionTraces200 = SessionTraceListResource +export const ListAgentSessionTraces200 = Schema.suspend((): Schema.Codec => + SessionTraceListResource +).annotate({ "description": "A page of published session traces." }) +export type ListAgentSessionTraces400 = ErrorResponse_2 +export const ListAgentSessionTraces400 = ErrorResponse_2 +export type ListAgentSessionTraces401 = ErrorResponse_2 +export const ListAgentSessionTraces401 = ErrorResponse_2 +export type ListAgentSessionTraces403 = ErrorResponse_2 +export const ListAgentSessionTraces403 = ErrorResponse_2 +export type ListAgentSessionTraces404 = ErrorResponse_2 +export const ListAgentSessionTraces404 = ErrorResponse_2 +export type ListAgentSessionTraces409 = ErrorResponse_2 +export const ListAgentSessionTraces409 = ErrorResponse_2 +export type ListAgentSessionTraces500 = ErrorResponse_2 +export const ListAgentSessionTraces500 = ErrorResponse_2 +export type ListAgentSessionTraces503 = ErrorResponse_2 +export const ListAgentSessionTraces503 = ErrorResponse_2 +export type ListAgentSessionTurnsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentSessionTurnsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessionTurns200 = SessionTurnListResource +export const ListAgentSessionTurns200 = Schema.suspend((): Schema.Codec => + SessionTurnListResource +).annotate({ "description": "A page of turns from an agent session or subagent." }) +export type ListAgentSessionTurns400 = ErrorResponse_2 +export const ListAgentSessionTurns400 = ErrorResponse_2 +export type ListAgentSessionTurns401 = ErrorResponse_2 +export const ListAgentSessionTurns401 = ErrorResponse_2 +export type ListAgentSessionTurns403 = ErrorResponse_2 +export const ListAgentSessionTurns403 = ErrorResponse_2 +export type ListAgentSessionTurns404 = ErrorResponse_2 +export const ListAgentSessionTurns404 = ErrorResponse_2 +export type ListAgentSessionTurns409 = ErrorResponse_2 +export const ListAgentSessionTurns409 = ErrorResponse_2 +export type ListAgentSessionTurns500 = ErrorResponse_2 +export const ListAgentSessionTurns500 = ErrorResponse_2 +export type ListAgentSessionTurns503 = ErrorResponse_2 +export const ListAgentSessionTurns503 = ErrorResponse_2 +export type RetrieveAgentSessionTurn200 = TurnResource +export const RetrieveAgentSessionTurn200 = TurnResource +export type RetrieveAgentSessionTurn400 = ErrorResponse_2 +export const RetrieveAgentSessionTurn400 = ErrorResponse_2 +export type RetrieveAgentSessionTurn401 = ErrorResponse_2 +export const RetrieveAgentSessionTurn401 = ErrorResponse_2 +export type RetrieveAgentSessionTurn403 = ErrorResponse_2 +export const RetrieveAgentSessionTurn403 = ErrorResponse_2 +export type RetrieveAgentSessionTurn404 = ErrorResponse_2 +export const RetrieveAgentSessionTurn404 = ErrorResponse_2 +export type RetrieveAgentSessionTurn409 = ErrorResponse_2 +export const RetrieveAgentSessionTurn409 = ErrorResponse_2 +export type RetrieveAgentSessionTurn500 = ErrorResponse_2 +export const RetrieveAgentSessionTurn500 = ErrorResponse_2 +export type RetrieveAgentSessionTurn503 = ErrorResponse_2 +export const RetrieveAgentSessionTurn503 = ErrorResponse_2 +export type ListAgentSessionTurnItemsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string +} +export const ListAgentSessionTurnItemsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ) +}) +export type ListAgentSessionTurnItems200 = SessionItemListResource +export const ListAgentSessionTurnItems200 = SessionItemListResource +export type ListAgentSessionTurnItems400 = ErrorResponse_2 +export const ListAgentSessionTurnItems400 = ErrorResponse_2 +export type ListAgentSessionTurnItems401 = ErrorResponse_2 +export const ListAgentSessionTurnItems401 = ErrorResponse_2 +export type ListAgentSessionTurnItems403 = ErrorResponse_2 +export const ListAgentSessionTurnItems403 = ErrorResponse_2 +export type ListAgentSessionTurnItems404 = ErrorResponse_2 +export const ListAgentSessionTurnItems404 = ErrorResponse_2 +export type ListAgentSessionTurnItems409 = ErrorResponse_2 +export const ListAgentSessionTurnItems409 = ErrorResponse_2 +export type ListAgentSessionTurnItems500 = ErrorResponse_2 +export const ListAgentSessionTurnItems500 = ErrorResponse_2 +export type ListAgentSessionTurnItems503 = ErrorResponse_2 +export const ListAgentSessionTurnItems503 = ErrorResponse_2 +export type ListVaultsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string + readonly "metadata"?: { readonly [x: string]: string } + readonly "status"?: VaultStatusFilterParam +} +export const ListVaultsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "metadata": Schema.optionalKey( + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) + ), + "status": Schema.optionalKey(VaultStatusFilterParam) +}) +export type ListVaults200 = VaultListResource +export const ListVaults200 = Schema.suspend((): Schema.Codec => VaultListResource).annotate({ + "description": "A page of vaults." +}) +export type ListVaults400 = ErrorResponse_2 +export const ListVaults400 = ErrorResponse_2 +export type ListVaults401 = ErrorResponse_2 +export const ListVaults401 = ErrorResponse_2 +export type ListVaults403 = ErrorResponse_2 +export const ListVaults403 = ErrorResponse_2 +export type ListVaults404 = ErrorResponse_2 +export const ListVaults404 = ErrorResponse_2 +export type ListVaults409 = ErrorResponse_2 +export const ListVaults409 = ErrorResponse_2 +export type ListVaults500 = ErrorResponse_2 +export const ListVaults500 = ErrorResponse_2 +export type ListVaults503 = ErrorResponse_2 +export const ListVaults503 = ErrorResponse_2 +export type CreateVaultRequestJson = CreateVaultParams +export const CreateVaultRequestJson = CreateVaultParams +export type CreateVault201 = VaultResource +export const CreateVault201 = VaultResource +export type CreateVault400 = ErrorResponse_2 +export const CreateVault400 = ErrorResponse_2 +export type CreateVault401 = ErrorResponse_2 +export const CreateVault401 = ErrorResponse_2 +export type CreateVault403 = ErrorResponse_2 +export const CreateVault403 = ErrorResponse_2 +export type CreateVault404 = ErrorResponse_2 +export const CreateVault404 = ErrorResponse_2 +export type CreateVault409 = ErrorResponse_2 +export const CreateVault409 = ErrorResponse_2 +export type CreateVault500 = ErrorResponse_2 +export const CreateVault500 = ErrorResponse_2 +export type CreateVault503 = ErrorResponse_2 +export const CreateVault503 = ErrorResponse_2 +export type RetrieveVault200 = VaultResource +export const RetrieveVault200 = VaultResource +export type RetrieveVault400 = ErrorResponse_2 +export const RetrieveVault400 = ErrorResponse_2 +export type RetrieveVault401 = ErrorResponse_2 +export const RetrieveVault401 = ErrorResponse_2 +export type RetrieveVault403 = ErrorResponse_2 +export const RetrieveVault403 = ErrorResponse_2 +export type RetrieveVault404 = ErrorResponse_2 +export const RetrieveVault404 = ErrorResponse_2 +export type RetrieveVault409 = ErrorResponse_2 +export const RetrieveVault409 = ErrorResponse_2 +export type RetrieveVault500 = ErrorResponse_2 +export const RetrieveVault500 = ErrorResponse_2 +export type RetrieveVault503 = ErrorResponse_2 +export const RetrieveVault503 = ErrorResponse_2 +export type UpdateVaultRequestJson = UpdateVaultParams +export const UpdateVaultRequestJson = UpdateVaultParams +export type UpdateVault200 = VaultResource +export const UpdateVault200 = VaultResource +export type UpdateVault400 = ErrorResponse_2 +export const UpdateVault400 = ErrorResponse_2 +export type UpdateVault401 = ErrorResponse_2 +export const UpdateVault401 = ErrorResponse_2 +export type UpdateVault403 = ErrorResponse_2 +export const UpdateVault403 = ErrorResponse_2 +export type UpdateVault404 = ErrorResponse_2 +export const UpdateVault404 = ErrorResponse_2 +export type UpdateVault409 = ErrorResponse_2 +export const UpdateVault409 = ErrorResponse_2 +export type UpdateVault500 = ErrorResponse_2 +export const UpdateVault500 = ErrorResponse_2 +export type UpdateVault503 = ErrorResponse_2 +export const UpdateVault503 = ErrorResponse_2 +export type DeleteVault200 = DeletedVaultResource +export const DeleteVault200 = DeletedVaultResource +export type DeleteVault400 = ErrorResponse_2 +export const DeleteVault400 = ErrorResponse_2 +export type DeleteVault401 = ErrorResponse_2 +export const DeleteVault401 = ErrorResponse_2 +export type DeleteVault403 = ErrorResponse_2 +export const DeleteVault403 = ErrorResponse_2 +export type DeleteVault404 = ErrorResponse_2 +export const DeleteVault404 = ErrorResponse_2 +export type DeleteVault409 = ErrorResponse_2 +export const DeleteVault409 = ErrorResponse_2 +export type DeleteVault500 = ErrorResponse_2 +export const DeleteVault500 = ErrorResponse_2 +export type DeleteVault503 = ErrorResponse_2 +export const DeleteVault503 = ErrorResponse_2 +export type ListVaultCredentialsParams = { + readonly "limit"?: number + readonly "order"?: ListOrderParam + readonly "after"?: string + readonly "metadata"?: { readonly [x: string]: string } + readonly "status"?: VaultStatusFilterParam +} +export const ListVaultCredentialsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.annotate({ "format": "int64" }).check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "order": Schema.optionalKey(ListOrderParam), + "after": Schema.optionalKey( + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(1048576).annotate({ "expected": "a string with at most 1048576 code points" })) + ), + "metadata": Schema.optionalKey( + Schema.Record( + Schema.String, + Schema.String.check(Schema.isMinCodePoints(0).annotate({ "expected": "a string with at least 0 code points" })) + .check(Schema.isMaxCodePoints(512).annotate({ "expected": "a string with at most 512 code points" })) + ).check(Schema.isMinProperties(0).annotate({ "expected": "a value with at least 0 entries" })).check( + Schema.isMaxProperties(16).annotate({ "expected": "a value with at most 16 entries" }) + ).check( + Schema.isPropertyNames( + Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) + .check(Schema.isMaxCodePoints(64).annotate({ "expected": "a string with at most 64 code points" })) + ).annotate({ "expected": "an object with property names matching the schema" }) + ) + ), + "status": Schema.optionalKey(VaultStatusFilterParam) +}) +export type ListVaultCredentials200 = VaultCredentialListResource +export const ListVaultCredentials200 = Schema.suspend((): Schema.Codec => + VaultCredentialListResource +).annotate({ "description": "A page of credentials in a vault." }) +export type ListVaultCredentials400 = ErrorResponse_2 +export const ListVaultCredentials400 = ErrorResponse_2 +export type ListVaultCredentials401 = ErrorResponse_2 +export const ListVaultCredentials401 = ErrorResponse_2 +export type ListVaultCredentials403 = ErrorResponse_2 +export const ListVaultCredentials403 = ErrorResponse_2 +export type ListVaultCredentials404 = ErrorResponse_2 +export const ListVaultCredentials404 = ErrorResponse_2 +export type ListVaultCredentials409 = ErrorResponse_2 +export const ListVaultCredentials409 = ErrorResponse_2 +export type ListVaultCredentials500 = ErrorResponse_2 +export const ListVaultCredentials500 = ErrorResponse_2 +export type ListVaultCredentials503 = ErrorResponse_2 +export const ListVaultCredentials503 = ErrorResponse_2 +export type CreateVaultCredentialRequestJson = CreateVaultCredentialParams +export const CreateVaultCredentialRequestJson = CreateVaultCredentialParams +export type CreateVaultCredential201 = VaultCredentialResource +export const CreateVaultCredential201 = VaultCredentialResource +export type CreateVaultCredential400 = ErrorResponse_2 +export const CreateVaultCredential400 = ErrorResponse_2 +export type CreateVaultCredential401 = ErrorResponse_2 +export const CreateVaultCredential401 = ErrorResponse_2 +export type CreateVaultCredential403 = ErrorResponse_2 +export const CreateVaultCredential403 = ErrorResponse_2 +export type CreateVaultCredential404 = ErrorResponse_2 +export const CreateVaultCredential404 = ErrorResponse_2 +export type CreateVaultCredential409 = ErrorResponse_2 +export const CreateVaultCredential409 = ErrorResponse_2 +export type CreateVaultCredential500 = ErrorResponse_2 +export const CreateVaultCredential500 = ErrorResponse_2 +export type CreateVaultCredential503 = ErrorResponse_2 +export const CreateVaultCredential503 = ErrorResponse_2 +export type RetrieveVaultCredential200 = VaultCredentialResource +export const RetrieveVaultCredential200 = VaultCredentialResource +export type RetrieveVaultCredential400 = ErrorResponse_2 +export const RetrieveVaultCredential400 = ErrorResponse_2 +export type RetrieveVaultCredential401 = ErrorResponse_2 +export const RetrieveVaultCredential401 = ErrorResponse_2 +export type RetrieveVaultCredential403 = ErrorResponse_2 +export const RetrieveVaultCredential403 = ErrorResponse_2 +export type RetrieveVaultCredential404 = ErrorResponse_2 +export const RetrieveVaultCredential404 = ErrorResponse_2 +export type RetrieveVaultCredential409 = ErrorResponse_2 +export const RetrieveVaultCredential409 = ErrorResponse_2 +export type RetrieveVaultCredential500 = ErrorResponse_2 +export const RetrieveVaultCredential500 = ErrorResponse_2 +export type RetrieveVaultCredential503 = ErrorResponse_2 +export const RetrieveVaultCredential503 = ErrorResponse_2 +export type RotateVaultCredentialRequestJson = RotateVaultCredentialParams +export const RotateVaultCredentialRequestJson = RotateVaultCredentialParams +export type RotateVaultCredential200 = VaultCredentialResource +export const RotateVaultCredential200 = VaultCredentialResource +export type RotateVaultCredential400 = ErrorResponse_2 +export const RotateVaultCredential400 = ErrorResponse_2 +export type RotateVaultCredential401 = ErrorResponse_2 +export const RotateVaultCredential401 = ErrorResponse_2 +export type RotateVaultCredential403 = ErrorResponse_2 +export const RotateVaultCredential403 = ErrorResponse_2 +export type RotateVaultCredential404 = ErrorResponse_2 +export const RotateVaultCredential404 = ErrorResponse_2 +export type RotateVaultCredential409 = ErrorResponse_2 +export const RotateVaultCredential409 = ErrorResponse_2 +export type RotateVaultCredential500 = ErrorResponse_2 +export const RotateVaultCredential500 = ErrorResponse_2 +export type RotateVaultCredential503 = ErrorResponse_2 +export const RotateVaultCredential503 = ErrorResponse_2 +export type DeleteVaultCredential200 = DeletedVaultCredentialResource +export const DeleteVaultCredential200 = DeletedVaultCredentialResource +export type DeleteVaultCredential400 = ErrorResponse_2 +export const DeleteVaultCredential400 = ErrorResponse_2 +export type DeleteVaultCredential401 = ErrorResponse_2 +export const DeleteVaultCredential401 = ErrorResponse_2 +export type DeleteVaultCredential403 = ErrorResponse_2 +export const DeleteVaultCredential403 = ErrorResponse_2 +export type DeleteVaultCredential404 = ErrorResponse_2 +export const DeleteVaultCredential404 = ErrorResponse_2 +export type DeleteVaultCredential409 = ErrorResponse_2 +export const DeleteVaultCredential409 = ErrorResponse_2 +export type DeleteVaultCredential500 = ErrorResponse_2 +export const DeleteVaultCredential500 = ErrorResponse_2 +export type DeleteVaultCredential503 = ErrorResponse_2 +export const DeleteVaultCredential503 = ErrorResponse_2 +export type ListWebhookEndpointsParams = { readonly "limit"?: number; readonly "after"?: string | null } +export const ListWebhookEndpointsParams = Schema.Struct({ + "limit": Schema.optionalKey( + Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" })).check( + Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" }) + ).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" })) + ), + "after": Schema.optionalKey(Schema.Union([Schema.String, Schema.Null])) +}) +export type ListWebhookEndpoints200 = WebhookEndpointListResource +export const ListWebhookEndpoints200 = WebhookEndpointListResource +export type ListWebhookEndpoints400 = ErrorResponse +export const ListWebhookEndpoints400 = ErrorResponse +export type ListWebhookEndpoints404 = ErrorResponse +export const ListWebhookEndpoints404 = ErrorResponse +export type CreateWebhookEndpointRequestJson = PublicCreateEndpointBody +export const CreateWebhookEndpointRequestJson = PublicCreateEndpointBody +export type CreateWebhookEndpoint200 = WebhookEndpointWithSecretResource +export const CreateWebhookEndpoint200 = WebhookEndpointWithSecretResource +export type CreateWebhookEndpoint400 = ErrorResponse +export const CreateWebhookEndpoint400 = ErrorResponse +export type RetrieveWebhookEndpoint200 = WebhookEndpointBody +export const RetrieveWebhookEndpoint200 = WebhookEndpointBody +export type RetrieveWebhookEndpoint400 = ErrorResponse +export const RetrieveWebhookEndpoint400 = ErrorResponse +export type RetrieveWebhookEndpoint404 = ErrorResponse +export const RetrieveWebhookEndpoint404 = ErrorResponse +export type UpdateWebhookEndpointRequestJson = PublicUpdateEndpointBody +export const UpdateWebhookEndpointRequestJson = PublicUpdateEndpointBody +export type UpdateWebhookEndpoint200 = WebhookEndpointBody +export const UpdateWebhookEndpoint200 = WebhookEndpointBody +export type UpdateWebhookEndpoint400 = ErrorResponse +export const UpdateWebhookEndpoint400 = ErrorResponse +export type UpdateWebhookEndpoint404 = ErrorResponse +export const UpdateWebhookEndpoint404 = ErrorResponse +export type DeleteWebhookEndpoint200 = DeletedWebhookEndpointResource +export const DeleteWebhookEndpoint200 = DeletedWebhookEndpointResource +export type DeleteWebhookEndpoint400 = ErrorResponse +export const DeleteWebhookEndpoint400 = ErrorResponse +export type DeleteWebhookEndpoint404 = ErrorResponse +export const DeleteWebhookEndpoint404 = ErrorResponse +export type RotateWebhookEndpointSigningSecretRequestJson = PublicRotateSecretBody +export const RotateWebhookEndpointSigningSecretRequestJson = PublicRotateSecretBody +export type RotateWebhookEndpointSigningSecret200 = WebhookEndpointWithSecretResource +export const RotateWebhookEndpointSigningSecret200 = WebhookEndpointWithSecretResource +export type RotateWebhookEndpointSigningSecret400 = ErrorResponse +export const RotateWebhookEndpointSigningSecret400 = ErrorResponse +export type RotateWebhookEndpointSigningSecret404 = ErrorResponse +export const RotateWebhookEndpointSigningSecret404 = ErrorResponse +export type TestWebhookEndpointRequestJson = PublicTestEndpointBody +export const TestWebhookEndpointRequestJson = PublicTestEndpointBody +export type TestWebhookEndpoint200 = WebhookEndpointTestResultResource +export const TestWebhookEndpoint200 = WebhookEndpointTestResultResource +export type TestWebhookEndpoint400 = ErrorResponse +export const TestWebhookEndpoint400 = ErrorResponse +export type TestWebhookEndpoint404 = ErrorResponse +export const TestWebhookEndpoint404 = ErrorResponse +export type TestWebhookEndpoint500 = ErrorResponse +export const TestWebhookEndpoint500 = ErrorResponse +export type ListWebhookEventTypes200 = WebhookEventTypeListResource +export const ListWebhookEventTypes200 = WebhookEventTypeListResource +export type ListWebhookEventTypes401 = ErrorResponse +export const ListWebhookEventTypes401 = ErrorResponse +export type BetaCreateResponseParams = { readonly "openai-beta"?: ReadonlyArray<"responses_multi_agent=v1"> } +export const BetaCreateResponseParams = Schema.Struct({ + "openai-beta": Schema.optionalKey(Schema.Array(Schema.Literal("responses_multi_agent=v1"))) +}) +export type BetaCreateResponseRequestJson = BetaCreateResponse +export const BetaCreateResponseRequestJson = BetaCreateResponse +export type BetaCreateResponse200 = BetaResponse +export const BetaCreateResponse200 = BetaResponse +export type BetaCreateResponse200Sse = BetaResponseStreamEvent +export const BetaCreateResponse200Sse = BetaResponseStreamEvent +export type BetaCreateResponse400 = BetaErrorResponse +export const BetaCreateResponse400 = BetaErrorResponse +export type BetaCreateResponse404 = BetaErrorResponse +export const BetaCreateResponse404 = BetaErrorResponse +export type BetaCreateResponse429 = ErrorResponse +export const BetaCreateResponse429 = ErrorResponse +export type BetaCreateResponse503 = ErrorResponse +export const BetaCreateResponse503 = ErrorResponse +export type BetaGetResponseParams = { + readonly "include"?: ReadonlyArray + readonly "stream"?: boolean + readonly "starting_after"?: number + readonly "include_obfuscation"?: boolean + readonly "openai-beta"?: ReadonlyArray<"responses_multi_agent=v1"> +} +export const BetaGetResponseParams = Schema.Struct({ + "include": Schema.optionalKey(Schema.Array(BetaIncludeEnum)), + "stream": Schema.optionalKey(Schema.Boolean), + "starting_after": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), + "include_obfuscation": Schema.optionalKey(Schema.Boolean), + "openai-beta": Schema.optionalKey(Schema.Array(Schema.Literal("responses_multi_agent=v1"))) +}) +export type BetaGetResponse200 = BetaResponse +export const BetaGetResponse200 = BetaResponse +export type BetaGetResponse404 = BetaErrorResponse +export const BetaGetResponse404 = BetaErrorResponse +export type BetaGetResponse429 = ErrorResponse +export const BetaGetResponse429 = ErrorResponse +export type BetaDeleteResponseParams = { readonly "openai-beta"?: ReadonlyArray<"responses_multi_agent=v1"> } +export const BetaDeleteResponseParams = Schema.Struct({ + "openai-beta": Schema.optionalKey(Schema.Array(Schema.Literal("responses_multi_agent=v1"))) +}) +export type BetaDeleteResponse200 = { + readonly "object": "response.deleted" + readonly "deleted": boolean + readonly "id": string +} +export const BetaDeleteResponse200 = Schema.Struct({ + "object": Schema.Literal("response.deleted"), + "deleted": Schema.Boolean, + "id": Schema.String +}) +export type BetaDeleteResponse404 = BetaErrorResponse +export const BetaDeleteResponse404 = BetaErrorResponse +export type BetaDeleteResponse429 = ErrorResponse +export const BetaDeleteResponse429 = ErrorResponse +export type BetaCancelResponseParams = { readonly "openai-beta"?: ReadonlyArray<"responses_multi_agent=v1"> } +export const BetaCancelResponseParams = Schema.Struct({ + "openai-beta": Schema.optionalKey(Schema.Array(Schema.Literal("responses_multi_agent=v1"))) +}) +export type BetaCancelResponse200 = BetaResponse +export const BetaCancelResponse200 = BetaResponse +export type BetaCancelResponse404 = BetaErrorResponse +export const BetaCancelResponse404 = BetaErrorResponse +export type BetaCancelResponse429 = ErrorResponse +export const BetaCancelResponse429 = ErrorResponse +export type BetaCompactconversationParams = { readonly "openai-beta"?: ReadonlyArray<"responses_multi_agent=v1"> } +export const BetaCompactconversationParams = Schema.Struct({ + "openai-beta": Schema.optionalKey(Schema.Array(Schema.Literal("responses_multi_agent=v1"))) +}) +export type BetaCompactconversationRequestJson = BetaCompactResponseMethodPublicBody +export const BetaCompactconversationRequestJson = BetaCompactResponseMethodPublicBody +export type BetaCompactconversation200 = BetaCompactResource +export const BetaCompactconversation200 = BetaCompactResource +export type BetaCompactconversation400 = BetaErrorResponse +export const BetaCompactconversation400 = BetaErrorResponse +export type BetaCompactconversation429 = ErrorResponse +export const BetaCompactconversation429 = ErrorResponse +export type BetaCompactconversation503 = ErrorResponse +export const BetaCompactconversation503 = ErrorResponse +export type BetaListInputItemsParams = { + readonly "limit"?: number + readonly "order"?: "asc" | "desc" + readonly "after"?: string + readonly "include"?: ReadonlyArray + readonly "openai-beta"?: ReadonlyArray<"responses_multi_agent=v1"> +} +export const BetaListInputItemsParams = Schema.Struct({ + "limit": Schema.optionalKey(Schema.Number.check(Schema.isInt().annotate({ "expected": "an integer" }))), + "order": Schema.optionalKey(Schema.Literals(["asc", "desc"])), + "after": Schema.optionalKey(Schema.String), + "include": Schema.optionalKey(Schema.Array(BetaIncludeEnum)), + "openai-beta": Schema.optionalKey(Schema.Array(Schema.Literal("responses_multi_agent=v1"))) +}) +export type BetaListInputItems200 = BetaResponseItemList +export const BetaListInputItems200 = BetaResponseItemList +export type BetaListInputItems404 = BetaErrorResponse +export const BetaListInputItems404 = BetaErrorResponse +export type BetaListInputItems429 = ErrorResponse +export const BetaListInputItems429 = ErrorResponse +export type BetaGetinputtokencountsParams = { readonly "openai-beta"?: ReadonlyArray<"responses_multi_agent=v1"> } +export const BetaGetinputtokencountsParams = Schema.Struct({ + "openai-beta": Schema.optionalKey(Schema.Array(Schema.Literal("responses_multi_agent=v1"))) +}) +export type BetaGetinputtokencountsRequestJson = BetaTokenCountsBody +export const BetaGetinputtokencountsRequestJson = BetaTokenCountsBody +export type BetaGetinputtokencounts200 = BetaTokenCountsResource +export const BetaGetinputtokencounts200 = BetaTokenCountsResource +export type BetaGetinputtokencounts400 = BetaErrorResponse +export const BetaGetinputtokencounts400 = BetaErrorResponse +export type BetaGetinputtokencounts429 = ErrorResponse +export const BetaGetinputtokencounts429 = ErrorResponse export interface OperationConfig { /** @@ -30411,10 +51360,11 @@ export interface OperationConfig { * of an operation based upon the value of the `includeResponse` configuration * option. */ -export type WithOptionalResponse = Config extends { +export type WithOptionalResponse = Config extends { readonly includeResponse: true -} ? [A, HttpClientResponse.HttpClientResponse] : - A +} ? [A, HttpClientResponse.HttpClientResponse] + : Config extends { readonly includeResponse?: false | undefined } | undefined ? A + : A | [A, HttpClientResponse.HttpClientResponse] export const make = ( httpClient: HttpClient.HttpClient, @@ -30453,6 +51403,44 @@ export const make = ( ) : (request) => Effect.flatMap(httpClient.execute(request), withOptionalResponse) } + const __encodePathParam = encodeURIComponent + const __makePathRequest = ( + method: (url: string) => HttpClientRequest.HttpClientRequest, + parameters: ReadonlyArray, + getPath: () => string + ) => + Effect.suspend(() => { + const fail = (description: string, cause?: unknown) => + Effect.fail( + new HttpClientError.HttpClientError({ + reason: new HttpClientError.InvalidUrlError({ + request: method(""), + cause, + description + }) + }) + ) + if (parameters.some((value) => value === "" || /^(?:\.|%2e){1,2}$/i.test(value))) { + return fail("Path parameters must be non-empty and cannot be dot segments") + } + let path: string + try { + path = getPath() + } catch (cause) { + return fail("Failed to encode path parameter", cause) + } + if (path.split("/").some((segment) => /^(?:\.|%2e){1,2}$/i.test(segment))) { + return fail("Request paths cannot contain dot segments") + } + return Effect.succeed(method(path)) + }) + const executeStreamRequest = (request: HttpClientRequest.HttpClientRequest) => + Effect.suspend(() => + options.transformClient + ? Effect.flatMap(options.transformClient(httpClient), (client) => + HttpClient.filterStatusOk(client).execute(request)) + : HttpClient.filterStatusOk(httpClient).execute(request) + ) const sseRequest = < Type, DecodingServices @@ -30464,1265 +51452,2973 @@ export const make = ( ): Stream.Stream< { readonly event: string; readonly id: string | undefined; readonly data: Type }, HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, - DecodingServices - > => - HttpClient.filterStatusOk(httpClient).execute(request).pipe( - Effect.map((response) => response.stream), - Stream.unwrap, - Stream.decodeText(), - Stream.pipeThroughChannel(Sse.decodeDataSchema(schema)) - ) - const binaryRequest = ( - request: HttpClientRequest.HttpClientRequest - ): Stream.Stream => - HttpClient.filterStatusOk(httpClient).execute(request).pipe( + DecodingServices + > => + executeStreamRequest(request).pipe( Effect.map((response) => response.stream), - Stream.unwrap - ) - const decodeSuccess = - (schema: Schema) => (response: HttpClientResponse.HttpClientResponse) => - HttpClientResponse.schemaBodyJson(schema)(response) - const decodeError = - (tag: Tag, schema: Schema) => - (response: HttpClientResponse.HttpClientResponse) => - Effect.flatMap( - HttpClientResponse.schemaBodyJson(schema)(response), - (cause) => Effect.fail(OpenAiClientError(tag, cause, response)) - ) - return { - httpClient, - "listAssistants": (options) => - HttpClientRequest.get(`/assistants`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListAssistants200), - orElse: unexpectedStatus - })) - ), - "createAssistant": (options) => - HttpClientRequest.post(`/assistants`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateAssistant200), - orElse: unexpectedStatus - })) - ), - "getAssistant": (assistantId, options) => - HttpClientRequest.get(`/assistants/${assistantId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetAssistant200), - orElse: unexpectedStatus - })) - ), - "modifyAssistant": (assistantId, options) => - HttpClientRequest.post(`/assistants/${assistantId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyAssistant200), - orElse: unexpectedStatus - })) - ), - "deleteAssistant": (assistantId, options) => - HttpClientRequest.delete(`/assistants/${assistantId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteAssistant200), - orElse: unexpectedStatus - })) - ), - "createSpeech": (options) => - HttpClientRequest.post(`/audio/speech`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - orElse: unexpectedStatus - })) - ), - "createSpeechSse": (options) => - HttpClientRequest.post(`/audio/speech`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - sseRequest(CreateSpeech200Sse) - ), - "createSpeechStream": (options) => - HttpClientRequest.post(`/audio/speech`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - binaryRequest - ), - "createTranscription": (options) => - HttpClientRequest.post(`/audio/transcriptions`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateTranscription200), - orElse: unexpectedStatus - })) - ), - "createTranscriptionSse": (options) => - HttpClientRequest.post(`/audio/transcriptions`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - sseRequest(CreateTranscription200Sse) - ), - "createTranslation": (options) => - HttpClientRequest.post(`/audio/translations`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateTranslation200), - orElse: unexpectedStatus - })) - ), - "listVoiceConsents": (options) => - HttpClientRequest.get(`/audio/voice_consents`).pipe( - HttpClientRequest.setUrlParams({ - "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListVoiceConsents200), - orElse: unexpectedStatus - })) - ), - "createVoiceConsent": (options) => - HttpClientRequest.post(`/audio/voice_consents`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVoiceConsent200), - orElse: unexpectedStatus - })) - ), - "getVoiceConsent": (consentId, options) => - HttpClientRequest.get(`/audio/voice_consents/${consentId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetVoiceConsent200), - orElse: unexpectedStatus - })) - ), - "updateVoiceConsent": (consentId, options) => - HttpClientRequest.post(`/audio/voice_consents/${consentId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateVoiceConsent200), - orElse: unexpectedStatus - })) - ), - "deleteVoiceConsent": (consentId, options) => - HttpClientRequest.delete(`/audio/voice_consents/${consentId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteVoiceConsent200), - orElse: unexpectedStatus - })) - ), - "createVoice": (options) => - HttpClientRequest.post(`/audio/voices`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVoice200), - orElse: unexpectedStatus - })) - ), - "listBatches": (options) => - HttpClientRequest.get(`/batches`).pipe( - HttpClientRequest.setUrlParams({ - "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListBatches200), - orElse: unexpectedStatus - })) - ), - "createBatch": (options) => - HttpClientRequest.post(`/batches`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateBatch200), - orElse: unexpectedStatus - })) - ), - "retrieveBatch": (batchId, options) => - HttpClientRequest.get(`/batches/${batchId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveBatch200), - orElse: unexpectedStatus - })) - ), - "cancelBatch": (batchId, options) => - HttpClientRequest.post(`/batches/${batchId}/cancel`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CancelBatch200), - orElse: unexpectedStatus - })) - ), - "listChatCompletions": (options) => - HttpClientRequest.get(`/chat/completions`).pipe( - HttpClientRequest.setUrlParams({ - "model": options?.params?.["model"] as any, - "metadata": options?.params?.["metadata"] as any, - "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListChatCompletions200), - orElse: unexpectedStatus - })) - ), - "createChatCompletion": (options) => - HttpClientRequest.post(`/chat/completions`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateChatCompletion200), - orElse: unexpectedStatus - })) - ), - "createChatCompletionSse": (options) => - HttpClientRequest.post(`/chat/completions`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - sseRequest(CreateChatCompletion200Sse) - ), - "getChatCompletion": (completionId, options) => - HttpClientRequest.get(`/chat/completions/${completionId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetChatCompletion200), - orElse: unexpectedStatus - })) - ), - "updateChatCompletion": (completionId, options) => - HttpClientRequest.post(`/chat/completions/${completionId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateChatCompletion200), - orElse: unexpectedStatus - })) - ), - "deleteChatCompletion": (completionId, options) => - HttpClientRequest.delete(`/chat/completions/${completionId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteChatCompletion200), - orElse: unexpectedStatus - })) - ), - "getChatCompletionMessages": (completionId, options) => - HttpClientRequest.get(`/chat/completions/${completionId}/messages`).pipe( - HttpClientRequest.setUrlParams({ - "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetChatCompletionMessages200), - orElse: unexpectedStatus - })) - ), - "createCompletion": (options) => - HttpClientRequest.post(`/completions`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateCompletion200), - orElse: unexpectedStatus - })) - ), - "ListContainers": (options) => - HttpClientRequest.get(`/containers`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "name": options?.params?.["name"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListContainers200), - orElse: unexpectedStatus - })) - ), - "CreateContainer": (options) => - HttpClientRequest.post(`/containers`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateContainer200), - orElse: unexpectedStatus - })) - ), - "RetrieveContainer": (containerId, options) => - HttpClientRequest.get(`/containers/${containerId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveContainer200), - orElse: unexpectedStatus - })) - ), - "DeleteContainer": (containerId, options) => - HttpClientRequest.delete(`/containers/${containerId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "200": () => Effect.void, - orElse: unexpectedStatus - })) - ), - "ListContainerFiles": (containerId, options) => - HttpClientRequest.get(`/containers/${containerId}/files`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListContainerFiles200), - orElse: unexpectedStatus - })) - ), - "CreateContainerFile": (containerId, options) => - HttpClientRequest.post(`/containers/${containerId}/files`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateContainerFile200), - orElse: unexpectedStatus - })) - ), - "RetrieveContainerFile": (containerId, fileId, options) => - HttpClientRequest.get(`/containers/${containerId}/files/${fileId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveContainerFile200), - orElse: unexpectedStatus - })) - ), - "DeleteContainerFile": (containerId, fileId, options) => - HttpClientRequest.delete(`/containers/${containerId}/files/${fileId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "200": () => Effect.void, - orElse: unexpectedStatus - })) - ), - "RetrieveContainerFileContent": (containerId, fileId, options) => - HttpClientRequest.get(`/containers/${containerId}/files/${fileId}/content`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "200": () => Effect.void, - orElse: unexpectedStatus - })) - ), - "listConversationItems": (conversationId, options) => - HttpClientRequest.get(`/conversations/${conversationId}/items`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "include": options?.params?.["include"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListConversationItems200), - orElse: unexpectedStatus - })) - ), - "createConversationItems": (conversationId, options) => - HttpClientRequest.post(`/conversations/${conversationId}/items`).pipe( - HttpClientRequest.setUrlParams({ "include": options.params?.["include"] as any }), - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateConversationItems200), - orElse: unexpectedStatus - })) - ), - "getConversationItem": (conversationId, itemId, options) => - HttpClientRequest.get(`/conversations/${conversationId}/items/${itemId}`).pipe( - HttpClientRequest.setUrlParams({ "include": options?.params?.["include"] as any }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetConversationItem200), - orElse: unexpectedStatus - })) - ), - "deleteConversationItem": (conversationId, itemId, options) => - HttpClientRequest.delete(`/conversations/${conversationId}/items/${itemId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteConversationItem200), - orElse: unexpectedStatus - })) - ), - "createEmbedding": (options) => - HttpClientRequest.post(`/embeddings`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateEmbedding200), - orElse: unexpectedStatus - })) - ), - "listEvals": (options) => - HttpClientRequest.get(`/evals`).pipe( + Stream.unwrap, + Stream.decodeText(), + Stream.pipeThroughChannel(Sse.decodeDataSchema(schema)) + ) + const decodeBinary = (response: HttpClientResponse.HttpClientResponse) => + Effect.map(response.arrayBuffer, (buffer) => new Uint8Array(buffer)) + const binaryRequest = ( + request: HttpClientRequest.HttpClientRequest + ): Stream.Stream => + executeStreamRequest(request).pipe( + Effect.map((response) => response.stream), + Stream.unwrap + ) + const decodeSuccess = + (schema: Schema) => (response: HttpClientResponse.HttpClientResponse) => + HttpClientResponse.schemaBodyJson(schema)(response) + const decodeError = + (tag: Tag, schema: Schema) => + (response: HttpClientResponse.HttpClientResponse) => + Effect.flatMap( + HttpClientResponse.schemaBodyJson(schema)(response), + (cause) => Effect.fail(OpenAiClientError(tag, cause, response)) + ) + return { + httpClient, + "listAssistants": (options: Parameters[0]) => + HttpClientRequest.get("/assistants").pipe( HttpClientRequest.setUrlParams({ - "after": options?.params?.["after"] as any, "limit": options?.params?.["limit"] as any, "order": options?.params?.["order"] as any, - "order_by": options?.params?.["order_by"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListEvals200), - orElse: unexpectedStatus - })) - ), - "createEval": (options) => - HttpClientRequest.post(`/evals`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateEval201), - orElse: unexpectedStatus - })) - ), - "getEval": (evalId, options) => - HttpClientRequest.get(`/evals/${evalId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetEval200), - orElse: unexpectedStatus - })) - ), - "updateEval": (evalId, options) => - HttpClientRequest.post(`/evals/${evalId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateEval200), - orElse: unexpectedStatus - })) - ), - "deleteEval": (evalId, options) => - HttpClientRequest.delete(`/evals/${evalId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteEval200), - "404": decodeError("DeleteEval404", DeleteEval404), - orElse: unexpectedStatus - })) - ), - "getEvalRuns": (evalId, options) => - HttpClientRequest.get(`/evals/${evalId}/runs`).pipe( - HttpClientRequest.setUrlParams({ "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "status": options?.params?.["status"] as any + "before": options?.params?.["before"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetEvalRuns200), + "2xx": decodeSuccess(ListAssistants200), + "429": decodeError("ListAssistants429", ListAssistants429), orElse: unexpectedStatus })) ), - "createEvalRun": (evalId, options) => - HttpClientRequest.post(`/evals/${evalId}/runs`).pipe( + "createAssistant": (options: Parameters[0]) => + HttpClientRequest.post("/assistants").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateEvalRun201), - "400": decodeError("CreateEvalRun400", CreateEvalRun400), - orElse: unexpectedStatus - })) - ), - "getEvalRun": (evalId, runId, options) => - HttpClientRequest.get(`/evals/${evalId}/runs/${runId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetEvalRun200), - orElse: unexpectedStatus - })) - ), - "cancelEvalRun": (evalId, runId, options) => - HttpClientRequest.post(`/evals/${evalId}/runs/${runId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CancelEvalRun200), - orElse: unexpectedStatus - })) - ), - "deleteEvalRun": (evalId, runId, options) => - HttpClientRequest.delete(`/evals/${evalId}/runs/${runId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteEvalRun200), - "404": decodeError("DeleteEvalRun404", DeleteEvalRun404), - orElse: unexpectedStatus - })) - ), - "getEvalRunOutputItems": (evalId, runId, options) => - HttpClientRequest.get(`/evals/${evalId}/runs/${runId}/output_items`).pipe( - HttpClientRequest.setUrlParams({ - "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any, - "status": options?.params?.["status"] as any, - "order": options?.params?.["order"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetEvalRunOutputItems200), - orElse: unexpectedStatus - })) - ), - "getEvalRunOutputItem": (evalId, runId, outputItemId, options) => - HttpClientRequest.get(`/evals/${evalId}/runs/${runId}/output_items/${outputItemId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetEvalRunOutputItem200), - orElse: unexpectedStatus - })) - ), - "listFiles": (options) => - HttpClientRequest.get(`/files`).pipe( - HttpClientRequest.setUrlParams({ - "purpose": options?.params?.["purpose"] as any, - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListFiles200), - orElse: unexpectedStatus - })) - ), - "createFile": (options) => - HttpClientRequest.post(`/files`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateFile200), + "2xx": decodeSuccess(CreateAssistant200), + "429": decodeError("CreateAssistant429", CreateAssistant429), orElse: unexpectedStatus })) ), - "retrieveFile": (fileId, options) => - HttpClientRequest.get(`/files/${fileId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveFile200), - orElse: unexpectedStatus - })) + "getAssistant": (assistantId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [assistantId], + () => "/assistants/" + __encodePathParam(assistantId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetAssistant200), + "429": decodeError("GetAssistant429", GetAssistant429), + orElse: unexpectedStatus + })) + ) + ) ), - "deleteFile": (fileId, options) => - HttpClientRequest.delete(`/files/${fileId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteFile200), - orElse: unexpectedStatus - })) + "modifyAssistant": (assistantId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [assistantId], + () => "/assistants/" + __encodePathParam(assistantId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyAssistant200), + "429": decodeError("ModifyAssistant429", ModifyAssistant429), + orElse: unexpectedStatus + })) + ) + ) ), - "downloadFile": (fileId, options) => - HttpClientRequest.get(`/files/${fileId}/content`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DownloadFile200), - orElse: unexpectedStatus - })) + "deleteAssistant": (assistantId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [assistantId], + () => "/assistants/" + __encodePathParam(assistantId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteAssistant200), + "429": decodeError("DeleteAssistant429", DeleteAssistant429), + orElse: unexpectedStatus + })) + ) + ) ), - "runGrader": (options) => - HttpClientRequest.post(`/fine_tuning/alpha/graders/run`).pipe( + "createSpeech": (options: Parameters[0]) => + HttpClientRequest.post("/audio/speech").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RunGrader200), + "2xx": decodeBinary, + "400": decodeError("CreateSpeech400", CreateSpeech400), + "401": decodeError("CreateSpeech401", CreateSpeech401), + "429": decodeError("CreateSpeech429", CreateSpeech429), + "500": decodeError("CreateSpeech500", CreateSpeech500), + "503": decodeError("CreateSpeech503", CreateSpeech503), orElse: unexpectedStatus })) ), - "validateGrader": (options) => - HttpClientRequest.post(`/fine_tuning/alpha/graders/validate`).pipe( + "createSpeechSse": (options) => + HttpClientRequest.post("/audio/speech").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ValidateGrader200), - orElse: unexpectedStatus - })) - ), - "listFineTuningCheckpointPermissions": (fineTunedModelCheckpoint, options) => - HttpClientRequest.get(`/fine_tuning/checkpoints/${fineTunedModelCheckpoint}/permissions`).pipe( - HttpClientRequest.setUrlParams({ - "project_id": options?.params?.["project_id"] as any, - "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListFineTuningCheckpointPermissions200), - orElse: unexpectedStatus - })) + sseRequest(CreateSpeech200Sse) ), - "createFineTuningCheckpointPermission": (fineTunedModelCheckpoint, options) => - HttpClientRequest.post(`/fine_tuning/checkpoints/${fineTunedModelCheckpoint}/permissions`).pipe( + "createSpeechStream": (options) => + HttpClientRequest.post("/audio/speech").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateFineTuningCheckpointPermission200), - orElse: unexpectedStatus - })) - ), - "deleteFineTuningCheckpointPermission": (fineTunedModelCheckpoint, permissionId, options) => - HttpClientRequest.delete(`/fine_tuning/checkpoints/${fineTunedModelCheckpoint}/permissions/${permissionId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteFineTuningCheckpointPermission200), - orElse: unexpectedStatus - })) - ), - "listPaginatedFineTuningJobs": (options) => - HttpClientRequest.get(`/fine_tuning/jobs`).pipe( - HttpClientRequest.setUrlParams({ - "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any, - "metadata": options?.params?.["metadata"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListPaginatedFineTuningJobs200), - orElse: unexpectedStatus - })) + binaryRequest ), - "createFineTuningJob": (options) => - HttpClientRequest.post(`/fine_tuning/jobs`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), + "createTranscription": (options: Parameters[0]) => + HttpClientRequest.post("/audio/transcriptions").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateFineTuningJob200), - orElse: unexpectedStatus - })) - ), - "retrieveFineTuningJob": (fineTuningJobId, options) => - HttpClientRequest.get(`/fine_tuning/jobs/${fineTuningJobId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveFineTuningJob200), + "2xx": decodeSuccess(CreateTranscription200), + "400": decodeError("CreateTranscription400", CreateTranscription400), + "401": decodeError("CreateTranscription401", CreateTranscription401), + "413": decodeError("CreateTranscription413", CreateTranscription413), + "429": decodeError("CreateTranscription429", CreateTranscription429), + "500": decodeError("CreateTranscription500", CreateTranscription500), + "502": decodeError("CreateTranscription502", CreateTranscription502), + "503": decodeError("CreateTranscription503", CreateTranscription503), orElse: unexpectedStatus })) ), - "cancelFineTuningJob": (fineTuningJobId, options) => - HttpClientRequest.post(`/fine_tuning/jobs/${fineTuningJobId}/cancel`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CancelFineTuningJob200), - orElse: unexpectedStatus - })) + "createTranscriptionSse": (options) => + HttpClientRequest.post("/audio/transcriptions").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + sseRequest(CreateTranscription200Sse) ), - "listFineTuningJobCheckpoints": (fineTuningJobId, options) => - HttpClientRequest.get(`/fine_tuning/jobs/${fineTuningJobId}/checkpoints`).pipe( - HttpClientRequest.setUrlParams({ - "after": options?.params?.["after"] as any, - "limit": options?.params?.["limit"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListFineTuningJobCheckpoints200), + "createTranslation": (options: Parameters[0]) => + HttpClientRequest.post("/audio/translations").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateTranslation200), + "400": decodeError("CreateTranslation400", CreateTranslation400), + "401": decodeError("CreateTranslation401", CreateTranslation401), + "413": decodeError("CreateTranslation413", CreateTranslation413), + "429": decodeError("CreateTranslation429", CreateTranslation429), + "500": decodeError("CreateTranslation500", CreateTranslation500), + "502": decodeError("CreateTranslation502", CreateTranslation502), + "503": decodeError("CreateTranslation503", CreateTranslation503), orElse: unexpectedStatus })) ), - "listFineTuningEvents": (fineTuningJobId, options) => - HttpClientRequest.get(`/fine_tuning/jobs/${fineTuningJobId}/events`).pipe( + "listVoiceConsents": (options: Parameters[0]) => + HttpClientRequest.get("/audio/voice_consents").pipe( HttpClientRequest.setUrlParams({ "after": options?.params?.["after"] as any, "limit": options?.params?.["limit"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListFineTuningEvents200), - orElse: unexpectedStatus - })) - ), - "pauseFineTuningJob": (fineTuningJobId, options) => - HttpClientRequest.post(`/fine_tuning/jobs/${fineTuningJobId}/pause`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(PauseFineTuningJob200), - orElse: unexpectedStatus - })) - ), - "resumeFineTuningJob": (fineTuningJobId, options) => - HttpClientRequest.post(`/fine_tuning/jobs/${fineTuningJobId}/resume`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ResumeFineTuningJob200), - orElse: unexpectedStatus - })) - ), - "createImageEdit": (options) => - HttpClientRequest.post(`/images/edits`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateImageEdit200), - orElse: unexpectedStatus - })) - ), - "createImageEditSse": (options) => - HttpClientRequest.post(`/images/edits`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - sseRequest(CreateImageEdit200Sse) - ), - "createImage": (options) => - HttpClientRequest.post(`/images/generations`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateImage200), + "2xx": decodeSuccess(ListVoiceConsents200), + "400": decodeError("ListVoiceConsents400", ListVoiceConsents400), + "404": decodeError("ListVoiceConsents404", ListVoiceConsents404), orElse: unexpectedStatus })) ), - "createImageSse": (options) => - HttpClientRequest.post(`/images/generations`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - sseRequest(CreateImage200Sse) - ), - "createImageVariation": (options) => - HttpClientRequest.post(`/images/variations`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), + "createVoiceConsent": (options: Parameters[0]) => + HttpClientRequest.post("/audio/voice_consents").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateImageVariation200), - orElse: unexpectedStatus - })) - ), - "listModels": (options) => - HttpClientRequest.get(`/models`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListModels200), - orElse: unexpectedStatus - })) - ), - "retrieveModel": (model, options) => - HttpClientRequest.get(`/models/${model}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveModel200), + "2xx": decodeSuccess(CreateVoiceConsent200), + "400": decodeError("CreateVoiceConsent400", CreateVoiceConsent400), + "404": decodeError("CreateVoiceConsent404", CreateVoiceConsent404), orElse: unexpectedStatus })) ), - "deleteModel": (model, options) => - HttpClientRequest.delete(`/models/${model}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteModel200), - orElse: unexpectedStatus - })) + "getVoiceConsent": (consentId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [consentId], + () => "/audio/voice_consents/" + __encodePathParam(consentId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetVoiceConsent200), + "400": decodeError("GetVoiceConsent400", GetVoiceConsent400), + "404": decodeError("GetVoiceConsent404", GetVoiceConsent404), + orElse: unexpectedStatus + })) + ) + ) ), - "createModeration": (options) => - HttpClientRequest.post(`/moderations`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateModeration200), - orElse: unexpectedStatus - })) + "updateVoiceConsent": (consentId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [consentId], + () => "/audio/voice_consents/" + __encodePathParam(consentId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateVoiceConsent200), + "400": decodeError("UpdateVoiceConsent400", UpdateVoiceConsent400), + "404": decodeError("UpdateVoiceConsent404", UpdateVoiceConsent404), + orElse: unexpectedStatus + })) + ) + ) ), - "adminApiKeysList": (options) => - HttpClientRequest.get(`/organization/admin_api_keys`).pipe( - HttpClientRequest.setUrlParams({ - "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any, - "limit": options?.params?.["limit"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AdminApiKeysList200), - orElse: unexpectedStatus - })) + "deleteVoiceConsent": (consentId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [consentId], + () => "/audio/voice_consents/" + __encodePathParam(consentId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteVoiceConsent200), + "400": decodeError("DeleteVoiceConsent400", DeleteVoiceConsent400), + "404": decodeError("DeleteVoiceConsent404", DeleteVoiceConsent404), + orElse: unexpectedStatus + })) + ) + ) ), - "adminApiKeysCreate": (options) => - HttpClientRequest.post(`/organization/admin_api_keys`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), + "createVoice": (options: Parameters[0]) => + HttpClientRequest.post("/audio/voices").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AdminApiKeysCreate200), - orElse: unexpectedStatus - })) - ), - "adminApiKeysGet": (keyId, options) => - HttpClientRequest.get(`/organization/admin_api_keys/${keyId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AdminApiKeysGet200), - orElse: unexpectedStatus - })) - ), - "adminApiKeysDelete": (keyId, options) => - HttpClientRequest.delete(`/organization/admin_api_keys/${keyId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AdminApiKeysDelete200), - orElse: unexpectedStatus - })) - ), - "listAuditLogs": (options) => - HttpClientRequest.get(`/organization/audit_logs`).pipe( - HttpClientRequest.setUrlParams({ - "effective_at[gt]": options?.params?.["effective_at[gt]"] as any, - "effective_at[gte]": options?.params?.["effective_at[gte]"] as any, - "effective_at[lt]": options?.params?.["effective_at[lt]"] as any, - "effective_at[lte]": options?.params?.["effective_at[lte]"] as any, - "project_ids[]": options?.params?.["project_ids[]"] as any, - "event_types[]": options?.params?.["event_types[]"] as any, - "actor_ids[]": options?.params?.["actor_ids[]"] as any, - "actor_emails[]": options?.params?.["actor_emails[]"] as any, - "resource_ids[]": options?.params?.["resource_ids[]"] as any, - "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListAuditLogs200), + "2xx": decodeSuccess(CreateVoice200), + "400": decodeError("CreateVoice400", CreateVoice400), + "404": decodeError("CreateVoice404", CreateVoice404), + "500": decodeError("CreateVoice500", CreateVoice500), orElse: unexpectedStatus })) ), - "listOrganizationCertificates": (options) => - HttpClientRequest.get(`/organization/certificates`).pipe( + "listBatches": (options: Parameters[0]) => + HttpClientRequest.get("/batches").pipe( HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any + "limit": options?.params?.["limit"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListOrganizationCertificates200), - orElse: unexpectedStatus - })) - ), - "uploadCertificate": (options) => - HttpClientRequest.post(`/organization/certificates`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UploadCertificate200), + "2xx": decodeSuccess(ListBatches200), + "400": decodeError("ListBatches400", ListBatches400), + "404": decodeError("ListBatches404", ListBatches404), + "429": decodeError("ListBatches429", ListBatches429), orElse: unexpectedStatus })) ), - "activateOrganizationCertificates": (options) => - HttpClientRequest.post(`/organization/certificates/activate`).pipe( + "createBatch": (options: Parameters[0]) => + HttpClientRequest.post("/batches").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ActivateOrganizationCertificates200), + "2xx": decodeSuccess(CreateBatch200), + "400": decodeError("CreateBatch400", CreateBatch400), + "429": decodeError("CreateBatch429", CreateBatch429), + "500": decodeError("CreateBatch500", CreateBatch500), + "503": decodeError("CreateBatch503", CreateBatch503), orElse: unexpectedStatus })) ), - "deactivateOrganizationCertificates": (options) => - HttpClientRequest.post(`/organization/certificates/deactivate`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeactivateOrganizationCertificates200), - orElse: unexpectedStatus - })) + "retrieveBatch": (batchId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [batchId], () => "/batches/" + __encodePathParam(batchId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveBatch200), + "400": decodeError("RetrieveBatch400", RetrieveBatch400), + "404": decodeError("RetrieveBatch404", RetrieveBatch404), + "429": decodeError("RetrieveBatch429", RetrieveBatch429), + orElse: unexpectedStatus + })) + ) + ) ), - "getCertificate": (certificateId, options) => - HttpClientRequest.get(`/organization/certificates/${certificateId}`).pipe( - HttpClientRequest.setUrlParams({ "include": options?.params?.["include"] as any }), + "cancelBatch": (batchId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [batchId], () => "/batches/" + __encodePathParam(batchId) + "/cancel") + .pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CancelBatch200), + "400": decodeError("CancelBatch400", CancelBatch400), + "404": decodeError("CancelBatch404", CancelBatch404), + "409": decodeError("CancelBatch409", CancelBatch409), + "429": decodeError("CancelBatch429", CancelBatch429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listChatCompletions": (options: Parameters[0]) => + HttpClientRequest.get("/chat/completions").pipe( + HttpClientRequest.setUrlParams({ + "model": options?.params?.["model"] as any, + "metadata": options?.params?.["metadata"] as any, + "after": options?.params?.["after"] as any, + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any + }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetCertificate200), + "2xx": decodeSuccess(ListChatCompletions200), + "400": decodeError("ListChatCompletions400", ListChatCompletions400), + "429": decodeError("ListChatCompletions429", ListChatCompletions429), + "500": decodeError("ListChatCompletions500", ListChatCompletions500), orElse: unexpectedStatus })) ), - "modifyCertificate": (certificateId, options) => - HttpClientRequest.post(`/organization/certificates/${certificateId}`).pipe( + "createChatCompletion": (options: Parameters[0]) => + HttpClientRequest.post("/chat/completions").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyCertificate200), + "2xx": decodeSuccess(CreateChatCompletion200), + "400": decodeError("CreateChatCompletion400", CreateChatCompletion400), + "401": decodeError("CreateChatCompletion401", CreateChatCompletion401), + "404": decodeError("CreateChatCompletion404", CreateChatCompletion404), + "429": decodeError("CreateChatCompletion429", CreateChatCompletion429), + "500": decodeError("CreateChatCompletion500", CreateChatCompletion500), + "503": decodeError("CreateChatCompletion503", CreateChatCompletion503), orElse: unexpectedStatus })) ), - "deleteCertificate": (certificateId, options) => - HttpClientRequest.delete(`/organization/certificates/${certificateId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteCertificate200), - orElse: unexpectedStatus - })) + "createChatCompletionSse": (options) => + HttpClientRequest.post("/chat/completions").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + sseRequest(CreateChatCompletion200Sse) ), - "usageCosts": (options) => - HttpClientRequest.get(`/organization/costs`).pipe( - HttpClientRequest.setUrlParams({ - "start_time": options.params["start_time"] as any, - "end_time": options.params["end_time"] as any, - "bucket_width": options.params["bucket_width"] as any, - "project_ids": options.params["project_ids"] as any, - "api_key_ids": options.params["api_key_ids"] as any, - "group_by": options.params["group_by"] as any, - "limit": options.params["limit"] as any, - "page": options.params["page"] as any - }), + "getChatCompletion": (completionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [completionId], + () => "/chat/completions/" + __encodePathParam(completionId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetChatCompletion200), + "404": decodeError("GetChatCompletion404", GetChatCompletion404), + "429": decodeError("GetChatCompletion429", GetChatCompletion429), + "500": decodeError("GetChatCompletion500", GetChatCompletion500), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateChatCompletion": (completionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [completionId], + () => "/chat/completions/" + __encodePathParam(completionId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateChatCompletion200), + "400": decodeError("UpdateChatCompletion400", UpdateChatCompletion400), + "404": decodeError("UpdateChatCompletion404", UpdateChatCompletion404), + "429": decodeError("UpdateChatCompletion429", UpdateChatCompletion429), + "500": decodeError("UpdateChatCompletion500", UpdateChatCompletion500), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteChatCompletion": (completionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [completionId], + () => "/chat/completions/" + __encodePathParam(completionId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteChatCompletion200), + "404": decodeError("DeleteChatCompletion404", DeleteChatCompletion404), + "429": decodeError("DeleteChatCompletion429", DeleteChatCompletion429), + "500": decodeError("DeleteChatCompletion500", DeleteChatCompletion500), + orElse: unexpectedStatus + })) + ) + ) + ), + "getChatCompletionMessages": (completionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [completionId], + () => "/chat/completions/" + __encodePathParam(completionId) + "/messages" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "after": options?.params?.["after"] as any, + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetChatCompletionMessages200), + "400": decodeError("GetChatCompletionMessages400", GetChatCompletionMessages400), + "404": decodeError("GetChatCompletionMessages404", GetChatCompletionMessages404), + "429": decodeError("GetChatCompletionMessages429", GetChatCompletionMessages429), + "500": decodeError("GetChatCompletionMessages500", GetChatCompletionMessages500), + orElse: unexpectedStatus + })) + ) + ) + ), + "createCompletion": (options: Parameters[0]) => + HttpClientRequest.post("/completions").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UsageCosts200), + "2xx": decodeSuccess(CreateCompletion200), + "400": decodeError("CreateCompletion400", CreateCompletion400), + "401": decodeError("CreateCompletion401", CreateCompletion401), + "404": decodeError("CreateCompletion404", CreateCompletion404), + "429": decodeError("CreateCompletion429", CreateCompletion429), + "500": decodeError("CreateCompletion500", CreateCompletion500), + "503": decodeError("CreateCompletion503", CreateCompletion503), orElse: unexpectedStatus })) ), - "listGroups": (options) => - HttpClientRequest.get(`/organization/groups`).pipe( + "ListContainers": (options: Parameters[0]) => + HttpClientRequest.get("/containers").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any + "name": options?.params?.["name"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListGroups200), + "2xx": decodeSuccess(ListContainers200), + "404": decodeError("ListContainers404", ListContainers404), + "429": decodeError("ListContainers429", ListContainers429), orElse: unexpectedStatus })) ), - "createGroup": (options) => - HttpClientRequest.post(`/organization/groups`).pipe( + "CreateContainer": (options: Parameters[0]) => + HttpClientRequest.post("/containers").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateGroup200), + "2xx": decodeSuccess(CreateContainer200), + "400": decodeError("CreateContainer400", CreateContainer400), + "429": decodeError("CreateContainer429", CreateContainer429), orElse: unexpectedStatus })) ), - "updateGroup": (groupId, options) => - HttpClientRequest.post(`/organization/groups/${groupId}`).pipe( + "RetrieveContainer": (containerId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [containerId], + () => "/containers/" + __encodePathParam(containerId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveContainer200), + "404": decodeError("RetrieveContainer404", RetrieveContainer404), + "429": decodeError("RetrieveContainer429", RetrieveContainer429), + orElse: unexpectedStatus + })) + ) + ) + ), + "DeleteContainer": (containerId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [containerId], + () => "/containers/" + __encodePathParam(containerId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteContainer200), + "404": decodeError("DeleteContainer404", DeleteContainer404), + "429": decodeError("DeleteContainer429", DeleteContainer429), + orElse: unexpectedStatus + })) + ) + ) + ), + "ListContainerFiles": (containerId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [containerId], + () => "/containers/" + __encodePathParam(containerId) + "/files" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListContainerFiles200), + "404": decodeError("ListContainerFiles404", ListContainerFiles404), + "429": decodeError("ListContainerFiles429", ListContainerFiles429), + orElse: unexpectedStatus + })) + ) + ) + ), + "CreateContainerFile": (containerId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [containerId], + () => "/containers/" + __encodePathParam(containerId) + "/files" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateContainerFile200), + "400": decodeError("CreateContainerFile400", CreateContainerFile400), + "404": decodeError("CreateContainerFile404", CreateContainerFile404), + "429": decodeError("CreateContainerFile429", CreateContainerFile429), + orElse: unexpectedStatus + })) + ) + ) + ), + "RetrieveContainerFile": (containerId, fileId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [containerId, fileId], + () => "/containers/" + __encodePathParam(containerId) + "/files/" + __encodePathParam(fileId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveContainerFile200), + "404": decodeError("RetrieveContainerFile404", RetrieveContainerFile404), + "429": decodeError("RetrieveContainerFile429", RetrieveContainerFile429), + orElse: unexpectedStatus + })) + ) + ) + ), + "DeleteContainerFile": (containerId, fileId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [containerId, fileId], + () => "/containers/" + __encodePathParam(containerId) + "/files/" + __encodePathParam(fileId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteContainerFile200), + "404": decodeError("DeleteContainerFile404", DeleteContainerFile404), + "429": decodeError("DeleteContainerFile429", DeleteContainerFile429), + orElse: unexpectedStatus + })) + ) + ) + ), + "RetrieveContainerFileContent": ( + containerId, + fileId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [containerId, fileId], + () => "/containers/" + __encodePathParam(containerId) + "/files/" + __encodePathParam(fileId) + "/content" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeBinary, + "404": decodeError("RetrieveContainerFileContent404", RetrieveContainerFileContent404), + "429": decodeError("RetrieveContainerFileContent429", RetrieveContainerFileContent429), + orElse: unexpectedStatus + })) + ) + ) + ), + "RetrieveContainerFileContentStream": (containerId, fileId) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.get, [containerId, fileId], () => + "/containers/" + __encodePathParam(containerId) + "/files/" + __encodePathParam(fileId) + "/content").pipe( + Effect.map((request) => + request.pipe( + binaryRequest + ) + ) + ) + ), + "listConversationItems": (conversationId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [conversationId], + () => "/conversations/" + __encodePathParam(conversationId) + "/items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "include": options?.params?.["include"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListConversationItems200), + "400": decodeError("ListConversationItems400", ListConversationItems400), + "404": decodeError("ListConversationItems404", ListConversationItems404), + "429": decodeError("ListConversationItems429", ListConversationItems429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createConversationItems": (conversationId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [conversationId], + () => "/conversations/" + __encodePathParam(conversationId) + "/items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "include": options.params?.["include"] as any }), + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateConversationItems200), + "400": decodeError("CreateConversationItems400", CreateConversationItems400), + "404": decodeError("CreateConversationItems404", CreateConversationItems404), + "429": decodeError("CreateConversationItems429", CreateConversationItems429), + "500": decodeError("CreateConversationItems500", CreateConversationItems500), + orElse: unexpectedStatus + })) + ) + ) + ), + "getConversationItem": (conversationId, itemId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [conversationId, itemId], + () => "/conversations/" + __encodePathParam(conversationId) + "/items/" + __encodePathParam(itemId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "include": options?.params?.["include"] as any }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetConversationItem200), + "404": decodeError("GetConversationItem404", GetConversationItem404), + "429": decodeError("GetConversationItem429", GetConversationItem429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteConversationItem": ( + conversationId, + itemId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.delete, + [conversationId, itemId], + () => "/conversations/" + __encodePathParam(conversationId) + "/items/" + __encodePathParam(itemId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteConversationItem200), + "400": decodeError("DeleteConversationItem400", DeleteConversationItem400), + "404": decodeError("DeleteConversationItem404", DeleteConversationItem404), + "429": decodeError("DeleteConversationItem429", DeleteConversationItem429), + "500": decodeError("DeleteConversationItem500", DeleteConversationItem500), + orElse: unexpectedStatus + })) + ) + ) + ), + "createEmbedding": (options: Parameters[0]) => + HttpClientRequest.post("/embeddings").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateGroup200), - orElse: unexpectedStatus - })) - ), - "deleteGroup": (groupId, options) => - HttpClientRequest.delete(`/organization/groups/${groupId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteGroup200), + "2xx": decodeSuccess(CreateEmbedding200), + "400": decodeError("CreateEmbedding400", CreateEmbedding400), + "401": decodeError("CreateEmbedding401", CreateEmbedding401), + "429": decodeError("CreateEmbedding429", CreateEmbedding429), + "500": decodeError("CreateEmbedding500", CreateEmbedding500), + "503": decodeError("CreateEmbedding503", CreateEmbedding503), orElse: unexpectedStatus })) ), - "listGroupRoleAssignments": (groupId, options) => - HttpClientRequest.get(`/organization/groups/${groupId}/roles`).pipe( + "listEvals": (options: Parameters[0]) => + HttpClientRequest.get("/evals").pipe( HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "order_by": options?.params?.["order_by"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListGroupRoleAssignments200), + "2xx": decodeSuccess(ListEvals200), + "429": decodeError("ListEvals429", ListEvals429), orElse: unexpectedStatus })) ), - "assignGroupRole": (groupId, options) => - HttpClientRequest.post(`/organization/groups/${groupId}/roles`).pipe( + "createEval": (options: Parameters[0]) => + HttpClientRequest.post("/evals").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AssignGroupRole200), + "2xx": decodeSuccess(CreateEval201), + "400": decodeError("CreateEval400", CreateEval400), + "429": decodeError("CreateEval429", CreateEval429), orElse: unexpectedStatus })) ), - "unassignGroupRole": (groupId, roleId, options) => - HttpClientRequest.delete(`/organization/groups/${groupId}/roles/${roleId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UnassignGroupRole200), - orElse: unexpectedStatus - })) + "getEval": (evalId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [evalId], () => "/evals/" + __encodePathParam(evalId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetEval200), + "404": decodeError("GetEval404", GetEval404), + "429": decodeError("GetEval429", GetEval429), + orElse: unexpectedStatus + })) + ) + ) ), - "listGroupUsers": (groupId, options) => - HttpClientRequest.get(`/organization/groups/${groupId}/users`).pipe( + "updateEval": (evalId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [evalId], () => "/evals/" + __encodePathParam(evalId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateEval200), + "400": decodeError("UpdateEval400", UpdateEval400), + "404": decodeError("UpdateEval404", UpdateEval404), + "429": decodeError("UpdateEval429", UpdateEval429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteEval": (evalId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.delete, [evalId], () => "/evals/" + __encodePathParam(evalId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteEval200), + "400": decodeError("DeleteEval400", DeleteEval400), + "404": decodeError("DeleteEval404", DeleteEval404), + "429": decodeError("DeleteEval429", DeleteEval429), + orElse: unexpectedStatus + })) + ) + ) + ), + "getEvalRuns": (evalId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [evalId], () => "/evals/" + __encodePathParam(evalId) + "/runs").pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "after": options?.params?.["after"] as any, + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "status": options?.params?.["status"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetEvalRuns200), + "400": decodeError("GetEvalRuns400", GetEvalRuns400), + "404": decodeError("GetEvalRuns404", GetEvalRuns404), + "429": decodeError("GetEvalRuns429", GetEvalRuns429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createEvalRun": (evalId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [evalId], () => "/evals/" + __encodePathParam(evalId) + "/runs").pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateEvalRun201), + "400": decodeError("CreateEvalRun400", CreateEvalRun400), + "404": decodeError("CreateEvalRun404", CreateEvalRun404), + "429": decodeError("CreateEvalRun429", CreateEvalRun429), + "500": decodeError("CreateEvalRun500", CreateEvalRun500), + orElse: unexpectedStatus + })) + ) + ) + ), + "getEvalRun": (evalId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [evalId, runId], + () => "/evals/" + __encodePathParam(evalId) + "/runs/" + __encodePathParam(runId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetEvalRun200), + "400": decodeError("GetEvalRun400", GetEvalRun400), + "404": decodeError("GetEvalRun404", GetEvalRun404), + "429": decodeError("GetEvalRun429", GetEvalRun429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteEvalRun": (evalId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [evalId, runId], + () => "/evals/" + __encodePathParam(evalId) + "/runs/" + __encodePathParam(runId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteEvalRun200), + "400": decodeError("DeleteEvalRun400", DeleteEvalRun400), + "404": decodeError("DeleteEvalRun404", DeleteEvalRun404), + "429": decodeError("DeleteEvalRun429", DeleteEvalRun429), + orElse: unexpectedStatus + })) + ) + ) + ), + "cancelEvalRun": (evalId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [evalId, runId], + () => "/evals/" + __encodePathParam(evalId) + "/runs/" + __encodePathParam(runId) + "/cancel" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CancelEvalRun200), + "429": decodeError("CancelEvalRun429", CancelEvalRun429), + orElse: unexpectedStatus + })) + ) + ) + ), + "getEvalRunOutputItems": (evalId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [evalId, runId], + () => "/evals/" + __encodePathParam(evalId) + "/runs/" + __encodePathParam(runId) + "/output_items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "after": options?.params?.["after"] as any, + "limit": options?.params?.["limit"] as any, + "status": options?.params?.["status"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetEvalRunOutputItems200), + "400": decodeError("GetEvalRunOutputItems400", GetEvalRunOutputItems400), + "404": decodeError("GetEvalRunOutputItems404", GetEvalRunOutputItems404), + "429": decodeError("GetEvalRunOutputItems429", GetEvalRunOutputItems429), + orElse: unexpectedStatus + })) + ) + ) + ), + "getEvalRunOutputItem": ( + evalId, + runId, + outputItemId, + options: Parameters[3] + ) => + __makePathRequest( + HttpClientRequest.get, + [evalId, runId, outputItemId], + () => + "/evals/" + __encodePathParam(evalId) + "/runs/" + __encodePathParam(runId) + "/output_items/" + + __encodePathParam(outputItemId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetEvalRunOutputItem200), + "400": decodeError("GetEvalRunOutputItem400", GetEvalRunOutputItem400), + "404": decodeError("GetEvalRunOutputItem404", GetEvalRunOutputItem404), + "429": decodeError("GetEvalRunOutputItem429", GetEvalRunOutputItem429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listFiles": (options: Parameters[0]) => + HttpClientRequest.get("/files").pipe( HttpClientRequest.setUrlParams({ + "purpose": options?.params?.["purpose"] as any, "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListGroupUsers200), + "2xx": decodeSuccess(ListFiles200), + "400": decodeError("ListFiles400", ListFiles400), + "404": decodeError("ListFiles404", ListFiles404), + "429": decodeError("ListFiles429", ListFiles429), + orElse: unexpectedStatus + })) + ), + "createFile": (options: Parameters[0]) => + HttpClientRequest.post("/files").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateFile200), + "400": decodeError("CreateFile400", CreateFile400), + "429": decodeError("CreateFile429", CreateFile429), + "500": decodeError("CreateFile500", CreateFile500), orElse: unexpectedStatus })) ), - "addGroupUser": (groupId, options) => - HttpClientRequest.post(`/organization/groups/${groupId}/users`).pipe( + "retrieveFile": (fileId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [fileId], () => "/files/" + __encodePathParam(fileId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveFile200), + "404": decodeError("RetrieveFile404", RetrieveFile404), + "429": decodeError("RetrieveFile429", RetrieveFile429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteFile": (fileId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.delete, [fileId], () => "/files/" + __encodePathParam(fileId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteFile200), + "404": decodeError("DeleteFile404", DeleteFile404), + "429": decodeError("DeleteFile429", DeleteFile429), + orElse: unexpectedStatus + })) + ) + ) + ), + "downloadFile": (fileId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [fileId], () => "/files/" + __encodePathParam(fileId) + "/content").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeBinary, + "400": decodeError("DownloadFile400", DownloadFile400), + "404": decodeError("DownloadFile404", DownloadFile404), + "429": decodeError("DownloadFile429", DownloadFile429), + "500": decodeError("DownloadFile500", DownloadFile500), + orElse: unexpectedStatus + })) + ) + ) + ), + "downloadFileStream": (fileId) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.get, [fileId], () => "/files/" + __encodePathParam(fileId) + "/content") + .pipe( + Effect.map((request) => + request.pipe( + binaryRequest + ) + ) + ) + ), + "runGrader": (options: Parameters[0]) => + HttpClientRequest.post("/fine_tuning/alpha/graders/run").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AddGroupUser200), + "2xx": decodeSuccess(RunGrader200), + "400": decodeError("RunGrader400", RunGrader400), + "429": decodeError("RunGrader429", RunGrader429), orElse: unexpectedStatus })) ), - "removeGroupUser": (groupId, userId, options) => - HttpClientRequest.delete(`/organization/groups/${groupId}/users/${userId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RemoveGroupUser200), + "validateGrader": (options: Parameters[0]) => + HttpClientRequest.post("/fine_tuning/alpha/graders/validate").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ValidateGrader200), + "400": decodeError("ValidateGrader400", ValidateGrader400), + "429": decodeError("ValidateGrader429", ValidateGrader429), orElse: unexpectedStatus })) ), - "listInvites": (options) => - HttpClientRequest.get(`/organization/invites`).pipe( + "listFineTuningCheckpointPermissions": ( + fineTunedModelCheckpoint, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.get, + [fineTunedModelCheckpoint], + () => "/fine_tuning/checkpoints/" + __encodePathParam(fineTunedModelCheckpoint) + "/permissions" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "project_id": options?.params?.["project_id"] as any, + "after": options?.params?.["after"] as any, + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListFineTuningCheckpointPermissions200), + "400": decodeError("ListFineTuningCheckpointPermissions400", ListFineTuningCheckpointPermissions400), + "429": decodeError("ListFineTuningCheckpointPermissions429", ListFineTuningCheckpointPermissions429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createFineTuningCheckpointPermission": ( + fineTunedModelCheckpoint, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.post, + [fineTunedModelCheckpoint], + () => "/fine_tuning/checkpoints/" + __encodePathParam(fineTunedModelCheckpoint) + "/permissions" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateFineTuningCheckpointPermission200), + "400": decodeError("CreateFineTuningCheckpointPermission400", CreateFineTuningCheckpointPermission400), + "404": decodeError("CreateFineTuningCheckpointPermission404", CreateFineTuningCheckpointPermission404), + "429": decodeError("CreateFineTuningCheckpointPermission429", CreateFineTuningCheckpointPermission429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteFineTuningCheckpointPermission": ( + fineTunedModelCheckpoint, + permissionId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.delete, + [fineTunedModelCheckpoint, permissionId], + () => + "/fine_tuning/checkpoints/" + __encodePathParam(fineTunedModelCheckpoint) + "/permissions/" + + __encodePathParam(permissionId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteFineTuningCheckpointPermission200), + "400": decodeError("DeleteFineTuningCheckpointPermission400", DeleteFineTuningCheckpointPermission400), + "404": decodeError("DeleteFineTuningCheckpointPermission404", DeleteFineTuningCheckpointPermission404), + "429": decodeError("DeleteFineTuningCheckpointPermission429", DeleteFineTuningCheckpointPermission429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listPaginatedFineTuningJobs": (options: Parameters[0]) => + HttpClientRequest.get("/fine_tuning/jobs").pipe( HttpClientRequest.setUrlParams({ + "after": options?.params?.["after"] as any, "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any + "metadata": options?.params?.["metadata"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListInvites200), + "2xx": decodeSuccess(ListPaginatedFineTuningJobs200), + "400": decodeError("ListPaginatedFineTuningJobs400", ListPaginatedFineTuningJobs400), + "429": decodeError("ListPaginatedFineTuningJobs429", ListPaginatedFineTuningJobs429), orElse: unexpectedStatus })) ), - "inviteUser": (options) => - HttpClientRequest.post(`/organization/invites`).pipe( + "createFineTuningJob": (options: Parameters[0]) => + HttpClientRequest.post("/fine_tuning/jobs").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(InviteUser200), + "2xx": decodeSuccess(CreateFineTuningJob200), + "400": decodeError("CreateFineTuningJob400", CreateFineTuningJob400), + "429": decodeError("CreateFineTuningJob429", CreateFineTuningJob429), orElse: unexpectedStatus })) ), - "retrieveInvite": (inviteId, options) => - HttpClientRequest.get(`/organization/invites/${inviteId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveInvite200), + "retrieveFineTuningJob": (fineTuningJobId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [fineTuningJobId], + () => "/fine_tuning/jobs/" + __encodePathParam(fineTuningJobId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveFineTuningJob200), + "404": decodeError("RetrieveFineTuningJob404", RetrieveFineTuningJob404), + "429": decodeError("RetrieveFineTuningJob429", RetrieveFineTuningJob429), + orElse: unexpectedStatus + })) + ) + ) + ), + "cancelFineTuningJob": (fineTuningJobId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [fineTuningJobId], + () => "/fine_tuning/jobs/" + __encodePathParam(fineTuningJobId) + "/cancel" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CancelFineTuningJob200), + "400": decodeError("CancelFineTuningJob400", CancelFineTuningJob400), + "404": decodeError("CancelFineTuningJob404", CancelFineTuningJob404), + "429": decodeError("CancelFineTuningJob429", CancelFineTuningJob429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listFineTuningJobCheckpoints": ( + fineTuningJobId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.get, + [fineTuningJobId], + () => "/fine_tuning/jobs/" + __encodePathParam(fineTuningJobId) + "/checkpoints" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "after": options?.params?.["after"] as any, + "limit": options?.params?.["limit"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListFineTuningJobCheckpoints200), + "400": decodeError("ListFineTuningJobCheckpoints400", ListFineTuningJobCheckpoints400), + "404": decodeError("ListFineTuningJobCheckpoints404", ListFineTuningJobCheckpoints404), + "429": decodeError("ListFineTuningJobCheckpoints429", ListFineTuningJobCheckpoints429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listFineTuningEvents": (fineTuningJobId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [fineTuningJobId], + () => "/fine_tuning/jobs/" + __encodePathParam(fineTuningJobId) + "/events" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "after": options?.params?.["after"] as any, + "limit": options?.params?.["limit"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListFineTuningEvents200), + "400": decodeError("ListFineTuningEvents400", ListFineTuningEvents400), + "404": decodeError("ListFineTuningEvents404", ListFineTuningEvents404), + "429": decodeError("ListFineTuningEvents429", ListFineTuningEvents429), + orElse: unexpectedStatus + })) + ) + ) + ), + "pauseFineTuningJob": (fineTuningJobId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [fineTuningJobId], + () => "/fine_tuning/jobs/" + __encodePathParam(fineTuningJobId) + "/pause" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(PauseFineTuningJob200), + "400": decodeError("PauseFineTuningJob400", PauseFineTuningJob400), + "404": decodeError("PauseFineTuningJob404", PauseFineTuningJob404), + "429": decodeError("PauseFineTuningJob429", PauseFineTuningJob429), + orElse: unexpectedStatus + })) + ) + ) + ), + "resumeFineTuningJob": (fineTuningJobId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [fineTuningJobId], + () => "/fine_tuning/jobs/" + __encodePathParam(fineTuningJobId) + "/resume" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ResumeFineTuningJob200), + "400": decodeError("ResumeFineTuningJob400", ResumeFineTuningJob400), + "404": decodeError("ResumeFineTuningJob404", ResumeFineTuningJob404), + "429": decodeError("ResumeFineTuningJob429", ResumeFineTuningJob429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createImageEdit": (options: Parameters[0]) => + HttpClientRequest.post("/images/edits").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateImageEdit200), + "400": decodeError("CreateImageEdit400", CreateImageEdit400), + "403": decodeError("CreateImageEdit403", CreateImageEdit403), + "410": decodeError("CreateImageEdit410", CreateImageEdit410), + "429": decodeError("CreateImageEdit429", CreateImageEdit429), + "500": decodeError("CreateImageEdit500", CreateImageEdit500), + "503": decodeError("CreateImageEdit503", CreateImageEdit503), orElse: unexpectedStatus })) ), - "deleteInvite": (inviteId, options) => - HttpClientRequest.delete(`/organization/invites/${inviteId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteInvite200), + "createImageEditSse": (options) => + HttpClientRequest.post("/images/edits").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + sseRequest(CreateImageEdit200Sse) + ), + "createImage": (options: Parameters[0]) => + HttpClientRequest.post("/images/generations").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateImage200), + "400": decodeError("CreateImage400", CreateImage400), + "403": decodeError("CreateImage403", CreateImage403), + "410": decodeError("CreateImage410", CreateImage410), + "429": decodeError("CreateImage429", CreateImage429), + "500": decodeError("CreateImage500", CreateImage500), + "503": decodeError("CreateImage503", CreateImage503), orElse: unexpectedStatus })) ), - "listProjects": (options) => - HttpClientRequest.get(`/organization/projects`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any, - "include_archived": options?.params?.["include_archived"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjects200), + "createImageSse": (options) => + HttpClientRequest.post("/images/generations").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + sseRequest(CreateImage200Sse) + ), + "createImageVariation": (options: Parameters[0]) => + HttpClientRequest.post("/images/variations").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateImageVariation200), + "400": decodeError("CreateImageVariation400", CreateImageVariation400), + "403": decodeError("CreateImageVariation403", CreateImageVariation403), + "410": decodeError("CreateImageVariation410", CreateImageVariation410), + "429": decodeError("CreateImageVariation429", CreateImageVariation429), + "500": decodeError("CreateImageVariation500", CreateImageVariation500), orElse: unexpectedStatus })) ), - "createProject": (options) => - HttpClientRequest.post(`/organization/projects`).pipe( + "createLive": (options: Parameters[0]) => + HttpClientRequest.post("/live/sessions").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateProject200), + "2xx": decodeSuccess(CreateLive201), + "400": decodeError("CreateLive400", CreateLive400), + "413": decodeError("CreateLive413", CreateLive413), + "429": decodeError("CreateLive429", CreateLive429), + "503": decodeError("CreateLive503", CreateLive503), + "504": decodeError("CreateLive504", CreateLive504), orElse: unexpectedStatus })) ), - "retrieveProject": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}`).pipe( + "acceptLiveSession": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [sessionId], + () => "/live/sessions/" + __encodePathParam(sessionId) + "/accept" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "400": decodeError("AcceptLiveSession400", AcceptLiveSession400), + "404": decodeError("AcceptLiveSession404", AcceptLiveSession404), + "409": decodeError("AcceptLiveSession409", AcceptLiveSession409), + "429": decodeError("AcceptLiveSession429", AcceptLiveSession429), + "503": decodeError("AcceptLiveSession503", AcceptLiveSession503), + "200": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) + ), + "forkLiveSession": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [sessionId], + () => "/live/sessions/" + __encodePathParam(sessionId) + "/fork" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ForkLiveSession201), + "400": decodeError("ForkLiveSession400", ForkLiveSession400), + "413": decodeError("ForkLiveSession413", ForkLiveSession413), + "429": decodeError("ForkLiveSession429", ForkLiveSession429), + "503": decodeError("ForkLiveSession503", ForkLiveSession503), + orElse: unexpectedStatus + })) + ) + ) + ), + "hangupLiveSession": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [sessionId], + () => "/live/sessions/" + __encodePathParam(sessionId) + "/hangup" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "404": decodeError("HangupLiveSession404", HangupLiveSession404), + "200": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) + ), + "referLiveSession": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [sessionId], + () => "/live/sessions/" + __encodePathParam(sessionId) + "/refer" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "400": decodeError("ReferLiveSession400", ReferLiveSession400), + "404": decodeError("ReferLiveSession404", ReferLiveSession404), + "200": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) + ), + "rejectLiveSession": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [sessionId], + () => "/live/sessions/" + __encodePathParam(sessionId) + "/reject" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "400": decodeError("RejectLiveSession400", RejectLiveSession400), + "404": decodeError("RejectLiveSession404", RejectLiveSession404), + "409": decodeError("RejectLiveSession409", RejectLiveSession409), + "200": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) + ), + "listModels": (options: Parameters[0]) => + HttpClientRequest.get("/models").pipe( withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveProject200), + "2xx": decodeSuccess(ListModels200), + "403": decodeError("ListModels403", ListModels403), orElse: unexpectedStatus })) ), - "modifyProject": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}`).pipe( + "retrieveModel": (model, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [model], () => "/models/" + __encodePathParam(model) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveModel200), + "403": decodeError("RetrieveModel403", RetrieveModel403), + "404": decodeError("RetrieveModel404", RetrieveModel404), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteModel": (model, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.delete, [model], () => "/models/" + __encodePathParam(model) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteModel200), + "403": decodeError("DeleteModel403", DeleteModel403), + "404": decodeError("DeleteModel404", DeleteModel404), + orElse: unexpectedStatus + })) + ) + ) + ), + "createModeration": (options: Parameters[0]) => + HttpClientRequest.post("/moderations").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyProject200), - "400": decodeError("ModifyProject400", ModifyProject400), + "2xx": decodeSuccess(CreateModeration200), + "400": decodeError("CreateModeration400", CreateModeration400), + "403": decodeError("CreateModeration403", CreateModeration403), + "429": decodeError("CreateModeration429", CreateModeration429), + "500": decodeError("CreateModeration500", CreateModeration500), + "503": decodeError("CreateModeration503", CreateModeration503), orElse: unexpectedStatus })) ), - "listProjectApiKeys": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/api_keys`).pipe( + "adminApiKeysList": (options: Parameters[0]) => + HttpClientRequest.get("/organization/admin_api_keys").pipe( HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any, + "limit": options?.params?.["limit"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectApiKeys200), + "2xx": decodeSuccess(AdminApiKeysList200), + "400": decodeError("AdminApiKeysList400", AdminApiKeysList400), + "403": decodeError("AdminApiKeysList403", AdminApiKeysList403), orElse: unexpectedStatus })) ), - "retrieveProjectApiKey": (projectId, apiKeyId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/api_keys/${apiKeyId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveProjectApiKey200), + "adminApiKeysCreate": (options: Parameters[0]) => + HttpClientRequest.post("/organization/admin_api_keys").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AdminApiKeysCreate200), + "400": decodeError("AdminApiKeysCreate400", AdminApiKeysCreate400), + "403": decodeError("AdminApiKeysCreate403", AdminApiKeysCreate403), + "404": decodeError("AdminApiKeysCreate404", AdminApiKeysCreate404), orElse: unexpectedStatus })) ), - "deleteProjectApiKey": (projectId, apiKeyId, options) => - HttpClientRequest.delete(`/organization/projects/${projectId}/api_keys/${apiKeyId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteProjectApiKey200), - "400": decodeError("DeleteProjectApiKey400", DeleteProjectApiKey400), - orElse: unexpectedStatus - })) + "adminApiKeysGet": (keyId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [keyId], + () => "/organization/admin_api_keys/" + __encodePathParam(keyId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AdminApiKeysGet200), + "403": decodeError("AdminApiKeysGet403", AdminApiKeysGet403), + "404": decodeError("AdminApiKeysGet404", AdminApiKeysGet404), + orElse: unexpectedStatus + })) + ) + ) + ), + "adminApiKeysDelete": (keyId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [keyId], + () => "/organization/admin_api_keys/" + __encodePathParam(keyId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AdminApiKeysDelete200), + "403": decodeError("AdminApiKeysDelete403", AdminApiKeysDelete403), + "404": decodeError("AdminApiKeysDelete404", AdminApiKeysDelete404), + orElse: unexpectedStatus + })) + ) + ) ), - "archiveProject": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/archive`).pipe( + "listAuditLogs": (options: Parameters[0]) => + HttpClientRequest.get("/organization/audit_logs").pipe( + HttpClientRequest.setUrlParams({ + "effective_at[gt]": options?.params?.["effective_at[gt]"] as any, + "effective_at[gte]": options?.params?.["effective_at[gte]"] as any, + "effective_at[lt]": options?.params?.["effective_at[lt]"] as any, + "effective_at[lte]": options?.params?.["effective_at[lte]"] as any, + "project_ids[]": options?.params?.["project_ids[]"] as any, + "event_types[]": options?.params?.["event_types[]"] as any, + "actor_ids[]": options?.params?.["actor_ids[]"] as any, + "actor_emails[]": options?.params?.["actor_emails[]"] as any, + "resource_ids[]": options?.params?.["resource_ids[]"] as any, + "tenant_only": options?.params?.["tenant_only"] as any, + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any + }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ArchiveProject200), + "2xx": decodeSuccess(ListAuditLogs200), + "400": decodeError("ListAuditLogs400", ListAuditLogs400), + "404": decodeError("ListAuditLogs404", ListAuditLogs404), + "429": decodeError("ListAuditLogs429", ListAuditLogs429), orElse: unexpectedStatus })) ), - "listProjectCertificates": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/certificates`).pipe( + "listOrganizationCertificates": (options: Parameters[0]) => + HttpClientRequest.get("/organization/certificates").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "after": options?.params?.["after"] as any, "order": options?.params?.["order"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectCertificates200), + "2xx": decodeSuccess(ListOrganizationCertificates200), + "400": decodeError("ListOrganizationCertificates400", ListOrganizationCertificates400), + "403": decodeError("ListOrganizationCertificates403", ListOrganizationCertificates403), + "429": decodeError("ListOrganizationCertificates429", ListOrganizationCertificates429), orElse: unexpectedStatus })) ), - "activateProjectCertificates": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/certificates/activate`).pipe( + "uploadCertificate": (options: Parameters[0]) => + HttpClientRequest.post("/organization/certificates").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ActivateProjectCertificates200), + "2xx": decodeSuccess(UploadCertificate200), + "400": decodeError("UploadCertificate400", UploadCertificate400), + "403": decodeError("UploadCertificate403", UploadCertificate403), + "429": decodeError("UploadCertificate429", UploadCertificate429), orElse: unexpectedStatus })) ), - "deactivateProjectCertificates": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/certificates/deactivate`).pipe( + "activateOrganizationCertificates": (options: Parameters[0]) => + HttpClientRequest.post("/organization/certificates/activate").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeactivateProjectCertificates200), - orElse: unexpectedStatus - })) - ), - "listProjectGroups": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/groups`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectGroups200), + "2xx": decodeSuccess(ActivateOrganizationCertificates200), + "400": decodeError("ActivateOrganizationCertificates400", ActivateOrganizationCertificates400), + "403": decodeError("ActivateOrganizationCertificates403", ActivateOrganizationCertificates403), + "404": decodeError("ActivateOrganizationCertificates404", ActivateOrganizationCertificates404), + "429": decodeError("ActivateOrganizationCertificates429", ActivateOrganizationCertificates429), + "500": decodeError("ActivateOrganizationCertificates500", ActivateOrganizationCertificates500), orElse: unexpectedStatus })) ), - "addProjectGroup": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/groups`).pipe( + "deactivateOrganizationCertificates": ( + options: Parameters[0] + ) => + HttpClientRequest.post("/organization/certificates/deactivate").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AddProjectGroup200), + "2xx": decodeSuccess(DeactivateOrganizationCertificates200), + "400": decodeError("DeactivateOrganizationCertificates400", DeactivateOrganizationCertificates400), + "403": decodeError("DeactivateOrganizationCertificates403", DeactivateOrganizationCertificates403), + "404": decodeError("DeactivateOrganizationCertificates404", DeactivateOrganizationCertificates404), + "429": decodeError("DeactivateOrganizationCertificates429", DeactivateOrganizationCertificates429), + "500": decodeError("DeactivateOrganizationCertificates500", DeactivateOrganizationCertificates500), orElse: unexpectedStatus })) ), - "removeProjectGroup": (projectId, groupId, options) => - HttpClientRequest.delete(`/organization/projects/${projectId}/groups/${groupId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RemoveProjectGroup200), - orElse: unexpectedStatus - })) + "getCertificate": (certificateId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [certificateId], + () => "/organization/certificates/" + __encodePathParam(certificateId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "include": options?.params?.["include"] as any }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetCertificate200), + "400": decodeError("GetCertificate400", GetCertificate400), + "403": decodeError("GetCertificate403", GetCertificate403), + "404": decodeError("GetCertificate404", GetCertificate404), + "429": decodeError("GetCertificate429", GetCertificate429), + orElse: unexpectedStatus + })) + ) + ) ), - "retrieveProjectHostedToolPermissions": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/hosted_tool_permissions`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveProjectHostedToolPermissions200), - orElse: unexpectedStatus - })) + "modifyCertificate": (certificateId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [certificateId], + () => "/organization/certificates/" + __encodePathParam(certificateId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyCertificate200), + "400": decodeError("ModifyCertificate400", ModifyCertificate400), + "403": decodeError("ModifyCertificate403", ModifyCertificate403), + "404": decodeError("ModifyCertificate404", ModifyCertificate404), + "429": decodeError("ModifyCertificate429", ModifyCertificate429), + "500": decodeError("ModifyCertificate500", ModifyCertificate500), + orElse: unexpectedStatus + })) + ) + ) ), - "updateProjectHostedToolPermissions": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/hosted_tool_permissions`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), + "deleteCertificate": (certificateId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [certificateId], + () => "/organization/certificates/" + __encodePathParam(certificateId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteCertificate200), + "400": decodeError("DeleteCertificate400", DeleteCertificate400), + "403": decodeError("DeleteCertificate403", DeleteCertificate403), + "404": decodeError("DeleteCertificate404", DeleteCertificate404), + "429": decodeError("DeleteCertificate429", DeleteCertificate429), + orElse: unexpectedStatus + })) + ) + ) + ), + "usageCosts": (options: Parameters[0]) => + HttpClientRequest.get("/organization/costs").pipe( + HttpClientRequest.setUrlParams({ + "start_time": options.params["start_time"] as any, + "end_time": options.params["end_time"] as any, + "bucket_width": options.params["bucket_width"] as any, + "project_ids": options.params["project_ids"] as any, + "api_key_ids": options.params["api_key_ids"] as any, + "line_items": options.params["line_items"] as any, + "group_by": options.params["group_by"] as any, + "limit": options.params["limit"] as any, + "page": options.params["page"] as any + }), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateProjectHostedToolPermissions200), + "2xx": decodeSuccess(UsageCosts200), + "400": decodeError("UsageCosts400", UsageCosts400), + "403": decodeError("UsageCosts403", UsageCosts403), + "429": decodeError("UsageCosts429", UsageCosts429), orElse: unexpectedStatus })) ), - "retrieveProjectModelPermissions": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/model_permissions`).pipe( + "retrieveOrganizationDataRetention": (options: Parameters[0]) => + HttpClientRequest.get("/organization/data_retention").pipe( withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveProjectModelPermissions200), + "2xx": decodeSuccess(RetrieveOrganizationDataRetention200), + "403": decodeError("RetrieveOrganizationDataRetention403", RetrieveOrganizationDataRetention403), + "404": decodeError("RetrieveOrganizationDataRetention404", RetrieveOrganizationDataRetention404), orElse: unexpectedStatus })) ), - "updateProjectModelPermissions": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/model_permissions`).pipe( + "updateOrganizationDataRetention": (options: Parameters[0]) => + HttpClientRequest.post("/organization/data_retention").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateProjectModelPermissions200), - orElse: unexpectedStatus - })) - ), - "deleteProjectModelPermissions": (projectId, options) => - HttpClientRequest.delete(`/organization/projects/${projectId}/model_permissions`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteProjectModelPermissions200), + "2xx": decodeSuccess(UpdateOrganizationDataRetention200), + "400": decodeError("UpdateOrganizationDataRetention400", UpdateOrganizationDataRetention400), + "403": decodeError("UpdateOrganizationDataRetention403", UpdateOrganizationDataRetention403), + "404": decodeError("UpdateOrganizationDataRetention404", UpdateOrganizationDataRetention404), orElse: unexpectedStatus })) ), - "listProjectRateLimits": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/rate_limits`).pipe( + "listGroups": (options: Parameters[0]) => + HttpClientRequest.get("/organization/groups").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any + "order": options?.params?.["order"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectRateLimits200), + "2xx": decodeSuccess(ListGroups200), + "400": decodeError("ListGroups400", ListGroups400), + "403": decodeError("ListGroups403", ListGroups403), + "404": decodeError("ListGroups404", ListGroups404), + "429": decodeError("ListGroups429", ListGroups429), orElse: unexpectedStatus })) ), - "updateProjectRateLimits": (projectId, rateLimitId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/rate_limits/${rateLimitId}`).pipe( + "createGroup": (options: Parameters[0]) => + HttpClientRequest.post("/organization/groups").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateProjectRateLimits200), - "400": decodeError("UpdateProjectRateLimits400", UpdateProjectRateLimits400), + "2xx": decodeSuccess(CreateGroup200), + "400": decodeError("CreateGroup400", CreateGroup400), + "403": decodeError("CreateGroup403", CreateGroup403), + "404": decodeError("CreateGroup404", CreateGroup404), + "422": decodeError("CreateGroup422", CreateGroup422), + "429": decodeError("CreateGroup429", CreateGroup429), + "500": decodeError("CreateGroup500", CreateGroup500), orElse: unexpectedStatus })) ), - "listProjectServiceAccounts": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/service_accounts`).pipe( + "retrieveGroup": (groupId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [groupId], + () => "/organization/groups/" + __encodePathParam(groupId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveGroup200), + "400": decodeError("RetrieveGroup400", RetrieveGroup400), + "403": decodeError("RetrieveGroup403", RetrieveGroup403), + "404": decodeError("RetrieveGroup404", RetrieveGroup404), + "429": decodeError("RetrieveGroup429", RetrieveGroup429), + "500": decodeError("RetrieveGroup500", RetrieveGroup500), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateGroup": (groupId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [groupId], + () => "/organization/groups/" + __encodePathParam(groupId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateGroup200), + "400": decodeError("UpdateGroup400", UpdateGroup400), + "403": decodeError("UpdateGroup403", UpdateGroup403), + "404": decodeError("UpdateGroup404", UpdateGroup404), + "429": decodeError("UpdateGroup429", UpdateGroup429), + "500": decodeError("UpdateGroup500", UpdateGroup500), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteGroup": (groupId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [groupId], + () => "/organization/groups/" + __encodePathParam(groupId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteGroup200), + "400": decodeError("DeleteGroup400", DeleteGroup400), + "403": decodeError("DeleteGroup403", DeleteGroup403), + "404": decodeError("DeleteGroup404", DeleteGroup404), + "429": decodeError("DeleteGroup429", DeleteGroup429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listGroupRoleAssignments": (groupId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [groupId], + () => "/organization/groups/" + __encodePathParam(groupId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListGroupRoleAssignments200), + "400": decodeError("ListGroupRoleAssignments400", ListGroupRoleAssignments400), + "403": decodeError("ListGroupRoleAssignments403", ListGroupRoleAssignments403), + "404": decodeError("ListGroupRoleAssignments404", ListGroupRoleAssignments404), + "429": decodeError("ListGroupRoleAssignments429", ListGroupRoleAssignments429), + orElse: unexpectedStatus + })) + ) + ) + ), + "assignGroupRole": (groupId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [groupId], + () => "/organization/groups/" + __encodePathParam(groupId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AssignGroupRole200), + "400": decodeError("AssignGroupRole400", AssignGroupRole400), + "403": decodeError("AssignGroupRole403", AssignGroupRole403), + "404": decodeError("AssignGroupRole404", AssignGroupRole404), + "429": decodeError("AssignGroupRole429", AssignGroupRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveGroupRole": (groupId, roleId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [groupId, roleId], + () => "/organization/groups/" + __encodePathParam(groupId) + "/roles/" + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveGroupRole200), + "400": decodeError("RetrieveGroupRole400", RetrieveGroupRole400), + "403": decodeError("RetrieveGroupRole403", RetrieveGroupRole403), + "404": decodeError("RetrieveGroupRole404", RetrieveGroupRole404), + "429": decodeError("RetrieveGroupRole429", RetrieveGroupRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "unassignGroupRole": (groupId, roleId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [groupId, roleId], + () => "/organization/groups/" + __encodePathParam(groupId) + "/roles/" + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UnassignGroupRole200), + "400": decodeError("UnassignGroupRole400", UnassignGroupRole400), + "403": decodeError("UnassignGroupRole403", UnassignGroupRole403), + "404": decodeError("UnassignGroupRole404", UnassignGroupRole404), + "429": decodeError("UnassignGroupRole429", UnassignGroupRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listGroupUsers": (groupId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [groupId], + () => "/organization/groups/" + __encodePathParam(groupId) + "/users" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListGroupUsers200), + "400": decodeError("ListGroupUsers400", ListGroupUsers400), + "403": decodeError("ListGroupUsers403", ListGroupUsers403), + "404": decodeError("ListGroupUsers404", ListGroupUsers404), + "429": decodeError("ListGroupUsers429", ListGroupUsers429), + "502": decodeError("ListGroupUsers502", ListGroupUsers502), + orElse: unexpectedStatus + })) + ) + ) + ), + "addGroupUser": (groupId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [groupId], + () => "/organization/groups/" + __encodePathParam(groupId) + "/users" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AddGroupUser200), + "400": decodeError("AddGroupUser400", AddGroupUser400), + "403": decodeError("AddGroupUser403", AddGroupUser403), + "404": decodeError("AddGroupUser404", AddGroupUser404), + "409": decodeError("AddGroupUser409", AddGroupUser409), + "429": decodeError("AddGroupUser429", AddGroupUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveGroupUser": (groupId, userId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [groupId, userId], + () => "/organization/groups/" + __encodePathParam(groupId) + "/users/" + __encodePathParam(userId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveGroupUser200), + "400": decodeError("RetrieveGroupUser400", RetrieveGroupUser400), + "403": decodeError("RetrieveGroupUser403", RetrieveGroupUser403), + "404": decodeError("RetrieveGroupUser404", RetrieveGroupUser404), + "429": decodeError("RetrieveGroupUser429", RetrieveGroupUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "removeGroupUser": (groupId, userId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [groupId, userId], + () => "/organization/groups/" + __encodePathParam(groupId) + "/users/" + __encodePathParam(userId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RemoveGroupUser200), + "400": decodeError("RemoveGroupUser400", RemoveGroupUser400), + "403": decodeError("RemoveGroupUser403", RemoveGroupUser403), + "404": decodeError("RemoveGroupUser404", RemoveGroupUser404), + "409": decodeError("RemoveGroupUser409", RemoveGroupUser409), + "429": decodeError("RemoveGroupUser429", RemoveGroupUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listInvites": (options: Parameters[0]) => + HttpClientRequest.get("/organization/invites").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "after": options?.params?.["after"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectServiceAccounts200), - "400": decodeError("ListProjectServiceAccounts400", ListProjectServiceAccounts400), + "2xx": decodeSuccess(ListInvites200), + "400": decodeError("ListInvites400", ListInvites400), + "403": decodeError("ListInvites403", ListInvites403), + "404": decodeError("ListInvites404", ListInvites404), + "429": decodeError("ListInvites429", ListInvites429), orElse: unexpectedStatus })) ), - "createProjectServiceAccount": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/service_accounts`).pipe( + "inviteUser": (options: Parameters[0]) => + HttpClientRequest.post("/organization/invites").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateProjectServiceAccount200), - "400": decodeError("CreateProjectServiceAccount400", CreateProjectServiceAccount400), + "200": decodeSuccess(InviteUser200), + "201": decodeSuccess(InviteUser201), + "400": decodeError("InviteUser400", InviteUser400), + "403": decodeError("InviteUser403", InviteUser403), + "429": decodeError("InviteUser429", InviteUser429), orElse: unexpectedStatus })) ), - "retrieveProjectServiceAccount": (projectId, serviceAccountId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/service_accounts/${serviceAccountId}`).pipe( + "retrieveInvite": (inviteId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [inviteId], + () => "/organization/invites/" + __encodePathParam(inviteId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveInvite200), + "400": decodeError("RetrieveInvite400", RetrieveInvite400), + "403": decodeError("RetrieveInvite403", RetrieveInvite403), + "404": decodeError("RetrieveInvite404", RetrieveInvite404), + "429": decodeError("RetrieveInvite429", RetrieveInvite429), + "500": decodeError("RetrieveInvite500", RetrieveInvite500), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteInvite": (inviteId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [inviteId], + () => "/organization/invites/" + __encodePathParam(inviteId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteInvite200), + "400": decodeError("DeleteInvite400", DeleteInvite400), + "403": decodeError("DeleteInvite403", DeleteInvite403), + "404": decodeError("DeleteInvite404", DeleteInvite404), + "429": decodeError("DeleteInvite429", DeleteInvite429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjects": (options: Parameters[0]) => + HttpClientRequest.get("/organization/projects").pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "include_archived": options?.params?.["include_archived"] as any + }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveProjectServiceAccount200), + "2xx": decodeSuccess(ListProjects200), + "400": decodeError("ListProjects400", ListProjects400), + "403": decodeError("ListProjects403", ListProjects403), + "404": decodeError("ListProjects404", ListProjects404), + "429": decodeError("ListProjects429", ListProjects429), orElse: unexpectedStatus })) ), - "deleteProjectServiceAccount": (projectId, serviceAccountId, options) => - HttpClientRequest.delete(`/organization/projects/${projectId}/service_accounts/${serviceAccountId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteProjectServiceAccount200), + "createProject": (options: Parameters[0]) => + HttpClientRequest.post("/organization/projects").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "200": decodeSuccess(CreateProject200), + "201": decodeSuccess(CreateProject201), + "400": decodeError("CreateProject400", CreateProject400), + "403": decodeError("CreateProject403", CreateProject403), + "429": decodeError("CreateProject429", CreateProject429), orElse: unexpectedStatus })) ), - "listProjectUsers": (projectId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/users`).pipe( + "retrieveProject": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProject200), + "403": decodeError("RetrieveProject403", RetrieveProject403), + "404": decodeError("RetrieveProject404", RetrieveProject404), + "429": decodeError("RetrieveProject429", RetrieveProject429), + orElse: unexpectedStatus + })) + ) + ) + ), + "modifyProject": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyProject200), + "400": decodeError("ModifyProject400", ModifyProject400), + "403": decodeError("ModifyProject403", ModifyProject403), + "404": decodeError("ModifyProject404", ModifyProject404), + "429": decodeError("ModifyProject429", ModifyProject429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectApiKeys": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/api_keys" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "owner_project_access": options?.params?.["owner_project_access"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectApiKeys200), + "400": decodeError("ListProjectApiKeys400", ListProjectApiKeys400), + "403": decodeError("ListProjectApiKeys403", ListProjectApiKeys403), + "404": decodeError("ListProjectApiKeys404", ListProjectApiKeys404), + "429": decodeError("ListProjectApiKeys429", ListProjectApiKeys429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectApiKey": (projectId, apiKeyId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [projectId, apiKeyId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/api_keys/" + __encodePathParam(apiKeyId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectApiKey200), + "400": decodeError("RetrieveProjectApiKey400", RetrieveProjectApiKey400), + "403": decodeError("RetrieveProjectApiKey403", RetrieveProjectApiKey403), + "404": decodeError("RetrieveProjectApiKey404", RetrieveProjectApiKey404), + "429": decodeError("RetrieveProjectApiKey429", RetrieveProjectApiKey429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteProjectApiKey": (projectId, apiKeyId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [projectId, apiKeyId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/api_keys/" + __encodePathParam(apiKeyId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteProjectApiKey200), + "400": decodeError("DeleteProjectApiKey400", DeleteProjectApiKey400), + "403": decodeError("DeleteProjectApiKey403", DeleteProjectApiKey403), + "404": decodeError("DeleteProjectApiKey404", DeleteProjectApiKey404), + "429": decodeError("DeleteProjectApiKey429", DeleteProjectApiKey429), + orElse: unexpectedStatus + })) + ) + ) + ), + "archiveProject": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/archive" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ArchiveProject200), + "400": decodeError("ArchiveProject400", ArchiveProject400), + "403": decodeError("ArchiveProject403", ArchiveProject403), + "404": decodeError("ArchiveProject404", ArchiveProject404), + "429": decodeError("ArchiveProject429", ArchiveProject429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectCertificates": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/certificates" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectCertificates200), + "400": decodeError("ListProjectCertificates400", ListProjectCertificates400), + "403": decodeError("ListProjectCertificates403", ListProjectCertificates403), + "429": decodeError("ListProjectCertificates429", ListProjectCertificates429), + orElse: unexpectedStatus + })) + ) + ) + ), + "activateProjectCertificates": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/certificates/activate" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ActivateProjectCertificates200), + "400": decodeError("ActivateProjectCertificates400", ActivateProjectCertificates400), + "403": decodeError("ActivateProjectCertificates403", ActivateProjectCertificates403), + "404": decodeError("ActivateProjectCertificates404", ActivateProjectCertificates404), + "429": decodeError("ActivateProjectCertificates429", ActivateProjectCertificates429), + "500": decodeError("ActivateProjectCertificates500", ActivateProjectCertificates500), + orElse: unexpectedStatus + })) + ) + ) + ), + "deactivateProjectCertificates": ( + projectId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/certificates/deactivate" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeactivateProjectCertificates200), + "400": decodeError("DeactivateProjectCertificates400", DeactivateProjectCertificates400), + "403": decodeError("DeactivateProjectCertificates403", DeactivateProjectCertificates403), + "404": decodeError("DeactivateProjectCertificates404", DeactivateProjectCertificates404), + "429": decodeError("DeactivateProjectCertificates429", DeactivateProjectCertificates429), + "500": decodeError("DeactivateProjectCertificates500", DeactivateProjectCertificates500), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectDataRetention": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/data_retention" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectDataRetention200), + "400": decodeError("RetrieveProjectDataRetention400", RetrieveProjectDataRetention400), + "403": decodeError("RetrieveProjectDataRetention403", RetrieveProjectDataRetention403), + "404": decodeError("RetrieveProjectDataRetention404", RetrieveProjectDataRetention404), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateProjectDataRetention": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/data_retention" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateProjectDataRetention200), + "400": decodeError("UpdateProjectDataRetention400", UpdateProjectDataRetention400), + "403": decodeError("UpdateProjectDataRetention403", UpdateProjectDataRetention403), + "404": decodeError("UpdateProjectDataRetention404", UpdateProjectDataRetention404), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectGroups": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/groups" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectGroups200), + "400": decodeError("ListProjectGroups400", ListProjectGroups400), + "403": decodeError("ListProjectGroups403", ListProjectGroups403), + "404": decodeError("ListProjectGroups404", ListProjectGroups404), + "429": decodeError("ListProjectGroups429", ListProjectGroups429), + orElse: unexpectedStatus + })) + ) + ) + ), + "addProjectGroup": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/groups" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AddProjectGroup200), + "400": decodeError("AddProjectGroup400", AddProjectGroup400), + "403": decodeError("AddProjectGroup403", AddProjectGroup403), + "404": decodeError("AddProjectGroup404", AddProjectGroup404), + "429": decodeError("AddProjectGroup429", AddProjectGroup429), + "500": decodeError("AddProjectGroup500", AddProjectGroup500), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectGroup": (projectId, groupId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [projectId, groupId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/groups/" + __encodePathParam(groupId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "group_type": options?.params?.["group_type"] as any }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectGroup200), + "400": decodeError("RetrieveProjectGroup400", RetrieveProjectGroup400), + "403": decodeError("RetrieveProjectGroup403", RetrieveProjectGroup403), + "404": decodeError("RetrieveProjectGroup404", RetrieveProjectGroup404), + "429": decodeError("RetrieveProjectGroup429", RetrieveProjectGroup429), + orElse: unexpectedStatus + })) + ) + ) + ), + "removeProjectGroup": (projectId, groupId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [projectId, groupId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/groups/" + __encodePathParam(groupId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RemoveProjectGroup200), + "400": decodeError("RemoveProjectGroup400", RemoveProjectGroup400), + "403": decodeError("RemoveProjectGroup403", RemoveProjectGroup403), + "404": decodeError("RemoveProjectGroup404", RemoveProjectGroup404), + "429": decodeError("RemoveProjectGroup429", RemoveProjectGroup429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectHostedToolPermissions": ( + projectId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/hosted_tool_permissions" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectHostedToolPermissions200), + "400": decodeError("RetrieveProjectHostedToolPermissions400", RetrieveProjectHostedToolPermissions400), + "403": decodeError("RetrieveProjectHostedToolPermissions403", RetrieveProjectHostedToolPermissions403), + "404": decodeError("RetrieveProjectHostedToolPermissions404", RetrieveProjectHostedToolPermissions404), + "429": decodeError("RetrieveProjectHostedToolPermissions429", RetrieveProjectHostedToolPermissions429), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateProjectHostedToolPermissions": ( + projectId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/hosted_tool_permissions" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateProjectHostedToolPermissions200), + "400": decodeError("UpdateProjectHostedToolPermissions400", UpdateProjectHostedToolPermissions400), + "403": decodeError("UpdateProjectHostedToolPermissions403", UpdateProjectHostedToolPermissions403), + "404": decodeError("UpdateProjectHostedToolPermissions404", UpdateProjectHostedToolPermissions404), + "409": decodeError("UpdateProjectHostedToolPermissions409", UpdateProjectHostedToolPermissions409), + "429": decodeError("UpdateProjectHostedToolPermissions429", UpdateProjectHostedToolPermissions429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectModelPermissions": ( + projectId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/model_permissions" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectModelPermissions200), + "400": decodeError("RetrieveProjectModelPermissions400", RetrieveProjectModelPermissions400), + "403": decodeError("RetrieveProjectModelPermissions403", RetrieveProjectModelPermissions403), + "404": decodeError("RetrieveProjectModelPermissions404", RetrieveProjectModelPermissions404), + "429": decodeError("RetrieveProjectModelPermissions429", RetrieveProjectModelPermissions429), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateProjectModelPermissions": ( + projectId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/model_permissions" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateProjectModelPermissions200), + "400": decodeError("UpdateProjectModelPermissions400", UpdateProjectModelPermissions400), + "403": decodeError("UpdateProjectModelPermissions403", UpdateProjectModelPermissions403), + "404": decodeError("UpdateProjectModelPermissions404", UpdateProjectModelPermissions404), + "429": decodeError("UpdateProjectModelPermissions429", UpdateProjectModelPermissions429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteProjectModelPermissions": ( + projectId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.delete, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/model_permissions" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteProjectModelPermissions200), + "400": decodeError("DeleteProjectModelPermissions400", DeleteProjectModelPermissions400), + "403": decodeError("DeleteProjectModelPermissions403", DeleteProjectModelPermissions403), + "404": decodeError("DeleteProjectModelPermissions404", DeleteProjectModelPermissions404), + "429": decodeError("DeleteProjectModelPermissions429", DeleteProjectModelPermissions429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectRateLimits": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/rate_limits" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectRateLimits200), + "400": decodeError("ListProjectRateLimits400", ListProjectRateLimits400), + "403": decodeError("ListProjectRateLimits403", ListProjectRateLimits403), + "404": decodeError("ListProjectRateLimits404", ListProjectRateLimits404), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateProjectRateLimits": ( + projectId, + rateLimitId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.post, + [projectId, rateLimitId], + () => + "/organization/projects/" + __encodePathParam(projectId) + "/rate_limits/" + __encodePathParam(rateLimitId) + + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateProjectRateLimits200), + "400": decodeError("UpdateProjectRateLimits400", UpdateProjectRateLimits400), + "403": decodeError("UpdateProjectRateLimits403", UpdateProjectRateLimits403), + "404": decodeError("UpdateProjectRateLimits404", UpdateProjectRateLimits404), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectServiceAccounts": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/service_accounts" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectServiceAccounts200), + "400": decodeError("ListProjectServiceAccounts400", ListProjectServiceAccounts400), + "403": decodeError("ListProjectServiceAccounts403", ListProjectServiceAccounts403), + "404": decodeError("ListProjectServiceAccounts404", ListProjectServiceAccounts404), + "429": decodeError("ListProjectServiceAccounts429", ListProjectServiceAccounts429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createProjectServiceAccount": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/service_accounts" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "200": decodeSuccess(CreateProjectServiceAccount200), + "201": decodeSuccess(CreateProjectServiceAccount201), + "400": decodeError("CreateProjectServiceAccount400", CreateProjectServiceAccount400), + "403": decodeError("CreateProjectServiceAccount403", CreateProjectServiceAccount403), + "404": decodeError("CreateProjectServiceAccount404", CreateProjectServiceAccount404), + "429": decodeError("CreateProjectServiceAccount429", CreateProjectServiceAccount429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectServiceAccount": ( + projectId, + serviceAccountId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [projectId, serviceAccountId], + () => + "/organization/projects/" + __encodePathParam(projectId) + "/service_accounts/" + + __encodePathParam(serviceAccountId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectServiceAccount200), + "400": decodeError("RetrieveProjectServiceAccount400", RetrieveProjectServiceAccount400), + "403": decodeError("RetrieveProjectServiceAccount403", RetrieveProjectServiceAccount403), + "404": decodeError("RetrieveProjectServiceAccount404", RetrieveProjectServiceAccount404), + "429": decodeError("RetrieveProjectServiceAccount429", RetrieveProjectServiceAccount429), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateProjectServiceAccount": ( + projectId, + serviceAccountId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.post, + [projectId, serviceAccountId], + () => + "/organization/projects/" + __encodePathParam(projectId) + "/service_accounts/" + + __encodePathParam(serviceAccountId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateProjectServiceAccount200), + "400": decodeError("UpdateProjectServiceAccount400", UpdateProjectServiceAccount400), + "403": decodeError("UpdateProjectServiceAccount403", UpdateProjectServiceAccount403), + "404": decodeError("UpdateProjectServiceAccount404", UpdateProjectServiceAccount404), + "429": decodeError("UpdateProjectServiceAccount429", UpdateProjectServiceAccount429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteProjectServiceAccount": ( + projectId, + serviceAccountId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.delete, + [projectId, serviceAccountId], + () => + "/organization/projects/" + __encodePathParam(projectId) + "/service_accounts/" + + __encodePathParam(serviceAccountId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteProjectServiceAccount200), + "400": decodeError("DeleteProjectServiceAccount400", DeleteProjectServiceAccount400), + "403": decodeError("DeleteProjectServiceAccount403", DeleteProjectServiceAccount403), + "404": decodeError("DeleteProjectServiceAccount404", DeleteProjectServiceAccount404), + "429": decodeError("DeleteProjectServiceAccount429", DeleteProjectServiceAccount429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectSpendAlerts": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/spend_alerts" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectSpendAlerts200), + "400": decodeError("ListProjectSpendAlerts400", ListProjectSpendAlerts400), + "403": decodeError("ListProjectSpendAlerts403", ListProjectSpendAlerts403), + "404": decodeError("ListProjectSpendAlerts404", ListProjectSpendAlerts404), + orElse: unexpectedStatus + })) + ) + ) + ), + "createProjectSpendAlert": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/spend_alerts" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateProjectSpendAlert200), + "400": decodeError("CreateProjectSpendAlert400", CreateProjectSpendAlert400), + "403": decodeError("CreateProjectSpendAlert403", CreateProjectSpendAlert403), + "404": decodeError("CreateProjectSpendAlert404", CreateProjectSpendAlert404), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectSpendAlert": ( + projectId, + alertId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [projectId, alertId], + () => + "/organization/projects/" + __encodePathParam(projectId) + "/spend_alerts/" + __encodePathParam(alertId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectSpendAlert200), + "400": decodeError("RetrieveProjectSpendAlert400", RetrieveProjectSpendAlert400), + "403": decodeError("RetrieveProjectSpendAlert403", RetrieveProjectSpendAlert403), + "404": decodeError("RetrieveProjectSpendAlert404", RetrieveProjectSpendAlert404), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateProjectSpendAlert": (projectId, alertId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [projectId, alertId], + () => + "/organization/projects/" + __encodePathParam(projectId) + "/spend_alerts/" + __encodePathParam(alertId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateProjectSpendAlert200), + "400": decodeError("UpdateProjectSpendAlert400", UpdateProjectSpendAlert400), + "403": decodeError("UpdateProjectSpendAlert403", UpdateProjectSpendAlert403), + "404": decodeError("UpdateProjectSpendAlert404", UpdateProjectSpendAlert404), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteProjectSpendAlert": (projectId, alertId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [projectId, alertId], + () => + "/organization/projects/" + __encodePathParam(projectId) + "/spend_alerts/" + __encodePathParam(alertId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteProjectSpendAlert200), + "400": decodeError("DeleteProjectSpendAlert400", DeleteProjectSpendAlert400), + "403": decodeError("DeleteProjectSpendAlert403", DeleteProjectSpendAlert403), + "404": decodeError("DeleteProjectSpendAlert404", DeleteProjectSpendAlert404), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectUsers": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/users" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectUsers200), + "400": decodeError("ListProjectUsers400", ListProjectUsers400), + "403": decodeError("ListProjectUsers403", ListProjectUsers403), + "404": decodeError("ListProjectUsers404", ListProjectUsers404), + "429": decodeError("ListProjectUsers429", ListProjectUsers429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createProjectUser": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/users" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "200": decodeSuccess(CreateProjectUser200), + "201": decodeSuccess(CreateProjectUser201), + "400": decodeError("CreateProjectUser400", CreateProjectUser400), + "403": decodeError("CreateProjectUser403", CreateProjectUser403), + "404": decodeError("CreateProjectUser404", CreateProjectUser404), + "409": decodeError("CreateProjectUser409", CreateProjectUser409), + "429": decodeError("CreateProjectUser429", CreateProjectUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectUser": (projectId, userId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [projectId, userId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/users/" + __encodePathParam(userId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectUser200), + "400": decodeError("RetrieveProjectUser400", RetrieveProjectUser400), + "403": decodeError("RetrieveProjectUser403", RetrieveProjectUser403), + "404": decodeError("RetrieveProjectUser404", RetrieveProjectUser404), + "429": decodeError("RetrieveProjectUser429", RetrieveProjectUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "modifyProjectUser": (projectId, userId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [projectId, userId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/users/" + __encodePathParam(userId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyProjectUser200), + "400": decodeError("ModifyProjectUser400", ModifyProjectUser400), + "403": decodeError("ModifyProjectUser403", ModifyProjectUser403), + "404": decodeError("ModifyProjectUser404", ModifyProjectUser404), + "429": decodeError("ModifyProjectUser429", ModifyProjectUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteProjectUser": (projectId, userId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [projectId, userId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/users/" + __encodePathParam(userId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteProjectUser200), + "400": decodeError("DeleteProjectUser400", DeleteProjectUser400), + "403": decodeError("DeleteProjectUser403", DeleteProjectUser403), + "404": decodeError("DeleteProjectUser404", DeleteProjectUser404), + "429": decodeError("DeleteProjectUser429", DeleteProjectUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listRoles": (options: Parameters[0]) => + HttpClientRequest.get("/organization/roles").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectUsers200), - "400": decodeError("ListProjectUsers400", ListProjectUsers400), - orElse: unexpectedStatus - })) - ), - "createProjectUser": (projectId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/users`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateProjectUser200), - "400": decodeError("CreateProjectUser400", CreateProjectUser400), - orElse: unexpectedStatus - })) - ), - "retrieveProjectUser": (projectId, userId, options) => - HttpClientRequest.get(`/organization/projects/${projectId}/users/${userId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveProjectUser200), + "2xx": decodeSuccess(ListRoles200), + "400": decodeError("ListRoles400", ListRoles400), + "403": decodeError("ListRoles403", ListRoles403), + "404": decodeError("ListRoles404", ListRoles404), + "429": decodeError("ListRoles429", ListRoles429), orElse: unexpectedStatus })) ), - "modifyProjectUser": (projectId, userId, options) => - HttpClientRequest.post(`/organization/projects/${projectId}/users/${userId}`).pipe( + "createRole": (options: Parameters[0]) => + HttpClientRequest.post("/organization/roles").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyProjectUser200), - "400": decodeError("ModifyProjectUser400", ModifyProjectUser400), + "2xx": decodeSuccess(CreateRole200), + "400": decodeError("CreateRole400", CreateRole400), + "403": decodeError("CreateRole403", CreateRole403), + "404": decodeError("CreateRole404", CreateRole404), + "429": decodeError("CreateRole429", CreateRole429), orElse: unexpectedStatus })) ), - "deleteProjectUser": (projectId, userId, options) => - HttpClientRequest.delete(`/organization/projects/${projectId}/users/${userId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteProjectUser200), - "400": decodeError("DeleteProjectUser400", DeleteProjectUser400), - orElse: unexpectedStatus - })) + "retrieveRole": (roleId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [roleId], () => "/organization/roles/" + __encodePathParam(roleId) + "") + .pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveRole200), + "403": decodeError("RetrieveRole403", RetrieveRole403), + "404": decodeError("RetrieveRole404", RetrieveRole404), + "429": decodeError("RetrieveRole429", RetrieveRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateRole": (roleId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [roleId], () => "/organization/roles/" + __encodePathParam(roleId) + "") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateRole200), + "400": decodeError("UpdateRole400", UpdateRole400), + "403": decodeError("UpdateRole403", UpdateRole403), + "404": decodeError("UpdateRole404", UpdateRole404), + "429": decodeError("UpdateRole429", UpdateRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteRole": (roleId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [roleId], + () => "/organization/roles/" + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteRole200), + "400": decodeError("DeleteRole400", DeleteRole400), + "403": decodeError("DeleteRole403", DeleteRole403), + "404": decodeError("DeleteRole404", DeleteRole404), + "429": decodeError("DeleteRole429", DeleteRole429), + orElse: unexpectedStatus + })) + ) + ) ), - "listRoles": (options) => - HttpClientRequest.get(`/organization/roles`).pipe( + "listOrganizationSpendAlerts": (options: Parameters[0]) => + HttpClientRequest.get("/organization/spend_alerts").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any + "before": options?.params?.["before"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListRoles200), + "2xx": decodeSuccess(ListOrganizationSpendAlerts200), + "400": decodeError("ListOrganizationSpendAlerts400", ListOrganizationSpendAlerts400), + "403": decodeError("ListOrganizationSpendAlerts403", ListOrganizationSpendAlerts403), + "404": decodeError("ListOrganizationSpendAlerts404", ListOrganizationSpendAlerts404), orElse: unexpectedStatus })) ), - "createRole": (options) => - HttpClientRequest.post(`/organization/roles`).pipe( + "createOrganizationSpendAlert": (options: Parameters[0]) => + HttpClientRequest.post("/organization/spend_alerts").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateRole200), + "2xx": decodeSuccess(CreateOrganizationSpendAlert200), + "400": decodeError("CreateOrganizationSpendAlert400", CreateOrganizationSpendAlert400), + "403": decodeError("CreateOrganizationSpendAlert403", CreateOrganizationSpendAlert403), orElse: unexpectedStatus })) ), - "updateRole": (roleId, options) => - HttpClientRequest.post(`/organization/roles/${roleId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateRole200), - orElse: unexpectedStatus - })) + "retrieveOrganizationSpendAlert": ( + alertId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.get, + [alertId], + () => "/organization/spend_alerts/" + __encodePathParam(alertId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveOrganizationSpendAlert200), + "403": decodeError("RetrieveOrganizationSpendAlert403", RetrieveOrganizationSpendAlert403), + "404": decodeError("RetrieveOrganizationSpendAlert404", RetrieveOrganizationSpendAlert404), + orElse: unexpectedStatus + })) + ) + ) ), - "deleteRole": (roleId, options) => - HttpClientRequest.delete(`/organization/roles/${roleId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteRole200), - orElse: unexpectedStatus - })) + "updateOrganizationSpendAlert": (alertId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [alertId], + () => "/organization/spend_alerts/" + __encodePathParam(alertId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateOrganizationSpendAlert200), + "400": decodeError("UpdateOrganizationSpendAlert400", UpdateOrganizationSpendAlert400), + "403": decodeError("UpdateOrganizationSpendAlert403", UpdateOrganizationSpendAlert403), + "404": decodeError("UpdateOrganizationSpendAlert404", UpdateOrganizationSpendAlert404), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteOrganizationSpendAlert": (alertId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [alertId], + () => "/organization/spend_alerts/" + __encodePathParam(alertId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteOrganizationSpendAlert200), + "403": decodeError("DeleteOrganizationSpendAlert403", DeleteOrganizationSpendAlert403), + "404": decodeError("DeleteOrganizationSpendAlert404", DeleteOrganizationSpendAlert404), + orElse: unexpectedStatus + })) + ) + ) ), - "usageAudioSpeeches": (options) => - HttpClientRequest.get(`/organization/usage/audio_speeches`).pipe( + "usageAudioSpeeches": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/audio_speeches").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31737,11 +54433,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageAudioSpeeches200), + "400": decodeError("UsageAudioSpeeches400", UsageAudioSpeeches400), + "403": decodeError("UsageAudioSpeeches403", UsageAudioSpeeches403), + "429": decodeError("UsageAudioSpeeches429", UsageAudioSpeeches429), orElse: unexpectedStatus })) ), - "usageAudioTranscriptions": (options) => - HttpClientRequest.get(`/organization/usage/audio_transcriptions`).pipe( + "usageAudioTranscriptions": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/audio_transcriptions").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31756,11 +54455,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageAudioTranscriptions200), + "400": decodeError("UsageAudioTranscriptions400", UsageAudioTranscriptions400), + "403": decodeError("UsageAudioTranscriptions403", UsageAudioTranscriptions403), + "429": decodeError("UsageAudioTranscriptions429", UsageAudioTranscriptions429), orElse: unexpectedStatus })) ), - "usageCodeInterpreterSessions": (options) => - HttpClientRequest.get(`/organization/usage/code_interpreter_sessions`).pipe( + "usageCodeInterpreterSessions": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/code_interpreter_sessions").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31772,11 +54474,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageCodeInterpreterSessions200), + "400": decodeError("UsageCodeInterpreterSessions400", UsageCodeInterpreterSessions400), + "403": decodeError("UsageCodeInterpreterSessions403", UsageCodeInterpreterSessions403), + "429": decodeError("UsageCodeInterpreterSessions429", UsageCodeInterpreterSessions429), orElse: unexpectedStatus })) ), - "usageCompletions": (options) => - HttpClientRequest.get(`/organization/usage/completions`).pipe( + "usageCompletions": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/completions").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31792,11 +54497,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageCompletions200), + "400": decodeError("UsageCompletions400", UsageCompletions400), + "403": decodeError("UsageCompletions403", UsageCompletions403), + "429": decodeError("UsageCompletions429", UsageCompletions429), orElse: unexpectedStatus })) ), - "usageEmbeddings": (options) => - HttpClientRequest.get(`/organization/usage/embeddings`).pipe( + "usageEmbeddings": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/embeddings").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31811,11 +54519,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageEmbeddings200), + "400": decodeError("UsageEmbeddings400", UsageEmbeddings400), + "403": decodeError("UsageEmbeddings403", UsageEmbeddings403), + "429": decodeError("UsageEmbeddings429", UsageEmbeddings429), orElse: unexpectedStatus })) ), - "usageFileSearchCalls": (options) => - HttpClientRequest.get(`/organization/usage/file_search_calls`).pipe( + "usageFileSearchCalls": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/file_search_calls").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31830,11 +54541,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageFileSearchCalls200), + "400": decodeError("UsageFileSearchCalls400", UsageFileSearchCalls400), + "403": decodeError("UsageFileSearchCalls403", UsageFileSearchCalls403), + "429": decodeError("UsageFileSearchCalls429", UsageFileSearchCalls429), orElse: unexpectedStatus })) ), - "usageImages": (options) => - HttpClientRequest.get(`/organization/usage/images`).pipe( + "usageImages": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/images").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31851,11 +54565,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageImages200), + "400": decodeError("UsageImages400", UsageImages400), + "403": decodeError("UsageImages403", UsageImages403), + "429": decodeError("UsageImages429", UsageImages429), orElse: unexpectedStatus })) ), - "usageModerations": (options) => - HttpClientRequest.get(`/organization/usage/moderations`).pipe( + "usageModerations": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/moderations").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31870,11 +54587,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageModerations200), + "400": decodeError("UsageModerations400", UsageModerations400), + "403": decodeError("UsageModerations403", UsageModerations403), + "429": decodeError("UsageModerations429", UsageModerations429), orElse: unexpectedStatus })) ), - "usageVectorStores": (options) => - HttpClientRequest.get(`/organization/usage/vector_stores`).pipe( + "usageVectorStores": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/vector_stores").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31886,11 +54606,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageVectorStores200), + "400": decodeError("UsageVectorStores400", UsageVectorStores400), + "403": decodeError("UsageVectorStores403", UsageVectorStores403), + "429": decodeError("UsageVectorStores429", UsageVectorStores429), orElse: unexpectedStatus })) ), - "usageWebSearchCalls": (options) => - HttpClientRequest.get(`/organization/usage/web_search_calls`).pipe( + "usageWebSearchCalls": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/web_search_calls").pipe( HttpClientRequest.setUrlParams({ "start_time": options.params["start_time"] as any, "end_time": options.params["end_time"] as any, @@ -31906,11 +54629,14 @@ export const make = ( }), withResponse(options.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(UsageWebSearchCalls200), + "400": decodeError("UsageWebSearchCalls400", UsageWebSearchCalls400), + "403": decodeError("UsageWebSearchCalls403", UsageWebSearchCalls403), + "429": decodeError("UsageWebSearchCalls429", UsageWebSearchCalls429), orElse: unexpectedStatus })) ), - "listUsers": (options) => - HttpClientRequest.get(`/organization/users`).pipe( + "listUsers": (options: Parameters[0]) => + HttpClientRequest.get("/organization/users").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "after": options?.params?.["after"] as any, @@ -31918,3855 +54644,14483 @@ export const make = ( }), withResponse(options?.config)(HttpClientResponse.matchStatus({ "2xx": decodeSuccess(ListUsers200), + "400": decodeError("ListUsers400", ListUsers400), + "403": decodeError("ListUsers403", ListUsers403), + "429": decodeError("ListUsers429", ListUsers429), orElse: unexpectedStatus })) ), - "retrieveUser": (userId, options) => - HttpClientRequest.get(`/organization/users/${userId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveUser200), - orElse: unexpectedStatus - })) + "retrieveUser": (userId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [userId], () => "/organization/users/" + __encodePathParam(userId) + "") + .pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveUser200), + "403": decodeError("RetrieveUser403", RetrieveUser403), + "404": decodeError("RetrieveUser404", RetrieveUser404), + "429": decodeError("RetrieveUser429", RetrieveUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "modifyUser": (userId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [userId], () => "/organization/users/" + __encodePathParam(userId) + "") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyUser200), + "400": decodeError("ModifyUser400", ModifyUser400), + "403": decodeError("ModifyUser403", ModifyUser403), + "404": decodeError("ModifyUser404", ModifyUser404), + "429": decodeError("ModifyUser429", ModifyUser429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteUser": (userId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [userId], + () => "/organization/users/" + __encodePathParam(userId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteUser200), + "400": decodeError("DeleteUser400", DeleteUser400), + "403": decodeError("DeleteUser403", DeleteUser403), + "404": decodeError("DeleteUser404", DeleteUser404), + "429": decodeError("DeleteUser429", DeleteUser429), + orElse: unexpectedStatus + })) + ) + ) ), - "modifyUser": (userId, options) => - HttpClientRequest.post(`/organization/users/${userId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), + "listUserRoleAssignments": (userId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [userId], + () => "/organization/users/" + __encodePathParam(userId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListUserRoleAssignments200), + "400": decodeError("ListUserRoleAssignments400", ListUserRoleAssignments400), + "403": decodeError("ListUserRoleAssignments403", ListUserRoleAssignments403), + "404": decodeError("ListUserRoleAssignments404", ListUserRoleAssignments404), + "429": decodeError("ListUserRoleAssignments429", ListUserRoleAssignments429), + orElse: unexpectedStatus + })) + ) + ) + ), + "assignUserRole": (userId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [userId], + () => "/organization/users/" + __encodePathParam(userId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AssignUserRole200), + "400": decodeError("AssignUserRole400", AssignUserRole400), + "403": decodeError("AssignUserRole403", AssignUserRole403), + "404": decodeError("AssignUserRole404", AssignUserRole404), + "429": decodeError("AssignUserRole429", AssignUserRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveUserRole": (userId, roleId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [userId, roleId], + () => "/organization/users/" + __encodePathParam(userId) + "/roles/" + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveUserRole200), + "400": decodeError("RetrieveUserRole400", RetrieveUserRole400), + "403": decodeError("RetrieveUserRole403", RetrieveUserRole403), + "404": decodeError("RetrieveUserRole404", RetrieveUserRole404), + "429": decodeError("RetrieveUserRole429", RetrieveUserRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "unassignUserRole": (userId, roleId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [userId, roleId], + () => "/organization/users/" + __encodePathParam(userId) + "/roles/" + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UnassignUserRole200), + "400": decodeError("UnassignUserRole400", UnassignUserRole400), + "403": decodeError("UnassignUserRole403", UnassignUserRole403), + "404": decodeError("UnassignUserRole404", UnassignUserRole404), + "429": decodeError("UnassignUserRole429", UnassignUserRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectGroupRoleAssignments": ( + projectId, + groupId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [projectId, groupId], + () => "/projects/" + __encodePathParam(projectId) + "/groups/" + __encodePathParam(groupId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectGroupRoleAssignments200), + "400": decodeError("ListProjectGroupRoleAssignments400", ListProjectGroupRoleAssignments400), + "403": decodeError("ListProjectGroupRoleAssignments403", ListProjectGroupRoleAssignments403), + "404": decodeError("ListProjectGroupRoleAssignments404", ListProjectGroupRoleAssignments404), + "429": decodeError("ListProjectGroupRoleAssignments429", ListProjectGroupRoleAssignments429), + orElse: unexpectedStatus + })) + ) + ) + ), + "assignProjectGroupRole": (projectId, groupId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [projectId, groupId], + () => "/projects/" + __encodePathParam(projectId) + "/groups/" + __encodePathParam(groupId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AssignProjectGroupRole200), + "400": decodeError("AssignProjectGroupRole400", AssignProjectGroupRole400), + "403": decodeError("AssignProjectGroupRole403", AssignProjectGroupRole403), + "404": decodeError("AssignProjectGroupRole404", AssignProjectGroupRole404), + "429": decodeError("AssignProjectGroupRole429", AssignProjectGroupRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectGroupRole": ( + projectId, + groupId, + roleId, + options: Parameters[3] + ) => + __makePathRequest( + HttpClientRequest.get, + [projectId, groupId, roleId], + () => + "/projects/" + __encodePathParam(projectId) + "/groups/" + __encodePathParam(groupId) + "/roles/" + + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectGroupRole200), + "400": decodeError("RetrieveProjectGroupRole400", RetrieveProjectGroupRole400), + "403": decodeError("RetrieveProjectGroupRole403", RetrieveProjectGroupRole403), + "404": decodeError("RetrieveProjectGroupRole404", RetrieveProjectGroupRole404), + "429": decodeError("RetrieveProjectGroupRole429", RetrieveProjectGroupRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "unassignProjectGroupRole": ( + projectId, + groupId, + roleId, + options: Parameters[3] + ) => + __makePathRequest( + HttpClientRequest.delete, + [projectId, groupId, roleId], + () => + "/projects/" + __encodePathParam(projectId) + "/groups/" + __encodePathParam(groupId) + "/roles/" + + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UnassignProjectGroupRole200), + "400": decodeError("UnassignProjectGroupRole400", UnassignProjectGroupRole400), + "403": decodeError("UnassignProjectGroupRole403", UnassignProjectGroupRole403), + "404": decodeError("UnassignProjectGroupRole404", UnassignProjectGroupRole404), + "429": decodeError("UnassignProjectGroupRole429", UnassignProjectGroupRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectRoles": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/projects/" + __encodePathParam(projectId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectRoles200), + "400": decodeError("ListProjectRoles400", ListProjectRoles400), + "403": decodeError("ListProjectRoles403", ListProjectRoles403), + "404": decodeError("ListProjectRoles404", ListProjectRoles404), + "429": decodeError("ListProjectRoles429", ListProjectRoles429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createProjectRole": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/projects/" + __encodePathParam(projectId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateProjectRole200), + "400": decodeError("CreateProjectRole400", CreateProjectRole400), + "403": decodeError("CreateProjectRole403", CreateProjectRole403), + "404": decodeError("CreateProjectRole404", CreateProjectRole404), + "429": decodeError("CreateProjectRole429", CreateProjectRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectRole": (projectId, roleId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [projectId, roleId], + () => "/projects/" + __encodePathParam(projectId) + "/roles/" + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectRole200), + "403": decodeError("RetrieveProjectRole403", RetrieveProjectRole403), + "404": decodeError("RetrieveProjectRole404", RetrieveProjectRole404), + "429": decodeError("RetrieveProjectRole429", RetrieveProjectRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateProjectRole": (projectId, roleId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [projectId, roleId], + () => "/projects/" + __encodePathParam(projectId) + "/roles/" + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateProjectRole200), + "400": decodeError("UpdateProjectRole400", UpdateProjectRole400), + "403": decodeError("UpdateProjectRole403", UpdateProjectRole403), + "404": decodeError("UpdateProjectRole404", UpdateProjectRole404), + "429": decodeError("UpdateProjectRole429", UpdateProjectRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteProjectRole": (projectId, roleId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [projectId, roleId], + () => "/projects/" + __encodePathParam(projectId) + "/roles/" + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteProjectRole200), + "400": decodeError("DeleteProjectRole400", DeleteProjectRole400), + "403": decodeError("DeleteProjectRole403", DeleteProjectRole403), + "404": decodeError("DeleteProjectRole404", DeleteProjectRole404), + "429": decodeError("DeleteProjectRole429", DeleteProjectRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listProjectUserRoleAssignments": ( + projectId, + userId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [projectId, userId], + () => "/projects/" + __encodePathParam(projectId) + "/users/" + __encodePathParam(userId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "after": options?.params?.["after"] as any, + "order": options?.params?.["order"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListProjectUserRoleAssignments200), + "400": decodeError("ListProjectUserRoleAssignments400", ListProjectUserRoleAssignments400), + "403": decodeError("ListProjectUserRoleAssignments403", ListProjectUserRoleAssignments403), + "404": decodeError("ListProjectUserRoleAssignments404", ListProjectUserRoleAssignments404), + "429": decodeError("ListProjectUserRoleAssignments429", ListProjectUserRoleAssignments429), + orElse: unexpectedStatus + })) + ) + ) + ), + "assignProjectUserRole": (projectId, userId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [projectId, userId], + () => "/projects/" + __encodePathParam(projectId) + "/users/" + __encodePathParam(userId) + "/roles" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AssignProjectUserRole200), + "400": decodeError("AssignProjectUserRole400", AssignProjectUserRole400), + "403": decodeError("AssignProjectUserRole403", AssignProjectUserRole403), + "404": decodeError("AssignProjectUserRole404", AssignProjectUserRole404), + "429": decodeError("AssignProjectUserRole429", AssignProjectUserRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveProjectUserRole": ( + projectId, + userId, + roleId, + options: Parameters[3] + ) => + __makePathRequest( + HttpClientRequest.get, + [projectId, userId, roleId], + () => + "/projects/" + __encodePathParam(projectId) + "/users/" + __encodePathParam(userId) + "/roles/" + + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveProjectUserRole200), + "400": decodeError("RetrieveProjectUserRole400", RetrieveProjectUserRole400), + "403": decodeError("RetrieveProjectUserRole403", RetrieveProjectUserRole403), + "404": decodeError("RetrieveProjectUserRole404", RetrieveProjectUserRole404), + "429": decodeError("RetrieveProjectUserRole429", RetrieveProjectUserRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "unassignProjectUserRole": ( + projectId, + userId, + roleId, + options: Parameters[3] + ) => + __makePathRequest( + HttpClientRequest.delete, + [projectId, userId, roleId], + () => + "/projects/" + __encodePathParam(projectId) + "/users/" + __encodePathParam(userId) + "/roles/" + + __encodePathParam(roleId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UnassignProjectUserRole200), + "400": decodeError("UnassignProjectUserRole400", UnassignProjectUserRole400), + "403": decodeError("UnassignProjectUserRole403", UnassignProjectUserRole403), + "404": decodeError("UnassignProjectUserRole404", UnassignProjectUserRole404), + "429": decodeError("UnassignProjectUserRole429", UnassignProjectUserRole429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createRealtimeCall": (options: Parameters[0]) => + HttpClientRequest.post("/realtime/calls").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyUser200), orElse: unexpectedStatus })) ), - "deleteUser": (userId, options) => - HttpClientRequest.delete(`/organization/users/${userId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteUser200), - orElse: unexpectedStatus - })) + "acceptRealtimeCall": (callId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [callId], + () => "/realtime/calls/" + __encodePathParam(callId) + "/accept" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "404": decodeError("AcceptRealtimeCall404", AcceptRealtimeCall404), + "409": decodeError("AcceptRealtimeCall409", AcceptRealtimeCall409), + "200": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) ), - "listUserRoleAssignments": (userId, options) => - HttpClientRequest.get(`/organization/users/${userId}/roles`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListUserRoleAssignments200), - orElse: unexpectedStatus - })) + "hangupRealtimeCall": (callId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [callId], + () => "/realtime/calls/" + __encodePathParam(callId) + "/hangup" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "404": decodeError("HangupRealtimeCall404", HangupRealtimeCall404), + "200": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) + ), + "referRealtimeCall": (callId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [callId], + () => "/realtime/calls/" + __encodePathParam(callId) + "/refer" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "404": decodeError("ReferRealtimeCall404", ReferRealtimeCall404), + "200": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) + ), + "rejectRealtimeCall": (callId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [callId], + () => "/realtime/calls/" + __encodePathParam(callId) + "/reject" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "404": decodeError("RejectRealtimeCall404", RejectRealtimeCall404), + "409": decodeError("RejectRealtimeCall409", RejectRealtimeCall409), + "200": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) ), - "assignUserRole": (userId, options) => - HttpClientRequest.post(`/organization/users/${userId}/roles`).pipe( + "createRealtimeClientSecret": (options: Parameters[0]) => + HttpClientRequest.post("/realtime/client_secrets").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AssignUserRole200), + "2xx": decodeSuccess(CreateRealtimeClientSecret200), + "400": decodeError("CreateRealtimeClientSecret400", CreateRealtimeClientSecret400), + "404": decodeError("CreateRealtimeClientSecret404", CreateRealtimeClientSecret404), + "500": decodeError("CreateRealtimeClientSecret500", CreateRealtimeClientSecret500), orElse: unexpectedStatus })) ), - "unassignUserRole": (userId, roleId, options) => - HttpClientRequest.delete(`/organization/users/${userId}/roles/${roleId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UnassignUserRole200), + "createRealtimeSession": (options: Parameters[0]) => + HttpClientRequest.post("/realtime/sessions").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateRealtimeSession200), orElse: unexpectedStatus })) ), - "listProjectGroupRoleAssignments": (projectId, groupId, options) => - HttpClientRequest.get(`/projects/${projectId}/groups/${groupId}/roles`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectGroupRoleAssignments200), + "createRealtimeTranscriptionSession": ( + options: Parameters[0] + ) => + HttpClientRequest.post("/realtime/transcription_sessions").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateRealtimeTranscriptionSession200), orElse: unexpectedStatus })) ), - "assignProjectGroupRole": (projectId, groupId, options) => - HttpClientRequest.post(`/projects/${projectId}/groups/${groupId}/roles`).pipe( + "createRealtimeTranslationClientSecret": ( + options: Parameters[0] + ) => + HttpClientRequest.post("/realtime/translations/client_secrets").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AssignProjectGroupRole200), + "2xx": decodeSuccess(CreateRealtimeTranslationClientSecret200), + "400": decodeError("CreateRealtimeTranslationClientSecret400", CreateRealtimeTranslationClientSecret400), + "404": decodeError("CreateRealtimeTranslationClientSecret404", CreateRealtimeTranslationClientSecret404), + "500": decodeError("CreateRealtimeTranslationClientSecret500", CreateRealtimeTranslationClientSecret500), orElse: unexpectedStatus })) ), - "unassignProjectGroupRole": (projectId, groupId, roleId, options) => - HttpClientRequest.delete(`/projects/${projectId}/groups/${groupId}/roles/${roleId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UnassignProjectGroupRole200), + "createResponse": (options: Parameters[0]) => + HttpClientRequest.post("/responses").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateResponse200), + "400": decodeError("CreateResponse400", CreateResponse400), + "404": decodeError("CreateResponse404", CreateResponse404), + "429": decodeError("CreateResponse429", CreateResponse429), + "503": decodeError("CreateResponse503", CreateResponse503), orElse: unexpectedStatus })) ), - "listProjectRoles": (projectId, options) => - HttpClientRequest.get(`/projects/${projectId}/roles`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectRoles200), - orElse: unexpectedStatus - })) + "createResponseSse": (options) => + HttpClientRequest.post("/responses").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + sseRequest(CreateResponse200Sse) + ), + "getResponse": (responseId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [responseId], () => "/responses/" + __encodePathParam(responseId) + "") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "include": options?.params?.["include"] as any, + "stream": options?.params?.["stream"] as any, + "starting_after": options?.params?.["starting_after"] as any, + "include_obfuscation": options?.params?.["include_obfuscation"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetResponse200), + "404": decodeError("GetResponse404", GetResponse404), + "429": decodeError("GetResponse429", GetResponse429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteResponse": (responseId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [responseId], + () => "/responses/" + __encodePathParam(responseId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteResponse200), + "404": decodeError("DeleteResponse404", DeleteResponse404), + "429": decodeError("DeleteResponse429", DeleteResponse429), + orElse: unexpectedStatus + })) + ) + ) + ), + "cancelResponse": (responseId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [responseId], + () => "/responses/" + __encodePathParam(responseId) + "/cancel" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CancelResponse200), + "404": decodeError("CancelResponse404", CancelResponse404), + "429": decodeError("CancelResponse429", CancelResponse429), + orElse: unexpectedStatus + })) + ) + ) ), - "createProjectRole": (projectId, options) => - HttpClientRequest.post(`/projects/${projectId}/roles`).pipe( + "listInputItems": (responseId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [responseId], + () => "/responses/" + __encodePathParam(responseId) + "/input_items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "include": options?.params?.["include"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListInputItems200), + "404": decodeError("ListInputItems404", ListInputItems404), + "429": decodeError("ListInputItems429", ListInputItems429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createThread": (options: Parameters[0]) => + HttpClientRequest.post("/threads").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateProjectRole200), + "2xx": decodeSuccess(CreateThread200), + "429": decodeError("CreateThread429", CreateThread429), orElse: unexpectedStatus })) ), - "updateProjectRole": (projectId, roleId, options) => - HttpClientRequest.post(`/projects/${projectId}/roles/${roleId}`).pipe( + "createThreadAndRun": (options: Parameters[0]) => + HttpClientRequest.post("/threads/runs").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateProjectRole200), + "2xx": decodeSuccess(CreateThreadAndRun200), + "429": decodeError("CreateThreadAndRun429", CreateThreadAndRun429), orElse: unexpectedStatus })) ), - "deleteProjectRole": (projectId, roleId, options) => - HttpClientRequest.delete(`/projects/${projectId}/roles/${roleId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteProjectRole200), + "createThreadAndRunSse": (options) => + HttpClientRequest.post("/threads/runs").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + sseRequest(CreateThreadAndRun200Sse) + ), + "getThread": (threadId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [threadId], () => "/threads/" + __encodePathParam(threadId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetThread200), + "429": decodeError("GetThread429", GetThread429), + orElse: unexpectedStatus + })) + ) + ) + ), + "modifyThread": (threadId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [threadId], () => "/threads/" + __encodePathParam(threadId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyThread200), + "429": decodeError("ModifyThread429", ModifyThread429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteThread": (threadId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.delete, [threadId], () => "/threads/" + __encodePathParam(threadId) + "") + .pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteThread200), + "429": decodeError("DeleteThread429", DeleteThread429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listMessages": (threadId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [threadId], + () => "/threads/" + __encodePathParam(threadId) + "/messages" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any, + "run_id": options?.params?.["run_id"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListMessages200), + "429": decodeError("ListMessages429", ListMessages429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createMessage": (threadId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [threadId], + () => "/threads/" + __encodePathParam(threadId) + "/messages" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateMessage200), + "429": decodeError("CreateMessage429", CreateMessage429), + orElse: unexpectedStatus + })) + ) + ) + ), + "getMessage": (threadId, messageId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [threadId, messageId], + () => "/threads/" + __encodePathParam(threadId) + "/messages/" + __encodePathParam(messageId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetMessage200), + "429": decodeError("GetMessage429", GetMessage429), + orElse: unexpectedStatus + })) + ) + ) + ), + "modifyMessage": (threadId, messageId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [threadId, messageId], + () => "/threads/" + __encodePathParam(threadId) + "/messages/" + __encodePathParam(messageId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyMessage200), + "429": decodeError("ModifyMessage429", ModifyMessage429), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteMessage": (threadId, messageId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [threadId, messageId], + () => "/threads/" + __encodePathParam(threadId) + "/messages/" + __encodePathParam(messageId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteMessage200), + "429": decodeError("DeleteMessage429", DeleteMessage429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listRuns": (threadId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [threadId], () => "/threads/" + __encodePathParam(threadId) + "/runs") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListRuns200), + "429": decodeError("ListRuns429", ListRuns429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createRun": (threadId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [threadId], () => "/threads/" + __encodePathParam(threadId) + "/runs") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "include[]": options.params?.["include[]"] as any }), + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateRun200), + "429": decodeError("CreateRun429", CreateRun429), + orElse: unexpectedStatus + })) + ) + ) + ), + "createRunSse": (threadId, options) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.post, [threadId], () => "/threads/" + __encodePathParam(threadId) + "/runs") + .pipe( + Effect.map((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "include[]": options.params?.["include[]"] as any }), + HttpClientRequest.bodyJsonUnsafe(options.payload), + sseRequest(CreateRun200Sse) + ) + ) + ) + ), + "getRun": (threadId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [threadId, runId], + () => "/threads/" + __encodePathParam(threadId) + "/runs/" + __encodePathParam(runId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetRun200), + "429": decodeError("GetRun429", GetRun429), + orElse: unexpectedStatus + })) + ) + ) + ), + "modifyRun": (threadId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [threadId, runId], + () => "/threads/" + __encodePathParam(threadId) + "/runs/" + __encodePathParam(runId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyRun200), + "429": decodeError("ModifyRun429", ModifyRun429), + orElse: unexpectedStatus + })) + ) + ) + ), + "cancelRun": (threadId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [threadId, runId], + () => "/threads/" + __encodePathParam(threadId) + "/runs/" + __encodePathParam(runId) + "/cancel" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CancelRun200), + "429": decodeError("CancelRun429", CancelRun429), + orElse: unexpectedStatus + })) + ) + ) + ), + "listRunSteps": (threadId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [threadId, runId], + () => "/threads/" + __encodePathParam(threadId) + "/runs/" + __encodePathParam(runId) + "/steps" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any, + "include[]": options?.params?.["include[]"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListRunSteps200), + "429": decodeError("ListRunSteps429", ListRunSteps429), + orElse: unexpectedStatus + })) + ) + ) + ), + "getRunStep": (threadId, runId, stepId, options: Parameters[3]) => + __makePathRequest( + HttpClientRequest.get, + [threadId, runId, stepId], + () => + "/threads/" + __encodePathParam(threadId) + "/runs/" + __encodePathParam(runId) + "/steps/" + + __encodePathParam(stepId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "include[]": options?.params?.["include[]"] as any }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetRunStep200), + "429": decodeError("GetRunStep429", GetRunStep429), + orElse: unexpectedStatus + })) + ) + ) + ), + "submitToolOuputsToRun": (threadId, runId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [threadId, runId], + () => "/threads/" + __encodePathParam(threadId) + "/runs/" + __encodePathParam(runId) + "/submit_tool_outputs" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(SubmitToolOuputsToRun200), + "429": decodeError("SubmitToolOuputsToRun429", SubmitToolOuputsToRun429), + orElse: unexpectedStatus + })) + ) + ) + ), + "submitToolOuputsToRunSse": (threadId, runId, options) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.post, [threadId, runId], () => + "/threads/" + __encodePathParam(threadId) + "/runs/" + __encodePathParam(runId) + "/submit_tool_outputs") + .pipe( + Effect.map((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + sseRequest(SubmitToolOuputsToRun200Sse) + ) + ) + ) + ), + "createUpload": (options: Parameters[0]) => + HttpClientRequest.post("/uploads").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateUpload200), + "400": decodeError("CreateUpload400", CreateUpload400), + "429": decodeError("CreateUpload429", CreateUpload429), orElse: unexpectedStatus })) ), - "listProjectUserRoleAssignments": (projectId, userId, options) => - HttpClientRequest.get(`/projects/${projectId}/users/${userId}/roles`).pipe( + "cancelUpload": (uploadId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [uploadId], () => "/uploads/" + __encodePathParam(uploadId) + "/cancel") + .pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CancelUpload200), + "400": decodeError("CancelUpload400", CancelUpload400), + "404": decodeError("CancelUpload404", CancelUpload404), + "410": decodeError("CancelUpload410", CancelUpload410), + "429": decodeError("CancelUpload429", CancelUpload429), + orElse: unexpectedStatus + })) + ) + ) + ), + "completeUpload": (uploadId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [uploadId], + () => "/uploads/" + __encodePathParam(uploadId) + "/complete" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CompleteUpload200), + "400": decodeError("CompleteUpload400", CompleteUpload400), + "404": decodeError("CompleteUpload404", CompleteUpload404), + "410": decodeError("CompleteUpload410", CompleteUpload410), + "429": decodeError("CompleteUpload429", CompleteUpload429), + "500": decodeError("CompleteUpload500", CompleteUpload500), + orElse: unexpectedStatus + })) + ) + ) + ), + "addUploadPart": (uploadId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [uploadId], () => "/uploads/" + __encodePathParam(uploadId) + "/parts") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(AddUploadPart200), + "400": decodeError("AddUploadPart400", AddUploadPart400), + "404": decodeError("AddUploadPart404", AddUploadPart404), + "410": decodeError("AddUploadPart410", AddUploadPart410), + "429": decodeError("AddUploadPart429", AddUploadPart429), + "500": decodeError("AddUploadPart500", AddUploadPart500), + orElse: unexpectedStatus + })) + ) + ) + ), + "listVectorStores": (options: Parameters[0]) => + HttpClientRequest.get("/vector_stores").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, "after": options?.params?.["after"] as any, - "order": options?.params?.["order"] as any + "before": options?.params?.["before"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListProjectUserRoleAssignments200), + "2xx": decodeSuccess(ListVectorStores200), + "429": decodeError("ListVectorStores429", ListVectorStores429), + "503": decodeError("ListVectorStores503", ListVectorStores503), orElse: unexpectedStatus })) ), - "assignProjectUserRole": (projectId, userId, options) => - HttpClientRequest.post(`/projects/${projectId}/users/${userId}/roles`).pipe( + "createVectorStore": (options: Parameters[0]) => + HttpClientRequest.post("/vector_stores").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AssignProjectUserRole200), + "2xx": decodeSuccess(CreateVectorStore200), + "400": decodeError("CreateVectorStore400", CreateVectorStore400), + "404": decodeError("CreateVectorStore404", CreateVectorStore404), + "429": decodeError("CreateVectorStore429", CreateVectorStore429), orElse: unexpectedStatus })) ), - "unassignProjectUserRole": (projectId, userId, roleId, options) => - HttpClientRequest.delete(`/projects/${projectId}/users/${userId}/roles/${roleId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UnassignProjectUserRole200), - orElse: unexpectedStatus - })) + "getVectorStore": (vectorStoreId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [vectorStoreId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetVectorStore200), + "404": decodeError("GetVectorStore404", GetVectorStore404), + "429": decodeError("GetVectorStore429", GetVectorStore429), + orElse: unexpectedStatus + })) + ) + ) ), - "createRealtimeCall": (options) => - HttpClientRequest.post(`/realtime/calls`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - orElse: unexpectedStatus - })) + "modifyVectorStore": (vectorStoreId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [vectorStoreId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ModifyVectorStore200), + "400": decodeError("ModifyVectorStore400", ModifyVectorStore400), + "403": decodeError("ModifyVectorStore403", ModifyVectorStore403), + "404": decodeError("ModifyVectorStore404", ModifyVectorStore404), + "429": decodeError("ModifyVectorStore429", ModifyVectorStore429), + orElse: unexpectedStatus + })) + ) + ) ), - "acceptRealtimeCall": (callId, options) => - HttpClientRequest.post(`/realtime/calls/${callId}/accept`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "200": () => Effect.void, - orElse: unexpectedStatus - })) + "deleteVectorStore": (vectorStoreId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [vectorStoreId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteVectorStore200), + "404": decodeError("DeleteVectorStore404", DeleteVectorStore404), + "409": decodeError("DeleteVectorStore409", DeleteVectorStore409), + "429": decodeError("DeleteVectorStore429", DeleteVectorStore429), + orElse: unexpectedStatus + })) + ) + ) ), - "hangupRealtimeCall": (callId, options) => - HttpClientRequest.post(`/realtime/calls/${callId}/hangup`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "200": () => Effect.void, - orElse: unexpectedStatus - })) + "createVectorStoreFileBatch": (vectorStoreId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [vectorStoreId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/file_batches" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateVectorStoreFileBatch200), + "400": decodeError("CreateVectorStoreFileBatch400", CreateVectorStoreFileBatch400), + "404": decodeError("CreateVectorStoreFileBatch404", CreateVectorStoreFileBatch404), + "409": decodeError("CreateVectorStoreFileBatch409", CreateVectorStoreFileBatch409), + "429": decodeError("CreateVectorStoreFileBatch429", CreateVectorStoreFileBatch429), + "500": decodeError("CreateVectorStoreFileBatch500", CreateVectorStoreFileBatch500), + orElse: unexpectedStatus + })) + ) + ) ), - "referRealtimeCall": (callId, options) => - HttpClientRequest.post(`/realtime/calls/${callId}/refer`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "200": () => Effect.void, - orElse: unexpectedStatus - })) + "getVectorStoreFileBatch": ( + vectorStoreId, + batchId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [vectorStoreId, batchId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/file_batches/" + __encodePathParam(batchId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetVectorStoreFileBatch200), + "400": decodeError("GetVectorStoreFileBatch400", GetVectorStoreFileBatch400), + "404": decodeError("GetVectorStoreFileBatch404", GetVectorStoreFileBatch404), + "429": decodeError("GetVectorStoreFileBatch429", GetVectorStoreFileBatch429), + orElse: unexpectedStatus + })) + ) + ) ), - "rejectRealtimeCall": (callId, options) => - HttpClientRequest.post(`/realtime/calls/${callId}/reject`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "200": () => Effect.void, - orElse: unexpectedStatus - })) + "cancelVectorStoreFileBatch": ( + vectorStoreId, + batchId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.post, + [vectorStoreId, batchId], + () => + "/vector_stores/" + __encodePathParam(vectorStoreId) + "/file_batches/" + __encodePathParam(batchId) + + "/cancel" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CancelVectorStoreFileBatch200), + "400": decodeError("CancelVectorStoreFileBatch400", CancelVectorStoreFileBatch400), + "404": decodeError("CancelVectorStoreFileBatch404", CancelVectorStoreFileBatch404), + "409": decodeError("CancelVectorStoreFileBatch409", CancelVectorStoreFileBatch409), + "429": decodeError("CancelVectorStoreFileBatch429", CancelVectorStoreFileBatch429), + orElse: unexpectedStatus + })) + ) + ) ), - "createRealtimeClientSecret": (options) => - HttpClientRequest.post(`/realtime/client_secrets`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateRealtimeClientSecret200), - orElse: unexpectedStatus - })) + "listFilesInVectorStoreBatch": ( + vectorStoreId, + batchId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [vectorStoreId, batchId], + () => + "/vector_stores/" + __encodePathParam(vectorStoreId) + "/file_batches/" + __encodePathParam(batchId) + + "/files" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any, + "filter": options?.params?.["filter"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListFilesInVectorStoreBatch200), + "400": decodeError("ListFilesInVectorStoreBatch400", ListFilesInVectorStoreBatch400), + "404": decodeError("ListFilesInVectorStoreBatch404", ListFilesInVectorStoreBatch404), + "429": decodeError("ListFilesInVectorStoreBatch429", ListFilesInVectorStoreBatch429), + orElse: unexpectedStatus + })) + ) + ) ), - "createRealtimeSession": (options) => - HttpClientRequest.post(`/realtime/sessions`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateRealtimeSession200), - orElse: unexpectedStatus - })) + "listVectorStoreFiles": (vectorStoreId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [vectorStoreId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/files" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any, + "filter": options?.params?.["filter"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListVectorStoreFiles200), + "400": decodeError("ListVectorStoreFiles400", ListVectorStoreFiles400), + "404": decodeError("ListVectorStoreFiles404", ListVectorStoreFiles404), + "429": decodeError("ListVectorStoreFiles429", ListVectorStoreFiles429), + orElse: unexpectedStatus + })) + ) + ) ), - "createRealtimeTranscriptionSession": (options) => - HttpClientRequest.post(`/realtime/transcription_sessions`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateRealtimeTranscriptionSession200), - orElse: unexpectedStatus - })) + "createVectorStoreFile": (vectorStoreId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [vectorStoreId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/files" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateVectorStoreFile200), + "400": decodeError("CreateVectorStoreFile400", CreateVectorStoreFile400), + "404": decodeError("CreateVectorStoreFile404", CreateVectorStoreFile404), + "409": decodeError("CreateVectorStoreFile409", CreateVectorStoreFile409), + "429": decodeError("CreateVectorStoreFile429", CreateVectorStoreFile429), + "500": decodeError("CreateVectorStoreFile500", CreateVectorStoreFile500), + orElse: unexpectedStatus + })) + ) + ) ), - "createRealtimeTranslationClientSecret": (options) => - HttpClientRequest.post(`/realtime/translations/client_secrets`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateRealtimeTranslationClientSecret200), - orElse: unexpectedStatus - })) + "getVectorStoreFile": (vectorStoreId, fileId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [vectorStoreId, fileId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/files/" + __encodePathParam(fileId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetVectorStoreFile200), + "404": decodeError("GetVectorStoreFile404", GetVectorStoreFile404), + "429": decodeError("GetVectorStoreFile429", GetVectorStoreFile429), + "500": decodeError("GetVectorStoreFile500", GetVectorStoreFile500), + orElse: unexpectedStatus + })) + ) + ) + ), + "updateVectorStoreFileAttributes": ( + vectorStoreId, + fileId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.post, + [vectorStoreId, fileId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/files/" + __encodePathParam(fileId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateVectorStoreFileAttributes200), + "400": decodeError("UpdateVectorStoreFileAttributes400", UpdateVectorStoreFileAttributes400), + "404": decodeError("UpdateVectorStoreFileAttributes404", UpdateVectorStoreFileAttributes404), + "409": decodeError("UpdateVectorStoreFileAttributes409", UpdateVectorStoreFileAttributes409), + "429": decodeError("UpdateVectorStoreFileAttributes429", UpdateVectorStoreFileAttributes429), + "500": decodeError("UpdateVectorStoreFileAttributes500", UpdateVectorStoreFileAttributes500), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteVectorStoreFile": (vectorStoreId, fileId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [vectorStoreId, fileId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/files/" + __encodePathParam(fileId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteVectorStoreFile200), + "400": decodeError("DeleteVectorStoreFile400", DeleteVectorStoreFile400), + "404": decodeError("DeleteVectorStoreFile404", DeleteVectorStoreFile404), + "409": decodeError("DeleteVectorStoreFile409", DeleteVectorStoreFile409), + "429": decodeError("DeleteVectorStoreFile429", DeleteVectorStoreFile429), + "500": decodeError("DeleteVectorStoreFile500", DeleteVectorStoreFile500), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveVectorStoreFileContent": ( + vectorStoreId, + fileId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [vectorStoreId, fileId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/files/" + __encodePathParam(fileId) + "/content" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveVectorStoreFileContent200), + "400": decodeError("RetrieveVectorStoreFileContent400", RetrieveVectorStoreFileContent400), + "404": decodeError("RetrieveVectorStoreFileContent404", RetrieveVectorStoreFileContent404), + "429": decodeError("RetrieveVectorStoreFileContent429", RetrieveVectorStoreFileContent429), + "500": decodeError("RetrieveVectorStoreFileContent500", RetrieveVectorStoreFileContent500), + orElse: unexpectedStatus + })) + ) + ) + ), + "searchVectorStore": (vectorStoreId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [vectorStoreId], + () => "/vector_stores/" + __encodePathParam(vectorStoreId) + "/search" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(SearchVectorStore200), + "400": decodeError("SearchVectorStore400", SearchVectorStore400), + "404": decodeError("SearchVectorStore404", SearchVectorStore404), + "429": decodeError("SearchVectorStore429", SearchVectorStore429), + orElse: unexpectedStatus + })) + ) + ) ), - "createResponse": (options) => - HttpClientRequest.post(`/responses`).pipe( + "createConversation": (options: Parameters[0]) => + HttpClientRequest.post("/conversations").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateResponse200), + "2xx": decodeSuccess(CreateConversation200), + "400": decodeError("CreateConversation400", CreateConversation400), + "429": decodeError("CreateConversation429", CreateConversation429), + "500": decodeError("CreateConversation500", CreateConversation500), orElse: unexpectedStatus })) ), - "createResponseSse": (options) => - HttpClientRequest.post(`/responses`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - sseRequest(CreateResponse200Sse) + "getConversation": (conversationId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [conversationId], + () => "/conversations/" + __encodePathParam(conversationId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetConversation200), + "404": decodeError("GetConversation404", GetConversation404), + "429": decodeError("GetConversation429", GetConversation429), + orElse: unexpectedStatus + })) + ) + ) ), - "getResponse": (responseId, options) => - HttpClientRequest.get(`/responses/${responseId}`).pipe( - HttpClientRequest.setUrlParams({ - "include": options?.params?.["include"] as any, - "stream": options?.params?.["stream"] as any, - "starting_after": options?.params?.["starting_after"] as any, - "include_obfuscation": options?.params?.["include_obfuscation"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetResponse200), - orElse: unexpectedStatus - })) + "updateConversation": (conversationId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [conversationId], + () => "/conversations/" + __encodePathParam(conversationId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateConversation200), + "400": decodeError("UpdateConversation400", UpdateConversation400), + "404": decodeError("UpdateConversation404", UpdateConversation404), + "429": decodeError("UpdateConversation429", UpdateConversation429), + "500": decodeError("UpdateConversation500", UpdateConversation500), + orElse: unexpectedStatus + })) + ) + ) ), - "deleteResponse": (responseId, options) => - HttpClientRequest.delete(`/responses/${responseId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "404": decodeError("DeleteResponse404", DeleteResponse404), - "200": () => Effect.void, - orElse: unexpectedStatus - })) + "deleteConversation": (conversationId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [conversationId], + () => "/conversations/" + __encodePathParam(conversationId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteConversation200), + "404": decodeError("DeleteConversation404", DeleteConversation404), + "429": decodeError("DeleteConversation429", DeleteConversation429), + orElse: unexpectedStatus + })) + ) + ) ), - "cancelResponse": (responseId, options) => - HttpClientRequest.post(`/responses/${responseId}/cancel`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CancelResponse200), - "404": decodeError("CancelResponse404", CancelResponse404), + "Getsafetycase": (id, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [id], () => "/safety/cases/" + __encodePathParam(id) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Getsafetycase200), + "400": decodeError("Getsafetycase400", Getsafetycase400), + "404": decodeError("Getsafetycase404", Getsafetycase404), + "429": decodeError("Getsafetycase429", Getsafetycase429), + "500": decodeError("Getsafetycase500", Getsafetycase500), + "503": decodeError("Getsafetycase503", Getsafetycase503), + orElse: unexpectedStatus + })) + ) + ) + ), + "Getprojectsafetyalert": (id, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [id], () => "/safety/alerts/" + __encodePathParam(id) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Getprojectsafetyalert200), + "400": decodeError("Getprojectsafetyalert400", Getprojectsafetyalert400), + "404": decodeError("Getprojectsafetyalert404", Getprojectsafetyalert404), + "429": decodeError("Getprojectsafetyalert429", Getprojectsafetyalert429), + "503": decodeError("Getprojectsafetyalert503", Getprojectsafetyalert503), + orElse: unexpectedStatus + })) + ) + ) + ), + "downloadLiveRecording": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId], + () => "/live/sessions/" + __encodePathParam(sessionId) + "/content" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeBinary, + "400": decodeError("DownloadLiveRecording400", DownloadLiveRecording400), + "404": decodeError("DownloadLiveRecording404", DownloadLiveRecording404), + "429": decodeError("DownloadLiveRecording429", DownloadLiveRecording429), + "500": decodeError("DownloadLiveRecording500", DownloadLiveRecording500), + "503": decodeError("DownloadLiveRecording503", DownloadLiveRecording503), + orElse: unexpectedStatus + })) + ) + ) + ), + "downloadLiveRecordingStream": (sessionId) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.get, [sessionId], () => + "/live/sessions/" + __encodePathParam(sessionId) + "/content").pipe( + Effect.map((request) => + request.pipe( + binaryRequest + ) + ) + ) + ), + "OrganizationDecisionsusage": (options: Parameters[0]) => + HttpClientRequest.get("/organization/usage/decisions").pipe( + HttpClientRequest.setUrlParams({ + "start_time": options.params["start_time"] as any, + "end_time": options.params["end_time"] as any, + "bucket_width": options.params["bucket_width"] as any, + "limit": options.params["limit"] as any, + "page": options.params["page"] as any, + "project_ids": options.params["project_ids"] as any, + "group_by": options.params["group_by"] as any, + "user_ids": options.params["user_ids"] as any, + "api_key_ids": options.params["api_key_ids"] as any, + "models": options.params["models"] as any, + "batch": options.params["batch"] as any + }), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(OrganizationDecisionsusage200), + "400": decodeError("OrganizationDecisionsusage400", OrganizationDecisionsusage400), + "403": decodeError("OrganizationDecisionsusage403", OrganizationDecisionsusage403), + "429": decodeError("OrganizationDecisionsusage429", OrganizationDecisionsusage429), orElse: unexpectedStatus })) ), - "listInputItems": (responseId, options) => - HttpClientRequest.get(`/responses/${responseId}/input_items`).pipe( + "Listexternalstorageconfigurations": (options: Parameters[0]) => + HttpClientRequest.get("/organization/external_storage").pipe( HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, + "project_id": options?.params?.["project_id"] as any, "after": options?.params?.["after"] as any, - "include": options?.params?.["include"] as any + "order": options?.params?.["order"] as any, + "limit": options?.params?.["limit"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListInputItems200), + "2xx": decodeSuccess(Listexternalstorageconfigurations200), + "400": decodeError("Listexternalstorageconfigurations400", Listexternalstorageconfigurations400), + "403": decodeError("Listexternalstorageconfigurations403", Listexternalstorageconfigurations403), + "404": decodeError("Listexternalstorageconfigurations404", Listexternalstorageconfigurations404), orElse: unexpectedStatus })) ), - "createThread": (options) => - HttpClientRequest.post(`/threads`).pipe( + "Createanexternalstorageconfiguration": ( + options: Parameters[0] + ) => + HttpClientRequest.post("/organization/external_storage").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateThread200), + "2xx": decodeSuccess(Createanexternalstorageconfiguration200), + "400": decodeError("Createanexternalstorageconfiguration400", Createanexternalstorageconfiguration400), + "403": decodeError("Createanexternalstorageconfiguration403", Createanexternalstorageconfiguration403), + "404": decodeError("Createanexternalstorageconfiguration404", Createanexternalstorageconfiguration404), + "503": decodeError("Createanexternalstorageconfiguration503", Createanexternalstorageconfiguration503), orElse: unexpectedStatus })) ), - "createThreadAndRun": (options) => - HttpClientRequest.post(`/threads/runs`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateThreadAndRun200), - orElse: unexpectedStatus - })) + "Getanexternalstorageconfiguration": ( + externalStorageId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.get, + [externalStorageId], + () => "/organization/external_storage/" + __encodePathParam(externalStorageId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Getanexternalstorageconfiguration200), + "400": decodeError("Getanexternalstorageconfiguration400", Getanexternalstorageconfiguration400), + "403": decodeError("Getanexternalstorageconfiguration403", Getanexternalstorageconfiguration403), + "404": decodeError("Getanexternalstorageconfiguration404", Getanexternalstorageconfiguration404), + orElse: unexpectedStatus + })) + ) + ) + ), + "Deleteanexternalstorageconfiguration": ( + externalStorageId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.delete, + [externalStorageId], + () => "/organization/external_storage/" + __encodePathParam(externalStorageId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Deleteanexternalstorageconfiguration200), + "400": decodeError("Deleteanexternalstorageconfiguration400", Deleteanexternalstorageconfiguration400), + "403": decodeError("Deleteanexternalstorageconfiguration403", Deleteanexternalstorageconfiguration403), + "404": decodeError("Deleteanexternalstorageconfiguration404", Deleteanexternalstorageconfiguration404), + orElse: unexpectedStatus + })) + ) + ) + ), + "Validateanexternalstorageconfiguration": ( + externalStorageId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.post, + [externalStorageId], + () => "/organization/external_storage/" + __encodePathParam(externalStorageId) + "/validate" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Validateanexternalstorageconfiguration200), + "400": decodeError( + "Validateanexternalstorageconfiguration400", + Validateanexternalstorageconfiguration400 + ), + "403": decodeError( + "Validateanexternalstorageconfiguration403", + Validateanexternalstorageconfiguration403 + ), + "404": decodeError( + "Validateanexternalstorageconfiguration404", + Validateanexternalstorageconfiguration404 + ), + "503": decodeError( + "Validateanexternalstorageconfiguration503", + Validateanexternalstorageconfiguration503 + ), + orElse: unexpectedStatus + })) + ) + ) ), - "getThread": (threadId, options) => - HttpClientRequest.get(`/threads/${threadId}`).pipe( + "Getorganizationspendlimit": (options: Parameters[0]) => + HttpClientRequest.get("/organization/spend_limit").pipe( withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetThread200), + "2xx": decodeSuccess(Getorganizationspendlimit200), + "403": decodeError("Getorganizationspendlimit403", Getorganizationspendlimit403), + "404": decodeError("Getorganizationspendlimit404", Getorganizationspendlimit404), orElse: unexpectedStatus })) ), - "modifyThread": (threadId, options) => - HttpClientRequest.post(`/threads/${threadId}`).pipe( + "Updateorganizationspendlimit": (options: Parameters[0]) => + HttpClientRequest.post("/organization/spend_limit").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyThread200), + "2xx": decodeSuccess(Updateorganizationspendlimit200), + "400": decodeError("Updateorganizationspendlimit400", Updateorganizationspendlimit400), + "403": decodeError("Updateorganizationspendlimit403", Updateorganizationspendlimit403), orElse: unexpectedStatus })) ), - "deleteThread": (threadId, options) => - HttpClientRequest.delete(`/threads/${threadId}`).pipe( + "Deleteorganizationspendlimit": (options: Parameters[0]) => + HttpClientRequest.delete("/organization/spend_limit").pipe( withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteThread200), + "2xx": decodeSuccess(Deleteorganizationspendlimit200), + "403": decodeError("Deleteorganizationspendlimit403", Deleteorganizationspendlimit403), + "404": decodeError("Deleteorganizationspendlimit404", Deleteorganizationspendlimit404), + orElse: unexpectedStatus + })) + ), + "Getprojectspendlimit": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/spend_limit" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Getprojectspendlimit200), + "400": decodeError("Getprojectspendlimit400", Getprojectspendlimit400), + "403": decodeError("Getprojectspendlimit403", Getprojectspendlimit403), + "404": decodeError("Getprojectspendlimit404", Getprojectspendlimit404), + orElse: unexpectedStatus + })) + ) + ) + ), + "Updateprojectspendlimit": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/spend_limit" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Updateprojectspendlimit200), + "400": decodeError("Updateprojectspendlimit400", Updateprojectspendlimit400), + "403": decodeError("Updateprojectspendlimit403", Updateprojectspendlimit403), + "404": decodeError("Updateprojectspendlimit404", Updateprojectspendlimit404), + orElse: unexpectedStatus + })) + ) + ) + ), + "Deleteprojectspendlimit": (projectId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [projectId], + () => "/organization/projects/" + __encodePathParam(projectId) + "/spend_limit" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Deleteprojectspendlimit200), + "400": decodeError("Deleteprojectspendlimit400", Deleteprojectspendlimit400), + "403": decodeError("Deleteprojectspendlimit403", Deleteprojectspendlimit403), + "404": decodeError("Deleteprojectspendlimit404", Deleteprojectspendlimit404), + orElse: unexpectedStatus + })) + ) + ) + ), + "CreateanAPIkeyforaserviceaccount": ( + projectId, + serviceAccountId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.post, + [projectId, serviceAccountId], + () => + "/organization/projects/" + __encodePathParam(projectId) + "/service_accounts/" + + __encodePathParam(serviceAccountId) + "/api_keys" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateanAPIkeyforaserviceaccount200), + "400": decodeError("CreateanAPIkeyforaserviceaccount400", CreateanAPIkeyforaserviceaccount400), + "403": decodeError("CreateanAPIkeyforaserviceaccount403", CreateanAPIkeyforaserviceaccount403), + "404": decodeError("CreateanAPIkeyforaserviceaccount404", CreateanAPIkeyforaserviceaccount404), + "409": decodeError("CreateanAPIkeyforaserviceaccount409", CreateanAPIkeyforaserviceaccount409), + "429": decodeError("CreateanAPIkeyforaserviceaccount429", CreateanAPIkeyforaserviceaccount429), + orElse: unexpectedStatus + })) + ) + ) + ), + "Createcontentprovenancecheck": (options: Parameters[0]) => + HttpClientRequest.post("/content_provenance_checks").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Createcontentprovenancecheck200), + "400": decodeError("Createcontentprovenancecheck400", Createcontentprovenancecheck400), + "404": decodeError("Createcontentprovenancecheck404", Createcontentprovenancecheck404), + "429": decodeError("Createcontentprovenancecheck429", Createcontentprovenancecheck429), + "500": decodeError("Createcontentprovenancecheck500", Createcontentprovenancecheck500), + "503": decodeError("Createcontentprovenancecheck503", Createcontentprovenancecheck503), orElse: unexpectedStatus })) ), - "listMessages": (threadId, options) => - HttpClientRequest.get(`/threads/${threadId}/messages`).pipe( + "ListVideos": (options: Parameters[0]) => + HttpClientRequest.get("/videos").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any, - "run_id": options?.params?.["run_id"] as any + "after": options?.params?.["after"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListMessages200), + "2xx": decodeSuccess(ListVideos200), + "400": decodeError("ListVideos400", ListVideos400), + "404": decodeError("ListVideos404", ListVideos404), orElse: unexpectedStatus })) ), - "createMessage": (threadId, options) => - HttpClientRequest.post(`/threads/${threadId}/messages`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), + "createVideo": (options: Parameters[0]) => + HttpClientRequest.post("/videos").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateMessage200), - orElse: unexpectedStatus - })) - ), - "getMessage": (threadId, messageId, options) => - HttpClientRequest.get(`/threads/${threadId}/messages/${messageId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetMessage200), + "2xx": decodeSuccess(CreateVideo200), + "400": decodeError("CreateVideo400", CreateVideo400), + "404": decodeError("CreateVideo404", CreateVideo404), + "429": decodeError("CreateVideo429", CreateVideo429), + "500": decodeError("CreateVideo500", CreateVideo500), + "503": decodeError("CreateVideo503", CreateVideo503), orElse: unexpectedStatus })) ), - "modifyMessage": (threadId, messageId, options) => - HttpClientRequest.post(`/threads/${threadId}/messages/${messageId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), + "CreateVideoCharacter": (options: Parameters[0]) => + HttpClientRequest.post("/videos/characters").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyMessage200), + "2xx": decodeSuccess(CreateVideoCharacter200), + "400": decodeError("CreateVideoCharacter400", CreateVideoCharacter400), + "404": decodeError("CreateVideoCharacter404", CreateVideoCharacter404), + "500": decodeError("CreateVideoCharacter500", CreateVideoCharacter500), + "504": decodeError("CreateVideoCharacter504", CreateVideoCharacter504), orElse: unexpectedStatus })) ), - "deleteMessage": (threadId, messageId, options) => - HttpClientRequest.delete(`/threads/${threadId}/messages/${messageId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteMessage200), - orElse: unexpectedStatus - })) + "GetVideoCharacter": (characterId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [characterId], + () => "/videos/characters/" + __encodePathParam(characterId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetVideoCharacter200), + "400": decodeError("GetVideoCharacter400", GetVideoCharacter400), + "404": decodeError("GetVideoCharacter404", GetVideoCharacter404), + orElse: unexpectedStatus + })) + ) + ) ), - "listRuns": (threadId, options) => - HttpClientRequest.get(`/threads/${threadId}/runs`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListRuns200), + "CreateVideoEdit": (options: Parameters[0]) => + HttpClientRequest.post("/videos/edits").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateVideoEdit200), + "400": decodeError("CreateVideoEdit400", CreateVideoEdit400), + "404": decodeError("CreateVideoEdit404", CreateVideoEdit404), + "429": decodeError("CreateVideoEdit429", CreateVideoEdit429), + "500": decodeError("CreateVideoEdit500", CreateVideoEdit500), + "503": decodeError("CreateVideoEdit503", CreateVideoEdit503), orElse: unexpectedStatus })) ), - "createRun": (threadId, options) => - HttpClientRequest.post(`/threads/${threadId}/runs`).pipe( - HttpClientRequest.setUrlParams({ "include[]": options.params?.["include[]"] as any }), - HttpClientRequest.bodyJsonUnsafe(options.payload), + "CreateVideoExtend": (options: Parameters[0]) => + HttpClientRequest.post("/videos/extensions").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateRun200), + "2xx": decodeSuccess(CreateVideoExtend200), + "400": decodeError("CreateVideoExtend400", CreateVideoExtend400), + "404": decodeError("CreateVideoExtend404", CreateVideoExtend404), + "429": decodeError("CreateVideoExtend429", CreateVideoExtend429), + "500": decodeError("CreateVideoExtend500", CreateVideoExtend500), + "503": decodeError("CreateVideoExtend503", CreateVideoExtend503), orElse: unexpectedStatus })) ), - "getRun": (threadId, runId, options) => - HttpClientRequest.get(`/threads/${threadId}/runs/${runId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetRun200), - orElse: unexpectedStatus - })) + "GetVideo": (videoId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [videoId], () => "/videos/" + __encodePathParam(videoId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetVideo200), + "400": decodeError("GetVideo400", GetVideo400), + "404": decodeError("GetVideo404", GetVideo404), + orElse: unexpectedStatus + })) + ) + ) + ), + "DeleteVideo": (videoId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.delete, [videoId], () => "/videos/" + __encodePathParam(videoId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteVideo200), + "400": decodeError("DeleteVideo400", DeleteVideo400), + "404": decodeError("DeleteVideo404", DeleteVideo404), + "500": decodeError("DeleteVideo500", DeleteVideo500), + orElse: unexpectedStatus + })) + ) + ) ), - "modifyRun": (threadId, runId, options) => - HttpClientRequest.post(`/threads/${threadId}/runs/${runId}`).pipe( + "RetrieveVideoContent": (videoId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [videoId], () => "/videos/" + __encodePathParam(videoId) + "/content") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "variant": options?.params?.["variant"] as any }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeBinary, + "400": decodeError("RetrieveVideoContent400", RetrieveVideoContent400), + "404": decodeError("RetrieveVideoContent404", RetrieveVideoContent404), + "500": decodeError("RetrieveVideoContent500", RetrieveVideoContent500), + orElse: unexpectedStatus + })) + ) + ) + ), + "RetrieveVideoContentStream": (videoId, options) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.get, [videoId], () => "/videos/" + __encodePathParam(videoId) + "/content") + .pipe( + Effect.map((request) => + request.pipe( + HttpClientRequest.setUrlParams({ "variant": options?.params?.["variant"] as any }), + binaryRequest + ) + ) + ) + ), + "CreateVideoRemix": (videoId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [videoId], () => "/videos/" + __encodePathParam(videoId) + "/remix") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateVideoRemix200), + "400": decodeError("CreateVideoRemix400", CreateVideoRemix400), + "404": decodeError("CreateVideoRemix404", CreateVideoRemix404), + "429": decodeError("CreateVideoRemix429", CreateVideoRemix429), + "500": decodeError("CreateVideoRemix500", CreateVideoRemix500), + "503": decodeError("CreateVideoRemix503", CreateVideoRemix503), + orElse: unexpectedStatus + })) + ) + ) + ), + "Getinputtokencounts": (options: Parameters[0]) => + HttpClientRequest.post("/responses/input_tokens").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyRun200), + "2xx": decodeSuccess(Getinputtokencounts200), + "400": decodeError("Getinputtokencounts400", Getinputtokencounts400), + "429": decodeError("Getinputtokencounts429", Getinputtokencounts429), orElse: unexpectedStatus })) ), - "cancelRun": (threadId, runId, options) => - HttpClientRequest.post(`/threads/${threadId}/runs/${runId}/cancel`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CancelRun200), + "Compactconversation": (options: Parameters[0]) => + HttpClientRequest.post("/responses/compact").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(Compactconversation200), + "400": decodeError("Compactconversation400", Compactconversation400), + "429": decodeError("Compactconversation429", Compactconversation429), + "503": decodeError("Compactconversation503", Compactconversation503), orElse: unexpectedStatus })) ), - "listRunSteps": (threadId, runId, options) => - HttpClientRequest.get(`/threads/${threadId}/runs/${runId}/steps`).pipe( + "ListSkills": (options: Parameters[0]) => + HttpClientRequest.get("/skills").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any, - "include[]": options?.params?.["include[]"] as any + "after": options?.params?.["after"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListRunSteps200), - orElse: unexpectedStatus - })) - ), - "getRunStep": (threadId, runId, stepId, options) => - HttpClientRequest.get(`/threads/${threadId}/runs/${runId}/steps/${stepId}`).pipe( - HttpClientRequest.setUrlParams({ "include[]": options?.params?.["include[]"] as any }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetRunStep200), + "2xx": decodeSuccess(ListSkills200), + "404": decodeError("ListSkills404", ListSkills404), + "429": decodeError("ListSkills429", ListSkills429), orElse: unexpectedStatus })) ), - "submitToolOuputsToRun": (threadId, runId, options) => - HttpClientRequest.post(`/threads/${threadId}/runs/${runId}/submit_tool_outputs`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), + "CreateSkill": (options: Parameters[0]) => + HttpClientRequest.post("/skills").pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(SubmitToolOuputsToRun200), + "2xx": decodeSuccess(CreateSkill200), + "400": decodeError("CreateSkill400", CreateSkill400), + "429": decodeError("CreateSkill429", CreateSkill429), + "500": decodeError("CreateSkill500", CreateSkill500), orElse: unexpectedStatus })) ), - "createUpload": (options) => - HttpClientRequest.post(`/uploads`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateUpload200), - orElse: unexpectedStatus - })) + "GetSkill": (skillId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [skillId], () => "/skills/" + __encodePathParam(skillId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetSkill200), + "404": decodeError("GetSkill404", GetSkill404), + "429": decodeError("GetSkill429", GetSkill429), + orElse: unexpectedStatus + })) + ) + ) + ), + "UpdateSkillDefaultVersion": (skillId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [skillId], () => "/skills/" + __encodePathParam(skillId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateSkillDefaultVersion200), + "400": decodeError("UpdateSkillDefaultVersion400", UpdateSkillDefaultVersion400), + "404": decodeError("UpdateSkillDefaultVersion404", UpdateSkillDefaultVersion404), + "429": decodeError("UpdateSkillDefaultVersion429", UpdateSkillDefaultVersion429), + orElse: unexpectedStatus + })) + ) + ) + ), + "DeleteSkill": (skillId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.delete, [skillId], () => "/skills/" + __encodePathParam(skillId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteSkill200), + "404": decodeError("DeleteSkill404", DeleteSkill404), + "429": decodeError("DeleteSkill429", DeleteSkill429), + orElse: unexpectedStatus + })) + ) + ) + ), + "GetSkillContent": (skillId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [skillId], () => "/skills/" + __encodePathParam(skillId) + "/content") + .pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeBinary, + "404": decodeError("GetSkillContent404", GetSkillContent404), + "429": decodeError("GetSkillContent429", GetSkillContent429), + orElse: unexpectedStatus + })) + ) + ) + ), + "GetSkillContentStream": (skillId) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.get, [skillId], () => "/skills/" + __encodePathParam(skillId) + "/content") + .pipe( + Effect.map((request) => + request.pipe( + binaryRequest + ) + ) + ) + ), + "ListSkillVersions": (skillId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [skillId], () => "/skills/" + __encodePathParam(skillId) + "/versions") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListSkillVersions200), + "400": decodeError("ListSkillVersions400", ListSkillVersions400), + "404": decodeError("ListSkillVersions404", ListSkillVersions404), + "429": decodeError("ListSkillVersions429", ListSkillVersions429), + orElse: unexpectedStatus + })) + ) + ) + ), + "CreateSkillVersion": (skillId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [skillId], () => "/skills/" + __encodePathParam(skillId) + "/versions") + .pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyFormDataRecord(options.payload as any), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateSkillVersion200), + "400": decodeError("CreateSkillVersion400", CreateSkillVersion400), + "404": decodeError("CreateSkillVersion404", CreateSkillVersion404), + "429": decodeError("CreateSkillVersion429", CreateSkillVersion429), + "500": decodeError("CreateSkillVersion500", CreateSkillVersion500), + orElse: unexpectedStatus + })) + ) + ) + ), + "GetSkillVersion": (skillId, version, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [skillId, version], + () => "/skills/" + __encodePathParam(skillId) + "/versions/" + __encodePathParam(version) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetSkillVersion200), + "400": decodeError("GetSkillVersion400", GetSkillVersion400), + "404": decodeError("GetSkillVersion404", GetSkillVersion404), + "429": decodeError("GetSkillVersion429", GetSkillVersion429), + orElse: unexpectedStatus + })) + ) + ) + ), + "DeleteSkillVersion": (skillId, version, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [skillId, version], + () => "/skills/" + __encodePathParam(skillId) + "/versions/" + __encodePathParam(version) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteSkillVersion200), + "400": decodeError("DeleteSkillVersion400", DeleteSkillVersion400), + "404": decodeError("DeleteSkillVersion404", DeleteSkillVersion404), + "429": decodeError("DeleteSkillVersion429", DeleteSkillVersion429), + orElse: unexpectedStatus + })) + ) + ) + ), + "GetSkillVersionContent": (skillId, version, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [skillId, version], + () => "/skills/" + __encodePathParam(skillId) + "/versions/" + __encodePathParam(version) + "/content" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeBinary, + "400": decodeError("GetSkillVersionContent400", GetSkillVersionContent400), + "404": decodeError("GetSkillVersionContent404", GetSkillVersionContent404), + "429": decodeError("GetSkillVersionContent429", GetSkillVersionContent429), + orElse: unexpectedStatus + })) + ) + ) + ), + "GetSkillVersionContentStream": (skillId, version) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.get, [skillId, version], () => + "/skills/" + __encodePathParam(skillId) + "/versions/" + __encodePathParam(version) + "/content").pipe( + Effect.map((request) => + request.pipe( + binaryRequest + ) + ) + ) ), - "cancelUpload": (uploadId, options) => - HttpClientRequest.post(`/uploads/${uploadId}/cancel`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CancelUpload200), - orElse: unexpectedStatus - })) + "CancelChatSessionMethod": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [sessionId], + () => "/chatkit/sessions/" + __encodePathParam(sessionId) + "/cancel" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CancelChatSessionMethod200), + "400": decodeError("CancelChatSessionMethod400", CancelChatSessionMethod400), + "404": decodeError("CancelChatSessionMethod404", CancelChatSessionMethod404), + "429": decodeError("CancelChatSessionMethod429", CancelChatSessionMethod429), + orElse: unexpectedStatus + })) + ) + ) ), - "completeUpload": (uploadId, options) => - HttpClientRequest.post(`/uploads/${uploadId}/complete`).pipe( + "CreateChatSessionMethod": (options: Parameters[0]) => + HttpClientRequest.post("/chatkit/sessions").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CompleteUpload200), + "2xx": decodeSuccess(CreateChatSessionMethod200), + "400": decodeError("CreateChatSessionMethod400", CreateChatSessionMethod400), + "404": decodeError("CreateChatSessionMethod404", CreateChatSessionMethod404), + "429": decodeError("CreateChatSessionMethod429", CreateChatSessionMethod429), orElse: unexpectedStatus })) ), - "addUploadPart": (uploadId, options) => - HttpClientRequest.post(`/uploads/${uploadId}/parts`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(AddUploadPart200), - orElse: unexpectedStatus - })) + "ListThreadItemsMethod": (threadId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [threadId], + () => "/chatkit/threads/" + __encodePathParam(threadId) + "/items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "before": options?.params?.["before"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListThreadItemsMethod200), + "400": decodeError("ListThreadItemsMethod400", ListThreadItemsMethod400), + "404": decodeError("ListThreadItemsMethod404", ListThreadItemsMethod404), + "429": decodeError("ListThreadItemsMethod429", ListThreadItemsMethod429), + orElse: unexpectedStatus + })) + ) + ) + ), + "GetThreadMethod": (threadId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [threadId], () => "/chatkit/threads/" + __encodePathParam(threadId) + "") + .pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(GetThreadMethod200), + "400": decodeError("GetThreadMethod400", GetThreadMethod400), + "404": decodeError("GetThreadMethod404", GetThreadMethod404), + "429": decodeError("GetThreadMethod429", GetThreadMethod429), + orElse: unexpectedStatus + })) + ) + ) + ), + "DeleteThreadMethod": (threadId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [threadId], + () => "/chatkit/threads/" + __encodePathParam(threadId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteThreadMethod200), + "400": decodeError("DeleteThreadMethod400", DeleteThreadMethod400), + "404": decodeError("DeleteThreadMethod404", DeleteThreadMethod404), + "429": decodeError("DeleteThreadMethod429", DeleteThreadMethod429), + orElse: unexpectedStatus + })) + ) + ) ), - "listVectorStores": (options) => - HttpClientRequest.get(`/vector_stores`).pipe( + "ListThreadsMethod": (options: Parameters[0]) => + HttpClientRequest.get("/chatkit/threads").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "order": options?.params?.["order"] as any, "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any + "before": options?.params?.["before"] as any, + "user": options?.params?.["user"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListVectorStores200), + "2xx": decodeSuccess(ListThreadsMethod200), + "400": decodeError("ListThreadsMethod400", ListThreadsMethod400), + "404": decodeError("ListThreadsMethod404", ListThreadsMethod404), + "429": decodeError("ListThreadsMethod429", ListThreadsMethod429), orElse: unexpectedStatus })) ), - "createVectorStore": (options) => - HttpClientRequest.post(`/vector_stores`).pipe( + "createDecision": (options: Parameters[0]) => + HttpClientRequest.post("/decisions").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVectorStore200), + "2xx": decodeSuccess(CreateDecision200), orElse: unexpectedStatus })) ), - "getVectorStore": (vectorStoreId, options) => - HttpClientRequest.get(`/vector_stores/${vectorStoreId}`).pipe( + "listAgentEnvironments": (options: Parameters[0]) => + HttpClientRequest.get("/agents/environments").pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "type": options?.params?.["type"] as any + }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetVectorStore200), + "2xx": decodeSuccess(ListAgentEnvironments200), + "400": decodeError("ListAgentEnvironments400", ListAgentEnvironments400), + "401": decodeError("ListAgentEnvironments401", ListAgentEnvironments401), + "403": decodeError("ListAgentEnvironments403", ListAgentEnvironments403), + "404": decodeError("ListAgentEnvironments404", ListAgentEnvironments404), + "409": decodeError("ListAgentEnvironments409", ListAgentEnvironments409), + "500": decodeError("ListAgentEnvironments500", ListAgentEnvironments500), + "503": decodeError("ListAgentEnvironments503", ListAgentEnvironments503), orElse: unexpectedStatus })) ), - "modifyVectorStore": (vectorStoreId, options) => - HttpClientRequest.post(`/vector_stores/${vectorStoreId}`).pipe( + "createAgentEnvironment": (options: Parameters[0]) => + HttpClientRequest.post("/agents/environments").pipe( + HttpClientRequest.setHeaders({ "Idempotency-Key": options.params?.["Idempotency-Key"] ?? undefined }), HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ModifyVectorStore200), + "2xx": decodeSuccess(CreateAgentEnvironment201), + "400": decodeError("CreateAgentEnvironment400", CreateAgentEnvironment400), + "401": decodeError("CreateAgentEnvironment401", CreateAgentEnvironment401), + "403": decodeError("CreateAgentEnvironment403", CreateAgentEnvironment403), + "404": decodeError("CreateAgentEnvironment404", CreateAgentEnvironment404), + "409": decodeError("CreateAgentEnvironment409", CreateAgentEnvironment409), + "429": decodeError("CreateAgentEnvironment429", CreateAgentEnvironment429), + "500": decodeError("CreateAgentEnvironment500", CreateAgentEnvironment500), + "503": decodeError("CreateAgentEnvironment503", CreateAgentEnvironment503), orElse: unexpectedStatus })) ), - "deleteVectorStore": (vectorStoreId, options) => - HttpClientRequest.delete(`/vector_stores/${vectorStoreId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteVectorStore200), - orElse: unexpectedStatus - })) + "retrieveAgentEnvironment": (environmentId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [environmentId], + () => "/agents/environments/" + __encodePathParam(environmentId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveAgentEnvironment200), + "400": decodeError("RetrieveAgentEnvironment400", RetrieveAgentEnvironment400), + "401": decodeError("RetrieveAgentEnvironment401", RetrieveAgentEnvironment401), + "403": decodeError("RetrieveAgentEnvironment403", RetrieveAgentEnvironment403), + "404": decodeError("RetrieveAgentEnvironment404", RetrieveAgentEnvironment404), + "409": decodeError("RetrieveAgentEnvironment409", RetrieveAgentEnvironment409), + "500": decodeError("RetrieveAgentEnvironment500", RetrieveAgentEnvironment500), + "503": decodeError("RetrieveAgentEnvironment503", RetrieveAgentEnvironment503), + orElse: unexpectedStatus + })) + ) + ) ), - "createVectorStoreFileBatch": (vectorStoreId, options) => - HttpClientRequest.post(`/vector_stores/${vectorStoreId}/file_batches`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVectorStoreFileBatch200), - orElse: unexpectedStatus - })) + "listAgentEnvironmentFiles": (environmentId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [environmentId], + () => "/agents/environments/" + __encodePathParam(environmentId) + "/files" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "path": options?.params?.["path"] as any, + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "page": options?.params?.["page"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentEnvironmentFiles200), + "400": decodeError("ListAgentEnvironmentFiles400", ListAgentEnvironmentFiles400), + "401": decodeError("ListAgentEnvironmentFiles401", ListAgentEnvironmentFiles401), + "403": decodeError("ListAgentEnvironmentFiles403", ListAgentEnvironmentFiles403), + "404": decodeError("ListAgentEnvironmentFiles404", ListAgentEnvironmentFiles404), + "409": decodeError("ListAgentEnvironmentFiles409", ListAgentEnvironmentFiles409), + "500": decodeError("ListAgentEnvironmentFiles500", ListAgentEnvironmentFiles500), + "503": decodeError("ListAgentEnvironmentFiles503", ListAgentEnvironmentFiles503), + orElse: unexpectedStatus + })) + ) + ) ), - "getVectorStoreFileBatch": (vectorStoreId, batchId, options) => - HttpClientRequest.get(`/vector_stores/${vectorStoreId}/file_batches/${batchId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetVectorStoreFileBatch200), - orElse: unexpectedStatus - })) + "createAgentEnvironmentFile": (environmentId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [environmentId], + () => "/agents/environments/" + __encodePathParam(environmentId) + "/files" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateAgentEnvironmentFile201), + "400": decodeError("CreateAgentEnvironmentFile400", CreateAgentEnvironmentFile400), + "401": decodeError("CreateAgentEnvironmentFile401", CreateAgentEnvironmentFile401), + "403": decodeError("CreateAgentEnvironmentFile403", CreateAgentEnvironmentFile403), + "404": decodeError("CreateAgentEnvironmentFile404", CreateAgentEnvironmentFile404), + "409": decodeError("CreateAgentEnvironmentFile409", CreateAgentEnvironmentFile409), + "429": decodeError("CreateAgentEnvironmentFile429", CreateAgentEnvironmentFile429), + "500": decodeError("CreateAgentEnvironmentFile500", CreateAgentEnvironmentFile500), + "503": decodeError("CreateAgentEnvironmentFile503", CreateAgentEnvironmentFile503), + orElse: unexpectedStatus + })) + ) + ) ), - "cancelVectorStoreFileBatch": (vectorStoreId, batchId, options) => - HttpClientRequest.post(`/vector_stores/${vectorStoreId}/file_batches/${batchId}/cancel`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CancelVectorStoreFileBatch200), - orElse: unexpectedStatus - })) + "listAgentSessionSubagents": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/subagents" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionSubagents200), + "400": decodeError("ListAgentSessionSubagents400", ListAgentSessionSubagents400), + "401": decodeError("ListAgentSessionSubagents401", ListAgentSessionSubagents401), + "403": decodeError("ListAgentSessionSubagents403", ListAgentSessionSubagents403), + "404": decodeError("ListAgentSessionSubagents404", ListAgentSessionSubagents404), + "409": decodeError("ListAgentSessionSubagents409", ListAgentSessionSubagents409), + "500": decodeError("ListAgentSessionSubagents500", ListAgentSessionSubagents500), + "503": decodeError("ListAgentSessionSubagents503", ListAgentSessionSubagents503), + orElse: unexpectedStatus + })) + ) + ) ), - "listFilesInVectorStoreBatch": (vectorStoreId, batchId, options) => - HttpClientRequest.get(`/vector_stores/${vectorStoreId}/file_batches/${batchId}/files`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any, - "filter": options?.params?.["filter"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListFilesInVectorStoreBatch200), - orElse: unexpectedStatus - })) + "retrieveAgentSessionSubagent": ( + sessionId, + subagentId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, subagentId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/subagents/" + __encodePathParam(subagentId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveAgentSessionSubagent200), + "400": decodeError("RetrieveAgentSessionSubagent400", RetrieveAgentSessionSubagent400), + "401": decodeError("RetrieveAgentSessionSubagent401", RetrieveAgentSessionSubagent401), + "403": decodeError("RetrieveAgentSessionSubagent403", RetrieveAgentSessionSubagent403), + "404": decodeError("RetrieveAgentSessionSubagent404", RetrieveAgentSessionSubagent404), + "409": decodeError("RetrieveAgentSessionSubagent409", RetrieveAgentSessionSubagent409), + "500": decodeError("RetrieveAgentSessionSubagent500", RetrieveAgentSessionSubagent500), + "503": decodeError("RetrieveAgentSessionSubagent503", RetrieveAgentSessionSubagent503), + orElse: unexpectedStatus + })) + ) + ) + ), + "listAgentSessionSubagentItems": ( + sessionId, + subagentId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, subagentId], + () => + "/agents/sessions/" + __encodePathParam(sessionId) + "/subagents/" + __encodePathParam(subagentId) + "/items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionSubagentItems200), + "400": decodeError("ListAgentSessionSubagentItems400", ListAgentSessionSubagentItems400), + "401": decodeError("ListAgentSessionSubagentItems401", ListAgentSessionSubagentItems401), + "403": decodeError("ListAgentSessionSubagentItems403", ListAgentSessionSubagentItems403), + "404": decodeError("ListAgentSessionSubagentItems404", ListAgentSessionSubagentItems404), + "409": decodeError("ListAgentSessionSubagentItems409", ListAgentSessionSubagentItems409), + "500": decodeError("ListAgentSessionSubagentItems500", ListAgentSessionSubagentItems500), + "503": decodeError("ListAgentSessionSubagentItems503", ListAgentSessionSubagentItems503), + orElse: unexpectedStatus + })) + ) + ) + ), + "listAgentSessionSubagentTurns": ( + sessionId, + subagentId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, subagentId], + () => + "/agents/sessions/" + __encodePathParam(sessionId) + "/subagents/" + __encodePathParam(subagentId) + "/turns" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionSubagentTurns200), + "400": decodeError("ListAgentSessionSubagentTurns400", ListAgentSessionSubagentTurns400), + "401": decodeError("ListAgentSessionSubagentTurns401", ListAgentSessionSubagentTurns401), + "403": decodeError("ListAgentSessionSubagentTurns403", ListAgentSessionSubagentTurns403), + "404": decodeError("ListAgentSessionSubagentTurns404", ListAgentSessionSubagentTurns404), + "409": decodeError("ListAgentSessionSubagentTurns409", ListAgentSessionSubagentTurns409), + "500": decodeError("ListAgentSessionSubagentTurns500", ListAgentSessionSubagentTurns500), + "503": decodeError("ListAgentSessionSubagentTurns503", ListAgentSessionSubagentTurns503), + orElse: unexpectedStatus + })) + ) + ) ), - "listVectorStoreFiles": (vectorStoreId, options) => - HttpClientRequest.get(`/vector_stores/${vectorStoreId}/files`).pipe( + "retrieveAgentSessionSubagentTurn": ( + sessionId, + subagentId, + turnId, + options: Parameters[3] + ) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, subagentId, turnId], + () => + "/agents/sessions/" + __encodePathParam(sessionId) + "/subagents/" + __encodePathParam(subagentId) + + "/turns/" + __encodePathParam(turnId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveAgentSessionSubagentTurn200), + "400": decodeError("RetrieveAgentSessionSubagentTurn400", RetrieveAgentSessionSubagentTurn400), + "401": decodeError("RetrieveAgentSessionSubagentTurn401", RetrieveAgentSessionSubagentTurn401), + "403": decodeError("RetrieveAgentSessionSubagentTurn403", RetrieveAgentSessionSubagentTurn403), + "404": decodeError("RetrieveAgentSessionSubagentTurn404", RetrieveAgentSessionSubagentTurn404), + "409": decodeError("RetrieveAgentSessionSubagentTurn409", RetrieveAgentSessionSubagentTurn409), + "500": decodeError("RetrieveAgentSessionSubagentTurn500", RetrieveAgentSessionSubagentTurn500), + "503": decodeError("RetrieveAgentSessionSubagentTurn503", RetrieveAgentSessionSubagentTurn503), + orElse: unexpectedStatus + })) + ) + ) + ), + "listAgentSessionSubagentTurnItems": ( + sessionId, + subagentId, + turnId, + options: Parameters[3] + ) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, subagentId, turnId], + () => + "/agents/sessions/" + __encodePathParam(sessionId) + "/subagents/" + __encodePathParam(subagentId) + + "/turns/" + __encodePathParam(turnId) + "/items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionSubagentTurnItems200), + "400": decodeError("ListAgentSessionSubagentTurnItems400", ListAgentSessionSubagentTurnItems400), + "401": decodeError("ListAgentSessionSubagentTurnItems401", ListAgentSessionSubagentTurnItems401), + "403": decodeError("ListAgentSessionSubagentTurnItems403", ListAgentSessionSubagentTurnItems403), + "404": decodeError("ListAgentSessionSubagentTurnItems404", ListAgentSessionSubagentTurnItems404), + "409": decodeError("ListAgentSessionSubagentTurnItems409", ListAgentSessionSubagentTurnItems409), + "500": decodeError("ListAgentSessionSubagentTurnItems500", ListAgentSessionSubagentTurnItems500), + "503": decodeError("ListAgentSessionSubagentTurnItems503", ListAgentSessionSubagentTurnItems503), + orElse: unexpectedStatus + })) + ) + ) + ), + "listAgents": (options: Parameters[0]) => + HttpClientRequest.get("/agents").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any, - "filter": options?.params?.["filter"] as any + "after": options?.params?.["after"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListVectorStoreFiles200), + "2xx": decodeSuccess(ListAgents200), + "400": decodeError("ListAgents400", ListAgents400), + "401": decodeError("ListAgents401", ListAgents401), + "403": decodeError("ListAgents403", ListAgents403), + "404": decodeError("ListAgents404", ListAgents404), + "409": decodeError("ListAgents409", ListAgents409), + "500": decodeError("ListAgents500", ListAgents500), + "503": decodeError("ListAgents503", ListAgents503), orElse: unexpectedStatus })) ), - "createVectorStoreFile": (vectorStoreId, options) => - HttpClientRequest.post(`/vector_stores/${vectorStoreId}/files`).pipe( + "createAgent": (options: Parameters[0]) => + HttpClientRequest.post("/agents").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVectorStoreFile200), + "2xx": decodeSuccess(CreateAgent201), + "400": decodeError("CreateAgent400", CreateAgent400), + "401": decodeError("CreateAgent401", CreateAgent401), + "403": decodeError("CreateAgent403", CreateAgent403), + "404": decodeError("CreateAgent404", CreateAgent404), + "409": decodeError("CreateAgent409", CreateAgent409), + "500": decodeError("CreateAgent500", CreateAgent500), + "503": decodeError("CreateAgent503", CreateAgent503), orElse: unexpectedStatus })) ), - "getVectorStoreFile": (vectorStoreId, fileId, options) => - HttpClientRequest.get(`/vector_stores/${vectorStoreId}/files/${fileId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetVectorStoreFile200), - orElse: unexpectedStatus - })) + "retrieveAgent": (agentId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [agentId], () => "/agents/" + __encodePathParam(agentId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveAgent200), + "400": decodeError("RetrieveAgent400", RetrieveAgent400), + "401": decodeError("RetrieveAgent401", RetrieveAgent401), + "403": decodeError("RetrieveAgent403", RetrieveAgent403), + "404": decodeError("RetrieveAgent404", RetrieveAgent404), + "409": decodeError("RetrieveAgent409", RetrieveAgent409), + "500": decodeError("RetrieveAgent500", RetrieveAgent500), + "503": decodeError("RetrieveAgent503", RetrieveAgent503), + orElse: unexpectedStatus + })) + ) + ) ), - "updateVectorStoreFileAttributes": (vectorStoreId, fileId, options) => - HttpClientRequest.post(`/vector_stores/${vectorStoreId}/files/${fileId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateVectorStoreFileAttributes200), - orElse: unexpectedStatus - })) + "updateAgent": (agentId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [agentId], () => "/agents/" + __encodePathParam(agentId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateAgent200), + "400": decodeError("UpdateAgent400", UpdateAgent400), + "401": decodeError("UpdateAgent401", UpdateAgent401), + "403": decodeError("UpdateAgent403", UpdateAgent403), + "404": decodeError("UpdateAgent404", UpdateAgent404), + "409": decodeError("UpdateAgent409", UpdateAgent409), + "500": decodeError("UpdateAgent500", UpdateAgent500), + "503": decodeError("UpdateAgent503", UpdateAgent503), + orElse: unexpectedStatus + })) + ) + ) ), - "deleteVectorStoreFile": (vectorStoreId, fileId, options) => - HttpClientRequest.delete(`/vector_stores/${vectorStoreId}/files/${fileId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteVectorStoreFile200), - orElse: unexpectedStatus - })) + "deleteAgent": (agentId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.delete, [agentId], () => "/agents/" + __encodePathParam(agentId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteAgent200), + "400": decodeError("DeleteAgent400", DeleteAgent400), + "401": decodeError("DeleteAgent401", DeleteAgent401), + "403": decodeError("DeleteAgent403", DeleteAgent403), + "404": decodeError("DeleteAgent404", DeleteAgent404), + "409": decodeError("DeleteAgent409", DeleteAgent409), + "500": decodeError("DeleteAgent500", DeleteAgent500), + "503": decodeError("DeleteAgent503", DeleteAgent503), + orElse: unexpectedStatus + })) + ) + ) ), - "retrieveVectorStoreFileContent": (vectorStoreId, fileId, options) => - HttpClientRequest.get(`/vector_stores/${vectorStoreId}/files/${fileId}/content`).pipe( + "listAgentEnvironmentTemplates": (options: Parameters[0]) => + HttpClientRequest.get("/agents/environments/templates").pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveVectorStoreFileContent200), - orElse: unexpectedStatus - })) - ), - "searchVectorStore": (vectorStoreId, options) => - HttpClientRequest.post(`/vector_stores/${vectorStoreId}/search`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(SearchVectorStore200), + "2xx": decodeSuccess(ListAgentEnvironmentTemplates200), + "400": decodeError("ListAgentEnvironmentTemplates400", ListAgentEnvironmentTemplates400), + "401": decodeError("ListAgentEnvironmentTemplates401", ListAgentEnvironmentTemplates401), + "403": decodeError("ListAgentEnvironmentTemplates403", ListAgentEnvironmentTemplates403), + "404": decodeError("ListAgentEnvironmentTemplates404", ListAgentEnvironmentTemplates404), + "500": decodeError("ListAgentEnvironmentTemplates500", ListAgentEnvironmentTemplates500), + "503": decodeError("ListAgentEnvironmentTemplates503", ListAgentEnvironmentTemplates503), orElse: unexpectedStatus })) ), - "createConversation": (options) => - HttpClientRequest.post(`/conversations`).pipe( + "createAgentEnvironmentTemplate": (options: Parameters[0]) => + HttpClientRequest.post("/agents/environments/templates").pipe( HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateConversation200), + "2xx": decodeSuccess(CreateAgentEnvironmentTemplate201), + "400": decodeError("CreateAgentEnvironmentTemplate400", CreateAgentEnvironmentTemplate400), + "401": decodeError("CreateAgentEnvironmentTemplate401", CreateAgentEnvironmentTemplate401), + "403": decodeError("CreateAgentEnvironmentTemplate403", CreateAgentEnvironmentTemplate403), + "404": decodeError("CreateAgentEnvironmentTemplate404", CreateAgentEnvironmentTemplate404), + "500": decodeError("CreateAgentEnvironmentTemplate500", CreateAgentEnvironmentTemplate500), + "503": decodeError("CreateAgentEnvironmentTemplate503", CreateAgentEnvironmentTemplate503), orElse: unexpectedStatus })) ), - "getConversation": (conversationId, options) => - HttpClientRequest.get(`/conversations/${conversationId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetConversation200), - orElse: unexpectedStatus - })) + "retrieveAgentEnvironmentTemplate": ( + environmentTemplateId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.get, + [environmentTemplateId], + () => "/agents/environments/templates/" + __encodePathParam(environmentTemplateId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveAgentEnvironmentTemplate200), + "400": decodeError("RetrieveAgentEnvironmentTemplate400", RetrieveAgentEnvironmentTemplate400), + "401": decodeError("RetrieveAgentEnvironmentTemplate401", RetrieveAgentEnvironmentTemplate401), + "403": decodeError("RetrieveAgentEnvironmentTemplate403", RetrieveAgentEnvironmentTemplate403), + "404": decodeError("RetrieveAgentEnvironmentTemplate404", RetrieveAgentEnvironmentTemplate404), + "500": decodeError("RetrieveAgentEnvironmentTemplate500", RetrieveAgentEnvironmentTemplate500), + "503": decodeError("RetrieveAgentEnvironmentTemplate503", RetrieveAgentEnvironmentTemplate503), + orElse: unexpectedStatus + })) + ) + ) ), - "updateConversation": (conversationId, options) => - HttpClientRequest.post(`/conversations/${conversationId}`).pipe( - HttpClientRequest.bodyJsonUnsafe(options.payload), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateConversation200), - orElse: unexpectedStatus - })) + "updateAgentEnvironmentTemplate": ( + environmentTemplateId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.post, + [environmentTemplateId], + () => "/agents/environments/templates/" + __encodePathParam(environmentTemplateId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateAgentEnvironmentTemplate200), + "400": decodeError("UpdateAgentEnvironmentTemplate400", UpdateAgentEnvironmentTemplate400), + "401": decodeError("UpdateAgentEnvironmentTemplate401", UpdateAgentEnvironmentTemplate401), + "403": decodeError("UpdateAgentEnvironmentTemplate403", UpdateAgentEnvironmentTemplate403), + "404": decodeError("UpdateAgentEnvironmentTemplate404", UpdateAgentEnvironmentTemplate404), + "409": decodeError("UpdateAgentEnvironmentTemplate409", UpdateAgentEnvironmentTemplate409), + "500": decodeError("UpdateAgentEnvironmentTemplate500", UpdateAgentEnvironmentTemplate500), + "503": decodeError("UpdateAgentEnvironmentTemplate503", UpdateAgentEnvironmentTemplate503), + orElse: unexpectedStatus + })) + ) + ) ), - "deleteConversation": (conversationId, options) => - HttpClientRequest.delete(`/conversations/${conversationId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteConversation200), - orElse: unexpectedStatus - })) + "deleteAgentEnvironmentTemplate": ( + environmentTemplateId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.delete, + [environmentTemplateId], + () => "/agents/environments/templates/" + __encodePathParam(environmentTemplateId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteAgentEnvironmentTemplate200), + "400": decodeError("DeleteAgentEnvironmentTemplate400", DeleteAgentEnvironmentTemplate400), + "401": decodeError("DeleteAgentEnvironmentTemplate401", DeleteAgentEnvironmentTemplate401), + "403": decodeError("DeleteAgentEnvironmentTemplate403", DeleteAgentEnvironmentTemplate403), + "404": decodeError("DeleteAgentEnvironmentTemplate404", DeleteAgentEnvironmentTemplate404), + "409": decodeError("DeleteAgentEnvironmentTemplate409", DeleteAgentEnvironmentTemplate409), + "500": decodeError("DeleteAgentEnvironmentTemplate500", DeleteAgentEnvironmentTemplate500), + "503": decodeError("DeleteAgentEnvironmentTemplate503", DeleteAgentEnvironmentTemplate503), + orElse: unexpectedStatus + })) + ) + ) ), - "ListVideos": (options) => - HttpClientRequest.get(`/videos`).pipe( + "listAgentSessions": (options: Parameters[0]) => + HttpClientRequest.get("/agents/sessions").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any + "after": options?.params?.["after"] as any, + "agent_id": options?.params?.["agent_id"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListVideos200), + "2xx": decodeSuccess(ListAgentSessions200), + "400": decodeError("ListAgentSessions400", ListAgentSessions400), + "401": decodeError("ListAgentSessions401", ListAgentSessions401), + "403": decodeError("ListAgentSessions403", ListAgentSessions403), + "404": decodeError("ListAgentSessions404", ListAgentSessions404), + "409": decodeError("ListAgentSessions409", ListAgentSessions409), + "500": decodeError("ListAgentSessions500", ListAgentSessions500), + "503": decodeError("ListAgentSessions503", ListAgentSessions503), orElse: unexpectedStatus })) ), - "createVideo": (options) => - HttpClientRequest.post(`/videos`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), + "createAgentSession": (options: Parameters[0]) => + HttpClientRequest.post("/agents/sessions").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVideo200), + "2xx": decodeSuccess(CreateAgentSession201), + "400": decodeError("CreateAgentSession400", CreateAgentSession400), + "401": decodeError("CreateAgentSession401", CreateAgentSession401), + "403": decodeError("CreateAgentSession403", CreateAgentSession403), + "404": decodeError("CreateAgentSession404", CreateAgentSession404), + "409": decodeError("CreateAgentSession409", CreateAgentSession409), + "429": decodeError("CreateAgentSession429", CreateAgentSession429), + "500": decodeError("CreateAgentSession500", CreateAgentSession500), + "503": decodeError("CreateAgentSession503", CreateAgentSession503), orElse: unexpectedStatus })) ), - "CreateVideoCharacter": (options) => - HttpClientRequest.post(`/videos/characters`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVideoCharacter200), - orElse: unexpectedStatus - })) + "createAgentSessionSse": (options) => + HttpClientRequest.post("/agents/sessions").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + sseRequest(CreateAgentSession201Sse) ), - "GetVideoCharacter": (characterId, options) => - HttpClientRequest.get(`/videos/characters/${characterId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetVideoCharacter200), - orElse: unexpectedStatus - })) + "retrieveAgentSession": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveAgentSession200), + "400": decodeError("RetrieveAgentSession400", RetrieveAgentSession400), + "401": decodeError("RetrieveAgentSession401", RetrieveAgentSession401), + "403": decodeError("RetrieveAgentSession403", RetrieveAgentSession403), + "404": decodeError("RetrieveAgentSession404", RetrieveAgentSession404), + "409": decodeError("RetrieveAgentSession409", RetrieveAgentSession409), + "500": decodeError("RetrieveAgentSession500", RetrieveAgentSession500), + "503": decodeError("RetrieveAgentSession503", RetrieveAgentSession503), + orElse: unexpectedStatus + })) + ) + ) ), - "CreateVideoEdit": (options) => - HttpClientRequest.post(`/videos/edits`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVideoEdit200), - orElse: unexpectedStatus - })) + "updateAgentSession": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateAgentSession200), + "400": decodeError("UpdateAgentSession400", UpdateAgentSession400), + "401": decodeError("UpdateAgentSession401", UpdateAgentSession401), + "403": decodeError("UpdateAgentSession403", UpdateAgentSession403), + "404": decodeError("UpdateAgentSession404", UpdateAgentSession404), + "409": decodeError("UpdateAgentSession409", UpdateAgentSession409), + "500": decodeError("UpdateAgentSession500", UpdateAgentSession500), + "503": decodeError("UpdateAgentSession503", UpdateAgentSession503), + orElse: unexpectedStatus + })) + ) + ) ), - "CreateVideoExtend": (options) => - HttpClientRequest.post(`/videos/extensions`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVideoExtend200), - orElse: unexpectedStatus - })) + "deleteAgentSession": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteAgentSession200), + "400": decodeError("DeleteAgentSession400", DeleteAgentSession400), + "401": decodeError("DeleteAgentSession401", DeleteAgentSession401), + "403": decodeError("DeleteAgentSession403", DeleteAgentSession403), + "404": decodeError("DeleteAgentSession404", DeleteAgentSession404), + "409": decodeError("DeleteAgentSession409", DeleteAgentSession409), + "500": decodeError("DeleteAgentSession500", DeleteAgentSession500), + "503": decodeError("DeleteAgentSession503", DeleteAgentSession503), + orElse: unexpectedStatus + })) + ) + ) ), - "GetVideo": (videoId, options) => - HttpClientRequest.get(`/videos/${videoId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetVideo200), - orElse: unexpectedStatus - })) + "listAgentSessionArtifacts": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/artifacts" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "environment_id": options?.params?.["environment_id"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionArtifacts200), + "400": decodeError("ListAgentSessionArtifacts400", ListAgentSessionArtifacts400), + "401": decodeError("ListAgentSessionArtifacts401", ListAgentSessionArtifacts401), + "403": decodeError("ListAgentSessionArtifacts403", ListAgentSessionArtifacts403), + "404": decodeError("ListAgentSessionArtifacts404", ListAgentSessionArtifacts404), + "409": decodeError("ListAgentSessionArtifacts409", ListAgentSessionArtifacts409), + "500": decodeError("ListAgentSessionArtifacts500", ListAgentSessionArtifacts500), + "503": decodeError("ListAgentSessionArtifacts503", ListAgentSessionArtifacts503), + orElse: unexpectedStatus + })) + ) + ) ), - "DeleteVideo": (videoId, options) => - HttpClientRequest.delete(`/videos/${videoId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteVideo200), - orElse: unexpectedStatus - })) + "retrieveAgentSessionArtifact": ( + sessionId, + artifactId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, artifactId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/artifacts/" + __encodePathParam(artifactId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveAgentSessionArtifact200), + "400": decodeError("RetrieveAgentSessionArtifact400", RetrieveAgentSessionArtifact400), + "401": decodeError("RetrieveAgentSessionArtifact401", RetrieveAgentSessionArtifact401), + "403": decodeError("RetrieveAgentSessionArtifact403", RetrieveAgentSessionArtifact403), + "404": decodeError("RetrieveAgentSessionArtifact404", RetrieveAgentSessionArtifact404), + "409": decodeError("RetrieveAgentSessionArtifact409", RetrieveAgentSessionArtifact409), + "500": decodeError("RetrieveAgentSessionArtifact500", RetrieveAgentSessionArtifact500), + "503": decodeError("RetrieveAgentSessionArtifact503", RetrieveAgentSessionArtifact503), + orElse: unexpectedStatus + })) + ) + ) ), - "RetrieveVideoContent": (videoId, options) => - HttpClientRequest.get(`/videos/${videoId}/content`).pipe( - HttpClientRequest.setUrlParams({ "variant": options?.params?.["variant"] as any }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(RetrieveVideoContent200), - orElse: unexpectedStatus - })) + "deleteAgentSessionArtifact": ( + sessionId, + artifactId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.delete, + [sessionId, artifactId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/artifacts/" + __encodePathParam(artifactId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteAgentSessionArtifact200), + "400": decodeError("DeleteAgentSessionArtifact400", DeleteAgentSessionArtifact400), + "401": decodeError("DeleteAgentSessionArtifact401", DeleteAgentSessionArtifact401), + "403": decodeError("DeleteAgentSessionArtifact403", DeleteAgentSessionArtifact403), + "404": decodeError("DeleteAgentSessionArtifact404", DeleteAgentSessionArtifact404), + "409": decodeError("DeleteAgentSessionArtifact409", DeleteAgentSessionArtifact409), + "500": decodeError("DeleteAgentSessionArtifact500", DeleteAgentSessionArtifact500), + "503": decodeError("DeleteAgentSessionArtifact503", DeleteAgentSessionArtifact503), + orElse: unexpectedStatus + })) + ) + ) ), - "CreateVideoRemix": (videoId, options) => - HttpClientRequest.post(`/videos/${videoId}/remix`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateVideoRemix200), - orElse: unexpectedStatus - })) + "retrieveAgentSessionArtifactContent": ( + sessionId, + artifactId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, artifactId], + () => + "/agents/sessions/" + __encodePathParam(sessionId) + "/artifacts/" + __encodePathParam(artifactId) + + "/content" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeBinary, + "400": decodeError("RetrieveAgentSessionArtifactContent400", RetrieveAgentSessionArtifactContent400), + "401": decodeError("RetrieveAgentSessionArtifactContent401", RetrieveAgentSessionArtifactContent401), + "403": decodeError("RetrieveAgentSessionArtifactContent403", RetrieveAgentSessionArtifactContent403), + "404": decodeError("RetrieveAgentSessionArtifactContent404", RetrieveAgentSessionArtifactContent404), + "409": decodeError("RetrieveAgentSessionArtifactContent409", RetrieveAgentSessionArtifactContent409), + "500": decodeError("RetrieveAgentSessionArtifactContent500", RetrieveAgentSessionArtifactContent500), + "503": decodeError("RetrieveAgentSessionArtifactContent503", RetrieveAgentSessionArtifactContent503), + orElse: unexpectedStatus + })) + ) + ) ), - "Getinputtokencounts": (options) => - HttpClientRequest.post(`/responses/input_tokens`).pipe( - HttpClientRequest.bodyUrlParams(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(Getinputtokencounts200), - orElse: unexpectedStatus - })) + "retrieveAgentSessionArtifactContentStream": (sessionId, artifactId) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.get, [sessionId, artifactId], () => + "/agents/sessions/" + __encodePathParam(sessionId) + "/artifacts/" + __encodePathParam(artifactId) + + "/content").pipe( + Effect.map((request) => + request.pipe( + binaryRequest + ) + ) + ) ), - "Compactconversation": (options) => - HttpClientRequest.post(`/responses/compact`).pipe( - HttpClientRequest.bodyUrlParams(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(Compactconversation200), - orElse: unexpectedStatus - })) + "listAgentSessionEvents": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/events" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "400": decodeError("ListAgentSessionEvents400", ListAgentSessionEvents400), + "401": decodeError("ListAgentSessionEvents401", ListAgentSessionEvents401), + "403": decodeError("ListAgentSessionEvents403", ListAgentSessionEvents403), + "404": decodeError("ListAgentSessionEvents404", ListAgentSessionEvents404), + "409": decodeError("ListAgentSessionEvents409", ListAgentSessionEvents409), + "500": decodeError("ListAgentSessionEvents500", ListAgentSessionEvents500), + "503": decodeError("ListAgentSessionEvents503", ListAgentSessionEvents503), + orElse: unexpectedStatus + })) + ) + ) + ), + "listAgentSessionEventsSse": (sessionId) => + Stream.unwrap( + __makePathRequest(HttpClientRequest.get, [sessionId], () => + "/agents/sessions/" + __encodePathParam(sessionId) + "/events").pipe( + Effect.map((request) => + request.pipe( + sseRequest(ListAgentSessionEvents200Sse) + ) + ) + ) + ), + "createAgentSessionEvents": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/events" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setHeaders({ "Idempotency-Key": options.params?.["Idempotency-Key"] ?? undefined }), + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "400": decodeError("CreateAgentSessionEvents400", CreateAgentSessionEvents400), + "401": decodeError("CreateAgentSessionEvents401", CreateAgentSessionEvents401), + "403": decodeError("CreateAgentSessionEvents403", CreateAgentSessionEvents403), + "404": decodeError("CreateAgentSessionEvents404", CreateAgentSessionEvents404), + "409": decodeError("CreateAgentSessionEvents409", CreateAgentSessionEvents409), + "500": decodeError("CreateAgentSessionEvents500", CreateAgentSessionEvents500), + "503": decodeError("CreateAgentSessionEvents503", CreateAgentSessionEvents503), + "202": () => Effect.void, + orElse: unexpectedStatus + })) + ) + ) + ), + "listAgentSessionItems": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionItems200), + "400": decodeError("ListAgentSessionItems400", ListAgentSessionItems400), + "401": decodeError("ListAgentSessionItems401", ListAgentSessionItems401), + "403": decodeError("ListAgentSessionItems403", ListAgentSessionItems403), + "404": decodeError("ListAgentSessionItems404", ListAgentSessionItems404), + "409": decodeError("ListAgentSessionItems409", ListAgentSessionItems409), + "500": decodeError("ListAgentSessionItems500", ListAgentSessionItems500), + "503": decodeError("ListAgentSessionItems503", ListAgentSessionItems503), + orElse: unexpectedStatus + })) + ) + ) + ), + "listAgentSessionTraces": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/traces" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionTraces200), + "400": decodeError("ListAgentSessionTraces400", ListAgentSessionTraces400), + "401": decodeError("ListAgentSessionTraces401", ListAgentSessionTraces401), + "403": decodeError("ListAgentSessionTraces403", ListAgentSessionTraces403), + "404": decodeError("ListAgentSessionTraces404", ListAgentSessionTraces404), + "409": decodeError("ListAgentSessionTraces409", ListAgentSessionTraces409), + "500": decodeError("ListAgentSessionTraces500", ListAgentSessionTraces500), + "503": decodeError("ListAgentSessionTraces503", ListAgentSessionTraces503), + orElse: unexpectedStatus + })) + ) + ) + ), + "listAgentSessionTurns": (sessionId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/turns" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionTurns200), + "400": decodeError("ListAgentSessionTurns400", ListAgentSessionTurns400), + "401": decodeError("ListAgentSessionTurns401", ListAgentSessionTurns401), + "403": decodeError("ListAgentSessionTurns403", ListAgentSessionTurns403), + "404": decodeError("ListAgentSessionTurns404", ListAgentSessionTurns404), + "409": decodeError("ListAgentSessionTurns409", ListAgentSessionTurns409), + "500": decodeError("ListAgentSessionTurns500", ListAgentSessionTurns500), + "503": decodeError("ListAgentSessionTurns503", ListAgentSessionTurns503), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveAgentSessionTurn": (sessionId, turnId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, turnId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/turns/" + __encodePathParam(turnId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveAgentSessionTurn200), + "400": decodeError("RetrieveAgentSessionTurn400", RetrieveAgentSessionTurn400), + "401": decodeError("RetrieveAgentSessionTurn401", RetrieveAgentSessionTurn401), + "403": decodeError("RetrieveAgentSessionTurn403", RetrieveAgentSessionTurn403), + "404": decodeError("RetrieveAgentSessionTurn404", RetrieveAgentSessionTurn404), + "409": decodeError("RetrieveAgentSessionTurn409", RetrieveAgentSessionTurn409), + "500": decodeError("RetrieveAgentSessionTurn500", RetrieveAgentSessionTurn500), + "503": decodeError("RetrieveAgentSessionTurn503", RetrieveAgentSessionTurn503), + orElse: unexpectedStatus + })) + ) + ) ), - "ListSkills": (options) => - HttpClientRequest.get(`/skills`).pipe( + "listAgentSessionTurnItems": ( + sessionId, + turnId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [sessionId, turnId], + () => "/agents/sessions/" + __encodePathParam(sessionId) + "/turns/" + __encodePathParam(turnId) + "/items" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListAgentSessionTurnItems200), + "400": decodeError("ListAgentSessionTurnItems400", ListAgentSessionTurnItems400), + "401": decodeError("ListAgentSessionTurnItems401", ListAgentSessionTurnItems401), + "403": decodeError("ListAgentSessionTurnItems403", ListAgentSessionTurnItems403), + "404": decodeError("ListAgentSessionTurnItems404", ListAgentSessionTurnItems404), + "409": decodeError("ListAgentSessionTurnItems409", ListAgentSessionTurnItems409), + "500": decodeError("ListAgentSessionTurnItems500", ListAgentSessionTurnItems500), + "503": decodeError("ListAgentSessionTurnItems503", ListAgentSessionTurnItems503), + orElse: unexpectedStatus + })) + ) + ) + ), + "listVaults": (options: Parameters[0]) => + HttpClientRequest.get("/vaults").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any + "after": options?.params?.["after"] as any, + "metadata": options?.params?.["metadata"] as any, + "status": options?.params?.["status"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListSkills200), + "2xx": decodeSuccess(ListVaults200), + "400": decodeError("ListVaults400", ListVaults400), + "401": decodeError("ListVaults401", ListVaults401), + "403": decodeError("ListVaults403", ListVaults403), + "404": decodeError("ListVaults404", ListVaults404), + "409": decodeError("ListVaults409", ListVaults409), + "500": decodeError("ListVaults500", ListVaults500), + "503": decodeError("ListVaults503", ListVaults503), orElse: unexpectedStatus })) ), - "CreateSkill": (options) => - HttpClientRequest.post(`/skills`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), + "createVault": (options: Parameters[0]) => + HttpClientRequest.post("/vaults").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateSkill200), + "2xx": decodeSuccess(CreateVault201), + "400": decodeError("CreateVault400", CreateVault400), + "401": decodeError("CreateVault401", CreateVault401), + "403": decodeError("CreateVault403", CreateVault403), + "404": decodeError("CreateVault404", CreateVault404), + "409": decodeError("CreateVault409", CreateVault409), + "500": decodeError("CreateVault500", CreateVault500), + "503": decodeError("CreateVault503", CreateVault503), orElse: unexpectedStatus })) ), - "GetSkill": (skillId, options) => - HttpClientRequest.get(`/skills/${skillId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetSkill200), - orElse: unexpectedStatus - })) + "retrieveVault": (vaultId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.get, [vaultId], () => "/vaults/" + __encodePathParam(vaultId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveVault200), + "400": decodeError("RetrieveVault400", RetrieveVault400), + "401": decodeError("RetrieveVault401", RetrieveVault401), + "403": decodeError("RetrieveVault403", RetrieveVault403), + "404": decodeError("RetrieveVault404", RetrieveVault404), + "409": decodeError("RetrieveVault409", RetrieveVault409), + "500": decodeError("RetrieveVault500", RetrieveVault500), + "503": decodeError("RetrieveVault503", RetrieveVault503), + orElse: unexpectedStatus + })) + ) + ) ), - "UpdateSkillDefaultVersion": (skillId, options) => - HttpClientRequest.post(`/skills/${skillId}`).pipe( - HttpClientRequest.bodyUrlParams(options.payload as any), - withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(UpdateSkillDefaultVersion200), - orElse: unexpectedStatus - })) + "updateVault": (vaultId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.post, [vaultId], () => "/vaults/" + __encodePathParam(vaultId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateVault200), + "400": decodeError("UpdateVault400", UpdateVault400), + "401": decodeError("UpdateVault401", UpdateVault401), + "403": decodeError("UpdateVault403", UpdateVault403), + "404": decodeError("UpdateVault404", UpdateVault404), + "409": decodeError("UpdateVault409", UpdateVault409), + "500": decodeError("UpdateVault500", UpdateVault500), + "503": decodeError("UpdateVault503", UpdateVault503), + orElse: unexpectedStatus + })) + ) + ) ), - "DeleteSkill": (skillId, options) => - HttpClientRequest.delete(`/skills/${skillId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteSkill200), - orElse: unexpectedStatus - })) + "deleteVault": (vaultId, options: Parameters[1]) => + __makePathRequest(HttpClientRequest.delete, [vaultId], () => "/vaults/" + __encodePathParam(vaultId) + "").pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteVault200), + "400": decodeError("DeleteVault400", DeleteVault400), + "401": decodeError("DeleteVault401", DeleteVault401), + "403": decodeError("DeleteVault403", DeleteVault403), + "404": decodeError("DeleteVault404", DeleteVault404), + "409": decodeError("DeleteVault409", DeleteVault409), + "500": decodeError("DeleteVault500", DeleteVault500), + "503": decodeError("DeleteVault503", DeleteVault503), + orElse: unexpectedStatus + })) + ) + ) ), - "GetSkillContent": (skillId, options) => - HttpClientRequest.get(`/skills/${skillId}/content`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetSkillContent200), - orElse: unexpectedStatus - })) + "listVaultCredentials": (vaultId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [vaultId], + () => "/vaults/" + __encodePathParam(vaultId) + "/credentials" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "metadata": options?.params?.["metadata"] as any, + "status": options?.params?.["status"] as any + }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(ListVaultCredentials200), + "400": decodeError("ListVaultCredentials400", ListVaultCredentials400), + "401": decodeError("ListVaultCredentials401", ListVaultCredentials401), + "403": decodeError("ListVaultCredentials403", ListVaultCredentials403), + "404": decodeError("ListVaultCredentials404", ListVaultCredentials404), + "409": decodeError("ListVaultCredentials409", ListVaultCredentials409), + "500": decodeError("ListVaultCredentials500", ListVaultCredentials500), + "503": decodeError("ListVaultCredentials503", ListVaultCredentials503), + orElse: unexpectedStatus + })) + ) + ) + ), + "createVaultCredential": (vaultId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [vaultId], + () => "/vaults/" + __encodePathParam(vaultId) + "/credentials" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(CreateVaultCredential201), + "400": decodeError("CreateVaultCredential400", CreateVaultCredential400), + "401": decodeError("CreateVaultCredential401", CreateVaultCredential401), + "403": decodeError("CreateVaultCredential403", CreateVaultCredential403), + "404": decodeError("CreateVaultCredential404", CreateVaultCredential404), + "409": decodeError("CreateVaultCredential409", CreateVaultCredential409), + "500": decodeError("CreateVaultCredential500", CreateVaultCredential500), + "503": decodeError("CreateVaultCredential503", CreateVaultCredential503), + orElse: unexpectedStatus + })) + ) + ) + ), + "retrieveVaultCredential": ( + vaultId, + credentialId, + options: Parameters[2] + ) => + __makePathRequest( + HttpClientRequest.get, + [vaultId, credentialId], + () => "/vaults/" + __encodePathParam(vaultId) + "/credentials/" + __encodePathParam(credentialId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveVaultCredential200), + "400": decodeError("RetrieveVaultCredential400", RetrieveVaultCredential400), + "401": decodeError("RetrieveVaultCredential401", RetrieveVaultCredential401), + "403": decodeError("RetrieveVaultCredential403", RetrieveVaultCredential403), + "404": decodeError("RetrieveVaultCredential404", RetrieveVaultCredential404), + "409": decodeError("RetrieveVaultCredential409", RetrieveVaultCredential409), + "500": decodeError("RetrieveVaultCredential500", RetrieveVaultCredential500), + "503": decodeError("RetrieveVaultCredential503", RetrieveVaultCredential503), + orElse: unexpectedStatus + })) + ) + ) + ), + "rotateVaultCredential": (vaultId, credentialId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.post, + [vaultId, credentialId], + () => "/vaults/" + __encodePathParam(vaultId) + "/credentials/" + __encodePathParam(credentialId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RotateVaultCredential200), + "400": decodeError("RotateVaultCredential400", RotateVaultCredential400), + "401": decodeError("RotateVaultCredential401", RotateVaultCredential401), + "403": decodeError("RotateVaultCredential403", RotateVaultCredential403), + "404": decodeError("RotateVaultCredential404", RotateVaultCredential404), + "409": decodeError("RotateVaultCredential409", RotateVaultCredential409), + "500": decodeError("RotateVaultCredential500", RotateVaultCredential500), + "503": decodeError("RotateVaultCredential503", RotateVaultCredential503), + orElse: unexpectedStatus + })) + ) + ) + ), + "deleteVaultCredential": (vaultId, credentialId, options: Parameters[2]) => + __makePathRequest( + HttpClientRequest.delete, + [vaultId, credentialId], + () => "/vaults/" + __encodePathParam(vaultId) + "/credentials/" + __encodePathParam(credentialId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteVaultCredential200), + "400": decodeError("DeleteVaultCredential400", DeleteVaultCredential400), + "401": decodeError("DeleteVaultCredential401", DeleteVaultCredential401), + "403": decodeError("DeleteVaultCredential403", DeleteVaultCredential403), + "404": decodeError("DeleteVaultCredential404", DeleteVaultCredential404), + "409": decodeError("DeleteVaultCredential409", DeleteVaultCredential409), + "500": decodeError("DeleteVaultCredential500", DeleteVaultCredential500), + "503": decodeError("DeleteVaultCredential503", DeleteVaultCredential503), + orElse: unexpectedStatus + })) + ) + ) ), - "ListSkillVersions": (skillId, options) => - HttpClientRequest.get(`/skills/${skillId}/versions`).pipe( + "ListWebhookEndpoints": (options: Parameters[0]) => + HttpClientRequest.get("/webhook_endpoints").pipe( HttpClientRequest.setUrlParams({ "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, "after": options?.params?.["after"] as any }), withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListSkillVersions200), + "2xx": decodeSuccess(ListWebhookEndpoints200), + "400": decodeError("ListWebhookEndpoints400", ListWebhookEndpoints400), + "404": decodeError("ListWebhookEndpoints404", ListWebhookEndpoints404), orElse: unexpectedStatus })) ), - "CreateSkillVersion": (skillId, options) => - HttpClientRequest.post(`/skills/${skillId}/versions`).pipe( - HttpClientRequest.bodyFormData(options.payload as any), + "CreateWebhookEndpoint": (options: Parameters[0]) => + HttpClientRequest.post("/webhook_endpoints").pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateSkillVersion200), + "2xx": decodeSuccess(CreateWebhookEndpoint200), + "400": decodeError("CreateWebhookEndpoint400", CreateWebhookEndpoint400), orElse: unexpectedStatus })) ), - "GetSkillVersion": (skillId, version, options) => - HttpClientRequest.get(`/skills/${skillId}/versions/${version}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetSkillVersion200), - orElse: unexpectedStatus - })) + "RetrieveWebhookEndpoint": (webhookEndpointId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [webhookEndpointId], + () => "/webhook_endpoints/" + __encodePathParam(webhookEndpointId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RetrieveWebhookEndpoint200), + "400": decodeError("RetrieveWebhookEndpoint400", RetrieveWebhookEndpoint400), + "404": decodeError("RetrieveWebhookEndpoint404", RetrieveWebhookEndpoint404), + orElse: unexpectedStatus + })) + ) + ) ), - "DeleteSkillVersion": (skillId, version, options) => - HttpClientRequest.delete(`/skills/${skillId}/versions/${version}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteSkillVersion200), - orElse: unexpectedStatus - })) + "UpdateWebhookEndpoint": (webhookEndpointId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [webhookEndpointId], + () => "/webhook_endpoints/" + __encodePathParam(webhookEndpointId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(UpdateWebhookEndpoint200), + "400": decodeError("UpdateWebhookEndpoint400", UpdateWebhookEndpoint400), + "404": decodeError("UpdateWebhookEndpoint404", UpdateWebhookEndpoint404), + orElse: unexpectedStatus + })) + ) + ) ), - "GetSkillVersionContent": (skillId, version, options) => - HttpClientRequest.get(`/skills/${skillId}/versions/${version}/content`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetSkillVersionContent200), - orElse: unexpectedStatus - })) + "DeleteWebhookEndpoint": (webhookEndpointId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [webhookEndpointId], + () => "/webhook_endpoints/" + __encodePathParam(webhookEndpointId) + "" + ).pipe( + Effect.flatMap((request) => + request.pipe( + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(DeleteWebhookEndpoint200), + "400": decodeError("DeleteWebhookEndpoint400", DeleteWebhookEndpoint400), + "404": decodeError("DeleteWebhookEndpoint404", DeleteWebhookEndpoint404), + orElse: unexpectedStatus + })) + ) + ) + ), + "RotateWebhookEndpointSigningSecret": ( + webhookEndpointId, + options: Parameters[1] + ) => + __makePathRequest( + HttpClientRequest.post, + [webhookEndpointId], + () => "/webhook_endpoints/" + __encodePathParam(webhookEndpointId) + "/rotate_secret" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(RotateWebhookEndpointSigningSecret200), + "400": decodeError("RotateWebhookEndpointSigningSecret400", RotateWebhookEndpointSigningSecret400), + "404": decodeError("RotateWebhookEndpointSigningSecret404", RotateWebhookEndpointSigningSecret404), + orElse: unexpectedStatus + })) + ) + ) ), - "CancelChatSessionMethod": (sessionId, options) => - HttpClientRequest.post(`/chatkit/sessions/${sessionId}/cancel`).pipe( + "TestWebhookEndpoint": (webhookEndpointId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [webhookEndpointId], + () => "/webhook_endpoints/" + __encodePathParam(webhookEndpointId) + "/test" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(TestWebhookEndpoint200), + "400": decodeError("TestWebhookEndpoint400", TestWebhookEndpoint400), + "404": decodeError("TestWebhookEndpoint404", TestWebhookEndpoint404), + "500": decodeError("TestWebhookEndpoint500", TestWebhookEndpoint500), + orElse: unexpectedStatus + })) + ) + ) + ), + "ListWebhookEventTypes": (options: Parameters[0]) => + HttpClientRequest.get("/webhook_event_types").pipe( withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CancelChatSessionMethod200), + "2xx": decodeSuccess(ListWebhookEventTypes200), + "401": decodeError("ListWebhookEventTypes401", ListWebhookEventTypes401), orElse: unexpectedStatus })) ), - "CreateChatSessionMethod": (options) => - HttpClientRequest.post(`/chatkit/sessions`).pipe( + "betaCreateResponse": (options: Parameters[0]) => + HttpClientRequest.post("/responses?beta=true").pipe( + HttpClientRequest.setHeaders({ "openai-beta": options.params?.["openai-beta"] ?? undefined }), HttpClientRequest.bodyJsonUnsafe(options.payload), withResponse(options.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(CreateChatSessionMethod200), + "2xx": decodeSuccess(BetaCreateResponse200), + "400": decodeError("BetaCreateResponse400", BetaCreateResponse400), + "404": decodeError("BetaCreateResponse404", BetaCreateResponse404), + "429": decodeError("BetaCreateResponse429", BetaCreateResponse429), + "503": decodeError("BetaCreateResponse503", BetaCreateResponse503), orElse: unexpectedStatus })) ), - "ListThreadItemsMethod": (threadId, options) => - HttpClientRequest.get(`/chatkit/threads/${threadId}/items`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListThreadItemsMethod200), - orElse: unexpectedStatus - })) + "betaCreateResponseSse": (options) => + HttpClientRequest.post("/responses?beta=true").pipe( + HttpClientRequest.setHeaders({ "openai-beta": options.params?.["openai-beta"] ?? undefined }), + HttpClientRequest.bodyJsonUnsafe(options.payload), + sseRequest(BetaCreateResponse200Sse) ), - "GetThreadMethod": (threadId, options) => - HttpClientRequest.get(`/chatkit/threads/${threadId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(GetThreadMethod200), - orElse: unexpectedStatus - })) + "betaGetResponse": (responseId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [responseId], + () => "/responses/" + __encodePathParam(responseId) + "?beta=true" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "include": options?.params?.["include"] as any, + "stream": options?.params?.["stream"] as any, + "starting_after": options?.params?.["starting_after"] as any, + "include_obfuscation": options?.params?.["include_obfuscation"] as any + }), + HttpClientRequest.setHeaders({ "openai-beta": options?.params?.["openai-beta"] ?? undefined }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(BetaGetResponse200), + "404": decodeError("BetaGetResponse404", BetaGetResponse404), + "429": decodeError("BetaGetResponse429", BetaGetResponse429), + orElse: unexpectedStatus + })) + ) + ) ), - "DeleteThreadMethod": (threadId, options) => - HttpClientRequest.delete(`/chatkit/threads/${threadId}`).pipe( - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(DeleteThreadMethod200), + "betaDeleteResponse": (responseId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.delete, + [responseId], + () => "/responses/" + __encodePathParam(responseId) + "?beta=true" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setHeaders({ "openai-beta": options?.params?.["openai-beta"] ?? undefined }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(BetaDeleteResponse200), + "404": decodeError("BetaDeleteResponse404", BetaDeleteResponse404), + "429": decodeError("BetaDeleteResponse429", BetaDeleteResponse429), + orElse: unexpectedStatus + })) + ) + ) + ), + "betaCancelResponse": (responseId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.post, + [responseId], + () => "/responses/" + __encodePathParam(responseId) + "/cancel?beta=true" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setHeaders({ "openai-beta": options?.params?.["openai-beta"] ?? undefined }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(BetaCancelResponse200), + "404": decodeError("BetaCancelResponse404", BetaCancelResponse404), + "429": decodeError("BetaCancelResponse429", BetaCancelResponse429), + orElse: unexpectedStatus + })) + ) + ) + ), + "betaCompactconversation": (options: Parameters[0]) => + HttpClientRequest.post("/responses/compact?beta=true").pipe( + HttpClientRequest.setHeaders({ "openai-beta": options.params?.["openai-beta"] ?? undefined }), + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(BetaCompactconversation200), + "400": decodeError("BetaCompactconversation400", BetaCompactconversation400), + "429": decodeError("BetaCompactconversation429", BetaCompactconversation429), + "503": decodeError("BetaCompactconversation503", BetaCompactconversation503), orElse: unexpectedStatus })) ), - "ListThreadsMethod": (options) => - HttpClientRequest.get(`/chatkit/threads`).pipe( - HttpClientRequest.setUrlParams({ - "limit": options?.params?.["limit"] as any, - "order": options?.params?.["order"] as any, - "after": options?.params?.["after"] as any, - "before": options?.params?.["before"] as any, - "user": options?.params?.["user"] as any - }), - withResponse(options?.config)(HttpClientResponse.matchStatus({ - "2xx": decodeSuccess(ListThreadsMethod200), + "betaListInputItems": (responseId, options: Parameters[1]) => + __makePathRequest( + HttpClientRequest.get, + [responseId], + () => "/responses/" + __encodePathParam(responseId) + "/input_items?beta=true" + ).pipe( + Effect.flatMap((request) => + request.pipe( + HttpClientRequest.setUrlParams({ + "limit": options?.params?.["limit"] as any, + "order": options?.params?.["order"] as any, + "after": options?.params?.["after"] as any, + "include": options?.params?.["include"] as any + }), + HttpClientRequest.setHeaders({ "openai-beta": options?.params?.["openai-beta"] ?? undefined }), + withResponse(options?.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(BetaListInputItems200), + "404": decodeError("BetaListInputItems404", BetaListInputItems404), + "429": decodeError("BetaListInputItems429", BetaListInputItems429), + orElse: unexpectedStatus + })) + ) + ) + ), + "betaGetinputtokencounts": (options: Parameters[0]) => + HttpClientRequest.post("/responses/input_tokens?beta=true").pipe( + HttpClientRequest.setHeaders({ "openai-beta": options.params?.["openai-beta"] ?? undefined }), + HttpClientRequest.bodyJsonUnsafe(options.payload), + withResponse(options.config)(HttpClientResponse.matchStatus({ + "2xx": decodeSuccess(BetaGetinputtokencounts200), + "400": decodeError("BetaGetinputtokencounts400", BetaGetinputtokencounts400), + "429": decodeError("BetaGetinputtokencounts429", BetaGetinputtokencounts429), orElse: unexpectedStatus })) ) } -} - -export interface OpenAiClient { - readonly httpClient: HttpClient.HttpClient +} + +export interface OpenAiClient { + readonly httpClient: HttpClient.HttpClient + /** + * Returns a list of assistants. + */ + readonly "listAssistants": { + ( + options: { readonly params?: typeof ListAssistantsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListAssistants429", ListAssistants429> + > + ( + options: { + readonly params?: typeof ListAssistantsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListAssistants429", ListAssistants429> + > + } + /** + * Create an assistant with a model and instructions. + */ + readonly "createAssistant": { + ( + options: { readonly payload: typeof CreateAssistantRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateAssistant429", CreateAssistant429> + > + ( + options: { readonly payload: typeof CreateAssistantRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateAssistant429", CreateAssistant429> + > + } + /** + * Retrieves an assistant. + */ + readonly "getAssistant": { + ( + assistantId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetAssistant429", GetAssistant429> + > + ( + assistantId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetAssistant429", GetAssistant429> + > + } + /** + * Modifies an assistant. + */ + readonly "modifyAssistant": { + ( + assistantId: string, + options: { readonly payload: typeof ModifyAssistantRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyAssistant429", ModifyAssistant429> + > + ( + assistantId: string, + options: { readonly payload: typeof ModifyAssistantRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyAssistant429", ModifyAssistant429> + > + } + /** + * Delete an assistant. + */ + readonly "deleteAssistant": { + ( + assistantId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"DeleteAssistant429", DeleteAssistant429> + > + ( + assistantId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"DeleteAssistant429", DeleteAssistant429> + > + } + /** + * Generates audio from the input text. + * + * Returns the audio file content, or a stream of audio events. + */ + readonly "createSpeech": { + ( + options: { readonly payload: typeof CreateSpeechRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateSpeech400", CreateSpeech400> + | OpenAiClientError<"CreateSpeech401", CreateSpeech401> + | OpenAiClientError<"CreateSpeech429", CreateSpeech429> + | OpenAiClientError<"CreateSpeech500", CreateSpeech500> + | OpenAiClientError<"CreateSpeech503", CreateSpeech503> + > + ( + options: { readonly payload: typeof CreateSpeechRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateSpeech400", CreateSpeech400> + | OpenAiClientError<"CreateSpeech401", CreateSpeech401> + | OpenAiClientError<"CreateSpeech429", CreateSpeech429> + | OpenAiClientError<"CreateSpeech500", CreateSpeech500> + | OpenAiClientError<"CreateSpeech503", CreateSpeech503> + > + } + /** + * Generates audio from the input text. + * + * Returns the audio file content, or a stream of audio events. + */ + readonly "createSpeechSse": ( + options: { readonly payload: typeof CreateSpeechRequestJson.Encoded } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: CreateSpeech200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof CreateSpeech200Sse.DecodingServices + > + /** + * Generates audio from the input text. + * + * Returns the audio file content, or a stream of audio events. + */ + readonly "createSpeechStream": ( + options: { readonly payload: typeof CreateSpeechRequestJson.Encoded } + ) => Stream.Stream + /** + * Transcribes audio into the input language. + * + * Returns a transcription object in `json`, `diarized_json`, or `verbose_json` + * format, plain text in `text`, `srt`, or `vtt` format, or a stream of + * transcript events. Supported formats depend on the model. + */ + readonly "createTranscription": { + ( + options: { readonly payload: typeof CreateTranscriptionRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateTranscription400", CreateTranscription400> + | OpenAiClientError<"CreateTranscription401", CreateTranscription401> + | OpenAiClientError<"CreateTranscription413", CreateTranscription413> + | OpenAiClientError<"CreateTranscription429", CreateTranscription429> + | OpenAiClientError<"CreateTranscription500", CreateTranscription500> + | OpenAiClientError<"CreateTranscription502", CreateTranscription502> + | OpenAiClientError<"CreateTranscription503", CreateTranscription503> + > + ( + options: { + readonly payload: typeof CreateTranscriptionRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateTranscription400", CreateTranscription400> + | OpenAiClientError<"CreateTranscription401", CreateTranscription401> + | OpenAiClientError<"CreateTranscription413", CreateTranscription413> + | OpenAiClientError<"CreateTranscription429", CreateTranscription429> + | OpenAiClientError<"CreateTranscription500", CreateTranscription500> + | OpenAiClientError<"CreateTranscription502", CreateTranscription502> + | OpenAiClientError<"CreateTranscription503", CreateTranscription503> + > + } + /** + * Transcribes audio into the input language. + * + * Returns a transcription object in `json`, `diarized_json`, or `verbose_json` + * format, plain text in `text`, `srt`, or `vtt` format, or a stream of + * transcript events. Supported formats depend on the model. + */ + readonly "createTranscriptionSse": ( + options: { readonly payload: typeof CreateTranscriptionRequestFormData.Encoded } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: CreateTranscription200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof CreateTranscription200Sse.DecodingServices + > + /** + * Translates audio into English. + */ + readonly "createTranslation": { + ( + options: { readonly payload: typeof CreateTranslationRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateTranslation400", CreateTranslation400> + | OpenAiClientError<"CreateTranslation401", CreateTranslation401> + | OpenAiClientError<"CreateTranslation413", CreateTranslation413> + | OpenAiClientError<"CreateTranslation429", CreateTranslation429> + | OpenAiClientError<"CreateTranslation500", CreateTranslation500> + | OpenAiClientError<"CreateTranslation502", CreateTranslation502> + | OpenAiClientError<"CreateTranslation503", CreateTranslation503> + > + ( + options: { + readonly payload: typeof CreateTranslationRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateTranslation400", CreateTranslation400> + | OpenAiClientError<"CreateTranslation401", CreateTranslation401> + | OpenAiClientError<"CreateTranslation413", CreateTranslation413> + | OpenAiClientError<"CreateTranslation429", CreateTranslation429> + | OpenAiClientError<"CreateTranslation500", CreateTranslation500> + | OpenAiClientError<"CreateTranslation502", CreateTranslation502> + | OpenAiClientError<"CreateTranslation503", CreateTranslation503> + > + } + /** + * Returns a list of voice consent recordings. + */ + readonly "listVoiceConsents": { + ( + options: { readonly params?: typeof ListVoiceConsentsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVoiceConsents400", ListVoiceConsents400> + | OpenAiClientError<"ListVoiceConsents404", ListVoiceConsents404> + > + ( + options: { + readonly params?: typeof ListVoiceConsentsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVoiceConsents400", ListVoiceConsents400> + | OpenAiClientError<"ListVoiceConsents404", ListVoiceConsents404> + > + } + /** + * Upload a voice consent recording. + */ + readonly "createVoiceConsent": { + ( + options: { readonly payload: typeof CreateVoiceConsentRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVoiceConsent400", CreateVoiceConsent400> + | OpenAiClientError<"CreateVoiceConsent404", CreateVoiceConsent404> + > + ( + options: { + readonly payload: typeof CreateVoiceConsentRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVoiceConsent400", CreateVoiceConsent400> + | OpenAiClientError<"CreateVoiceConsent404", CreateVoiceConsent404> + > + } + /** + * Retrieves a voice consent recording. + */ + readonly "getVoiceConsent": { + ( + consentId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVoiceConsent400", GetVoiceConsent400> + | OpenAiClientError<"GetVoiceConsent404", GetVoiceConsent404> + > + ( + consentId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVoiceConsent400", GetVoiceConsent400> + | OpenAiClientError<"GetVoiceConsent404", GetVoiceConsent404> + > + } + /** + * Updates a voice consent recording (metadata only). + */ + readonly "updateVoiceConsent": { + ( + consentId: string, + options: { readonly payload: typeof UpdateVoiceConsentRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateVoiceConsent400", UpdateVoiceConsent400> + | OpenAiClientError<"UpdateVoiceConsent404", UpdateVoiceConsent404> + > + ( + consentId: string, + options: { readonly payload: typeof UpdateVoiceConsentRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateVoiceConsent400", UpdateVoiceConsent400> + | OpenAiClientError<"UpdateVoiceConsent404", UpdateVoiceConsent404> + > + } + /** + * Deletes a voice consent recording. + */ + readonly "deleteVoiceConsent": { + ( + consentId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVoiceConsent400", DeleteVoiceConsent400> + | OpenAiClientError<"DeleteVoiceConsent404", DeleteVoiceConsent404> + > + ( + consentId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVoiceConsent400", DeleteVoiceConsent400> + | OpenAiClientError<"DeleteVoiceConsent404", DeleteVoiceConsent404> + > + } + /** + * Create a custom voice you can use for audio output (for example, in Text-to-Speech and the Realtime API). This requires an audio sample and a previously uploaded consent recording. + * + * Send `name`, `audio_sample`, and the `consent` recording ID as multipart form data. The optional `type` defaults to `audio_sample`. + * + * Returns the saved voice's metadata. See the [custom voices guide](https://developers.openai.com/api/docs/guides/text-to-speech#custom-voices) for requirements and best practices. Custom voices are limited to eligible customers. + */ + readonly "createVoice": { + ( + options: { readonly payload: typeof CreateVoiceRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVoice400", CreateVoice400> + | OpenAiClientError<"CreateVoice404", CreateVoice404> + | OpenAiClientError<"CreateVoice500", CreateVoice500> + > + ( + options: { readonly payload: typeof CreateVoiceRequestFormData.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVoice400", CreateVoice400> + | OpenAiClientError<"CreateVoice404", CreateVoice404> + | OpenAiClientError<"CreateVoice500", CreateVoice500> + > + } + /** + * List your organization's batches. + */ + readonly "listBatches": { + ( + options: { readonly params?: typeof ListBatchesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListBatches400", ListBatches400> + | OpenAiClientError<"ListBatches404", ListBatches404> + | OpenAiClientError<"ListBatches429", ListBatches429> + > + ( + options: + | { readonly params?: typeof ListBatchesParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListBatches400", ListBatches400> + | OpenAiClientError<"ListBatches404", ListBatches404> + | OpenAiClientError<"ListBatches429", ListBatches429> + > + } + /** + * Creates and executes a batch from an uploaded file of requests + */ + readonly "createBatch": { + ( + options: { readonly payload: typeof CreateBatchRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateBatch400", CreateBatch400> + | OpenAiClientError<"CreateBatch429", CreateBatch429> + | OpenAiClientError<"CreateBatch500", CreateBatch500> + | OpenAiClientError<"CreateBatch503", CreateBatch503> + > + ( + options: { readonly payload: typeof CreateBatchRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateBatch400", CreateBatch400> + | OpenAiClientError<"CreateBatch429", CreateBatch429> + | OpenAiClientError<"CreateBatch500", CreateBatch500> + | OpenAiClientError<"CreateBatch503", CreateBatch503> + > + } + /** + * Retrieves a batch. + */ + readonly "retrieveBatch": { + ( + batchId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveBatch400", RetrieveBatch400> + | OpenAiClientError<"RetrieveBatch404", RetrieveBatch404> + | OpenAiClientError<"RetrieveBatch429", RetrieveBatch429> + > + ( + batchId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveBatch400", RetrieveBatch400> + | OpenAiClientError<"RetrieveBatch404", RetrieveBatch404> + | OpenAiClientError<"RetrieveBatch429", RetrieveBatch429> + > + } + /** + * Cancels an in-progress batch. The batch will be in status `cancelling` for up to 10 minutes, before changing to `cancelled`, where it will have partial results (if any) available in the output file. + */ + readonly "cancelBatch": { + ( + batchId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelBatch400", CancelBatch400> + | OpenAiClientError<"CancelBatch404", CancelBatch404> + | OpenAiClientError<"CancelBatch409", CancelBatch409> + | OpenAiClientError<"CancelBatch429", CancelBatch429> + > + ( + batchId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelBatch400", CancelBatch400> + | OpenAiClientError<"CancelBatch404", CancelBatch404> + | OpenAiClientError<"CancelBatch409", CancelBatch409> + | OpenAiClientError<"CancelBatch429", CancelBatch429> + > + } + /** + * List stored Chat Completions. Only Chat Completions that have been stored + * with the `store` parameter set to `true` will be returned. + */ + readonly "listChatCompletions": { + ( + options: { readonly params?: typeof ListChatCompletionsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListChatCompletions400", ListChatCompletions400> + | OpenAiClientError<"ListChatCompletions429", ListChatCompletions429> + | OpenAiClientError<"ListChatCompletions500", ListChatCompletions500> + > + ( + options: { + readonly params?: typeof ListChatCompletionsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListChatCompletions400", ListChatCompletions400> + | OpenAiClientError<"ListChatCompletions429", ListChatCompletions429> + | OpenAiClientError<"ListChatCompletions500", ListChatCompletions500> + > + } + /** + * **Starting a new project?** We recommend trying [Responses](https://developers.openai.com/api/reference/resources/responses) + * to take advantage of the latest OpenAI platform features. Compare + * [Chat Completions with Responses](https://developers.openai.com/api/docs/guides/migrate-to-responses?api-mode=responses). + * + * --- + * + * Creates a model response for the given chat conversation. Learn more in the + * [text generation](https://developers.openai.com/api/docs/guides/text), [vision](https://developers.openai.com/api/docs/guides/images-vision), + * and [audio](https://developers.openai.com/api/docs/guides/audio) guides. + * + * Parameter support can differ depending on the model used to generate the + * response, particularly for newer reasoning models. Parameters that are only + * supported for reasoning models are noted below. For the current state of + * unsupported parameters in reasoning models, + * [refer to the reasoning guide](https://developers.openai.com/api/docs/guides/reasoning). + * + * Returns a chat completion object, or a streamed sequence of chat completion + * chunk objects if the request is streamed. + */ + readonly "createChatCompletion": { + ( + options: { readonly payload: typeof CreateChatCompletionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateChatCompletion400", CreateChatCompletion400> + | OpenAiClientError<"CreateChatCompletion401", CreateChatCompletion401> + | OpenAiClientError<"CreateChatCompletion404", CreateChatCompletion404> + | OpenAiClientError<"CreateChatCompletion429", CreateChatCompletion429> + | OpenAiClientError<"CreateChatCompletion500", CreateChatCompletion500> + | OpenAiClientError<"CreateChatCompletion503", CreateChatCompletion503> + > + ( + options: { + readonly payload: typeof CreateChatCompletionRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateChatCompletion400", CreateChatCompletion400> + | OpenAiClientError<"CreateChatCompletion401", CreateChatCompletion401> + | OpenAiClientError<"CreateChatCompletion404", CreateChatCompletion404> + | OpenAiClientError<"CreateChatCompletion429", CreateChatCompletion429> + | OpenAiClientError<"CreateChatCompletion500", CreateChatCompletion500> + | OpenAiClientError<"CreateChatCompletion503", CreateChatCompletion503> + > + } + /** + * **Starting a new project?** We recommend trying [Responses](https://developers.openai.com/api/reference/resources/responses) + * to take advantage of the latest OpenAI platform features. Compare + * [Chat Completions with Responses](https://developers.openai.com/api/docs/guides/migrate-to-responses?api-mode=responses). + * + * --- + * + * Creates a model response for the given chat conversation. Learn more in the + * [text generation](https://developers.openai.com/api/docs/guides/text), [vision](https://developers.openai.com/api/docs/guides/images-vision), + * and [audio](https://developers.openai.com/api/docs/guides/audio) guides. + * + * Parameter support can differ depending on the model used to generate the + * response, particularly for newer reasoning models. Parameters that are only + * supported for reasoning models are noted below. For the current state of + * unsupported parameters in reasoning models, + * [refer to the reasoning guide](https://developers.openai.com/api/docs/guides/reasoning). + * + * Returns a chat completion object, or a streamed sequence of chat completion + * chunk objects if the request is streamed. + */ + readonly "createChatCompletionSse": ( + options: { readonly payload: typeof CreateChatCompletionRequestJson.Encoded } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: CreateChatCompletion200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof CreateChatCompletion200Sse.DecodingServices + > + /** + * Get a stored chat completion. Only Chat Completions that have been created + * with the `store` parameter set to `true` will be returned. + */ + readonly "getChatCompletion": { + ( + completionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetChatCompletion404", GetChatCompletion404> + | OpenAiClientError<"GetChatCompletion429", GetChatCompletion429> + | OpenAiClientError<"GetChatCompletion500", GetChatCompletion500> + > + ( + completionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetChatCompletion404", GetChatCompletion404> + | OpenAiClientError<"GetChatCompletion429", GetChatCompletion429> + | OpenAiClientError<"GetChatCompletion500", GetChatCompletion500> + > + } + /** + * Modify a stored chat completion. Only Chat Completions that have been + * created with the `store` parameter set to `true` can be modified. Currently, + * the only supported modification is to update the `metadata` field. + */ + readonly "updateChatCompletion": { + ( + completionId: string, + options: { readonly payload: typeof UpdateChatCompletionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateChatCompletion400", UpdateChatCompletion400> + | OpenAiClientError<"UpdateChatCompletion404", UpdateChatCompletion404> + | OpenAiClientError<"UpdateChatCompletion429", UpdateChatCompletion429> + | OpenAiClientError<"UpdateChatCompletion500", UpdateChatCompletion500> + > + ( + completionId: string, + options: { + readonly payload: typeof UpdateChatCompletionRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateChatCompletion400", UpdateChatCompletion400> + | OpenAiClientError<"UpdateChatCompletion404", UpdateChatCompletion404> + | OpenAiClientError<"UpdateChatCompletion429", UpdateChatCompletion429> + | OpenAiClientError<"UpdateChatCompletion500", UpdateChatCompletion500> + > + } + /** + * Delete a stored chat completion. Only Chat Completions that have been + * created with the `store` parameter set to `true` can be deleted. + */ + readonly "deleteChatCompletion": { + ( + completionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteChatCompletion404", DeleteChatCompletion404> + | OpenAiClientError<"DeleteChatCompletion429", DeleteChatCompletion429> + | OpenAiClientError<"DeleteChatCompletion500", DeleteChatCompletion500> + > + ( + completionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteChatCompletion404", DeleteChatCompletion404> + | OpenAiClientError<"DeleteChatCompletion429", DeleteChatCompletion429> + | OpenAiClientError<"DeleteChatCompletion500", DeleteChatCompletion500> + > + } + /** + * Get the messages in a stored chat completion. Only Chat Completions that + * have been created with the `store` parameter set to `true` will be + * returned. + */ + readonly "getChatCompletionMessages": { + ( + completionId: string, + options: { readonly params?: typeof GetChatCompletionMessagesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetChatCompletionMessages400", GetChatCompletionMessages400> + | OpenAiClientError<"GetChatCompletionMessages404", GetChatCompletionMessages404> + | OpenAiClientError<"GetChatCompletionMessages429", GetChatCompletionMessages429> + | OpenAiClientError<"GetChatCompletionMessages500", GetChatCompletionMessages500> + > + ( + completionId: string, + options: { + readonly params?: typeof GetChatCompletionMessagesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetChatCompletionMessages400", GetChatCompletionMessages400> + | OpenAiClientError<"GetChatCompletionMessages404", GetChatCompletionMessages404> + | OpenAiClientError<"GetChatCompletionMessages429", GetChatCompletionMessages429> + | OpenAiClientError<"GetChatCompletionMessages500", GetChatCompletionMessages500> + > + } + /** + * Creates a completion for the provided prompt and parameters. + * + * Returns a completion object, or a sequence of completion objects if the request is streamed. + */ + readonly "createCompletion": { + ( + options: { readonly payload: typeof CreateCompletionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateCompletion400", CreateCompletion400> + | OpenAiClientError<"CreateCompletion401", CreateCompletion401> + | OpenAiClientError<"CreateCompletion404", CreateCompletion404> + | OpenAiClientError<"CreateCompletion429", CreateCompletion429> + | OpenAiClientError<"CreateCompletion500", CreateCompletion500> + | OpenAiClientError<"CreateCompletion503", CreateCompletion503> + > + ( + options: { readonly payload: typeof CreateCompletionRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateCompletion400", CreateCompletion400> + | OpenAiClientError<"CreateCompletion401", CreateCompletion401> + | OpenAiClientError<"CreateCompletion404", CreateCompletion404> + | OpenAiClientError<"CreateCompletion429", CreateCompletion429> + | OpenAiClientError<"CreateCompletion500", CreateCompletion500> + | OpenAiClientError<"CreateCompletion503", CreateCompletion503> + > + } + /** + * List Containers + */ + readonly "ListContainers": { + ( + options: { readonly params?: typeof ListContainersParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListContainers404", ListContainers404> + | OpenAiClientError<"ListContainers429", ListContainers429> + > + ( + options: { + readonly params?: typeof ListContainersParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListContainers404", ListContainers404> + | OpenAiClientError<"ListContainers429", ListContainers429> + > + } + /** + * Create Container + */ + readonly "CreateContainer": { + ( + options: { readonly payload: typeof CreateContainerRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateContainer400", CreateContainer400> + | OpenAiClientError<"CreateContainer429", CreateContainer429> + > + ( + options: { readonly payload: typeof CreateContainerRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateContainer400", CreateContainer400> + | OpenAiClientError<"CreateContainer429", CreateContainer429> + > + } + /** + * Retrieve Container + */ + readonly "RetrieveContainer": { + ( + containerId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveContainer404", RetrieveContainer404> + | OpenAiClientError<"RetrieveContainer429", RetrieveContainer429> + > + ( + containerId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveContainer404", RetrieveContainer404> + | OpenAiClientError<"RetrieveContainer429", RetrieveContainer429> + > + } + /** + * Delete Container + */ + readonly "DeleteContainer": { + ( + containerId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteContainer404", DeleteContainer404> + | OpenAiClientError<"DeleteContainer429", DeleteContainer429> + > + ( + containerId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteContainer404", DeleteContainer404> + | OpenAiClientError<"DeleteContainer429", DeleteContainer429> + > + } + /** + * List Container files + */ + readonly "ListContainerFiles": { + ( + containerId: string, + options: { readonly params?: typeof ListContainerFilesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListContainerFiles404", ListContainerFiles404> + | OpenAiClientError<"ListContainerFiles429", ListContainerFiles429> + > + ( + containerId: string, + options: { + readonly params?: typeof ListContainerFilesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListContainerFiles404", ListContainerFiles404> + | OpenAiClientError<"ListContainerFiles429", ListContainerFiles429> + > + } + /** + * Create a Container File + * + * You can send either a multipart/form-data request with the raw file content, or a JSON request with a file ID. + */ + readonly "CreateContainerFile": { + ( + containerId: string, + options: { readonly payload: typeof CreateContainerFileRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateContainerFile400", CreateContainerFile400> + | OpenAiClientError<"CreateContainerFile404", CreateContainerFile404> + | OpenAiClientError<"CreateContainerFile429", CreateContainerFile429> + > + ( + containerId: string, + options: { + readonly payload: typeof CreateContainerFileRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateContainerFile400", CreateContainerFile400> + | OpenAiClientError<"CreateContainerFile404", CreateContainerFile404> + | OpenAiClientError<"CreateContainerFile429", CreateContainerFile429> + > + } + /** + * Retrieve Container File + */ + readonly "RetrieveContainerFile": { + ( + containerId: string, + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveContainerFile404", RetrieveContainerFile404> + | OpenAiClientError<"RetrieveContainerFile429", RetrieveContainerFile429> + > + ( + containerId: string, + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveContainerFile404", RetrieveContainerFile404> + | OpenAiClientError<"RetrieveContainerFile429", RetrieveContainerFile429> + > + } + /** + * Delete Container File + */ + readonly "DeleteContainerFile": { + ( + containerId: string, + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteContainerFile404", DeleteContainerFile404> + | OpenAiClientError<"DeleteContainerFile429", DeleteContainerFile429> + > + ( + containerId: string, + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteContainerFile404", DeleteContainerFile404> + | OpenAiClientError<"DeleteContainerFile429", DeleteContainerFile429> + > + } + /** + * Retrieve Container File Content + */ + readonly "RetrieveContainerFileContent": { + ( + containerId: string, + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveContainerFileContent404", RetrieveContainerFileContent404> + | OpenAiClientError<"RetrieveContainerFileContent429", RetrieveContainerFileContent429> + > + ( + containerId: string, + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveContainerFileContent404", RetrieveContainerFileContent404> + | OpenAiClientError<"RetrieveContainerFileContent429", RetrieveContainerFileContent429> + > + } + /** + * Retrieve Container File Content + */ + readonly "RetrieveContainerFileContentStream": ( + containerId: string, + fileId: string + ) => Stream.Stream + /** + * List all items for a conversation with the given ID. + */ + readonly "listConversationItems": { + ( + conversationId: string, + options: { readonly params?: typeof ListConversationItemsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListConversationItems400", ListConversationItems400> + | OpenAiClientError<"ListConversationItems404", ListConversationItems404> + | OpenAiClientError<"ListConversationItems429", ListConversationItems429> + > + ( + conversationId: string, + options: { + readonly params?: typeof ListConversationItemsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListConversationItems400", ListConversationItems400> + | OpenAiClientError<"ListConversationItems404", ListConversationItems404> + | OpenAiClientError<"ListConversationItems429", ListConversationItems429> + > + } + /** + * Create items in a conversation with the given ID. + */ + readonly "createConversationItems": { + ( + conversationId: string, + options: { + readonly params?: typeof CreateConversationItemsParams.Encoded | undefined + readonly payload: typeof CreateConversationItemsRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateConversationItems400", CreateConversationItems400> + | OpenAiClientError<"CreateConversationItems404", CreateConversationItems404> + | OpenAiClientError<"CreateConversationItems429", CreateConversationItems429> + | OpenAiClientError<"CreateConversationItems500", CreateConversationItems500> + > + ( + conversationId: string, + options: { + readonly params?: typeof CreateConversationItemsParams.Encoded | undefined + readonly payload: typeof CreateConversationItemsRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateConversationItems400", CreateConversationItems400> + | OpenAiClientError<"CreateConversationItems404", CreateConversationItems404> + | OpenAiClientError<"CreateConversationItems429", CreateConversationItems429> + | OpenAiClientError<"CreateConversationItems500", CreateConversationItems500> + > + } + /** + * Get a single item from a conversation with the given IDs. + */ + readonly "getConversationItem": { + ( + conversationId: string, + itemId: string, + options: { readonly params?: typeof GetConversationItemParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetConversationItem404", GetConversationItem404> + | OpenAiClientError<"GetConversationItem429", GetConversationItem429> + > + ( + conversationId: string, + itemId: string, + options: { + readonly params?: typeof GetConversationItemParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetConversationItem404", GetConversationItem404> + | OpenAiClientError<"GetConversationItem429", GetConversationItem429> + > + } + /** + * Delete an item from a conversation with the given IDs. + */ + readonly "deleteConversationItem": { + ( + conversationId: string, + itemId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteConversationItem400", DeleteConversationItem400> + | OpenAiClientError<"DeleteConversationItem404", DeleteConversationItem404> + | OpenAiClientError<"DeleteConversationItem429", DeleteConversationItem429> + | OpenAiClientError<"DeleteConversationItem500", DeleteConversationItem500> + > + ( + conversationId: string, + itemId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteConversationItem400", DeleteConversationItem400> + | OpenAiClientError<"DeleteConversationItem404", DeleteConversationItem404> + | OpenAiClientError<"DeleteConversationItem429", DeleteConversationItem429> + | OpenAiClientError<"DeleteConversationItem500", DeleteConversationItem500> + > + } + /** + * Creates an embedding vector representing the input text. + */ + readonly "createEmbedding": { + ( + options: { readonly payload: typeof CreateEmbeddingRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateEmbedding400", CreateEmbedding400> + | OpenAiClientError<"CreateEmbedding401", CreateEmbedding401> + | OpenAiClientError<"CreateEmbedding429", CreateEmbedding429> + | OpenAiClientError<"CreateEmbedding500", CreateEmbedding500> + | OpenAiClientError<"CreateEmbedding503", CreateEmbedding503> + > + ( + options: { readonly payload: typeof CreateEmbeddingRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateEmbedding400", CreateEmbedding400> + | OpenAiClientError<"CreateEmbedding401", CreateEmbedding401> + | OpenAiClientError<"CreateEmbedding429", CreateEmbedding429> + | OpenAiClientError<"CreateEmbedding500", CreateEmbedding500> + | OpenAiClientError<"CreateEmbedding503", CreateEmbedding503> + > + } + /** + * List evaluations for a project. + */ + readonly "listEvals": { + ( + options: { readonly params?: typeof ListEvalsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListEvals429", ListEvals429> + > + ( + options: + | { readonly params?: typeof ListEvalsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListEvals429", ListEvals429> + > + } + /** + * Create the structure of an evaluation that can be used to test a model's performance. + * An evaluation is a set of testing criteria and the config for a data source, which dictates the schema of the data used in the evaluation. After creating an evaluation, you can run it on different models and model parameters. We support several types of graders and datasources. + * For more information, see the [Evals guide](https://developers.openai.com/api/docs/guides/evals). + */ + readonly "createEval": { + ( + options: { readonly payload: typeof CreateEvalRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateEval400", CreateEval400> + | OpenAiClientError<"CreateEval429", CreateEval429> + > + ( + options: { readonly payload: typeof CreateEvalRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateEval400", CreateEval400> + | OpenAiClientError<"CreateEval429", CreateEval429> + > + } + /** + * Get an evaluation by ID. + */ + readonly "getEval": { + ( + evalId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEval404", GetEval404> + | OpenAiClientError<"GetEval429", GetEval429> + > + ( + evalId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEval404", GetEval404> + | OpenAiClientError<"GetEval429", GetEval429> + > + } + /** + * Update certain properties of an evaluation. + */ + readonly "updateEval": { + ( + evalId: string, + options: { readonly payload: typeof UpdateEvalRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateEval400", UpdateEval400> + | OpenAiClientError<"UpdateEval404", UpdateEval404> + | OpenAiClientError<"UpdateEval429", UpdateEval429> + > + ( + evalId: string, + options: { readonly payload: typeof UpdateEvalRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateEval400", UpdateEval400> + | OpenAiClientError<"UpdateEval404", UpdateEval404> + | OpenAiClientError<"UpdateEval429", UpdateEval429> + > + } + /** + * Delete an evaluation. + */ + readonly "deleteEval": { + ( + evalId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteEval400", DeleteEval400> + | OpenAiClientError<"DeleteEval404", DeleteEval404> + | OpenAiClientError<"DeleteEval429", DeleteEval429> + > + ( + evalId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteEval400", DeleteEval400> + | OpenAiClientError<"DeleteEval404", DeleteEval404> + | OpenAiClientError<"DeleteEval429", DeleteEval429> + > + } + /** + * Get a list of runs for an evaluation. + */ + readonly "getEvalRuns": { + ( + evalId: string, + options: { readonly params?: typeof GetEvalRunsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEvalRuns400", GetEvalRuns400> + | OpenAiClientError<"GetEvalRuns404", GetEvalRuns404> + | OpenAiClientError<"GetEvalRuns429", GetEvalRuns429> + > + ( + evalId: string, + options: + | { readonly params?: typeof GetEvalRunsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEvalRuns400", GetEvalRuns400> + | OpenAiClientError<"GetEvalRuns404", GetEvalRuns404> + | OpenAiClientError<"GetEvalRuns429", GetEvalRuns429> + > + } + /** + * Kicks off a new run for a given evaluation, specifying the data source, and what model configuration to use to test. The datasource will be validated against the schema specified in the config of the evaluation. + */ + readonly "createEvalRun": { + ( + evalId: string, + options: { readonly payload: typeof CreateEvalRunRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateEvalRun400", CreateEvalRun400> + | OpenAiClientError<"CreateEvalRun404", CreateEvalRun404> + | OpenAiClientError<"CreateEvalRun429", CreateEvalRun429> + | OpenAiClientError<"CreateEvalRun500", CreateEvalRun500> + > + ( + evalId: string, + options: { readonly payload: typeof CreateEvalRunRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateEvalRun400", CreateEvalRun400> + | OpenAiClientError<"CreateEvalRun404", CreateEvalRun404> + | OpenAiClientError<"CreateEvalRun429", CreateEvalRun429> + | OpenAiClientError<"CreateEvalRun500", CreateEvalRun500> + > + } + /** + * Get an evaluation run by ID. + */ + readonly "getEvalRun": { + ( + evalId: string, + runId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEvalRun400", GetEvalRun400> + | OpenAiClientError<"GetEvalRun404", GetEvalRun404> + | OpenAiClientError<"GetEvalRun429", GetEvalRun429> + > + ( + evalId: string, + runId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEvalRun400", GetEvalRun400> + | OpenAiClientError<"GetEvalRun404", GetEvalRun404> + | OpenAiClientError<"GetEvalRun429", GetEvalRun429> + > + } + /** + * Delete an eval run. + */ + readonly "deleteEvalRun": { + ( + evalId: string, + runId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteEvalRun400", DeleteEvalRun400> + | OpenAiClientError<"DeleteEvalRun404", DeleteEvalRun404> + | OpenAiClientError<"DeleteEvalRun429", DeleteEvalRun429> + > + ( + evalId: string, + runId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteEvalRun400", DeleteEvalRun400> + | OpenAiClientError<"DeleteEvalRun404", DeleteEvalRun404> + | OpenAiClientError<"DeleteEvalRun429", DeleteEvalRun429> + > + } + /** + * Cancel an ongoing evaluation run. + */ + readonly "cancelEvalRun": { + ( + evalId: string, + runId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CancelEvalRun429", CancelEvalRun429> + > + ( + evalId: string, + runId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CancelEvalRun429", CancelEvalRun429> + > + } + /** + * Get a list of output items for an evaluation run. + */ + readonly "getEvalRunOutputItems": { + ( + evalId: string, + runId: string, + options: { readonly params?: typeof GetEvalRunOutputItemsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEvalRunOutputItems400", GetEvalRunOutputItems400> + | OpenAiClientError<"GetEvalRunOutputItems404", GetEvalRunOutputItems404> + | OpenAiClientError<"GetEvalRunOutputItems429", GetEvalRunOutputItems429> + > + ( + evalId: string, + runId: string, + options: { + readonly params?: typeof GetEvalRunOutputItemsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEvalRunOutputItems400", GetEvalRunOutputItems400> + | OpenAiClientError<"GetEvalRunOutputItems404", GetEvalRunOutputItems404> + | OpenAiClientError<"GetEvalRunOutputItems429", GetEvalRunOutputItems429> + > + } + /** + * Get an evaluation run output item by ID. + */ + readonly "getEvalRunOutputItem": { + ( + evalId: string, + runId: string, + outputItemId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEvalRunOutputItem400", GetEvalRunOutputItem400> + | OpenAiClientError<"GetEvalRunOutputItem404", GetEvalRunOutputItem404> + | OpenAiClientError<"GetEvalRunOutputItem429", GetEvalRunOutputItem429> + > + ( + evalId: string, + runId: string, + outputItemId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetEvalRunOutputItem400", GetEvalRunOutputItem400> + | OpenAiClientError<"GetEvalRunOutputItem404", GetEvalRunOutputItem404> + | OpenAiClientError<"GetEvalRunOutputItem429", GetEvalRunOutputItem429> + > + } + /** + * Returns a list of files. + */ + readonly "listFiles": { + ( + options: { readonly params?: typeof ListFilesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFiles400", ListFiles400> + | OpenAiClientError<"ListFiles404", ListFiles404> + | OpenAiClientError<"ListFiles429", ListFiles429> + > + ( + options: + | { readonly params?: typeof ListFilesParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFiles400", ListFiles400> + | OpenAiClientError<"ListFiles404", ListFiles404> + | OpenAiClientError<"ListFiles429", ListFiles429> + > + } + /** + * Upload a file that can be used across various endpoints. Individual files + * can be up to 512 MB, and each project can store up to 2.5 TB of files in + * total. There is no organization-wide storage limit. Uploads to this + * endpoint are rate-limited to 1,000 requests per minute per authenticated + * user. + * + * - The Assistants API supports files up to 2 million tokens and of specific + * file types. See the [Assistants Tools guide](https://developers.openai.com/api/docs/guides/tools) for + * details. + * - The Fine-tuning API only supports `.jsonl` files. The input also has + * certain required formats for fine-tuning + * [chat](https://developers.openai.com/api/docs/guides/supervised-fine-tuning#formatting-your-data) or + * [completions](https://developers.openai.com/api/docs/guides/supervised-fine-tuning#formatting-your-data) models. + * - The Batch API only supports `.jsonl` files up to 200 MB in size. The input + * also has a specific required + * [format](https://developers.openai.com/api/docs/guides/batch#1-prepare-your-batch-file). + * - For Retrieval or `file_search` ingestion, upload files here first. If + * you need to attach multiple uploaded files to the same vector store, use + * [`/vector_stores/{vector_store_id}/file_batches`](https://developers.openai.com/api/reference/resources/vector_stores/subresources/file_batches/methods/create) + * instead of attaching them one by one. Vector store attachment has separate + * limits from file upload, including 2,000 attached files per minute per + * organization. + * + * Please [contact us](https://help.openai.com/) if you need to increase these + * storage limits. + */ + readonly "createFile": { + ( + options: { readonly payload: typeof CreateFileRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateFile400", CreateFile400> + | OpenAiClientError<"CreateFile429", CreateFile429> + | OpenAiClientError<"CreateFile500", CreateFile500> + > + ( + options: { readonly payload: typeof CreateFileRequestFormData.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateFile400", CreateFile400> + | OpenAiClientError<"CreateFile429", CreateFile429> + | OpenAiClientError<"CreateFile500", CreateFile500> + > + } + /** + * Returns information about a specific file. + */ + readonly "retrieveFile": { + ( + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveFile404", RetrieveFile404> + | OpenAiClientError<"RetrieveFile429", RetrieveFile429> + > + ( + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveFile404", RetrieveFile404> + | OpenAiClientError<"RetrieveFile429", RetrieveFile429> + > + } + /** + * Delete a file and remove it from all vector stores. + */ + readonly "deleteFile": { + ( + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteFile404", DeleteFile404> + | OpenAiClientError<"DeleteFile429", DeleteFile429> + > + ( + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteFile404", DeleteFile404> + | OpenAiClientError<"DeleteFile429", DeleteFile429> + > + } + /** + * Returns a response containing the contents of the specified file. + */ + readonly "downloadFile": { + ( + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DownloadFile400", DownloadFile400> + | OpenAiClientError<"DownloadFile404", DownloadFile404> + | OpenAiClientError<"DownloadFile429", DownloadFile429> + | OpenAiClientError<"DownloadFile500", DownloadFile500> + > + ( + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DownloadFile400", DownloadFile400> + | OpenAiClientError<"DownloadFile404", DownloadFile404> + | OpenAiClientError<"DownloadFile429", DownloadFile429> + | OpenAiClientError<"DownloadFile500", DownloadFile500> + > + } + /** + * Returns a response containing the contents of the specified file. + */ + readonly "downloadFileStream": (fileId: string) => Stream.Stream + /** + * Run a grader. + */ + readonly "runGrader": { + ( + options: { readonly payload: typeof RunGraderRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RunGrader400", RunGrader400> + | OpenAiClientError<"RunGrader429", RunGrader429> + > + ( + options: { readonly payload: typeof RunGraderRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RunGrader400", RunGrader400> + | OpenAiClientError<"RunGrader429", RunGrader429> + > + } + /** + * Validate a grader. + */ + readonly "validateGrader": { + ( + options: { readonly payload: typeof ValidateGraderRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ValidateGrader400", ValidateGrader400> + | OpenAiClientError<"ValidateGrader429", ValidateGrader429> + > + ( + options: { readonly payload: typeof ValidateGraderRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ValidateGrader400", ValidateGrader400> + | OpenAiClientError<"ValidateGrader429", ValidateGrader429> + > + } + /** + * **NOTE:** This endpoint requires an [admin API key](https://developers.openai.com/api/reference/resources/admin/subresources/organization/subresources/admin_api_keys). + * + * Organization owners can use this endpoint to view all permissions for a fine-tuned model checkpoint. + */ + readonly "listFineTuningCheckpointPermissions": { + ( + fineTunedModelCheckpoint: string, + options: { + readonly params?: typeof ListFineTuningCheckpointPermissionsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFineTuningCheckpointPermissions400", ListFineTuningCheckpointPermissions400> + | OpenAiClientError<"ListFineTuningCheckpointPermissions429", ListFineTuningCheckpointPermissions429> + > + ( + fineTunedModelCheckpoint: string, + options: { + readonly params?: typeof ListFineTuningCheckpointPermissionsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFineTuningCheckpointPermissions400", ListFineTuningCheckpointPermissions400> + | OpenAiClientError<"ListFineTuningCheckpointPermissions429", ListFineTuningCheckpointPermissions429> + > + } + /** + * **NOTE:** Calling this endpoint requires an [admin API key](https://developers.openai.com/api/reference/resources/admin/subresources/organization/subresources/admin_api_keys). + * + * This enables organization owners to share fine-tuned models with other projects in their organization. + */ + readonly "createFineTuningCheckpointPermission": { + ( + fineTunedModelCheckpoint: string, + options: { + readonly payload: typeof CreateFineTuningCheckpointPermissionRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateFineTuningCheckpointPermission400", CreateFineTuningCheckpointPermission400> + | OpenAiClientError<"CreateFineTuningCheckpointPermission404", CreateFineTuningCheckpointPermission404> + | OpenAiClientError<"CreateFineTuningCheckpointPermission429", CreateFineTuningCheckpointPermission429> + > + ( + fineTunedModelCheckpoint: string, + options: { + readonly payload: typeof CreateFineTuningCheckpointPermissionRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateFineTuningCheckpointPermission400", CreateFineTuningCheckpointPermission400> + | OpenAiClientError<"CreateFineTuningCheckpointPermission404", CreateFineTuningCheckpointPermission404> + | OpenAiClientError<"CreateFineTuningCheckpointPermission429", CreateFineTuningCheckpointPermission429> + > + } + /** + * **NOTE:** This endpoint requires an [admin API key](https://developers.openai.com/api/reference/resources/admin/subresources/organization/subresources/admin_api_keys). + * + * Organization owners can use this endpoint to delete a permission for a fine-tuned model checkpoint. + */ + readonly "deleteFineTuningCheckpointPermission": { + ( + fineTunedModelCheckpoint: string, + permissionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteFineTuningCheckpointPermission400", DeleteFineTuningCheckpointPermission400> + | OpenAiClientError<"DeleteFineTuningCheckpointPermission404", DeleteFineTuningCheckpointPermission404> + | OpenAiClientError<"DeleteFineTuningCheckpointPermission429", DeleteFineTuningCheckpointPermission429> + > + ( + fineTunedModelCheckpoint: string, + permissionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteFineTuningCheckpointPermission400", DeleteFineTuningCheckpointPermission400> + | OpenAiClientError<"DeleteFineTuningCheckpointPermission404", DeleteFineTuningCheckpointPermission404> + | OpenAiClientError<"DeleteFineTuningCheckpointPermission429", DeleteFineTuningCheckpointPermission429> + > + } + /** + * List your organization's fine-tuning jobs + */ + readonly "listPaginatedFineTuningJobs": { + ( + options: { + readonly params?: typeof ListPaginatedFineTuningJobsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListPaginatedFineTuningJobs400", ListPaginatedFineTuningJobs400> + | OpenAiClientError<"ListPaginatedFineTuningJobs429", ListPaginatedFineTuningJobs429> + > + ( + options: { + readonly params?: typeof ListPaginatedFineTuningJobsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListPaginatedFineTuningJobs400", ListPaginatedFineTuningJobs400> + | OpenAiClientError<"ListPaginatedFineTuningJobs429", ListPaginatedFineTuningJobs429> + > + } + /** + * Creates a fine-tuning job which begins the process of creating a new model from a given dataset. + * + * Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + * + * [Learn more about fine-tuning](https://developers.openai.com/api/docs/guides/model-optimization) + */ + readonly "createFineTuningJob": { + ( + options: { readonly payload: typeof CreateFineTuningJobRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateFineTuningJob400", CreateFineTuningJob400> + | OpenAiClientError<"CreateFineTuningJob429", CreateFineTuningJob429> + > + ( + options: { readonly payload: typeof CreateFineTuningJobRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateFineTuningJob400", CreateFineTuningJob400> + | OpenAiClientError<"CreateFineTuningJob429", CreateFineTuningJob429> + > + } + /** + * Get info about a fine-tuning job. + * + * [Learn more about fine-tuning](https://developers.openai.com/api/docs/guides/model-optimization) + */ + readonly "retrieveFineTuningJob": { + ( + fineTuningJobId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveFineTuningJob404", RetrieveFineTuningJob404> + | OpenAiClientError<"RetrieveFineTuningJob429", RetrieveFineTuningJob429> + > + ( + fineTuningJobId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveFineTuningJob404", RetrieveFineTuningJob404> + | OpenAiClientError<"RetrieveFineTuningJob429", RetrieveFineTuningJob429> + > + } + /** + * Immediately cancel a fine-tune job. + */ + readonly "cancelFineTuningJob": { + ( + fineTuningJobId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelFineTuningJob400", CancelFineTuningJob400> + | OpenAiClientError<"CancelFineTuningJob404", CancelFineTuningJob404> + | OpenAiClientError<"CancelFineTuningJob429", CancelFineTuningJob429> + > + ( + fineTuningJobId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelFineTuningJob400", CancelFineTuningJob400> + | OpenAiClientError<"CancelFineTuningJob404", CancelFineTuningJob404> + | OpenAiClientError<"CancelFineTuningJob429", CancelFineTuningJob429> + > + } + /** + * List checkpoints for a fine-tuning job. + */ + readonly "listFineTuningJobCheckpoints": { + ( + fineTuningJobId: string, + options: { + readonly params?: typeof ListFineTuningJobCheckpointsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFineTuningJobCheckpoints400", ListFineTuningJobCheckpoints400> + | OpenAiClientError<"ListFineTuningJobCheckpoints404", ListFineTuningJobCheckpoints404> + | OpenAiClientError<"ListFineTuningJobCheckpoints429", ListFineTuningJobCheckpoints429> + > + ( + fineTuningJobId: string, + options: { + readonly params?: typeof ListFineTuningJobCheckpointsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFineTuningJobCheckpoints400", ListFineTuningJobCheckpoints400> + | OpenAiClientError<"ListFineTuningJobCheckpoints404", ListFineTuningJobCheckpoints404> + | OpenAiClientError<"ListFineTuningJobCheckpoints429", ListFineTuningJobCheckpoints429> + > + } + /** + * Get status updates for a fine-tuning job. + */ + readonly "listFineTuningEvents": { + ( + fineTuningJobId: string, + options: { readonly params?: typeof ListFineTuningEventsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFineTuningEvents400", ListFineTuningEvents400> + | OpenAiClientError<"ListFineTuningEvents404", ListFineTuningEvents404> + | OpenAiClientError<"ListFineTuningEvents429", ListFineTuningEvents429> + > + ( + fineTuningJobId: string, + options: { + readonly params?: typeof ListFineTuningEventsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFineTuningEvents400", ListFineTuningEvents400> + | OpenAiClientError<"ListFineTuningEvents404", ListFineTuningEvents404> + | OpenAiClientError<"ListFineTuningEvents429", ListFineTuningEvents429> + > + } + /** + * Pause a fine-tune job. + */ + readonly "pauseFineTuningJob": { + ( + fineTuningJobId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"PauseFineTuningJob400", PauseFineTuningJob400> + | OpenAiClientError<"PauseFineTuningJob404", PauseFineTuningJob404> + | OpenAiClientError<"PauseFineTuningJob429", PauseFineTuningJob429> + > + ( + fineTuningJobId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"PauseFineTuningJob400", PauseFineTuningJob400> + | OpenAiClientError<"PauseFineTuningJob404", PauseFineTuningJob404> + | OpenAiClientError<"PauseFineTuningJob429", PauseFineTuningJob429> + > + } + /** + * Resume a fine-tune job. + */ + readonly "resumeFineTuningJob": { + ( + fineTuningJobId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ResumeFineTuningJob400", ResumeFineTuningJob400> + | OpenAiClientError<"ResumeFineTuningJob404", ResumeFineTuningJob404> + | OpenAiClientError<"ResumeFineTuningJob429", ResumeFineTuningJob429> + > + ( + fineTuningJobId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ResumeFineTuningJob400", ResumeFineTuningJob400> + | OpenAiClientError<"ResumeFineTuningJob404", ResumeFineTuningJob404> + | OpenAiClientError<"ResumeFineTuningJob429", ResumeFineTuningJob429> + > + } + /** + * Creates an edited or extended image given one or more source images and a prompt. This endpoint supports GPT Image models. + */ + readonly "createImageEdit": { + ( + options: { readonly payload: typeof CreateImageEditRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateImageEdit400", CreateImageEdit400> + | OpenAiClientError<"CreateImageEdit403", CreateImageEdit403> + | OpenAiClientError<"CreateImageEdit410", CreateImageEdit410> + | OpenAiClientError<"CreateImageEdit429", CreateImageEdit429> + | OpenAiClientError<"CreateImageEdit500", CreateImageEdit500> + | OpenAiClientError<"CreateImageEdit503", CreateImageEdit503> + > + ( + options: { readonly payload: typeof CreateImageEditRequestFormData.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateImageEdit400", CreateImageEdit400> + | OpenAiClientError<"CreateImageEdit403", CreateImageEdit403> + | OpenAiClientError<"CreateImageEdit410", CreateImageEdit410> + | OpenAiClientError<"CreateImageEdit429", CreateImageEdit429> + | OpenAiClientError<"CreateImageEdit500", CreateImageEdit500> + | OpenAiClientError<"CreateImageEdit503", CreateImageEdit503> + > + } + /** + * Creates an edited or extended image given one or more source images and a prompt. This endpoint supports GPT Image models. + */ + readonly "createImageEditSse": ( + options: { readonly payload: typeof CreateImageEditRequestFormData.Encoded } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: CreateImageEdit200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof CreateImageEdit200Sse.DecodingServices + > + /** + * Creates an image given a prompt using a GPT Image model. [Learn more](https://developers.openai.com/api/docs/guides/images-vision). + */ + readonly "createImage": { + ( + options: { readonly payload: typeof CreateImageRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateImage400", CreateImage400> + | OpenAiClientError<"CreateImage403", CreateImage403> + | OpenAiClientError<"CreateImage410", CreateImage410> + | OpenAiClientError<"CreateImage429", CreateImage429> + | OpenAiClientError<"CreateImage500", CreateImage500> + | OpenAiClientError<"CreateImage503", CreateImage503> + > + ( + options: { readonly payload: typeof CreateImageRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateImage400", CreateImage400> + | OpenAiClientError<"CreateImage403", CreateImage403> + | OpenAiClientError<"CreateImage410", CreateImage410> + | OpenAiClientError<"CreateImage429", CreateImage429> + | OpenAiClientError<"CreateImage500", CreateImage500> + | OpenAiClientError<"CreateImage503", CreateImage503> + > + } + /** + * Creates an image given a prompt using a GPT Image model. [Learn more](https://developers.openai.com/api/docs/guides/images-vision). + */ + readonly "createImageSse": ( + options: { readonly payload: typeof CreateImageRequestJson.Encoded } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: CreateImage200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof CreateImage200Sse.DecodingServices + > + /** + * This endpoint is retired and no longer available. Use the image edits endpoint with a GPT Image model and a prompt to create a variation of an image. The request and response schemas below describe the legacy contract. + */ + readonly "createImageVariation": { + ( + options: { readonly payload: typeof CreateImageVariationRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateImageVariation400", CreateImageVariation400> + | OpenAiClientError<"CreateImageVariation403", CreateImageVariation403> + | OpenAiClientError<"CreateImageVariation410", CreateImageVariation410> + | OpenAiClientError<"CreateImageVariation429", CreateImageVariation429> + | OpenAiClientError<"CreateImageVariation500", CreateImageVariation500> + > + ( + options: { + readonly payload: typeof CreateImageVariationRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateImageVariation400", CreateImageVariation400> + | OpenAiClientError<"CreateImageVariation403", CreateImageVariation403> + | OpenAiClientError<"CreateImageVariation410", CreateImageVariation410> + | OpenAiClientError<"CreateImageVariation429", CreateImageVariation429> + | OpenAiClientError<"CreateImageVariation500", CreateImageVariation500> + > + } + /** + * Create a Live WebRTC session or place an outbound SIP call. Start with the + * [Live prompting guide](https://developers.openai.com/api/docs/guides/live-prompting) for session configuration + * and [Telephony and SIP](https://developers.openai.com/api/docs/guides/voice-sip?api=live#place-an-outbound-call) + * for trunk setup and call monitoring. + * + * Set transport.type to `webrtc` and supply an SDP offer, or set it to `sip` + * and supply an E.164 destination and trunk credentials. Outbound SIP calling + * must be enabled for your organization. + * Ringing is limited to 3 minutes and connected calls to 2 hours; these limits + * are not configurable in the request. + * + * Returns `201 Created` after session initialization. WebRTC responses include an + * SDP answer. SIP responses do not wait for the callee to answer. Attach a + * sideband connection using session.id to monitor SIP call progress. + * + * Each SIP request creates a new call. If a request times out or the connection + * fails, retry with caution: the original request may have succeeded, and a + * retry can place another call. + */ + readonly "createLive": { + ( + options: { readonly payload: typeof CreateLiveRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateLive400", CreateLive400> + | OpenAiClientError<"CreateLive413", CreateLive413> + | OpenAiClientError<"CreateLive429", CreateLive429> + | OpenAiClientError<"CreateLive503", CreateLive503> + | OpenAiClientError<"CreateLive504", CreateLive504> + > + ( + options: { readonly payload: typeof CreateLiveRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateLive400", CreateLive400> + | OpenAiClientError<"CreateLive413", CreateLive413> + | OpenAiClientError<"CreateLive429", CreateLive429> + | OpenAiClientError<"CreateLive503", CreateLive503> + | OpenAiClientError<"CreateLive504", CreateLive504> + > + } + /** + * Accept an incoming SIP call. Supply session with type live, the model, and startup configuration. Before accepting calls, follow the [Live prompting guide](https://developers.openai.com/api/docs/guides/live-prompting) to write frontend conversation instructions and a separate backend prompt. SIP media format is negotiated; omit audio.format. + */ + readonly "acceptLiveSession": { + ( + sessionId: string, + options: { readonly payload: typeof AcceptLiveSessionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AcceptLiveSession400", AcceptLiveSession400> + | OpenAiClientError<"AcceptLiveSession404", AcceptLiveSession404> + | OpenAiClientError<"AcceptLiveSession409", AcceptLiveSession409> + | OpenAiClientError<"AcceptLiveSession429", AcceptLiveSession429> + | OpenAiClientError<"AcceptLiveSession503", AcceptLiveSession503> + > + ( + sessionId: string, + options: { readonly payload: typeof AcceptLiveSessionRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AcceptLiveSession400", AcceptLiveSession400> + | OpenAiClientError<"AcceptLiveSession404", AcceptLiveSession404> + | OpenAiClientError<"AcceptLiveSession409", AcceptLiveSession409> + | OpenAiClientError<"AcceptLiveSession429", AcceptLiveSession429> + | OpenAiClientError<"AcceptLiveSession503", AcceptLiveSession503> + > + } + /** + * Fork a stored Live session onto a new WebRTC connection. + */ + readonly "forkLiveSession": { + ( + sessionId: string, + options: { readonly payload: typeof ForkLiveSessionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ForkLiveSession400", ForkLiveSession400> + | OpenAiClientError<"ForkLiveSession413", ForkLiveSession413> + | OpenAiClientError<"ForkLiveSession429", ForkLiveSession429> + | OpenAiClientError<"ForkLiveSession503", ForkLiveSession503> + > + ( + sessionId: string, + options: { readonly payload: typeof ForkLiveSessionRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ForkLiveSession400", ForkLiveSession400> + | OpenAiClientError<"ForkLiveSession413", ForkLiveSession413> + | OpenAiClientError<"ForkLiveSession429", ForkLiveSession429> + | OpenAiClientError<"ForkLiveSession503", ForkLiveSession503> + > + } + /** + * End a SIP call identified by session_id. + */ + readonly "hangupLiveSession": { + ( + sessionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"HangupLiveSession404", HangupLiveSession404> + > + ( + sessionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"HangupLiveSession404", HangupLiveSession404> + > + } + /** + * Transfer a SIP call to another destination. Supply a nonblank target_uri for the SIP Refer-To header. + */ + readonly "referLiveSession": { + ( + sessionId: string, + options: { readonly payload: typeof ReferLiveSessionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ReferLiveSession400", ReferLiveSession400> + | OpenAiClientError<"ReferLiveSession404", ReferLiveSession404> + > + ( + sessionId: string, + options: { readonly payload: typeof ReferLiveSessionRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ReferLiveSession400", ReferLiveSession400> + | OpenAiClientError<"ReferLiveSession404", ReferLiveSession404> + > + } + /** + * Reject an incoming SIP call. Send a required SIP rejection status_code between 300 and 699. + */ + readonly "rejectLiveSession": { + ( + sessionId: string, + options: { readonly payload: typeof RejectLiveSessionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RejectLiveSession400", RejectLiveSession400> + | OpenAiClientError<"RejectLiveSession404", RejectLiveSession404> + | OpenAiClientError<"RejectLiveSession409", RejectLiveSession409> + > + ( + sessionId: string, + options: { readonly payload: typeof RejectLiveSessionRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RejectLiveSession400", RejectLiveSession400> + | OpenAiClientError<"RejectLiveSession404", RejectLiveSession404> + | OpenAiClientError<"RejectLiveSession409", RejectLiveSession409> + > + } + /** + * Lists the currently available models, and provides basic information about each one such as the owner and availability. + */ + readonly "listModels": { + ( + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListModels403", ListModels403> + > + ( + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListModels403", ListModels403> + > + } + /** + * Retrieves a model instance, providing basic information about the model such as the owner and permissioning. + */ + readonly "retrieveModel": { + ( + model: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveModel403", RetrieveModel403> + | OpenAiClientError<"RetrieveModel404", RetrieveModel404> + > + ( + model: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveModel403", RetrieveModel403> + | OpenAiClientError<"RetrieveModel404", RetrieveModel404> + > + } + /** + * Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. + */ + readonly "deleteModel": { + ( + model: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteModel403", DeleteModel403> + | OpenAiClientError<"DeleteModel404", DeleteModel404> + > + ( + model: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteModel403", DeleteModel403> + | OpenAiClientError<"DeleteModel404", DeleteModel404> + > + } + /** + * Classifies if text and/or image inputs are potentially harmful. Learn + * more in the [moderation guide](https://developers.openai.com/api/docs/guides/moderation). + */ + readonly "createModeration": { + ( + options: { readonly payload: typeof CreateModerationRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateModeration400", CreateModeration400> + | OpenAiClientError<"CreateModeration403", CreateModeration403> + | OpenAiClientError<"CreateModeration429", CreateModeration429> + | OpenAiClientError<"CreateModeration500", CreateModeration500> + | OpenAiClientError<"CreateModeration503", CreateModeration503> + > + ( + options: { readonly payload: typeof CreateModerationRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateModeration400", CreateModeration400> + | OpenAiClientError<"CreateModeration403", CreateModeration403> + | OpenAiClientError<"CreateModeration429", CreateModeration429> + | OpenAiClientError<"CreateModeration500", CreateModeration500> + | OpenAiClientError<"CreateModeration503", CreateModeration503> + > + } + /** + * List organization API keys + */ + readonly "adminApiKeysList": { + ( + options: { readonly params?: typeof AdminApiKeysListParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AdminApiKeysList400", AdminApiKeysList400> + | OpenAiClientError<"AdminApiKeysList403", AdminApiKeysList403> + > + ( + options: { + readonly params?: typeof AdminApiKeysListParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AdminApiKeysList400", AdminApiKeysList400> + | OpenAiClientError<"AdminApiKeysList403", AdminApiKeysList403> + > + } + /** + * Create an organization admin API key + */ + readonly "adminApiKeysCreate": { + ( + options: { readonly payload: typeof AdminApiKeysCreateRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AdminApiKeysCreate400", AdminApiKeysCreate400> + | OpenAiClientError<"AdminApiKeysCreate403", AdminApiKeysCreate403> + | OpenAiClientError<"AdminApiKeysCreate404", AdminApiKeysCreate404> + > + ( + options: { readonly payload: typeof AdminApiKeysCreateRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AdminApiKeysCreate400", AdminApiKeysCreate400> + | OpenAiClientError<"AdminApiKeysCreate403", AdminApiKeysCreate403> + | OpenAiClientError<"AdminApiKeysCreate404", AdminApiKeysCreate404> + > + } + /** + * Retrieve a single organization API key + */ + readonly "adminApiKeysGet": { + ( + keyId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AdminApiKeysGet403", AdminApiKeysGet403> + | OpenAiClientError<"AdminApiKeysGet404", AdminApiKeysGet404> + > + ( + keyId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AdminApiKeysGet403", AdminApiKeysGet403> + | OpenAiClientError<"AdminApiKeysGet404", AdminApiKeysGet404> + > + } + /** + * Delete an organization admin API key + */ + readonly "adminApiKeysDelete": { + ( + keyId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AdminApiKeysDelete403", AdminApiKeysDelete403> + | OpenAiClientError<"AdminApiKeysDelete404", AdminApiKeysDelete404> + > + ( + keyId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AdminApiKeysDelete403", AdminApiKeysDelete403> + | OpenAiClientError<"AdminApiKeysDelete404", AdminApiKeysDelete404> + > + } + /** + * List user actions and configuration changes within this organization. + */ + readonly "listAuditLogs": { + ( + options: { readonly params?: typeof ListAuditLogsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAuditLogs400", ListAuditLogs400> + | OpenAiClientError<"ListAuditLogs404", ListAuditLogs404> + | OpenAiClientError<"ListAuditLogs429", ListAuditLogs429> + > + ( + options: { + readonly params?: typeof ListAuditLogsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAuditLogs400", ListAuditLogs400> + | OpenAiClientError<"ListAuditLogs404", ListAuditLogs404> + | OpenAiClientError<"ListAuditLogs429", ListAuditLogs429> + > + } + /** + * List uploaded certificates for this organization. + */ + readonly "listOrganizationCertificates": { + ( + options: { + readonly params?: typeof ListOrganizationCertificatesParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListOrganizationCertificates400", ListOrganizationCertificates400> + | OpenAiClientError<"ListOrganizationCertificates403", ListOrganizationCertificates403> + | OpenAiClientError<"ListOrganizationCertificates429", ListOrganizationCertificates429> + > + ( + options: { + readonly params?: typeof ListOrganizationCertificatesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListOrganizationCertificates400", ListOrganizationCertificates400> + | OpenAiClientError<"ListOrganizationCertificates403", ListOrganizationCertificates403> + | OpenAiClientError<"ListOrganizationCertificates429", ListOrganizationCertificates429> + > + } + /** + * Upload a certificate to the organization. This does **not** automatically activate the certificate. + * + * Organizations can upload up to 50 certificates. + */ + readonly "uploadCertificate": { + ( + options: { readonly payload: typeof UploadCertificateRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UploadCertificate400", UploadCertificate400> + | OpenAiClientError<"UploadCertificate403", UploadCertificate403> + | OpenAiClientError<"UploadCertificate429", UploadCertificate429> + > + ( + options: { readonly payload: typeof UploadCertificateRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UploadCertificate400", UploadCertificate400> + | OpenAiClientError<"UploadCertificate403", UploadCertificate403> + | OpenAiClientError<"UploadCertificate429", UploadCertificate429> + > + } + /** + * Activate certificates at the organization level. + * + * You can atomically and idempotently activate up to 10 certificates at a time. + */ + readonly "activateOrganizationCertificates": { + ( + options: { readonly payload: typeof ActivateOrganizationCertificatesRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ActivateOrganizationCertificates400", ActivateOrganizationCertificates400> + | OpenAiClientError<"ActivateOrganizationCertificates403", ActivateOrganizationCertificates403> + | OpenAiClientError<"ActivateOrganizationCertificates404", ActivateOrganizationCertificates404> + | OpenAiClientError<"ActivateOrganizationCertificates429", ActivateOrganizationCertificates429> + | OpenAiClientError<"ActivateOrganizationCertificates500", ActivateOrganizationCertificates500> + > + ( + options: { + readonly payload: typeof ActivateOrganizationCertificatesRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ActivateOrganizationCertificates400", ActivateOrganizationCertificates400> + | OpenAiClientError<"ActivateOrganizationCertificates403", ActivateOrganizationCertificates403> + | OpenAiClientError<"ActivateOrganizationCertificates404", ActivateOrganizationCertificates404> + | OpenAiClientError<"ActivateOrganizationCertificates429", ActivateOrganizationCertificates429> + | OpenAiClientError<"ActivateOrganizationCertificates500", ActivateOrganizationCertificates500> + > + } + /** + * Deactivate certificates at the organization level. + * + * You can atomically and idempotently deactivate up to 10 certificates at a time. + */ + readonly "deactivateOrganizationCertificates": { + ( + options: { + readonly payload: typeof DeactivateOrganizationCertificatesRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeactivateOrganizationCertificates400", DeactivateOrganizationCertificates400> + | OpenAiClientError<"DeactivateOrganizationCertificates403", DeactivateOrganizationCertificates403> + | OpenAiClientError<"DeactivateOrganizationCertificates404", DeactivateOrganizationCertificates404> + | OpenAiClientError<"DeactivateOrganizationCertificates429", DeactivateOrganizationCertificates429> + | OpenAiClientError<"DeactivateOrganizationCertificates500", DeactivateOrganizationCertificates500> + > + ( + options: { + readonly payload: typeof DeactivateOrganizationCertificatesRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeactivateOrganizationCertificates400", DeactivateOrganizationCertificates400> + | OpenAiClientError<"DeactivateOrganizationCertificates403", DeactivateOrganizationCertificates403> + | OpenAiClientError<"DeactivateOrganizationCertificates404", DeactivateOrganizationCertificates404> + | OpenAiClientError<"DeactivateOrganizationCertificates429", DeactivateOrganizationCertificates429> + | OpenAiClientError<"DeactivateOrganizationCertificates500", DeactivateOrganizationCertificates500> + > + } + /** + * Get a certificate that has been uploaded to the organization. + * + * You can get a certificate regardless of whether it is active or not. + */ + readonly "getCertificate": { + ( + certificateId: string, + options: { readonly params?: typeof GetCertificateParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetCertificate400", GetCertificate400> + | OpenAiClientError<"GetCertificate403", GetCertificate403> + | OpenAiClientError<"GetCertificate404", GetCertificate404> + | OpenAiClientError<"GetCertificate429", GetCertificate429> + > + ( + certificateId: string, + options: { + readonly params?: typeof GetCertificateParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetCertificate400", GetCertificate400> + | OpenAiClientError<"GetCertificate403", GetCertificate403> + | OpenAiClientError<"GetCertificate404", GetCertificate404> + | OpenAiClientError<"GetCertificate429", GetCertificate429> + > + } + /** + * Modify a certificate. Note that only the name can be modified. + */ + readonly "modifyCertificate": { + ( + certificateId: string, + options: { readonly payload: typeof ModifyCertificateRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyCertificate400", ModifyCertificate400> + | OpenAiClientError<"ModifyCertificate403", ModifyCertificate403> + | OpenAiClientError<"ModifyCertificate404", ModifyCertificate404> + | OpenAiClientError<"ModifyCertificate429", ModifyCertificate429> + | OpenAiClientError<"ModifyCertificate500", ModifyCertificate500> + > + ( + certificateId: string, + options: { readonly payload: typeof ModifyCertificateRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyCertificate400", ModifyCertificate400> + | OpenAiClientError<"ModifyCertificate403", ModifyCertificate403> + | OpenAiClientError<"ModifyCertificate404", ModifyCertificate404> + | OpenAiClientError<"ModifyCertificate429", ModifyCertificate429> + | OpenAiClientError<"ModifyCertificate500", ModifyCertificate500> + > + } + /** + * Delete a certificate from the organization. + * + * The certificate must be inactive for the organization and all projects. + */ + readonly "deleteCertificate": { + ( + certificateId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteCertificate400", DeleteCertificate400> + | OpenAiClientError<"DeleteCertificate403", DeleteCertificate403> + | OpenAiClientError<"DeleteCertificate404", DeleteCertificate404> + | OpenAiClientError<"DeleteCertificate429", DeleteCertificate429> + > + ( + certificateId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteCertificate400", DeleteCertificate400> + | OpenAiClientError<"DeleteCertificate403", DeleteCertificate403> + | OpenAiClientError<"DeleteCertificate404", DeleteCertificate404> + | OpenAiClientError<"DeleteCertificate429", DeleteCertificate429> + > + } + /** + * Get costs details for the organization. + */ + readonly "usageCosts": { + ( + options: { readonly params: typeof UsageCostsParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageCosts400", UsageCosts400> + | OpenAiClientError<"UsageCosts403", UsageCosts403> + | OpenAiClientError<"UsageCosts429", UsageCosts429> + > + ( + options: { readonly params: typeof UsageCostsParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageCosts400", UsageCosts400> + | OpenAiClientError<"UsageCosts403", UsageCosts403> + | OpenAiClientError<"UsageCosts429", UsageCosts429> + > + } /** - * Returns a list of assistants. + * Retrieves organization data retention controls. */ - readonly "listAssistants": ( - options: - | { readonly params?: typeof ListAssistantsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveOrganizationDataRetention": { + ( + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveOrganizationDataRetention403", RetrieveOrganizationDataRetention403> + | OpenAiClientError<"RetrieveOrganizationDataRetention404", RetrieveOrganizationDataRetention404> + > + ( + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveOrganizationDataRetention403", RetrieveOrganizationDataRetention403> + | OpenAiClientError<"RetrieveOrganizationDataRetention404", RetrieveOrganizationDataRetention404> + > + } /** - * Create an assistant with a model and instructions. + * Updates organization data retention controls. */ - readonly "createAssistant": ( - options: { readonly payload: typeof CreateAssistantRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateOrganizationDataRetention": { + ( + options: { readonly payload: typeof UpdateOrganizationDataRetentionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateOrganizationDataRetention400", UpdateOrganizationDataRetention400> + | OpenAiClientError<"UpdateOrganizationDataRetention403", UpdateOrganizationDataRetention403> + | OpenAiClientError<"UpdateOrganizationDataRetention404", UpdateOrganizationDataRetention404> + > + ( + options: { + readonly payload: typeof UpdateOrganizationDataRetentionRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateOrganizationDataRetention400", UpdateOrganizationDataRetention400> + | OpenAiClientError<"UpdateOrganizationDataRetention403", UpdateOrganizationDataRetention403> + | OpenAiClientError<"UpdateOrganizationDataRetention404", UpdateOrganizationDataRetention404> + > + } /** - * Retrieves an assistant. + * Lists all groups in the organization. */ - readonly "getAssistant": ( - assistantId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listGroups": { + ( + options: { readonly params?: typeof ListGroupsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListGroups400", ListGroups400> + | OpenAiClientError<"ListGroups403", ListGroups403> + | OpenAiClientError<"ListGroups404", ListGroups404> + | OpenAiClientError<"ListGroups429", ListGroups429> + > + ( + options: + | { readonly params?: typeof ListGroupsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListGroups400", ListGroups400> + | OpenAiClientError<"ListGroups403", ListGroups403> + | OpenAiClientError<"ListGroups404", ListGroups404> + | OpenAiClientError<"ListGroups429", ListGroups429> + > + } /** - * Modifies an assistant. + * Creates a new group in the organization. */ - readonly "modifyAssistant": ( - assistantId: string, - options: { readonly payload: typeof ModifyAssistantRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createGroup": { + ( + options: { readonly payload: typeof CreateGroupRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateGroup400", CreateGroup400> + | OpenAiClientError<"CreateGroup403", CreateGroup403> + | OpenAiClientError<"CreateGroup404", CreateGroup404> + | OpenAiClientError<"CreateGroup422", CreateGroup422> + | OpenAiClientError<"CreateGroup429", CreateGroup429> + | OpenAiClientError<"CreateGroup500", CreateGroup500> + > + ( + options: { readonly payload: typeof CreateGroupRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateGroup400", CreateGroup400> + | OpenAiClientError<"CreateGroup403", CreateGroup403> + | OpenAiClientError<"CreateGroup404", CreateGroup404> + | OpenAiClientError<"CreateGroup422", CreateGroup422> + | OpenAiClientError<"CreateGroup429", CreateGroup429> + | OpenAiClientError<"CreateGroup500", CreateGroup500> + > + } /** - * Delete an assistant. + * Retrieves a group. */ - readonly "deleteAssistant": ( - assistantId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveGroup": { + ( + groupId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveGroup400", RetrieveGroup400> + | OpenAiClientError<"RetrieveGroup403", RetrieveGroup403> + | OpenAiClientError<"RetrieveGroup404", RetrieveGroup404> + | OpenAiClientError<"RetrieveGroup429", RetrieveGroup429> + | OpenAiClientError<"RetrieveGroup500", RetrieveGroup500> + > + ( + groupId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveGroup400", RetrieveGroup400> + | OpenAiClientError<"RetrieveGroup403", RetrieveGroup403> + | OpenAiClientError<"RetrieveGroup404", RetrieveGroup404> + | OpenAiClientError<"RetrieveGroup429", RetrieveGroup429> + | OpenAiClientError<"RetrieveGroup500", RetrieveGroup500> + > + } /** - * Generates audio from the input text. + * Updates a group's information. + */ + readonly "updateGroup": { + ( + groupId: string, + options: { readonly payload: typeof UpdateGroupRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateGroup400", UpdateGroup400> + | OpenAiClientError<"UpdateGroup403", UpdateGroup403> + | OpenAiClientError<"UpdateGroup404", UpdateGroup404> + | OpenAiClientError<"UpdateGroup429", UpdateGroup429> + | OpenAiClientError<"UpdateGroup500", UpdateGroup500> + > + ( + groupId: string, + options: { readonly payload: typeof UpdateGroupRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateGroup400", UpdateGroup400> + | OpenAiClientError<"UpdateGroup403", UpdateGroup403> + | OpenAiClientError<"UpdateGroup404", UpdateGroup404> + | OpenAiClientError<"UpdateGroup429", UpdateGroup429> + | OpenAiClientError<"UpdateGroup500", UpdateGroup500> + > + } + /** + * Deletes a group from the organization. + */ + readonly "deleteGroup": { + ( + groupId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteGroup400", DeleteGroup400> + | OpenAiClientError<"DeleteGroup403", DeleteGroup403> + | OpenAiClientError<"DeleteGroup404", DeleteGroup404> + | OpenAiClientError<"DeleteGroup429", DeleteGroup429> + > + ( + groupId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteGroup400", DeleteGroup400> + | OpenAiClientError<"DeleteGroup403", DeleteGroup403> + | OpenAiClientError<"DeleteGroup404", DeleteGroup404> + | OpenAiClientError<"DeleteGroup429", DeleteGroup429> + > + } + /** + * Lists the organization roles assigned to a group within the organization. + */ + readonly "listGroupRoleAssignments": { + ( + groupId: string, + options: { readonly params?: typeof ListGroupRoleAssignmentsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListGroupRoleAssignments400", ListGroupRoleAssignments400> + | OpenAiClientError<"ListGroupRoleAssignments403", ListGroupRoleAssignments403> + | OpenAiClientError<"ListGroupRoleAssignments404", ListGroupRoleAssignments404> + | OpenAiClientError<"ListGroupRoleAssignments429", ListGroupRoleAssignments429> + > + ( + groupId: string, + options: { + readonly params?: typeof ListGroupRoleAssignmentsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListGroupRoleAssignments400", ListGroupRoleAssignments400> + | OpenAiClientError<"ListGroupRoleAssignments403", ListGroupRoleAssignments403> + | OpenAiClientError<"ListGroupRoleAssignments404", ListGroupRoleAssignments404> + | OpenAiClientError<"ListGroupRoleAssignments429", ListGroupRoleAssignments429> + > + } + /** + * Assigns an organization role to a group within the organization. + */ + readonly "assignGroupRole": { + ( + groupId: string, + options: { readonly payload: typeof AssignGroupRoleRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AssignGroupRole400", AssignGroupRole400> + | OpenAiClientError<"AssignGroupRole403", AssignGroupRole403> + | OpenAiClientError<"AssignGroupRole404", AssignGroupRole404> + | OpenAiClientError<"AssignGroupRole429", AssignGroupRole429> + > + ( + groupId: string, + options: { readonly payload: typeof AssignGroupRoleRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AssignGroupRole400", AssignGroupRole400> + | OpenAiClientError<"AssignGroupRole403", AssignGroupRole403> + | OpenAiClientError<"AssignGroupRole404", AssignGroupRole404> + | OpenAiClientError<"AssignGroupRole429", AssignGroupRole429> + > + } + /** + * Retrieves an organization role assigned to a group. + */ + readonly "retrieveGroupRole": { + ( + groupId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveGroupRole400", RetrieveGroupRole400> + | OpenAiClientError<"RetrieveGroupRole403", RetrieveGroupRole403> + | OpenAiClientError<"RetrieveGroupRole404", RetrieveGroupRole404> + | OpenAiClientError<"RetrieveGroupRole429", RetrieveGroupRole429> + > + ( + groupId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveGroupRole400", RetrieveGroupRole400> + | OpenAiClientError<"RetrieveGroupRole403", RetrieveGroupRole403> + | OpenAiClientError<"RetrieveGroupRole404", RetrieveGroupRole404> + | OpenAiClientError<"RetrieveGroupRole429", RetrieveGroupRole429> + > + } + /** + * Unassigns an organization role from a group within the organization. + */ + readonly "unassignGroupRole": { + ( + groupId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UnassignGroupRole400", UnassignGroupRole400> + | OpenAiClientError<"UnassignGroupRole403", UnassignGroupRole403> + | OpenAiClientError<"UnassignGroupRole404", UnassignGroupRole404> + | OpenAiClientError<"UnassignGroupRole429", UnassignGroupRole429> + > + ( + groupId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UnassignGroupRole400", UnassignGroupRole400> + | OpenAiClientError<"UnassignGroupRole403", UnassignGroupRole403> + | OpenAiClientError<"UnassignGroupRole404", UnassignGroupRole404> + | OpenAiClientError<"UnassignGroupRole429", UnassignGroupRole429> + > + } + /** + * Lists the users assigned to a group. + */ + readonly "listGroupUsers": { + ( + groupId: string, + options: { readonly params?: typeof ListGroupUsersParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListGroupUsers400", ListGroupUsers400> + | OpenAiClientError<"ListGroupUsers403", ListGroupUsers403> + | OpenAiClientError<"ListGroupUsers404", ListGroupUsers404> + | OpenAiClientError<"ListGroupUsers429", ListGroupUsers429> + | OpenAiClientError<"ListGroupUsers502", ListGroupUsers502> + > + ( + groupId: string, + options: { + readonly params?: typeof ListGroupUsersParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListGroupUsers400", ListGroupUsers400> + | OpenAiClientError<"ListGroupUsers403", ListGroupUsers403> + | OpenAiClientError<"ListGroupUsers404", ListGroupUsers404> + | OpenAiClientError<"ListGroupUsers429", ListGroupUsers429> + | OpenAiClientError<"ListGroupUsers502", ListGroupUsers502> + > + } + /** + * Adds a user to a group. + */ + readonly "addGroupUser": { + ( + groupId: string, + options: { readonly payload: typeof AddGroupUserRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AddGroupUser400", AddGroupUser400> + | OpenAiClientError<"AddGroupUser403", AddGroupUser403> + | OpenAiClientError<"AddGroupUser404", AddGroupUser404> + | OpenAiClientError<"AddGroupUser409", AddGroupUser409> + | OpenAiClientError<"AddGroupUser429", AddGroupUser429> + > + ( + groupId: string, + options: { readonly payload: typeof AddGroupUserRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AddGroupUser400", AddGroupUser400> + | OpenAiClientError<"AddGroupUser403", AddGroupUser403> + | OpenAiClientError<"AddGroupUser404", AddGroupUser404> + | OpenAiClientError<"AddGroupUser409", AddGroupUser409> + | OpenAiClientError<"AddGroupUser429", AddGroupUser429> + > + } + /** + * Retrieves a user in a group. + */ + readonly "retrieveGroupUser": { + ( + groupId: string, + userId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveGroupUser400", RetrieveGroupUser400> + | OpenAiClientError<"RetrieveGroupUser403", RetrieveGroupUser403> + | OpenAiClientError<"RetrieveGroupUser404", RetrieveGroupUser404> + | OpenAiClientError<"RetrieveGroupUser429", RetrieveGroupUser429> + > + ( + groupId: string, + userId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveGroupUser400", RetrieveGroupUser400> + | OpenAiClientError<"RetrieveGroupUser403", RetrieveGroupUser403> + | OpenAiClientError<"RetrieveGroupUser404", RetrieveGroupUser404> + | OpenAiClientError<"RetrieveGroupUser429", RetrieveGroupUser429> + > + } + /** + * Removes a user from a group. + */ + readonly "removeGroupUser": { + ( + groupId: string, + userId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RemoveGroupUser400", RemoveGroupUser400> + | OpenAiClientError<"RemoveGroupUser403", RemoveGroupUser403> + | OpenAiClientError<"RemoveGroupUser404", RemoveGroupUser404> + | OpenAiClientError<"RemoveGroupUser409", RemoveGroupUser409> + | OpenAiClientError<"RemoveGroupUser429", RemoveGroupUser429> + > + ( + groupId: string, + userId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RemoveGroupUser400", RemoveGroupUser400> + | OpenAiClientError<"RemoveGroupUser403", RemoveGroupUser403> + | OpenAiClientError<"RemoveGroupUser404", RemoveGroupUser404> + | OpenAiClientError<"RemoveGroupUser409", RemoveGroupUser409> + | OpenAiClientError<"RemoveGroupUser429", RemoveGroupUser429> + > + } + /** + * Returns a list of invites in the organization. + */ + readonly "listInvites": { + ( + options: { readonly params?: typeof ListInvitesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListInvites400", ListInvites400> + | OpenAiClientError<"ListInvites403", ListInvites403> + | OpenAiClientError<"ListInvites404", ListInvites404> + | OpenAiClientError<"ListInvites429", ListInvites429> + > + ( + options: + | { readonly params?: typeof ListInvitesParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListInvites400", ListInvites400> + | OpenAiClientError<"ListInvites403", ListInvites403> + | OpenAiClientError<"ListInvites404", ListInvites404> + | OpenAiClientError<"ListInvites429", ListInvites429> + > + } + /** + * Create an invite for a user to the organization. The invite must be accepted by the user before they have access to the organization. + */ + readonly "inviteUser": { + ( + options: { readonly payload: typeof InviteUserRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"InviteUser400", InviteUser400> + | OpenAiClientError<"InviteUser403", InviteUser403> + | OpenAiClientError<"InviteUser429", InviteUser429> + > + ( + options: { readonly payload: typeof InviteUserRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"InviteUser400", InviteUser400> + | OpenAiClientError<"InviteUser403", InviteUser403> + | OpenAiClientError<"InviteUser429", InviteUser429> + > + } + /** + * Retrieves an invite. + */ + readonly "retrieveInvite": { + ( + inviteId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveInvite400", RetrieveInvite400> + | OpenAiClientError<"RetrieveInvite403", RetrieveInvite403> + | OpenAiClientError<"RetrieveInvite404", RetrieveInvite404> + | OpenAiClientError<"RetrieveInvite429", RetrieveInvite429> + | OpenAiClientError<"RetrieveInvite500", RetrieveInvite500> + > + ( + inviteId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveInvite400", RetrieveInvite400> + | OpenAiClientError<"RetrieveInvite403", RetrieveInvite403> + | OpenAiClientError<"RetrieveInvite404", RetrieveInvite404> + | OpenAiClientError<"RetrieveInvite429", RetrieveInvite429> + | OpenAiClientError<"RetrieveInvite500", RetrieveInvite500> + > + } + /** + * Delete an invite. If the invite has already been accepted, it cannot be deleted. + */ + readonly "deleteInvite": { + ( + inviteId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteInvite400", DeleteInvite400> + | OpenAiClientError<"DeleteInvite403", DeleteInvite403> + | OpenAiClientError<"DeleteInvite404", DeleteInvite404> + | OpenAiClientError<"DeleteInvite429", DeleteInvite429> + > + ( + inviteId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteInvite400", DeleteInvite400> + | OpenAiClientError<"DeleteInvite403", DeleteInvite403> + | OpenAiClientError<"DeleteInvite404", DeleteInvite404> + | OpenAiClientError<"DeleteInvite429", DeleteInvite429> + > + } + /** + * Returns a list of projects. + */ + readonly "listProjects": { + ( + options: { readonly params?: typeof ListProjectsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjects400", ListProjects400> + | OpenAiClientError<"ListProjects403", ListProjects403> + | OpenAiClientError<"ListProjects404", ListProjects404> + | OpenAiClientError<"ListProjects429", ListProjects429> + > + ( + options: + | { readonly params?: typeof ListProjectsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjects400", ListProjects400> + | OpenAiClientError<"ListProjects403", ListProjects403> + | OpenAiClientError<"ListProjects404", ListProjects404> + | OpenAiClientError<"ListProjects429", ListProjects429> + > + } + /** + * Create a new project in the organization. Projects can be created and archived, but cannot be deleted. + */ + readonly "createProject": { + ( + options: { readonly payload: typeof CreateProjectRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProject400", CreateProject400> + | OpenAiClientError<"CreateProject403", CreateProject403> + | OpenAiClientError<"CreateProject429", CreateProject429> + > + ( + options: { readonly payload: typeof CreateProjectRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProject400", CreateProject400> + | OpenAiClientError<"CreateProject403", CreateProject403> + | OpenAiClientError<"CreateProject429", CreateProject429> + > + } + /** + * Retrieves a project. + */ + readonly "retrieveProject": { + ( + projectId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProject403", RetrieveProject403> + | OpenAiClientError<"RetrieveProject404", RetrieveProject404> + | OpenAiClientError<"RetrieveProject429", RetrieveProject429> + > + ( + projectId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProject403", RetrieveProject403> + | OpenAiClientError<"RetrieveProject404", RetrieveProject404> + | OpenAiClientError<"RetrieveProject429", RetrieveProject429> + > + } + /** + * Modifies a project in the organization. + */ + readonly "modifyProject": { + ( + projectId: string, + options: { readonly payload: typeof ModifyProjectRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyProject400", ModifyProject400> + | OpenAiClientError<"ModifyProject403", ModifyProject403> + | OpenAiClientError<"ModifyProject404", ModifyProject404> + | OpenAiClientError<"ModifyProject429", ModifyProject429> + > + ( + projectId: string, + options: { readonly payload: typeof ModifyProjectRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyProject400", ModifyProject400> + | OpenAiClientError<"ModifyProject403", ModifyProject403> + | OpenAiClientError<"ModifyProject404", ModifyProject404> + | OpenAiClientError<"ModifyProject429", ModifyProject429> + > + } + /** + * Returns a list of API keys in the project. + */ + readonly "listProjectApiKeys": { + ( + projectId: string, + options: { readonly params?: typeof ListProjectApiKeysParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectApiKeys400", ListProjectApiKeys400> + | OpenAiClientError<"ListProjectApiKeys403", ListProjectApiKeys403> + | OpenAiClientError<"ListProjectApiKeys404", ListProjectApiKeys404> + | OpenAiClientError<"ListProjectApiKeys429", ListProjectApiKeys429> + > + ( + projectId: string, + options: { + readonly params?: typeof ListProjectApiKeysParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectApiKeys400", ListProjectApiKeys400> + | OpenAiClientError<"ListProjectApiKeys403", ListProjectApiKeys403> + | OpenAiClientError<"ListProjectApiKeys404", ListProjectApiKeys404> + | OpenAiClientError<"ListProjectApiKeys429", ListProjectApiKeys429> + > + } + /** + * Retrieves an API key in the project. + */ + readonly "retrieveProjectApiKey": { + ( + projectId: string, + apiKeyId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectApiKey400", RetrieveProjectApiKey400> + | OpenAiClientError<"RetrieveProjectApiKey403", RetrieveProjectApiKey403> + | OpenAiClientError<"RetrieveProjectApiKey404", RetrieveProjectApiKey404> + | OpenAiClientError<"RetrieveProjectApiKey429", RetrieveProjectApiKey429> + > + ( + projectId: string, + apiKeyId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectApiKey400", RetrieveProjectApiKey400> + | OpenAiClientError<"RetrieveProjectApiKey403", RetrieveProjectApiKey403> + | OpenAiClientError<"RetrieveProjectApiKey404", RetrieveProjectApiKey404> + | OpenAiClientError<"RetrieveProjectApiKey429", RetrieveProjectApiKey429> + > + } + /** + * Deletes an API key from the project. * - * Returns the audio file content, or a stream of audio events. + * Returns confirmation of the key deletion, or an error if the key belonged to + * a service account. + */ + readonly "deleteProjectApiKey": { + ( + projectId: string, + apiKeyId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectApiKey400", DeleteProjectApiKey400> + | OpenAiClientError<"DeleteProjectApiKey403", DeleteProjectApiKey403> + | OpenAiClientError<"DeleteProjectApiKey404", DeleteProjectApiKey404> + | OpenAiClientError<"DeleteProjectApiKey429", DeleteProjectApiKey429> + > + ( + projectId: string, + apiKeyId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectApiKey400", DeleteProjectApiKey400> + | OpenAiClientError<"DeleteProjectApiKey403", DeleteProjectApiKey403> + | OpenAiClientError<"DeleteProjectApiKey404", DeleteProjectApiKey404> + | OpenAiClientError<"DeleteProjectApiKey429", DeleteProjectApiKey429> + > + } + /** + * Archives a project in the organization. Archived projects cannot be used or updated. + */ + readonly "archiveProject": { + ( + projectId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ArchiveProject400", ArchiveProject400> + | OpenAiClientError<"ArchiveProject403", ArchiveProject403> + | OpenAiClientError<"ArchiveProject404", ArchiveProject404> + | OpenAiClientError<"ArchiveProject429", ArchiveProject429> + > + ( + projectId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ArchiveProject400", ArchiveProject400> + | OpenAiClientError<"ArchiveProject403", ArchiveProject403> + | OpenAiClientError<"ArchiveProject404", ArchiveProject404> + | OpenAiClientError<"ArchiveProject429", ArchiveProject429> + > + } + /** + * List certificates for this project. + */ + readonly "listProjectCertificates": { + ( + projectId: string, + options: { readonly params?: typeof ListProjectCertificatesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectCertificates400", ListProjectCertificates400> + | OpenAiClientError<"ListProjectCertificates403", ListProjectCertificates403> + | OpenAiClientError<"ListProjectCertificates429", ListProjectCertificates429> + > + ( + projectId: string, + options: { + readonly params?: typeof ListProjectCertificatesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectCertificates400", ListProjectCertificates400> + | OpenAiClientError<"ListProjectCertificates403", ListProjectCertificates403> + | OpenAiClientError<"ListProjectCertificates429", ListProjectCertificates429> + > + } + /** + * Activate certificates at the project level. + * + * You can atomically and idempotently activate up to 10 certificates at a time. + */ + readonly "activateProjectCertificates": { + ( + projectId: string, + options: { readonly payload: typeof ActivateProjectCertificatesRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ActivateProjectCertificates400", ActivateProjectCertificates400> + | OpenAiClientError<"ActivateProjectCertificates403", ActivateProjectCertificates403> + | OpenAiClientError<"ActivateProjectCertificates404", ActivateProjectCertificates404> + | OpenAiClientError<"ActivateProjectCertificates429", ActivateProjectCertificates429> + | OpenAiClientError<"ActivateProjectCertificates500", ActivateProjectCertificates500> + > + ( + projectId: string, + options: { + readonly payload: typeof ActivateProjectCertificatesRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ActivateProjectCertificates400", ActivateProjectCertificates400> + | OpenAiClientError<"ActivateProjectCertificates403", ActivateProjectCertificates403> + | OpenAiClientError<"ActivateProjectCertificates404", ActivateProjectCertificates404> + | OpenAiClientError<"ActivateProjectCertificates429", ActivateProjectCertificates429> + | OpenAiClientError<"ActivateProjectCertificates500", ActivateProjectCertificates500> + > + } + /** + * Deactivate certificates at the project level. You can atomically and + * idempotently deactivate up to 10 certificates at a time. + */ + readonly "deactivateProjectCertificates": { + ( + projectId: string, + options: { readonly payload: typeof DeactivateProjectCertificatesRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeactivateProjectCertificates400", DeactivateProjectCertificates400> + | OpenAiClientError<"DeactivateProjectCertificates403", DeactivateProjectCertificates403> + | OpenAiClientError<"DeactivateProjectCertificates404", DeactivateProjectCertificates404> + | OpenAiClientError<"DeactivateProjectCertificates429", DeactivateProjectCertificates429> + | OpenAiClientError<"DeactivateProjectCertificates500", DeactivateProjectCertificates500> + > + ( + projectId: string, + options: { + readonly payload: typeof DeactivateProjectCertificatesRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeactivateProjectCertificates400", DeactivateProjectCertificates400> + | OpenAiClientError<"DeactivateProjectCertificates403", DeactivateProjectCertificates403> + | OpenAiClientError<"DeactivateProjectCertificates404", DeactivateProjectCertificates404> + | OpenAiClientError<"DeactivateProjectCertificates429", DeactivateProjectCertificates429> + | OpenAiClientError<"DeactivateProjectCertificates500", DeactivateProjectCertificates500> + > + } + /** + * Retrieves project data retention controls. + */ + readonly "retrieveProjectDataRetention": { + ( + projectId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectDataRetention400", RetrieveProjectDataRetention400> + | OpenAiClientError<"RetrieveProjectDataRetention403", RetrieveProjectDataRetention403> + | OpenAiClientError<"RetrieveProjectDataRetention404", RetrieveProjectDataRetention404> + > + ( + projectId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectDataRetention400", RetrieveProjectDataRetention400> + | OpenAiClientError<"RetrieveProjectDataRetention403", RetrieveProjectDataRetention403> + | OpenAiClientError<"RetrieveProjectDataRetention404", RetrieveProjectDataRetention404> + > + } + /** + * Updates project data retention controls. + */ + readonly "updateProjectDataRetention": { + ( + projectId: string, + options: { readonly payload: typeof UpdateProjectDataRetentionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectDataRetention400", UpdateProjectDataRetention400> + | OpenAiClientError<"UpdateProjectDataRetention403", UpdateProjectDataRetention403> + | OpenAiClientError<"UpdateProjectDataRetention404", UpdateProjectDataRetention404> + > + ( + projectId: string, + options: { + readonly payload: typeof UpdateProjectDataRetentionRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectDataRetention400", UpdateProjectDataRetention400> + | OpenAiClientError<"UpdateProjectDataRetention403", UpdateProjectDataRetention403> + | OpenAiClientError<"UpdateProjectDataRetention404", UpdateProjectDataRetention404> + > + } + /** + * Lists the groups that have access to a project. + */ + readonly "listProjectGroups": { + ( + projectId: string, + options: { readonly params?: typeof ListProjectGroupsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectGroups400", ListProjectGroups400> + | OpenAiClientError<"ListProjectGroups403", ListProjectGroups403> + | OpenAiClientError<"ListProjectGroups404", ListProjectGroups404> + | OpenAiClientError<"ListProjectGroups429", ListProjectGroups429> + > + ( + projectId: string, + options: { + readonly params?: typeof ListProjectGroupsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectGroups400", ListProjectGroups400> + | OpenAiClientError<"ListProjectGroups403", ListProjectGroups403> + | OpenAiClientError<"ListProjectGroups404", ListProjectGroups404> + | OpenAiClientError<"ListProjectGroups429", ListProjectGroups429> + > + } + /** + * Grants a group access to a project. + */ + readonly "addProjectGroup": { + ( + projectId: string, + options: { readonly payload: typeof AddProjectGroupRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AddProjectGroup400", AddProjectGroup400> + | OpenAiClientError<"AddProjectGroup403", AddProjectGroup403> + | OpenAiClientError<"AddProjectGroup404", AddProjectGroup404> + | OpenAiClientError<"AddProjectGroup429", AddProjectGroup429> + | OpenAiClientError<"AddProjectGroup500", AddProjectGroup500> + > + ( + projectId: string, + options: { readonly payload: typeof AddProjectGroupRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AddProjectGroup400", AddProjectGroup400> + | OpenAiClientError<"AddProjectGroup403", AddProjectGroup403> + | OpenAiClientError<"AddProjectGroup404", AddProjectGroup404> + | OpenAiClientError<"AddProjectGroup429", AddProjectGroup429> + | OpenAiClientError<"AddProjectGroup500", AddProjectGroup500> + > + } + /** + * Retrieves a project's group. + */ + readonly "retrieveProjectGroup": { + ( + projectId: string, + groupId: string, + options: { readonly params?: typeof RetrieveProjectGroupParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectGroup400", RetrieveProjectGroup400> + | OpenAiClientError<"RetrieveProjectGroup403", RetrieveProjectGroup403> + | OpenAiClientError<"RetrieveProjectGroup404", RetrieveProjectGroup404> + | OpenAiClientError<"RetrieveProjectGroup429", RetrieveProjectGroup429> + > + ( + projectId: string, + groupId: string, + options: { + readonly params?: typeof RetrieveProjectGroupParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectGroup400", RetrieveProjectGroup400> + | OpenAiClientError<"RetrieveProjectGroup403", RetrieveProjectGroup403> + | OpenAiClientError<"RetrieveProjectGroup404", RetrieveProjectGroup404> + | OpenAiClientError<"RetrieveProjectGroup429", RetrieveProjectGroup429> + > + } + /** + * Revokes a group's access to a project. + */ + readonly "removeProjectGroup": { + ( + projectId: string, + groupId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RemoveProjectGroup400", RemoveProjectGroup400> + | OpenAiClientError<"RemoveProjectGroup403", RemoveProjectGroup403> + | OpenAiClientError<"RemoveProjectGroup404", RemoveProjectGroup404> + | OpenAiClientError<"RemoveProjectGroup429", RemoveProjectGroup429> + > + ( + projectId: string, + groupId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RemoveProjectGroup400", RemoveProjectGroup400> + | OpenAiClientError<"RemoveProjectGroup403", RemoveProjectGroup403> + | OpenAiClientError<"RemoveProjectGroup404", RemoveProjectGroup404> + | OpenAiClientError<"RemoveProjectGroup429", RemoveProjectGroup429> + > + } + /** + * Returns hosted tool permissions for a project. + */ + readonly "retrieveProjectHostedToolPermissions": { + ( + projectId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectHostedToolPermissions400", RetrieveProjectHostedToolPermissions400> + | OpenAiClientError<"RetrieveProjectHostedToolPermissions403", RetrieveProjectHostedToolPermissions403> + | OpenAiClientError<"RetrieveProjectHostedToolPermissions404", RetrieveProjectHostedToolPermissions404> + | OpenAiClientError<"RetrieveProjectHostedToolPermissions429", RetrieveProjectHostedToolPermissions429> + > + ( + projectId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectHostedToolPermissions400", RetrieveProjectHostedToolPermissions400> + | OpenAiClientError<"RetrieveProjectHostedToolPermissions403", RetrieveProjectHostedToolPermissions403> + | OpenAiClientError<"RetrieveProjectHostedToolPermissions404", RetrieveProjectHostedToolPermissions404> + | OpenAiClientError<"RetrieveProjectHostedToolPermissions429", RetrieveProjectHostedToolPermissions429> + > + } + /** + * Updates hosted tool permissions for a project. + */ + readonly "updateProjectHostedToolPermissions": { + ( + projectId: string, + options: { + readonly payload: typeof UpdateProjectHostedToolPermissionsRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectHostedToolPermissions400", UpdateProjectHostedToolPermissions400> + | OpenAiClientError<"UpdateProjectHostedToolPermissions403", UpdateProjectHostedToolPermissions403> + | OpenAiClientError<"UpdateProjectHostedToolPermissions404", UpdateProjectHostedToolPermissions404> + | OpenAiClientError<"UpdateProjectHostedToolPermissions409", UpdateProjectHostedToolPermissions409> + | OpenAiClientError<"UpdateProjectHostedToolPermissions429", UpdateProjectHostedToolPermissions429> + > + ( + projectId: string, + options: { + readonly payload: typeof UpdateProjectHostedToolPermissionsRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectHostedToolPermissions400", UpdateProjectHostedToolPermissions400> + | OpenAiClientError<"UpdateProjectHostedToolPermissions403", UpdateProjectHostedToolPermissions403> + | OpenAiClientError<"UpdateProjectHostedToolPermissions404", UpdateProjectHostedToolPermissions404> + | OpenAiClientError<"UpdateProjectHostedToolPermissions409", UpdateProjectHostedToolPermissions409> + | OpenAiClientError<"UpdateProjectHostedToolPermissions429", UpdateProjectHostedToolPermissions429> + > + } + /** + * Returns model permissions for a project. + */ + readonly "retrieveProjectModelPermissions": { + ( + projectId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectModelPermissions400", RetrieveProjectModelPermissions400> + | OpenAiClientError<"RetrieveProjectModelPermissions403", RetrieveProjectModelPermissions403> + | OpenAiClientError<"RetrieveProjectModelPermissions404", RetrieveProjectModelPermissions404> + | OpenAiClientError<"RetrieveProjectModelPermissions429", RetrieveProjectModelPermissions429> + > + ( + projectId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectModelPermissions400", RetrieveProjectModelPermissions400> + | OpenAiClientError<"RetrieveProjectModelPermissions403", RetrieveProjectModelPermissions403> + | OpenAiClientError<"RetrieveProjectModelPermissions404", RetrieveProjectModelPermissions404> + | OpenAiClientError<"RetrieveProjectModelPermissions429", RetrieveProjectModelPermissions429> + > + } + /** + * Updates model permissions for a project. + */ + readonly "updateProjectModelPermissions": { + ( + projectId: string, + options: { readonly payload: typeof UpdateProjectModelPermissionsRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectModelPermissions400", UpdateProjectModelPermissions400> + | OpenAiClientError<"UpdateProjectModelPermissions403", UpdateProjectModelPermissions403> + | OpenAiClientError<"UpdateProjectModelPermissions404", UpdateProjectModelPermissions404> + | OpenAiClientError<"UpdateProjectModelPermissions429", UpdateProjectModelPermissions429> + > + ( + projectId: string, + options: { + readonly payload: typeof UpdateProjectModelPermissionsRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectModelPermissions400", UpdateProjectModelPermissions400> + | OpenAiClientError<"UpdateProjectModelPermissions403", UpdateProjectModelPermissions403> + | OpenAiClientError<"UpdateProjectModelPermissions404", UpdateProjectModelPermissions404> + | OpenAiClientError<"UpdateProjectModelPermissions429", UpdateProjectModelPermissions429> + > + } + /** + * Deletes model permissions for a project. */ - readonly "createSpeech": ( - options: { readonly payload: typeof CreateSpeechRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "deleteProjectModelPermissions": { + ( + projectId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectModelPermissions400", DeleteProjectModelPermissions400> + | OpenAiClientError<"DeleteProjectModelPermissions403", DeleteProjectModelPermissions403> + | OpenAiClientError<"DeleteProjectModelPermissions404", DeleteProjectModelPermissions404> + | OpenAiClientError<"DeleteProjectModelPermissions429", DeleteProjectModelPermissions429> + > + ( + projectId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectModelPermissions400", DeleteProjectModelPermissions400> + | OpenAiClientError<"DeleteProjectModelPermissions403", DeleteProjectModelPermissions403> + | OpenAiClientError<"DeleteProjectModelPermissions404", DeleteProjectModelPermissions404> + | OpenAiClientError<"DeleteProjectModelPermissions429", DeleteProjectModelPermissions429> + > + } /** - * Generates audio from the input text. - * - * Returns the audio file content, or a stream of audio events. + * Returns the rate limits per model for a project. */ - readonly "createSpeechSse": ( - options: { readonly payload: typeof CreateSpeechRequestJson.Encoded } - ) => Stream.Stream< - { readonly event: string; readonly id: string | undefined; readonly data: typeof CreateSpeech200Sse.Type }, - HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, - typeof CreateSpeech200Sse.DecodingServices - > + readonly "listProjectRateLimits": { + ( + projectId: string, + options: { readonly params?: typeof ListProjectRateLimitsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectRateLimits400", ListProjectRateLimits400> + | OpenAiClientError<"ListProjectRateLimits403", ListProjectRateLimits403> + | OpenAiClientError<"ListProjectRateLimits404", ListProjectRateLimits404> + > + ( + projectId: string, + options: { + readonly params?: typeof ListProjectRateLimitsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectRateLimits400", ListProjectRateLimits400> + | OpenAiClientError<"ListProjectRateLimits403", ListProjectRateLimits403> + | OpenAiClientError<"ListProjectRateLimits404", ListProjectRateLimits404> + > + } /** - * Generates audio from the input text. - * - * Returns the audio file content, or a stream of audio events. + * Updates a project rate limit. */ - readonly "createSpeechStream": ( - options: { readonly payload: typeof CreateSpeechRequestJson.Encoded } - ) => Stream.Stream + readonly "updateProjectRateLimits": { + ( + projectId: string, + rateLimitId: string, + options: { readonly payload: typeof UpdateProjectRateLimitsRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectRateLimits400", UpdateProjectRateLimits400> + | OpenAiClientError<"UpdateProjectRateLimits403", UpdateProjectRateLimits403> + | OpenAiClientError<"UpdateProjectRateLimits404", UpdateProjectRateLimits404> + > + ( + projectId: string, + rateLimitId: string, + options: { + readonly payload: typeof UpdateProjectRateLimitsRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectRateLimits400", UpdateProjectRateLimits400> + | OpenAiClientError<"UpdateProjectRateLimits403", UpdateProjectRateLimits403> + | OpenAiClientError<"UpdateProjectRateLimits404", UpdateProjectRateLimits404> + > + } /** - * Transcribes audio into the input language. - * - * Returns a transcription object in `json`, `diarized_json`, or `verbose_json` - * format, or a stream of transcript events. + * Returns a list of service accounts in the project. */ - readonly "createTranscription": ( - options: { - readonly payload: typeof CreateTranscriptionRequestFormData.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listProjectServiceAccounts": { + ( + projectId: string, + options: { + readonly params?: typeof ListProjectServiceAccountsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectServiceAccounts400", ListProjectServiceAccounts400> + | OpenAiClientError<"ListProjectServiceAccounts403", ListProjectServiceAccounts403> + | OpenAiClientError<"ListProjectServiceAccounts404", ListProjectServiceAccounts404> + | OpenAiClientError<"ListProjectServiceAccounts429", ListProjectServiceAccounts429> + > + ( + projectId: string, + options: { + readonly params?: typeof ListProjectServiceAccountsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectServiceAccounts400", ListProjectServiceAccounts400> + | OpenAiClientError<"ListProjectServiceAccounts403", ListProjectServiceAccounts403> + | OpenAiClientError<"ListProjectServiceAccounts404", ListProjectServiceAccounts404> + | OpenAiClientError<"ListProjectServiceAccounts429", ListProjectServiceAccounts429> + > + } /** - * Transcribes audio into the input language. - * - * Returns a transcription object in `json`, `diarized_json`, or `verbose_json` - * format, or a stream of transcript events. + * Creates a new service account in the project. By default, this also returns an unredacted API key for the service account. */ - readonly "createTranscriptionSse": ( - options: { readonly payload: typeof CreateTranscriptionRequestFormData.Encoded } - ) => Stream.Stream< - { readonly event: string; readonly id: string | undefined; readonly data: typeof CreateTranscription200Sse.Type }, - HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, - typeof CreateTranscription200Sse.DecodingServices - > + readonly "createProjectServiceAccount": { + ( + projectId: string, + options: { readonly payload: typeof CreateProjectServiceAccountRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProjectServiceAccount400", CreateProjectServiceAccount400> + | OpenAiClientError<"CreateProjectServiceAccount403", CreateProjectServiceAccount403> + | OpenAiClientError<"CreateProjectServiceAccount404", CreateProjectServiceAccount404> + | OpenAiClientError<"CreateProjectServiceAccount429", CreateProjectServiceAccount429> + > + ( + projectId: string, + options: { + readonly payload: typeof CreateProjectServiceAccountRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProjectServiceAccount400", CreateProjectServiceAccount400> + | OpenAiClientError<"CreateProjectServiceAccount403", CreateProjectServiceAccount403> + | OpenAiClientError<"CreateProjectServiceAccount404", CreateProjectServiceAccount404> + | OpenAiClientError<"CreateProjectServiceAccount429", CreateProjectServiceAccount429> + > + } /** - * Translates audio into English. + * Retrieves a service account in the project. */ - readonly "createTranslation": ( - options: { readonly payload: typeof CreateTranslationRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveProjectServiceAccount": { + ( + projectId: string, + serviceAccountId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectServiceAccount400", RetrieveProjectServiceAccount400> + | OpenAiClientError<"RetrieveProjectServiceAccount403", RetrieveProjectServiceAccount403> + | OpenAiClientError<"RetrieveProjectServiceAccount404", RetrieveProjectServiceAccount404> + | OpenAiClientError<"RetrieveProjectServiceAccount429", RetrieveProjectServiceAccount429> + > + ( + projectId: string, + serviceAccountId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectServiceAccount400", RetrieveProjectServiceAccount400> + | OpenAiClientError<"RetrieveProjectServiceAccount403", RetrieveProjectServiceAccount403> + | OpenAiClientError<"RetrieveProjectServiceAccount404", RetrieveProjectServiceAccount404> + | OpenAiClientError<"RetrieveProjectServiceAccount429", RetrieveProjectServiceAccount429> + > + } /** - * List consent recordings available to your organization for creating custom voices. - * - * See the [custom voices guide](/docs/guides/text-to-speech#custom-voices). Custom voices are limited to eligible customers. + * Updates a service account in the project. */ - readonly "listVoiceConsents": ( - options: { - readonly params?: typeof ListVoiceConsentsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateProjectServiceAccount": { + ( + projectId: string, + serviceAccountId: string, + options: { readonly payload: typeof UpdateProjectServiceAccountRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectServiceAccount400", UpdateProjectServiceAccount400> + | OpenAiClientError<"UpdateProjectServiceAccount403", UpdateProjectServiceAccount403> + | OpenAiClientError<"UpdateProjectServiceAccount404", UpdateProjectServiceAccount404> + | OpenAiClientError<"UpdateProjectServiceAccount429", UpdateProjectServiceAccount429> + > + ( + projectId: string, + serviceAccountId: string, + options: { + readonly payload: typeof UpdateProjectServiceAccountRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectServiceAccount400", UpdateProjectServiceAccount400> + | OpenAiClientError<"UpdateProjectServiceAccount403", UpdateProjectServiceAccount403> + | OpenAiClientError<"UpdateProjectServiceAccount404", UpdateProjectServiceAccount404> + | OpenAiClientError<"UpdateProjectServiceAccount429", UpdateProjectServiceAccount429> + > + } /** - * Upload a consent recording that authorizes creation of a custom voice. + * Deletes a service account from the project. * - * See the [custom voices guide](/docs/guides/text-to-speech#custom-voices) for requirements and best practices. Custom voices are limited to eligible customers. + * Returns confirmation of service account deletion, or an error if the project + * is archived (archived projects have no service accounts). */ - readonly "createVoiceConsent": ( - options: { - readonly payload: typeof CreateVoiceConsentRequestFormData.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Retrieve consent recording metadata used for creating custom voices. - * - * See the [custom voices guide](/docs/guides/text-to-speech#custom-voices). Custom voices are limited to eligible customers. - */ - readonly "getVoiceConsent": ( - consentId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteProjectServiceAccount": { + ( + projectId: string, + serviceAccountId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectServiceAccount400", DeleteProjectServiceAccount400> + | OpenAiClientError<"DeleteProjectServiceAccount403", DeleteProjectServiceAccount403> + | OpenAiClientError<"DeleteProjectServiceAccount404", DeleteProjectServiceAccount404> + | OpenAiClientError<"DeleteProjectServiceAccount429", DeleteProjectServiceAccount429> + > + ( + projectId: string, + serviceAccountId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectServiceAccount400", DeleteProjectServiceAccount400> + | OpenAiClientError<"DeleteProjectServiceAccount403", DeleteProjectServiceAccount403> + | OpenAiClientError<"DeleteProjectServiceAccount404", DeleteProjectServiceAccount404> + | OpenAiClientError<"DeleteProjectServiceAccount429", DeleteProjectServiceAccount429> + > + } /** - * Update consent recording metadata used for creating custom voices. This endpoint updates metadata only and does not replace the underlying audio. - * - * See the [custom voices guide](/docs/guides/text-to-speech#custom-voices). Custom voices are limited to eligible customers. - */ - readonly "updateVoiceConsent": ( - consentId: string, - options: { readonly payload: typeof UpdateVoiceConsentRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + * Lists project spend alerts. + */ + readonly "listProjectSpendAlerts": { + ( + projectId: string, + options: { readonly params?: typeof ListProjectSpendAlertsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectSpendAlerts400", ListProjectSpendAlerts400> + | OpenAiClientError<"ListProjectSpendAlerts403", ListProjectSpendAlerts403> + | OpenAiClientError<"ListProjectSpendAlerts404", ListProjectSpendAlerts404> + > + ( + projectId: string, + options: { + readonly params?: typeof ListProjectSpendAlertsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectSpendAlerts400", ListProjectSpendAlerts400> + | OpenAiClientError<"ListProjectSpendAlerts403", ListProjectSpendAlerts403> + | OpenAiClientError<"ListProjectSpendAlerts404", ListProjectSpendAlerts404> + > + } /** - * Delete a consent recording that was uploaded for creating custom voices. - * - * See the [custom voices guide](/docs/guides/text-to-speech#custom-voices). Custom voices are limited to eligible customers. - */ - readonly "deleteVoiceConsent": ( - consentId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + * Creates a project spend alert. + */ + readonly "createProjectSpendAlert": { + ( + projectId: string, + options: { readonly payload: typeof CreateProjectSpendAlertRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProjectSpendAlert400", CreateProjectSpendAlert400> + | OpenAiClientError<"CreateProjectSpendAlert403", CreateProjectSpendAlert403> + | OpenAiClientError<"CreateProjectSpendAlert404", CreateProjectSpendAlert404> + > + ( + projectId: string, + options: { + readonly payload: typeof CreateProjectSpendAlertRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProjectSpendAlert400", CreateProjectSpendAlert400> + | OpenAiClientError<"CreateProjectSpendAlert403", CreateProjectSpendAlert403> + | OpenAiClientError<"CreateProjectSpendAlert404", CreateProjectSpendAlert404> + > + } /** - * Create a custom voice you can use for audio output (for example, in Text-to-Speech and the Realtime API). This requires an audio sample and a previously uploaded consent recording. - * - * See the [custom voices guide](/docs/guides/text-to-speech#custom-voices) for requirements and best practices. Custom voices are limited to eligible customers. + * Retrieves a project spend alert. */ - readonly "createVoice": ( - options: { readonly payload: typeof CreateVoiceRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveProjectSpendAlert": { + ( + projectId: string, + alertId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectSpendAlert400", RetrieveProjectSpendAlert400> + | OpenAiClientError<"RetrieveProjectSpendAlert403", RetrieveProjectSpendAlert403> + | OpenAiClientError<"RetrieveProjectSpendAlert404", RetrieveProjectSpendAlert404> + > + ( + projectId: string, + alertId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectSpendAlert400", RetrieveProjectSpendAlert400> + | OpenAiClientError<"RetrieveProjectSpendAlert403", RetrieveProjectSpendAlert403> + | OpenAiClientError<"RetrieveProjectSpendAlert404", RetrieveProjectSpendAlert404> + > + } /** - * List your organization's batches. + * Updates a project spend alert. */ - readonly "listBatches": ( - options: - | { readonly params?: typeof ListBatchesParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateProjectSpendAlert": { + ( + projectId: string, + alertId: string, + options: { readonly payload: typeof UpdateProjectSpendAlertRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectSpendAlert400", UpdateProjectSpendAlert400> + | OpenAiClientError<"UpdateProjectSpendAlert403", UpdateProjectSpendAlert403> + | OpenAiClientError<"UpdateProjectSpendAlert404", UpdateProjectSpendAlert404> + > + ( + projectId: string, + alertId: string, + options: { + readonly payload: typeof UpdateProjectSpendAlertRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectSpendAlert400", UpdateProjectSpendAlert400> + | OpenAiClientError<"UpdateProjectSpendAlert403", UpdateProjectSpendAlert403> + | OpenAiClientError<"UpdateProjectSpendAlert404", UpdateProjectSpendAlert404> + > + } /** - * Creates and executes a batch from an uploaded file of requests + * Deletes a project spend alert. */ - readonly "createBatch": ( - options: { readonly payload: typeof CreateBatchRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteProjectSpendAlert": { + ( + projectId: string, + alertId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectSpendAlert400", DeleteProjectSpendAlert400> + | OpenAiClientError<"DeleteProjectSpendAlert403", DeleteProjectSpendAlert403> + | OpenAiClientError<"DeleteProjectSpendAlert404", DeleteProjectSpendAlert404> + > + ( + projectId: string, + alertId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectSpendAlert400", DeleteProjectSpendAlert400> + | OpenAiClientError<"DeleteProjectSpendAlert403", DeleteProjectSpendAlert403> + | OpenAiClientError<"DeleteProjectSpendAlert404", DeleteProjectSpendAlert404> + > + } /** - * Retrieves a batch. + * Returns a list of users in the project. */ - readonly "retrieveBatch": ( - batchId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listProjectUsers": { + ( + projectId: string, + options: { readonly params?: typeof ListProjectUsersParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectUsers400", ListProjectUsers400> + | OpenAiClientError<"ListProjectUsers403", ListProjectUsers403> + | OpenAiClientError<"ListProjectUsers404", ListProjectUsers404> + | OpenAiClientError<"ListProjectUsers429", ListProjectUsers429> + > + ( + projectId: string, + options: { + readonly params?: typeof ListProjectUsersParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectUsers400", ListProjectUsers400> + | OpenAiClientError<"ListProjectUsers403", ListProjectUsers403> + | OpenAiClientError<"ListProjectUsers404", ListProjectUsers404> + | OpenAiClientError<"ListProjectUsers429", ListProjectUsers429> + > + } /** - * Cancels an in-progress batch. The batch will be in status `cancelling` for up to 10 minutes, before changing to `cancelled`, where it will have partial results (if any) available in the output file. + * Adds a user to the project. Users must already be members of the organization to be added to a project. */ - readonly "cancelBatch": ( - batchId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createProjectUser": { + ( + projectId: string, + options: { readonly payload: typeof CreateProjectUserRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProjectUser400", CreateProjectUser400> + | OpenAiClientError<"CreateProjectUser403", CreateProjectUser403> + | OpenAiClientError<"CreateProjectUser404", CreateProjectUser404> + | OpenAiClientError<"CreateProjectUser409", CreateProjectUser409> + | OpenAiClientError<"CreateProjectUser429", CreateProjectUser429> + > + ( + projectId: string, + options: { readonly payload: typeof CreateProjectUserRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProjectUser400", CreateProjectUser400> + | OpenAiClientError<"CreateProjectUser403", CreateProjectUser403> + | OpenAiClientError<"CreateProjectUser404", CreateProjectUser404> + | OpenAiClientError<"CreateProjectUser409", CreateProjectUser409> + | OpenAiClientError<"CreateProjectUser429", CreateProjectUser429> + > + } /** - * List stored Chat Completions. Only Chat Completions that have been stored - * with the `store` parameter set to `true` will be returned. + * Retrieves a user in the project. */ - readonly "listChatCompletions": ( - options: { - readonly params?: typeof ListChatCompletionsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveProjectUser": { + ( + projectId: string, + userId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectUser400", RetrieveProjectUser400> + | OpenAiClientError<"RetrieveProjectUser403", RetrieveProjectUser403> + | OpenAiClientError<"RetrieveProjectUser404", RetrieveProjectUser404> + | OpenAiClientError<"RetrieveProjectUser429", RetrieveProjectUser429> + > + ( + projectId: string, + userId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectUser400", RetrieveProjectUser400> + | OpenAiClientError<"RetrieveProjectUser403", RetrieveProjectUser403> + | OpenAiClientError<"RetrieveProjectUser404", RetrieveProjectUser404> + | OpenAiClientError<"RetrieveProjectUser429", RetrieveProjectUser429> + > + } /** - * **Starting a new project?** We recommend trying [Responses](/docs/api-reference/responses) - * to take advantage of the latest OpenAI platform features. Compare - * [Chat Completions with Responses](/docs/guides/responses-vs-chat-completions?api-mode=responses). - * - * --- - * - * Creates a model response for the given chat conversation. Learn more in the - * [text generation](/docs/guides/text-generation), [vision](/docs/guides/vision), - * and [audio](/docs/guides/audio) guides. - * - * Parameter support can differ depending on the model used to generate the - * response, particularly for newer reasoning models. Parameters that are only - * supported for reasoning models are noted below. For the current state of - * unsupported parameters in reasoning models, - * [refer to the reasoning guide](/docs/guides/reasoning). - * - * Returns a chat completion object, or a streamed sequence of chat completion - * chunk objects if the request is streamed. + * Modifies a user's role in the project. */ - readonly "createChatCompletion": ( - options: { readonly payload: typeof CreateChatCompletionRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "modifyProjectUser": { + ( + projectId: string, + userId: string, + options: { readonly payload: typeof ModifyProjectUserRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyProjectUser400", ModifyProjectUser400> + | OpenAiClientError<"ModifyProjectUser403", ModifyProjectUser403> + | OpenAiClientError<"ModifyProjectUser404", ModifyProjectUser404> + | OpenAiClientError<"ModifyProjectUser429", ModifyProjectUser429> + > + ( + projectId: string, + userId: string, + options: { readonly payload: typeof ModifyProjectUserRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyProjectUser400", ModifyProjectUser400> + | OpenAiClientError<"ModifyProjectUser403", ModifyProjectUser403> + | OpenAiClientError<"ModifyProjectUser404", ModifyProjectUser404> + | OpenAiClientError<"ModifyProjectUser429", ModifyProjectUser429> + > + } /** - * **Starting a new project?** We recommend trying [Responses](/docs/api-reference/responses) - * to take advantage of the latest OpenAI platform features. Compare - * [Chat Completions with Responses](/docs/guides/responses-vs-chat-completions?api-mode=responses). - * - * --- - * - * Creates a model response for the given chat conversation. Learn more in the - * [text generation](/docs/guides/text-generation), [vision](/docs/guides/vision), - * and [audio](/docs/guides/audio) guides. - * - * Parameter support can differ depending on the model used to generate the - * response, particularly for newer reasoning models. Parameters that are only - * supported for reasoning models are noted below. For the current state of - * unsupported parameters in reasoning models, - * [refer to the reasoning guide](/docs/guides/reasoning). + * Deletes a user from the project. * - * Returns a chat completion object, or a streamed sequence of chat completion - * chunk objects if the request is streamed. + * Returns confirmation of project user deletion, or an error if the project is + * archived (archived projects have no users). */ - readonly "createChatCompletionSse": ( - options: { readonly payload: typeof CreateChatCompletionRequestJson.Encoded } - ) => Stream.Stream< - { readonly event: string; readonly id: string | undefined; readonly data: typeof CreateChatCompletion200Sse.Type }, - HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, - typeof CreateChatCompletion200Sse.DecodingServices - > + readonly "deleteProjectUser": { + ( + projectId: string, + userId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectUser400", DeleteProjectUser400> + | OpenAiClientError<"DeleteProjectUser403", DeleteProjectUser403> + | OpenAiClientError<"DeleteProjectUser404", DeleteProjectUser404> + | OpenAiClientError<"DeleteProjectUser429", DeleteProjectUser429> + > + ( + projectId: string, + userId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectUser400", DeleteProjectUser400> + | OpenAiClientError<"DeleteProjectUser403", DeleteProjectUser403> + | OpenAiClientError<"DeleteProjectUser404", DeleteProjectUser404> + | OpenAiClientError<"DeleteProjectUser429", DeleteProjectUser429> + > + } /** - * Get a stored chat completion. Only Chat Completions that have been created - * with the `store` parameter set to `true` will be returned. + * Lists the roles configured for the organization. */ - readonly "getChatCompletion": ( - completionId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listRoles": { + ( + options: { readonly params?: typeof ListRolesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListRoles400", ListRoles400> + | OpenAiClientError<"ListRoles403", ListRoles403> + | OpenAiClientError<"ListRoles404", ListRoles404> + | OpenAiClientError<"ListRoles429", ListRoles429> + > + ( + options: + | { readonly params?: typeof ListRolesParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListRoles400", ListRoles400> + | OpenAiClientError<"ListRoles403", ListRoles403> + | OpenAiClientError<"ListRoles404", ListRoles404> + | OpenAiClientError<"ListRoles429", ListRoles429> + > + } /** - * Modify a stored chat completion. Only Chat Completions that have been - * created with the `store` parameter set to `true` can be modified. Currently, - * the only supported modification is to update the `metadata` field. + * Creates a custom role for the organization. */ - readonly "updateChatCompletion": ( - completionId: string, - options: { readonly payload: typeof UpdateChatCompletionRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createRole": { + ( + options: { readonly payload: typeof CreateRoleRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateRole400", CreateRole400> + | OpenAiClientError<"CreateRole403", CreateRole403> + | OpenAiClientError<"CreateRole404", CreateRole404> + | OpenAiClientError<"CreateRole429", CreateRole429> + > + ( + options: { readonly payload: typeof CreateRoleRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateRole400", CreateRole400> + | OpenAiClientError<"CreateRole403", CreateRole403> + | OpenAiClientError<"CreateRole404", CreateRole404> + | OpenAiClientError<"CreateRole429", CreateRole429> + > + } /** - * Delete a stored chat completion. Only Chat Completions that have been - * created with the `store` parameter set to `true` can be deleted. + * Retrieves an organization role. */ - readonly "deleteChatCompletion": ( - completionId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveRole": { + ( + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveRole403", RetrieveRole403> + | OpenAiClientError<"RetrieveRole404", RetrieveRole404> + | OpenAiClientError<"RetrieveRole429", RetrieveRole429> + > + ( + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveRole403", RetrieveRole403> + | OpenAiClientError<"RetrieveRole404", RetrieveRole404> + | OpenAiClientError<"RetrieveRole429", RetrieveRole429> + > + } /** - * Get the messages in a stored chat completion. Only Chat Completions that - * have been created with the `store` parameter set to `true` will be - * returned. + * Updates an existing organization role. */ - readonly "getChatCompletionMessages": ( - completionId: string, - options: { - readonly params?: typeof GetChatCompletionMessagesParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateRole": { + ( + roleId: string, + options: { readonly payload: typeof UpdateRoleRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateRole400", UpdateRole400> + | OpenAiClientError<"UpdateRole403", UpdateRole403> + | OpenAiClientError<"UpdateRole404", UpdateRole404> + | OpenAiClientError<"UpdateRole429", UpdateRole429> + > + ( + roleId: string, + options: { readonly payload: typeof UpdateRoleRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateRole400", UpdateRole400> + | OpenAiClientError<"UpdateRole403", UpdateRole403> + | OpenAiClientError<"UpdateRole404", UpdateRole404> + | OpenAiClientError<"UpdateRole429", UpdateRole429> + > + } /** - * Creates a completion for the provided prompt and parameters. - * - * Returns a completion object, or a sequence of completion objects if the request is streamed. + * Deletes a custom role from the organization. */ - readonly "createCompletion": ( - options: { readonly payload: typeof CreateCompletionRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteRole": { + ( + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteRole400", DeleteRole400> + | OpenAiClientError<"DeleteRole403", DeleteRole403> + | OpenAiClientError<"DeleteRole404", DeleteRole404> + | OpenAiClientError<"DeleteRole429", DeleteRole429> + > + ( + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteRole400", DeleteRole400> + | OpenAiClientError<"DeleteRole403", DeleteRole403> + | OpenAiClientError<"DeleteRole404", DeleteRole404> + | OpenAiClientError<"DeleteRole429", DeleteRole429> + > + } /** - * Lists containers. + * Lists organization spend alerts. */ - readonly "ListContainers": ( - options: - | { readonly params?: typeof ListContainersParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listOrganizationSpendAlerts": { + ( + options: { + readonly params?: typeof ListOrganizationSpendAlertsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListOrganizationSpendAlerts400", ListOrganizationSpendAlerts400> + | OpenAiClientError<"ListOrganizationSpendAlerts403", ListOrganizationSpendAlerts403> + | OpenAiClientError<"ListOrganizationSpendAlerts404", ListOrganizationSpendAlerts404> + > + ( + options: { + readonly params?: typeof ListOrganizationSpendAlertsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListOrganizationSpendAlerts400", ListOrganizationSpendAlerts400> + | OpenAiClientError<"ListOrganizationSpendAlerts403", ListOrganizationSpendAlerts403> + | OpenAiClientError<"ListOrganizationSpendAlerts404", ListOrganizationSpendAlerts404> + > + } /** - * Creates a container. + * Creates an organization spend alert. */ - readonly "CreateContainer": ( - options: { readonly payload: typeof CreateContainerRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createOrganizationSpendAlert": { + ( + options: { readonly payload: typeof CreateOrganizationSpendAlertRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateOrganizationSpendAlert400", CreateOrganizationSpendAlert400> + | OpenAiClientError<"CreateOrganizationSpendAlert403", CreateOrganizationSpendAlert403> + > + ( + options: { + readonly payload: typeof CreateOrganizationSpendAlertRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateOrganizationSpendAlert400", CreateOrganizationSpendAlert400> + | OpenAiClientError<"CreateOrganizationSpendAlert403", CreateOrganizationSpendAlert403> + > + } /** - * Retrieves a container. + * Retrieves an organization spend alert. */ - readonly "RetrieveContainer": ( - containerId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveOrganizationSpendAlert": { + ( + alertId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveOrganizationSpendAlert403", RetrieveOrganizationSpendAlert403> + | OpenAiClientError<"RetrieveOrganizationSpendAlert404", RetrieveOrganizationSpendAlert404> + > + ( + alertId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveOrganizationSpendAlert403", RetrieveOrganizationSpendAlert403> + | OpenAiClientError<"RetrieveOrganizationSpendAlert404", RetrieveOrganizationSpendAlert404> + > + } /** - * Delete a container. + * Updates an organization spend alert. */ - readonly "DeleteContainer": ( - containerId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "updateOrganizationSpendAlert": { + ( + alertId: string, + options: { readonly payload: typeof UpdateOrganizationSpendAlertRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateOrganizationSpendAlert400", UpdateOrganizationSpendAlert400> + | OpenAiClientError<"UpdateOrganizationSpendAlert403", UpdateOrganizationSpendAlert403> + | OpenAiClientError<"UpdateOrganizationSpendAlert404", UpdateOrganizationSpendAlert404> + > + ( + alertId: string, + options: { + readonly payload: typeof UpdateOrganizationSpendAlertRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateOrganizationSpendAlert400", UpdateOrganizationSpendAlert400> + | OpenAiClientError<"UpdateOrganizationSpendAlert403", UpdateOrganizationSpendAlert403> + | OpenAiClientError<"UpdateOrganizationSpendAlert404", UpdateOrganizationSpendAlert404> + > + } /** - * Lists container files. + * Deletes an organization spend alert. */ - readonly "ListContainerFiles": ( - containerId: string, - options: { - readonly params?: typeof ListContainerFilesParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteOrganizationSpendAlert": { + ( + alertId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteOrganizationSpendAlert403", DeleteOrganizationSpendAlert403> + | OpenAiClientError<"DeleteOrganizationSpendAlert404", DeleteOrganizationSpendAlert404> + > + ( + alertId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteOrganizationSpendAlert403", DeleteOrganizationSpendAlert403> + | OpenAiClientError<"DeleteOrganizationSpendAlert404", DeleteOrganizationSpendAlert404> + > + } /** - * Creates a container file. + * Get audio speeches usage details for the organization. */ - readonly "CreateContainerFile": ( - containerId: string, - options: { - readonly payload: typeof CreateContainerFileRequestFormData.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "usageAudioSpeeches": { + ( + options: { readonly params: typeof UsageAudioSpeechesParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageAudioSpeeches400", UsageAudioSpeeches400> + | OpenAiClientError<"UsageAudioSpeeches403", UsageAudioSpeeches403> + | OpenAiClientError<"UsageAudioSpeeches429", UsageAudioSpeeches429> + > + ( + options: { readonly params: typeof UsageAudioSpeechesParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageAudioSpeeches400", UsageAudioSpeeches400> + | OpenAiClientError<"UsageAudioSpeeches403", UsageAudioSpeeches403> + | OpenAiClientError<"UsageAudioSpeeches429", UsageAudioSpeeches429> + > + } /** - * Retrieves a container file. + * Get audio transcriptions usage details for the organization. */ - readonly "RetrieveContainerFile": ( - containerId: string, - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "usageAudioTranscriptions": { + ( + options: { readonly params: typeof UsageAudioTranscriptionsParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageAudioTranscriptions400", UsageAudioTranscriptions400> + | OpenAiClientError<"UsageAudioTranscriptions403", UsageAudioTranscriptions403> + | OpenAiClientError<"UsageAudioTranscriptions429", UsageAudioTranscriptions429> + > + ( + options: { readonly params: typeof UsageAudioTranscriptionsParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageAudioTranscriptions400", UsageAudioTranscriptions400> + | OpenAiClientError<"UsageAudioTranscriptions403", UsageAudioTranscriptions403> + | OpenAiClientError<"UsageAudioTranscriptions429", UsageAudioTranscriptions429> + > + } /** - * Delete a container file. + * Get code interpreter sessions usage details for the organization. */ - readonly "DeleteContainerFile": ( - containerId: string, - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "usageCodeInterpreterSessions": { + ( + options: { readonly params: typeof UsageCodeInterpreterSessionsParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageCodeInterpreterSessions400", UsageCodeInterpreterSessions400> + | OpenAiClientError<"UsageCodeInterpreterSessions403", UsageCodeInterpreterSessions403> + | OpenAiClientError<"UsageCodeInterpreterSessions429", UsageCodeInterpreterSessions429> + > + ( + options: { + readonly params: typeof UsageCodeInterpreterSessionsParams.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageCodeInterpreterSessions400", UsageCodeInterpreterSessions400> + | OpenAiClientError<"UsageCodeInterpreterSessions403", UsageCodeInterpreterSessions403> + | OpenAiClientError<"UsageCodeInterpreterSessions429", UsageCodeInterpreterSessions429> + > + } /** - * Retrieves a container file content. + * Get completions usage details for the organization. */ - readonly "RetrieveContainerFileContent": ( - containerId: string, - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "usageCompletions": { + ( + options: { readonly params: typeof UsageCompletionsParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageCompletions400", UsageCompletions400> + | OpenAiClientError<"UsageCompletions403", UsageCompletions403> + | OpenAiClientError<"UsageCompletions429", UsageCompletions429> + > + ( + options: { readonly params: typeof UsageCompletionsParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageCompletions400", UsageCompletions400> + | OpenAiClientError<"UsageCompletions403", UsageCompletions403> + | OpenAiClientError<"UsageCompletions429", UsageCompletions429> + > + } /** - * List all items for a conversation with the given ID. + * Get embeddings usage details for the organization. */ - readonly "listConversationItems": ( - conversationId: string, - options: { - readonly params?: typeof ListConversationItemsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "usageEmbeddings": { + ( + options: { readonly params: typeof UsageEmbeddingsParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageEmbeddings400", UsageEmbeddings400> + | OpenAiClientError<"UsageEmbeddings403", UsageEmbeddings403> + | OpenAiClientError<"UsageEmbeddings429", UsageEmbeddings429> + > + ( + options: { readonly params: typeof UsageEmbeddingsParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageEmbeddings400", UsageEmbeddings400> + | OpenAiClientError<"UsageEmbeddings403", UsageEmbeddings403> + | OpenAiClientError<"UsageEmbeddings429", UsageEmbeddings429> + > + } /** - * Create items in a conversation with the given ID. + * Get file search calls usage details for the organization. */ - readonly "createConversationItems": ( - conversationId: string, - options: { - readonly params?: typeof CreateConversationItemsParams.Encoded | undefined - readonly payload: typeof CreateConversationItemsRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "usageFileSearchCalls": { + ( + options: { readonly params: typeof UsageFileSearchCallsParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageFileSearchCalls400", UsageFileSearchCalls400> + | OpenAiClientError<"UsageFileSearchCalls403", UsageFileSearchCalls403> + | OpenAiClientError<"UsageFileSearchCalls429", UsageFileSearchCalls429> + > + ( + options: { readonly params: typeof UsageFileSearchCallsParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageFileSearchCalls400", UsageFileSearchCalls400> + | OpenAiClientError<"UsageFileSearchCalls403", UsageFileSearchCalls403> + | OpenAiClientError<"UsageFileSearchCalls429", UsageFileSearchCalls429> + > + } /** - * Get a single item from a conversation with the given IDs. + * Get images usage details for the organization. */ - readonly "getConversationItem": ( - conversationId: string, - itemId: string, - options: { - readonly params?: typeof GetConversationItemParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "usageImages": { + ( + options: { readonly params: typeof UsageImagesParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageImages400", UsageImages400> + | OpenAiClientError<"UsageImages403", UsageImages403> + | OpenAiClientError<"UsageImages429", UsageImages429> + > + ( + options: { readonly params: typeof UsageImagesParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageImages400", UsageImages400> + | OpenAiClientError<"UsageImages403", UsageImages403> + | OpenAiClientError<"UsageImages429", UsageImages429> + > + } /** - * Delete an item from a conversation with the given IDs. + * Get moderations usage details for the organization. */ - readonly "deleteConversationItem": ( - conversationId: string, - itemId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "usageModerations": { + ( + options: { readonly params: typeof UsageModerationsParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageModerations400", UsageModerations400> + | OpenAiClientError<"UsageModerations403", UsageModerations403> + | OpenAiClientError<"UsageModerations429", UsageModerations429> + > + ( + options: { readonly params: typeof UsageModerationsParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageModerations400", UsageModerations400> + | OpenAiClientError<"UsageModerations403", UsageModerations403> + | OpenAiClientError<"UsageModerations429", UsageModerations429> + > + } /** - * Creates an embedding vector representing the input text. + * Get vector stores usage details for the organization. */ - readonly "createEmbedding": ( - options: { readonly payload: typeof CreateEmbeddingRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "usageVectorStores": { + ( + options: { readonly params: typeof UsageVectorStoresParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageVectorStores400", UsageVectorStores400> + | OpenAiClientError<"UsageVectorStores403", UsageVectorStores403> + | OpenAiClientError<"UsageVectorStores429", UsageVectorStores429> + > + ( + options: { readonly params: typeof UsageVectorStoresParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageVectorStores400", UsageVectorStores400> + | OpenAiClientError<"UsageVectorStores403", UsageVectorStores403> + | OpenAiClientError<"UsageVectorStores429", UsageVectorStores429> + > + } /** - * List evaluations for a project. + * Get web search calls usage details for the organization. */ - readonly "listEvals": ( - options: - | { readonly params?: typeof ListEvalsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "usageWebSearchCalls": { + ( + options: { readonly params: typeof UsageWebSearchCallsParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageWebSearchCalls400", UsageWebSearchCalls400> + | OpenAiClientError<"UsageWebSearchCalls403", UsageWebSearchCalls403> + | OpenAiClientError<"UsageWebSearchCalls429", UsageWebSearchCalls429> + > + ( + options: { readonly params: typeof UsageWebSearchCallsParams.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UsageWebSearchCalls400", UsageWebSearchCalls400> + | OpenAiClientError<"UsageWebSearchCalls403", UsageWebSearchCalls403> + | OpenAiClientError<"UsageWebSearchCalls429", UsageWebSearchCalls429> + > + } /** - * Create the structure of an evaluation that can be used to test a model's performance. - * An evaluation is a set of testing criteria and the config for a data source, which dictates the schema of the data used in the evaluation. After creating an evaluation, you can run it on different models and model parameters. We support several types of graders and datasources. - * For more information, see the [Evals guide](/docs/guides/evals). + * Lists all of the users in the organization. */ - readonly "createEval": ( - options: { readonly payload: typeof CreateEvalRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listUsers": { + ( + options: { readonly params?: typeof ListUsersParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListUsers400", ListUsers400> + | OpenAiClientError<"ListUsers403", ListUsers403> + | OpenAiClientError<"ListUsers429", ListUsers429> + > + ( + options: + | { readonly params?: typeof ListUsersParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListUsers400", ListUsers400> + | OpenAiClientError<"ListUsers403", ListUsers403> + | OpenAiClientError<"ListUsers429", ListUsers429> + > + } /** - * Get an evaluation by ID. + * Retrieves a user by their identifier. */ - readonly "getEval": ( - evalId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveUser": { + ( + userId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveUser403", RetrieveUser403> + | OpenAiClientError<"RetrieveUser404", RetrieveUser404> + | OpenAiClientError<"RetrieveUser429", RetrieveUser429> + > + ( + userId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveUser403", RetrieveUser403> + | OpenAiClientError<"RetrieveUser404", RetrieveUser404> + | OpenAiClientError<"RetrieveUser429", RetrieveUser429> + > + } /** - * Update certain properties of an evaluation. + * Modifies a user's role in the organization. */ - readonly "updateEval": ( - evalId: string, - options: { readonly payload: typeof UpdateEvalRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "modifyUser": { + ( + userId: string, + options: { readonly payload: typeof ModifyUserRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyUser400", ModifyUser400> + | OpenAiClientError<"ModifyUser403", ModifyUser403> + | OpenAiClientError<"ModifyUser404", ModifyUser404> + | OpenAiClientError<"ModifyUser429", ModifyUser429> + > + ( + userId: string, + options: { readonly payload: typeof ModifyUserRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyUser400", ModifyUser400> + | OpenAiClientError<"ModifyUser403", ModifyUser403> + | OpenAiClientError<"ModifyUser404", ModifyUser404> + | OpenAiClientError<"ModifyUser429", ModifyUser429> + > + } /** - * Delete an evaluation. + * Deletes a user from the organization. */ - readonly "deleteEval": ( - evalId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"DeleteEval404", typeof DeleteEval404.Type> - > + readonly "deleteUser": { + ( + userId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteUser400", DeleteUser400> + | OpenAiClientError<"DeleteUser403", DeleteUser403> + | OpenAiClientError<"DeleteUser404", DeleteUser404> + | OpenAiClientError<"DeleteUser429", DeleteUser429> + > + ( + userId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteUser400", DeleteUser400> + | OpenAiClientError<"DeleteUser403", DeleteUser403> + | OpenAiClientError<"DeleteUser404", DeleteUser404> + | OpenAiClientError<"DeleteUser429", DeleteUser429> + > + } /** - * Get a list of runs for an evaluation. + * Lists the organization roles assigned to a user within the organization. */ - readonly "getEvalRuns": ( - evalId: string, - options: - | { readonly params?: typeof GetEvalRunsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listUserRoleAssignments": { + ( + userId: string, + options: { readonly params?: typeof ListUserRoleAssignmentsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListUserRoleAssignments400", ListUserRoleAssignments400> + | OpenAiClientError<"ListUserRoleAssignments403", ListUserRoleAssignments403> + | OpenAiClientError<"ListUserRoleAssignments404", ListUserRoleAssignments404> + | OpenAiClientError<"ListUserRoleAssignments429", ListUserRoleAssignments429> + > + ( + userId: string, + options: { + readonly params?: typeof ListUserRoleAssignmentsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListUserRoleAssignments400", ListUserRoleAssignments400> + | OpenAiClientError<"ListUserRoleAssignments403", ListUserRoleAssignments403> + | OpenAiClientError<"ListUserRoleAssignments404", ListUserRoleAssignments404> + | OpenAiClientError<"ListUserRoleAssignments429", ListUserRoleAssignments429> + > + } /** - * Kicks off a new run for a given evaluation, specifying the data source, and what model configuration to use to test. The datasource will be validated against the schema specified in the config of the evaluation. + * Assigns an organization role to a user within the organization. */ - readonly "createEvalRun": ( - evalId: string, - options: { readonly payload: typeof CreateEvalRunRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateEvalRun400", typeof CreateEvalRun400.Type> - > + readonly "assignUserRole": { + ( + userId: string, + options: { readonly payload: typeof AssignUserRoleRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AssignUserRole400", AssignUserRole400> + | OpenAiClientError<"AssignUserRole403", AssignUserRole403> + | OpenAiClientError<"AssignUserRole404", AssignUserRole404> + | OpenAiClientError<"AssignUserRole429", AssignUserRole429> + > + ( + userId: string, + options: { readonly payload: typeof AssignUserRoleRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AssignUserRole400", AssignUserRole400> + | OpenAiClientError<"AssignUserRole403", AssignUserRole403> + | OpenAiClientError<"AssignUserRole404", AssignUserRole404> + | OpenAiClientError<"AssignUserRole429", AssignUserRole429> + > + } /** - * Get an evaluation run by ID. + * Retrieves an organization role assigned to a user. */ - readonly "getEvalRun": ( - evalId: string, - runId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveUserRole": { + ( + userId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveUserRole400", RetrieveUserRole400> + | OpenAiClientError<"RetrieveUserRole403", RetrieveUserRole403> + | OpenAiClientError<"RetrieveUserRole404", RetrieveUserRole404> + | OpenAiClientError<"RetrieveUserRole429", RetrieveUserRole429> + > + ( + userId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveUserRole400", RetrieveUserRole400> + | OpenAiClientError<"RetrieveUserRole403", RetrieveUserRole403> + | OpenAiClientError<"RetrieveUserRole404", RetrieveUserRole404> + | OpenAiClientError<"RetrieveUserRole429", RetrieveUserRole429> + > + } /** - * Cancel an ongoing evaluation run. + * Unassigns an organization role from a user within the organization. */ - readonly "cancelEvalRun": ( - evalId: string, - runId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "unassignUserRole": { + ( + userId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UnassignUserRole400", UnassignUserRole400> + | OpenAiClientError<"UnassignUserRole403", UnassignUserRole403> + | OpenAiClientError<"UnassignUserRole404", UnassignUserRole404> + | OpenAiClientError<"UnassignUserRole429", UnassignUserRole429> + > + ( + userId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UnassignUserRole400", UnassignUserRole400> + | OpenAiClientError<"UnassignUserRole403", UnassignUserRole403> + | OpenAiClientError<"UnassignUserRole404", UnassignUserRole404> + | OpenAiClientError<"UnassignUserRole429", UnassignUserRole429> + > + } /** - * Delete an eval run. + * Lists the project roles assigned to a group within a project. */ - readonly "deleteEvalRun": ( - evalId: string, - runId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"DeleteEvalRun404", typeof DeleteEvalRun404.Type> - > + readonly "listProjectGroupRoleAssignments": { + ( + projectId: string, + groupId: string, + options: { + readonly params?: typeof ListProjectGroupRoleAssignmentsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectGroupRoleAssignments400", ListProjectGroupRoleAssignments400> + | OpenAiClientError<"ListProjectGroupRoleAssignments403", ListProjectGroupRoleAssignments403> + | OpenAiClientError<"ListProjectGroupRoleAssignments404", ListProjectGroupRoleAssignments404> + | OpenAiClientError<"ListProjectGroupRoleAssignments429", ListProjectGroupRoleAssignments429> + > + ( + projectId: string, + groupId: string, + options: { + readonly params?: typeof ListProjectGroupRoleAssignmentsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectGroupRoleAssignments400", ListProjectGroupRoleAssignments400> + | OpenAiClientError<"ListProjectGroupRoleAssignments403", ListProjectGroupRoleAssignments403> + | OpenAiClientError<"ListProjectGroupRoleAssignments404", ListProjectGroupRoleAssignments404> + | OpenAiClientError<"ListProjectGroupRoleAssignments429", ListProjectGroupRoleAssignments429> + > + } /** - * Get a list of output items for an evaluation run. + * Assigns a project role to a group within a project. */ - readonly "getEvalRunOutputItems": ( - evalId: string, - runId: string, - options: { - readonly params?: typeof GetEvalRunOutputItemsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "assignProjectGroupRole": { + ( + projectId: string, + groupId: string, + options: { readonly payload: typeof AssignProjectGroupRoleRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AssignProjectGroupRole400", AssignProjectGroupRole400> + | OpenAiClientError<"AssignProjectGroupRole403", AssignProjectGroupRole403> + | OpenAiClientError<"AssignProjectGroupRole404", AssignProjectGroupRole404> + | OpenAiClientError<"AssignProjectGroupRole429", AssignProjectGroupRole429> + > + ( + projectId: string, + groupId: string, + options: { + readonly payload: typeof AssignProjectGroupRoleRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AssignProjectGroupRole400", AssignProjectGroupRole400> + | OpenAiClientError<"AssignProjectGroupRole403", AssignProjectGroupRole403> + | OpenAiClientError<"AssignProjectGroupRole404", AssignProjectGroupRole404> + | OpenAiClientError<"AssignProjectGroupRole429", AssignProjectGroupRole429> + > + } /** - * Get an evaluation run output item by ID. + * Retrieves a project role assigned to a group. */ - readonly "getEvalRunOutputItem": ( - evalId: string, - runId: string, - outputItemId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveProjectGroupRole": { + ( + projectId: string, + groupId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectGroupRole400", RetrieveProjectGroupRole400> + | OpenAiClientError<"RetrieveProjectGroupRole403", RetrieveProjectGroupRole403> + | OpenAiClientError<"RetrieveProjectGroupRole404", RetrieveProjectGroupRole404> + | OpenAiClientError<"RetrieveProjectGroupRole429", RetrieveProjectGroupRole429> + > + ( + projectId: string, + groupId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectGroupRole400", RetrieveProjectGroupRole400> + | OpenAiClientError<"RetrieveProjectGroupRole403", RetrieveProjectGroupRole403> + | OpenAiClientError<"RetrieveProjectGroupRole404", RetrieveProjectGroupRole404> + | OpenAiClientError<"RetrieveProjectGroupRole429", RetrieveProjectGroupRole429> + > + } /** - * Returns a list of files. + * Unassigns a project role from a group within a project. */ - readonly "listFiles": ( - options: - | { readonly params?: typeof ListFilesParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "unassignProjectGroupRole": { + ( + projectId: string, + groupId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UnassignProjectGroupRole400", UnassignProjectGroupRole400> + | OpenAiClientError<"UnassignProjectGroupRole403", UnassignProjectGroupRole403> + | OpenAiClientError<"UnassignProjectGroupRole404", UnassignProjectGroupRole404> + | OpenAiClientError<"UnassignProjectGroupRole429", UnassignProjectGroupRole429> + > + ( + projectId: string, + groupId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UnassignProjectGroupRole400", UnassignProjectGroupRole400> + | OpenAiClientError<"UnassignProjectGroupRole403", UnassignProjectGroupRole403> + | OpenAiClientError<"UnassignProjectGroupRole404", UnassignProjectGroupRole404> + | OpenAiClientError<"UnassignProjectGroupRole429", UnassignProjectGroupRole429> + > + } /** - * Upload a file that can be used across various endpoints. Individual files - * can be up to 512 MB, and each project can store up to 2.5 TB of files in - * total. There is no organization-wide storage limit. Uploads to this - * endpoint are rate-limited to 1,000 requests per minute per authenticated - * user. - * - * - The Assistants API supports files up to 2 million tokens and of specific - * file types. See the [Assistants Tools guide](/docs/assistants/tools) for - * details. - * - The Fine-tuning API only supports `.jsonl` files. The input also has - * certain required formats for fine-tuning - * [chat](/docs/api-reference/fine-tuning/chat-input) or - * [completions](/docs/api-reference/fine-tuning/completions-input) models. - * - The Batch API only supports `.jsonl` files up to 200 MB in size. The input - * also has a specific required - * [format](/docs/api-reference/batch/request-input). - * - For Retrieval or `file_search` ingestion, upload files here first. If - * you need to attach multiple uploaded files to the same vector store, use - * [`/vector_stores/{vector_store_id}/file_batches`](/docs/api-reference/vector-stores-file-batches/createBatch) - * instead of attaching them one by one. Vector store attachment has separate - * limits from file upload, including 2,000 attached files per minute per - * organization. - * - * Please [contact us](https://help.openai.com/) if you need to increase these - * storage limits. + * Lists the roles configured for a project. */ - readonly "createFile": ( - options: { readonly payload: typeof CreateFileRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listProjectRoles": { + ( + projectId: string, + options: { readonly params?: typeof ListProjectRolesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectRoles400", ListProjectRoles400> + | OpenAiClientError<"ListProjectRoles403", ListProjectRoles403> + | OpenAiClientError<"ListProjectRoles404", ListProjectRoles404> + | OpenAiClientError<"ListProjectRoles429", ListProjectRoles429> + > + ( + projectId: string, + options: { + readonly params?: typeof ListProjectRolesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectRoles400", ListProjectRoles400> + | OpenAiClientError<"ListProjectRoles403", ListProjectRoles403> + | OpenAiClientError<"ListProjectRoles404", ListProjectRoles404> + | OpenAiClientError<"ListProjectRoles429", ListProjectRoles429> + > + } /** - * Returns information about a specific file. + * Creates a custom role for a project. */ - readonly "retrieveFile": ( - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createProjectRole": { + ( + projectId: string, + options: { readonly payload: typeof CreateProjectRoleRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProjectRole400", CreateProjectRole400> + | OpenAiClientError<"CreateProjectRole403", CreateProjectRole403> + | OpenAiClientError<"CreateProjectRole404", CreateProjectRole404> + | OpenAiClientError<"CreateProjectRole429", CreateProjectRole429> + > + ( + projectId: string, + options: { readonly payload: typeof CreateProjectRoleRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateProjectRole400", CreateProjectRole400> + | OpenAiClientError<"CreateProjectRole403", CreateProjectRole403> + | OpenAiClientError<"CreateProjectRole404", CreateProjectRole404> + | OpenAiClientError<"CreateProjectRole429", CreateProjectRole429> + > + } /** - * Delete a file and remove it from all vector stores. + * Retrieves a project role. */ - readonly "deleteFile": ( - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveProjectRole": { + ( + projectId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectRole403", RetrieveProjectRole403> + | OpenAiClientError<"RetrieveProjectRole404", RetrieveProjectRole404> + | OpenAiClientError<"RetrieveProjectRole429", RetrieveProjectRole429> + > + ( + projectId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectRole403", RetrieveProjectRole403> + | OpenAiClientError<"RetrieveProjectRole404", RetrieveProjectRole404> + | OpenAiClientError<"RetrieveProjectRole429", RetrieveProjectRole429> + > + } /** - * Returns the contents of the specified file. + * Updates an existing project role. */ - readonly "downloadFile": ( - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateProjectRole": { + ( + projectId: string, + roleId: string, + options: { readonly payload: typeof UpdateProjectRoleRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectRole400", UpdateProjectRole400> + | OpenAiClientError<"UpdateProjectRole403", UpdateProjectRole403> + | OpenAiClientError<"UpdateProjectRole404", UpdateProjectRole404> + | OpenAiClientError<"UpdateProjectRole429", UpdateProjectRole429> + > + ( + projectId: string, + roleId: string, + options: { readonly payload: typeof UpdateProjectRoleRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateProjectRole400", UpdateProjectRole400> + | OpenAiClientError<"UpdateProjectRole403", UpdateProjectRole403> + | OpenAiClientError<"UpdateProjectRole404", UpdateProjectRole404> + | OpenAiClientError<"UpdateProjectRole429", UpdateProjectRole429> + > + } /** - * Run a grader. + * Deletes a custom role from a project. */ - readonly "runGrader": ( - options: { readonly payload: typeof RunGraderRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteProjectRole": { + ( + projectId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectRole400", DeleteProjectRole400> + | OpenAiClientError<"DeleteProjectRole403", DeleteProjectRole403> + | OpenAiClientError<"DeleteProjectRole404", DeleteProjectRole404> + | OpenAiClientError<"DeleteProjectRole429", DeleteProjectRole429> + > + ( + projectId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteProjectRole400", DeleteProjectRole400> + | OpenAiClientError<"DeleteProjectRole403", DeleteProjectRole403> + | OpenAiClientError<"DeleteProjectRole404", DeleteProjectRole404> + | OpenAiClientError<"DeleteProjectRole429", DeleteProjectRole429> + > + } /** - * Validate a grader. + * Lists the project roles assigned to a user within a project. */ - readonly "validateGrader": ( - options: { readonly payload: typeof ValidateGraderRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listProjectUserRoleAssignments": { + ( + projectId: string, + userId: string, + options: { + readonly params?: typeof ListProjectUserRoleAssignmentsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectUserRoleAssignments400", ListProjectUserRoleAssignments400> + | OpenAiClientError<"ListProjectUserRoleAssignments403", ListProjectUserRoleAssignments403> + | OpenAiClientError<"ListProjectUserRoleAssignments404", ListProjectUserRoleAssignments404> + | OpenAiClientError<"ListProjectUserRoleAssignments429", ListProjectUserRoleAssignments429> + > + ( + projectId: string, + userId: string, + options: { + readonly params?: typeof ListProjectUserRoleAssignmentsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListProjectUserRoleAssignments400", ListProjectUserRoleAssignments400> + | OpenAiClientError<"ListProjectUserRoleAssignments403", ListProjectUserRoleAssignments403> + | OpenAiClientError<"ListProjectUserRoleAssignments404", ListProjectUserRoleAssignments404> + | OpenAiClientError<"ListProjectUserRoleAssignments429", ListProjectUserRoleAssignments429> + > + } /** - * **NOTE:** This endpoint requires an [admin API key](../admin-api-keys). - * - * Organization owners can use this endpoint to view all permissions for a fine-tuned model checkpoint. + * Assigns a project role to a user within a project. */ - readonly "listFineTuningCheckpointPermissions": ( - fineTunedModelCheckpoint: string, - options: { - readonly params?: typeof ListFineTuningCheckpointPermissionsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "assignProjectUserRole": { + ( + projectId: string, + userId: string, + options: { readonly payload: typeof AssignProjectUserRoleRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AssignProjectUserRole400", AssignProjectUserRole400> + | OpenAiClientError<"AssignProjectUserRole403", AssignProjectUserRole403> + | OpenAiClientError<"AssignProjectUserRole404", AssignProjectUserRole404> + | OpenAiClientError<"AssignProjectUserRole429", AssignProjectUserRole429> + > + ( + projectId: string, + userId: string, + options: { + readonly payload: typeof AssignProjectUserRoleRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AssignProjectUserRole400", AssignProjectUserRole400> + | OpenAiClientError<"AssignProjectUserRole403", AssignProjectUserRole403> + | OpenAiClientError<"AssignProjectUserRole404", AssignProjectUserRole404> + | OpenAiClientError<"AssignProjectUserRole429", AssignProjectUserRole429> + > + } /** - * **NOTE:** Calling this endpoint requires an [admin API key](../admin-api-keys). - * - * This enables organization owners to share fine-tuned models with other projects in their organization. + * Retrieves a project role assigned to a user. */ - readonly "createFineTuningCheckpointPermission": ( - fineTunedModelCheckpoint: string, - options: { - readonly payload: typeof CreateFineTuningCheckpointPermissionRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveProjectUserRole": { + ( + projectId: string, + userId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectUserRole400", RetrieveProjectUserRole400> + | OpenAiClientError<"RetrieveProjectUserRole403", RetrieveProjectUserRole403> + | OpenAiClientError<"RetrieveProjectUserRole404", RetrieveProjectUserRole404> + | OpenAiClientError<"RetrieveProjectUserRole429", RetrieveProjectUserRole429> + > + ( + projectId: string, + userId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveProjectUserRole400", RetrieveProjectUserRole400> + | OpenAiClientError<"RetrieveProjectUserRole403", RetrieveProjectUserRole403> + | OpenAiClientError<"RetrieveProjectUserRole404", RetrieveProjectUserRole404> + | OpenAiClientError<"RetrieveProjectUserRole429", RetrieveProjectUserRole429> + > + } /** - * **NOTE:** This endpoint requires an [admin API key](../admin-api-keys). - * - * Organization owners can use this endpoint to delete a permission for a fine-tuned model checkpoint. + * Unassigns a project role from a user within a project. */ - readonly "deleteFineTuningCheckpointPermission": ( - fineTunedModelCheckpoint: string, - permissionId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "unassignProjectUserRole": { + ( + projectId: string, + userId: string, + roleId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UnassignProjectUserRole400", UnassignProjectUserRole400> + | OpenAiClientError<"UnassignProjectUserRole403", UnassignProjectUserRole403> + | OpenAiClientError<"UnassignProjectUserRole404", UnassignProjectUserRole404> + | OpenAiClientError<"UnassignProjectUserRole429", UnassignProjectUserRole429> + > + ( + projectId: string, + userId: string, + roleId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UnassignProjectUserRole400", UnassignProjectUserRole400> + | OpenAiClientError<"UnassignProjectUserRole403", UnassignProjectUserRole403> + | OpenAiClientError<"UnassignProjectUserRole404", UnassignProjectUserRole404> + | OpenAiClientError<"UnassignProjectUserRole429", UnassignProjectUserRole429> + > + } /** - * List your organization's fine-tuning jobs + * Create a new Realtime API call over WebRTC and receive the SDP answer needed + * to complete the peer connection. */ - readonly "listPaginatedFineTuningJobs": ( - options: { - readonly params?: typeof ListPaginatedFineTuningJobsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createRealtimeCall": { + ( + options: { readonly payload: typeof CreateRealtimeCallRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect, HttpClientError.HttpClientError | SchemaError> + ( + options: { + readonly payload: typeof CreateRealtimeCallRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect, HttpClientError.HttpClientError | SchemaError> + } /** - * Creates a fine-tuning job which begins the process of creating a new model from a given dataset. - * - * Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - * - * [Learn more about fine-tuning](/docs/guides/model-optimization) + * Accept an incoming SIP call and configure the realtime session that will + * handle it. */ - readonly "createFineTuningJob": ( - options: { readonly payload: typeof CreateFineTuningJobRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Get info about a fine-tuning job. - * - * [Learn more about fine-tuning](/docs/guides/model-optimization) - */ - readonly "retrieveFineTuningJob": ( - fineTuningJobId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "acceptRealtimeCall": { + ( + callId: string, + options: { readonly payload: typeof AcceptRealtimeCallRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AcceptRealtimeCall404", AcceptRealtimeCall404> + | OpenAiClientError<"AcceptRealtimeCall409", AcceptRealtimeCall409> + > + ( + callId: string, + options: { readonly payload: typeof AcceptRealtimeCallRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AcceptRealtimeCall404", AcceptRealtimeCall404> + | OpenAiClientError<"AcceptRealtimeCall409", AcceptRealtimeCall409> + > + } /** - * Immediately cancel a fine-tune job. + * End an active Realtime API call, whether it was initiated over SIP or + * WebRTC. */ - readonly "cancelFineTuningJob": ( - fineTuningJobId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "hangupRealtimeCall": { + ( + callId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"HangupRealtimeCall404", HangupRealtimeCall404> + > + ( + callId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"HangupRealtimeCall404", HangupRealtimeCall404> + > + } /** - * List checkpoints for a fine-tuning job. + * Transfer an active SIP call to a new destination using the SIP REFER verb. */ - readonly "listFineTuningJobCheckpoints": ( - fineTuningJobId: string, - options: { - readonly params?: typeof ListFineTuningJobCheckpointsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "referRealtimeCall": { + ( + callId: string, + options: { readonly payload: typeof ReferRealtimeCallRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ReferRealtimeCall404", ReferRealtimeCall404> + > + ( + callId: string, + options: { readonly payload: typeof ReferRealtimeCallRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ReferRealtimeCall404", ReferRealtimeCall404> + > + } /** - * Get status updates for a fine-tuning job. + * Decline an incoming SIP call by returning a SIP status code to the caller. */ - readonly "listFineTuningEvents": ( - fineTuningJobId: string, - options: { - readonly params?: typeof ListFineTuningEventsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "rejectRealtimeCall": { + ( + callId: string, + options: { readonly payload: typeof RejectRealtimeCallRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RejectRealtimeCall404", RejectRealtimeCall404> + | OpenAiClientError<"RejectRealtimeCall409", RejectRealtimeCall409> + > + ( + callId: string, + options: { readonly payload: typeof RejectRealtimeCallRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RejectRealtimeCall404", RejectRealtimeCall404> + | OpenAiClientError<"RejectRealtimeCall409", RejectRealtimeCall409> + > + } /** - * Pause a fine-tune job. + * Create a Realtime client secret with an associated session configuration. + * + * Client secrets are short-lived tokens that can be passed to a client app, + * such as a web frontend or mobile client, which grants access to the Realtime API without + * leaking your main API key. You can configure a custom TTL for each client secret. + * + * You can also attach session configuration options to the client secret, which will be + * applied to any sessions created using that client secret, but these can also be overridden + * by the client connection. + * + * [Learn more about authentication with client secrets over WebRTC](https://developers.openai.com/api/docs/guides/realtime-webrtc). + * + * Returns the created client secret and the effective session object. The client secret is a string that looks like `ek_1234`. */ - readonly "pauseFineTuningJob": ( - fineTuningJobId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createRealtimeClientSecret": { + ( + options: { readonly payload: typeof CreateRealtimeClientSecretRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateRealtimeClientSecret400", CreateRealtimeClientSecret400> + | OpenAiClientError<"CreateRealtimeClientSecret404", CreateRealtimeClientSecret404> + | OpenAiClientError<"CreateRealtimeClientSecret500", CreateRealtimeClientSecret500> + > + ( + options: { + readonly payload: typeof CreateRealtimeClientSecretRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateRealtimeClientSecret400", CreateRealtimeClientSecret400> + | OpenAiClientError<"CreateRealtimeClientSecret404", CreateRealtimeClientSecret404> + | OpenAiClientError<"CreateRealtimeClientSecret500", CreateRealtimeClientSecret500> + > + } /** - * Resume a fine-tune job. + * Create an ephemeral API token for use in client-side applications with the + * Realtime API. Can be configured with the same session parameters as the + * `session.update` client event. + * + * It responds with a session object, plus a `client_secret` key which contains + * a usable ephemeral API token that can be used to authenticate browser clients + * for the Realtime API. + * + * Returns the created Realtime session object, plus an ephemeral key. */ - readonly "resumeFineTuningJob": ( - fineTuningJobId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createRealtimeSession": { + ( + options: { readonly payload: typeof CreateRealtimeSessionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError + > + ( + options: { + readonly payload: typeof CreateRealtimeSessionRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError + > + } /** - * You can call this endpoint with either: + * Create an ephemeral API token for use in client-side applications with the + * Realtime API specifically for realtime transcriptions. + * Can be configured with the same session parameters as the `transcription_session.update` client event. * - * - `multipart/form-data`: use binary uploads via `image` (and optional `mask`). - * - `application/json`: use `images` (and optional `mask`) as references with either `image_url` or `file_id`. + * It responds with a session object, plus a `client_secret` key which contains + * a usable ephemeral API token that can be used to authenticate browser clients + * for the Realtime API. * - * Note that JSON requests use `images` (array) instead of the multipart `image` field. + * Returns the created Realtime transcription session object, plus an ephemeral key. */ - readonly "createImageEdit": ( - options: { readonly payload: typeof CreateImageEditRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createRealtimeTranscriptionSession": { + ( + options: { + readonly payload: typeof CreateRealtimeTranscriptionSessionRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError + > + ( + options: { + readonly payload: typeof CreateRealtimeTranscriptionSessionRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError + > + } /** - * You can call this endpoint with either: + * Create a Realtime translation client secret with an associated translation session configuration. * - * - `multipart/form-data`: use binary uploads via `image` (and optional `mask`). - * - `application/json`: use `images` (and optional `mask`) as references with either `image_url` or `file_id`. + * Client secrets are short-lived tokens that can be passed to a client app, + * such as a web frontend or mobile client, which grants access to the Realtime + * Translation API without leaking your main API key. You can configure a custom + * TTL for each client secret. * - * Note that JSON requests use `images` (array) instead of the multipart `image` field. + * Returns the created client secret and the effective translation session object. + * The client secret is a string that looks like `ek_1234`. */ - readonly "createImageEditSse": ( - options: { readonly payload: typeof CreateImageEditRequestFormData.Encoded } - ) => Stream.Stream< - { readonly event: string; readonly id: string | undefined; readonly data: typeof CreateImageEdit200Sse.Type }, - HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, - typeof CreateImageEdit200Sse.DecodingServices - > + readonly "createRealtimeTranslationClientSecret": { + ( + options: { + readonly payload: typeof CreateRealtimeTranslationClientSecretRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateRealtimeTranslationClientSecret400", CreateRealtimeTranslationClientSecret400> + | OpenAiClientError<"CreateRealtimeTranslationClientSecret404", CreateRealtimeTranslationClientSecret404> + | OpenAiClientError<"CreateRealtimeTranslationClientSecret500", CreateRealtimeTranslationClientSecret500> + > + ( + options: { + readonly payload: typeof CreateRealtimeTranslationClientSecretRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateRealtimeTranslationClientSecret400", CreateRealtimeTranslationClientSecret400> + | OpenAiClientError<"CreateRealtimeTranslationClientSecret404", CreateRealtimeTranslationClientSecret404> + | OpenAiClientError<"CreateRealtimeTranslationClientSecret500", CreateRealtimeTranslationClientSecret500> + > + } /** - * Creates an image given a prompt. [Learn more](/docs/guides/images). + * Creates a model response. Provide [text](https://developers.openai.com/api/docs/guides/text) or + * [image](https://developers.openai.com/api/docs/guides/images-vision) inputs to generate [text](https://developers.openai.com/api/docs/guides/text) + * or [JSON](https://developers.openai.com/api/docs/guides/structured-outputs) outputs. Have the model call + * your own [custom code](https://developers.openai.com/api/docs/guides/function-calling) or use built-in + * [tools](https://developers.openai.com/api/docs/guides/tools) like [web search](https://developers.openai.com/api/docs/guides/tools-web-search) + * or [file search](https://developers.openai.com/api/docs/guides/tools-file-search) to use your own data + * as input for the model's response. */ - readonly "createImage": ( - options: { readonly payload: typeof CreateImageRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createResponse": { + ( + options: { readonly payload: typeof CreateResponseRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateResponse400", CreateResponse400> + | OpenAiClientError<"CreateResponse404", CreateResponse404> + | OpenAiClientError<"CreateResponse429", CreateResponse429> + | OpenAiClientError<"CreateResponse503", CreateResponse503> + > + ( + options: { readonly payload: typeof CreateResponseRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateResponse400", CreateResponse400> + | OpenAiClientError<"CreateResponse404", CreateResponse404> + | OpenAiClientError<"CreateResponse429", CreateResponse429> + | OpenAiClientError<"CreateResponse503", CreateResponse503> + > + } /** - * Creates an image given a prompt. [Learn more](/docs/guides/images). + * Creates a model response. Provide [text](https://developers.openai.com/api/docs/guides/text) or + * [image](https://developers.openai.com/api/docs/guides/images-vision) inputs to generate [text](https://developers.openai.com/api/docs/guides/text) + * or [JSON](https://developers.openai.com/api/docs/guides/structured-outputs) outputs. Have the model call + * your own [custom code](https://developers.openai.com/api/docs/guides/function-calling) or use built-in + * [tools](https://developers.openai.com/api/docs/guides/tools) like [web search](https://developers.openai.com/api/docs/guides/tools-web-search) + * or [file search](https://developers.openai.com/api/docs/guides/tools-file-search) to use your own data + * as input for the model's response. */ - readonly "createImageSse": ( - options: { readonly payload: typeof CreateImageRequestJson.Encoded } + readonly "createResponseSse": ( + options: { readonly payload: typeof CreateResponseRequestJson.Encoded } ) => Stream.Stream< - { readonly event: string; readonly id: string | undefined; readonly data: typeof CreateImage200Sse.Type }, + { readonly event: string; readonly id: string | undefined; readonly data: CreateResponse200Sse }, HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, - typeof CreateImage200Sse.DecodingServices - > - /** - * Creates a variation of a given image. This endpoint only supports `dall-e-2`. - */ - readonly "createImageVariation": ( - options: { - readonly payload: typeof CreateImageVariationRequestFormData.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Lists the currently available models, and provides basic information about each one such as the owner and availability. - */ - readonly "listModels": ( - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Retrieves a model instance, providing basic information about the model such as the owner and permissioning. - */ - readonly "retrieveModel": ( - model: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. - */ - readonly "deleteModel": ( - model: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Classifies if text and/or image inputs are potentially harmful. Learn - * more in the [moderation guide](/docs/guides/moderation). - */ - readonly "createModeration": ( - options: { readonly payload: typeof CreateModerationRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError + typeof CreateResponse200Sse.DecodingServices > /** - * Retrieve a paginated list of organization admin API keys. + * Retrieves a model response with the given ID. */ - readonly "adminApiKeysList": ( - options: { - readonly params?: typeof AdminApiKeysListParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getResponse": { + ( + responseId: string, + options: { readonly params?: typeof GetResponseParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetResponse404", GetResponse404> + | OpenAiClientError<"GetResponse429", GetResponse429> + > + ( + responseId: string, + options: + | { readonly params?: typeof GetResponseParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetResponse404", GetResponse404> + | OpenAiClientError<"GetResponse429", GetResponse429> + > + } /** - * Create a new admin-level API key for the organization. + * Deletes a model response with the given ID. */ - readonly "adminApiKeysCreate": ( - options: { readonly payload: typeof AdminApiKeysCreateRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteResponse": { + ( + responseId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteResponse404", DeleteResponse404> + | OpenAiClientError<"DeleteResponse429", DeleteResponse429> + > + ( + responseId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteResponse404", DeleteResponse404> + | OpenAiClientError<"DeleteResponse429", DeleteResponse429> + > + } /** - * Get details for a specific organization API key by its ID. + * Cancels a model response with the given ID. Only responses created with + * the `background` parameter set to `true` can be cancelled. + * [Learn more](https://developers.openai.com/api/docs/guides/background). */ - readonly "adminApiKeysGet": ( - keyId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "cancelResponse": { + ( + responseId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelResponse404", CancelResponse404> + | OpenAiClientError<"CancelResponse429", CancelResponse429> + > + ( + responseId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelResponse404", CancelResponse404> + | OpenAiClientError<"CancelResponse429", CancelResponse429> + > + } /** - * Delete the specified admin API key. + * Returns a list of input items for a given response. */ - readonly "adminApiKeysDelete": ( - keyId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listInputItems": { + ( + responseId: string, + options: { readonly params?: typeof ListInputItemsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListInputItems404", ListInputItems404> + | OpenAiClientError<"ListInputItems429", ListInputItems429> + > + ( + responseId: string, + options: { + readonly params?: typeof ListInputItemsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListInputItems404", ListInputItems404> + | OpenAiClientError<"ListInputItems429", ListInputItems429> + > + } /** - * List user actions and configuration changes within this organization. + * Create a thread. */ - readonly "listAuditLogs": ( - options: - | { readonly params?: typeof ListAuditLogsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createThread": { + ( + options: { readonly payload: typeof CreateThreadRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateThread429", CreateThread429> + > + ( + options: { readonly payload: typeof CreateThreadRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateThread429", CreateThread429> + > + } /** - * List uploaded certificates for this organization. + * Create a thread and run it in one request. */ - readonly "listOrganizationCertificates": ( - options: { - readonly params?: typeof ListOrganizationCertificatesParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createThreadAndRun": { + ( + options: { readonly payload: typeof CreateThreadAndRunRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateThreadAndRun429", CreateThreadAndRun429> + > + ( + options: { readonly payload: typeof CreateThreadAndRunRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateThreadAndRun429", CreateThreadAndRun429> + > + } /** - * Upload a certificate to the organization. This does **not** automatically activate the certificate. - * - * Organizations can upload up to 50 certificates. + * Create a thread and run it in one request. */ - readonly "uploadCertificate": ( - options: { readonly payload: typeof UploadCertificateRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError + readonly "createThreadAndRunSse": ( + options: { readonly payload: typeof CreateThreadAndRunRequestJson.Encoded } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: CreateThreadAndRun200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof CreateThreadAndRun200Sse.DecodingServices > /** - * Activate certificates at the organization level. - * - * You can atomically and idempotently activate up to 10 certificates at a time. + * Retrieves a thread. */ - readonly "activateOrganizationCertificates": ( - options: { - readonly payload: typeof ActivateOrganizationCertificatesRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getThread": { + ( + threadId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetThread429", GetThread429> + > + ( + threadId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetThread429", GetThread429> + > + } /** - * Deactivate certificates at the organization level. - * - * You can atomically and idempotently deactivate up to 10 certificates at a time. + * Modifies a thread. */ - readonly "deactivateOrganizationCertificates": ( - options: { - readonly payload: typeof DeactivateOrganizationCertificatesRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "modifyThread": { + ( + threadId: string, + options: { readonly payload: typeof ModifyThreadRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyThread429", ModifyThread429> + > + ( + threadId: string, + options: { readonly payload: typeof ModifyThreadRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyThread429", ModifyThread429> + > + } /** - * Get a certificate that has been uploaded to the organization. - * - * You can get a certificate regardless of whether it is active or not. + * Delete a thread. */ - readonly "getCertificate": ( - certificateId: string, - options: - | { readonly params?: typeof GetCertificateParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteThread": { + ( + threadId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"DeleteThread429", DeleteThread429> + > + ( + threadId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"DeleteThread429", DeleteThread429> + > + } /** - * Modify a certificate. Note that only the name can be modified. + * Returns a list of messages for a given thread. */ - readonly "modifyCertificate": ( - certificateId: string, - options: { readonly payload: typeof ModifyCertificateRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listMessages": { + ( + threadId: string, + options: { readonly params?: typeof ListMessagesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListMessages429", ListMessages429> + > + ( + threadId: string, + options: + | { readonly params?: typeof ListMessagesParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListMessages429", ListMessages429> + > + } /** - * Delete a certificate from the organization. - * - * The certificate must be inactive for the organization and all projects. + * Create a message. */ - readonly "deleteCertificate": ( - certificateId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createMessage": { + ( + threadId: string, + options: { readonly payload: typeof CreateMessageRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateMessage429", CreateMessage429> + > + ( + threadId: string, + options: { readonly payload: typeof CreateMessageRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateMessage429", CreateMessage429> + > + } /** - * Get costs details for the organization. + * Retrieve a message. */ - readonly "usageCosts": ( - options: { readonly params: typeof UsageCostsParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getMessage": { + ( + threadId: string, + messageId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetMessage429", GetMessage429> + > + ( + threadId: string, + messageId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetMessage429", GetMessage429> + > + } /** - * Lists all groups in the organization. + * Modifies a message. */ - readonly "listGroups": ( - options: - | { readonly params?: typeof ListGroupsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "modifyMessage": { + ( + threadId: string, + messageId: string, + options: { readonly payload: typeof ModifyMessageRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyMessage429", ModifyMessage429> + > + ( + threadId: string, + messageId: string, + options: { readonly payload: typeof ModifyMessageRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyMessage429", ModifyMessage429> + > + } /** - * Creates a new group in the organization. + * Deletes a message. */ - readonly "createGroup": ( - options: { readonly payload: typeof CreateGroupRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteMessage": { + ( + threadId: string, + messageId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"DeleteMessage429", DeleteMessage429> + > + ( + threadId: string, + messageId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"DeleteMessage429", DeleteMessage429> + > + } /** - * Updates a group's information. + * Returns a list of runs belonging to a thread. */ - readonly "updateGroup": ( - groupId: string, - options: { readonly payload: typeof UpdateGroupRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listRuns": { + ( + threadId: string, + options: { readonly params?: typeof ListRunsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListRuns429", ListRuns429> + > + ( + threadId: string, + options: + | { readonly params?: typeof ListRunsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListRuns429", ListRuns429> + > + } /** - * Deletes a group from the organization. + * Create a run. */ - readonly "deleteGroup": ( - groupId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createRun": { + ( + threadId: string, + options: { + readonly params?: typeof CreateRunParams.Encoded | undefined + readonly payload: typeof CreateRunRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateRun429", CreateRun429> + > + ( + threadId: string, + options: { + readonly params?: typeof CreateRunParams.Encoded | undefined + readonly payload: typeof CreateRunRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CreateRun429", CreateRun429> + > + } /** - * Lists the organization roles assigned to a group within the organization. + * Create a run. */ - readonly "listGroupRoleAssignments": ( - groupId: string, + readonly "createRunSse": ( + threadId: string, options: { - readonly params?: typeof ListGroupRoleAssignmentsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Assigns an organization role to a group within the organization. - */ - readonly "assignGroupRole": ( - groupId: string, - options: { readonly payload: typeof AssignGroupRoleRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Unassigns an organization role from a group within the organization. - */ - readonly "unassignGroupRole": ( - groupId: string, - roleId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Lists the users assigned to a group. - */ - readonly "listGroupUsers": ( - groupId: string, - options: - | { readonly params?: typeof ListGroupUsersParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Adds a user to a group. - */ - readonly "addGroupUser": ( - groupId: string, - options: { readonly payload: typeof AddGroupUserRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError + readonly params?: typeof CreateRunParams.Encoded | undefined + readonly payload: typeof CreateRunRequestJson.Encoded + } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: CreateRun200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof CreateRun200Sse.DecodingServices > /** - * Removes a user from a group. + * Retrieves a run. */ - readonly "removeGroupUser": ( - groupId: string, - userId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getRun": { + ( + threadId: string, + runId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetRun429", GetRun429> + > + ( + threadId: string, + runId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetRun429", GetRun429> + > + } /** - * Returns a list of invites in the organization. + * Modifies a run. */ - readonly "listInvites": ( - options: - | { readonly params?: typeof ListInvitesParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "modifyRun": { + ( + threadId: string, + runId: string, + options: { readonly payload: typeof ModifyRunRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyRun429", ModifyRun429> + > + ( + threadId: string, + runId: string, + options: { readonly payload: typeof ModifyRunRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyRun429", ModifyRun429> + > + } /** - * Create an invite for a user to the organization. The invite must be accepted by the user before they have access to the organization. + * Cancels a run that is `in_progress`. */ - readonly "inviteUser": ( - options: { readonly payload: typeof InviteUserRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "cancelRun": { + ( + threadId: string, + runId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CancelRun429", CancelRun429> + > + ( + threadId: string, + runId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"CancelRun429", CancelRun429> + > + } /** - * Retrieves an invite. + * Returns a list of run steps belonging to a run. */ - readonly "retrieveInvite": ( - inviteId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listRunSteps": { + ( + threadId: string, + runId: string, + options: { readonly params?: typeof ListRunStepsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListRunSteps429", ListRunSteps429> + > + ( + threadId: string, + runId: string, + options: + | { readonly params?: typeof ListRunStepsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ListRunSteps429", ListRunSteps429> + > + } /** - * Delete an invite. If the invite has already been accepted, it cannot be deleted. + * Retrieves a run step. */ - readonly "deleteInvite": ( - inviteId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getRunStep": { + ( + threadId: string, + runId: string, + stepId: string, + options: { readonly params?: typeof GetRunStepParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetRunStep429", GetRunStep429> + > + ( + threadId: string, + runId: string, + stepId: string, + options: + | { readonly params?: typeof GetRunStepParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"GetRunStep429", GetRunStep429> + > + } /** - * Returns a list of projects. + * When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. */ - readonly "listProjects": ( - options: - | { readonly params?: typeof ListProjectsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "submitToolOuputsToRun": { + ( + threadId: string, + runId: string, + options: { readonly payload: typeof SubmitToolOuputsToRunRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"SubmitToolOuputsToRun429", SubmitToolOuputsToRun429> + > + ( + threadId: string, + runId: string, + options: { + readonly payload: typeof SubmitToolOuputsToRunRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"SubmitToolOuputsToRun429", SubmitToolOuputsToRun429> + > + } /** - * Create a new project in the organization. Projects can be created and archived, but cannot be deleted. + * When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. */ - readonly "createProject": ( - options: { readonly payload: typeof CreateProjectRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError + readonly "submitToolOuputsToRunSse": ( + threadId: string, + runId: string, + options: { readonly payload: typeof SubmitToolOuputsToRunRequestJson.Encoded } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: SubmitToolOuputsToRun200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof SubmitToolOuputsToRun200Sse.DecodingServices > /** - * Retrieves a project. + * Creates an intermediate [Upload](https://developers.openai.com/api/reference/resources/uploads) object + * that you can add [Parts](https://developers.openai.com/api/reference/resources/uploads/subresources/parts) to. + * Currently, an Upload can accept at most 8 GB in total and expires after an + * hour after you create it. + * + * Once you complete the Upload, we will create a + * [File](https://developers.openai.com/api/reference/resources/files) object that contains all the parts + * you uploaded. This File is usable in the rest of our platform as a regular + * File object. + * + * For certain `purpose` values, the correct `mime_type` must be specified. + * Please refer to documentation for the + * [supported MIME types for your use case](https://developers.openai.com/api/docs/guides/tools-file-search#supported-files). + * + * For guidance on the proper filename extensions for each purpose, please + * follow the documentation on [creating a + * File](https://developers.openai.com/api/reference/resources/files/methods/create). + * + * Returns the Upload object with status `pending`. */ - readonly "retrieveProject": ( - projectId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createUpload": { + ( + options: { readonly payload: typeof CreateUploadRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateUpload400", CreateUpload400> + | OpenAiClientError<"CreateUpload429", CreateUpload429> + > + ( + options: { readonly payload: typeof CreateUploadRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateUpload400", CreateUpload400> + | OpenAiClientError<"CreateUpload429", CreateUpload429> + > + } /** - * Modifies a project in the organization. + * Cancels the Upload. No Parts may be added after an Upload is cancelled. + * + * Returns the Upload object with status `cancelled`. */ - readonly "modifyProject": ( - projectId: string, - options: { readonly payload: typeof ModifyProjectRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError | OpenAiClientError<"ModifyProject400", typeof ModifyProject400.Type> - > + readonly "cancelUpload": { + ( + uploadId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelUpload400", CancelUpload400> + | OpenAiClientError<"CancelUpload404", CancelUpload404> + | OpenAiClientError<"CancelUpload410", CancelUpload410> + | OpenAiClientError<"CancelUpload429", CancelUpload429> + > + ( + uploadId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelUpload400", CancelUpload400> + | OpenAiClientError<"CancelUpload404", CancelUpload404> + | OpenAiClientError<"CancelUpload410", CancelUpload410> + | OpenAiClientError<"CancelUpload429", CancelUpload429> + > + } /** - * Returns a list of API keys in the project. + * Completes the [Upload](https://developers.openai.com/api/reference/resources/uploads). + * + * Within the returned Upload object, there is a nested [File](https://developers.openai.com/api/reference/resources/files) object that is ready to use in the rest of the platform. + * + * You can specify the order of the Parts by passing in an ordered list of the Part IDs. + * + * The number of bytes uploaded upon completion must match the number of bytes initially specified when creating the Upload object. No Parts may be added after an Upload is completed. + * Returns the Upload object with status `completed`, including an additional `file` property containing the created usable File object. */ - readonly "listProjectApiKeys": ( - projectId: string, - options: { - readonly params?: typeof ListProjectApiKeysParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "completeUpload": { + ( + uploadId: string, + options: { readonly payload: typeof CompleteUploadRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CompleteUpload400", CompleteUpload400> + | OpenAiClientError<"CompleteUpload404", CompleteUpload404> + | OpenAiClientError<"CompleteUpload410", CompleteUpload410> + | OpenAiClientError<"CompleteUpload429", CompleteUpload429> + | OpenAiClientError<"CompleteUpload500", CompleteUpload500> + > + ( + uploadId: string, + options: { readonly payload: typeof CompleteUploadRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CompleteUpload400", CompleteUpload400> + | OpenAiClientError<"CompleteUpload404", CompleteUpload404> + | OpenAiClientError<"CompleteUpload410", CompleteUpload410> + | OpenAiClientError<"CompleteUpload429", CompleteUpload429> + | OpenAiClientError<"CompleteUpload500", CompleteUpload500> + > + } /** - * Retrieves an API key in the project. + * Adds a [Part](https://developers.openai.com/api/reference/resources/uploads/subresources/parts) to an [Upload](https://developers.openai.com/api/reference/resources/uploads) object. A Part represents a chunk of bytes from the file you are trying to upload. + * + * Each Part can be at most 64 MB, and you can add Parts until you hit the Upload maximum of 8 GB. + * + * It is possible to add multiple Parts in parallel. You can decide the intended order of the Parts when you [complete the Upload](https://developers.openai.com/api/reference/resources/uploads/methods/complete). */ - readonly "retrieveProjectApiKey": ( - projectId: string, - apiKeyId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "addUploadPart": { + ( + uploadId: string, + options: { readonly payload: typeof AddUploadPartRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AddUploadPart400", AddUploadPart400> + | OpenAiClientError<"AddUploadPart404", AddUploadPart404> + | OpenAiClientError<"AddUploadPart410", AddUploadPart410> + | OpenAiClientError<"AddUploadPart429", AddUploadPart429> + | OpenAiClientError<"AddUploadPart500", AddUploadPart500> + > + ( + uploadId: string, + options: { readonly payload: typeof AddUploadPartRequestFormData.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"AddUploadPart400", AddUploadPart400> + | OpenAiClientError<"AddUploadPart404", AddUploadPart404> + | OpenAiClientError<"AddUploadPart410", AddUploadPart410> + | OpenAiClientError<"AddUploadPart429", AddUploadPart429> + | OpenAiClientError<"AddUploadPart500", AddUploadPart500> + > + } /** - * Deletes an API key from the project. - * - * Returns confirmation of the key deletion, or an error if the key belonged to - * a service account. + * Returns a list of vector stores. */ - readonly "deleteProjectApiKey": ( - projectId: string, - apiKeyId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"DeleteProjectApiKey400", typeof DeleteProjectApiKey400.Type> - > + readonly "listVectorStores": { + ( + options: { readonly params?: typeof ListVectorStoresParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVectorStores429", ListVectorStores429> + | OpenAiClientError<"ListVectorStores503", ListVectorStores503> + > + ( + options: { + readonly params?: typeof ListVectorStoresParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVectorStores429", ListVectorStores429> + | OpenAiClientError<"ListVectorStores503", ListVectorStores503> + > + } /** - * Archives a project in the organization. Archived projects cannot be used or updated. + * Create a vector store. */ - readonly "archiveProject": ( - projectId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createVectorStore": { + ( + options: { readonly payload: typeof CreateVectorStoreRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVectorStore400", CreateVectorStore400> + | OpenAiClientError<"CreateVectorStore404", CreateVectorStore404> + | OpenAiClientError<"CreateVectorStore429", CreateVectorStore429> + > + ( + options: { readonly payload: typeof CreateVectorStoreRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVectorStore400", CreateVectorStore400> + | OpenAiClientError<"CreateVectorStore404", CreateVectorStore404> + | OpenAiClientError<"CreateVectorStore429", CreateVectorStore429> + > + } /** - * List certificates for this project. + * Retrieves a vector store. */ - readonly "listProjectCertificates": ( - projectId: string, - options: { - readonly params?: typeof ListProjectCertificatesParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getVectorStore": { + ( + vectorStoreId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVectorStore404", GetVectorStore404> + | OpenAiClientError<"GetVectorStore429", GetVectorStore429> + > + ( + vectorStoreId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVectorStore404", GetVectorStore404> + | OpenAiClientError<"GetVectorStore429", GetVectorStore429> + > + } /** - * Activate certificates at the project level. - * - * You can atomically and idempotently activate up to 10 certificates at a time. + * Modifies a vector store. */ - readonly "activateProjectCertificates": ( - projectId: string, - options: { - readonly payload: typeof ActivateProjectCertificatesRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "modifyVectorStore": { + ( + vectorStoreId: string, + options: { readonly payload: typeof ModifyVectorStoreRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyVectorStore400", ModifyVectorStore400> + | OpenAiClientError<"ModifyVectorStore403", ModifyVectorStore403> + | OpenAiClientError<"ModifyVectorStore404", ModifyVectorStore404> + | OpenAiClientError<"ModifyVectorStore429", ModifyVectorStore429> + > + ( + vectorStoreId: string, + options: { readonly payload: typeof ModifyVectorStoreRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ModifyVectorStore400", ModifyVectorStore400> + | OpenAiClientError<"ModifyVectorStore403", ModifyVectorStore403> + | OpenAiClientError<"ModifyVectorStore404", ModifyVectorStore404> + | OpenAiClientError<"ModifyVectorStore429", ModifyVectorStore429> + > + } /** - * Deactivate certificates at the project level. You can atomically and - * idempotently deactivate up to 10 certificates at a time. + * Delete a vector store. */ - readonly "deactivateProjectCertificates": ( - projectId: string, - options: { - readonly payload: typeof DeactivateProjectCertificatesRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteVectorStore": { + ( + vectorStoreId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVectorStore404", DeleteVectorStore404> + | OpenAiClientError<"DeleteVectorStore409", DeleteVectorStore409> + | OpenAiClientError<"DeleteVectorStore429", DeleteVectorStore429> + > + ( + vectorStoreId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVectorStore404", DeleteVectorStore404> + | OpenAiClientError<"DeleteVectorStore409", DeleteVectorStore409> + | OpenAiClientError<"DeleteVectorStore429", DeleteVectorStore429> + > + } /** - * Lists the groups that have access to a project. + * Create a vector store file batch. */ - readonly "listProjectGroups": ( - projectId: string, - options: { - readonly params?: typeof ListProjectGroupsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createVectorStoreFileBatch": { + ( + vectorStoreId: string, + options: { readonly payload: typeof CreateVectorStoreFileBatchRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVectorStoreFileBatch400", CreateVectorStoreFileBatch400> + | OpenAiClientError<"CreateVectorStoreFileBatch404", CreateVectorStoreFileBatch404> + | OpenAiClientError<"CreateVectorStoreFileBatch409", CreateVectorStoreFileBatch409> + | OpenAiClientError<"CreateVectorStoreFileBatch429", CreateVectorStoreFileBatch429> + | OpenAiClientError<"CreateVectorStoreFileBatch500", CreateVectorStoreFileBatch500> + > + ( + vectorStoreId: string, + options: { + readonly payload: typeof CreateVectorStoreFileBatchRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVectorStoreFileBatch400", CreateVectorStoreFileBatch400> + | OpenAiClientError<"CreateVectorStoreFileBatch404", CreateVectorStoreFileBatch404> + | OpenAiClientError<"CreateVectorStoreFileBatch409", CreateVectorStoreFileBatch409> + | OpenAiClientError<"CreateVectorStoreFileBatch429", CreateVectorStoreFileBatch429> + | OpenAiClientError<"CreateVectorStoreFileBatch500", CreateVectorStoreFileBatch500> + > + } /** - * Grants a group access to a project. + * Retrieves a vector store file batch. */ - readonly "addProjectGroup": ( - projectId: string, - options: { readonly payload: typeof AddProjectGroupRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getVectorStoreFileBatch": { + ( + vectorStoreId: string, + batchId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVectorStoreFileBatch400", GetVectorStoreFileBatch400> + | OpenAiClientError<"GetVectorStoreFileBatch404", GetVectorStoreFileBatch404> + | OpenAiClientError<"GetVectorStoreFileBatch429", GetVectorStoreFileBatch429> + > + ( + vectorStoreId: string, + batchId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVectorStoreFileBatch400", GetVectorStoreFileBatch400> + | OpenAiClientError<"GetVectorStoreFileBatch404", GetVectorStoreFileBatch404> + | OpenAiClientError<"GetVectorStoreFileBatch429", GetVectorStoreFileBatch429> + > + } /** - * Revokes a group's access to a project. + * Cancel a vector store file batch. This attempts to cancel the processing of files in this batch as soon as possible. */ - readonly "removeProjectGroup": ( - projectId: string, - groupId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "cancelVectorStoreFileBatch": { + ( + vectorStoreId: string, + batchId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelVectorStoreFileBatch400", CancelVectorStoreFileBatch400> + | OpenAiClientError<"CancelVectorStoreFileBatch404", CancelVectorStoreFileBatch404> + | OpenAiClientError<"CancelVectorStoreFileBatch409", CancelVectorStoreFileBatch409> + | OpenAiClientError<"CancelVectorStoreFileBatch429", CancelVectorStoreFileBatch429> + > + ( + vectorStoreId: string, + batchId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelVectorStoreFileBatch400", CancelVectorStoreFileBatch400> + | OpenAiClientError<"CancelVectorStoreFileBatch404", CancelVectorStoreFileBatch404> + | OpenAiClientError<"CancelVectorStoreFileBatch409", CancelVectorStoreFileBatch409> + | OpenAiClientError<"CancelVectorStoreFileBatch429", CancelVectorStoreFileBatch429> + > + } /** - * Returns hosted tool permissions for a project. + * Returns a list of vector store files in a batch. */ - readonly "retrieveProjectHostedToolPermissions": ( - projectId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listFilesInVectorStoreBatch": { + ( + vectorStoreId: string, + batchId: string, + options: { + readonly params?: typeof ListFilesInVectorStoreBatchParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFilesInVectorStoreBatch400", ListFilesInVectorStoreBatch400> + | OpenAiClientError<"ListFilesInVectorStoreBatch404", ListFilesInVectorStoreBatch404> + | OpenAiClientError<"ListFilesInVectorStoreBatch429", ListFilesInVectorStoreBatch429> + > + ( + vectorStoreId: string, + batchId: string, + options: { + readonly params?: typeof ListFilesInVectorStoreBatchParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListFilesInVectorStoreBatch400", ListFilesInVectorStoreBatch400> + | OpenAiClientError<"ListFilesInVectorStoreBatch404", ListFilesInVectorStoreBatch404> + | OpenAiClientError<"ListFilesInVectorStoreBatch429", ListFilesInVectorStoreBatch429> + > + } /** - * Updates hosted tool permissions for a project. + * Returns a list of vector store files. */ - readonly "updateProjectHostedToolPermissions": ( - projectId: string, - options: { - readonly payload: typeof UpdateProjectHostedToolPermissionsRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listVectorStoreFiles": { + ( + vectorStoreId: string, + options: { readonly params?: typeof ListVectorStoreFilesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVectorStoreFiles400", ListVectorStoreFiles400> + | OpenAiClientError<"ListVectorStoreFiles404", ListVectorStoreFiles404> + | OpenAiClientError<"ListVectorStoreFiles429", ListVectorStoreFiles429> + > + ( + vectorStoreId: string, + options: { + readonly params?: typeof ListVectorStoreFilesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVectorStoreFiles400", ListVectorStoreFiles400> + | OpenAiClientError<"ListVectorStoreFiles404", ListVectorStoreFiles404> + | OpenAiClientError<"ListVectorStoreFiles429", ListVectorStoreFiles429> + > + } /** - * Returns model permissions for a project. + * Create a vector store file by attaching a [File](https://developers.openai.com/api/reference/resources/files) to a [vector store](https://developers.openai.com/api/reference/resources/vector_stores). */ - readonly "retrieveProjectModelPermissions": ( - projectId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createVectorStoreFile": { + ( + vectorStoreId: string, + options: { readonly payload: typeof CreateVectorStoreFileRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVectorStoreFile400", CreateVectorStoreFile400> + | OpenAiClientError<"CreateVectorStoreFile404", CreateVectorStoreFile404> + | OpenAiClientError<"CreateVectorStoreFile409", CreateVectorStoreFile409> + | OpenAiClientError<"CreateVectorStoreFile429", CreateVectorStoreFile429> + | OpenAiClientError<"CreateVectorStoreFile500", CreateVectorStoreFile500> + > + ( + vectorStoreId: string, + options: { + readonly payload: typeof CreateVectorStoreFileRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVectorStoreFile400", CreateVectorStoreFile400> + | OpenAiClientError<"CreateVectorStoreFile404", CreateVectorStoreFile404> + | OpenAiClientError<"CreateVectorStoreFile409", CreateVectorStoreFile409> + | OpenAiClientError<"CreateVectorStoreFile429", CreateVectorStoreFile429> + | OpenAiClientError<"CreateVectorStoreFile500", CreateVectorStoreFile500> + > + } /** - * Updates model permissions for a project. + * Retrieves a vector store file. */ - readonly "updateProjectModelPermissions": ( - projectId: string, - options: { - readonly payload: typeof UpdateProjectModelPermissionsRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getVectorStoreFile": { + ( + vectorStoreId: string, + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVectorStoreFile404", GetVectorStoreFile404> + | OpenAiClientError<"GetVectorStoreFile429", GetVectorStoreFile429> + | OpenAiClientError<"GetVectorStoreFile500", GetVectorStoreFile500> + > + ( + vectorStoreId: string, + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVectorStoreFile404", GetVectorStoreFile404> + | OpenAiClientError<"GetVectorStoreFile429", GetVectorStoreFile429> + | OpenAiClientError<"GetVectorStoreFile500", GetVectorStoreFile500> + > + } /** - * Deletes model permissions for a project. + * Update attributes on a vector store file. */ - readonly "deleteProjectModelPermissions": ( - projectId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateVectorStoreFileAttributes": { + ( + vectorStoreId: string, + fileId: string, + options: { readonly payload: typeof UpdateVectorStoreFileAttributesRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateVectorStoreFileAttributes400", UpdateVectorStoreFileAttributes400> + | OpenAiClientError<"UpdateVectorStoreFileAttributes404", UpdateVectorStoreFileAttributes404> + | OpenAiClientError<"UpdateVectorStoreFileAttributes409", UpdateVectorStoreFileAttributes409> + | OpenAiClientError<"UpdateVectorStoreFileAttributes429", UpdateVectorStoreFileAttributes429> + | OpenAiClientError<"UpdateVectorStoreFileAttributes500", UpdateVectorStoreFileAttributes500> + > + ( + vectorStoreId: string, + fileId: string, + options: { + readonly payload: typeof UpdateVectorStoreFileAttributesRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateVectorStoreFileAttributes400", UpdateVectorStoreFileAttributes400> + | OpenAiClientError<"UpdateVectorStoreFileAttributes404", UpdateVectorStoreFileAttributes404> + | OpenAiClientError<"UpdateVectorStoreFileAttributes409", UpdateVectorStoreFileAttributes409> + | OpenAiClientError<"UpdateVectorStoreFileAttributes429", UpdateVectorStoreFileAttributes429> + | OpenAiClientError<"UpdateVectorStoreFileAttributes500", UpdateVectorStoreFileAttributes500> + > + } /** - * Returns the rate limits per model for a project. + * Delete a vector store file. This will remove the file from the vector store but the file itself will not be deleted. To delete the file, use the [delete file](https://developers.openai.com/api/reference/resources/files/methods/delete) endpoint. */ - readonly "listProjectRateLimits": ( - projectId: string, - options: { - readonly params?: typeof ListProjectRateLimitsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteVectorStoreFile": { + ( + vectorStoreId: string, + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVectorStoreFile400", DeleteVectorStoreFile400> + | OpenAiClientError<"DeleteVectorStoreFile404", DeleteVectorStoreFile404> + | OpenAiClientError<"DeleteVectorStoreFile409", DeleteVectorStoreFile409> + | OpenAiClientError<"DeleteVectorStoreFile429", DeleteVectorStoreFile429> + | OpenAiClientError<"DeleteVectorStoreFile500", DeleteVectorStoreFile500> + > + ( + vectorStoreId: string, + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVectorStoreFile400", DeleteVectorStoreFile400> + | OpenAiClientError<"DeleteVectorStoreFile404", DeleteVectorStoreFile404> + | OpenAiClientError<"DeleteVectorStoreFile409", DeleteVectorStoreFile409> + | OpenAiClientError<"DeleteVectorStoreFile429", DeleteVectorStoreFile429> + | OpenAiClientError<"DeleteVectorStoreFile500", DeleteVectorStoreFile500> + > + } /** - * Updates a project rate limit. + * Retrieve the parsed contents of a vector store file. */ - readonly "updateProjectRateLimits": ( - projectId: string, - rateLimitId: string, - options: { - readonly payload: typeof UpdateProjectRateLimitsRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"UpdateProjectRateLimits400", typeof UpdateProjectRateLimits400.Type> - > + readonly "retrieveVectorStoreFileContent": { + ( + vectorStoreId: string, + fileId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveVectorStoreFileContent400", RetrieveVectorStoreFileContent400> + | OpenAiClientError<"RetrieveVectorStoreFileContent404", RetrieveVectorStoreFileContent404> + | OpenAiClientError<"RetrieveVectorStoreFileContent429", RetrieveVectorStoreFileContent429> + | OpenAiClientError<"RetrieveVectorStoreFileContent500", RetrieveVectorStoreFileContent500> + > + ( + vectorStoreId: string, + fileId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveVectorStoreFileContent400", RetrieveVectorStoreFileContent400> + | OpenAiClientError<"RetrieveVectorStoreFileContent404", RetrieveVectorStoreFileContent404> + | OpenAiClientError<"RetrieveVectorStoreFileContent429", RetrieveVectorStoreFileContent429> + | OpenAiClientError<"RetrieveVectorStoreFileContent500", RetrieveVectorStoreFileContent500> + > + } /** - * Returns a list of service accounts in the project. + * Search a vector store for relevant chunks based on a query and file attributes filter. */ - readonly "listProjectServiceAccounts": ( - projectId: string, - options: { - readonly params?: typeof ListProjectServiceAccountsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"ListProjectServiceAccounts400", typeof ListProjectServiceAccounts400.Type> - > + readonly "searchVectorStore": { + ( + vectorStoreId: string, + options: { readonly payload: typeof SearchVectorStoreRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"SearchVectorStore400", SearchVectorStore400> + | OpenAiClientError<"SearchVectorStore404", SearchVectorStore404> + | OpenAiClientError<"SearchVectorStore429", SearchVectorStore429> + > + ( + vectorStoreId: string, + options: { readonly payload: typeof SearchVectorStoreRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"SearchVectorStore400", SearchVectorStore400> + | OpenAiClientError<"SearchVectorStore404", SearchVectorStore404> + | OpenAiClientError<"SearchVectorStore429", SearchVectorStore429> + > + } /** - * Creates a new service account in the project. This also returns an unredacted API key for the service account. + * Create a conversation. */ - readonly "createProjectServiceAccount": ( - projectId: string, - options: { - readonly payload: typeof CreateProjectServiceAccountRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"CreateProjectServiceAccount400", typeof CreateProjectServiceAccount400.Type> - > + readonly "createConversation": { + ( + options: { readonly payload: typeof CreateConversationRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateConversation400", CreateConversation400> + | OpenAiClientError<"CreateConversation429", CreateConversation429> + | OpenAiClientError<"CreateConversation500", CreateConversation500> + > + ( + options: { readonly payload: typeof CreateConversationRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateConversation400", CreateConversation400> + | OpenAiClientError<"CreateConversation429", CreateConversation429> + | OpenAiClientError<"CreateConversation500", CreateConversation500> + > + } /** - * Retrieves a service account in the project. + * Get a conversation */ - readonly "retrieveProjectServiceAccount": ( - projectId: string, - serviceAccountId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "getConversation": { + ( + conversationId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetConversation404", GetConversation404> + | OpenAiClientError<"GetConversation429", GetConversation429> + > + ( + conversationId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetConversation404", GetConversation404> + | OpenAiClientError<"GetConversation429", GetConversation429> + > + } /** - * Deletes a service account from the project. - * - * Returns confirmation of service account deletion, or an error if the project - * is archived (archived projects have no service accounts). + * Update a conversation */ - readonly "deleteProjectServiceAccount": ( - projectId: string, - serviceAccountId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateConversation": { + ( + conversationId: string, + options: { readonly payload: typeof UpdateConversationRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateConversation400", UpdateConversation400> + | OpenAiClientError<"UpdateConversation404", UpdateConversation404> + | OpenAiClientError<"UpdateConversation429", UpdateConversation429> + | OpenAiClientError<"UpdateConversation500", UpdateConversation500> + > + ( + conversationId: string, + options: { readonly payload: typeof UpdateConversationRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateConversation400", UpdateConversation400> + | OpenAiClientError<"UpdateConversation404", UpdateConversation404> + | OpenAiClientError<"UpdateConversation429", UpdateConversation429> + | OpenAiClientError<"UpdateConversation500", UpdateConversation500> + > + } /** - * Returns a list of users in the project. + * Delete a conversation. Items in the conversation will not be deleted. */ - readonly "listProjectUsers": ( - projectId: string, - options: { - readonly params?: typeof ListProjectUsersParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"ListProjectUsers400", typeof ListProjectUsers400.Type> - > + readonly "deleteConversation": { + ( + conversationId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteConversation404", DeleteConversation404> + | OpenAiClientError<"DeleteConversation429", DeleteConversation429> + > + ( + conversationId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteConversation404", DeleteConversation404> + | OpenAiClientError<"DeleteConversation429", DeleteConversation429> + > + } /** - * Adds a user to the project. Users must already be members of the organization to be added to a project. + * Get a safety case by ID. */ - readonly "createProjectUser": ( - projectId: string, - options: { readonly payload: typeof CreateProjectUserRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"CreateProjectUser400", typeof CreateProjectUser400.Type> - > + readonly "Getsafetycase": { + ( + id: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getsafetycase400", Getsafetycase400> + | OpenAiClientError<"Getsafetycase404", Getsafetycase404> + | OpenAiClientError<"Getsafetycase429", Getsafetycase429> + | OpenAiClientError<"Getsafetycase500", Getsafetycase500> + | OpenAiClientError<"Getsafetycase503", Getsafetycase503> + > + ( + id: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getsafetycase400", Getsafetycase400> + | OpenAiClientError<"Getsafetycase404", Getsafetycase404> + | OpenAiClientError<"Getsafetycase429", Getsafetycase429> + | OpenAiClientError<"Getsafetycase500", Getsafetycase500> + | OpenAiClientError<"Getsafetycase503", Getsafetycase503> + > + } /** - * Retrieves a user in the project. + * Get a safety alert belonging to the authenticated API project. */ - readonly "retrieveProjectUser": ( - projectId: string, - userId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Getprojectsafetyalert": { + ( + id: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getprojectsafetyalert400", Getprojectsafetyalert400> + | OpenAiClientError<"Getprojectsafetyalert404", Getprojectsafetyalert404> + | OpenAiClientError<"Getprojectsafetyalert429", Getprojectsafetyalert429> + | OpenAiClientError<"Getprojectsafetyalert503", Getprojectsafetyalert503> + > + ( + id: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getprojectsafetyalert400", Getprojectsafetyalert400> + | OpenAiClientError<"Getprojectsafetyalert404", Getprojectsafetyalert404> + | OpenAiClientError<"Getprojectsafetyalert429", Getprojectsafetyalert429> + | OpenAiClientError<"Getprojectsafetyalert503", Getprojectsafetyalert503> + > + } /** - * Modifies a user's role in the project. + * Get Live session content */ - readonly "modifyProjectUser": ( - projectId: string, - userId: string, - options: { readonly payload: typeof ModifyProjectUserRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"ModifyProjectUser400", typeof ModifyProjectUser400.Type> - > + readonly "downloadLiveRecording": { + ( + sessionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DownloadLiveRecording400", DownloadLiveRecording400> + | OpenAiClientError<"DownloadLiveRecording404", DownloadLiveRecording404> + | OpenAiClientError<"DownloadLiveRecording429", DownloadLiveRecording429> + | OpenAiClientError<"DownloadLiveRecording500", DownloadLiveRecording500> + | OpenAiClientError<"DownloadLiveRecording503", DownloadLiveRecording503> + > + ( + sessionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DownloadLiveRecording400", DownloadLiveRecording400> + | OpenAiClientError<"DownloadLiveRecording404", DownloadLiveRecording404> + | OpenAiClientError<"DownloadLiveRecording429", DownloadLiveRecording429> + | OpenAiClientError<"DownloadLiveRecording500", DownloadLiveRecording500> + | OpenAiClientError<"DownloadLiveRecording503", DownloadLiveRecording503> + > + } /** - * Deletes a user from the project. - * - * Returns confirmation of project user deletion, or an error if the project is - * archived (archived projects have no users). + * Get Live session content */ - readonly "deleteProjectUser": ( - projectId: string, - userId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"DeleteProjectUser400", typeof DeleteProjectUser400.Type> - > + readonly "downloadLiveRecordingStream": ( + sessionId: string + ) => Stream.Stream /** - * Lists the roles configured for the organization. + * Get Decisions API usage details for the organization. */ - readonly "listRoles": ( - options: - | { readonly params?: typeof ListRolesParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "OrganizationDecisionsusage": { + ( + options: { readonly params: typeof OrganizationDecisionsusageParams.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"OrganizationDecisionsusage400", OrganizationDecisionsusage400> + | OpenAiClientError<"OrganizationDecisionsusage403", OrganizationDecisionsusage403> + | OpenAiClientError<"OrganizationDecisionsusage429", OrganizationDecisionsusage429> + > + ( + options: { + readonly params: typeof OrganizationDecisionsusageParams.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"OrganizationDecisionsusage400", OrganizationDecisionsusage400> + | OpenAiClientError<"OrganizationDecisionsusage403", OrganizationDecisionsusage403> + | OpenAiClientError<"OrganizationDecisionsusage429", OrganizationDecisionsusage429> + > + } /** - * Creates a custom role for the organization. + * List the organization's customer-managed external storage configurations. */ - readonly "createRole": ( - options: { readonly payload: typeof CreateRoleRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Listexternalstorageconfigurations": { + ( + options: { + readonly params?: typeof ListexternalstorageconfigurationsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Listexternalstorageconfigurations400", Listexternalstorageconfigurations400> + | OpenAiClientError<"Listexternalstorageconfigurations403", Listexternalstorageconfigurations403> + | OpenAiClientError<"Listexternalstorageconfigurations404", Listexternalstorageconfigurations404> + > + ( + options: { + readonly params?: typeof ListexternalstorageconfigurationsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Listexternalstorageconfigurations400", Listexternalstorageconfigurations400> + | OpenAiClientError<"Listexternalstorageconfigurations403", Listexternalstorageconfigurations403> + | OpenAiClientError<"Listexternalstorageconfigurations404", Listexternalstorageconfigurations404> + > + } /** - * Updates an existing organization role. + * Register one customer-managed external storage configuration. */ - readonly "updateRole": ( - roleId: string, - options: { readonly payload: typeof UpdateRoleRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Createanexternalstorageconfiguration": { + ( + options: { + readonly payload: typeof CreateanexternalstorageconfigurationRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Createanexternalstorageconfiguration400", Createanexternalstorageconfiguration400> + | OpenAiClientError<"Createanexternalstorageconfiguration403", Createanexternalstorageconfiguration403> + | OpenAiClientError<"Createanexternalstorageconfiguration404", Createanexternalstorageconfiguration404> + | OpenAiClientError<"Createanexternalstorageconfiguration503", Createanexternalstorageconfiguration503> + > + ( + options: { + readonly payload: typeof CreateanexternalstorageconfigurationRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Createanexternalstorageconfiguration400", Createanexternalstorageconfiguration400> + | OpenAiClientError<"Createanexternalstorageconfiguration403", Createanexternalstorageconfiguration403> + | OpenAiClientError<"Createanexternalstorageconfiguration404", Createanexternalstorageconfiguration404> + | OpenAiClientError<"Createanexternalstorageconfiguration503", Createanexternalstorageconfiguration503> + > + } /** - * Deletes a custom role from the organization. + * Get one customer-managed external storage configuration. */ - readonly "deleteRole": ( - roleId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Getanexternalstorageconfiguration": { + ( + externalStorageId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getanexternalstorageconfiguration400", Getanexternalstorageconfiguration400> + | OpenAiClientError<"Getanexternalstorageconfiguration403", Getanexternalstorageconfiguration403> + | OpenAiClientError<"Getanexternalstorageconfiguration404", Getanexternalstorageconfiguration404> + > + ( + externalStorageId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getanexternalstorageconfiguration400", Getanexternalstorageconfiguration400> + | OpenAiClientError<"Getanexternalstorageconfiguration403", Getanexternalstorageconfiguration403> + | OpenAiClientError<"Getanexternalstorageconfiguration404", Getanexternalstorageconfiguration404> + > + } /** - * Get audio speeches usage details for the organization. + * Disconnect a customer-managed external storage configuration. Removing the project's last configuration restores organization-default retention if customer-managed retention was active. Repeating a deletion also completes any interrupted retention update. Cloud storage is unchanged. */ - readonly "usageAudioSpeeches": ( - options: { readonly params: typeof UsageAudioSpeechesParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Deleteanexternalstorageconfiguration": { + ( + externalStorageId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Deleteanexternalstorageconfiguration400", Deleteanexternalstorageconfiguration400> + | OpenAiClientError<"Deleteanexternalstorageconfiguration403", Deleteanexternalstorageconfiguration403> + | OpenAiClientError<"Deleteanexternalstorageconfiguration404", Deleteanexternalstorageconfiguration404> + > + ( + externalStorageId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Deleteanexternalstorageconfiguration400", Deleteanexternalstorageconfiguration400> + | OpenAiClientError<"Deleteanexternalstorageconfiguration403", Deleteanexternalstorageconfiguration403> + | OpenAiClientError<"Deleteanexternalstorageconfiguration404", Deleteanexternalstorageconfiguration404> + > + } /** - * Get audio transcriptions usage details for the organization. + * Validate one customer-managed external storage configuration. */ - readonly "usageAudioTranscriptions": ( - options: { readonly params: typeof UsageAudioTranscriptionsParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Validateanexternalstorageconfiguration": { + ( + externalStorageId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Validateanexternalstorageconfiguration400", Validateanexternalstorageconfiguration400> + | OpenAiClientError<"Validateanexternalstorageconfiguration403", Validateanexternalstorageconfiguration403> + | OpenAiClientError<"Validateanexternalstorageconfiguration404", Validateanexternalstorageconfiguration404> + | OpenAiClientError<"Validateanexternalstorageconfiguration503", Validateanexternalstorageconfiguration503> + > + ( + externalStorageId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Validateanexternalstorageconfiguration400", Validateanexternalstorageconfiguration400> + | OpenAiClientError<"Validateanexternalstorageconfiguration403", Validateanexternalstorageconfiguration403> + | OpenAiClientError<"Validateanexternalstorageconfiguration404", Validateanexternalstorageconfiguration404> + | OpenAiClientError<"Validateanexternalstorageconfiguration503", Validateanexternalstorageconfiguration503> + > + } /** - * Get code interpreter sessions usage details for the organization. + * Get the organization's hard spend limit. */ - readonly "usageCodeInterpreterSessions": ( - options: { - readonly params: typeof UsageCodeInterpreterSessionsParams.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Getorganizationspendlimit": { + ( + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getorganizationspendlimit403", Getorganizationspendlimit403> + | OpenAiClientError<"Getorganizationspendlimit404", Getorganizationspendlimit404> + > + ( + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getorganizationspendlimit403", Getorganizationspendlimit403> + | OpenAiClientError<"Getorganizationspendlimit404", Getorganizationspendlimit404> + > + } /** - * Get completions usage details for the organization. + * Create or replace the organization's hard spend limit. */ - readonly "usageCompletions": ( - options: { readonly params: typeof UsageCompletionsParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Updateorganizationspendlimit": { + ( + options: { readonly payload: typeof UpdateorganizationspendlimitRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Updateorganizationspendlimit400", Updateorganizationspendlimit400> + | OpenAiClientError<"Updateorganizationspendlimit403", Updateorganizationspendlimit403> + > + ( + options: { + readonly payload: typeof UpdateorganizationspendlimitRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Updateorganizationspendlimit400", Updateorganizationspendlimit400> + | OpenAiClientError<"Updateorganizationspendlimit403", Updateorganizationspendlimit403> + > + } /** - * Get embeddings usage details for the organization. + * Delete the organization's hard spend limit. */ - readonly "usageEmbeddings": ( - options: { readonly params: typeof UsageEmbeddingsParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Deleteorganizationspendlimit": { + ( + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Deleteorganizationspendlimit403", Deleteorganizationspendlimit403> + | OpenAiClientError<"Deleteorganizationspendlimit404", Deleteorganizationspendlimit404> + > + ( + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Deleteorganizationspendlimit403", Deleteorganizationspendlimit403> + | OpenAiClientError<"Deleteorganizationspendlimit404", Deleteorganizationspendlimit404> + > + } /** - * Get file search calls usage details for the organization. + * Get a project's hard spend limit. */ - readonly "usageFileSearchCalls": ( - options: { readonly params: typeof UsageFileSearchCallsParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Getprojectspendlimit": { + ( + projectId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getprojectspendlimit400", Getprojectspendlimit400> + | OpenAiClientError<"Getprojectspendlimit403", Getprojectspendlimit403> + | OpenAiClientError<"Getprojectspendlimit404", Getprojectspendlimit404> + > + ( + projectId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getprojectspendlimit400", Getprojectspendlimit400> + | OpenAiClientError<"Getprojectspendlimit403", Getprojectspendlimit403> + | OpenAiClientError<"Getprojectspendlimit404", Getprojectspendlimit404> + > + } /** - * Get images usage details for the organization. + * Create or replace a project's hard spend limit. */ - readonly "usageImages": ( - options: { readonly params: typeof UsageImagesParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Updateprojectspendlimit": { + ( + projectId: string, + options: { readonly payload: typeof UpdateprojectspendlimitRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Updateprojectspendlimit400", Updateprojectspendlimit400> + | OpenAiClientError<"Updateprojectspendlimit403", Updateprojectspendlimit403> + | OpenAiClientError<"Updateprojectspendlimit404", Updateprojectspendlimit404> + > + ( + projectId: string, + options: { + readonly payload: typeof UpdateprojectspendlimitRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Updateprojectspendlimit400", Updateprojectspendlimit400> + | OpenAiClientError<"Updateprojectspendlimit403", Updateprojectspendlimit403> + | OpenAiClientError<"Updateprojectspendlimit404", Updateprojectspendlimit404> + > + } /** - * Get moderations usage details for the organization. + * Delete a project's hard spend limit. */ - readonly "usageModerations": ( - options: { readonly params: typeof UsageModerationsParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Deleteprojectspendlimit": { + ( + projectId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Deleteprojectspendlimit400", Deleteprojectspendlimit400> + | OpenAiClientError<"Deleteprojectspendlimit403", Deleteprojectspendlimit403> + | OpenAiClientError<"Deleteprojectspendlimit404", Deleteprojectspendlimit404> + > + ( + projectId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Deleteprojectspendlimit400", Deleteprojectspendlimit400> + | OpenAiClientError<"Deleteprojectspendlimit403", Deleteprojectspendlimit403> + | OpenAiClientError<"Deleteprojectspendlimit404", Deleteprojectspendlimit404> + > + } /** - * Get vector stores usage details for the organization. + * Creates an API key for a service account in the project. */ - readonly "usageVectorStores": ( - options: { readonly params: typeof UsageVectorStoresParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "CreateanAPIkeyforaserviceaccount": { + ( + projectId: string, + serviceAccountId: string, + options: { readonly payload: typeof CreateanAPIkeyforaserviceaccountRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount400", CreateanAPIkeyforaserviceaccount400> + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount403", CreateanAPIkeyforaserviceaccount403> + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount404", CreateanAPIkeyforaserviceaccount404> + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount409", CreateanAPIkeyforaserviceaccount409> + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount429", CreateanAPIkeyforaserviceaccount429> + > + ( + projectId: string, + serviceAccountId: string, + options: { + readonly payload: typeof CreateanAPIkeyforaserviceaccountRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount400", CreateanAPIkeyforaserviceaccount400> + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount403", CreateanAPIkeyforaserviceaccount403> + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount404", CreateanAPIkeyforaserviceaccount404> + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount409", CreateanAPIkeyforaserviceaccount409> + | OpenAiClientError<"CreateanAPIkeyforaserviceaccount429", CreateanAPIkeyforaserviceaccount429> + > + } /** - * Get web search calls usage details for the organization. + * Check whether an image or audio file contains known OpenAI provenance signals. [Learn more about content provenance](https://developers.openai.com/api/docs/guides/content-provenance). + * + * If `not_detected`, it means the tool did not find supported signals in the uploaded file. The content could still have been generated by OpenAI if the metadata was stripped or has evidence of tampering, the watermark was degraded, it comes from a legacy generation model, or it was created before provenance signals were available. Content could also still be AI-generated by another company's model, which the tool currently does not detect. */ - readonly "usageWebSearchCalls": ( - options: { readonly params: typeof UsageWebSearchCallsParams.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Createcontentprovenancecheck": { + ( + options: { readonly payload: typeof CreatecontentprovenancecheckRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Createcontentprovenancecheck400", Createcontentprovenancecheck400> + | OpenAiClientError<"Createcontentprovenancecheck404", Createcontentprovenancecheck404> + | OpenAiClientError<"Createcontentprovenancecheck429", Createcontentprovenancecheck429> + | OpenAiClientError<"Createcontentprovenancecheck500", Createcontentprovenancecheck500> + | OpenAiClientError<"Createcontentprovenancecheck503", Createcontentprovenancecheck503> + > + ( + options: { + readonly payload: typeof CreatecontentprovenancecheckRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Createcontentprovenancecheck400", Createcontentprovenancecheck400> + | OpenAiClientError<"Createcontentprovenancecheck404", Createcontentprovenancecheck404> + | OpenAiClientError<"Createcontentprovenancecheck429", Createcontentprovenancecheck429> + | OpenAiClientError<"Createcontentprovenancecheck500", Createcontentprovenancecheck500> + | OpenAiClientError<"Createcontentprovenancecheck503", Createcontentprovenancecheck503> + > + } /** - * Lists all of the users in the organization. + * List recently generated videos for the current project. */ - readonly "listUsers": ( - options: - | { readonly params?: typeof ListUsersParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "ListVideos": { + ( + options: { readonly params?: typeof ListVideosParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVideos400", ListVideos400> + | OpenAiClientError<"ListVideos404", ListVideos404> + > + ( + options: + | { readonly params?: typeof ListVideosParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVideos400", ListVideos400> + | OpenAiClientError<"ListVideos404", ListVideos404> + > + } /** - * Retrieves a user by their identifier. + * Create a new video generation job from a prompt and optional reference assets. */ - readonly "retrieveUser": ( - userId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createVideo": { + ( + options: { readonly payload: typeof CreateVideoRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideo400", CreateVideo400> + | OpenAiClientError<"CreateVideo404", CreateVideo404> + | OpenAiClientError<"CreateVideo429", CreateVideo429> + | OpenAiClientError<"CreateVideo500", CreateVideo500> + | OpenAiClientError<"CreateVideo503", CreateVideo503> + > + ( + options: { readonly payload: typeof CreateVideoRequestFormData.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideo400", CreateVideo400> + | OpenAiClientError<"CreateVideo404", CreateVideo404> + | OpenAiClientError<"CreateVideo429", CreateVideo429> + | OpenAiClientError<"CreateVideo500", CreateVideo500> + | OpenAiClientError<"CreateVideo503", CreateVideo503> + > + } /** - * Modifies a user's role in the organization. + * Create a character from an uploaded video. */ - readonly "modifyUser": ( - userId: string, - options: { readonly payload: typeof ModifyUserRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "CreateVideoCharacter": { + ( + options: { readonly payload: typeof CreateVideoCharacterRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideoCharacter400", CreateVideoCharacter400> + | OpenAiClientError<"CreateVideoCharacter404", CreateVideoCharacter404> + | OpenAiClientError<"CreateVideoCharacter500", CreateVideoCharacter500> + | OpenAiClientError<"CreateVideoCharacter504", CreateVideoCharacter504> + > + ( + options: { + readonly payload: typeof CreateVideoCharacterRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideoCharacter400", CreateVideoCharacter400> + | OpenAiClientError<"CreateVideoCharacter404", CreateVideoCharacter404> + | OpenAiClientError<"CreateVideoCharacter500", CreateVideoCharacter500> + | OpenAiClientError<"CreateVideoCharacter504", CreateVideoCharacter504> + > + } /** - * Deletes a user from the organization. + * Fetch a character. */ - readonly "deleteUser": ( - userId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "GetVideoCharacter": { + ( + characterId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVideoCharacter400", GetVideoCharacter400> + | OpenAiClientError<"GetVideoCharacter404", GetVideoCharacter404> + > + ( + characterId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVideoCharacter400", GetVideoCharacter400> + | OpenAiClientError<"GetVideoCharacter404", GetVideoCharacter404> + > + } /** - * Lists the organization roles assigned to a user within the organization. + * Create a new video generation job by editing a source video or existing generated video. */ - readonly "listUserRoleAssignments": ( - userId: string, - options: { - readonly params?: typeof ListUserRoleAssignmentsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "CreateVideoEdit": { + ( + options: { readonly payload: typeof CreateVideoEditRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideoEdit400", CreateVideoEdit400> + | OpenAiClientError<"CreateVideoEdit404", CreateVideoEdit404> + | OpenAiClientError<"CreateVideoEdit429", CreateVideoEdit429> + | OpenAiClientError<"CreateVideoEdit500", CreateVideoEdit500> + | OpenAiClientError<"CreateVideoEdit503", CreateVideoEdit503> + > + ( + options: { readonly payload: typeof CreateVideoEditRequestFormData.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideoEdit400", CreateVideoEdit400> + | OpenAiClientError<"CreateVideoEdit404", CreateVideoEdit404> + | OpenAiClientError<"CreateVideoEdit429", CreateVideoEdit429> + | OpenAiClientError<"CreateVideoEdit500", CreateVideoEdit500> + | OpenAiClientError<"CreateVideoEdit503", CreateVideoEdit503> + > + } /** - * Assigns an organization role to a user within the organization. + * Create an extension of a completed video. */ - readonly "assignUserRole": ( - userId: string, - options: { readonly payload: typeof AssignUserRoleRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "CreateVideoExtend": { + ( + options: { readonly payload: typeof CreateVideoExtendRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideoExtend400", CreateVideoExtend400> + | OpenAiClientError<"CreateVideoExtend404", CreateVideoExtend404> + | OpenAiClientError<"CreateVideoExtend429", CreateVideoExtend429> + | OpenAiClientError<"CreateVideoExtend500", CreateVideoExtend500> + | OpenAiClientError<"CreateVideoExtend503", CreateVideoExtend503> + > + ( + options: { + readonly payload: typeof CreateVideoExtendRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideoExtend400", CreateVideoExtend400> + | OpenAiClientError<"CreateVideoExtend404", CreateVideoExtend404> + | OpenAiClientError<"CreateVideoExtend429", CreateVideoExtend429> + | OpenAiClientError<"CreateVideoExtend500", CreateVideoExtend500> + | OpenAiClientError<"CreateVideoExtend503", CreateVideoExtend503> + > + } /** - * Unassigns an organization role from a user within the organization. + * Fetch the latest metadata for a generated video. */ - readonly "unassignUserRole": ( - userId: string, - roleId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "GetVideo": { + ( + videoId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVideo400", GetVideo400> + | OpenAiClientError<"GetVideo404", GetVideo404> + > + ( + videoId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetVideo400", GetVideo400> + | OpenAiClientError<"GetVideo404", GetVideo404> + > + } /** - * Lists the project roles assigned to a group within a project. + * Permanently delete a completed or failed video and its stored assets. */ - readonly "listProjectGroupRoleAssignments": ( - projectId: string, - groupId: string, - options: { - readonly params?: typeof ListProjectGroupRoleAssignmentsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "DeleteVideo": { + ( + videoId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVideo400", DeleteVideo400> + | OpenAiClientError<"DeleteVideo404", DeleteVideo404> + | OpenAiClientError<"DeleteVideo500", DeleteVideo500> + > + ( + videoId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVideo400", DeleteVideo400> + | OpenAiClientError<"DeleteVideo404", DeleteVideo404> + | OpenAiClientError<"DeleteVideo500", DeleteVideo500> + > + } /** - * Assigns a project role to a group within a project. + * Download the generated video bytes or a derived preview asset. + * + * Streams the rendered video content for the specified video job. */ - readonly "assignProjectGroupRole": ( - projectId: string, - groupId: string, - options: { - readonly payload: typeof AssignProjectGroupRoleRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "RetrieveVideoContent": { + ( + videoId: string, + options: { readonly params?: typeof RetrieveVideoContentParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveVideoContent400", RetrieveVideoContent400> + | OpenAiClientError<"RetrieveVideoContent404", RetrieveVideoContent404> + | OpenAiClientError<"RetrieveVideoContent500", RetrieveVideoContent500> + > + ( + videoId: string, + options: { + readonly params?: typeof RetrieveVideoContentParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveVideoContent400", RetrieveVideoContent400> + | OpenAiClientError<"RetrieveVideoContent404", RetrieveVideoContent404> + | OpenAiClientError<"RetrieveVideoContent500", RetrieveVideoContent500> + > + } /** - * Unassigns a project role from a group within a project. + * Download the generated video bytes or a derived preview asset. + * + * Streams the rendered video content for the specified video job. */ - readonly "unassignProjectGroupRole": ( - projectId: string, - groupId: string, - roleId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "RetrieveVideoContentStream": ( + videoId: string, + options: { readonly params?: typeof RetrieveVideoContentParams.Encoded | undefined } | undefined + ) => Stream.Stream /** - * Lists the roles configured for a project. + * Create a remix of a completed video using a refreshed prompt. */ - readonly "listProjectRoles": ( - projectId: string, - options: { - readonly params?: typeof ListProjectRolesParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "CreateVideoRemix": { + ( + videoId: string, + options: { readonly payload: typeof CreateVideoRemixRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideoRemix400", CreateVideoRemix400> + | OpenAiClientError<"CreateVideoRemix404", CreateVideoRemix404> + | OpenAiClientError<"CreateVideoRemix429", CreateVideoRemix429> + | OpenAiClientError<"CreateVideoRemix500", CreateVideoRemix500> + | OpenAiClientError<"CreateVideoRemix503", CreateVideoRemix503> + > + ( + videoId: string, + options: { + readonly payload: typeof CreateVideoRemixRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVideoRemix400", CreateVideoRemix400> + | OpenAiClientError<"CreateVideoRemix404", CreateVideoRemix404> + | OpenAiClientError<"CreateVideoRemix429", CreateVideoRemix429> + | OpenAiClientError<"CreateVideoRemix500", CreateVideoRemix500> + | OpenAiClientError<"CreateVideoRemix503", CreateVideoRemix503> + > + } /** - * Creates a custom role for a project. + * Returns input token counts of the request. + * + * Returns an object with `object` set to `response.input_tokens` and an `input_tokens` count. */ - readonly "createProjectRole": ( - projectId: string, - options: { readonly payload: typeof CreateProjectRoleRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Getinputtokencounts": { + ( + options: { readonly payload: typeof GetinputtokencountsRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getinputtokencounts400", Getinputtokencounts400> + | OpenAiClientError<"Getinputtokencounts429", Getinputtokencounts429> + > + ( + options: { readonly payload: typeof GetinputtokencountsRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Getinputtokencounts400", Getinputtokencounts400> + | OpenAiClientError<"Getinputtokencounts429", Getinputtokencounts429> + > + } /** - * Updates an existing project role. + * Compact a conversation. Returns a compacted response object. + * + * Learn when and how to compact long-running conversations in the [conversation state guide](https://developers.openai.com/api/docs/guides/conversation-state#managing-the-context-window). For ZDR-compatible compaction details, see [Compaction (advanced)](https://developers.openai.com/api/docs/guides/conversation-state#compaction-advanced). */ - readonly "updateProjectRole": ( - projectId: string, - roleId: string, - options: { readonly payload: typeof UpdateProjectRoleRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "Compactconversation": { + ( + options: { readonly payload: typeof CompactconversationRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Compactconversation400", Compactconversation400> + | OpenAiClientError<"Compactconversation429", Compactconversation429> + | OpenAiClientError<"Compactconversation503", Compactconversation503> + > + ( + options: { readonly payload: typeof CompactconversationRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"Compactconversation400", Compactconversation400> + | OpenAiClientError<"Compactconversation429", Compactconversation429> + | OpenAiClientError<"Compactconversation503", Compactconversation503> + > + } /** - * Deletes a custom role from a project. + * List all skills for the current project. */ - readonly "deleteProjectRole": ( - projectId: string, - roleId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "ListSkills": { + ( + options: { readonly params?: typeof ListSkillsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListSkills404", ListSkills404> + | OpenAiClientError<"ListSkills429", ListSkills429> + > + ( + options: + | { readonly params?: typeof ListSkillsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListSkills404", ListSkills404> + | OpenAiClientError<"ListSkills429", ListSkills429> + > + } /** - * Lists the project roles assigned to a user within a project. + * Create a new skill. */ - readonly "listProjectUserRoleAssignments": ( - projectId: string, - userId: string, - options: { - readonly params?: typeof ListProjectUserRoleAssignmentsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "CreateSkill": { + ( + options: { readonly payload: typeof CreateSkillRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateSkill400", CreateSkill400> + | OpenAiClientError<"CreateSkill429", CreateSkill429> + | OpenAiClientError<"CreateSkill500", CreateSkill500> + > + ( + options: { readonly payload: typeof CreateSkillRequestFormData.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateSkill400", CreateSkill400> + | OpenAiClientError<"CreateSkill429", CreateSkill429> + | OpenAiClientError<"CreateSkill500", CreateSkill500> + > + } /** - * Assigns a project role to a user within a project. + * Get a skill by its ID. */ - readonly "assignProjectUserRole": ( - projectId: string, - userId: string, - options: { readonly payload: typeof AssignProjectUserRoleRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "GetSkill": { + ( + skillId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetSkill404", GetSkill404> + | OpenAiClientError<"GetSkill429", GetSkill429> + > + ( + skillId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetSkill404", GetSkill404> + | OpenAiClientError<"GetSkill429", GetSkill429> + > + } /** - * Unassigns a project role from a user within a project. + * Update the default version pointer for a skill. */ - readonly "unassignProjectUserRole": ( - projectId: string, - userId: string, - roleId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "UpdateSkillDefaultVersion": { + ( + skillId: string, + options: { readonly payload: typeof UpdateSkillDefaultVersionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateSkillDefaultVersion400", UpdateSkillDefaultVersion400> + | OpenAiClientError<"UpdateSkillDefaultVersion404", UpdateSkillDefaultVersion404> + | OpenAiClientError<"UpdateSkillDefaultVersion429", UpdateSkillDefaultVersion429> + > + ( + skillId: string, + options: { + readonly payload: typeof UpdateSkillDefaultVersionRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateSkillDefaultVersion400", UpdateSkillDefaultVersion400> + | OpenAiClientError<"UpdateSkillDefaultVersion404", UpdateSkillDefaultVersion404> + | OpenAiClientError<"UpdateSkillDefaultVersion429", UpdateSkillDefaultVersion429> + > + } /** - * Create a new Realtime API call over WebRTC and receive the SDP answer needed - * to complete the peer connection. + * Delete a skill by its ID. */ - readonly "createRealtimeCall": ( - options: { - readonly payload: typeof CreateRealtimeCallRequestFormData.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "DeleteSkill": { + ( + skillId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteSkill404", DeleteSkill404> + | OpenAiClientError<"DeleteSkill429", DeleteSkill429> + > + ( + skillId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteSkill404", DeleteSkill404> + | OpenAiClientError<"DeleteSkill429", DeleteSkill429> + > + } /** - * Accept an incoming SIP call and configure the realtime session that will - * handle it. + * Download a skill zip bundle by its ID. */ - readonly "acceptRealtimeCall": ( - callId: string, - options: { readonly payload: typeof AcceptRealtimeCallRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "GetSkillContent": { + ( + skillId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetSkillContent404", GetSkillContent404> + | OpenAiClientError<"GetSkillContent429", GetSkillContent429> + > + ( + skillId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetSkillContent404", GetSkillContent404> + | OpenAiClientError<"GetSkillContent429", GetSkillContent429> + > + } /** - * End an active Realtime API call, whether it was initiated over SIP or - * WebRTC. + * Download a skill zip bundle by its ID. */ - readonly "hangupRealtimeCall": ( - callId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "GetSkillContentStream": (skillId: string) => Stream.Stream /** - * Transfer an active SIP call to a new destination using the SIP REFER verb. + * List skill versions for a skill. */ - readonly "referRealtimeCall": ( - callId: string, - options: { readonly payload: typeof ReferRealtimeCallRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "ListSkillVersions": { + ( + skillId: string, + options: { readonly params?: typeof ListSkillVersionsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListSkillVersions400", ListSkillVersions400> + | OpenAiClientError<"ListSkillVersions404", ListSkillVersions404> + | OpenAiClientError<"ListSkillVersions429", ListSkillVersions429> + > + ( + skillId: string, + options: { + readonly params?: typeof ListSkillVersionsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListSkillVersions400", ListSkillVersions400> + | OpenAiClientError<"ListSkillVersions404", ListSkillVersions404> + | OpenAiClientError<"ListSkillVersions429", ListSkillVersions429> + > + } /** - * Decline an incoming SIP call by returning a SIP status code to the caller. + * Create a new immutable skill version. */ - readonly "rejectRealtimeCall": ( - callId: string, - options: { readonly payload: typeof RejectRealtimeCallRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "CreateSkillVersion": { + ( + skillId: string, + options: { readonly payload: typeof CreateSkillVersionRequestFormData.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateSkillVersion400", CreateSkillVersion400> + | OpenAiClientError<"CreateSkillVersion404", CreateSkillVersion404> + | OpenAiClientError<"CreateSkillVersion429", CreateSkillVersion429> + | OpenAiClientError<"CreateSkillVersion500", CreateSkillVersion500> + > + ( + skillId: string, + options: { + readonly payload: typeof CreateSkillVersionRequestFormData.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateSkillVersion400", CreateSkillVersion400> + | OpenAiClientError<"CreateSkillVersion404", CreateSkillVersion404> + | OpenAiClientError<"CreateSkillVersion429", CreateSkillVersion429> + | OpenAiClientError<"CreateSkillVersion500", CreateSkillVersion500> + > + } /** - * Create a Realtime client secret with an associated session configuration. - * - * Client secrets are short-lived tokens that can be passed to a client app, - * such as a web frontend or mobile client, which grants access to the Realtime API without - * leaking your main API key. You can configure a custom TTL for each client secret. - * - * You can also attach session configuration options to the client secret, which will be - * applied to any sessions created using that client secret, but these can also be overridden - * by the client connection. - * - * [Learn more about authentication with client secrets over WebRTC](/docs/guides/realtime-webrtc). - * - * Returns the created client secret and the effective session object. The client secret is a string that looks like `ek_1234`. + * Get a specific skill version. */ - readonly "createRealtimeClientSecret": ( - options: { - readonly payload: typeof CreateRealtimeClientSecretRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "GetSkillVersion": { + ( + skillId: string, + version: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetSkillVersion400", GetSkillVersion400> + | OpenAiClientError<"GetSkillVersion404", GetSkillVersion404> + | OpenAiClientError<"GetSkillVersion429", GetSkillVersion429> + > + ( + skillId: string, + version: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetSkillVersion400", GetSkillVersion400> + | OpenAiClientError<"GetSkillVersion404", GetSkillVersion404> + | OpenAiClientError<"GetSkillVersion429", GetSkillVersion429> + > + } /** - * Create an ephemeral API token for use in client-side applications with the - * Realtime API. Can be configured with the same session parameters as the - * `session.update` client event. - * - * It responds with a session object, plus a `client_secret` key which contains - * a usable ephemeral API token that can be used to authenticate browser clients - * for the Realtime API. - * - * Returns the created Realtime session object, plus an ephemeral key. + * Delete a skill version. */ - readonly "createRealtimeSession": ( - options: { readonly payload: typeof CreateRealtimeSessionRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "DeleteSkillVersion": { + ( + skillId: string, + version: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteSkillVersion400", DeleteSkillVersion400> + | OpenAiClientError<"DeleteSkillVersion404", DeleteSkillVersion404> + | OpenAiClientError<"DeleteSkillVersion429", DeleteSkillVersion429> + > + ( + skillId: string, + version: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteSkillVersion400", DeleteSkillVersion400> + | OpenAiClientError<"DeleteSkillVersion404", DeleteSkillVersion404> + | OpenAiClientError<"DeleteSkillVersion429", DeleteSkillVersion429> + > + } /** - * Create an ephemeral API token for use in client-side applications with the - * Realtime API specifically for realtime transcriptions. - * Can be configured with the same session parameters as the `transcription_session.update` client event. - * - * It responds with a session object, plus a `client_secret` key which contains - * a usable ephemeral API token that can be used to authenticate browser clients - * for the Realtime API. - * - * Returns the created Realtime transcription session object, plus an ephemeral key. + * Download a skill version zip bundle. */ - readonly "createRealtimeTranscriptionSession": ( - options: { - readonly payload: typeof CreateRealtimeTranscriptionSessionRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "GetSkillVersionContent": { + ( + skillId: string, + version: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetSkillVersionContent400", GetSkillVersionContent400> + | OpenAiClientError<"GetSkillVersionContent404", GetSkillVersionContent404> + | OpenAiClientError<"GetSkillVersionContent429", GetSkillVersionContent429> + > + ( + skillId: string, + version: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetSkillVersionContent400", GetSkillVersionContent400> + | OpenAiClientError<"GetSkillVersionContent404", GetSkillVersionContent404> + | OpenAiClientError<"GetSkillVersionContent429", GetSkillVersionContent429> + > + } /** - * Create a Realtime translation client secret with an associated translation session configuration. - * - * Client secrets are short-lived tokens that can be passed to a client app, - * such as a web frontend or mobile client, which grants access to the Realtime - * Translation API without leaking your main API key. You can configure a custom - * TTL for each client secret. - * - * Returns the created client secret and the effective translation session object. - * The client secret is a string that looks like `ek_1234`. + * Download a skill version zip bundle. */ - readonly "createRealtimeTranslationClientSecret": ( - options: { - readonly payload: typeof CreateRealtimeTranslationClientSecretRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "GetSkillVersionContentStream": ( + skillId: string, + version: string + ) => Stream.Stream /** - * Creates a model response. Provide [text](/docs/guides/text) or - * [image](/docs/guides/images) inputs to generate [text](/docs/guides/text) - * or [JSON](/docs/guides/structured-outputs) outputs. Have the model call - * your own [custom code](/docs/guides/function-calling) or use built-in - * [tools](/docs/guides/tools) like [web search](/docs/guides/tools-web-search) - * or [file search](/docs/guides/tools-file-search) to use your own data - * as input for the model's response. + * Cancel an active ChatKit session and return its most recent metadata. + * + * Cancelling prevents new requests from using the issued client secret. */ - readonly "createResponse": ( - options: { readonly payload: typeof CreateResponseRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "CancelChatSessionMethod": { + ( + sessionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelChatSessionMethod400", CancelChatSessionMethod400> + | OpenAiClientError<"CancelChatSessionMethod404", CancelChatSessionMethod404> + | OpenAiClientError<"CancelChatSessionMethod429", CancelChatSessionMethod429> + > + ( + sessionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CancelChatSessionMethod400", CancelChatSessionMethod400> + | OpenAiClientError<"CancelChatSessionMethod404", CancelChatSessionMethod404> + | OpenAiClientError<"CancelChatSessionMethod429", CancelChatSessionMethod429> + > + } /** - * Creates a model response. Provide [text](/docs/guides/text) or - * [image](/docs/guides/images) inputs to generate [text](/docs/guides/text) - * or [JSON](/docs/guides/structured-outputs) outputs. Have the model call - * your own [custom code](/docs/guides/function-calling) or use built-in - * [tools](/docs/guides/tools) like [web search](/docs/guides/tools-web-search) - * or [file search](/docs/guides/tools-file-search) to use your own data - * as input for the model's response. + * Create a ChatKit session. */ - readonly "createResponseSse": ( - options: { readonly payload: typeof CreateResponseRequestJson.Encoded } - ) => Stream.Stream< - { readonly event: string; readonly id: string | undefined; readonly data: typeof CreateResponse200Sse.Type }, - HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, - typeof CreateResponse200Sse.DecodingServices - > + readonly "CreateChatSessionMethod": { + ( + options: { readonly payload: typeof CreateChatSessionMethodRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateChatSessionMethod400", CreateChatSessionMethod400> + | OpenAiClientError<"CreateChatSessionMethod404", CreateChatSessionMethod404> + | OpenAiClientError<"CreateChatSessionMethod429", CreateChatSessionMethod429> + > + ( + options: { + readonly payload: typeof CreateChatSessionMethodRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateChatSessionMethod400", CreateChatSessionMethod400> + | OpenAiClientError<"CreateChatSessionMethod404", CreateChatSessionMethod404> + | OpenAiClientError<"CreateChatSessionMethod429", CreateChatSessionMethod429> + > + } /** - * Retrieves a model response with the given ID. + * List items that belong to a ChatKit thread. */ - readonly "getResponse": ( - responseId: string, - options: - | { readonly params?: typeof GetResponseParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "ListThreadItemsMethod": { + ( + threadId: string, + options: { readonly params?: typeof ListThreadItemsMethodParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListThreadItemsMethod400", ListThreadItemsMethod400> + | OpenAiClientError<"ListThreadItemsMethod404", ListThreadItemsMethod404> + | OpenAiClientError<"ListThreadItemsMethod429", ListThreadItemsMethod429> + > + ( + threadId: string, + options: { + readonly params?: typeof ListThreadItemsMethodParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListThreadItemsMethod400", ListThreadItemsMethod400> + | OpenAiClientError<"ListThreadItemsMethod404", ListThreadItemsMethod404> + | OpenAiClientError<"ListThreadItemsMethod429", ListThreadItemsMethod429> + > + } /** - * Deletes a model response with the given ID. + * Retrieve a ChatKit thread by its identifier. */ - readonly "deleteResponse": ( - responseId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"DeleteResponse404", typeof DeleteResponse404.Type> - > - /** - * Cancels a model response with the given ID. Only responses created with - * the `background` parameter set to `true` can be cancelled. - * [Learn more](/docs/guides/background). - */ - readonly "cancelResponse": ( - responseId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - | HttpClientError.HttpClientError - | SchemaError - | OpenAiClientError<"CancelResponse404", typeof CancelResponse404.Type> - > + readonly "GetThreadMethod": { + ( + threadId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetThreadMethod400", GetThreadMethod400> + | OpenAiClientError<"GetThreadMethod404", GetThreadMethod404> + | OpenAiClientError<"GetThreadMethod429", GetThreadMethod429> + > + ( + threadId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"GetThreadMethod400", GetThreadMethod400> + | OpenAiClientError<"GetThreadMethod404", GetThreadMethod404> + | OpenAiClientError<"GetThreadMethod429", GetThreadMethod429> + > + } /** - * Returns a list of input items for a given response. + * Delete a ChatKit thread along with its items and stored attachments. */ - readonly "listInputItems": ( - responseId: string, - options: - | { readonly params?: typeof ListInputItemsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "DeleteThreadMethod": { + ( + threadId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteThreadMethod400", DeleteThreadMethod400> + | OpenAiClientError<"DeleteThreadMethod404", DeleteThreadMethod404> + | OpenAiClientError<"DeleteThreadMethod429", DeleteThreadMethod429> + > + ( + threadId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteThreadMethod400", DeleteThreadMethod400> + | OpenAiClientError<"DeleteThreadMethod404", DeleteThreadMethod404> + | OpenAiClientError<"DeleteThreadMethod429", DeleteThreadMethod429> + > + } /** - * Create a thread. + * List ChatKit threads with optional pagination and user filters. */ - readonly "createThread": ( - options: { readonly payload: typeof CreateThreadRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "ListThreadsMethod": { + ( + options: { readonly params?: typeof ListThreadsMethodParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListThreadsMethod400", ListThreadsMethod400> + | OpenAiClientError<"ListThreadsMethod404", ListThreadsMethod404> + | OpenAiClientError<"ListThreadsMethod429", ListThreadsMethod429> + > + ( + options: { + readonly params?: typeof ListThreadsMethodParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListThreadsMethod400", ListThreadsMethod400> + | OpenAiClientError<"ListThreadsMethod404", ListThreadsMethod404> + | OpenAiClientError<"ListThreadsMethod429", ListThreadsMethod429> + > + } /** - * Create a thread and run it in one request. + * Use this endpoint to ask classification or scoring questions about the same input. You’ll get the answers back in the order you asked the questions. + * + * For text, you can pass a string. You can also send user messages containing `input_text` and `input_image` parts, with up to 128 images per request. Images can be base64 data URLs or publicly accessible HTTP(S) URLs. File IDs aren’t accepted. Other message roles, function calls, files, audio, and item references aren’t supported. + * + * Sometimes a question returns a refusal instead of an answer. The result has type `refusal` and includes the question’s name, or `null` if you didn’t give it one. */ - readonly "createThreadAndRun": ( - options: { readonly payload: typeof CreateThreadAndRunRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createDecision": { + ( + options: { readonly payload: typeof CreateDecisionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect, HttpClientError.HttpClientError | SchemaError> + ( + options: { readonly payload: typeof CreateDecisionRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + HttpClientError.HttpClientError | SchemaError + > + } /** - * Retrieves a thread. + * Lists OpenAI-hosted environments owned by the authenticated principal. Requires access to the prewarming beta. */ - readonly "getThread": ( - threadId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentEnvironments": { + ( + options: { readonly params?: typeof ListAgentEnvironmentsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentEnvironments400", ListAgentEnvironments400> + | OpenAiClientError<"ListAgentEnvironments401", ListAgentEnvironments401> + | OpenAiClientError<"ListAgentEnvironments403", ListAgentEnvironments403> + | OpenAiClientError<"ListAgentEnvironments404", ListAgentEnvironments404> + | OpenAiClientError<"ListAgentEnvironments409", ListAgentEnvironments409> + | OpenAiClientError<"ListAgentEnvironments500", ListAgentEnvironments500> + | OpenAiClientError<"ListAgentEnvironments503", ListAgentEnvironments503> + > + ( + options: { + readonly params?: typeof ListAgentEnvironmentsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentEnvironments400", ListAgentEnvironments400> + | OpenAiClientError<"ListAgentEnvironments401", ListAgentEnvironments401> + | OpenAiClientError<"ListAgentEnvironments403", ListAgentEnvironments403> + | OpenAiClientError<"ListAgentEnvironments404", ListAgentEnvironments404> + | OpenAiClientError<"ListAgentEnvironments409", ListAgentEnvironments409> + | OpenAiClientError<"ListAgentEnvironments500", ListAgentEnvironments500> + | OpenAiClientError<"ListAgentEnvironments503", ListAgentEnvironments503> + > + } /** - * Modifies a thread. + * Creates an OpenAI-hosted environment before creating a session. Requires access to the prewarming beta. */ - readonly "modifyThread": ( - threadId: string, - options: { readonly payload: typeof ModifyThreadRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createAgentEnvironment": { + ( + options: { + readonly params?: typeof CreateAgentEnvironmentParams2.Encoded | undefined + readonly payload: typeof CreateAgentEnvironmentRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentEnvironment400", CreateAgentEnvironment400> + | OpenAiClientError<"CreateAgentEnvironment401", CreateAgentEnvironment401> + | OpenAiClientError<"CreateAgentEnvironment403", CreateAgentEnvironment403> + | OpenAiClientError<"CreateAgentEnvironment404", CreateAgentEnvironment404> + | OpenAiClientError<"CreateAgentEnvironment409", CreateAgentEnvironment409> + | OpenAiClientError<"CreateAgentEnvironment429", CreateAgentEnvironment429> + | OpenAiClientError<"CreateAgentEnvironment500", CreateAgentEnvironment500> + | OpenAiClientError<"CreateAgentEnvironment503", CreateAgentEnvironment503> + > + ( + options: { + readonly params?: typeof CreateAgentEnvironmentParams2.Encoded | undefined + readonly payload: typeof CreateAgentEnvironmentRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentEnvironment400", CreateAgentEnvironment400> + | OpenAiClientError<"CreateAgentEnvironment401", CreateAgentEnvironment401> + | OpenAiClientError<"CreateAgentEnvironment403", CreateAgentEnvironment403> + | OpenAiClientError<"CreateAgentEnvironment404", CreateAgentEnvironment404> + | OpenAiClientError<"CreateAgentEnvironment409", CreateAgentEnvironment409> + | OpenAiClientError<"CreateAgentEnvironment429", CreateAgentEnvironment429> + | OpenAiClientError<"CreateAgentEnvironment500", CreateAgentEnvironment500> + | OpenAiClientError<"CreateAgentEnvironment503", CreateAgentEnvironment503> + > + } /** - * Delete a thread. + * Retrieves an execution environment's connection status and safe installed metadata. See [environment lifecycle](https://developers.openai.com/api/docs/guides/agents-api/environments/lifecycle). */ - readonly "deleteThread": ( - threadId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentEnvironment": { + ( + environmentId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentEnvironment400", RetrieveAgentEnvironment400> + | OpenAiClientError<"RetrieveAgentEnvironment401", RetrieveAgentEnvironment401> + | OpenAiClientError<"RetrieveAgentEnvironment403", RetrieveAgentEnvironment403> + | OpenAiClientError<"RetrieveAgentEnvironment404", RetrieveAgentEnvironment404> + | OpenAiClientError<"RetrieveAgentEnvironment409", RetrieveAgentEnvironment409> + | OpenAiClientError<"RetrieveAgentEnvironment500", RetrieveAgentEnvironment500> + | OpenAiClientError<"RetrieveAgentEnvironment503", RetrieveAgentEnvironment503> + > + ( + environmentId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentEnvironment400", RetrieveAgentEnvironment400> + | OpenAiClientError<"RetrieveAgentEnvironment401", RetrieveAgentEnvironment401> + | OpenAiClientError<"RetrieveAgentEnvironment403", RetrieveAgentEnvironment403> + | OpenAiClientError<"RetrieveAgentEnvironment404", RetrieveAgentEnvironment404> + | OpenAiClientError<"RetrieveAgentEnvironment409", RetrieveAgentEnvironment409> + | OpenAiClientError<"RetrieveAgentEnvironment500", RetrieveAgentEnvironment500> + | OpenAiClientError<"RetrieveAgentEnvironment503", RetrieveAgentEnvironment503> + > + } /** - * Returns a list of messages for a given thread. + * Lists live files on a connected execution environment with optional directory filtering and opaque cursor pagination. See [environment files](https://developers.openai.com/api/docs/guides/agents-api/environments/files). */ - readonly "listMessages": ( - threadId: string, - options: - | { readonly params?: typeof ListMessagesParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentEnvironmentFiles": { + ( + environmentId: string, + options: { readonly params?: typeof ListAgentEnvironmentFilesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentEnvironmentFiles400", ListAgentEnvironmentFiles400> + | OpenAiClientError<"ListAgentEnvironmentFiles401", ListAgentEnvironmentFiles401> + | OpenAiClientError<"ListAgentEnvironmentFiles403", ListAgentEnvironmentFiles403> + | OpenAiClientError<"ListAgentEnvironmentFiles404", ListAgentEnvironmentFiles404> + | OpenAiClientError<"ListAgentEnvironmentFiles409", ListAgentEnvironmentFiles409> + | OpenAiClientError<"ListAgentEnvironmentFiles500", ListAgentEnvironmentFiles500> + | OpenAiClientError<"ListAgentEnvironmentFiles503", ListAgentEnvironmentFiles503> + > + ( + environmentId: string, + options: { + readonly params?: typeof ListAgentEnvironmentFilesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentEnvironmentFiles400", ListAgentEnvironmentFiles400> + | OpenAiClientError<"ListAgentEnvironmentFiles401", ListAgentEnvironmentFiles401> + | OpenAiClientError<"ListAgentEnvironmentFiles403", ListAgentEnvironmentFiles403> + | OpenAiClientError<"ListAgentEnvironmentFiles404", ListAgentEnvironmentFiles404> + | OpenAiClientError<"ListAgentEnvironmentFiles409", ListAgentEnvironmentFiles409> + | OpenAiClientError<"ListAgentEnvironmentFiles500", ListAgentEnvironmentFiles500> + | OpenAiClientError<"ListAgentEnvironmentFiles503", ListAgentEnvironmentFiles503> + > + } /** - * Create a message. + * Copies inline bytes or a Files API file into a connected execution environment. See [environment files](https://developers.openai.com/api/docs/guides/agents-api/environments/files). */ - readonly "createMessage": ( - threadId: string, - options: { readonly payload: typeof CreateMessageRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createAgentEnvironmentFile": { + ( + environmentId: string, + options: { readonly payload: typeof CreateAgentEnvironmentFileRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentEnvironmentFile400", CreateAgentEnvironmentFile400> + | OpenAiClientError<"CreateAgentEnvironmentFile401", CreateAgentEnvironmentFile401> + | OpenAiClientError<"CreateAgentEnvironmentFile403", CreateAgentEnvironmentFile403> + | OpenAiClientError<"CreateAgentEnvironmentFile404", CreateAgentEnvironmentFile404> + | OpenAiClientError<"CreateAgentEnvironmentFile409", CreateAgentEnvironmentFile409> + | OpenAiClientError<"CreateAgentEnvironmentFile429", CreateAgentEnvironmentFile429> + | OpenAiClientError<"CreateAgentEnvironmentFile500", CreateAgentEnvironmentFile500> + | OpenAiClientError<"CreateAgentEnvironmentFile503", CreateAgentEnvironmentFile503> + > + ( + environmentId: string, + options: { + readonly payload: typeof CreateAgentEnvironmentFileRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentEnvironmentFile400", CreateAgentEnvironmentFile400> + | OpenAiClientError<"CreateAgentEnvironmentFile401", CreateAgentEnvironmentFile401> + | OpenAiClientError<"CreateAgentEnvironmentFile403", CreateAgentEnvironmentFile403> + | OpenAiClientError<"CreateAgentEnvironmentFile404", CreateAgentEnvironmentFile404> + | OpenAiClientError<"CreateAgentEnvironmentFile409", CreateAgentEnvironmentFile409> + | OpenAiClientError<"CreateAgentEnvironmentFile429", CreateAgentEnvironmentFile429> + | OpenAiClientError<"CreateAgentEnvironmentFile500", CreateAgentEnvironmentFile500> + | OpenAiClientError<"CreateAgentEnvironmentFile503", CreateAgentEnvironmentFile503> + > + } /** - * Retrieve a message. + * Lists subagents in a session, including nested and closed subagents. See [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent). */ - readonly "getMessage": ( - threadId: string, - messageId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionSubagents": { + ( + sessionId: string, + options: { readonly params?: typeof ListAgentSessionSubagentsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionSubagents400", ListAgentSessionSubagents400> + | OpenAiClientError<"ListAgentSessionSubagents401", ListAgentSessionSubagents401> + | OpenAiClientError<"ListAgentSessionSubagents403", ListAgentSessionSubagents403> + | OpenAiClientError<"ListAgentSessionSubagents404", ListAgentSessionSubagents404> + | OpenAiClientError<"ListAgentSessionSubagents409", ListAgentSessionSubagents409> + | OpenAiClientError<"ListAgentSessionSubagents500", ListAgentSessionSubagents500> + | OpenAiClientError<"ListAgentSessionSubagents503", ListAgentSessionSubagents503> + > + ( + sessionId: string, + options: { + readonly params?: typeof ListAgentSessionSubagentsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionSubagents400", ListAgentSessionSubagents400> + | OpenAiClientError<"ListAgentSessionSubagents401", ListAgentSessionSubagents401> + | OpenAiClientError<"ListAgentSessionSubagents403", ListAgentSessionSubagents403> + | OpenAiClientError<"ListAgentSessionSubagents404", ListAgentSessionSubagents404> + | OpenAiClientError<"ListAgentSessionSubagents409", ListAgentSessionSubagents409> + | OpenAiClientError<"ListAgentSessionSubagents500", ListAgentSessionSubagents500> + | OpenAiClientError<"ListAgentSessionSubagents503", ListAgentSessionSubagents503> + > + } /** - * Modifies a message. + * Retrieves a subagent belonging to this session. See [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent). */ - readonly "modifyMessage": ( - threadId: string, - messageId: string, - options: { readonly payload: typeof ModifyMessageRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentSessionSubagent": { + ( + sessionId: string, + subagentId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionSubagent400", RetrieveAgentSessionSubagent400> + | OpenAiClientError<"RetrieveAgentSessionSubagent401", RetrieveAgentSessionSubagent401> + | OpenAiClientError<"RetrieveAgentSessionSubagent403", RetrieveAgentSessionSubagent403> + | OpenAiClientError<"RetrieveAgentSessionSubagent404", RetrieveAgentSessionSubagent404> + | OpenAiClientError<"RetrieveAgentSessionSubagent409", RetrieveAgentSessionSubagent409> + | OpenAiClientError<"RetrieveAgentSessionSubagent500", RetrieveAgentSessionSubagent500> + | OpenAiClientError<"RetrieveAgentSessionSubagent503", RetrieveAgentSessionSubagent503> + > + ( + sessionId: string, + subagentId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionSubagent400", RetrieveAgentSessionSubagent400> + | OpenAiClientError<"RetrieveAgentSessionSubagent401", RetrieveAgentSessionSubagent401> + | OpenAiClientError<"RetrieveAgentSessionSubagent403", RetrieveAgentSessionSubagent403> + | OpenAiClientError<"RetrieveAgentSessionSubagent404", RetrieveAgentSessionSubagent404> + | OpenAiClientError<"RetrieveAgentSessionSubagent409", RetrieveAgentSessionSubagent409> + | OpenAiClientError<"RetrieveAgentSessionSubagent500", RetrieveAgentSessionSubagent500> + | OpenAiClientError<"RetrieveAgentSessionSubagent503", RetrieveAgentSessionSubagent503> + > + } /** - * Deletes a message. + * Lists this subagent's own items across all of its turns. See [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent). */ - readonly "deleteMessage": ( - threadId: string, - messageId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionSubagentItems": { + ( + sessionId: string, + subagentId: string, + options: { + readonly params?: typeof ListAgentSessionSubagentItemsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionSubagentItems400", ListAgentSessionSubagentItems400> + | OpenAiClientError<"ListAgentSessionSubagentItems401", ListAgentSessionSubagentItems401> + | OpenAiClientError<"ListAgentSessionSubagentItems403", ListAgentSessionSubagentItems403> + | OpenAiClientError<"ListAgentSessionSubagentItems404", ListAgentSessionSubagentItems404> + | OpenAiClientError<"ListAgentSessionSubagentItems409", ListAgentSessionSubagentItems409> + | OpenAiClientError<"ListAgentSessionSubagentItems500", ListAgentSessionSubagentItems500> + | OpenAiClientError<"ListAgentSessionSubagentItems503", ListAgentSessionSubagentItems503> + > + ( + sessionId: string, + subagentId: string, + options: { + readonly params?: typeof ListAgentSessionSubagentItemsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionSubagentItems400", ListAgentSessionSubagentItems400> + | OpenAiClientError<"ListAgentSessionSubagentItems401", ListAgentSessionSubagentItems401> + | OpenAiClientError<"ListAgentSessionSubagentItems403", ListAgentSessionSubagentItems403> + | OpenAiClientError<"ListAgentSessionSubagentItems404", ListAgentSessionSubagentItems404> + | OpenAiClientError<"ListAgentSessionSubagentItems409", ListAgentSessionSubagentItems409> + | OpenAiClientError<"ListAgentSessionSubagentItems500", ListAgentSessionSubagentItems500> + | OpenAiClientError<"ListAgentSessionSubagentItems503", ListAgentSessionSubagentItems503> + > + } /** - * Returns a list of runs belonging to a thread. + * Lists all turns of this subagent, including turns after a resume. See [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent). */ - readonly "listRuns": ( - threadId: string, - options: - | { readonly params?: typeof ListRunsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionSubagentTurns": { + ( + sessionId: string, + subagentId: string, + options: { + readonly params?: typeof ListAgentSessionSubagentTurnsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionSubagentTurns400", ListAgentSessionSubagentTurns400> + | OpenAiClientError<"ListAgentSessionSubagentTurns401", ListAgentSessionSubagentTurns401> + | OpenAiClientError<"ListAgentSessionSubagentTurns403", ListAgentSessionSubagentTurns403> + | OpenAiClientError<"ListAgentSessionSubagentTurns404", ListAgentSessionSubagentTurns404> + | OpenAiClientError<"ListAgentSessionSubagentTurns409", ListAgentSessionSubagentTurns409> + | OpenAiClientError<"ListAgentSessionSubagentTurns500", ListAgentSessionSubagentTurns500> + | OpenAiClientError<"ListAgentSessionSubagentTurns503", ListAgentSessionSubagentTurns503> + > + ( + sessionId: string, + subagentId: string, + options: { + readonly params?: typeof ListAgentSessionSubagentTurnsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionSubagentTurns400", ListAgentSessionSubagentTurns400> + | OpenAiClientError<"ListAgentSessionSubagentTurns401", ListAgentSessionSubagentTurns401> + | OpenAiClientError<"ListAgentSessionSubagentTurns403", ListAgentSessionSubagentTurns403> + | OpenAiClientError<"ListAgentSessionSubagentTurns404", ListAgentSessionSubagentTurns404> + | OpenAiClientError<"ListAgentSessionSubagentTurns409", ListAgentSessionSubagentTurns409> + | OpenAiClientError<"ListAgentSessionSubagentTurns500", ListAgentSessionSubagentTurns500> + | OpenAiClientError<"ListAgentSessionSubagentTurns503", ListAgentSessionSubagentTurns503> + > + } /** - * Create a run. + * Retrieves a turn belonging to this subagent. See [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent). */ - readonly "createRun": ( - threadId: string, - options: { - readonly params?: typeof CreateRunParams.Encoded | undefined - readonly payload: typeof CreateRunRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentSessionSubagentTurn": { + ( + sessionId: string, + subagentId: string, + turnId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn400", RetrieveAgentSessionSubagentTurn400> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn401", RetrieveAgentSessionSubagentTurn401> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn403", RetrieveAgentSessionSubagentTurn403> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn404", RetrieveAgentSessionSubagentTurn404> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn409", RetrieveAgentSessionSubagentTurn409> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn500", RetrieveAgentSessionSubagentTurn500> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn503", RetrieveAgentSessionSubagentTurn503> + > + ( + sessionId: string, + subagentId: string, + turnId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn400", RetrieveAgentSessionSubagentTurn400> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn401", RetrieveAgentSessionSubagentTurn401> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn403", RetrieveAgentSessionSubagentTurn403> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn404", RetrieveAgentSessionSubagentTurn404> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn409", RetrieveAgentSessionSubagentTurn409> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn500", RetrieveAgentSessionSubagentTurn500> + | OpenAiClientError<"RetrieveAgentSessionSubagentTurn503", RetrieveAgentSessionSubagentTurn503> + > + } /** - * Retrieves a run. + * Lists items belonging to one turn of this subagent. See [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent). */ - readonly "getRun": ( - threadId: string, - runId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect, HttpClientError.HttpClientError | SchemaError> + readonly "listAgentSessionSubagentTurnItems": { + ( + sessionId: string, + subagentId: string, + turnId: string, + options: { + readonly params?: typeof ListAgentSessionSubagentTurnItemsParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionSubagentTurnItems400", ListAgentSessionSubagentTurnItems400> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems401", ListAgentSessionSubagentTurnItems401> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems403", ListAgentSessionSubagentTurnItems403> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems404", ListAgentSessionSubagentTurnItems404> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems409", ListAgentSessionSubagentTurnItems409> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems500", ListAgentSessionSubagentTurnItems500> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems503", ListAgentSessionSubagentTurnItems503> + > + ( + sessionId: string, + subagentId: string, + turnId: string, + options: { + readonly params?: typeof ListAgentSessionSubagentTurnItemsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionSubagentTurnItems400", ListAgentSessionSubagentTurnItems400> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems401", ListAgentSessionSubagentTurnItems401> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems403", ListAgentSessionSubagentTurnItems403> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems404", ListAgentSessionSubagentTurnItems404> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems409", ListAgentSessionSubagentTurnItems409> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems500", ListAgentSessionSubagentTurnItems500> + | OpenAiClientError<"ListAgentSessionSubagentTurnItems503", ListAgentSessionSubagentTurnItems503> + > + } /** - * Modifies a run. + * Lists reusable agents in the current project. See [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration). */ - readonly "modifyRun": ( - threadId: string, - runId: string, - options: { readonly payload: typeof ModifyRunRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgents": { + ( + options: { readonly params?: typeof ListAgentsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgents400", ListAgents400> + | OpenAiClientError<"ListAgents401", ListAgents401> + | OpenAiClientError<"ListAgents403", ListAgents403> + | OpenAiClientError<"ListAgents404", ListAgents404> + | OpenAiClientError<"ListAgents409", ListAgents409> + | OpenAiClientError<"ListAgents500", ListAgents500> + | OpenAiClientError<"ListAgents503", ListAgents503> + > + ( + options: + | { readonly params?: typeof ListAgentsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgents400", ListAgents400> + | OpenAiClientError<"ListAgents401", ListAgents401> + | OpenAiClientError<"ListAgents403", ListAgents403> + | OpenAiClientError<"ListAgents404", ListAgents404> + | OpenAiClientError<"ListAgents409", ListAgents409> + | OpenAiClientError<"ListAgents500", ListAgents500> + | OpenAiClientError<"ListAgents503", ListAgents503> + > + } /** - * Cancels a run that is `in_progress`. + * Creates a reusable agent without storing credentials. See [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration). */ - readonly "cancelRun": ( - threadId: string, - runId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createAgent": { + ( + options: { readonly payload: typeof CreateAgentRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgent400", CreateAgent400> + | OpenAiClientError<"CreateAgent401", CreateAgent401> + | OpenAiClientError<"CreateAgent403", CreateAgent403> + | OpenAiClientError<"CreateAgent404", CreateAgent404> + | OpenAiClientError<"CreateAgent409", CreateAgent409> + | OpenAiClientError<"CreateAgent500", CreateAgent500> + | OpenAiClientError<"CreateAgent503", CreateAgent503> + > + ( + options: { readonly payload: typeof CreateAgentRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgent400", CreateAgent400> + | OpenAiClientError<"CreateAgent401", CreateAgent401> + | OpenAiClientError<"CreateAgent403", CreateAgent403> + | OpenAiClientError<"CreateAgent404", CreateAgent404> + | OpenAiClientError<"CreateAgent409", CreateAgent409> + | OpenAiClientError<"CreateAgent500", CreateAgent500> + | OpenAiClientError<"CreateAgent503", CreateAgent503> + > + } /** - * Returns a list of run steps belonging to a run. + * Retrieves a reusable agent by ID. See [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration). */ - readonly "listRunSteps": ( - threadId: string, - runId: string, - options: - | { readonly params?: typeof ListRunStepsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgent": { + ( + agentId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgent400", RetrieveAgent400> + | OpenAiClientError<"RetrieveAgent401", RetrieveAgent401> + | OpenAiClientError<"RetrieveAgent403", RetrieveAgent403> + | OpenAiClientError<"RetrieveAgent404", RetrieveAgent404> + | OpenAiClientError<"RetrieveAgent409", RetrieveAgent409> + | OpenAiClientError<"RetrieveAgent500", RetrieveAgent500> + | OpenAiClientError<"RetrieveAgent503", RetrieveAgent503> + > + ( + agentId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgent400", RetrieveAgent400> + | OpenAiClientError<"RetrieveAgent401", RetrieveAgent401> + | OpenAiClientError<"RetrieveAgent403", RetrieveAgent403> + | OpenAiClientError<"RetrieveAgent404", RetrieveAgent404> + | OpenAiClientError<"RetrieveAgent409", RetrieveAgent409> + | OpenAiClientError<"RetrieveAgent500", RetrieveAgent500> + | OpenAiClientError<"RetrieveAgent503", RetrieveAgent503> + > + } /** - * Retrieves a run step. + * Updates a reusable agent. See [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration). */ - readonly "getRunStep": ( - threadId: string, - runId: string, - stepId: string, - options: - | { readonly params?: typeof GetRunStepParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateAgent": { + ( + agentId: string, + options: { readonly payload: typeof UpdateAgentRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateAgent400", UpdateAgent400> + | OpenAiClientError<"UpdateAgent401", UpdateAgent401> + | OpenAiClientError<"UpdateAgent403", UpdateAgent403> + | OpenAiClientError<"UpdateAgent404", UpdateAgent404> + | OpenAiClientError<"UpdateAgent409", UpdateAgent409> + | OpenAiClientError<"UpdateAgent500", UpdateAgent500> + | OpenAiClientError<"UpdateAgent503", UpdateAgent503> + > + ( + agentId: string, + options: { readonly payload: typeof UpdateAgentRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateAgent400", UpdateAgent400> + | OpenAiClientError<"UpdateAgent401", UpdateAgent401> + | OpenAiClientError<"UpdateAgent403", UpdateAgent403> + | OpenAiClientError<"UpdateAgent404", UpdateAgent404> + | OpenAiClientError<"UpdateAgent409", UpdateAgent409> + | OpenAiClientError<"UpdateAgent500", UpdateAgent500> + | OpenAiClientError<"UpdateAgent503", UpdateAgent503> + > + } /** - * When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. + * Deletes a reusable agent. See [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration). */ - readonly "submitToolOuputsToRun": ( - threadId: string, - runId: string, - options: { readonly payload: typeof SubmitToolOuputsToRunRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteAgent": { + ( + agentId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteAgent400", DeleteAgent400> + | OpenAiClientError<"DeleteAgent401", DeleteAgent401> + | OpenAiClientError<"DeleteAgent403", DeleteAgent403> + | OpenAiClientError<"DeleteAgent404", DeleteAgent404> + | OpenAiClientError<"DeleteAgent409", DeleteAgent409> + | OpenAiClientError<"DeleteAgent500", DeleteAgent500> + | OpenAiClientError<"DeleteAgent503", DeleteAgent503> + > + ( + agentId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteAgent400", DeleteAgent400> + | OpenAiClientError<"DeleteAgent401", DeleteAgent401> + | OpenAiClientError<"DeleteAgent403", DeleteAgent403> + | OpenAiClientError<"DeleteAgent404", DeleteAgent404> + | OpenAiClientError<"DeleteAgent409", DeleteAgent409> + | OpenAiClientError<"DeleteAgent500", DeleteAgent500> + | OpenAiClientError<"DeleteAgent503", DeleteAgent503> + > + } /** - * Creates an intermediate [Upload](/docs/api-reference/uploads/object) object - * that you can add [Parts](/docs/api-reference/uploads/part-object) to. - * Currently, an Upload can accept at most 8 GB in total and expires after an - * hour after you create it. - * - * Once you complete the Upload, we will create a - * [File](/docs/api-reference/files/object) object that contains all the parts - * you uploaded. This File is usable in the rest of our platform as a regular - * File object. - * - * For certain `purpose` values, the correct `mime_type` must be specified. - * Please refer to documentation for the - * [supported MIME types for your use case](/docs/assistants/tools/file-search#supported-files). - * - * For guidance on the proper filename extensions for each purpose, please - * follow the documentation on [creating a - * File](/docs/api-reference/files/create). - * - * Returns the Upload object with status `pending`. + * Lists reusable environment templates without returning confidential values. See [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup). */ - readonly "createUpload": ( - options: { readonly payload: typeof CreateUploadRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentEnvironmentTemplates": { + ( + options: { + readonly params?: typeof ListAgentEnvironmentTemplatesParams.Encoded | undefined + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentEnvironmentTemplates400", ListAgentEnvironmentTemplates400> + | OpenAiClientError<"ListAgentEnvironmentTemplates401", ListAgentEnvironmentTemplates401> + | OpenAiClientError<"ListAgentEnvironmentTemplates403", ListAgentEnvironmentTemplates403> + | OpenAiClientError<"ListAgentEnvironmentTemplates404", ListAgentEnvironmentTemplates404> + | OpenAiClientError<"ListAgentEnvironmentTemplates500", ListAgentEnvironmentTemplates500> + | OpenAiClientError<"ListAgentEnvironmentTemplates503", ListAgentEnvironmentTemplates503> + > + ( + options: { + readonly params?: typeof ListAgentEnvironmentTemplatesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentEnvironmentTemplates400", ListAgentEnvironmentTemplates400> + | OpenAiClientError<"ListAgentEnvironmentTemplates401", ListAgentEnvironmentTemplates401> + | OpenAiClientError<"ListAgentEnvironmentTemplates403", ListAgentEnvironmentTemplates403> + | OpenAiClientError<"ListAgentEnvironmentTemplates404", ListAgentEnvironmentTemplates404> + | OpenAiClientError<"ListAgentEnvironmentTemplates500", ListAgentEnvironmentTemplates500> + | OpenAiClientError<"ListAgentEnvironmentTemplates503", ListAgentEnvironmentTemplates503> + > + } /** - * Cancels the Upload. No Parts may be added after an Upload is cancelled. - * - * Returns the Upload object with status `cancelled`. + * Creates reusable environment configuration without returning confidential setup commands or environment values. See [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup). */ - readonly "cancelUpload": ( - uploadId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createAgentEnvironmentTemplate": { + ( + options: { readonly payload: typeof CreateAgentEnvironmentTemplateRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentEnvironmentTemplate400", CreateAgentEnvironmentTemplate400> + | OpenAiClientError<"CreateAgentEnvironmentTemplate401", CreateAgentEnvironmentTemplate401> + | OpenAiClientError<"CreateAgentEnvironmentTemplate403", CreateAgentEnvironmentTemplate403> + | OpenAiClientError<"CreateAgentEnvironmentTemplate404", CreateAgentEnvironmentTemplate404> + | OpenAiClientError<"CreateAgentEnvironmentTemplate500", CreateAgentEnvironmentTemplate500> + | OpenAiClientError<"CreateAgentEnvironmentTemplate503", CreateAgentEnvironmentTemplate503> + > + ( + options: { + readonly payload: typeof CreateAgentEnvironmentTemplateRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentEnvironmentTemplate400", CreateAgentEnvironmentTemplate400> + | OpenAiClientError<"CreateAgentEnvironmentTemplate401", CreateAgentEnvironmentTemplate401> + | OpenAiClientError<"CreateAgentEnvironmentTemplate403", CreateAgentEnvironmentTemplate403> + | OpenAiClientError<"CreateAgentEnvironmentTemplate404", CreateAgentEnvironmentTemplate404> + | OpenAiClientError<"CreateAgentEnvironmentTemplate500", CreateAgentEnvironmentTemplate500> + | OpenAiClientError<"CreateAgentEnvironmentTemplate503", CreateAgentEnvironmentTemplate503> + > + } /** - * Completes the [Upload](/docs/api-reference/uploads/object). - * - * Within the returned Upload object, there is a nested [File](/docs/api-reference/files/object) object that is ready to use in the rest of the platform. - * - * You can specify the order of the Parts by passing in an ordered list of the Part IDs. - * - * The number of bytes uploaded upon completion must match the number of bytes initially specified when creating the Upload object. No Parts may be added after an Upload is completed. - * Returns the Upload object with status `completed`, including an additional `file` property containing the created usable File object. + * Retrieves reusable environment configuration without returning confidential values. See [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup). */ - readonly "completeUpload": ( - uploadId: string, - options: { readonly payload: typeof CompleteUploadRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentEnvironmentTemplate": { + ( + environmentTemplateId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate400", RetrieveAgentEnvironmentTemplate400> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate401", RetrieveAgentEnvironmentTemplate401> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate403", RetrieveAgentEnvironmentTemplate403> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate404", RetrieveAgentEnvironmentTemplate404> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate500", RetrieveAgentEnvironmentTemplate500> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate503", RetrieveAgentEnvironmentTemplate503> + > + ( + environmentTemplateId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate400", RetrieveAgentEnvironmentTemplate400> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate401", RetrieveAgentEnvironmentTemplate401> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate403", RetrieveAgentEnvironmentTemplate403> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate404", RetrieveAgentEnvironmentTemplate404> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate500", RetrieveAgentEnvironmentTemplate500> + | OpenAiClientError<"RetrieveAgentEnvironmentTemplate503", RetrieveAgentEnvironmentTemplate503> + > + } /** - * Adds a [Part](/docs/api-reference/uploads/part-object) to an [Upload](/docs/api-reference/uploads/object) object. A Part represents a chunk of bytes from the file you are trying to upload. - * - * Each Part can be at most 64 MB, and you can add Parts until you hit the Upload maximum of 8 GB. - * - * It is possible to add multiple Parts in parallel. You can decide the intended order of the Parts when you [complete the Upload](/docs/api-reference/uploads/complete). - */ - readonly "addUploadPart": ( - uploadId: string, - options: { readonly payload: typeof AddUploadPartRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + * Updates reusable environment configuration without returning confidential values. See [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup). + */ + readonly "updateAgentEnvironmentTemplate": { + ( + environmentTemplateId: string, + options: { readonly payload: typeof UpdateAgentEnvironmentTemplateRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateAgentEnvironmentTemplate400", UpdateAgentEnvironmentTemplate400> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate401", UpdateAgentEnvironmentTemplate401> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate403", UpdateAgentEnvironmentTemplate403> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate404", UpdateAgentEnvironmentTemplate404> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate409", UpdateAgentEnvironmentTemplate409> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate500", UpdateAgentEnvironmentTemplate500> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate503", UpdateAgentEnvironmentTemplate503> + > + ( + environmentTemplateId: string, + options: { + readonly payload: typeof UpdateAgentEnvironmentTemplateRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateAgentEnvironmentTemplate400", UpdateAgentEnvironmentTemplate400> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate401", UpdateAgentEnvironmentTemplate401> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate403", UpdateAgentEnvironmentTemplate403> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate404", UpdateAgentEnvironmentTemplate404> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate409", UpdateAgentEnvironmentTemplate409> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate500", UpdateAgentEnvironmentTemplate500> + | OpenAiClientError<"UpdateAgentEnvironmentTemplate503", UpdateAgentEnvironmentTemplate503> + > + } /** - * Returns a list of vector stores. + * Deletes reusable environment configuration and all confidential template inputs. See [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup). */ - readonly "listVectorStores": ( - options: { - readonly params?: typeof ListVectorStoresParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteAgentEnvironmentTemplate": { + ( + environmentTemplateId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteAgentEnvironmentTemplate400", DeleteAgentEnvironmentTemplate400> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate401", DeleteAgentEnvironmentTemplate401> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate403", DeleteAgentEnvironmentTemplate403> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate404", DeleteAgentEnvironmentTemplate404> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate409", DeleteAgentEnvironmentTemplate409> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate500", DeleteAgentEnvironmentTemplate500> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate503", DeleteAgentEnvironmentTemplate503> + > + ( + environmentTemplateId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteAgentEnvironmentTemplate400", DeleteAgentEnvironmentTemplate400> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate401", DeleteAgentEnvironmentTemplate401> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate403", DeleteAgentEnvironmentTemplate403> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate404", DeleteAgentEnvironmentTemplate404> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate409", DeleteAgentEnvironmentTemplate409> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate500", DeleteAgentEnvironmentTemplate500> + | OpenAiClientError<"DeleteAgentEnvironmentTemplate503", DeleteAgentEnvironmentTemplate503> + > + } /** - * Create a vector store. + * Lists managed agent sessions using ID-based pagination and the requested sort order. See [managing sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage). */ - readonly "createVectorStore": ( - options: { readonly payload: typeof CreateVectorStoreRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessions": { + ( + options: { readonly params?: typeof ListAgentSessionsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessions400", ListAgentSessions400> + | OpenAiClientError<"ListAgentSessions401", ListAgentSessions401> + | OpenAiClientError<"ListAgentSessions403", ListAgentSessions403> + | OpenAiClientError<"ListAgentSessions404", ListAgentSessions404> + | OpenAiClientError<"ListAgentSessions409", ListAgentSessions409> + | OpenAiClientError<"ListAgentSessions500", ListAgentSessions500> + | OpenAiClientError<"ListAgentSessions503", ListAgentSessions503> + > + ( + options: { + readonly params?: typeof ListAgentSessionsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessions400", ListAgentSessions400> + | OpenAiClientError<"ListAgentSessions401", ListAgentSessions401> + | OpenAiClientError<"ListAgentSessions403", ListAgentSessions403> + | OpenAiClientError<"ListAgentSessions404", ListAgentSessions404> + | OpenAiClientError<"ListAgentSessions409", ListAgentSessions409> + | OpenAiClientError<"ListAgentSessions500", ListAgentSessions500> + | OpenAiClientError<"ListAgentSessions503", ListAgentSessions503> + > + } /** - * Retrieves a vector store. + * Creates a managed agent session, optionally submits initial input, and returns the session or streams its events when stream is true. See [running sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions). */ - readonly "getVectorStore": ( - vectorStoreId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createAgentSession": { + ( + options: { readonly payload: typeof CreateAgentSessionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentSession400", CreateAgentSession400> + | OpenAiClientError<"CreateAgentSession401", CreateAgentSession401> + | OpenAiClientError<"CreateAgentSession403", CreateAgentSession403> + | OpenAiClientError<"CreateAgentSession404", CreateAgentSession404> + | OpenAiClientError<"CreateAgentSession409", CreateAgentSession409> + | OpenAiClientError<"CreateAgentSession429", CreateAgentSession429> + | OpenAiClientError<"CreateAgentSession500", CreateAgentSession500> + | OpenAiClientError<"CreateAgentSession503", CreateAgentSession503> + > + ( + options: { readonly payload: typeof CreateAgentSessionRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentSession400", CreateAgentSession400> + | OpenAiClientError<"CreateAgentSession401", CreateAgentSession401> + | OpenAiClientError<"CreateAgentSession403", CreateAgentSession403> + | OpenAiClientError<"CreateAgentSession404", CreateAgentSession404> + | OpenAiClientError<"CreateAgentSession409", CreateAgentSession409> + | OpenAiClientError<"CreateAgentSession429", CreateAgentSession429> + | OpenAiClientError<"CreateAgentSession500", CreateAgentSession500> + | OpenAiClientError<"CreateAgentSession503", CreateAgentSession503> + > + } /** - * Modifies a vector store. + * Creates a managed agent session, optionally submits initial input, and returns the session or streams its events when stream is true. See [running sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions). */ - readonly "modifyVectorStore": ( - vectorStoreId: string, - options: { readonly payload: typeof ModifyVectorStoreRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError + readonly "createAgentSessionSse": ( + options: { readonly payload: typeof CreateAgentSessionRequestJson.Encoded } + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: CreateAgentSession201Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof CreateAgentSession201Sse.DecodingServices > /** - * Delete a vector store. + * Retrieves the current state of a managed agent session. See [managing sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage). */ - readonly "deleteVectorStore": ( - vectorStoreId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentSession": { + ( + sessionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSession400", RetrieveAgentSession400> + | OpenAiClientError<"RetrieveAgentSession401", RetrieveAgentSession401> + | OpenAiClientError<"RetrieveAgentSession403", RetrieveAgentSession403> + | OpenAiClientError<"RetrieveAgentSession404", RetrieveAgentSession404> + | OpenAiClientError<"RetrieveAgentSession409", RetrieveAgentSession409> + | OpenAiClientError<"RetrieveAgentSession500", RetrieveAgentSession500> + | OpenAiClientError<"RetrieveAgentSession503", RetrieveAgentSession503> + > + ( + sessionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSession400", RetrieveAgentSession400> + | OpenAiClientError<"RetrieveAgentSession401", RetrieveAgentSession401> + | OpenAiClientError<"RetrieveAgentSession403", RetrieveAgentSession403> + | OpenAiClientError<"RetrieveAgentSession404", RetrieveAgentSession404> + | OpenAiClientError<"RetrieveAgentSession409", RetrieveAgentSession409> + | OpenAiClientError<"RetrieveAgentSession500", RetrieveAgentSession500> + | OpenAiClientError<"RetrieveAgentSession503", RetrieveAgentSession503> + > + } /** - * The maximum number of files in a single batch request is 2000. - * Vector store file attach requests are rate limited per vector store (300 requests per minute across both this endpoint and `/vector_stores/{vector_store_id}/files`). - * For ingesting multiple files into the same vector store, this batch endpoint is recommended. + * Updates session metadata, model, reasoning effort, or service tier. Model settings apply to subsequent turns. Omitted fields are unchanged. See [managing sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage). */ - readonly "createVectorStoreFileBatch": ( - vectorStoreId: string, - options: { - readonly payload: typeof CreateVectorStoreFileBatchRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateAgentSession": { + ( + sessionId: string, + options: { readonly payload: typeof UpdateAgentSessionRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateAgentSession400", UpdateAgentSession400> + | OpenAiClientError<"UpdateAgentSession401", UpdateAgentSession401> + | OpenAiClientError<"UpdateAgentSession403", UpdateAgentSession403> + | OpenAiClientError<"UpdateAgentSession404", UpdateAgentSession404> + | OpenAiClientError<"UpdateAgentSession409", UpdateAgentSession409> + | OpenAiClientError<"UpdateAgentSession500", UpdateAgentSession500> + | OpenAiClientError<"UpdateAgentSession503", UpdateAgentSession503> + > + ( + sessionId: string, + options: { readonly payload: typeof UpdateAgentSessionRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateAgentSession400", UpdateAgentSession400> + | OpenAiClientError<"UpdateAgentSession401", UpdateAgentSession401> + | OpenAiClientError<"UpdateAgentSession403", UpdateAgentSession403> + | OpenAiClientError<"UpdateAgentSession404", UpdateAgentSession404> + | OpenAiClientError<"UpdateAgentSession409", UpdateAgentSession409> + | OpenAiClientError<"UpdateAgentSession500", UpdateAgentSession500> + | OpenAiClientError<"UpdateAgentSession503", UpdateAgentSession503> + > + } /** - * Retrieves a vector store file batch. + * Removes a managed agent session from the public API and returns a deletion confirmation. If backend execution has ended, deletion can cancel a still-open public turn and abandon unpublished outputs. Running execution must be cancelled first. Physical cleanup may continue asynchronously. See [managing sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage). */ - readonly "getVectorStoreFileBatch": ( - vectorStoreId: string, - batchId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteAgentSession": { + ( + sessionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteAgentSession400", DeleteAgentSession400> + | OpenAiClientError<"DeleteAgentSession401", DeleteAgentSession401> + | OpenAiClientError<"DeleteAgentSession403", DeleteAgentSession403> + | OpenAiClientError<"DeleteAgentSession404", DeleteAgentSession404> + | OpenAiClientError<"DeleteAgentSession409", DeleteAgentSession409> + | OpenAiClientError<"DeleteAgentSession500", DeleteAgentSession500> + | OpenAiClientError<"DeleteAgentSession503", DeleteAgentSession503> + > + ( + sessionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteAgentSession400", DeleteAgentSession400> + | OpenAiClientError<"DeleteAgentSession401", DeleteAgentSession401> + | OpenAiClientError<"DeleteAgentSession403", DeleteAgentSession403> + | OpenAiClientError<"DeleteAgentSession404", DeleteAgentSession404> + | OpenAiClientError<"DeleteAgentSession409", DeleteAgentSession409> + | OpenAiClientError<"DeleteAgentSession500", DeleteAgentSession500> + | OpenAiClientError<"DeleteAgentSession503", DeleteAgentSession503> + > + } /** - * Cancel a vector store file batch. This attempts to cancel the processing of files in this batch as soon as possible. + * Lists immutable artifacts published by completed hosted session turns. See [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts). */ - readonly "cancelVectorStoreFileBatch": ( - vectorStoreId: string, - batchId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionArtifacts": { + ( + sessionId: string, + options: { readonly params?: typeof ListAgentSessionArtifactsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionArtifacts400", ListAgentSessionArtifacts400> + | OpenAiClientError<"ListAgentSessionArtifacts401", ListAgentSessionArtifacts401> + | OpenAiClientError<"ListAgentSessionArtifacts403", ListAgentSessionArtifacts403> + | OpenAiClientError<"ListAgentSessionArtifacts404", ListAgentSessionArtifacts404> + | OpenAiClientError<"ListAgentSessionArtifacts409", ListAgentSessionArtifacts409> + | OpenAiClientError<"ListAgentSessionArtifacts500", ListAgentSessionArtifacts500> + | OpenAiClientError<"ListAgentSessionArtifacts503", ListAgentSessionArtifacts503> + > + ( + sessionId: string, + options: { + readonly params?: typeof ListAgentSessionArtifactsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionArtifacts400", ListAgentSessionArtifacts400> + | OpenAiClientError<"ListAgentSessionArtifacts401", ListAgentSessionArtifacts401> + | OpenAiClientError<"ListAgentSessionArtifacts403", ListAgentSessionArtifacts403> + | OpenAiClientError<"ListAgentSessionArtifacts404", ListAgentSessionArtifacts404> + | OpenAiClientError<"ListAgentSessionArtifacts409", ListAgentSessionArtifacts409> + | OpenAiClientError<"ListAgentSessionArtifacts500", ListAgentSessionArtifacts500> + | OpenAiClientError<"ListAgentSessionArtifacts503", ListAgentSessionArtifacts503> + > + } /** - * Returns a list of vector store files in a batch. + * Retrieves immutable metadata for one durable session artifact. See [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts). */ - readonly "listFilesInVectorStoreBatch": ( - vectorStoreId: string, - batchId: string, - options: { - readonly params?: typeof ListFilesInVectorStoreBatchParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentSessionArtifact": { + ( + sessionId: string, + artifactId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionArtifact400", RetrieveAgentSessionArtifact400> + | OpenAiClientError<"RetrieveAgentSessionArtifact401", RetrieveAgentSessionArtifact401> + | OpenAiClientError<"RetrieveAgentSessionArtifact403", RetrieveAgentSessionArtifact403> + | OpenAiClientError<"RetrieveAgentSessionArtifact404", RetrieveAgentSessionArtifact404> + | OpenAiClientError<"RetrieveAgentSessionArtifact409", RetrieveAgentSessionArtifact409> + | OpenAiClientError<"RetrieveAgentSessionArtifact500", RetrieveAgentSessionArtifact500> + | OpenAiClientError<"RetrieveAgentSessionArtifact503", RetrieveAgentSessionArtifact503> + > + ( + sessionId: string, + artifactId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionArtifact400", RetrieveAgentSessionArtifact400> + | OpenAiClientError<"RetrieveAgentSessionArtifact401", RetrieveAgentSessionArtifact401> + | OpenAiClientError<"RetrieveAgentSessionArtifact403", RetrieveAgentSessionArtifact403> + | OpenAiClientError<"RetrieveAgentSessionArtifact404", RetrieveAgentSessionArtifact404> + | OpenAiClientError<"RetrieveAgentSessionArtifact409", RetrieveAgentSessionArtifact409> + | OpenAiClientError<"RetrieveAgentSessionArtifact500", RetrieveAgentSessionArtifact500> + | OpenAiClientError<"RetrieveAgentSessionArtifact503", RetrieveAgentSessionArtifact503> + > + } /** - * Returns a list of vector store files. + * Deletes an immutable session artifact without deleting its live environment file or original Files API object. See [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts). */ - readonly "listVectorStoreFiles": ( - vectorStoreId: string, - options: { - readonly params?: typeof ListVectorStoreFilesParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteAgentSessionArtifact": { + ( + sessionId: string, + artifactId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteAgentSessionArtifact400", DeleteAgentSessionArtifact400> + | OpenAiClientError<"DeleteAgentSessionArtifact401", DeleteAgentSessionArtifact401> + | OpenAiClientError<"DeleteAgentSessionArtifact403", DeleteAgentSessionArtifact403> + | OpenAiClientError<"DeleteAgentSessionArtifact404", DeleteAgentSessionArtifact404> + | OpenAiClientError<"DeleteAgentSessionArtifact409", DeleteAgentSessionArtifact409> + | OpenAiClientError<"DeleteAgentSessionArtifact500", DeleteAgentSessionArtifact500> + | OpenAiClientError<"DeleteAgentSessionArtifact503", DeleteAgentSessionArtifact503> + > + ( + sessionId: string, + artifactId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteAgentSessionArtifact400", DeleteAgentSessionArtifact400> + | OpenAiClientError<"DeleteAgentSessionArtifact401", DeleteAgentSessionArtifact401> + | OpenAiClientError<"DeleteAgentSessionArtifact403", DeleteAgentSessionArtifact403> + | OpenAiClientError<"DeleteAgentSessionArtifact404", DeleteAgentSessionArtifact404> + | OpenAiClientError<"DeleteAgentSessionArtifact409", DeleteAgentSessionArtifact409> + | OpenAiClientError<"DeleteAgentSessionArtifact500", DeleteAgentSessionArtifact500> + | OpenAiClientError<"DeleteAgentSessionArtifact503", DeleteAgentSessionArtifact503> + > + } /** - * This endpoint is subject to a per-vector-store write rate limit of 300 requests per minute, shared with `/vector_stores/{vector_store_id}/file_batches`. - * For uploading multiple files to the same vector store, use the file batches endpoint to reduce request volume. + * Downloads immutable session artifact bytes after the execution environment expires. See [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts). */ - readonly "createVectorStoreFile": ( - vectorStoreId: string, - options: { readonly payload: typeof CreateVectorStoreFileRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentSessionArtifactContent": { + ( + sessionId: string, + artifactId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionArtifactContent400", RetrieveAgentSessionArtifactContent400> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent401", RetrieveAgentSessionArtifactContent401> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent403", RetrieveAgentSessionArtifactContent403> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent404", RetrieveAgentSessionArtifactContent404> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent409", RetrieveAgentSessionArtifactContent409> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent500", RetrieveAgentSessionArtifactContent500> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent503", RetrieveAgentSessionArtifactContent503> + > + ( + sessionId: string, + artifactId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionArtifactContent400", RetrieveAgentSessionArtifactContent400> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent401", RetrieveAgentSessionArtifactContent401> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent403", RetrieveAgentSessionArtifactContent403> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent404", RetrieveAgentSessionArtifactContent404> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent409", RetrieveAgentSessionArtifactContent409> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent500", RetrieveAgentSessionArtifactContent500> + | OpenAiClientError<"RetrieveAgentSessionArtifactContent503", RetrieveAgentSessionArtifactContent503> + > + } /** - * Retrieves a vector store file. + * Downloads immutable session artifact bytes after the execution environment expires. See [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts). */ - readonly "getVectorStoreFile": ( - vectorStoreId: string, - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentSessionArtifactContentStream": ( + sessionId: string, + artifactId: string + ) => Stream.Stream /** - * Update attributes on a vector store file. + * Streams live events for an agent session. See [session events](https://developers.openai.com/api/docs/guides/agents-api/sessions/events). */ - readonly "updateVectorStoreFileAttributes": ( - vectorStoreId: string, - fileId: string, - options: { - readonly payload: typeof UpdateVectorStoreFileAttributesRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionEvents": { + ( + sessionId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionEvents400", ListAgentSessionEvents400> + | OpenAiClientError<"ListAgentSessionEvents401", ListAgentSessionEvents401> + | OpenAiClientError<"ListAgentSessionEvents403", ListAgentSessionEvents403> + | OpenAiClientError<"ListAgentSessionEvents404", ListAgentSessionEvents404> + | OpenAiClientError<"ListAgentSessionEvents409", ListAgentSessionEvents409> + | OpenAiClientError<"ListAgentSessionEvents500", ListAgentSessionEvents500> + | OpenAiClientError<"ListAgentSessionEvents503", ListAgentSessionEvents503> + > + ( + sessionId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionEvents400", ListAgentSessionEvents400> + | OpenAiClientError<"ListAgentSessionEvents401", ListAgentSessionEvents401> + | OpenAiClientError<"ListAgentSessionEvents403", ListAgentSessionEvents403> + | OpenAiClientError<"ListAgentSessionEvents404", ListAgentSessionEvents404> + | OpenAiClientError<"ListAgentSessionEvents409", ListAgentSessionEvents409> + | OpenAiClientError<"ListAgentSessionEvents500", ListAgentSessionEvents500> + | OpenAiClientError<"ListAgentSessionEvents503", ListAgentSessionEvents503> + > + } /** - * Delete a vector store file. This will remove the file from the vector store but the file itself will not be deleted. To delete the file, use the [delete file](/docs/api-reference/files/delete) endpoint. + * Streams live events for an agent session. See [session events](https://developers.openai.com/api/docs/guides/agents-api/sessions/events). */ - readonly "deleteVectorStoreFile": ( - vectorStoreId: string, - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError + readonly "listAgentSessionEventsSse": ( + sessionId: string + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: ListAgentSessionEvents200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof ListAgentSessionEvents200Sse.DecodingServices > /** - * Retrieve the parsed contents of a vector store file. + * Submits message, cancellation, tool-result, or computer-use approval-response events to a managed agent session. Cancellation can recover a still-open turn whose backend execution has ended by marking it cancelled and abandoning unpublished outputs. Saved results, published files, and existing terminal outcomes are preserved. HTTP 202 confirms acceptance, not durable completion. See [session events](https://developers.openai.com/api/docs/guides/agents-api/sessions/events). */ - readonly "retrieveVectorStoreFileContent": ( - vectorStoreId: string, - fileId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createAgentSessionEvents": { + ( + sessionId: string, + options: { + readonly params?: typeof CreateAgentSessionEventsParams.Encoded | undefined + readonly payload: typeof CreateAgentSessionEventsRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentSessionEvents400", CreateAgentSessionEvents400> + | OpenAiClientError<"CreateAgentSessionEvents401", CreateAgentSessionEvents401> + | OpenAiClientError<"CreateAgentSessionEvents403", CreateAgentSessionEvents403> + | OpenAiClientError<"CreateAgentSessionEvents404", CreateAgentSessionEvents404> + | OpenAiClientError<"CreateAgentSessionEvents409", CreateAgentSessionEvents409> + | OpenAiClientError<"CreateAgentSessionEvents500", CreateAgentSessionEvents500> + | OpenAiClientError<"CreateAgentSessionEvents503", CreateAgentSessionEvents503> + > + ( + sessionId: string, + options: { + readonly params?: typeof CreateAgentSessionEventsParams.Encoded | undefined + readonly payload: typeof CreateAgentSessionEventsRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateAgentSessionEvents400", CreateAgentSessionEvents400> + | OpenAiClientError<"CreateAgentSessionEvents401", CreateAgentSessionEvents401> + | OpenAiClientError<"CreateAgentSessionEvents403", CreateAgentSessionEvents403> + | OpenAiClientError<"CreateAgentSessionEvents404", CreateAgentSessionEvents404> + | OpenAiClientError<"CreateAgentSessionEvents409", CreateAgentSessionEvents409> + | OpenAiClientError<"CreateAgentSessionEvents500", CreateAgentSessionEvents500> + | OpenAiClientError<"CreateAgentSessionEvents503", CreateAgentSessionEvents503> + > + } /** - * Search a vector store for relevant chunks based on a query and file attributes filter. + * Lists items produced by the session's root agent, including its interactions with subagents. Each subagent has its own item history. See [inspecting agent output](https://developers.openai.com/api/docs/guides/agents-api/observability). */ - readonly "searchVectorStore": ( - vectorStoreId: string, - options: { readonly payload: typeof SearchVectorStoreRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionItems": { + ( + sessionId: string, + options: { readonly params?: typeof ListAgentSessionItemsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionItems400", ListAgentSessionItems400> + | OpenAiClientError<"ListAgentSessionItems401", ListAgentSessionItems401> + | OpenAiClientError<"ListAgentSessionItems403", ListAgentSessionItems403> + | OpenAiClientError<"ListAgentSessionItems404", ListAgentSessionItems404> + | OpenAiClientError<"ListAgentSessionItems409", ListAgentSessionItems409> + | OpenAiClientError<"ListAgentSessionItems500", ListAgentSessionItems500> + | OpenAiClientError<"ListAgentSessionItems503", ListAgentSessionItems503> + > + ( + sessionId: string, + options: { + readonly params?: typeof ListAgentSessionItemsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionItems400", ListAgentSessionItems400> + | OpenAiClientError<"ListAgentSessionItems401", ListAgentSessionItems401> + | OpenAiClientError<"ListAgentSessionItems403", ListAgentSessionItems403> + | OpenAiClientError<"ListAgentSessionItems404", ListAgentSessionItems404> + | OpenAiClientError<"ListAgentSessionItems409", ListAgentSessionItems409> + | OpenAiClientError<"ListAgentSessionItems500", ListAgentSessionItems500> + | OpenAiClientError<"ListAgentSessionItems503", ListAgentSessionItems503> + > + } /** - * Create a conversation. + * Lists published root-turn traces as OTLP JSON, ordered by turn creation time and ID. Unpublished traces are skipped. Each page returns data available when read; it does not wait for late traces. Trace reads and the JSON response are limited to 16 MiB per request. If the limit is exceeded, request fewer traces. */ - readonly "createConversation": ( - options: { readonly payload: typeof CreateConversationRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionTraces": { + ( + sessionId: string, + options: { readonly params?: typeof ListAgentSessionTracesParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionTraces400", ListAgentSessionTraces400> + | OpenAiClientError<"ListAgentSessionTraces401", ListAgentSessionTraces401> + | OpenAiClientError<"ListAgentSessionTraces403", ListAgentSessionTraces403> + | OpenAiClientError<"ListAgentSessionTraces404", ListAgentSessionTraces404> + | OpenAiClientError<"ListAgentSessionTraces409", ListAgentSessionTraces409> + | OpenAiClientError<"ListAgentSessionTraces500", ListAgentSessionTraces500> + | OpenAiClientError<"ListAgentSessionTraces503", ListAgentSessionTraces503> + > + ( + sessionId: string, + options: { + readonly params?: typeof ListAgentSessionTracesParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionTraces400", ListAgentSessionTraces400> + | OpenAiClientError<"ListAgentSessionTraces401", ListAgentSessionTraces401> + | OpenAiClientError<"ListAgentSessionTraces403", ListAgentSessionTraces403> + | OpenAiClientError<"ListAgentSessionTraces404", ListAgentSessionTraces404> + | OpenAiClientError<"ListAgentSessionTraces409", ListAgentSessionTraces409> + | OpenAiClientError<"ListAgentSessionTraces500", ListAgentSessionTraces500> + | OpenAiClientError<"ListAgentSessionTraces503", ListAgentSessionTraces503> + > + } /** - * Get a conversation + * Lists turns by creation time and turn ID. The after cursor is exclusive in the selected order. See [session turns](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage#inspect-session-turns). */ - readonly "getConversation": ( - conversationId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionTurns": { + ( + sessionId: string, + options: { readonly params?: typeof ListAgentSessionTurnsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionTurns400", ListAgentSessionTurns400> + | OpenAiClientError<"ListAgentSessionTurns401", ListAgentSessionTurns401> + | OpenAiClientError<"ListAgentSessionTurns403", ListAgentSessionTurns403> + | OpenAiClientError<"ListAgentSessionTurns404", ListAgentSessionTurns404> + | OpenAiClientError<"ListAgentSessionTurns409", ListAgentSessionTurns409> + | OpenAiClientError<"ListAgentSessionTurns500", ListAgentSessionTurns500> + | OpenAiClientError<"ListAgentSessionTurns503", ListAgentSessionTurns503> + > + ( + sessionId: string, + options: { + readonly params?: typeof ListAgentSessionTurnsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionTurns400", ListAgentSessionTurns400> + | OpenAiClientError<"ListAgentSessionTurns401", ListAgentSessionTurns401> + | OpenAiClientError<"ListAgentSessionTurns403", ListAgentSessionTurns403> + | OpenAiClientError<"ListAgentSessionTurns404", ListAgentSessionTurns404> + | OpenAiClientError<"ListAgentSessionTurns409", ListAgentSessionTurns409> + | OpenAiClientError<"ListAgentSessionTurns500", ListAgentSessionTurns500> + | OpenAiClientError<"ListAgentSessionTurns503", ListAgentSessionTurns503> + > + } /** - * Update a conversation + * Retrieves a turn's current status, timestamps, usage, and error. Returns 404 if the turn does not belong to the session. See [session turns](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage#inspect-session-turns). */ - readonly "updateConversation": ( - conversationId: string, - options: { readonly payload: typeof UpdateConversationRequestJson.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveAgentSessionTurn": { + ( + sessionId: string, + turnId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionTurn400", RetrieveAgentSessionTurn400> + | OpenAiClientError<"RetrieveAgentSessionTurn401", RetrieveAgentSessionTurn401> + | OpenAiClientError<"RetrieveAgentSessionTurn403", RetrieveAgentSessionTurn403> + | OpenAiClientError<"RetrieveAgentSessionTurn404", RetrieveAgentSessionTurn404> + | OpenAiClientError<"RetrieveAgentSessionTurn409", RetrieveAgentSessionTurn409> + | OpenAiClientError<"RetrieveAgentSessionTurn500", RetrieveAgentSessionTurn500> + | OpenAiClientError<"RetrieveAgentSessionTurn503", RetrieveAgentSessionTurn503> + > + ( + sessionId: string, + turnId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveAgentSessionTurn400", RetrieveAgentSessionTurn400> + | OpenAiClientError<"RetrieveAgentSessionTurn401", RetrieveAgentSessionTurn401> + | OpenAiClientError<"RetrieveAgentSessionTurn403", RetrieveAgentSessionTurn403> + | OpenAiClientError<"RetrieveAgentSessionTurn404", RetrieveAgentSessionTurn404> + | OpenAiClientError<"RetrieveAgentSessionTurn409", RetrieveAgentSessionTurn409> + | OpenAiClientError<"RetrieveAgentSessionTurn500", RetrieveAgentSessionTurn500> + | OpenAiClientError<"RetrieveAgentSessionTurn503", RetrieveAgentSessionTurn503> + > + } /** - * Delete a conversation. Items in the conversation will not be deleted. + * Lists items belonging to one root-agent turn, including its interactions with subagents. See [inspecting agent output](https://developers.openai.com/api/docs/guides/agents-api/observability). */ - readonly "deleteConversation": ( - conversationId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listAgentSessionTurnItems": { + ( + sessionId: string, + turnId: string, + options: { readonly params?: typeof ListAgentSessionTurnItemsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionTurnItems400", ListAgentSessionTurnItems400> + | OpenAiClientError<"ListAgentSessionTurnItems401", ListAgentSessionTurnItems401> + | OpenAiClientError<"ListAgentSessionTurnItems403", ListAgentSessionTurnItems403> + | OpenAiClientError<"ListAgentSessionTurnItems404", ListAgentSessionTurnItems404> + | OpenAiClientError<"ListAgentSessionTurnItems409", ListAgentSessionTurnItems409> + | OpenAiClientError<"ListAgentSessionTurnItems500", ListAgentSessionTurnItems500> + | OpenAiClientError<"ListAgentSessionTurnItems503", ListAgentSessionTurnItems503> + > + ( + sessionId: string, + turnId: string, + options: { + readonly params?: typeof ListAgentSessionTurnItemsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListAgentSessionTurnItems400", ListAgentSessionTurnItems400> + | OpenAiClientError<"ListAgentSessionTurnItems401", ListAgentSessionTurnItems401> + | OpenAiClientError<"ListAgentSessionTurnItems403", ListAgentSessionTurnItems403> + | OpenAiClientError<"ListAgentSessionTurnItems404", ListAgentSessionTurnItems404> + | OpenAiClientError<"ListAgentSessionTurnItems409", ListAgentSessionTurnItems409> + | OpenAiClientError<"ListAgentSessionTurnItems500", ListAgentSessionTurnItems500> + | OpenAiClientError<"ListAgentSessionTurnItems503", ListAgentSessionTurnItems503> + > + } /** - * List recently generated videos for the current project. + * Lists vaults using ID-based pagination. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "ListVideos": ( - options: - | { readonly params?: typeof ListVideosParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listVaults": { + ( + options: { readonly params?: typeof ListVaultsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVaults400", ListVaults400> + | OpenAiClientError<"ListVaults401", ListVaults401> + | OpenAiClientError<"ListVaults403", ListVaults403> + | OpenAiClientError<"ListVaults404", ListVaults404> + | OpenAiClientError<"ListVaults409", ListVaults409> + | OpenAiClientError<"ListVaults500", ListVaults500> + | OpenAiClientError<"ListVaults503", ListVaults503> + > + ( + options: + | { readonly params?: typeof ListVaultsParams.Encoded | undefined; readonly config?: Config | undefined } + | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVaults400", ListVaults400> + | OpenAiClientError<"ListVaults401", ListVaults401> + | OpenAiClientError<"ListVaults403", ListVaults403> + | OpenAiClientError<"ListVaults404", ListVaults404> + | OpenAiClientError<"ListVaults409", ListVaults409> + | OpenAiClientError<"ListVaults500", ListVaults500> + | OpenAiClientError<"ListVaults503", ListVaults503> + > + } /** - * Create a new video generation job from a prompt and optional reference assets. + * Creates a vault for the current project. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "createVideo": ( - options: { readonly payload: typeof CreateVideoRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createVault": { + ( + options: { readonly payload: typeof CreateVaultRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVault400", CreateVault400> + | OpenAiClientError<"CreateVault401", CreateVault401> + | OpenAiClientError<"CreateVault403", CreateVault403> + | OpenAiClientError<"CreateVault404", CreateVault404> + | OpenAiClientError<"CreateVault409", CreateVault409> + | OpenAiClientError<"CreateVault500", CreateVault500> + | OpenAiClientError<"CreateVault503", CreateVault503> + > + ( + options: { readonly payload: typeof CreateVaultRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVault400", CreateVault400> + | OpenAiClientError<"CreateVault401", CreateVault401> + | OpenAiClientError<"CreateVault403", CreateVault403> + | OpenAiClientError<"CreateVault404", CreateVault404> + | OpenAiClientError<"CreateVault409", CreateVault409> + | OpenAiClientError<"CreateVault500", CreateVault500> + | OpenAiClientError<"CreateVault503", CreateVault503> + > + } /** - * Create a character from an uploaded video. + * Retrieves a vault by its ID. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "CreateVideoCharacter": ( - options: { - readonly payload: typeof CreateVideoCharacterRequestFormData.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveVault": { + ( + vaultId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveVault400", RetrieveVault400> + | OpenAiClientError<"RetrieveVault401", RetrieveVault401> + | OpenAiClientError<"RetrieveVault403", RetrieveVault403> + | OpenAiClientError<"RetrieveVault404", RetrieveVault404> + | OpenAiClientError<"RetrieveVault409", RetrieveVault409> + | OpenAiClientError<"RetrieveVault500", RetrieveVault500> + | OpenAiClientError<"RetrieveVault503", RetrieveVault503> + > + ( + vaultId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveVault400", RetrieveVault400> + | OpenAiClientError<"RetrieveVault401", RetrieveVault401> + | OpenAiClientError<"RetrieveVault403", RetrieveVault403> + | OpenAiClientError<"RetrieveVault404", RetrieveVault404> + | OpenAiClientError<"RetrieveVault409", RetrieveVault409> + | OpenAiClientError<"RetrieveVault500", RetrieveVault500> + | OpenAiClientError<"RetrieveVault503", RetrieveVault503> + > + } /** - * Fetch a character. + * Updates the name or metadata of an active vault. Omitted fields remain unchanged. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "GetVideoCharacter": ( - characterId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "updateVault": { + ( + vaultId: string, + options: { readonly payload: typeof UpdateVaultRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateVault400", UpdateVault400> + | OpenAiClientError<"UpdateVault401", UpdateVault401> + | OpenAiClientError<"UpdateVault403", UpdateVault403> + | OpenAiClientError<"UpdateVault404", UpdateVault404> + | OpenAiClientError<"UpdateVault409", UpdateVault409> + | OpenAiClientError<"UpdateVault500", UpdateVault500> + | OpenAiClientError<"UpdateVault503", UpdateVault503> + > + ( + vaultId: string, + options: { readonly payload: typeof UpdateVaultRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateVault400", UpdateVault400> + | OpenAiClientError<"UpdateVault401", UpdateVault401> + | OpenAiClientError<"UpdateVault403", UpdateVault403> + | OpenAiClientError<"UpdateVault404", UpdateVault404> + | OpenAiClientError<"UpdateVault409", UpdateVault409> + | OpenAiClientError<"UpdateVault500", UpdateVault500> + | OpenAiClientError<"UpdateVault503", UpdateVault503> + > + } /** - * Create a new video generation job by editing a source video or existing generated video. + * Deletes a vault and all its credentials. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "CreateVideoEdit": ( - options: { readonly payload: typeof CreateVideoEditRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteVault": { + ( + vaultId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVault400", DeleteVault400> + | OpenAiClientError<"DeleteVault401", DeleteVault401> + | OpenAiClientError<"DeleteVault403", DeleteVault403> + | OpenAiClientError<"DeleteVault404", DeleteVault404> + | OpenAiClientError<"DeleteVault409", DeleteVault409> + | OpenAiClientError<"DeleteVault500", DeleteVault500> + | OpenAiClientError<"DeleteVault503", DeleteVault503> + > + ( + vaultId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVault400", DeleteVault400> + | OpenAiClientError<"DeleteVault401", DeleteVault401> + | OpenAiClientError<"DeleteVault403", DeleteVault403> + | OpenAiClientError<"DeleteVault404", DeleteVault404> + | OpenAiClientError<"DeleteVault409", DeleteVault409> + | OpenAiClientError<"DeleteVault500", DeleteVault500> + | OpenAiClientError<"DeleteVault503", DeleteVault503> + > + } /** - * Create an extension of a completed video. + * Lists a vault's credentials using ID-based pagination without returning secret values. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "CreateVideoExtend": ( - options: { readonly payload: typeof CreateVideoExtendRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "listVaultCredentials": { + ( + vaultId: string, + options: { readonly params?: typeof ListVaultCredentialsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVaultCredentials400", ListVaultCredentials400> + | OpenAiClientError<"ListVaultCredentials401", ListVaultCredentials401> + | OpenAiClientError<"ListVaultCredentials403", ListVaultCredentials403> + | OpenAiClientError<"ListVaultCredentials404", ListVaultCredentials404> + | OpenAiClientError<"ListVaultCredentials409", ListVaultCredentials409> + | OpenAiClientError<"ListVaultCredentials500", ListVaultCredentials500> + | OpenAiClientError<"ListVaultCredentials503", ListVaultCredentials503> + > + ( + vaultId: string, + options: { + readonly params?: typeof ListVaultCredentialsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListVaultCredentials400", ListVaultCredentials400> + | OpenAiClientError<"ListVaultCredentials401", ListVaultCredentials401> + | OpenAiClientError<"ListVaultCredentials403", ListVaultCredentials403> + | OpenAiClientError<"ListVaultCredentials404", ListVaultCredentials404> + | OpenAiClientError<"ListVaultCredentials409", ListVaultCredentials409> + | OpenAiClientError<"ListVaultCredentials500", ListVaultCredentials500> + | OpenAiClientError<"ListVaultCredentials503", ListVaultCredentials503> + > + } /** - * Fetch the latest metadata for a generated video. + * Creates a vault credential. Secret values are write-only and are never returned. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "GetVideo": ( - videoId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "createVaultCredential": { + ( + vaultId: string, + options: { readonly payload: typeof CreateVaultCredentialRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVaultCredential400", CreateVaultCredential400> + | OpenAiClientError<"CreateVaultCredential401", CreateVaultCredential401> + | OpenAiClientError<"CreateVaultCredential403", CreateVaultCredential403> + | OpenAiClientError<"CreateVaultCredential404", CreateVaultCredential404> + | OpenAiClientError<"CreateVaultCredential409", CreateVaultCredential409> + | OpenAiClientError<"CreateVaultCredential500", CreateVaultCredential500> + | OpenAiClientError<"CreateVaultCredential503", CreateVaultCredential503> + > + ( + vaultId: string, + options: { + readonly payload: typeof CreateVaultCredentialRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateVaultCredential400", CreateVaultCredential400> + | OpenAiClientError<"CreateVaultCredential401", CreateVaultCredential401> + | OpenAiClientError<"CreateVaultCredential403", CreateVaultCredential403> + | OpenAiClientError<"CreateVaultCredential404", CreateVaultCredential404> + | OpenAiClientError<"CreateVaultCredential409", CreateVaultCredential409> + | OpenAiClientError<"CreateVaultCredential500", CreateVaultCredential500> + | OpenAiClientError<"CreateVaultCredential503", CreateVaultCredential503> + > + } /** - * Permanently delete a completed or failed video and its stored assets. + * Retrieves vault credential metadata without returning secret values. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "DeleteVideo": ( - videoId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "retrieveVaultCredential": { + ( + vaultId: string, + credentialId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveVaultCredential400", RetrieveVaultCredential400> + | OpenAiClientError<"RetrieveVaultCredential401", RetrieveVaultCredential401> + | OpenAiClientError<"RetrieveVaultCredential403", RetrieveVaultCredential403> + | OpenAiClientError<"RetrieveVaultCredential404", RetrieveVaultCredential404> + | OpenAiClientError<"RetrieveVaultCredential409", RetrieveVaultCredential409> + | OpenAiClientError<"RetrieveVaultCredential500", RetrieveVaultCredential500> + | OpenAiClientError<"RetrieveVaultCredential503", RetrieveVaultCredential503> + > + ( + vaultId: string, + credentialId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveVaultCredential400", RetrieveVaultCredential400> + | OpenAiClientError<"RetrieveVaultCredential401", RetrieveVaultCredential401> + | OpenAiClientError<"RetrieveVaultCredential403", RetrieveVaultCredential403> + | OpenAiClientError<"RetrieveVaultCredential404", RetrieveVaultCredential404> + | OpenAiClientError<"RetrieveVaultCredential409", RetrieveVaultCredential409> + | OpenAiClientError<"RetrieveVaultCredential500", RetrieveVaultCredential500> + | OpenAiClientError<"RetrieveVaultCredential503", RetrieveVaultCredential503> + > + } /** - * Download the generated video bytes or a derived preview asset. - * - * Streams the rendered video content for the specified video job. + * Updates credential metadata or rotates its write-only secret. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "RetrieveVideoContent": ( - videoId: string, - options: { - readonly params?: typeof RetrieveVideoContentParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "rotateVaultCredential": { + ( + vaultId: string, + credentialId: string, + options: { readonly payload: typeof RotateVaultCredentialRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RotateVaultCredential400", RotateVaultCredential400> + | OpenAiClientError<"RotateVaultCredential401", RotateVaultCredential401> + | OpenAiClientError<"RotateVaultCredential403", RotateVaultCredential403> + | OpenAiClientError<"RotateVaultCredential404", RotateVaultCredential404> + | OpenAiClientError<"RotateVaultCredential409", RotateVaultCredential409> + | OpenAiClientError<"RotateVaultCredential500", RotateVaultCredential500> + | OpenAiClientError<"RotateVaultCredential503", RotateVaultCredential503> + > + ( + vaultId: string, + credentialId: string, + options: { + readonly payload: typeof RotateVaultCredentialRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RotateVaultCredential400", RotateVaultCredential400> + | OpenAiClientError<"RotateVaultCredential401", RotateVaultCredential401> + | OpenAiClientError<"RotateVaultCredential403", RotateVaultCredential403> + | OpenAiClientError<"RotateVaultCredential404", RotateVaultCredential404> + | OpenAiClientError<"RotateVaultCredential409", RotateVaultCredential409> + | OpenAiClientError<"RotateVaultCredential500", RotateVaultCredential500> + | OpenAiClientError<"RotateVaultCredential503", RotateVaultCredential503> + > + } /** - * Create a remix of a completed video using a refreshed prompt. + * Deletes a vault credential. See [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults). */ - readonly "CreateVideoRemix": ( - videoId: string, - options: { readonly payload: typeof CreateVideoRemixRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "deleteVaultCredential": { + ( + vaultId: string, + credentialId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVaultCredential400", DeleteVaultCredential400> + | OpenAiClientError<"DeleteVaultCredential401", DeleteVaultCredential401> + | OpenAiClientError<"DeleteVaultCredential403", DeleteVaultCredential403> + | OpenAiClientError<"DeleteVaultCredential404", DeleteVaultCredential404> + | OpenAiClientError<"DeleteVaultCredential409", DeleteVaultCredential409> + | OpenAiClientError<"DeleteVaultCredential500", DeleteVaultCredential500> + | OpenAiClientError<"DeleteVaultCredential503", DeleteVaultCredential503> + > + ( + vaultId: string, + credentialId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteVaultCredential400", DeleteVaultCredential400> + | OpenAiClientError<"DeleteVaultCredential401", DeleteVaultCredential401> + | OpenAiClientError<"DeleteVaultCredential403", DeleteVaultCredential403> + | OpenAiClientError<"DeleteVaultCredential404", DeleteVaultCredential404> + | OpenAiClientError<"DeleteVaultCredential409", DeleteVaultCredential409> + | OpenAiClientError<"DeleteVaultCredential500", DeleteVaultCredential500> + | OpenAiClientError<"DeleteVaultCredential503", DeleteVaultCredential503> + > + } /** - * Returns input token counts of the request. - * - * Returns an object with `object` set to `response.input_tokens` and an `input_tokens` count. + * Returns webhook endpoints for the authenticated project in newest-first order. */ - readonly "Getinputtokencounts": ( - options: { - readonly payload: typeof GetinputtokencountsRequestFormUrlEncoded.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "ListWebhookEndpoints": { + ( + options: { readonly params?: typeof ListWebhookEndpointsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListWebhookEndpoints400", ListWebhookEndpoints400> + | OpenAiClientError<"ListWebhookEndpoints404", ListWebhookEndpoints404> + > + ( + options: { + readonly params?: typeof ListWebhookEndpointsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListWebhookEndpoints400", ListWebhookEndpoints400> + | OpenAiClientError<"ListWebhookEndpoints404", ListWebhookEndpoints404> + > + } /** - * Compact a conversation. Returns a compacted response object. - * - * Learn when and how to compact long-running conversations in the [conversation state guide](/docs/guides/conversation-state#managing-the-context-window). For ZDR-compatible compaction details, see [Compaction (advanced)](/docs/guides/conversation-state#compaction-advanced). + * Creates a webhook endpoint for the authenticated project. */ - readonly "Compactconversation": ( - options: { - readonly payload: typeof CompactconversationRequestFormUrlEncoded.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "CreateWebhookEndpoint": { + ( + options: { readonly payload: typeof CreateWebhookEndpointRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateWebhookEndpoint400", CreateWebhookEndpoint400> + > + ( + options: { + readonly payload: typeof CreateWebhookEndpointRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"CreateWebhookEndpoint400", CreateWebhookEndpoint400> + > + } /** - * List all skills for the current project. + * Retrieves a webhook endpoint for the authenticated project. */ - readonly "ListSkills": ( - options: - | { readonly params?: typeof ListSkillsParams.Encoded | undefined; readonly config?: Config | undefined } - | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "RetrieveWebhookEndpoint": { + ( + webhookEndpointId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveWebhookEndpoint400", RetrieveWebhookEndpoint400> + | OpenAiClientError<"RetrieveWebhookEndpoint404", RetrieveWebhookEndpoint404> + > + ( + webhookEndpointId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RetrieveWebhookEndpoint400", RetrieveWebhookEndpoint400> + | OpenAiClientError<"RetrieveWebhookEndpoint404", RetrieveWebhookEndpoint404> + > + } /** - * Create a new skill. + * Updates a webhook endpoint for the authenticated project. */ - readonly "CreateSkill": ( - options: { readonly payload: typeof CreateSkillRequestFormData.Encoded; readonly config?: Config | undefined } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "UpdateWebhookEndpoint": { + ( + webhookEndpointId: string, + options: { readonly payload: typeof UpdateWebhookEndpointRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateWebhookEndpoint400", UpdateWebhookEndpoint400> + | OpenAiClientError<"UpdateWebhookEndpoint404", UpdateWebhookEndpoint404> + > + ( + webhookEndpointId: string, + options: { + readonly payload: typeof UpdateWebhookEndpointRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"UpdateWebhookEndpoint400", UpdateWebhookEndpoint400> + | OpenAiClientError<"UpdateWebhookEndpoint404", UpdateWebhookEndpoint404> + > + } /** - * Get a skill by its ID. + * Deletes a webhook endpoint for the authenticated project. */ - readonly "GetSkill": ( - skillId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "DeleteWebhookEndpoint": { + ( + webhookEndpointId: string, + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteWebhookEndpoint400", DeleteWebhookEndpoint400> + | OpenAiClientError<"DeleteWebhookEndpoint404", DeleteWebhookEndpoint404> + > + ( + webhookEndpointId: string, + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"DeleteWebhookEndpoint400", DeleteWebhookEndpoint400> + | OpenAiClientError<"DeleteWebhookEndpoint404", DeleteWebhookEndpoint404> + > + } /** - * Update the default version pointer for a skill. + * Rotates the signing secret for a webhook endpoint in the authenticated project. */ - readonly "UpdateSkillDefaultVersion": ( - skillId: string, - options: { - readonly payload: typeof UpdateSkillDefaultVersionRequestFormUrlEncoded.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "RotateWebhookEndpointSigningSecret": { + ( + webhookEndpointId: string, + options: { + readonly payload: typeof RotateWebhookEndpointSigningSecretRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RotateWebhookEndpointSigningSecret400", RotateWebhookEndpointSigningSecret400> + | OpenAiClientError<"RotateWebhookEndpointSigningSecret404", RotateWebhookEndpointSigningSecret404> + > + ( + webhookEndpointId: string, + options: { + readonly payload: typeof RotateWebhookEndpointSigningSecretRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"RotateWebhookEndpointSigningSecret400", RotateWebhookEndpointSigningSecret400> + | OpenAiClientError<"RotateWebhookEndpointSigningSecret404", RotateWebhookEndpointSigningSecret404> + > + } /** - * Delete a skill by its ID. + * Sends a sample event to a webhook endpoint for the authenticated project. */ - readonly "DeleteSkill": ( - skillId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "TestWebhookEndpoint": { + ( + webhookEndpointId: string, + options: { readonly payload: typeof TestWebhookEndpointRequestJson.Encoded; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"TestWebhookEndpoint400", TestWebhookEndpoint400> + | OpenAiClientError<"TestWebhookEndpoint404", TestWebhookEndpoint404> + | OpenAiClientError<"TestWebhookEndpoint500", TestWebhookEndpoint500> + > + ( + webhookEndpointId: string, + options: { readonly payload: typeof TestWebhookEndpointRequestJson.Encoded; readonly config?: Config | undefined } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"TestWebhookEndpoint400", TestWebhookEndpoint400> + | OpenAiClientError<"TestWebhookEndpoint404", TestWebhookEndpoint404> + | OpenAiClientError<"TestWebhookEndpoint500", TestWebhookEndpoint500> + > + } /** - * Download a skill zip bundle by its ID. + * Returns webhook event types visible to the authenticated project. */ - readonly "GetSkillContent": ( - skillId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "ListWebhookEventTypes": { + ( + options: { readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListWebhookEventTypes401", ListWebhookEventTypes401> + > + ( + options: { readonly config?: Config | undefined } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"ListWebhookEventTypes401", ListWebhookEventTypes401> + > + } /** - * List skill versions for a skill. + * Creates a model response. Provide [text](https://developers.openai.com/api/docs/guides/text) or + * [image](https://developers.openai.com/api/docs/guides/images-vision) inputs to generate [text](https://developers.openai.com/api/docs/guides/text) + * or [JSON](https://developers.openai.com/api/docs/guides/structured-outputs) outputs. Have the model call + * your own [custom code](https://developers.openai.com/api/docs/guides/function-calling) or use built-in + * [tools](https://developers.openai.com/api/docs/guides/tools) like [web search](https://developers.openai.com/api/docs/guides/tools-web-search) + * or [file search](https://developers.openai.com/api/docs/guides/tools-file-search) to use your own data + * as input for the model's response. */ - readonly "ListSkillVersions": ( - skillId: string, - options: { - readonly params?: typeof ListSkillVersionsParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "betaCreateResponse": { + ( + options: { + readonly params?: typeof BetaCreateResponseParams.Encoded | undefined + readonly payload: typeof BetaCreateResponseRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaCreateResponse400", BetaCreateResponse400> + | OpenAiClientError<"BetaCreateResponse404", BetaCreateResponse404> + | OpenAiClientError<"BetaCreateResponse429", BetaCreateResponse429> + | OpenAiClientError<"BetaCreateResponse503", BetaCreateResponse503> + > + ( + options: { + readonly params?: typeof BetaCreateResponseParams.Encoded | undefined + readonly payload: typeof BetaCreateResponseRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaCreateResponse400", BetaCreateResponse400> + | OpenAiClientError<"BetaCreateResponse404", BetaCreateResponse404> + | OpenAiClientError<"BetaCreateResponse429", BetaCreateResponse429> + | OpenAiClientError<"BetaCreateResponse503", BetaCreateResponse503> + > + } /** - * Create a new immutable skill version. + * Creates a model response. Provide [text](https://developers.openai.com/api/docs/guides/text) or + * [image](https://developers.openai.com/api/docs/guides/images-vision) inputs to generate [text](https://developers.openai.com/api/docs/guides/text) + * or [JSON](https://developers.openai.com/api/docs/guides/structured-outputs) outputs. Have the model call + * your own [custom code](https://developers.openai.com/api/docs/guides/function-calling) or use built-in + * [tools](https://developers.openai.com/api/docs/guides/tools) like [web search](https://developers.openai.com/api/docs/guides/tools-web-search) + * or [file search](https://developers.openai.com/api/docs/guides/tools-file-search) to use your own data + * as input for the model's response. */ - readonly "CreateSkillVersion": ( - skillId: string, + readonly "betaCreateResponseSse": ( options: { - readonly payload: typeof CreateSkillVersionRequestFormData.Encoded - readonly config?: Config | undefined + readonly params?: typeof BetaCreateResponseParams.Encoded | undefined + readonly payload: typeof BetaCreateResponseRequestJson.Encoded } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError + ) => Stream.Stream< + { readonly event: string; readonly id: string | undefined; readonly data: BetaCreateResponse200Sse }, + HttpClientError.HttpClientError | SchemaError | Sse.Retry | Sse.SseError, + typeof BetaCreateResponse200Sse.DecodingServices > /** - * Get a specific skill version. + * Retrieves a model response with the given ID. */ - readonly "GetSkillVersion": ( - skillId: string, - version: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "betaGetResponse": { + ( + responseId: string, + options: { readonly params?: typeof BetaGetResponseParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaGetResponse404", BetaGetResponse404> + | OpenAiClientError<"BetaGetResponse429", BetaGetResponse429> + > + ( + responseId: string, + options: { + readonly params?: typeof BetaGetResponseParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaGetResponse404", BetaGetResponse404> + | OpenAiClientError<"BetaGetResponse429", BetaGetResponse429> + > + } /** - * Delete a skill version. + * Deletes a model response with the given ID. */ - readonly "DeleteSkillVersion": ( - skillId: string, - version: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "betaDeleteResponse": { + ( + responseId: string, + options: { readonly params?: typeof BetaDeleteResponseParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaDeleteResponse404", BetaDeleteResponse404> + | OpenAiClientError<"BetaDeleteResponse429", BetaDeleteResponse429> + > + ( + responseId: string, + options: { + readonly params?: typeof BetaDeleteResponseParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaDeleteResponse404", BetaDeleteResponse404> + | OpenAiClientError<"BetaDeleteResponse429", BetaDeleteResponse429> + > + } /** - * Download a skill version zip bundle. + * Cancels a model response with the given ID. Only responses created with + * the `background` parameter set to `true` can be cancelled. + * [Learn more](https://developers.openai.com/api/docs/guides/background). */ - readonly "GetSkillVersionContent": ( - skillId: string, - version: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "betaCancelResponse": { + ( + responseId: string, + options: { readonly params?: typeof BetaCancelResponseParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaCancelResponse404", BetaCancelResponse404> + | OpenAiClientError<"BetaCancelResponse429", BetaCancelResponse429> + > + ( + responseId: string, + options: { + readonly params?: typeof BetaCancelResponseParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaCancelResponse404", BetaCancelResponse404> + | OpenAiClientError<"BetaCancelResponse429", BetaCancelResponse429> + > + } /** - * Cancel an active ChatKit session and return its most recent metadata. + * Compact a conversation. Returns a compacted response object. * - * Cancelling prevents new requests from using the issued client secret. - */ - readonly "CancelChatSessionMethod": ( - sessionId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Create a ChatKit session. - */ - readonly "CreateChatSessionMethod": ( - options: { - readonly payload: typeof CreateChatSessionMethodRequestJson.Encoded - readonly config?: Config | undefined - } - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * List items that belong to a ChatKit thread. - */ - readonly "ListThreadItemsMethod": ( - threadId: string, - options: { - readonly params?: typeof ListThreadItemsMethodParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > - /** - * Retrieve a ChatKit thread by its identifier. + * Learn when and how to compact long-running conversations in the [conversation state guide](https://developers.openai.com/api/docs/guides/conversation-state#managing-the-context-window). For ZDR-compatible compaction details, see [Compaction (advanced)](https://developers.openai.com/api/docs/guides/conversation-state#compaction-advanced). */ - readonly "GetThreadMethod": ( - threadId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "betaCompactconversation": { + ( + options: { + readonly params?: typeof BetaCompactconversationParams.Encoded | undefined + readonly payload: typeof BetaCompactconversationRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaCompactconversation400", BetaCompactconversation400> + | OpenAiClientError<"BetaCompactconversation429", BetaCompactconversation429> + | OpenAiClientError<"BetaCompactconversation503", BetaCompactconversation503> + > + ( + options: { + readonly params?: typeof BetaCompactconversationParams.Encoded | undefined + readonly payload: typeof BetaCompactconversationRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaCompactconversation400", BetaCompactconversation400> + | OpenAiClientError<"BetaCompactconversation429", BetaCompactconversation429> + | OpenAiClientError<"BetaCompactconversation503", BetaCompactconversation503> + > + } /** - * Delete a ChatKit thread along with its items and stored attachments. + * Returns a list of input items for a given response. */ - readonly "DeleteThreadMethod": ( - threadId: string, - options: { readonly config?: Config | undefined } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "betaListInputItems": { + ( + responseId: string, + options: { readonly params?: typeof BetaListInputItemsParams.Encoded | undefined; readonly config: Config } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaListInputItems404", BetaListInputItems404> + | OpenAiClientError<"BetaListInputItems429", BetaListInputItems429> + > + ( + responseId: string, + options: { + readonly params?: typeof BetaListInputItemsParams.Encoded | undefined + readonly config?: Config | undefined + } | undefined + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaListInputItems404", BetaListInputItems404> + | OpenAiClientError<"BetaListInputItems429", BetaListInputItems429> + > + } /** - * List ChatKit threads with optional pagination and user filters. + * Returns input token counts of the request. + * + * Returns an object with `object` set to `response.input_tokens` and an `input_tokens` count. */ - readonly "ListThreadsMethod": ( - options: { - readonly params?: typeof ListThreadsMethodParams.Encoded | undefined - readonly config?: Config | undefined - } | undefined - ) => Effect.Effect< - WithOptionalResponse, - HttpClientError.HttpClientError | SchemaError - > + readonly "betaGetinputtokencounts": { + ( + options: { + readonly params?: typeof BetaGetinputtokencountsParams.Encoded | undefined + readonly payload: typeof BetaGetinputtokencountsRequestJson.Encoded + readonly config: Config + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaGetinputtokencounts400", BetaGetinputtokencounts400> + | OpenAiClientError<"BetaGetinputtokencounts429", BetaGetinputtokencounts429> + > + ( + options: { + readonly params?: typeof BetaGetinputtokencountsParams.Encoded | undefined + readonly payload: typeof BetaGetinputtokencountsRequestJson.Encoded + readonly config?: Config | undefined + } + ): Effect.Effect< + WithOptionalResponse, + | HttpClientError.HttpClientError + | SchemaError + | OpenAiClientError<"BetaGetinputtokencounts400", BetaGetinputtokencounts400> + | OpenAiClientError<"BetaGetinputtokencounts429", BetaGetinputtokencounts429> + > + } } export interface OpenAiClientError { diff --git a/repos/effect/packages/ai/openai/src/OpenAiClient.ts b/repos/effect/packages/ai/openai/src/OpenAiClient.ts index 0238e5152a..73a3daeaa0 100644 --- a/repos/effect/packages/ai/openai/src/OpenAiClient.ts +++ b/repos/effect/packages/ai/openai/src/OpenAiClient.ts @@ -38,6 +38,8 @@ import * as Errors from "./internal/errors.ts" import { OpenAiConfig } from "./OpenAiConfig.ts" import * as OpenAiSchema from "./OpenAiSchema.ts" +const decodeResponseStreamEvent = Schema.decodeUnknownEffect(Schema.fromJsonString(OpenAiSchema.ResponseStreamEvent)) + // ============================================================================= // Service Interface // ============================================================================= @@ -88,6 +90,13 @@ export interface Service { readonly createEmbedding: ( options: typeof OpenAiSchema.CreateEmbeddingRequest.Encoded ) => Effect.Effect + + /** + * Answer decision questions using the OpenAI decisions endpoint. + */ + readonly createDecisions: ( + options: typeof OpenAiSchema.CreateDecisionsRequest.Encoded + ) => Effect.Effect } // ============================================================================= @@ -273,13 +282,15 @@ export const make = Effect.fnUntraced( ] => { const stream = response.stream.pipe( Stream.decodeText(), - Stream.pipeThroughChannel(Sse.decodeDataSchema(OpenAiSchema.ResponseStreamEvent)), + Stream.pipeThroughChannel(Sse.decode()), + // Some OpenAI-compatible servers end the stream with `data: [DONE]` + Stream.takeWhile((event) => event.data !== "[DONE]"), + Stream.mapEffect((event) => decodeResponseStreamEvent(event.data)), Stream.takeUntil((event) => - event.data.type === "response.completed" || - event.data.type === "response.incomplete" || - event.data.type === "response.failed" + event.type === "response.completed" || + event.type === "response.incomplete" || + event.type === "response.failed" ), - Stream.map((event) => event.data), Stream.catchTags({ // TODO: handle SSE retries Retry: (error) => Stream.die(error), @@ -311,31 +322,47 @@ export const make = Effect.fnUntraced( ) }) - const decodeEmbedding = HttpClientResponse.schemaBodyJson(OpenAiSchema.CreateEmbeddingResponse) + const postJson = >( + path: string, + schema: Response, + method: string + ) => { + const decode = HttpClientResponse.schemaBodyJson(schema) + return (payload: unknown): Effect.Effect => + resolveHttpClient.pipe( + Effect.flatMap((client) => + client.execute(HttpClientRequest.post(path, { + body: HttpBody.jsonUnsafe(payload) + })).pipe( + Effect.flatMap(decode), + Effect.catchTags({ + HttpClientError: (error) => Errors.mapHttpClientError(error, method), + SchemaError: (error) => Effect.fail(Errors.mapSchemaError(error, method)) + }) + ) + ), + withRedactedHeaders + ) + } + + const createEmbedding: Service["createEmbedding"] = postJson( + "/embeddings", + OpenAiSchema.CreateEmbeddingResponse, + "createEmbedding" + ) - const createEmbedding = ( - payload: typeof OpenAiSchema.CreateEmbeddingRequest.Encoded - ): Effect.Effect => - resolveHttpClient.pipe( - Effect.flatMap((client) => - client.execute(HttpClientRequest.post("/embeddings", { - body: HttpBody.jsonUnsafe(payload) - })).pipe( - Effect.flatMap(decodeEmbedding), - Effect.catchTags({ - HttpClientError: (error) => Errors.mapHttpClientError(error, "createEmbedding"), - SchemaError: (error) => Effect.fail(Errors.mapSchemaError(error, "createEmbedding")) - }) - ) - ), - withRedactedHeaders - ) + const createDecisions: Service["createDecisions"] = postJson( + "/decisions", + OpenAiSchema.CreateDecisionsResponse, + "createDecisions" + ) return OpenAiClient.of({ client: httpClient, createResponse, createResponseStream, - createEmbedding + createEmbedding, + createDecisions }) }, withRedactedHeaders diff --git a/repos/effect/packages/ai/openai/src/OpenAiDecisionModel.ts b/repos/effect/packages/ai/openai/src/OpenAiDecisionModel.ts new file mode 100644 index 0000000000..3e5995b2ed --- /dev/null +++ b/repos/effect/packages/ai/openai/src/OpenAiDecisionModel.ts @@ -0,0 +1,208 @@ +/** + * OpenAI implementation of DecisionModel over the Decisions API. + * + * @stability unstable + * @since 4.0.5 + */ +import * as AiError from "effect/ai/AiError" +import type * as Decision from "effect/ai/Decision" +import * as DecisionModel from "effect/ai/DecisionModel" +import * as AiModel from "effect/ai/Model" +import * as Effect from "effect/Effect" +import * as Base64 from "effect/encoding/Base64" +import * as Layer from "effect/Layer" +import * as Record from "effect/Record" +import { OpenAiClient } from "./OpenAiClient.ts" +import type * as OpenAiSchema from "./OpenAiSchema.ts" + +/** + * OpenAI decision model identifiers. + * + * @stability unstable + * @category models + * @since 4.0.5 + */ +export type Model = typeof OpenAiSchema.CreateDecisionsRequest.Encoded["model"] + +/** + * Creates a decision model with OpenAI provider metadata. + * + * @stability unstable + * @category constructors + * @since 4.0.5 + */ +export const model = ( + model: Model +): AiModel.Model<"openai", DecisionModel.DecisionModel, OpenAiClient> => AiModel.make("openai", model, layer({ model })) + +/** + * Builds a decision service with tolerance for two-decimal probability rounding. + * + * **Details** + * + * String state is sent as `input` unchanged, and other state is sent as JSON. + * With images, `input` becomes one user message with the state as text + * followed by the images. Byte arrays and base64 strings are sent as `data:` + * URLs, and `data:` URLs are sent unchanged. + * + * Probability criteria are appended to the question instructions, and each + * rating level is sent with its label and description. + * String instructions and descriptions are unchanged; structured values and + * null descriptions are serialized with `JSON.stringify`. + * + * **Gotchas** + * + * - Remote URLs fail with `AiError.InvalidUserInputError` because OpenAI only + * accepts inline images. + * - If OpenAI refuses any decision, the whole call fails with + * `AiError.ContentPolicyError`. The refused names are in + * `metadata.openai.refusedDecisions`. + * + * @stability unstable + * @category constructors + * @since 4.0.5 + */ +export const make = Effect.fnUntraced( + function*( + options: { readonly model: Model } + ): Effect.fn.Return { + const client = yield* OpenAiClient + return yield* DecisionModel.make({ + probabilityPrecision: 2, + supportsImages: true, + decide: Effect.fnUntraced(function*({ state, decisions, images }) { + if (images?.some((image) => image.data instanceof URL && image.data.protocol !== "data:")) { + return yield* invalidUserInput("OpenAI decisions accept base64 or data URL images, not remote URLs") + } + const questions: Array = [] + for (const [name, decision] of Object.entries(decisions)) { + questions.push(encodeQuestion(name, decision)) + } + const text = typeof state === "string" ? state : JSON.stringify(state) + const response = yield* client.createDecisions({ + model: options.model, + input: images === undefined ? text : [{ + role: "user", + content: [ + { type: "input_text", text }, + ...images.map((image) => ({ type: "input_image" as const, image_url: encodeImage(image) })) + ] + }], + questions + }) + const answers: Record = Object.create(null) + const refused: Array = [] + for (const answer of response.answers) { + switch (answer.type) { + case "refusal": + refused.push(answer.name) + break + case "choice": + answers[answer.name] = { + _tag: "Classify", + label: answer.choice, + probabilities: Record.fromIterableWith(answer.probabilities, (p) => [p.value, p.probability]), + confidence: answer.confidence + } + break + case "score": { + const decision = decisions[answer.name] + if (decision?._tag !== "Rate") break + const probabilities: Record = Object.create(null) + for (const { value, probability } of answer.probabilities) { + const level = decision.criteria[value] + if (level !== undefined) probabilities[level.label] = probability + } + answers[answer.name] = { + _tag: "Rate", + rating: answer.score, + probabilities, + confidence: answer.confidence + } + break + } + case "predicate": + answers[answer.name] = { _tag: "Probability", probability: answer.probability } + break + } + } + if (refused.length > 0) { + return yield* Effect.fail(AiError.make({ + module: "OpenAiDecisionModel", + method: "decide", + reason: new AiError.ContentPolicyError({ + description: `OpenAI refused to answer: ${refused.join(", ")}`, + metadata: { openai: { errorCode: null, errorType: null, requestId: null, refusedDecisions: refused } } + }) + })) + } + return { + answers, + usage: { inputTokens: response.usage?.input_tokens, outputTokens: response.usage?.output_tokens } + } + }) + }) + } +) + +const invalidUserInput = (description: string) => + Effect.fail(AiError.make({ + module: "OpenAiDecisionModel", + method: "decide", + reason: new AiError.InvalidUserInputError({ description }) + })) + +const encodeQuestion = ( + name: string, + decision: Decision.Any +): typeof OpenAiSchema.DecisionQuestion.Encoded => { + const instructions = encodeDescription(decision.instructions) + switch (decision._tag) { + case "Classify": { + const choices = Object.entries(decision.criteria).map(([value, description]) => ({ + value, + description: encodeDescription(description) + })) + return { type: "choice", name, instructions, choices } + } + case "Rate": + return { + type: "score", + name, + instructions, + levels: decision.criteria.map(({ label, description }) => ({ + label, + description: encodeDescription(description) + })) + } + case "Probability": { + if (decision.criteria === undefined) return { type: "predicate", name, instructions } + const { false: no, true: yes } = decision.criteria + return { + type: "predicate", + name, + instructions: `${instructions}\n\nfalse: ${encodeDescription(no)}\ntrue: ${encodeDescription(yes)}` + } + } + } +} + +const encodeDescription = (description: Decision.Description | null): string => + typeof description === "string" ? description : JSON.stringify(description) + +const encodeImage = (image: DecisionModel.Image): string => + image.data instanceof URL + ? image.data.href + : `data:${image.mediaType};base64,${typeof image.data === "string" ? image.data : Base64.encode(image.data)}` + +/** + * Provides DecisionModel using an existing OpenAiClient. + * + * @stability unstable + * @category layers + * @since 4.0.5 + */ +export const layer = ( + options: { readonly model: Model } +): Layer.Layer => + Layer.effect(DecisionModel.DecisionModel, make(options)) diff --git a/repos/effect/packages/ai/openai/src/OpenAiError.ts b/repos/effect/packages/ai/openai/src/OpenAiError.ts index 1f777293e9..470a9ef03f 100644 --- a/repos/effect/packages/ai/openai/src/OpenAiError.ts +++ b/repos/effect/packages/ai/openai/src/OpenAiError.ts @@ -30,6 +30,25 @@ export type OpenAiErrorMetadata = { readonly requestId: string | null } +/** + * OpenAI-specific content policy metadata fields. + * + * **Details** + * + * Extends base error metadata with the names of decisions that OpenAI refused + * to answer. + * + * @stability unstable + * @category models + * @since 4.0.5 + */ +export type OpenAiContentPolicyMetadata = OpenAiErrorMetadata & { + /** + * Names of the decisions that came back as refusals. + */ + readonly refusedDecisions?: Array +} + /** * OpenAI-specific rate limit metadata fields. * @@ -132,7 +151,7 @@ declare module "effect/ai/AiError" { /** * OpenAI-specific details for the content policy response. */ - readonly openai?: OpenAiErrorMetadata | null + readonly openai?: OpenAiContentPolicyMetadata | null } /** diff --git a/repos/effect/packages/ai/openai/src/OpenAiLanguageModel.ts b/repos/effect/packages/ai/openai/src/OpenAiLanguageModel.ts index f84ac63775..8217553d5b 100644 --- a/repos/effect/packages/ai/openai/src/OpenAiLanguageModel.ts +++ b/repos/effect/packages/ai/openai/src/OpenAiLanguageModel.ts @@ -76,6 +76,8 @@ type PromptCacheBreakpoint = { readonly mode: "explicit" } * Config values are merged with the config object passed to `model`, `make`, or * `layer`, with scoped context values taking precedence. * + * Explicit `include` values are merged with automatic entries without duplicates. + * * @see {@link withConfigOverride} for scoping language model request overrides * * @stability unstable @@ -130,6 +132,19 @@ export class Config extends Context.Service< * Defaults to `true` when `store` is `true`. */ readonly useItemReferences?: boolean | undefined + /** + * Override reasoning model detection. Reasoning models use the `developer` + * role for system prompts and request `reasoning.encrypted_content` when + * item references are disabled or a WebSocket connection is used. + * + * Defaults to `true` except for `gpt-3*`, `gpt-4*`, `chatgpt-*`, + * `chat-latest`, and `gpt--chat*`. Fine-tuned `ft:` models follow + * their base model. + * + * Set to `false` for deployments that do not support these defaults. + * Explicit `include` values are still preserved. + */ + readonly reasoningModel?: boolean | undefined } > >()("@effect/ai-openai/OpenAiLanguageModel/Config") {} @@ -197,9 +212,8 @@ declare module "effect/ai/Prompt" { */ readonly itemId?: string | null /** - * The encrypted content of the reasoning item - populated when a response - * is generated with `reasoning.encrypted_content` in the `include` - * parameter. + * Encrypted reasoning returned by OpenAI for `store: false` or when + * `include` contains `reasoning.encrypted_content`. */ readonly encryptedContent?: string | null } | null @@ -576,7 +590,7 @@ declare module "effect/ai/Response" { /** * The service tier reported by OpenAI for the response. */ - readonly serviceTier?: "default" | "auto" | "flex" | "scale" | "priority" | null + readonly serviceTier?: "default" | "auto" | "flex" | "scale" | "priority" | "ultrafast" | null /** * Prompt cache diagnostics for `prompt_cache_options.comparison_response_id`. */ @@ -662,12 +676,11 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig readonly options: LanguageModel.ProviderOptions readonly toolNameMapper: Tool.NameMapper }): Effect.fn.Return { - const include = new Set() - const capabilities = getModelCapabilities(config.model as string) + const include = new Set(config.include) const messages = yield* prepareMessages({ config, options, - capabilities, + isReasoningModel: resolveReasoningModel(config), include, toolNameMapper }) @@ -684,6 +697,7 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig fileIdPrefixes: _fip, strictJsonSchema: _sjs, useItemReferences: _uir, + reasoningModel: _rm, ...apiConfig } = config const request: Mutable = { @@ -821,26 +835,18 @@ export const withConfigOverride: { // Prompt Conversion // ============================================================================= -const getSystemMessageMode = (model: string): "system" | "developer" => - model.startsWith("o") || - model.startsWith("gpt-5") || - model.startsWith("codex-") || - model.startsWith("computer-use") - ? "developer" - : "system" - const prepareMessages = Effect.fnUntraced( function*>({ config, options, - capabilities, + isReasoningModel, include, toolNameMapper }: { readonly config: typeof Config.Service readonly options: LanguageModel.ProviderOptions readonly include: Set - readonly capabilities: ModelCapabilities + readonly isReasoningModel: boolean readonly toolNameMapper: Tool.NameMapper }): Effect.fn.Return, AiError.AiError> { const processedApprovalIds = new Set() @@ -875,7 +881,7 @@ const prepareMessages = Effect.fnUntraced( if (Predicate.isNotUndefined(config.top_logprobs)) { include.add("message.output_text.logprobs") } - if ((websocketMode || !useItemReferences) && capabilities.isReasoningModel) { + if ((websocketMode || !useItemReferences) && isReasoningModel) { include.add("reasoning.encrypted_content") } if (codeInterpreterTool) { @@ -892,7 +898,7 @@ const prepareMessages = Effect.fnUntraced( switch (message.role) { case "system": { messages.push({ - role: getSystemMessageMode(config.model as string), + role: isReasoningModel ? "developer" : "system", content: [{ type: "input_text", text: message.content, @@ -1556,7 +1562,7 @@ const makeResponse = Effect.fnUntraced( }) }) - const params = yield* transformToolCallParams(options.tools, part.name, toolParams) + const params = yield* transformToolCallParams(options, part.name, toolParams) parts.push({ type: "tool-call", @@ -2343,7 +2349,7 @@ const makeStreamResponse = Effect.fnUntraced( }) }) - const params = yield* transformToolCallParams(options.tools, toolName, toolParams) + const params = yield* transformToolCallParams(options, toolName, toolParams) parts.push({ type: "tool-params-end", @@ -2651,7 +2657,7 @@ const makeStreamResponse = Effect.fnUntraced( }) }) - const params = yield* transformToolCallParams(options.tools, toolCall.name, toolParams) + const params = yield* transformToolCallParams(options, toolCall.name, toolParams) parts.push({ type: "tool-params-end", @@ -3184,52 +3190,16 @@ const prepareResponseFormat = Effect.fnUntraced(function*({ config, options }: { return { type: "text" } }) -interface ModelCapabilities { - readonly isReasoningModel: boolean - readonly systemMessageMode: "remove" | "system" | "developer" - readonly supportsFlexProcessing: boolean - readonly supportsPriorityProcessing: boolean - /** - * Allow temperature, topP, logProbs when reasoningEffort is none. - */ - readonly supportsNonReasoningParameters: boolean -} - -const getModelCapabilities = (modelId: string): ModelCapabilities => { - const supportsFlexProcessing = modelId.startsWith("o3") || - modelId.startsWith("o4-mini") || - (modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat")) - - const supportsPriorityProcessing = modelId.startsWith("gpt-4") || - modelId.startsWith("gpt-5-mini") || - (modelId.startsWith("gpt-5") && - !modelId.startsWith("gpt-5-nano") && - !modelId.startsWith("gpt-5-chat")) || - modelId.startsWith("o3") || - modelId.startsWith("o4-mini") - - // Use allowlist approach: only known reasoning models should use 'developer' role - // This prevents issues with fine-tuned models, third-party models, and custom models - const isReasoningModel = modelId.startsWith("o1") || - modelId.startsWith("o3") || - modelId.startsWith("o4-mini") || - modelId.startsWith("codex-mini") || - modelId.startsWith("computer-use-preview") || - (modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat")) - - // https://platform.openai.com/docs/guides/latest-model#gpt-5-1-parameter-compatibility - // GPT-5.1 and GPT-5.2 support temperature, topP, logProbs when reasoningEffort is none - const supportsNonReasoningParameters = modelId.startsWith("gpt-5.1") || modelId.startsWith("gpt-5.2") - - const systemMessageMode = isReasoningModel ? "developer" : "system" +// Default new model names to reasoning without extending an allowlist. +const nonReasoningModelPattern = /^(?:gpt-[34]|chatgpt-|chat-latest|gpt-\d+(?:\.\d+)?-chat)/ - return { - supportsFlexProcessing, - supportsPriorityProcessing, - isReasoningModel, - systemMessageMode, - supportsNonReasoningParameters +const resolveReasoningModel = (config: typeof Config.Service): boolean => { + if (Predicate.isNotUndefined(config.reasoningModel)) { + return config.reasoningModel } + const model = config.model ?? "" + const baseModel = model.startsWith("ft:") ? model.slice(3) : model + return !nonReasoningModelPattern.test(baseModel) } const getApprovalRequestIdMapping = (prompt: Prompt.Prompt): ReadonlyMap => { @@ -3328,7 +3298,7 @@ const getUsage = (usage: OpenAiSchema.ResponseUsage | null | undefined): Respons } } -type ServiceTier = "default" | "auto" | "flex" | "scale" | "priority" | null +type ServiceTier = "default" | "auto" | "flex" | "scale" | "priority" | "ultrafast" | null const toFinishMetadata = (response: OpenAiSchema.Response): { readonly metadata: Response.FinishPartMetadata @@ -3340,6 +3310,7 @@ const toFinishMetadata = (response: OpenAiSchema.Response): { case "flex": case "scale": case "priority": + case "ultrafast": serviceTier = response.service_tier break } @@ -3362,20 +3333,23 @@ const toFinishMetadata = (response: OpenAiSchema.Response): { const getUsageTokenDetail = (details: unknown, key: string): number | undefined => Predicate.hasProperty(details, key) && typeof details[key] === "number" ? details[key] : undefined -const transformToolCallParams = Effect.fnUntraced(function*>( - tools: Tools, +const transformToolCallParams = Effect.fnUntraced(function*( + options: LanguageModel.ProviderOptions, toolName: string, toolParams: unknown ): Effect.fn.Return { - const tool = tools.find((tool) => tool.name === toolName) + const tool = options.tools.find((tool) => tool.name === toolName) if (Predicate.isUndefined(tool)) { + if (options.toolCallValidation === "deferred") { + return toolParams + } return yield* AiError.make({ module: "OpenAiLanguageModel", method: "makeResponse", reason: new AiError.ToolNotFoundError({ toolName, - availableTools: tools.map((tool) => tool.name) + availableTools: options.tools.map((tool) => tool.name) }) }) } diff --git a/repos/effect/packages/ai/openai/src/OpenAiSchema.ts b/repos/effect/packages/ai/openai/src/OpenAiSchema.ts index f88b492fdb..4849960885 100644 --- a/repos/effect/packages/ai/openai/src/OpenAiSchema.ts +++ b/repos/effect/packages/ai/openai/src/OpenAiSchema.ts @@ -1,8 +1,8 @@ /** * The `OpenAiSchema` module defines the request, response, streaming, and * embedding schemas used by the handwritten OpenAI client. These schemas are - * the transport boundary for JSON sent to and decoded from the Responses and - * embeddings endpoints. + * the transport boundary for JSON sent to and decoded from the Responses, + * embeddings, and decisions endpoints. * * @stability unstable * @since 4.0.0 @@ -1442,3 +1442,193 @@ export const CreateEmbeddingResponse = Schema.Struct({ * @since 4.0.0 */ export type CreateEmbeddingResponse = typeof CreateEmbeddingResponse.Type + +// ============================================================================= +// Decisions +// ============================================================================= + +/** + * Schema for a question sent to the OpenAI Decisions API. + * + * **Details** + * + * A `predicate` asks for the probability that a statement holds. A `choice` + * picks one of the supplied `choices`. A `score` rates against `levels`, + * ordered from lowest to highest. Each question needs a `name` that is unique + * within the request. + * + * @stability unstable + * @category schemas + * @since 4.0.5 + */ +export const DecisionQuestion = Schema.Union([ + Schema.Struct({ + type: Schema.Literal("predicate"), + name: Schema.String, + instructions: Schema.String + }), + Schema.Struct({ + type: Schema.Literal("choice"), + name: Schema.String, + instructions: Schema.String, + choices: Schema.Array(Schema.Struct({ value: Schema.String, description: Schema.String })) + }), + Schema.Struct({ + type: Schema.Literal("score"), + name: Schema.String, + instructions: Schema.String, + levels: Schema.Array(Schema.Struct({ label: Schema.String, description: Schema.String })) + }) +]) + +/** + * A question sent to the OpenAI Decisions API. + * + * @stability unstable + * @category models + * @since 4.0.5 + */ +export type DecisionQuestion = typeof DecisionQuestion.Type + +/** + * Schema for a content part in a Decisions API input message. + * + * **Gotchas** + * + * `image_url` must be an inline base64 `data:` URL. OpenAI rejects hosted + * URLs and file ids. + * + * @stability unstable + * @category schemas + * @since 4.0.5 + */ +export const DecisionInputContent = Schema.Union([ + Schema.Struct({ type: Schema.Literal("input_text"), text: Schema.String }), + Schema.Struct({ type: Schema.Literal("input_image"), image_url: Schema.String }) +]) + +/** + * A content part in a Decisions API input message. + * + * @stability unstable + * @category models + * @since 4.0.5 + */ +export type DecisionInputContent = typeof DecisionInputContent.Type + +/** + * Schema for the request payload sent to `POST /decisions`. + * + * **Details** + * + * `input` is either a string or a list of user messages made of text and image + * parts. + * + * @stability unstable + * @category schemas + * @since 4.0.5 + */ +export const CreateDecisionsRequest = Schema.Struct({ + model: Schema.Union([Schema.Literal("gpt-6-luna"), Schema.StringForLiteralAutocomplete]), + input: Schema.Union([ + Schema.String, + Schema.Array(Schema.Struct({ role: Schema.Literal("user"), content: Schema.Array(DecisionInputContent) })) + ]), + questions: Schema.Array(DecisionQuestion) +}) + +/** + * Request payload sent to `POST /decisions`. + * + * @stability unstable + * @category models + * @since 4.0.5 + */ +export type CreateDecisionsRequest = typeof CreateDecisionsRequest.Type + +/** + * Schema for an answer returned by the OpenAI Decisions API. + * + * **Details** + * + * Each answer echoes the `name` of its question. Answers to `predicate`, + * `choice`, and `score` questions have the same `type` as the question. A + * `score` is a probability-weighted average of the 0-based level indices, so + * it can fall between levels. + * + * **Gotchas** + * + * OpenAI can refuse a single question. That answer has `type: "refusal"` and + * no result fields. + * + * @stability unstable + * @category schemas + * @since 4.0.5 + */ +export const DecisionAnswer = Schema.Union([ + Schema.Struct({ + type: Schema.Literal("predicate"), + name: Schema.String, + probability: Schema.Number + }), + Schema.Struct({ + type: Schema.Literal("choice"), + name: Schema.String, + choice: Schema.String, + probabilities: Schema.Array(Schema.Struct({ value: Schema.String, probability: Schema.Number })), + confidence: Schema.Number + }), + Schema.Struct({ + type: Schema.Literal("score"), + name: Schema.String, + score: Schema.Number, + probabilities: Schema.Array(Schema.Struct({ + value: Schema.Int, + label: Schema.String, + probability: Schema.Number + })), + confidence: Schema.Number + }), + Schema.Struct({ + type: Schema.Literal("refusal"), + name: Schema.String + }) +]) + +/** + * An answer returned by the OpenAI Decisions API. + * + * @stability unstable + * @category models + * @since 4.0.5 + */ +export type DecisionAnswer = typeof DecisionAnswer.Type + +/** + * Schema for a successful response from `POST /decisions`. + * + * **Gotchas** + * + * OpenAI does not document usage for this endpoint, so `usage` and its token + * counts are optional. + * + * @stability unstable + * @category schemas + * @since 4.0.5 + */ +export const CreateDecisionsResponse = Schema.Struct({ + answers: Schema.Array(DecisionAnswer), + usage: Schema.optionalKey(Schema.Struct({ + input_tokens: Schema.optionalKey(Schema.Int), + output_tokens: Schema.optionalKey(Schema.Int) + })) +}) + +/** + * Successful response from `POST /decisions`. + * + * @stability unstable + * @category models + * @since 4.0.5 + */ +export type CreateDecisionsResponse = typeof CreateDecisionsResponse.Type diff --git a/repos/effect/packages/ai/openai/src/OpenAiTool.ts b/repos/effect/packages/ai/openai/src/OpenAiTool.ts index b74dec8177..8041cd04a8 100644 --- a/repos/effect/packages/ai/openai/src/OpenAiTool.ts +++ b/repos/effect/packages/ai/openai/src/OpenAiTool.ts @@ -321,7 +321,7 @@ const WebSearchSuccess = Schema.Struct({ const WebSearchFailure = Schema.Struct({ action: Generated.WebSearchToolCall.fields.action, - status: Schema.Literals(Generated.WebSearchToolCall.fields.status.literals.filter((status) => status !== "completed")) + status: Schema.Literals(Generated.WebSearchCallStatus.literals.filter((status) => status !== "completed")) }) /** diff --git a/repos/effect/packages/ai/openai/src/index.ts b/repos/effect/packages/ai/openai/src/index.ts index 69d7e26bd4..026e4467d4 100644 --- a/repos/effect/packages/ai/openai/src/index.ts +++ b/repos/effect/packages/ai/openai/src/index.ts @@ -29,6 +29,12 @@ export * as OpenAiClientGenerated from "./OpenAiClientGenerated.ts" */ export * as OpenAiConfig from "./OpenAiConfig.ts" +/** + * @stability unstable + * @since 4.0.5 + */ +export * as OpenAiDecisionModel from "./OpenAiDecisionModel.ts" + /** * @stability unstable * @since 4.0.0 diff --git a/repos/effect/packages/ai/openai/test/OpenAiClient.test.ts b/repos/effect/packages/ai/openai/test/OpenAiClient.test.ts index 8440e4893b..2a3b3d5310 100644 --- a/repos/effect/packages/ai/openai/test/OpenAiClient.test.ts +++ b/repos/effect/packages/ai/openai/test/OpenAiClient.test.ts @@ -508,6 +508,23 @@ describe("OpenAiClient", () => { }) describe("createResponseStream", () => { + it.effect("emits response.completed before [DONE] in the same SSE chunk", () => + Effect.gen(function*() { + const client = yield* OpenAiClient.OpenAiClient + const [, stream] = yield* client.createResponseStream({ model: "gpt-4o", input: "test" }) + const events = yield* Stream.runCollect(stream) + + assert.deepStrictEqual(events.map((event) => event.type), ["response.completed"]) + }).pipe(Effect.provide(makeTestLayer(undefined, { + _tag: "Sse", + events: [{ + type: "response.completed", + sequence_number: 1, + response: makeResponseBody({ status: "completed" }) + }], + trailer: "data: [DONE]\n\n" + })))) + it.live("terminates an SSE stream at response.failed", () => Effect.gen(function*() { const client = yield* OpenAiClient.OpenAiClient @@ -1128,6 +1145,7 @@ type MockResponse = | { readonly _tag: "Sse" readonly events: ReadonlyArray + readonly trailer?: string | undefined readonly keepOpen?: boolean | undefined readonly status?: number | undefined readonly headers?: Record | undefined @@ -1247,7 +1265,7 @@ const makeResponse = ( : "text/event-stream" const body = response._tag === "Json" ? JSON.stringify(response.body) - : response.events.map((event) => `data: ${JSON.stringify(event)}\n\n`).join("") + : response.events.map((event) => `data: ${JSON.stringify(event)}\n\n`).join("") + (response.trailer ?? "") const httpResponse = HttpClientResponse.fromWeb( request, diff --git a/repos/effect/packages/ai/openai/test/OpenAiDecisionModel.test.ts b/repos/effect/packages/ai/openai/test/OpenAiDecisionModel.test.ts new file mode 100644 index 0000000000..2b4b425e0b --- /dev/null +++ b/repos/effect/packages/ai/openai/test/OpenAiDecisionModel.test.ts @@ -0,0 +1,327 @@ +import { OpenAiClient } from "@effect/ai-openai" +import * as OpenAiDecisionModel from "@effect/ai-openai/OpenAiDecisionModel" +import { assert, describe, it } from "@effect/vitest" +import { Effect, Layer, Redacted, Schema } from "effect" +import { Decision, DecisionModel, Model } from "effect/ai" +import { HttpClient, type HttpClientError, type HttpClientRequest, HttpClientResponse } from "effect/http" + +const Triage = Decision.make({ + input: Schema.Struct({ message: Schema.String }), + decisions: { + team: Decision.classify({ + instructions: "Which team should handle this request?", + criteria: { billing: "Payments", technical: "Outages" } + }), + severity: Decision.rate({ + instructions: "How severe is the impact?", + criteria: ["Minor", "Major", "Critical"] + }), + urgent: Decision.probability({ + instructions: "Does this need immediate attention?", + criteria: { false: "Can wait", true: "Act now" } + }) + } +}) + +const Urgency = Decision.make({ + input: Schema.String, + decisions: { + urgent: Decision.probability({ instructions: "Does this need immediate attention?" }) + } +}) + +const input = { message: "Checkout is down" } + +const answers = [ + { + name: "team", + type: "choice", + choice: "technical", + probabilities: [{ value: "billing", probability: 0.1 }, { value: "technical", probability: 0.9 }], + confidence: 0.9 + }, + { + name: "severity", + type: "score", + score: 1.75, + probabilities: [ + { value: 0, label: "minor", probability: 0.05 }, + { value: 1, label: "major", probability: 0.15 }, + { value: 2, label: "critical", probability: 0.8 } + ], + confidence: 0.8 + }, + { name: "urgent", type: "predicate", probability: 0.99 } +] + +const response = ( + answers: ReadonlyArray, + fields: object = { usage: { input_tokens: 120, output_tokens: 0 } } +) => ({ id: "dec_123", object: "decision", model: "gpt-6-luna", answers, ...fields }) + +const clientLayer = ( + body: unknown, + onRequest: (request: HttpClientRequest.HttpClientRequest) => void = () => {} +) => + OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") }).pipe( + Layer.provide(Layer.succeed( + HttpClient.HttpClient, + HttpClient.makeWith( + Effect.map((request) => { + onRequest(request) + return HttpClientResponse.fromWeb(request, Response.json(body)) + }), + Effect.succeed as HttpClient.HttpClient.Preprocess + ) + )) + ) + +const layer = (body: unknown) => + OpenAiDecisionModel.layer({ model: "gpt-6-luna" }).pipe(Layer.provide(clientLayer(body))) + +const requestBody = (request: HttpClientRequest.HttpClientRequest) => { + assert.strictEqual(request.body._tag, "Uint8Array") + return request.body._tag === "Uint8Array" ? JSON.parse(new TextDecoder().decode(request.body.body)) : undefined +} + +describe("OpenAiDecisionModel", () => { + it.effect("keeps explicit Rate labels separate from their string descriptions", () => { + const definition = Decision.make({ + input: Schema.String, + decisions: { + severity: Decision.rate({ + instructions: "Severity?", + criteria: ["Minor", { label: "Critical", description: "Checkout unavailable" }] + }) + } + }) + return Effect.gen(function*() { + const result = yield* DecisionModel.decide(definition, { input: "Checkout is down" }) + assert.strictEqual(result.answers.severity.label, "Critical") + assert.deepStrictEqual({ ...result.answers.severity.probabilities }, { Minor: 0.1, Critical: 0.9 }) + }).pipe( + Effect.provide(OpenAiDecisionModel.layer({ model: "gpt-6-luna" })), + Effect.provide(clientLayer( + response([{ + name: "severity", + type: "score", + score: 0.9, + confidence: 0.9, + probabilities: [{ value: 0, label: "ignored", probability: 0.1 }, { + value: 1, + label: "ignored", + probability: 0.9 + }] + }]), + (request) => { + assert.deepStrictEqual(requestBody(request).questions, [{ + type: "score", + name: "severity", + instructions: "Severity?", + levels: [{ label: "Minor", description: "Minor" }, { + label: "Critical", + description: "Checkout unavailable" + }] + }]) + } + )) + ) + }) + + it.effect("serializes structured instructions and descriptions to strings, including null choices", () => { + const definition = Decision.make({ + input: Schema.String, + decisions: { + team: Decision.classify({ + instructions: { question: "Team?" }, + criteria: { billing: null, technical: { handles: "Outages" } } + }), + severity: Decision.rate({ + instructions: ["Severity?"], + criteria: ["Minor", "Major", { label: "Critical", description: ["outage"] }] + }), + urgent: Decision.probability({ + instructions: { question: "Urgent?" }, + criteria: { false: ["Can wait"], true: { action: "Act now" } } + }) + } + }) + return DecisionModel.decide(definition, { input: "Checkout is down" }).pipe( + Effect.provide(OpenAiDecisionModel.layer({ model: "gpt-6-luna" })), + Effect.provide(clientLayer(response(answers), (request) => { + assert.deepStrictEqual(requestBody(request).questions, [ + { + type: "choice", + name: "team", + instructions: "{\"question\":\"Team?\"}", + choices: [ + { value: "billing", description: "null" }, + { value: "technical", description: "{\"handles\":\"Outages\"}" } + ] + }, + { + type: "score", + name: "severity", + instructions: "[\"Severity?\"]", + levels: [ + { label: "Minor", description: "Minor" }, + { label: "Major", description: "Major" }, + { label: "Critical", description: "[\"outage\"]" } + ] + }, + { + type: "predicate", + name: "urgent", + instructions: "{\"question\":\"Urgent?\"}\n\nfalse: [\"Can wait\"]\ntrue: {\"action\":\"Act now\"}" + } + ]) + })) + ) + }) + + it.effect("sends every decision as a named question and keys the answers by name", () => + Effect.gen(function*() { + const result = yield* DecisionModel.decide(Triage, { input }) + assert.strictEqual(yield* Model.ProviderName, "openai") + assert.strictEqual(yield* Model.ModelName, "gpt-6-luna") + assert.strictEqual(result.answers.team.label, "technical") + assert.deepStrictEqual({ ...result.answers.team.probabilities }, { billing: 0.1, technical: 0.9 }) + assert.strictEqual(result.answers.team.confidence, 0.9) + assert.strictEqual(result.answers.severity.label, "Critical") + assert.strictEqual(result.answers.severity.rating, 1.75) + assert.deepStrictEqual({ ...result.answers.severity.probabilities }, { Minor: 0.05, Major: 0.15, Critical: 0.8 }) + assert.strictEqual(result.answers.severity.confidence, 0.8) + assert.strictEqual(result.answers.urgent.probability, 0.99) + assert.strictEqual(result.usage.inputTokens, 120) + assert.strictEqual(result.usage.outputTokens, 0) + }).pipe( + Effect.provide(OpenAiDecisionModel.model("gpt-6-luna")), + Effect.provide(clientLayer(response([...answers].reverse()), (request) => { + assert.strictEqual(request.method, "POST") + assert.strictEqual(request.url, "https://api.openai.com/v1/decisions") + assert.deepStrictEqual(requestBody(request), { + model: "gpt-6-luna", + input: JSON.stringify(input), + questions: [ + { + type: "choice", + name: "team", + instructions: "Which team should handle this request?", + choices: [ + { value: "billing", description: "Payments" }, + { value: "technical", description: "Outages" } + ] + }, + { + type: "score", + name: "severity", + instructions: "How severe is the impact?", + levels: [ + { label: "Minor", description: "Minor" }, + { label: "Major", description: "Major" }, + { label: "Critical", description: "Critical" } + ] + }, + { + type: "predicate", + name: "urgent", + instructions: "Does this need immediate attention?\n\nfalse: Can wait\ntrue: Act now" + } + ] + }) + })) + )) + + it.effect("sends string state unchanged without images and leaves omitted usage undefined", () => + Effect.gen(function*() { + const result = yield* DecisionModel.decide(Urgency, { input: "Checkout is down" }) + assert.isUndefined(result.usage.inputTokens) + assert.isUndefined(result.usage.outputTokens) + }).pipe( + Effect.provide(OpenAiDecisionModel.layer({ model: "gpt-6-luna" })), + Effect.provide(clientLayer(response([answers[2]], {}), (request) => { + assert.strictEqual(requestBody(request).input, "Checkout is down") + })) + )) + + it.effect("fails with InvalidOutputError when an answer is missing", () => + Effect.gen(function*() { + const error = yield* Effect.flip(DecisionModel.decide(Triage, { input })) + assert.strictEqual(error.reason._tag, "InvalidOutputError") + }).pipe(Effect.provide(layer(response(answers.slice(0, 2)))))) + + it.effect("fails the whole call with ContentPolicyError when any answer is a refusal", () => + Effect.gen(function*() { + const error = yield* Effect.flip(DecisionModel.decide(Triage, { input })) + assert.strictEqual(error.reason._tag, "ContentPolicyError") + if (error.reason._tag === "ContentPolicyError") { + assert.include(error.reason.description, "severity") + assert.notInclude(error.reason.description, "team") + assert.include(JSON.stringify(error.reason.metadata.openai), "severity") + } + }).pipe(Effect.provide(layer(response([ + answers[0], + { name: "severity", type: "refusal", refusal: "I can't help with that." }, + answers[2] + ]))))) + + it.effect("sends string and JSON state with byte array, base64 string, and data URL images", () => { + const dataUrl = "data:image/webp;base64,UklGRg==" + const images = [ + { mediaType: "image/png", data: new Uint8Array([137, 80, 78, 71]) }, + { mediaType: "image/jpeg", data: "/9j/4AAQ" }, + { mediaType: "image/webp", data: new URL(dataUrl) } + ] + const assertInput = (request: HttpClientRequest.HttpClientRequest, text: string) => { + const body = requestBody(request) + assert.strictEqual(body.input.length, 1) + assert.strictEqual(body.input[0].role, "user") + assert.deepStrictEqual(body.input[0].content, [ + { type: "input_text", text }, + { type: "input_image", image_url: "data:image/png;base64,iVBORw==" }, + { type: "input_image", image_url: "data:image/jpeg;base64,/9j/4AAQ" }, + { type: "input_image", image_url: dataUrl } + ]) + } + return Effect.gen(function*() { + const result = yield* DecisionModel.decide(Urgency, { + input: "Checkout is down", + images + }) + assert.strictEqual(result.answers.urgent.probability, 0.99) + const jsonResult = yield* DecisionModel.decide(Triage, { input, images }).pipe( + Effect.provide(OpenAiDecisionModel.layer({ model: "gpt-6-luna" })), + Effect.provide(clientLayer(response(answers), (request) => { + assertInput(request, "{\"message\":\"Checkout is down\"}") + })) + ) + assert.strictEqual(jsonResult.answers.urgent.probability, 0.99) + }).pipe( + Effect.provide(OpenAiDecisionModel.layer({ model: "gpt-6-luna" })), + Effect.provide(clientLayer(response([answers[2]]), (request) => { + const body = requestBody(request) + assert.deepStrictEqual(body.questions, [ + { type: "predicate", name: "urgent", instructions: "Does this need immediate attention?" } + ]) + assertInput(request, "Checkout is down") + })) + ) + }) + + it.effect("rejects remote image URLs without sending a request", () => { + let requests = 0 + return Effect.gen(function*() { + const error = yield* Effect.flip(DecisionModel.decide(Urgency, { + input: "Checkout is down", + images: [{ mediaType: "image/png", data: new URL("https://example.com/cat.png") }] + })) + assert.strictEqual(error.reason._tag, "InvalidUserInputError") + assert.strictEqual(requests, 0) + }).pipe( + Effect.provide(OpenAiDecisionModel.layer({ model: "gpt-6-luna" })), + Effect.provide(clientLayer(response([answers[2]]), () => { + requests++ + })) + ) + }) +}) diff --git a/repos/effect/packages/ai/openai/test/OpenAiEmbeddingModel.test.ts b/repos/effect/packages/ai/openai/test/OpenAiEmbeddingModel.test.ts index 65ab739b31..ffe9c4496c 100644 --- a/repos/effect/packages/ai/openai/test/OpenAiEmbeddingModel.test.ts +++ b/repos/effect/packages/ai/openai/test/OpenAiEmbeddingModel.test.ts @@ -283,6 +283,7 @@ const getRequestBody = (request: HttpClientRequest.HttpClientRequest) => const noopOpenAiClient: OpenAiClient.Service = { client: undefined as unknown as OpenAiClient.Service["client"], + createDecisions: () => Effect.die(new Error("noop")), createResponse: () => Effect.die(new Error("noop")), createResponseStream: () => Effect.die(new Error("noop")), createEmbedding: () => Effect.die(new Error("noop")) diff --git a/repos/effect/packages/ai/openai/test/OpenAiLanguageModel.test.ts b/repos/effect/packages/ai/openai/test/OpenAiLanguageModel.test.ts index a015ec2067..197f5ff283 100644 --- a/repos/effect/packages/ai/openai/test/OpenAiLanguageModel.test.ts +++ b/repos/effect/packages/ai/openai/test/OpenAiLanguageModel.test.ts @@ -82,6 +82,40 @@ describe("OpenAiLanguageModel", () => { ) }) + describe("web search find_in_page", () => { + it.effect.each(["generateText", "streamText"] as const)( + "preserves actions without a URL with %s", + (method) => + Effect.gen(function*() { + const action = { type: "find_in_page", pattern: "og:image" } as const + const item = { type: "web_search_call", id: "ws_123", status: "completed", action } + const event = { type: "response.output_item.done", sequence_number: 1, output_index: 0, item } + const body = method === "generateText" + ? JSON.stringify({ ...makeDefaultResponse(), output: [item] }) + : `data: ${JSON.stringify(event)}\n\n` + const client = makeRawResponseClient( + body, + method === "generateText" ? "application/json" : "text/event-stream" + ) + const options = { prompt: "Search the page", toolkit: Toolkit.make(OpenAiTool.WebSearch({})) } + const parts = yield* Effect.gen(function*() { + if (method === "generateText") return (yield* LanguageModel.generateText(options)).content + return yield* LanguageModel.streamText(options).pipe(Stream.runCollect) + }).pipe( + Effect.provide(OpenAiLanguageModel.model("gpt-5.4")), + Effect.provide(OpenAiClient.layer({ apiKey: Redacted.make("sk-test-key") })), + Effect.provideService(HttpClient.HttpClient, client) + ) + + deepStrictEqual(parts.filter((part) => part.type === "tool-call").map((part) => part.params), [{ action }]) + deepStrictEqual( + parts.filter((part) => part.type === "tool-result").map((part) => part.result), + [{ action, status: "completed" }] + ) + }) + ) + }) + describe("web search without an action", () => { it.effect.each( [ @@ -125,7 +159,7 @@ describe("OpenAiLanguageModel", () => { })) it.effect("rejects null and malformed actions when present", () => - Effect.forEach([null, { type: "find_in_page", url: "https://example.com" }], (action) => { + Effect.forEach([null, { type: "find_in_page", url: "https://example.com", pattern: null }], (action) => { const event = { type: "response.output_item.done", sequence_number: 1, @@ -573,6 +607,45 @@ describe("OpenAiLanguageModel", () => { }) }).pipe(Effect.provide(makeTestLayer({ body: { model: "o1" } })))) + it.effect("replays encrypted reasoning statelessly for an unknown model", () => + Effect.gen(function*() { + const history = Prompt.fromResponseParts([ + AiResponse.makePart("reasoning-start", { + id: "reasoning_123:0", + metadata: { openai: { itemId: "reasoning_123" } } + }), + AiResponse.makePart("reasoning-delta", { + id: "reasoning_123:0", + delta: "Let me think..." + }), + AiResponse.makePart("reasoning-end", { + id: "reasoning_123:0", + metadata: { + openai: { + itemId: "reasoning_123", + encryptedContent: "encrypted-reasoning" + } + } + }) + ]) + + yield* LanguageModel.generateText({ + prompt: Prompt.concat(history, Prompt.make("Continue")) + }).pipe(Effect.provide(OpenAiLanguageModel.model("custom-model", { store: false }))) + + const requests = yield* MockHttpClient.requests + const body = yield* getRequestBody(requests[0]) + const reasoningItem = body.input.find((item: any) => item.type === "reasoning") + + assert.isDefined(reasoningItem) + deepStrictEqual(reasoningItem, { + type: "reasoning", + id: "reasoning_123", + summary: [{ type: "summary_text", text: "Let me think..." }], + encrypted_content: "encrypted-reasoning" + }) + }).pipe(Effect.provide(makeTestLayer({ body: { model: "custom-model" } })))) + it.effect("serializes stored assistant history according to item reference config", () => Effect.gen(function*() { yield* LanguageModel.generateText({ @@ -1247,7 +1320,7 @@ describe("OpenAiLanguageModel", () => { }) describe("response handling", () => { - it.effect("preserves prompt cache diagnostics alongside the service tier", () => + it.effect("preserves ultrafast service tier alongside prompt cache diagnostics", () => Effect.gen(function*() { const diagnostics = { type: "cache_miss", @@ -1256,7 +1329,7 @@ describe("OpenAiLanguageModel", () => { comparison_reusable_tokens: 2048 } as const const body = JSON.stringify({ - ...makeDefaultResponse({ service_tier: "priority" }), + ...makeDefaultResponse({ service_tier: "ultrafast" }), prompt_cache_diagnostics: diagnostics }) const result = yield* LanguageModel.generateText({ prompt: "test" }).pipe( @@ -1268,7 +1341,7 @@ describe("OpenAiLanguageModel", () => { const finish = result.content.find((part) => part.type === "finish") assert.isDefined(finish) deepStrictEqual(finish.metadata.openai, { - serviceTier: "priority", + serviceTier: "ultrafast", promptCacheDiagnostics: diagnostics }) })) @@ -1759,9 +1832,27 @@ describe("OpenAiLanguageModel", () => { }) describe("streamText", () => { - it.effect.each(["completed", "failed"] as const)( - "preserves prompt cache diagnostics in response.%s", - (status) => + it.effect.each( + [ + { + status: "completed", + serviceTier: "fast", + expectedMetadata: { promptCacheDiagnostics: { type: "cache_hit" } } + }, + { + status: "completed", + serviceTier: "ultrafast", + expectedMetadata: { serviceTier: "ultrafast", promptCacheDiagnostics: { type: "cache_hit" } } + }, + { + status: "failed", + serviceTier: "ultrafast", + expectedMetadata: { serviceTier: "ultrafast", promptCacheDiagnostics: { type: "cache_hit" } } + } + ] as const + )( + "preserves supported tiers and prompt cache diagnostics in response.$status with $serviceTier", + ({ status, serviceTier, expectedMetadata }) => Effect.gen(function*() { const event = { type: `response.${status}`, @@ -1771,7 +1862,7 @@ describe("OpenAiLanguageModel", () => { status, error: status === "failed" ? { code: "server_error", message: "generation failed" } : null }), - service_tier: "fast", + service_tier: serviceTier, prompt_cache_diagnostics: { type: "cache_hit" } } } @@ -1790,7 +1881,7 @@ describe("OpenAiLanguageModel", () => { const finish = parts.find((part) => part.type === "finish") assert.isDefined(finish) - deepStrictEqual(finish.metadata.openai, { promptCacheDiagnostics: { type: "cache_hit" } }) + deepStrictEqual(finish.metadata.openai, expectedMetadata) }) ) @@ -2052,6 +2143,51 @@ describe("OpenAiLanguageModel", () => { assert.isDefined(parts.find((part) => part.type === "finish")) })) + it.effect("streams undeclared tool calls when tool call validation is deferred", () => + Effect.gen(function*() { + const streamEvents = [ + { + type: "response.created", + sequence_number: 1, + response: makeDefaultResponse({ status: "in_progress" }) + }, + { + type: "response.output_item.added", + sequence_number: 2, + output_index: 0, + item: makeFunctionCall("Write", {}, { arguments: "", status: "in_progress" }) + }, + { + type: "response.output_item.done", + sequence_number: 3, + output_index: 0, + item: makeFunctionCall("Write", { path: "a" }) + }, + { + type: "response.completed", + sequence_number: 4, + response: makeDefaultResponse() + } + ] as unknown as ReadonlyArray + + const parts = yield* LanguageModel.streamText({ + prompt: "Use the tools", + toolkit: TestToolkit, + disableToolCallResolution: true, + toolCallValidation: "deferred" + }).pipe( + Stream.runCollect, + Effect.provide(OpenAiLanguageModel.model("gpt-4o-mini")), + Effect.provide(makeStreamTestLayer(streamEvents)), + Effect.provide(TestToolkitLayer) + ) + + deepStrictEqual( + parts.filter((part) => part.type === "tool-call").map(({ name, params }) => ({ name, params })), + [{ name: "Write", params: { path: "a" } }] + ) + })) + it.effect("waits for the stable streamed web search action before emitting the tool call", () => Effect.gen(function*() { const toolkit = Toolkit.make(OpenAiTool.WebSearch({})) @@ -2408,6 +2544,7 @@ describe("OpenAiLanguageModel", () => { fileIdPrefixes: ["file-"], strictJsonSchema: false, useItemReferences: false, + reasoningModel: true, temperature: 0.5 })) ) @@ -2418,11 +2555,94 @@ describe("OpenAiLanguageModel", () => { strictEqual(body.fileIdPrefixes, undefined) strictEqual(body.strictJsonSchema, undefined) strictEqual(body.useItemReferences, undefined) + strictEqual(body.reasoningModel, undefined) strictEqual(body.temperature, 0.5) }).pipe(Effect.provide(makeTestLayer()))) }) + + describe("reasoning capabilities", () => { + it.effect("merges explicit include values with generated values", () => + Effect.gen(function*() { + yield* LanguageModel.generateText({ prompt: "test" }).pipe( + Effect.provide(OpenAiLanguageModel.model("custom-model", { + store: false, + include: ["message.input_image.image_url", "reasoning.encrypted_content"], + top_logprobs: 2 + })) + ) + + const requests = yield* MockHttpClient.requests + const body = yield* getRequestBody(requests[0]) + + deepStrictEqual(body.include, [ + "message.input_image.image_url", + "reasoning.encrypted_content", + "message.output_text.logprobs" + ]) + }).pipe(Effect.provide(makeTestLayer()))) + + for (const { name, model, config, include, role } of reasoningCapabilityCases) { + it.effect(name, () => + Effect.gen(function*() { + yield* LanguageModel.generateText({ + prompt: Prompt.make([ + { role: "system", content: "You are a helpful assistant" }, + { role: "user", content: "Hello" } + ]) + }).pipe(Effect.provide(OpenAiLanguageModel.model(model, config))) + + const requests = yield* MockHttpClient.requests + const body = yield* getRequestBody(requests[0]) + + deepStrictEqual(body.include, include) + strictEqual(body.input[0].role, role) + }).pipe(Effect.provide(makeTestLayer({ body: { model } })))) + } + + it.effect("prefers the reasoningModel override from withConfigOverride", () => + Effect.gen(function*() { + yield* LanguageModel.generateText({ + prompt: Prompt.make([ + { role: "system", content: "You are a helpful assistant" }, + { role: "user", content: "Hello" } + ]) + }).pipe( + OpenAiLanguageModel.withConfigOverride({ reasoningModel: true }), + Effect.provide(OpenAiLanguageModel.model("gpt-4.1", { store: false, reasoningModel: false })) + ) + + const requests = yield* MockHttpClient.requests + const body = yield* getRequestBody(requests[0]) + + deepStrictEqual(body.include, ["reasoning.encrypted_content"]) + strictEqual(body.input[0].role, "developer") + }).pipe(Effect.provide(makeTestLayer({ body: { model: "gpt-4.1" } })))) + }) }) +const reasoningCapabilityCases: ReadonlyArray<{ + readonly name: string + readonly model: string + readonly config: Omit + readonly include: ReadonlyArray | undefined + readonly role: "system" | "developer" +}> = [ + { + name: "defaults an unknown model to reasoning", + model: "custom-model", + config: { store: false }, + include: ["reasoning.encrypted_content"], + role: "developer" + }, + { + name: "disables automatic reasoning without dropping explicit includes", + model: "custom-model", + config: { store: false, reasoningModel: false, include: ["message.input_image.image_url"] }, + include: ["message.input_image.image_url"], + role: "system" + } +] + // ============================================================================= // Test Infrastructure // ============================================================================= @@ -2491,6 +2711,7 @@ const makeStreamTestLayer = (events: ReadonlyArray Effect.die(new Error("unexpected createDecisions call")), createResponse: () => Effect.die(new Error("unexpected createResponse call")), createResponseStream: () => Effect.succeed([response, Stream.fromIterable(events)]), createEmbedding: () => Effect.die(new Error("unexpected createEmbedding call")) diff --git a/repos/effect/packages/ai/openai/test/OpenAiSchema.test.ts b/repos/effect/packages/ai/openai/test/OpenAiSchema.test.ts index 7de0dc6aee..da4e2bb83a 100644 --- a/repos/effect/packages/ai/openai/test/OpenAiSchema.test.ts +++ b/repos/effect/packages/ai/openai/test/OpenAiSchema.test.ts @@ -457,6 +457,7 @@ describe("OpenAiSchema", () => { OpenAiClient.OpenAiClient, OpenAiClient.OpenAiClient.of({ client: undefined as any, + createDecisions: () => Effect.die("unexpected"), createResponse: () => Effect.die("unexpected"), createResponseStream: () => Effect.succeed([ diff --git a/repos/effect/packages/ai/openai/typetest/OpenAiDecisionModel.tst.ts b/repos/effect/packages/ai/openai/typetest/OpenAiDecisionModel.tst.ts new file mode 100644 index 0000000000..f1f715d54d --- /dev/null +++ b/repos/effect/packages/ai/openai/typetest/OpenAiDecisionModel.tst.ts @@ -0,0 +1,86 @@ +import { type OpenAiClient, OpenAiDecisionModel } from "@effect/ai-openai" +import { Effect, type Layer, Schema } from "effect" +import { Decision, DecisionModel, type Model } from "effect/ai" +import { describe, expect, it } from "tstyche" + +declare const client: OpenAiClient.Service + +const Triage = Decision.make({ + input: Schema.String, + decisions: { + urgent: Decision.probability({ + instructions: "The message conveys urgency", + criteria: { false: "No time pressure", true: "Needs action now" } + }) + } +}) + +describe("OpenAiDecisionModel", () => { + it("suggests gpt-6-luna while accepting other model ids", () => { + expect().type.toBe<"gpt-6-luna" | (string & {})>() + expect(OpenAiDecisionModel.layer).type.toBeCallableWith({ model: "gpt-6-luna-next" }) + }) + + it("model provides DecisionModel and requires OpenAiClient", () => { + expect(OpenAiDecisionModel.model("gpt-6-luna")).type.toBe< + Model.Model<"openai", DecisionModel.DecisionModel, OpenAiClient.OpenAiClient> + >() + }) + + it("layer provides DecisionModel and requires OpenAiClient", () => { + expect(OpenAiDecisionModel.layer({ model: "gpt-6-luna" })).type.toBe< + Layer.Layer + >() + }) + + it("make builds a DecisionModel from the client service", () => { + expect(OpenAiDecisionModel.make({ model: "gpt-6-luna" })).type.toBe< + Effect.Effect + >() + }) + + it("satisfies a decide program's DecisionModel requirement", () => { + const program = DecisionModel.decide(Triage, { input: "hello" }).pipe( + Effect.provide(OpenAiDecisionModel.model("gpt-6-luna")) + ) + + type Requirements = typeof program extends Effect.Effect ? R : never + + expect().type.toBe() + }) +}) + +describe("OpenAiClient.createDecisions", () => { + it("accepts string input and message input with text and image parts", () => { + const questions = [ + { type: "predicate", name: "urgent", instructions: "Act now?" }, + { + type: "choice", + name: "team", + instructions: "Which team?", + choices: [{ value: "billing", description: "Pay" }] + }, + { type: "score", name: "severity", instructions: "How bad?", levels: [{ label: "Minor", description: "Minor" }] } + ] as const + expect(client.createDecisions).type.toBeCallableWith({ model: "gpt-6-luna", input: "Checkout is down", questions }) + expect(client.createDecisions).type.toBeCallableWith({ + model: "gpt-6-luna", + input: [{ + role: "user", + content: [ + { type: "input_text", text: "Checkout is down" }, + { type: "input_image", image_url: "data:image/png;base64,iVBORw==" } + ] + }], + questions + }) + }) + + it("rejects questions without a name", () => { + expect(client.createDecisions).type.not.toBeCallableWith({ + model: "gpt-6-luna", + input: "Checkout is down", + questions: [{ type: "predicate", instructions: "Act now?" }] + }) + }) +}) diff --git a/repos/effect/packages/ai/openrouter/CHANGELOG.md b/repos/effect/packages/ai/openrouter/CHANGELOG.md index 36088fdc27..7e564ba4f2 100644 --- a/repos/effect/packages/ai/openrouter/CHANGELOG.md +++ b/repos/effect/packages/ai/openrouter/CHANGELOG.md @@ -1,5 +1,27 @@ # @effect/ai-openrouter +## 4.0.5 + +### Patch Changes + +- [#9124](https://github.com/Effect-TS/effect/pull/9124) [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e) Thanks @jem-computer! - Support structured decision instructions, descriptions, and score legends in TypeSafe, Cloudflare, and OpenRouter. `Decision.rate` accepts labeled descriptions; `Rate.criteria` entries are now `{ label, description }` objects instead of strings. +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/ai/openrouter/package.json b/repos/effect/packages/ai/openrouter/package.json index 46b99545b1..0d63a00849 100644 --- a/repos/effect/packages/ai/openrouter/package.json +++ b/repos/effect/packages/ai/openrouter/package.json @@ -1,6 +1,6 @@ { "name": "@effect/ai-openrouter", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "An OpenRouter provider integration for Effect AI SDK", diff --git a/repos/effect/packages/ai/openrouter/src/OpenRouterDecisionModel.ts b/repos/effect/packages/ai/openrouter/src/OpenRouterDecisionModel.ts index 66dfd86e71..b548ed5d6e 100644 --- a/repos/effect/packages/ai/openrouter/src/OpenRouterDecisionModel.ts +++ b/repos/effect/packages/ai/openrouter/src/OpenRouterDecisionModel.ts @@ -77,7 +77,11 @@ export const make = Effect.fnUntraced(function*(options: { questions[key] = { type: "choice", instructions: decision.instructions, criteria: decision.criteria } break case "Rate": - questions[key] = { type: "score", instructions: decision.instructions, criteria: decision.criteria } + questions[key] = { + type: "score", + instructions: decision.instructions, + criteria: decision.criteria.map((level) => level.description) + } break case "Probability": questions[key] = { type: "noul", instructions: decision.instructions, criteria: decision.criteria } @@ -111,7 +115,7 @@ export const make = Effect.fnUntraced(function*(options: { const decision = decisions[key] const probabilities: Record = Object.create(null) if (decision?._tag === "Rate") { - for (const [index, label] of decision.criteria.entries()) { + for (const [index, { label }] of decision.criteria.entries()) { const probability = answer.probabilities[String(index)] if (probability !== undefined) { probabilities[label] = probability diff --git a/repos/effect/packages/ai/openrouter/src/OpenRouterSchema.ts b/repos/effect/packages/ai/openrouter/src/OpenRouterSchema.ts index c222a73ace..2eee16bccd 100644 --- a/repos/effect/packages/ai/openrouter/src/OpenRouterSchema.ts +++ b/repos/effect/packages/ai/openrouter/src/OpenRouterSchema.ts @@ -7,6 +7,8 @@ import * as Schema from "effect/Schema" import * as Generated from "./Generated.ts" +const Entry = Schema.Union([Schema.String, Schema.JsonObject, Schema.Array(Schema.Json)]) + /** * A choice question with descriptions keyed by choice label. * @@ -16,8 +18,8 @@ import * as Generated from "./Generated.ts" */ export const ChoiceQuestion = Schema.Struct({ type: Schema.Literal("choice"), - instructions: Schema.String, - criteria: Schema.Record(Schema.String, Schema.String) + instructions: Entry, + criteria: Schema.Record(Schema.String, Schema.NullOr(Entry)) }) /** @@ -29,8 +31,8 @@ export const ChoiceQuestion = Schema.Struct({ */ export const ScoreQuestion = Schema.Struct({ type: Schema.Literal("score"), - instructions: Schema.String, - criteria: Schema.Array(Schema.String) + instructions: Entry, + criteria: Schema.Array(Entry) }) /** @@ -42,12 +44,13 @@ export const ScoreQuestion = Schema.Struct({ */ export const NoulQuestion = Schema.Struct({ type: Schema.Literal("noul"), - instructions: Schema.String, - criteria: Schema.optional(Schema.Struct({ true: Schema.String, false: Schema.String })) + instructions: Entry, + criteria: Schema.optional(Schema.Struct({ true: Entry, false: Entry })) }) /** - * A choice, ordered score, or probability question. + * A choice, score, or probability question with string, JSON object, or JSON array + * instructions and descriptions. Choice descriptions also accept `null`. * * @stability unstable * @category schemas @@ -78,7 +81,7 @@ export const Answer = Schema.Union([ score: Schema.Finite, confidence: Schema.optional(Schema.Finite), probabilities: Schema.optional(Schema.Record(Schema.String, Schema.Finite)), - legend: Schema.optional(Schema.Record(Schema.String, Schema.String)) + legend: Schema.optional(Schema.Record(Schema.String, Schema.Json)) }), Schema.Struct({ type: Schema.Literal("noul"), noul: Schema.Finite }) ]) diff --git a/repos/effect/packages/ai/openrouter/test/OpenRouterDecisionModel.test.ts b/repos/effect/packages/ai/openrouter/test/OpenRouterDecisionModel.test.ts index bd1d21c332..c3da61a013 100644 --- a/repos/effect/packages/ai/openrouter/test/OpenRouterDecisionModel.test.ts +++ b/repos/effect/packages/ai/openrouter/test/OpenRouterDecisionModel.test.ts @@ -67,6 +67,16 @@ const decisionsResponse = { usage: { input_tokens: 312, output_tokens: 48 } } +const Structured = Decision.make({ + input: Schema.String, + decisions: { + severity: Decision.rate({ + instructions: ["How severe?"], + criteria: ["Minor", { label: "Critical", description: { impact: "outage" } }] + }) + } +}) + describe("OpenRouterDecisionModel", () => { it.effect("accepts rounded choice probabilities that total 0.99", () => Effect.gen(function*() { @@ -819,8 +829,37 @@ describe("OpenRouterDecisionModel", () => { assert.strictEqual(error.reason._tag, reason) })) } -}) + it.effect("sends structured descriptions and maps score indices to labels", () => + Effect.gen(function*() { + const result = yield* DecisionModel.decide(Structured, { input: "Checkout is down" }) + assert.strictEqual(result.answers.severity.label, "Critical") + assert.deepStrictEqual({ ...result.answers.severity.probabilities }, { Minor: 0.1, Critical: 0.9 }) + }).pipe( + Effect.provide(OpenRouterDecisionModel.layer({ model: "test/decision-model" })), + Effect.provide(makeClientLayer((request) => + Effect.gen(function*() { + const body = yield* getRequestBody(request) + assert.deepStrictEqual(body.questions, { + severity: { type: "score", instructions: ["How severe?"], criteria: ["Minor", { impact: "outage" }] } + }) + return jsonResponse(request, { + model: "test/decision-model", + usage: { input_tokens: 120, output_tokens: 0 }, + answers: { + severity: { + type: "score", + score: 0.9, + probabilities: { "0": 0.1, "1": 0.9 }, + confidence: 0.9, + legend: { "0": "Minor", "1": { impact: "outage" } } + } + } + }) + }) + )) + )) +}) const makeClientLayer = ( handler: ( request: HttpClientRequest.HttpClientRequest diff --git a/repos/effect/packages/ai/typesafe/CHANGELOG.md b/repos/effect/packages/ai/typesafe/CHANGELOG.md index a7bb9b5da0..b8eae25715 100644 --- a/repos/effect/packages/ai/typesafe/CHANGELOG.md +++ b/repos/effect/packages/ai/typesafe/CHANGELOG.md @@ -1,5 +1,27 @@ # @effect/ai-typesafe +## 4.0.5 + +### Patch Changes + +- [#9124](https://github.com/Effect-TS/effect/pull/9124) [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e) Thanks @jem-computer! - Support structured decision instructions, descriptions, and score legends in TypeSafe, Cloudflare, and OpenRouter. `Decision.rate` accepts labeled descriptions; `Rate.criteria` entries are now `{ label, description }` objects instead of strings. +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/ai/typesafe/README.md b/repos/effect/packages/ai/typesafe/README.md index 1df4b28e97..45ed94f58e 100644 --- a/repos/effect/packages/ai/typesafe/README.md +++ b/repos/effect/packages/ai/typesafe/README.md @@ -28,4 +28,19 @@ Whether your team is considering Effect, rolling it out, or already running it i Use `TypeSafeClient.layerConfig()` to read `TYPESAFE_API_KEY`, then provide `TypeSafeDecisionModel.model("jev-latest")` to a decision workflow. Versioned model identifiers such as `jev-1.13.0` are also supported. +Instructions and descriptions can be strings, JSON objects, or JSON arrays, as in TypeSafe's [structured questions](https://docs.typesafe.ai/primitives/advanced). A rating level with a structured description takes an explicit label, which answers use: + +```ts +import { Decision } from "effect/ai" + +const severity = Decision.rate({ + instructions: "How severe is the reported issue?", + criteria: [ + { label: "cosmetic", description: { what: "No impact to functionality", examples: ["typo in a label"] } }, + { label: "degraded", description: { what: "Broken, but a workaround exists", examples: ["fails in one browser"] } }, + { label: "blocking", description: { what: "No workaround exists", examples: ["cannot log in"] } } + ] +}) +``` + The client does not retry automatically. Rate-limit errors include the provider's retry delay when available. Provider distributions are preserved, not normalized; they must satisfy the core `DecisionModel` validation, including its current `1e-6` sum tolerance. TypeSafe's rounding behavior has not been verified against the live API. diff --git a/repos/effect/packages/ai/typesafe/package.json b/repos/effect/packages/ai/typesafe/package.json index 28f861cd00..0c89df7646 100644 --- a/repos/effect/packages/ai/typesafe/package.json +++ b/repos/effect/packages/ai/typesafe/package.json @@ -1,6 +1,6 @@ { "name": "@effect/ai-typesafe", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "A TypeSafe DecisionModel provider for Effect", diff --git a/repos/effect/packages/ai/typesafe/src/TypeSafeDecisionModel.ts b/repos/effect/packages/ai/typesafe/src/TypeSafeDecisionModel.ts index 91fead032b..2ac15d16c2 100644 --- a/repos/effect/packages/ai/typesafe/src/TypeSafeDecisionModel.ts +++ b/repos/effect/packages/ai/typesafe/src/TypeSafeDecisionModel.ts @@ -56,7 +56,11 @@ export const make = Effect.fnUntraced( questions[key] = { type: "choice", instructions: decision.instructions, criteria: decision.criteria } break case "Rate": - questions[key] = { type: "score", instructions: decision.instructions, criteria: decision.criteria } + questions[key] = { + type: "score", + instructions: decision.instructions, + criteria: decision.criteria.map((level) => level.description) + } break case "Probability": questions[key] = { type: "noul", instructions: decision.instructions, criteria: decision.criteria } @@ -81,7 +85,7 @@ export const make = Effect.fnUntraced( const probabilities: Record = Object.create(null) for (let index = 0; index < levels.length; index++) { const probability = answer.probabilities[String(index)] - if (probability !== undefined) probabilities[levels[index]] = probability + if (probability !== undefined) probabilities[levels[index].label] = probability } answers[key] = { _tag: "Rate", rating: answer.score, probabilities, confidence: answer.confidence } break diff --git a/repos/effect/packages/ai/typesafe/src/TypeSafeSchema.ts b/repos/effect/packages/ai/typesafe/src/TypeSafeSchema.ts index 5f034aca51..794b7a4c42 100644 --- a/repos/effect/packages/ai/typesafe/src/TypeSafeSchema.ts +++ b/repos/effect/packages/ai/typesafe/src/TypeSafeSchema.ts @@ -6,6 +6,8 @@ */ import * as Schema from "effect/Schema" +const Entry = Schema.NullOr(Schema.Union([Schema.String, Schema.JsonObject, Schema.Array(Schema.Json)])) + /** * A classification question. * @@ -15,8 +17,8 @@ import * as Schema from "effect/Schema" */ export const ChoiceQuestion = Schema.Struct({ type: Schema.Literal("choice"), - instructions: Schema.String, - criteria: Schema.Record(Schema.String, Schema.String) + instructions: Entry, + criteria: Schema.Record(Schema.String, Entry) }) /** @@ -28,8 +30,8 @@ export const ChoiceQuestion = Schema.Struct({ */ export const ScoreQuestion = Schema.Struct({ type: Schema.Literal("score"), - instructions: Schema.String, - criteria: Schema.Array(Schema.String) + instructions: Entry, + criteria: Schema.Array(Entry) }) /** @@ -41,12 +43,12 @@ export const ScoreQuestion = Schema.Struct({ */ export const NoulQuestion = Schema.Struct({ type: Schema.Literal("noul"), - instructions: Schema.String, - criteria: Schema.optional(Schema.Struct({ false: Schema.String, true: Schema.String })) + instructions: Entry, + criteria: Schema.optional(Schema.Struct({ false: Entry, true: Entry })) }) /** - * A System One question. + * A System One question with string, JSON object, JSON array, or `null` instructions and descriptions. * * @stability unstable * @category schemas @@ -82,7 +84,7 @@ export const ChoiceAnswer = Schema.Struct({ }) /** - * A zero-based rating and index-keyed distribution. + * A zero-based rating and index-keyed distribution. `legend` maps indices to descriptions. * * @stability unstable * @category schemas @@ -93,7 +95,7 @@ export const ScoreAnswer = Schema.Struct({ score: Schema.Number, probabilities: Schema.Record(Schema.String, Schema.Number), confidence: Schema.Number, - legend: Schema.optional(Schema.Record(Schema.String, Schema.String)) + legend: Schema.optional(Schema.Record(Schema.String, Schema.Json)) }) /** diff --git a/repos/effect/packages/ai/typesafe/test/TypeSafeDecisionModel.test.ts b/repos/effect/packages/ai/typesafe/test/TypeSafeDecisionModel.test.ts index 12909ed0e4..071451bd04 100644 --- a/repos/effect/packages/ai/typesafe/test/TypeSafeDecisionModel.test.ts +++ b/repos/effect/packages/ai/typesafe/test/TypeSafeDecisionModel.test.ts @@ -67,6 +67,16 @@ const systemOneResponse = { usage: { input_tokens: 312, output_tokens: 48 } } +const Structured = Decision.make({ + input: Schema.String, + decisions: { + severity: Decision.rate({ + instructions: ["How severe?"], + criteria: ["Minor", { label: "Critical", description: { impact: "outage" } }] + }) + } +}) + describe("TypeSafeDecisionModel", () => { it.effect("accepts rounded choice probabilities that total 0.99", () => Effect.gen(function*() { @@ -655,8 +665,36 @@ describe("TypeSafeDecisionModel", () => { assert.strictEqual(error._tag, "AiError") assert.strictEqual(error.reason._tag, "RateLimitError") })) -}) + it.effect("sends structured descriptions and maps score indices to labels", () => + Effect.gen(function*() { + const result = yield* DecisionModel.decide(Structured, { input: "Checkout is down" }) + assert.strictEqual(result.answers.severity.label, "Critical") + assert.deepStrictEqual({ ...result.answers.severity.probabilities }, { Minor: 0.1, Critical: 0.9 }) + }).pipe( + Effect.provide(TypeSafeDecisionModel.layer({ model: "jev-latest" })), + Effect.provide(makeClientLayer((request) => + Effect.gen(function*() { + const body = yield* getRequestBody(request) + assert.deepStrictEqual(body.questions, { + severity: { type: "score", instructions: ["How severe?"], criteria: ["Minor", { impact: "outage" }] } + }) + return jsonResponse(request, { + model: "jev-latest", + answers: { + severity: { + type: "score", + score: 0.9, + probabilities: { "0": 0.1, "1": 0.9 }, + confidence: 0.9, + legend: { "0": "Minor", "1": { impact: "outage" } } + } + } + }) + }) + )) + )) +}) const makeClientLayer = ( handler: ( request: HttpClientRequest.HttpClientRequest diff --git a/repos/effect/packages/atom/react/CHANGELOG.md b/repos/effect/packages/atom/react/CHANGELOG.md index d767fc56e0..1d20aef210 100644 --- a/repos/effect/packages/atom/react/CHANGELOG.md +++ b/repos/effect/packages/atom/react/CHANGELOG.md @@ -1,5 +1,27 @@ # @effect/atom-react +## 4.0.5 + +### Patch Changes + +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- [#8954](https://github.com/Effect-TS/effect/pull/8954) [`310228c`](https://github.com/Effect-TS/effect/commit/310228c2be1b629988496eef954012d932ca0eea) Thanks @tmkx! - Allow scheduler 0.28 as a peer dependency so React 19.3 installs no longer report a peer conflict. +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/atom/react/package.json b/repos/effect/packages/atom/react/package.json index 33646b6cc0..543733154d 100644 --- a/repos/effect/packages/atom/react/package.json +++ b/repos/effect/packages/atom/react/package.json @@ -1,6 +1,6 @@ { "name": "@effect/atom-react", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "React bindings for the Effect Atom modules", @@ -62,7 +62,7 @@ "peerDependencies": { "effect": "workspace:^", "react": ">=19.0.0 <20.0.0", - "scheduler": ">=0.25.0 <0.28.0" + "scheduler": ">=0.25.0 <0.29.0" }, "devDependencies": { "@testing-library/dom": "^10.4.2", diff --git a/repos/effect/packages/atom/solid/CHANGELOG.md b/repos/effect/packages/atom/solid/CHANGELOG.md index 5b0c6d4703..3b20ba862a 100644 --- a/repos/effect/packages/atom/solid/CHANGELOG.md +++ b/repos/effect/packages/atom/solid/CHANGELOG.md @@ -1,5 +1,26 @@ # @effect/atom-solid +## 4.0.5 + +### Patch Changes + +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/atom/solid/package.json b/repos/effect/packages/atom/solid/package.json index 80949332f4..9f614f0cd9 100644 --- a/repos/effect/packages/atom/solid/package.json +++ b/repos/effect/packages/atom/solid/package.json @@ -1,6 +1,6 @@ { "name": "@effect/atom-solid", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "SolidJS bindings for the Effect Atom modules", @@ -69,6 +69,6 @@ "@testing-library/jest-dom": "^7.0.1", "effect": "workspace:^", "jsdom": "~30.0.1", - "solid-js": "^1.9.15" + "solid-js": "^1.9.17" } } diff --git a/repos/effect/packages/atom/vue/CHANGELOG.md b/repos/effect/packages/atom/vue/CHANGELOG.md index 14c477bcfd..1cf87edc13 100644 --- a/repos/effect/packages/atom/vue/CHANGELOG.md +++ b/repos/effect/packages/atom/vue/CHANGELOG.md @@ -1,5 +1,26 @@ # @effect/atom-vue +## 4.0.5 + +### Patch Changes + +- Updated dependencies [[`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1), [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2), [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f), [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c), [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82), [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02), [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba), [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23), [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741), [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227), [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0), [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e), [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d), [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7), [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80), [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584), [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217), [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664), [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f), [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220), [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b), [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff), [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2), [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866), [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1), [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88), [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69), [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb), [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97), [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87), [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe), [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0), [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d), [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263), [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a), [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e), [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a), [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331), [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6), [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc), [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6)]: + - effect@4.0.5 + +## 4.0.4 + +### Patch Changes + +- Updated dependencies [[`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8), [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98), [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c), [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236), [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5), [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7), [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be), [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a), [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64), [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177), [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f), [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f), [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04), [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7), [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6), [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925), [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94), [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e), [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013), [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa), [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3), [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491), [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447), [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163), [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708), [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06), [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852)]: + - effect@4.0.4 + +## 4.0.3 + +### Patch Changes + +- Updated dependencies [[`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02), [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7), [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f), [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a), [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681), [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5), [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0), [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f), [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81), [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52), [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e), [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa), [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e), [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0), [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee), [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60), [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303), [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa), [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6), [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a), [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02), [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7), [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e), [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0), [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb), [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503), [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a), [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545), [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c), [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911), [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5), [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112), [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7), [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df), [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b), [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50), [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a), [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530), [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1), [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d), [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c), [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68), [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6), [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08), [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318), [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e)]: + - effect@4.0.3 + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/atom/vue/package.json b/repos/effect/packages/atom/vue/package.json index 6d7ba713ae..d983ef8baa 100644 --- a/repos/effect/packages/atom/vue/package.json +++ b/repos/effect/packages/atom/vue/package.json @@ -1,6 +1,6 @@ { "name": "@effect/atom-vue", - "version": "4.0.2", + "version": "4.0.5", "type": "module", "license": "MIT", "description": "Vue bindings for the Effect Atom modules", diff --git a/repos/effect/packages/effect/CHANGELOG.md b/repos/effect/packages/effect/CHANGELOG.md index 8a345116ac..fb6f29ad07 100644 --- a/repos/effect/packages/effect/CHANGELOG.md +++ b/repos/effect/packages/effect/CHANGELOG.md @@ -1,5 +1,257 @@ # effect +## 4.0.5 + +### Patch Changes + +- [#9055](https://github.com/Effect-TS/effect/pull/9055) [`f665607`](https://github.com/Effect-TS/effect/commit/f665607ee81bee248af7c8129a75692a7ad464e1) Thanks @Tyagiquamar! - Pass a `NonEmptyArray` to the `onNonEmpty` callback of `Array.match` when the input is a mutable array. + +- [#9110](https://github.com/Effect-TS/effect/pull/9110) [`dbf442b`](https://github.com/Effect-TS/effect/commit/dbf442b914b0ab755b42fabb8d29675508dff8d2) Thanks @petar-omni! - Fix `AsyncResult.all` failures carrying a single input's `previousSuccess` instead of the combined record or tuple. + +- [#9105](https://github.com/Effect-TS/effect/pull/9105) [`74d1930`](https://github.com/Effect-TS/effect/commit/74d19304da077d98cc6dcb294c71e253365f272f) Thanks @tim-smart! - Fix infinite atom rebuilds caused by late reads of uninitialized dependencies. + +- [#9145](https://github.com/Effect-TS/effect/pull/9145) [`a03afb6`](https://github.com/Effect-TS/effect/commit/a03afb6147651b8813f6f6d7218e1e7e2c27d93c) Thanks @jayhemnani9910! - Add `Flag.withOptionalValue` for GNU-style flags with an optional value, like `--color[=WHEN]`. A bare flag uses the given value; an explicit value must be attached with `=`. + +- [#9131](https://github.com/Effect-TS/effect/pull/9131) [`f159284`](https://github.com/Effect-TS/effect/commit/f1592843755ec2c41c5b65a0dbe0eb38c96dba82) Thanks @tim-smart! - Fix lost deferred callback wakes in cluster workflows when an activity suspends while a parallel activity is still running. + +- [#9094](https://github.com/Effect-TS/effect/pull/9094) [`5d301cc`](https://github.com/Effect-TS/effect/commit/5d301cc7aaf23e40cc8b59feea9389f747048d02) Thanks @okxint! - Name cluster entity RPC server spans by entity type only (e.g. `WorkflowEntity.Run`) so span names stay low-cardinality. The entity ID is still recorded in the `entity.id` span attribute. + +- [#9176](https://github.com/Effect-TS/effect/pull/9176) [`cd74ea2`](https://github.com/Effect-TS/effect/commit/cd74ea211980de0989ec45f0632cbb0bf07e96ba) Thanks @effect-bot! - Recover persisted local cluster replies from storage to prevent requests hanging when replies arrive before handler registration. Retain local reply notifications as storage-reader wakeups for low-latency streaming. + + Defer terminal in-memory reply publication until the successful outer transaction completes, preserving the commit boundary for reply readers. + +- [#9095](https://github.com/Effect-TS/effect/pull/9095) [`925cf64`](https://github.com/Effect-TS/effect/commit/925cf641c7070140541aef0d6a7fe6b545f9da23) Thanks @jayhemnani9910! - Fix `ConfigProvider.fromDotEnv` and `fromDotEnvContents` rescanning expanded values when `expandVariables` is enabled. Self and circular references no longer overflow the stack, escaped `\$NAME` stays literal, and defaults apply when a reference expands to an empty value. + +- [#9109](https://github.com/Effect-TS/effect/pull/9109) [`54c51d9`](https://github.com/Effect-TS/effect/commit/54c51d9e96134fe20394336fa7f6fd980b299741) Thanks @devangpratap! - Fix `Duration` conversions throwing for very large millisecond values, and make those durations equal to their nanosecond equivalents. + +- [#9161](https://github.com/Effect-TS/effect/pull/9161) [`995c104`](https://github.com/Effect-TS/effect/commit/995c104f7bfd9fb298d6f921fa21b94fbe53b227) Thanks @devangpratap! - Fix `Duration` conversions losing nanosecond precision for large integer millisecond values. + +- [#9112](https://github.com/Effect-TS/effect/pull/9112) [`816575e`](https://github.com/Effect-TS/effect/commit/816575e11cb8c6d9bc9101f20c16a512b88829d0) Thanks @effect-bot! - Use `bigint` for 64-bit `FileSystem.File.Info` metadata. `dev` is now a `bigint`, and `ino`, `rdev`, `nlink`, and `blocks` are `Option`, so file stats no longer fail or drop values outside the safe integer range. Node and Bun read `dev`, `ino`, `rdev`, and `nlink` as unsigned 64-bit integers. Deno reports these fields as numbers, so values above `Number.MAX_SAFE_INTEGER` are rounded by Deno before conversion. + +- [#9150](https://github.com/Effect-TS/effect/pull/9150) [`0df6e06`](https://github.com/Effect-TS/effect/commit/0df6e068b6df2093cefbb1d7ef208d762c5f5b1e) Thanks @tim-smart! - Support per-request URLs in `GraphQLProtocol.layerHttp` and `makeHttp`, as a function of the context and operation or as an `Effect`. `GraphQLResolver` batches lookups by URL. + +- [#9137](https://github.com/Effect-TS/effect/pull/9137) [`52a7d3c`](https://github.com/Effect-TS/effect/commit/52a7d3c8d3ec78caff07e85e7eb88e7c2d67755d) Thanks @tim-smart! - Add HttpClientRequest.compressBody for gzip and deflate request body compression. + +- [#9160](https://github.com/Effect-TS/effect/pull/9160) [`ec831c3`](https://github.com/Effect-TS/effect/commit/ec831c3795b060ca6644cabdc0a8f62365f67af7) Thanks @fubhy! - Accept `Redacted` values as URL parameters in `UrlParams` and `HttpClientRequest`. + +- [#9138](https://github.com/Effect-TS/effect/pull/9138) [`3abc63e`](https://github.com/Effect-TS/effect/commit/3abc63eae45675ad90e52026695366ea0e548c80) Thanks @tim-smart! - Add `HttpMiddleware.decompression`, which decompresses `gzip` and `deflate` request bodies, limits the decompressed size, and rejects other codings with `415`. + +- [#9113](https://github.com/Effect-TS/effect/pull/9113) [`a841b8b`](https://github.com/Effect-TS/effect/commit/a841b8b144607d3dadddd08c5e6807526d24f584) Thanks @effect-bot! - Fix interruption calling `Math.random` and hashing defects, which made deterministic hosts that forbid randomness loop forever or overflow the stack. + +- [#9098](https://github.com/Effect-TS/effect/pull/9098) [`91efea7`](https://github.com/Effect-TS/effect/commit/91efea7860bbb42bd53cd76059538c44fada3217) Thanks @armancharan! - Narrow only the matched prefix when a `Match` tuple pattern is applied to an array or variadic tuple, so the remaining elements keep their original type. + +- [#9151](https://github.com/Effect-TS/effect/pull/9151) [`e271997`](https://github.com/Effect-TS/effect/commit/e271997a14a6ae5201c70217f86537818abbe664) Thanks @tim-smart! - Fix `McpServer` types to require schema services for resource templates and encoding services for prompt parameters with completion handlers. Missing services are now caught at compile time. + +- [#9117](https://github.com/Effect-TS/effect/pull/9117) [`7719bda`](https://github.com/Effect-TS/effect/commit/7719bda8a5bddd561c5332984b827f02f610be3f) Thanks @jayhemnani9910! - Pad 64-bit trace ids to 128 bits in OTLP exports and `traceparent` headers. + +- [#9139](https://github.com/Effect-TS/effect/pull/9139) [`563397f`](https://github.com/Effect-TS/effect/commit/563397fbb8484f41eca5ee3e9fee01596a1c6220) Thanks @tim-smart! - Add opt-in gzip compression to built-in OTLP JSON and protobuf exporters via the compression option or OTEL_EXPORTER_OTLP_COMPRESSION and per-signal environment variables. Compress batches once before retries using HttpClientRequest.compressBody, retaining its default 1KB threshold and uncompressed defaults. + +- [#9127](https://github.com/Effect-TS/effect/pull/9127) [`65b04f8`](https://github.com/Effect-TS/effect/commit/65b04f87b7f0179e6402a3d0e51f039897fdad9b) Thanks @effect-bot! - Add `Path.resolveWithin(root, input)`, which resolves a relative path beneath a root and returns `Option.none()` for traversal escapes and rooted inputs, using the platform's path rules. + +- [#9143](https://github.com/Effect-TS/effect/pull/9143) [`c2859bf`](https://github.com/Effect-TS/effect/commit/c2859bf0176a671154e578653dfb3ba2578a79ff) Thanks @danieljvdm! - Collect tool approvals once per `LanguageModel` request instead of twice. + +- [#9134](https://github.com/Effect-TS/effect/pull/9134) [`c462214`](https://github.com/Effect-TS/effect/commit/c462214483775e57f32cd4854346f49328043ed2) Thanks @effect-bot! - Reduce SQLite statement overhead by borrowing the shared connection while preserving semaphore exclusion and failed-COMMIT recovery. + +- [#9169](https://github.com/Effect-TS/effect/pull/9169) [`d1ad2c7`](https://github.com/Effect-TS/effect/commit/d1ad2c71a0dace15d14bc6f158ea8de2ccbed866) Thanks @danieljvdm! - Cache the last response decoder for each language model response kind, keyed by validation mode and ordered tool schema identities. + +- [#9136](https://github.com/Effect-TS/effect/pull/9136) [`12be65e`](https://github.com/Effect-TS/effect/commit/12be65e5e3a0b2f3231d9ae47665727851d9b7b1) Thanks @tim-smart! - Redact sensitive query values in HTTP spans, request inspection and error messages. Also redact URL credentials in client spans, request inspection and errors. Request URLs sent over the wire are unchanged. + + Move `AWSAccessKeyId`, `Signature`, `sig` and `X-Goog-Signature` from `Headers.CurrentRedactedNames` to the new `UrlParams.CurrentRedactedNames`. A custom list replaces these defaults. Add `UrlParams.isRedactedName`, `UrlParams.redact` and `UrlParams.redactUrl` for explicit redaction. + +- [#9088](https://github.com/Effect-TS/effect/pull/9088) [`352618a`](https://github.com/Effect-TS/effect/commit/352618a562d6f5693e6255a3dcc0c15929c01d88) Thanks @armancharan! - `Match.when`, `Match.whenOr`, `Match.whenAnd`, and `Match.not` now reject object patterns with keys the input type does not have. + +- [#9166](https://github.com/Effect-TS/effect/pull/9166) [`2a8ec8b`](https://github.com/Effect-TS/effect/commit/2a8ec8be832a91292a4c378ac0f94b8dfd547f69) Thanks @danieljvdm! - Keep `Schema` decoding synchronous when a decoding default is an already-successful effect, such as `Effect.succeed(...)`. + +- [#9135](https://github.com/Effect-TS/effect/pull/9135) [`8dec89d`](https://github.com/Effect-TS/effect/commit/8dec89d318297fb27916330ea01b8ff17c1faacb) Thanks @tim-smart! - Preserve completion-handler service requirements in `McpServer.registerResource` and `McpServer.resource` URI templates when handlers take a context argument. + +- [#9118](https://github.com/Effect-TS/effect/pull/9118) [`f05642f`](https://github.com/Effect-TS/effect/commit/f05642f77734e192c6a382e5cfe225cf48a19c97) Thanks @jayhemnani9910! - Fix handler-local `request.url` for parameterized and percent-encoded `HttpRouter` prefixes, respecting duplicate-slash configuration. + +- [#9187](https://github.com/Effect-TS/effect/pull/9187) [`3ad9a0c`](https://github.com/Effect-TS/effect/commit/3ad9a0c6334f579ee38650060f2690c4273dea87) Thanks @effect-bot! - Fix RPC socket clients closing healthy connections before sending a ping when a ping tick runs late. Slow requests now stay connected while the server responds to pings. + +- [#9103](https://github.com/Effect-TS/effect/pull/9103) [`dba4e52`](https://github.com/Effect-TS/effect/commit/dba4e52f505e10730623a7610413156d82fee6fe) Thanks @gcanti! - Reject duplicate discriminants at compile time in `Schema.toTaggedUnion`, including duplicates in nested unions and numeric/string property-key collisions such as `1` and `"1"`. + +- [#9096](https://github.com/Effect-TS/effect/pull/9096) [`7ca8224`](https://github.com/Effect-TS/effect/commit/7ca8224ebb87a603f7a3eaee7470537067fe2bc0) Thanks @jayhemnani9910! - Fix `Sse.encoder` dropping event data after a lone `\r`. CR and CRLF line endings in event data now start a new `data:` line, like LF. + +- [#9133](https://github.com/Effect-TS/effect/pull/9133) [`65d20dd`](https://github.com/Effect-TS/effect/commit/65d20dd6e85a4d1af2ef964625832ae38fa60d8d) Thanks @tim-smart! - Add filesystem watcher installation notifications and wait for all GraphQL watch subscriptions, including nested directories, before generating. This prevents edits during startup from being missed. + +- [#9106](https://github.com/Effect-TS/effect/pull/9106) [`e3ff963`](https://github.com/Effect-TS/effect/commit/e3ff963eb59eb6a71316b3581c35bcffaaa2c263) Thanks @armancharan! - Fix `Stream.timeout` and `Stream.timeoutOrElse` hanging when an async iterator's pending `next()` never settles. + +- [#9183](https://github.com/Effect-TS/effect/pull/9183) [`bc454a3`](https://github.com/Effect-TS/effect/commit/bc454a377dda3b92a24359c7b92810e47694d97a) Thanks @Marve10s! - Fix `String.snakeToCamel` and `String.snakeToPascal` throwing on a trailing underscore or an even-length run of underscores, such as `"foo_"` or `"__"`. A trailing underscore is now dropped and an even-length run of underscores returns `""`; inputs that converted before give the same result. + + `String.noCase` no longer calls a custom `transform` for input without words, such as `""` or `"---"`. + +- [#9124](https://github.com/Effect-TS/effect/pull/9124) [`793d89e`](https://github.com/Effect-TS/effect/commit/793d89efa9201730ba52282a6c53ab12ad50b59e) Thanks @jem-computer! - Support structured decision instructions, descriptions, and score legends in TypeSafe, Cloudflare, and OpenRouter. `Decision.rate` accepts labeled descriptions; `Rate.criteria` entries are now `{ label, description }` objects instead of strings. + +- [#9173](https://github.com/Effect-TS/effect/pull/9173) [`ec9332b`](https://github.com/Effect-TS/effect/commit/ec9332ba2b79a3539579e3241da7b053a5e1e11a) Thanks @effect-bot! - Remove interrupted sleeps from `TestClock` and insert new sleeps in order instead of re-sorting the queue. + +- [#9172](https://github.com/Effect-TS/effect/pull/9172) [`f2b3d8a`](https://github.com/Effect-TS/effect/commit/f2b3d8a573d9189d46cf8ab2c209512dabc89331) Thanks @effect-bot! - Fix `TestClock.adjust` and `TestClock.setTime` skipping sleeps that a woken fiber registers after more than one scheduler hop, such as after `Effect.yieldNow` or forking and joining a child. + +- [#8166](https://github.com/Effect-TS/effect/pull/8166) [`cb2cf5f`](https://github.com/Effect-TS/effect/commit/cb2cf5f19dd23cc65a5cd826844fe7b11e95f4f6) Thanks @KhraksMamtsov! - `Effect.Transaction` now stores attempt metadata, analogous to `Schedule.CurrentMetadata`. Yield it inside a transaction body to read `attempt`, `retryReason`, and the same timing fields as a schedule (`start`, `now`, `elapsed`, `elapsedSincePrevious`). + +- [#9092](https://github.com/Effect-TS/effect/pull/9092) [`b8c201d`](https://github.com/Effect-TS/effect/commit/b8c201d0f492f669bbdbdf5d6f1834abe25ed1fc) Thanks @effect-bot! - Add a `detached` option for discarded child workflows. Detached children neither wake their parent on completion nor get interrupted with it. + +- [#9091](https://github.com/Effect-TS/effect/pull/9091) [`118c9c4`](https://github.com/Effect-TS/effect/commit/118c9c4fe5fa5bac292bed88c01a7c10fe6ed2e6) Thanks @effect-bot! - Keep workflows suspended by `Workflow.SuspendOnFailure` from retrying failed activities until explicitly resumed. Interrupting a failure-suspended workflow now completes it as interrupted without re-running the failed activity. + +## 4.0.4 + +### Patch Changes + +- [#9030](https://github.com/Effect-TS/effect/pull/9030) [`7547a99`](https://github.com/Effect-TS/effect/commit/7547a99f81fa6f7e651d52f3d42081f399bfbca8) Thanks @effect-bot! - Bound sparse array indices in `SchemaGetter.makeTreeRecord`, used by `Schema.fromURLSearchParams` and `Schema.fromFormData`. An indexed container with more than 20 holes is now returned as an object keyed by its index strings instead of a sparse array, and appending after the maximum array index no longer throws. + +- [#9083](https://github.com/Effect-TS/effect/pull/9083) [`711719d`](https://github.com/Effect-TS/effect/commit/711719d28d78dddda4d1685b916d1edf1eae9e98) Thanks @effect-bot! - Bound import-time stack detection probes to the frames they inspect, restoring the caller's stack trace limit afterward. + +- [#9041](https://github.com/Effect-TS/effect/pull/9041) [`8f1ea52`](https://github.com/Effect-TS/effect/commit/8f1ea52f0c073daf445adb987d23860dd76a147c) Thanks @tim-smart! - Stop grouped RequestResolvers from retaining batch keys for the lifetime of the resolver. Equal keys are now matched by the pending batch map, so a key is dropped as soon as its batch stops pending, including after interruption. + +- [#9010](https://github.com/Effect-TS/effect/pull/9010) [`c93485e`](https://github.com/Effect-TS/effect/commit/c93485e365555763b8cf043d2e2a1399ac5bb236) Thanks @effect-bot! - Support an explicit client `servername` for TLS socket upgrades without changing hostname behavior when omitted. + +- [#8990](https://github.com/Effect-TS/effect/pull/8990) [`37e088f`](https://github.com/Effect-TS/effect/commit/37e088f2af8dc03271bb9e2ca2874b750487b0f5) Thanks @bastiankistner! - Use decoded response aliases in generated HTTP clients. Render bare numbers with a standard leading finite check as `Schema.Finite`, preserving annotations and other checks. + +- [#8998](https://github.com/Effect-TS/effect/pull/8998) [`9314666`](https://github.com/Effect-TS/effect/commit/93146666ec49cd6831e9c9d5fa0f9bc72730aaa7) Thanks @gchen0002! - Optimize `Context.pick` for zero or one service. + +- [#9048](https://github.com/Effect-TS/effect/pull/9048) [`a0a26b7`](https://github.com/Effect-TS/effect/commit/a0a26b789c5e865a2f2baf0b29b7b369b100d8be) Thanks @jayhemnani9910! - Fix zoned `DateTime.add` and `DateTime.subtract` to apply hours, minutes, seconds and milliseconds as elapsed time across DST transitions. + +- [#9008](https://github.com/Effect-TS/effect/pull/9008) [`cc843ea`](https://github.com/Effect-TS/effect/commit/cc843ea091e68a57d91f39fc51baff094c50e41d) Thanks @effect-bot! - Add `toolCallValidation: "deferred"` for callers using `disableToolCallResolution: true`. Model-generated tool calls return with `unknown` parameters, including invalid parameters and undeclared tool names, even without a toolkit. Supported by the Anthropic, OpenAI, and OpenAI-compatible providers. Strict validation remains the default; provider-executed calls remain validated. + +- [#8979](https://github.com/Effect-TS/effect/pull/8979) [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3) Thanks @tim-smart! - Add experimental `effect/graphql` with typed operations, middleware, HTTP and subscription transports, partial results, serializable errors and cursor pagination. + +- [#9052](https://github.com/Effect-TS/effect/pull/9052) [`a59b971`](https://github.com/Effect-TS/effect/commit/a59b9711aff7b1af8ab3838b23d0981fb53d7a9a) Thanks @Tarekkharsa! - Fix `HttpClient.withRateLimiter` reading a `Retry-After` HTTP date as a number of seconds. + +- [#9031](https://github.com/Effect-TS/effect/pull/9031) [`fccf660`](https://github.com/Effect-TS/effect/commit/fccf660d83f1db48087cc32da767c43d8e385f64) Thanks @effect-bot! - Add `McpServer.layerHttpRequestScoped` for serverless hosts such as Cloudflare Workers. Each POST is served by an MCP server owned by that request, so no fiber or timer outlives the request. The new layer accepts only sessionless protocol adapters such as `v2026_07_28`, with no subscription or session termination options. `McpServer.layerHttp` retains its long-lived server behavior. + +- [#9081](https://github.com/Effect-TS/effect/pull/9081) [`1bfd8fd`](https://github.com/Effect-TS/effect/commit/1bfd8fddebc978643b7a2077a837b82dc8998177) Thanks @hsyntax! - Tighten colliding bounds in place when exporting JSON Schema, instead of moving them into `allOf`. This applies to numeric, length, item-count and property-count bounds, and an inclusive or exclusive bound implied by the other on the same side is dropped. For example, `Schema.Natural` now exports `minimum: 0`, and `Schema.Int.check(Schema.isGreaterThan(0))` exports `exclusiveMinimum: 0` without the safe-integer `minimum`. + +- [#9013](https://github.com/Effect-TS/effect/pull/9013) [`78e4c43`](https://github.com/Effect-TS/effect/commit/78e4c435ede00c7757c3507e60feb821edc85b5f) Thanks @jayhemnani9910! - Fix `Multipart.toPersisted` failing for uploads named `.` or `..` and for long multi-byte file names. + +- [#8991](https://github.com/Effect-TS/effect/pull/8991) [`fde67a1`](https://github.com/Effect-TS/effect/commit/fde67a10e9245aa3974ecdca00239de8dfd2cc9f) Thanks @fubhy! - Add `NetAddress.loopbackAddresses`. + +- [#8992](https://github.com/Effect-TS/effect/pull/8992) [`118deef`](https://github.com/Effect-TS/effect/commit/118deefe7c02089b1bc5d202ce3225f05a98cd04) Thanks @fubhy! - Add `Host.toFullyQualified`, `Host.toRelative`, and `Host.parseHostsFile`. + +- [#9046](https://github.com/Effect-TS/effect/pull/9046) [`cea74c9`](https://github.com/Effect-TS/effect/commit/cea74c92ac839009c6ba112504689d8726f648d7) Thanks @effect-bot! - Persist outgoing cluster messages while the locally assigned shard is waiting for its lock. + +- [#9056](https://github.com/Effect-TS/effect/pull/9056) [`b7c1ac6`](https://github.com/Effect-TS/effect/commit/b7c1ac683775f37c78061da3304d37a800d227d6) Thanks @tim-smart! - `Prompt.fromResponseParts` now keeps streamed text and reasoning in stream order, and keeps partial text from unended text blocks. + +- [#8997](https://github.com/Effect-TS/effect/pull/8997) [`f837966`](https://github.com/Effect-TS/effect/commit/f8379667c914cc5bbc5acfd41eee0090ee247925) Thanks @effect-bot! - Release the durable waits of losing `DurableDeferred.raceAll` branches once the race settles, so a late completion such as a losing `DurableClock.sleep` no longer preempts and replays the continuing workflow + +- [#9053](https://github.com/Effect-TS/effect/pull/9053) [`09738f4`](https://github.com/Effect-TS/effect/commit/09738f4aa61f4e188d0b1db76b405618f0e31d94) Thanks @Tarekkharsa! - Honor `Retry-After` in `HttpClient.retryTransient`. + +- [#9019](https://github.com/Effect-TS/effect/pull/9019) [`22e7129`](https://github.com/Effect-TS/effect/commit/22e7129023f15aea70ec3bb5ab92c93aad605b4e) Thanks @effect-bot! - Allow configuring Scalar's preferred authentication security scheme through HttpApiScalar without a TypeScript cast. + +- [#9069](https://github.com/Effect-TS/effect/pull/9069) [`fdcb47e`](https://github.com/Effect-TS/effect/commit/fdcb47e64304b52299bad350aa57722fa9e3c013) Thanks @effect-bot! - Fix cluster Sharding startup accessing storage-loop state before initialization, preventing a scheduler-dependent ReferenceError and delayed initial storage reads. + +- [#9049](https://github.com/Effect-TS/effect/pull/9049) [`fc349a1`](https://github.com/Effect-TS/effect/commit/fc349a13f77c5cc4c94752546913b90be8d0bfaa) Thanks @jayhemnani9910! - Fix `Sink.takeUntil` and `Sink.takeUntilEffect` dropping the element after a match. They now stop at the match and return the remaining input as leftovers. + +- [#8979](https://github.com/Effect-TS/effect/pull/8979) [`ab90be9`](https://github.com/Effect-TS/effect/commit/ab90be98ea693df4c0d647cf29a4b913ecbef8f3) Thanks @tim-smart! - Add `dispatchEmptyNamedEvents` to `Sse` decode options. It also dispatches an event that sets an `event:` name but has no `data:` line, which protocols such as graphql-sse use for `complete`. + +- [#9065](https://github.com/Effect-TS/effect/pull/9065) [`892d14d`](https://github.com/Effect-TS/effect/commit/892d14d88b84f842457494792bf702eb15d5b491) Thanks @Abdullah1738! - Fix quadratic parsing time in `Sse.makeParser` and `Sse.decode` for long lines split across many chunks. + +- [#9066](https://github.com/Effect-TS/effect/pull/9066) [`077c557`](https://github.com/Effect-TS/effect/commit/077c55770db747f04213af82bb4651376ea04447) Thanks @effect-bot! - Complete HTTP server spans synchronously before the request fiber exits, preventing completed spans from being lost during immediate runtime shutdown. + +- [#9029](https://github.com/Effect-TS/effect/pull/9029) [`4a999a3`](https://github.com/Effect-TS/effect/commit/4a999a34e81ef754b959f6ded75b272503bc1163) Thanks @effect-bot! - Clean up unused Anthropic bindings and make documentation-only imports type-only, preserving server-tool inputs and documentation links. + +- [#9062](https://github.com/Effect-TS/effect/pull/9062) [`797696a`](https://github.com/Effect-TS/effect/commit/797696a2b7b5b3c73e01b8d72d9a327e49a39708) Thanks @adam-r-kowalski! - Merge outer headers and cookies into a copy of a raw `Response` in `HttpServerResponse.toWeb`, leaving the original headers unchanged. This supports immutable headers and prevents cookies from accumulating across requests that reuse a response. Responses with nothing to merge are returned unchanged. + +- [#9007](https://github.com/Effect-TS/effect/pull/9007) [`cf5179b`](https://github.com/Effect-TS/effect/commit/cf5179b48867597342ccc9912252ac75637aec06) Thanks @effect-bot! - Wake a suspended `WorkflowEngine.execute` caller as soon as its workflow has a final result, instead of waiting for the next `suspendedRetrySchedule` step. A replay that suspends again does not spend a step of the schedule. With `ClusterWorkflowEngine`, only callers on the runner that owns the execution are woken early; other callers keep relying on `suspendedRetrySchedule`. + +- [#9037](https://github.com/Effect-TS/effect/pull/9037) [`e1c6053`](https://github.com/Effect-TS/effect/commit/e1c6053c5e813596a24793c90cbf732b63c98852) Thanks @effect-bot! - `HttpEffect.toWebHandler` now interrupts a streamed response body when the request is aborted after its headers were sent, even if the body is no longer being read, which releases the request scope. + +## 4.0.3 + +### Patch Changes + +- [#8977](https://github.com/Effect-TS/effect/pull/8977) [`b4e5af8`](https://github.com/Effect-TS/effect/commit/b4e5af825ac4c869d09c008b2d1b58cdd0ce4c02) Thanks @kitlangton! - Prevent crashes and premature interruption when `Effect.cached`, `Effect.cachedWithTTL`, and `Effect.cachedInvalidateWithTTL` are synchronously re-entered. + +- [#8982](https://github.com/Effect-TS/effect/pull/8982) [`b8d6e7a`](https://github.com/Effect-TS/effect/commit/b8d6e7a89b8c2283aebbfa154963efccd7addbd7) Thanks @Yi-111-a! - Export `CliOutput.displayWidth` to measure terminal-cell widths using the same logic as built-in CLI help and tables. + +- [#8933](https://github.com/Effect-TS/effect/pull/8933) [`89d5c88`](https://github.com/Effect-TS/effect/commit/89d5c8881024e31b08344bf9f992be0e5d024e4f) Thanks @tim-smart! - Respect `NO_COLOR` in CLI prompts and the command wizard, suppressing color and style escapes while preserving cursor and redraw controls. + +- [#8941](https://github.com/Effect-TS/effect/pull/8941) [`66257d2`](https://github.com/Effect-TS/effect/commit/66257d29224e949f7b300ff33416098519c7e86a) Thanks @Tanner-Scadden! - Hand cluster shards off one at a time when `Sharding` shuts down, after their entities and singletons have stopped, so live runners can take them over sooner. The handoff is best effort: its wait is bounded, and if it times out, `releaseAll` attempts to release the remaining locks. A runner that is shutting down no longer acquires new shards, and releasing a shard no longer waits forever on an entity whose id is also active on another shard. + +- [#8940](https://github.com/Effect-TS/effect/pull/8940) [`cd2ab19`](https://github.com/Effect-TS/effect/commit/cd2ab19600d00e1e9c84028f29dcb22978e8c681) Thanks @Tanner-Scadden! - Fix cluster shard handoffs. Interrupts and stream acknowledgements now reach requests still draining on the previous owner, and `RpcServer` accepts acknowledgements for active streams after a client's EOF. Volatile requests sent during a handoff wait, for at most `shardLockExpiration`, until the shard can be served instead of repeatedly failing with `EntityNotAssignedToRunner`. + +- [#8897](https://github.com/Effect-TS/effect/pull/8897) [`ca068ce`](https://github.com/Effect-TS/effect/commit/ca068cef445101cbb2710c24360ca3a7ab9b94d5) Thanks @effect-bot! - Add separate migration and storage layers to cluster SQL storage so applications can use tables migrated by an owner connection. + +- [#8895](https://github.com/Effect-TS/effect/pull/8895) [`f686000`](https://github.com/Effect-TS/effect/commit/f686000760c2d3ff27aea5767e73c1618c5d21c0) Thanks @tim-smart! - Serialize SchemaError as a compact object containing its tag and formatted message in JSON logs and Node inspection, without dumping schema AST nodes. + +- [#8968](https://github.com/Effect-TS/effect/pull/8968) [`e052f1b`](https://github.com/Effect-TS/effect/commit/e052f1b30b379f120854f9b2394efa7ac44fc01f) Thanks @sledorze! - Avoid a redundant map copy when `Context.add` rebases an overlay chain. + +- [#8487](https://github.com/Effect-TS/effect/pull/8487) [`c755b69`](https://github.com/Effect-TS/effect/commit/c755b69701e29e055ef5c4c87ced83e15b3faa81) Thanks @fubhy! - Add `TestCrypto.layer`, which provides deterministic random operations derived from a seed while preserving a platform crypto service's digest implementation. + +- [#8935](https://github.com/Effect-TS/effect/pull/8935) [`ebe487f`](https://github.com/Effect-TS/effect/commit/ebe487f88846a131faa0c61a5f65f80187782e52) Thanks @tim-smart! - Turn `Crypto.randomUUIDv4` and `Crypto.randomUUIDv7` into functions accepting an optional `{ format: "hex" | "bytes" }` option. Call them with `()` for the default lowercase, hyphenated UUID string, or with `{ format: "bytes" }` for a 16-byte `Uint8Array`. + +- [#8926](https://github.com/Effect-TS/effect/pull/8926) [`63bfad8`](https://github.com/Effect-TS/effect/commit/63bfad88fc60de2d8c21dc7f02a62f48a0b5281e) Thanks @effect-bot! - Fix `DurableDeferred.raceAll` and `DurableDeferred.into` so a workflow branch continues after its result is recorded instead of stalling until a concurrently parked sibling is woken. The effect passed to `DurableDeferred.into` now counts as in-flight work, so a parked sibling no longer suspends the run while it runs. + +- [#8921](https://github.com/Effect-TS/effect/pull/8921) [`8598157`](https://github.com/Effect-TS/effect/commit/8598157653e46fb12af342cb8bd6d30122afa4fa) Thanks @devangpratap! - Fix `Duration.fromInputUnsafe` throwing on infinite nanosecond totals. It now returns an infinite duration, and `Duration.fromInput` returns `Some` instead of `None`. + +- [#8972](https://github.com/Effect-TS/effect/pull/8972) [`76a03f7`](https://github.com/Effect-TS/effect/commit/76a03f759980de88cdcb7c906fca92a6212b760e) Thanks @devangpratap! - Fix `Duration.times` throwing when a nanosecond-backed duration is multiplied by a fractional or non-finite number. Fractional results round to the nearest nanosecond. + +- [#8900](https://github.com/Effect-TS/effect/pull/8900) [`182e26d`](https://github.com/Effect-TS/effect/commit/182e26dae1c8d16adf0372b6b106babb87d0f7b0) Thanks @effect-bot! - Add a `noFollow` option to `FileSystem.open` to reject symlinks at the final path component. Supported on Node and Bun on POSIX; Windows and Deno return `BadArgument`. Add `{ position }` to `File.read` and `File.readAlloc` for concurrent reads that leave the cursor unchanged. + +- [#8885](https://github.com/Effect-TS/effect/pull/8885) [`a46592a`](https://github.com/Effect-TS/effect/commit/a46592aed944b046e562815083b367ad28c8eaee) Thanks @effect-bot! - Preserve duplicate slashes in query values when FindMyWay normalizes request paths. + +- [#8986](https://github.com/Effect-TS/effect/pull/8986) [`1d3419e`](https://github.com/Effect-TS/effect/commit/1d3419e76ca8ad7c2504b9ec75b281ef3dff6b60) Thanks @jayhemnani9910! - Fix histogram exporters to retain all finite boundaries and overflow observations in OTLP, and emit a single `+Inf` bucket in Prometheus. + +- [#8932](https://github.com/Effect-TS/effect/pull/8932) [`e00eaae`](https://github.com/Effect-TS/effect/commit/e00eaae8d9d503bea1871031670c28f82935c303) Thanks @tim-smart! - Defer terminal input acquisition until a prompt needs user input, so constant fallback prompts leave piped stdin untouched. + +- [#8888](https://github.com/Effect-TS/effect/pull/8888) [`133ceb2`](https://github.com/Effect-TS/effect/commit/133ceb2b77331742f381c09552478a86975826fa) Thanks @RhysSullivan! - Return empty 200 text/event-stream responses for MCP HTTP request POSTs when cancellation withholds every reply. Return 500 for other request POSTs that end without a response. + +- [#8924](https://github.com/Effect-TS/effect/pull/8924) [`a494a64`](https://github.com/Effect-TS/effect/commit/a494a647885d8eacff4fce0ebde1263e8b261be6) Thanks @effect-bot! - Add `McpServer.layerHttp({ allowSubscriptions: false })` to disable `v2026_07_28` subscriptions while keeping request-scoped progress and log notifications. + +- [#8890](https://github.com/Effect-TS/effect/pull/8890) [`d6082a2`](https://github.com/Effect-TS/effect/commit/d6082a25a3779f7e2abba2787323d5d9c7e1d24a) Thanks @tim-smart! - Send MCP cancellation notifications for interrupted server-to-client requests instead of internal RPC control messages. + +- [#8925](https://github.com/Effect-TS/effect/pull/8925) [`ee3a350`](https://github.com/Effect-TS/effect/commit/ee3a35076854eb6a49183bf8d5ac610e46393d02) Thanks @effect-bot! - Prevent MCP subscriptions from receiving deferred list-change notifications emitted before they subscribed, while preserving coalesced runtime changes. + +- [#8955](https://github.com/Effect-TS/effect/pull/8955) [`7ba976c`](https://github.com/Effect-TS/effect/commit/7ba976c620d62125ecc7924be379308cf9b87cd7) Thanks @effect-bot! - Allow interrupted activities to run again when the in-memory workflow engine replays a preempted execution. + +- [#8973](https://github.com/Effect-TS/effect/pull/8973) [`9dbd07e`](https://github.com/Effect-TS/effect/commit/9dbd07e0063301b2361e04dd9b3697d5469ab85e) Thanks @fubhy! - Accept address inputs in `Dns.reverse` and name server inputs in the platform `Dns` services, and add `Dns.nameServerFromInput`. + +- [#8953](https://github.com/Effect-TS/effect/pull/8953) [`d4f7dc3`](https://github.com/Effect-TS/effect/commit/d4f7dc3300a04b45800bd5331bd8282ce1dd0ea0) Thanks @fubhy! - Add TLSA records to `effect/net/Dns`, with a `Schema.DnsTlsaRecord` schema whose JSON codec encodes the certificate association data as hex. The Node.js `Dns` service queries them with `resolveTlsa` (Node.js 22.15 or 23.9 and later); Bun, Deno, and older Node.js versions fail TLSA queries with `Unsupported`. + +- [#8880](https://github.com/Effect-TS/effect/pull/8880) [`a9b5148`](https://github.com/Effect-TS/effect/commit/a9b514822573c0e27452d80bcf35a6fa036d32fb) Thanks @fubhy! - Add experimental `Host`, `Dns`, and `AddressResolver` modules to `effect/net` for host parsing, DNS queries, and endpoint resolution, with Node, Bun, and Deno services. DNS operations accept and normalize domain-name strings; endpoint resolution also accepts `host:port` strings. Add scoped IPv6 literals and host and DNS record schemas, including JSON codecs for records. + + Provide the services explicitly; they are not included in the platform `*Services` layers. Use `NodeAddressResolver.layer.pipe(Layer.provideMerge(NodeDns.layer))` to provide both Node services. + +- [#8970](https://github.com/Effect-TS/effect/pull/8970) [`e7d84e4`](https://github.com/Effect-TS/effect/commit/e7d84e449a0e75d1d04486ea81dfb58531fd6503) Thanks @fubhy! - Add `fromInput` constructors to the `effect/net` data types. + +- [#8899](https://github.com/Effect-TS/effect/pull/8899) [`0e2b988`](https://github.com/Effect-TS/effect/commit/0e2b988eec37873bf37f056e2b1b1e52193c4a7a) Thanks @tim-smart! - Answer orphaned cluster workflow activity requests with Suspended instead of waiting indefinitely for replay registration. + +- [#8987](https://github.com/Effect-TS/effect/pull/8987) [`84f48df`](https://github.com/Effect-TS/effect/commit/84f48df586ef1be9290910e3f37b5bb2811b9545) Thanks @jayhemnani9910! - Omit `min` and `max` from subsequent delta histogram exports in `OtlpMetrics`: cumulative extrema do not describe the reported interval. + +- [#8907](https://github.com/Effect-TS/effect/pull/8907) [`48ed32f`](https://github.com/Effect-TS/effect/commit/48ed32f846c11ab702b22c84ed103c767d0dd21c) Thanks @tim-smart! - Add a `delay` option to `PersistedQueue.offer` that postpones an element's first delivery in the memory, Redis and SQL stores. + +- [#8904](https://github.com/Effect-TS/effect/pull/8904) [`59e58a6`](https://github.com/Effect-TS/effect/commit/59e58a6b9839b475e02f2f551dd4c1328b548911) Thanks @effect-bot! - Add PowerShell CLI completions with `--completions powershell` (alias `pwsh`). + +- [#8409](https://github.com/Effect-TS/effect/pull/8409) [`b9e7821`](https://github.com/Effect-TS/effect/commit/b9e7821be3efd61b5ac01f8ced0818e50ed7f0e5) Thanks @tim-smart! - Add `DatagramSocket` for UDP on Node, Bun, and Deno, and `NetAddress.inetAddressFromNativeUnsafe` for runtime-reported addresses. + +- [#8943](https://github.com/Effect-TS/effect/pull/8943) [`aa811e4`](https://github.com/Effect-TS/effect/commit/aa811e454b61033ec150204d959bbf09e44e2112) Thanks @Tanner-Scadden! - Report RPC response encoding failures to ErrorReporter and include the RPC tag in client defects. + +- [#8958](https://github.com/Effect-TS/effect/pull/8958) [`bfc5742`](https://github.com/Effect-TS/effect/commit/bfc5742e18945026e4360e928e311042d8e47ab7) Thanks @tim-smart! - End the RPC server span with the encoding defect when a response fails to encode, instead of recording it as a client interruption. + +- [#8976](https://github.com/Effect-TS/effect/pull/8976) [`f9f7a5a`](https://github.com/Effect-TS/effect/commit/f9f7a5a16e1f7685b6653a71cd0265ad027c69df) Thanks @juliusmarminge! - Add `onPingTimeout` to `RpcClient.makeProtocolSocket` and `RpcClient.layerProtocolSocket` to distinguish ping timeouts from other socket failures. It runs only when a ping timeout drops an open connection, before `onDisconnect` and in-flight call failures; defects are logged and ignored. + +- [#8956](https://github.com/Effect-TS/effect/pull/8956) [`73fa287`](https://github.com/Effect-TS/effect/commit/73fa2873cb1269874eec8998d2f5ce9d44b0bb0b) Thanks @schickling-assistant! - Export `Schema.isInt` and `Schema.Int` as exact JSON Schema integers bounded by `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER`. Composed bounds retain the tighter constraint, and exact integer branches preserve `oneOf`. + +- [#8937](https://github.com/Effect-TS/effect/pull/8937) [`7ff5048`](https://github.com/Effect-TS/effect/commit/7ff5048db51daba7c31ee90d5e3d17861a9e6b50) Thanks @effect-bot! - Skip startup stack probing when `Error.stackTraceLimit` is zero, avoiding unnecessary stack formatting during module loading. + +- [#8927](https://github.com/Effect-TS/effect/pull/8927) [`7803e51`](https://github.com/Effect-TS/effect/commit/7803e51e940727382c8af049f4744955fa21f53a) Thanks @effect-bot! - Hold the shared connection for the whole statement or stream on single-connection SQL clients, so another fiber's transaction can no longer roll back an acknowledged write or expose uncommitted rows to a plain read. + +- [#8938](https://github.com/Effect-TS/effect/pull/8938) [`93410da`](https://github.com/Effect-TS/effect/commit/93410da528b46607caf006f8c8d37dc6cee94530) Thanks @effect-bot! - Add `Stdio.stderrIsTerminal` with an overridable false default and runtime detection for Node.js, Bun, and Deno. + +- [#8963](https://github.com/Effect-TS/effect/pull/8963) [`aef1d1f`](https://github.com/Effect-TS/effect/commit/aef1d1f2e59cdfd85766a2b168bb3ec1b64538a1) Thanks @tim-smart! - Add `ClusterSchema.InterruptOnTermination` to interrupt opted-in RPCs as soon as entity termination starts. Persisted requests resume under the next owner without saving an interrupt reply, and server-side `Uninterruptible` takes precedence. + +- [#8917](https://github.com/Effect-TS/effect/pull/8917) [`d6d515b`](https://github.com/Effect-TS/effect/commit/d6d515bafc83e02bee055231b52fdce2ea24d88d) Thanks @Brendonovich! - Make `HttpClient.withRateLimiter` wait for the reported reset once a response's remaining budget is exhausted, including when a limit header is also present. + +- [#8892](https://github.com/Effect-TS/effect/pull/8892) [`ea52c24`](https://github.com/Effect-TS/effect/commit/ea52c245f64b378628ca290bf99bdb6cd033809c) Thanks @effect-bot! - Propagate SQL transaction COMMIT errors as typed SqlError failures when cleanup succeeds. Preserve both COMMIT and cleanup errors as defects when cleanup fails, so typed recovery cannot hide an unsafe connection state. + +- [#8913](https://github.com/Effect-TS/effect/pull/8913) [`7e44402`](https://github.com/Effect-TS/effect/commit/7e444029d3101640ea2edbffafa882097b78bb68) Thanks @grzegorz-naileditgames! - Reject B3 single-header and multi-header trace contexts with invalid trace or span identifiers. + +- [#8978](https://github.com/Effect-TS/effect/pull/8978) [`0b17b9e`](https://github.com/Effect-TS/effect/commit/0b17b9e2e43c2f95726470aee188fd9e2bf1baf6) Thanks @tim-smart! - Allow WebSocket clients on Node and Bun to send handshake headers alongside subprotocols through socket constructors, channels, and layers. Preserve browser-compatible constructor calls when headers are not supplied. + +- [#8891](https://github.com/Effect-TS/effect/pull/8891) [`9753be9`](https://github.com/Effect-TS/effect/commit/9753be9ecf8dfa9c58169f41a4b876d638b9cc08) Thanks @tim-smart! - Deliver terminal replies for persisted `ClusterSchema.WithTransaction` requests only after commit or clean rollback. On transaction failure, recover a committed reply or retry the request. + +- [#8886](https://github.com/Effect-TS/effect/pull/8886) [`977096b`](https://github.com/Effect-TS/effect/commit/977096bcea55317ef0e845218c818430cc6e5318) Thanks @effect-bot! - Fix lost failure replies for persisted cluster RPCs using `ClusterSchema.WithTransaction`. Save typed failures and non-fatal defects after rollback so retries receive the stored reply. Successful replies still commit with the handler's writes. + +- [#8882](https://github.com/Effect-TS/effect/pull/8882) [`cf58cb0`](https://github.com/Effect-TS/effect/commit/cf58cb0362972b4b46b762d8c9062ec7349b438e) Thanks @devangpratap! - Fix generated Zsh completions for flag descriptions containing `]`. + ## 4.0.2 ### Patch Changes diff --git a/repos/effect/packages/effect/SCHEMA.md b/repos/effect/packages/effect/SCHEMA.md index 5168151ca3..ac4a29956a 100644 --- a/repos/effect/packages/effect/SCHEMA.md +++ b/repos/effect/packages/effect/SCHEMA.md @@ -1049,6 +1049,20 @@ An index signature lets a struct accept any string key in addition to its fixed Filters applied to either the struct or the record are preserved when combined. +The base schema must have an object-shaped encoded type. Whole-object transformations are not supported, even when the rest array is empty. For JSON-string encoding, wrap the completed schema with `Schema.fromJsonString` rather than passing a JSON-string schema to `Schema.StructWithRest`: + +```ts +import { Schema } from "effect" + +const base = Schema.Record(Schema.Literals(["bash", "sh"]), Schema.NonEmptyString) +const records = [Schema.Record(Schema.NonEmptyString, Schema.NonEmptyString)] as const +const schema = Schema.fromJsonString(Schema.StructWithRest(base, records), { space: 2 }) + +type Encoded = typeof schema.Encoded // string +``` + +Object-shaped encoded types alone do not guarantee compatibility: unsupported whole-object encodings are still rejected at runtime. Transformations on individual fields remain supported. + **Example** (Combining fixed properties with an index signature) ```ts @@ -2160,7 +2174,7 @@ This helper has some advantages over a dedicated constructor: - You can choose among multiple possible tag fields if present. - It supports unions that include nested unions. -Each member must have a unique discriminant property key. `toTaggedUnion` throws when it encounters a duplicate. Numeric and string values that resolve to the same property key, such as `1` and `"1"`, are considered duplicates. +Each member must have a unique discriminant property key. `toTaggedUnion` rejects overlapping discriminant types in known member tuples at compile time, including nested unions. It also throws when it encounters a duplicate at runtime. Numeric and string values that resolve to the same property key, such as `1` and `"1"`, are considered duplicates. **Note**. If the tag is the standard `_tag` field, you can use `Schema.TaggedUnion` instead. @@ -4393,6 +4407,8 @@ console.log(A.ast.annotations?.title) Use `extend` to create a subclass that adds fields to the base schema. Instance fields declared on the base class are also available on the subclass. +Fields with the same name replace inherited fields. Use this to refine validation or change encoding. Effect does not check compatibility; the caller must ensure the replacement preserves the base class contract. + **Example** (Extending a class with new fields) ```ts diff --git a/repos/effect/packages/effect/package.json b/repos/effect/packages/effect/package.json index 48e82a4481..da512a3781 100644 --- a/repos/effect/packages/effect/package.json +++ b/repos/effect/packages/effect/package.json @@ -1,7 +1,7 @@ { "name": "effect", "type": "module", - "version": "4.0.2", + "version": "4.0.5", "license": "MIT", "description": "The missing standard library for TypeScript, for writing production-grade software.", "homepage": "https://effect.website", @@ -46,6 +46,7 @@ "./persistence": "./src/persistence/index.ts", "./process": "./src/process/index.ts", "./reactivity": "./src/reactivity/index.ts", + "./graphql": "./src/graphql/index.ts", "./rpc": "./src/rpc/index.ts", "./schema": "./src/schema/index.ts", "./socket": "./src/socket/index.ts", @@ -89,6 +90,7 @@ "./persistence": "./dist/persistence/index.js", "./process": "./dist/process/index.js", "./reactivity": "./dist/reactivity/index.js", + "./graphql": "./dist/graphql/index.js", "./rpc": "./dist/rpc/index.js", "./schema": "./dist/schema/index.js", "./socket": "./dist/socket/index.js", @@ -110,13 +112,15 @@ "check": "tsc -b tsconfig.json" }, "devDependencies": { - "@types/node": "^26.6.4", + "@types/node": "^26.6.5", "ajv": "^8.20.0", "ajv-draft-04": "^1.0.0", "ast-types": "^0.16.3", + "esbuild": "^0.28.2", "immer": "^11.1.21", + "miniflare": "5.20260925.0-alpha", "protobufjs": "^8.8.0", - "tinybench": "^6.2.0", + "tinybench": "^6.2.1", "valibot": "^1.5.0" } } diff --git a/repos/effect/packages/effect/src/Array.ts b/repos/effect/packages/effect/src/Array.ts index 402966e7f5..31f0b052d8 100644 --- a/repos/effect/packages/effect/src/Array.ts +++ b/repos/effect/packages/effect/src/Array.ts @@ -411,8 +411,10 @@ export const fromOption: (self: Option.Option) => Array = Option.toArra * * **Details** * - * `onNonEmpty` receives a `NonEmptyReadonlyArray`. Supports both data-first and - * data-last usage. + * `onNonEmpty` receives a `NonEmptyArray` for mutable arrays and a + * `NonEmptyReadonlyArray` otherwise. Data-last calls default to the readonly + * callback, so the returned function still accepts `ReadonlyArray`. Supports + * both data-first and data-last usage. * * **Example** (Branching on emptiness) * @@ -442,6 +444,19 @@ export const match: { readonly onNonEmpty: (self: NonEmptyReadonlyArray) => C } ): (self: ReadonlyArray) => B | C + ( + options: { + readonly onEmpty: LazyArg + readonly onNonEmpty: (self: NonEmptyArray) => C + } + ): (self: Array) => B | C + ( + self: Array, + options: { + readonly onEmpty: LazyArg + readonly onNonEmpty: (self: NonEmptyArray) => C + } + ): B | C ( self: ReadonlyArray, options: { diff --git a/repos/effect/packages/effect/src/Channel.ts b/repos/effect/packages/effect/src/Channel.ts index c6f3a68a18..35f3d6955f 100644 --- a/repos/effect/packages/effect/src/Channel.ts +++ b/repos/effect/packages/effect/src/Channel.ts @@ -1932,7 +1932,9 @@ const readableStreamToPullUnsafe = (options: { * Each yielded value is emitted as an output element. The iterator's return * value becomes the channel's done value. Thrown or rejected iterator errors * are converted with `onError`. If the channel scope closes early and the - * iterator has a `return` method, that method is called. + * iterator has a `return` method, that method is called. It is awaited unless + * a `next()` call is still pending, in which case its result is ignored and an + * async generator may not run its cleanup until that pull settles. * * @stability stable * @category constructors @@ -1944,12 +1946,28 @@ export const fromAsyncIterable = ( ): Channel => fromTransform(Effect.fnUntraced(function*(_, scope) { const iter = iterable[Symbol.asyncIterator]() + let pulling = false if (iter.return) { - yield* Scope.addFinalizer(scope, Effect.promise(() => iter.return!())) + // `return()` may not settle until a pending `next()` does, so only + // await it when the iterator is idle. + yield* Scope.addFinalizer( + scope, + Effect.suspend(() => + pulling + ? Effect.sync(() => void iter.return!().catch(constVoid)) + : Effect.promise(() => iter.return!()) + ) + ) } return Effect.flatMap( Effect.tryPromise({ - try: () => iter.next(), + try: () => { + const promise = iter.next() + pulling = true + return promise.finally(() => { + pulling = false + }) + }, catch: onError }), (result) => result.done ? Cause.done(result.value) : Effect.succeed(result.value) @@ -1965,6 +1983,9 @@ export const fromAsyncIterable = ( * The iterator's return value becomes the channel's done value. Thrown or * rejected iterator errors are converted with `onError`. If the channel scope * closes early and the iterator has a `return` method, that method is called. + * It is awaited unless a `next()` call is still pending, in which case its + * result is ignored and an async generator may not run its cleanup until that + * pull settles. * * @stability stable * @category constructors diff --git a/repos/effect/packages/effect/src/ConfigProvider.ts b/repos/effect/packages/effect/src/ConfigProvider.ts index 4250c4bc26..b07eef48f8 100644 --- a/repos/effect/packages/effect/src/ConfigProvider.ts +++ b/repos/effect/packages/effect/src/ConfigProvider.ts @@ -1116,56 +1116,52 @@ function dotEnvExpand(parsed: Record): Record { for (const configKey of Object.keys(parsed)) { // resolve escape sequences - newParsed[configKey] = interpolate(parsed[configKey], parsed).replace(/\\\$/g, "$") + newParsed[configKey] = interpolate(parsed[configKey], parsed, new Set([configKey])).replace(/\\\$/g, "$") } return newParsed } -function interpolate(envValue: string, parsed: Record): string { - // find the last unescaped dollar sign in the - // value so that we can evaluate it - const lastUnescapedDollarSignIndex = searchLast(envValue, /(?!(?<=\\))\$/g) - - // If we couldn't match any unescaped dollar sign - // let's return the string as is - if (lastUnescapedDollarSignIndex === -1) return envValue - - // This is the right-most group of variables in the string - const rightMostGroup = envValue.slice(lastUnescapedDollarSignIndex) - - /** - * This finds the inner most variable/group divided - * by variable name and default value (if present) - * ( - * (?!(?<=\\))\$ // only match dollar signs that are not escaped - * {? // optional opening curly brace - * ([\w]+) // match the variable name - * (?::-([^}\\]*))? // match an optional default value - * }? // optional closing curly brace - * ) - */ - const matchGroup = /((?!(?<=\\))\${?([\w]+)(?::-([^}\\]*))?}?)/ - const match = rightMostGroup.match(matchGroup) - - if (match !== null) { - const [_, group, variableName, defaultValue] = match - const value = Object.hasOwn(parsed, variableName) && parsed[variableName] !== "" - ? parsed[variableName] - : defaultValue ?? "" - - return interpolate( - envValue.replace(group, () => value), - parsed - ) +function interpolate( + envValue: string, + parsed: Record, + seen: ReadonlySet +): string { + const reference = /(? 0 ? matches.slice(-1)[0].index : -1 + return result + envValue.slice(cursor) } /** diff --git a/repos/effect/packages/effect/src/Context.ts b/repos/effect/packages/effect/src/Context.ts index 90e6f0d6c0..c943df47f3 100644 --- a/repos/effect/packages/effect/src/Context.ts +++ b/repos/effect/packages/effect/src/Context.ts @@ -813,9 +813,9 @@ export const addUnsafe = ( const impl = self as ContextImpl const cacheRoot = cacheKeys.has(key) ? undefined : impl.cacheRoot if (impl.depth >= MaxDepth) { - // Rebase the overlay chain into a flat map, keeping the cacheRoot so a - // rebase on an ordinary key does not invalidate fiber caches - const map = new Map(impl.mapUnsafe) + // Avoid mapUnsafe: it would flatten the parent before copying. + const map = new Map(impl._flat ?? impl.base) + if (!impl._flat) applyOverlays(map, impl.overlay) map.set(key, service) return makeImpl(cacheRoot, map, undefined, 0) } @@ -1258,6 +1258,15 @@ export const pick = >>( ...services: S ) => (self: Context): Context> => { + if (services.length <= 1) { + const map = new Map() + if (services.length === 1) { + const key = services[0].key + const value = lookup(self, key) + if (value !== notFound) map.set(key, value) + } + return makeUnsafe(map) + } const keep = new Set(services.map((key) => key.key)) return withFlat(self, (map) => map.forEach((_, key) => { diff --git a/repos/effect/packages/effect/src/Crypto.ts b/repos/effect/packages/effect/src/Crypto.ts index 43daf4330f..482c3be067 100644 --- a/repos/effect/packages/effect/src/Crypto.ts +++ b/repos/effect/packages/effect/src/Crypto.ts @@ -66,7 +66,7 @@ export type DigestAlgorithm = "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512" * const program = Effect.gen(function*() { * const crypto = yield* Crypto.Crypto * const bytes = yield* crypto.randomBytes(16) - * const uuidv4 = yield* crypto.randomUUIDv4 + * const uuidv4 = yield* crypto.randomUUIDv4() * const hash = yield* crypto.digest("SHA-256", bytes) * return [bytes.length, uuidv4.length, hash.length] * }) @@ -148,14 +148,42 @@ export interface Crypto { randomShuffle(elements: Iterable): Effect.Effect> /** - * Generates a cryptographically secure UUIDv4 string. + * Generates a cryptographically secure UUIDv4. + * + * **Details** + * + * The default `"hex"` format returns a lowercase, hyphenated UUID string + * (36 characters), not a bare hexadecimal string. The `"bytes"` format + * returns the 16 UUID bytes, including the version and variant bits. */ - readonly randomUUIDv4: Effect.Effect + randomUUIDv4(options?: { + readonly format?: "hex" | undefined + }): Effect.Effect + randomUUIDv4(options: { + readonly format: Format + }): Effect.Effect + randomUUIDv4(options?: { + readonly format?: "hex" | "bytes" | undefined + }): Effect.Effect /** - * Generates a cryptographically secure UUIDv7 string. + * Generates a cryptographically secure UUIDv7 using the `Clock` timestamp. + * + * **Details** + * + * The default `"hex"` format returns a lowercase, hyphenated UUID string + * (36 characters), not a bare hexadecimal string. The `"bytes"` format + * returns the 16 UUID bytes, including the timestamp, version and variant bits. */ - readonly randomUUIDv7: Effect.Effect + randomUUIDv7(options?: { + readonly format?: "hex" | undefined + }): Effect.Effect + randomUUIDv7(options: { + readonly format: Format + }): Effect.Effect + randomUUIDv7(options?: { + readonly format?: "hex" | "bytes" | undefined + }): Effect.Effect /** * Generates a cryptographically secure ULID string. @@ -293,10 +321,16 @@ export const make = ( } return buffer }), - randomUUIDv4: Effect.sync(() => Uuid.v4String(randomBytesUnsafe(16))), - randomUUIDv7: Effect.clockWith((clock) => - Effect.succeed(Uuid.v7String(clock.currentTimeMillisUnsafe(), randomBytesUnsafe(16))) - ), + randomUUIDv4: ((options?: { readonly format?: "hex" | "bytes" | undefined }) => + Effect.sync(() => { + const bytes = Uuid.v4Bytes(randomBytesUnsafe(16)) + return options?.format === "bytes" ? bytes : Uuid.stringify(bytes) + })) as Crypto["randomUUIDv4"], + randomUUIDv7: ((options?: { readonly format?: "hex" | "bytes" | undefined }) => + Effect.clockWith((clock) => { + const bytes = Uuid.v7Bytes(clock.currentTimeMillisUnsafe(), randomBytesUnsafe(16)) + return Effect.succeed(options?.format === "bytes" ? bytes : Uuid.stringify(bytes)) + })) as Crypto["randomUUIDv7"], randomULID: Effect.clockWith((clock) => Effect.succeed(Ulid.ulidString(clock.currentTimeMillisUnsafe(), randomBytesUnsafe(10))) ) diff --git a/repos/effect/packages/effect/src/DateTime.ts b/repos/effect/packages/effect/src/DateTime.ts index 38a7e456a2..b86d4f6a98 100644 --- a/repos/effect/packages/effect/src/DateTime.ts +++ b/repos/effect/packages/effect/src/DateTime.ts @@ -1551,7 +1551,7 @@ export const isPastUnsafe: (self: DateTime) => boolean = Internal.isPastUnsafe * * **Details** * - * This always returns the UTC representation, ignoring any time zone information. + * This preserves the original instant, regardless of any time zone information. * * **Example** (Converting DateTime values to UTC Dates) * @@ -1576,7 +1576,9 @@ export const toDateUtc: (self: DateTime) => Date = Internal.toDateUtc * * **Details** * - * For `DateTime.Zoned`, this adjusts for the time zone before converting. + * For `DateTime.Zoned`, this stores the zoned wall-clock time in the returned + * `Date`'s UTC fields, rather than preserving the original instant. Use + * `toDateUtc` to preserve the instant. * For `DateTime.Utc`, this is equivalent to `toDateUtc`. * * **Example** (Converting DateTime values to Dates) @@ -1584,13 +1586,14 @@ export const toDateUtc: (self: DateTime) => Date = Internal.toDateUtc * ```ts import.meta.vitest * import { DateTime } from "effect" * - * const utc = DateTime.makeUnsafe("2024-01-01T12:00:00Z") - * const zoned = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", { + * const utc = DateTime.makeUnsafe("2024-07-01T12:00:00Z") + * const zoned = DateTime.makeZonedUnsafe("2024-07-01T12:00:00Z", { * timeZone: "Europe/London" * }) * - * DateTime.toDate(utc).toISOString() // => "2024-01-01T12:00:00.000Z" - * DateTime.toDate(zoned).toISOString() // => "2024-01-01T12:00:00.000Z" + * DateTime.toDate(utc).toISOString() // => "2024-07-01T12:00:00.000Z" + * DateTime.toDate(zoned).toISOString() // => "2024-07-01T13:00:00.000Z" + * DateTime.toDateUtc(zoned).toISOString() // => "2024-07-01T12:00:00.000Z" * ``` * * @stability stable diff --git a/repos/effect/packages/effect/src/Duration.ts b/repos/effect/packages/effect/src/Duration.ts index e93556fa93..5d4a3a4026 100644 --- a/repos/effect/packages/effect/src/Duration.ts +++ b/repos/effect/packages/effect/src/Duration.ts @@ -36,10 +36,12 @@ const bigint1e3 = BigInt(1_000) const bigint1e6 = BigInt(1_000_000) const bigint1e9 = BigInt(1_000_000_000) -const roundTiesAwayFromZero = (input: number): bigint => - BigInt(input < 0 ? Math.ceil(input - 0.5) : Math.floor(input + 0.5)) +const roundTiesAwayFromZero = (input: number): bigint => BigInt(Math.sign(input) * Math.round(Math.abs(input))) -const roundMillisToNanos = (millis: number): bigint => roundTiesAwayFromZero(millis * 1_000_000) +const roundMillisToNanos = (millis: number): bigint => + Number.isInteger(millis) ? BigInt(millis) * bigint1e6 : roundTiesAwayFromZero(millis * 1_000_000) + +const fromNanosNumber = (nanos: number): Duration => make(Number.isFinite(nanos) ? roundTiesAwayFromZero(nanos) : nanos) const parseNanos = (input: string, scale: bigint): bigint => { const decimalIndex = input.indexOf(".") @@ -51,9 +53,13 @@ const parseNanos = (input: string, scale: bigint): bigint => { const scaled = ( BigInt(input.slice(isNegative ? 1 : 0, decimalIndex)) * fractionalScale + BigInt(fractional) ) * scale - const rounded = scaled / fractionalScale + - (scaled % fractionalScale * bigint2 >= fractionalScale ? bigint1 : bigint0) - return isNegative ? -rounded : rounded + return divideTiesAwayFromZero(isNegative ? -scaled : scaled, fractionalScale) +} + +const divideTiesAwayFromZero = (numerator: bigint, denominator: bigint): bigint => { + const absolute = numerator < bigint0 ? -numerator : numerator + const rounded = absolute / denominator + (absolute % denominator * bigint2 >= denominator ? bigint1 : bigint0) + return numerator < bigint0 ? -rounded : rounded } const nanosToHrTime = (nanos: bigint): [seconds: number, nanos: number] => { @@ -307,7 +313,7 @@ export const fromInputUnsafe = (input: Input): Duration => { if (input[0] === Infinity || input[1] === Infinity) { return infinity } - return make(roundTiesAwayFromZero(input[0] * 1_000_000_000 + input[1])) + return fromNanosNumber(input[0] * 1_000_000_000 + input[1]) } const obj = input as DurationObject let millis = 0 @@ -319,9 +325,7 @@ export const fromInputUnsafe = (input: Input): Duration => { if (obj.seconds) millis += obj.seconds * 1_000 if (obj.milliseconds) millis += obj.milliseconds if (!obj.microseconds && !obj.nanoseconds) return make(millis) - return make(roundTiesAwayFromZero( - millis * 1_000_000 + (obj.microseconds ?? 0) * 1_000 + (obj.nanoseconds ?? 0) - )) + return fromNanosNumber(millis * 1_000_000 + (obj.microseconds ?? 0) * 1_000 + (obj.nanoseconds ?? 0)) } } return invalid(input) @@ -362,10 +366,8 @@ const DurationProto: Omit = { // Hash equal finite durations using the same canonical nanoseconds // representation used by `equals`. switch (this.value._tag) { - case "Millis": { - const nanos = this.value.millis * 1_000_000 - return Number.isFinite(nanos) ? Hash.hash(roundTiesAwayFromZero(nanos)) : Hash.number(this.value.millis) - } + case "Millis": + return Hash.hash(roundMillisToNanos(this.value.millis)) case "Nanos": return Hash.hash(this.value.nanos) default: @@ -1434,8 +1436,8 @@ export const divideUnsafe: { * * **Details** * - * For nanosecond-backed durations, the multiplier must be convertible to a - * `bigint`; fractional or non-finite multipliers can throw. Infinite + * Fractional multipliers on nanosecond-backed durations round the result to + * the nearest nanosecond, with ties rounding away from zero. Infinite * durations return positive infinity, negative infinity, or zero depending on * the multiplier sign. * @@ -1459,7 +1461,24 @@ export const times: { (self: Duration, times: number): Duration => match(self, { onMillis: (millis) => make(millis * times), - onNanos: (nanos) => make(nanos * BigInt(times)), + onNanos: (nanos) => { + if (Number.isInteger(times)) return make(nanos * BigInt(times)) + const nanosNumber = Number(nanos) + const scaled = nanosNumber * times + if ( + !Number.isFinite(times) || + (Number.isSafeInteger(nanosNumber) && Math.abs(scaled) <= Number.MAX_SAFE_INTEGER) + ) { + return fromNanosNumber(scaled) + } + let numerator = times + let denominator = bigint1 + while (!Number.isInteger(numerator)) { + numerator *= 2 + denominator *= bigint2 + } + return make(divideTiesAwayFromZero(nanos * BigInt(numerator), denominator)) + }, onInfinity: () => times > 0 ? infinity : times < 0 ? negativeInfinity : zero, onNegativeInfinity: () => times > 0 ? negativeInfinity : times < 0 ? infinity : zero }) diff --git a/repos/effect/packages/effect/src/Effect.ts b/repos/effect/packages/effect/src/Effect.ts index ac90f3f94f..94a25e42f1 100644 --- a/repos/effect/packages/effect/src/Effect.ts +++ b/repos/effect/packages/effect/src/Effect.ts @@ -20,7 +20,7 @@ import type * as ExecutionPlan from "./ExecutionPlan.ts" import * as Exit from "./Exit.ts" import type { Fiber } from "./Fiber.ts" import type * as Filter from "./Filter.ts" -import { constant, dual, type LazyArg } from "./Function.ts" +import { dual, type LazyArg } from "./Function.ts" import type { TypeLambda } from "./HKT.ts" import type { Inspectable } from "./Inspectable.ts" import * as core from "./internal/core.ts" @@ -14770,50 +14770,113 @@ export const trackDuration: { // Transactions // ----------------------------------------------------------------------------- +/** + * Why the current transaction attempt started after a previous attempt did not commit. + * + * **Details** + * + * `"retry"` means the previous attempt called {@link txRetry}. `"conflict"` + * means an accessed `TxRef` changed before commit. The first attempt has no + * retry reason. + * + * @stability stable + * @category models + * @since 4.0.0 + */ +export type TransactionRetryReason = "retry" | "conflict" + +/** + * Journal and attempt metadata for an Effect transaction. + * + * **When to use** + * + * Use to type the value provided by {@link Transaction}. + * + * **Details** + * + * `attempt` starts at `1` and counts each run of the outermost transaction body. + * `retryReason` is `"retry"` after {@link txRetry} and `"conflict"` after an + * accessed `TxRef` changes before commit; it is unset on the first attempt. + * `start`, `now`, `elapsed`, and `elapsedSincePrevious` are millisecond + * timestamps and durations for the current attempt, matching {@link Schedule} + * metadata. Each journal entry stores the observed version and value of a + * `TxRef`. `written` is true when this transaction has updated that ref. + * + * @see {@link Transaction} for the context service that provides this metadata + * @see {@link TransactionRetryReason} for the retry-reason tags recorded on later attempts + * + * @stability stable + * @category models + * @since 4.0.0 + */ +export interface TransactionMeta { + readonly journal: ReadonlyMap< + TxRef, + { + readonly version: number + readonly value: any + readonly written: boolean + } + > + readonly attempt: number + readonly retryReason: TransactionRetryReason | undefined + readonly start: number + readonly now: number + readonly elapsed: number + readonly elapsedSincePrevious: number +} + +/** @internal */ +export interface TransactionMetaInner { + retry: boolean + journal: Map< + TxRef, + { + readonly version: number + value: any + written: boolean + } + > + attempt: number + retryReason: TransactionRetryReason | undefined + start: number + now: number + elapsed: number + elapsedSincePrevious: number +} + /** * Service that holds the current transaction state. * * **Details** * - * It includes a journal that stores non-committed changes to `TxRef` values and - * a retry flag that records whether the transaction should be retried. + * Nested {@link tx} calls reuse this same service instance. Yield it inside a + * transaction body to read {@link TransactionMeta} fields such as `attempt` + * and `retryReason`. * - * **Example** (Building transactions) + * **Example** (Reading transaction metadata) * * ```ts import.meta.vitest * import { Effect } from "effect" * - * // Transaction class for software transactional memory operations - * const txEffect = Effect.gen(function*() { + * const program = Effect.tx(Effect.gen(function*() { * const tx = yield* Effect.Transaction - * // Use transaction for coordinated state changes - * return "Transaction complete" - * }) + * return [tx.attempt, tx.retryReason, tx.elapsed, tx.elapsedSincePrevious] + * })) * - * const runnable = Effect.provideService(txEffect, Effect.Transaction, { - * retry: false, - * journal: new Map() - * }) - * Effect.runSync(runnable) // => "Transaction complete" + * Effect.runSync(program) // => [1, undefined, 0, 0] * ``` * + * @see {@link tx} for the outermost transaction boundary that creates this service + * @see {@link TransactionMeta} for the journal and attempt metadata + * * @stability stable * @category transactions * @since 4.0.0 */ export class Transaction extends Context.Service< Transaction, - { - retry: boolean - readonly journal: Map< - TxRef, - { - readonly version: number - value: any - written: boolean - } - > - } + TransactionMeta >()("effect/Effect/Transaction") {} /** @@ -14867,52 +14930,75 @@ export const tx = ( effect: Effect ): Effect> => withFiber((fiber) => { - let state = Context.getOrUndefined(fiber.context, Transaction) + const state = Context.getOrUndefined(fiber.context, Transaction) if (state && !completedTransactions.has(state)) { return effect as Effect> } + const clock = fiber.getRef(internal.ClockRef) + const now = clock.currentTimeMillisUnsafe() // Create transaction state only at the outermost boundary - state = { journal: new Map(), retry: false } + const mutable: TransactionMetaInner = { + journal: new Map(), + retry: false, + attempt: 1, + retryReason: undefined, + start: now, + now, + elapsed: 0, + elapsedSincePrevious: 0 + } let result: Exit.Exit | undefined - return uninterruptibleMask((restore) => - flatMap( + return uninterruptibleMask((restore) => { + const run = restore(effect).pipe( + provideService(Transaction, mutable), + tapCause((cause) => { + if (!mutable.retry) return void_ + // txRetry interrupts the body; any other reason in the cause is a real failure. + // Roll back now so the step below fails instead of waiting or rerunning. + if (!internal.hasInterruptsOnly(cause)) return sync(() => clearTransaction(mutable)) + return restore(awaitPendingTransaction(mutable)) + }), + exit + ) + return flatMap( whileLoop({ while: () => !result, - body: constant( - restore(effect).pipe( - provideService(Transaction, state), - tapCause((cause) => { - if (!state.retry) return void_ - // txRetry interrupts the body; any other reason in the cause is a real failure. - // Roll back now so the step below fails instead of waiting or rerunning. - if (!internal.hasInterruptsOnly(cause)) return sync(() => clearTransaction(state)) - return restore(awaitPendingTransaction(state)) - }), - exit - ) - ), + body: () => { + if (mutable.attempt > 1) { + stampTransaction(mutable, clock.currentTimeMillisUnsafe()) + } + return run + }, step(exit: Exit.Exit) { - if (state.retry || !isTransactionConsistent(state)) { - return clearTransaction(state) + if (mutable.retry || !isTransactionConsistent(mutable)) { + mutable.attempt++ + mutable.retryReason = mutable.retry ? "retry" : "conflict" + return clearTransaction(mutable) } if (Exit.isSuccess(exit)) { - commitTransaction(fiber, state) + commitTransaction(fiber, mutable) } - clearTransaction(state) - completedTransactions.add(state) + clearTransaction(mutable) + completedTransactions.add(mutable) result = exit } }), () => result! ) - ) + }) }) // Child fibers inherit the boundary's state, so mark it completed once the // boundary finishes and let later `tx` calls start a fresh boundary. const completedTransactions = new WeakSet() -const isTransactionConsistent = (state: Transaction["Service"]) => { +const stampTransaction = (state: TransactionMetaInner, now: number) => { + state.elapsedSincePrevious = now - state.now + state.now = now + state.elapsed = now - state.start +} + +const isTransactionConsistent = (state: TransactionMeta) => { for (const [ref, { version }] of state.journal) { if (ref.version !== version) { return false @@ -14921,7 +15007,7 @@ const isTransactionConsistent = (state: Transaction["Service"]) => { return true } -const awaitPendingTransaction = (state: Transaction["Service"]) => +const awaitPendingTransaction = (state: TransactionMeta) => callback((resume) => { // Validate the read set and register the waiter in one synchronous step. // A commit that landed after the reads has already signalled its waiters @@ -14946,7 +15032,7 @@ const awaitPendingTransaction = (state: Transaction["Service"]) => return sync(clearPending) }) -function commitTransaction(fiber: Fiber, state: Transaction["Service"]) { +function commitTransaction(fiber: Fiber, state: TransactionMeta) { for (const [ref, { value, written }] of state.journal) { if (!written) continue if (!Object.is(value, ref.value)) { @@ -14960,7 +15046,7 @@ function commitTransaction(fiber: Fiber, state: Transaction["S } } -function clearTransaction(state: Transaction["Service"]) { +function clearTransaction(state: TransactionMetaInner) { state.retry = false state.journal.clear() } @@ -15005,7 +15091,8 @@ function clearTransaction(state: Transaction["Service"]) { export const txRetry: Effect = flatMap( Transaction, (state) => { - state.retry = true + const mutable = state as TransactionMetaInner + mutable.retry = true return interrupt } ) diff --git a/repos/effect/packages/effect/src/FileSystem.ts b/repos/effect/packages/effect/src/FileSystem.ts index e633dd873d..6ef5241013 100644 --- a/repos/effect/packages/effect/src/FileSystem.ts +++ b/repos/effect/packages/effect/src/FileSystem.ts @@ -220,12 +220,17 @@ export interface FileSystem { * **Details** * * The file handle will be automatically closed when the scope is closed. + * + * `noFollow` rejects symlinks at the final path component, not in parent + * directories. Node and Bun support it on POSIX; unsupported platforms, + * including Windows and Deno, fail with `BadArgument`. */ readonly open: ( path: string, options?: { readonly flag?: OpenFlag | undefined readonly mode?: number | undefined + readonly noFollow?: boolean | undefined } ) => Effect.Effect /** @@ -827,6 +832,10 @@ export const isFile = (u: unknown): u is File => hasProperty(u, FileTypeId) * cursor. Outside append mode, `truncate` clamps a cursor past the new length * to that length. * + * Positional reads leave the cursor unchanged and may run concurrently on + * one handle. Cursor operations (`seek`, reads without a position, and writes) + * must not run concurrently with each other. + * * **Example** (Working with file handles) * * ```ts import.meta.vitest @@ -877,8 +886,20 @@ export interface File { */ readonly seek: (offset: bigint, from: SeekMode) => Effect.Effect readonly sync: Effect.Effect - readonly read: (buffer: Uint8Array) => Effect.Effect - readonly readAlloc: (size: number) => Effect.Effect, PlatformError> + /** + * Reads into `buffer`, returning the byte count or `0` at EOF. Advances the + * cursor unless `options.position` is set (see `File.ReadOptions`). + */ + readonly read: (buffer: Uint8Array, options?: File.ReadOptions) => Effect.Effect + /** + * Reads up to `size` bytes into a new buffer, returning `Option.none()` at + * EOF. Advances the cursor unless `options.position` is set (see + * `File.ReadOptions`). + */ + readonly readAlloc: ( + size: number, + options?: File.ReadOptions + ) => Effect.Effect, PlatformError> readonly truncate: (length?: number) => Effect.Effect readonly write: (buffer: Uint8Array) => Effect.Effect readonly writeAll: (buffer: Uint8Array) => Effect.Effect @@ -892,6 +913,31 @@ export interface File { * @since 4.0.0 */ export declare namespace File { + /** + * Options for `File.read` and `File.readAlloc`. + * + * **Details** + * + * `position` is a byte offset from the start of the file. It leaves the + * cursor unchanged, fails with `BadArgument` if negative, and reads nothing + * at or past EOF. + * + * **Example** (Reading a byte range without moving the cursor) + * + * ```ts import.meta.vitest + * import type { FileSystem } from "effect" + * + * const options: FileSystem.File.ReadOptions = { position: BigInt(1024) } + * options.position // => 1024n + * ``` + * + * @category models + * @since 4.1.0 + */ + export interface ReadOptions { + readonly position?: bigint | undefined + } + /** * Enumeration of possible file system entry types. * @@ -922,9 +968,17 @@ export declare namespace File { * permissions, and size information. This structure is returned by file * stat operations. * - * Node and Bun preserve `size` and `blksize` exactly. Optional `number` - * metadata is `Option.none()` when absent or outside the safe integer range. - * Unsafe `dev` or `mode` values fail the stat operation with `BadArgument`. + * `dev`, `ino`, `rdev`, `nlink`, and `blocks` are `bigint` values, so + * 64-bit device identifiers, inode numbers, and counts are not limited to + * the safe integer range. `mode`, `uid`, and `gid` are 32-bit values and + * remain `number`. Optional metadata is `Option.none()` only when the + * platform does not report it. + * + * Node and Bun report all fields exactly, with `dev`, `ino`, `rdev`, and + * `nlink` interpreted as unsigned 64-bit integers. Unsafe `mode` values fail + * the stat operation with `BadArgument`. Deno reports these fields as + * `number`, so on Deno values above `Number.MAX_SAFE_INTEGER` are already + * rounded before they are converted to `bigint`. * * **Example** (Inspecting file information) * @@ -936,7 +990,7 @@ export declare namespace File { * mtime: Option.none(), * atime: Option.none(), * birthtime: Option.none(), - * dev: 1, + * dev: 1n, * ino: Option.none(), * mode: 0o644, * nlink: Option.none(), @@ -968,16 +1022,16 @@ export declare namespace File { readonly mtime: Option.Option readonly atime: Option.Option readonly birthtime: Option.Option - readonly dev: number - readonly ino: Option.Option + readonly dev: bigint + readonly ino: Option.Option readonly mode: number - readonly nlink: Option.Option + readonly nlink: Option.Option readonly uid: Option.Option readonly gid: Option.Option - readonly rdev: Option.Option + readonly rdev: Option.Option readonly size: ByteSize.ByteSize readonly blksize: Option.Option - readonly blocks: Option.Option + readonly blocks: Option.Option } } @@ -1015,6 +1069,12 @@ export interface WatchOptions { * When `true`, changes in subdirectories are also reported. */ readonly recursive?: boolean | undefined + /** + * Called once the underlying watcher is installed and can buffer events. + * Stream construction alone does not install a watcher. Custom watch + * backends must also call this callback after installation, when supplied. + */ + readonly onReady?: (() => void) | undefined } /** diff --git a/repos/effect/packages/effect/src/Match.ts b/repos/effect/packages/effect/src/Match.ts index 4cd1646190..8dd3b5f5e0 100644 --- a/repos/effect/packages/effect/src/Match.ts +++ b/repos/effect/packages/effect/src/Match.ts @@ -569,6 +569,26 @@ export const withReturnType: () => [Ret] extends [[A] extends [never] ? any : A] ? Matcher : "withReturnType constraint does not extend Result type" = internal.withReturnType +// `P` is a const type parameter, so object literals skip excess-property checks. +// Reject pattern keys that no object variant of the input has. Functions, +// refinements, and array patterns are not checked. +type PatternKey = K extends number ? `${K}` : K + +type PatternKeys = object extends A ? PropertyKey + : A extends object ? PatternKey + : never + +type ObjectPatternGuard = [P] extends [Function | ReadonlyArray | SafeRefinement] ? unknown + : [P] extends [object] ? { readonly [K in Exclude, PatternKeys>]: never } + : unknown + +type ExactPattern = (Types.PatternPrimitive | Types.PatternBase) & ObjectPatternGuard + +type ExactPatterns = { + readonly [I in keyof P]: I extends number | `${number}` ? P[I] & ExactPattern + : P[I] +} + /** * Defines a condition for matching values. * @@ -620,7 +640,7 @@ export const withReturnType: () => | Types.PatternBase, + const P extends ExactPattern, Ret, Args extends Array, Fn extends (_: Types.WhenMatch, ...args: Args) => Ret @@ -688,7 +708,7 @@ export const whenOr: < Args extends Array, Fn extends (_: Types.WhenMatch, ...args: Args) => Ret >( - ...args: [...patterns: P, f: Fn] + ...args: [...patterns: ExactPatterns, f: Fn] ) => ( self: Matcher ) => Matcher< @@ -699,7 +719,13 @@ export const whenOr: < Pr, Ret, Args -> = internal.whenOr +> = < + R, + const P extends ReadonlyArray | Types.PatternBase>, + Ret, + Args extends Array, + Fn extends (_: Types.WhenMatch, ...args: Args) => Ret +>(...args: [...patterns: ExactPatterns, f: Fn]) => internal.whenOr(...args) /** * Matches a value that satisfies all provided patterns. @@ -747,7 +773,7 @@ export const whenAnd: < Args extends Array, Fn extends (_: Types.WhenMatch>, ...args: Args) => Ret >( - ...args: [...patterns: P, f: Fn] + ...args: [...patterns: ExactPatterns, f: Fn] ) => ( self: Matcher ) => Matcher< @@ -758,7 +784,13 @@ export const whenAnd: < Pr, Ret, Args -> = internal.whenAnd +> = < + R, + const P extends ReadonlyArray | Types.PatternBase>, + Ret, + Args extends Array, + Fn extends (_: Types.WhenMatch>, ...args: Args) => Ret +>(...args: [...patterns: ExactPatterns, f: Fn]) => internal.whenAnd(...args) /** * Matches values based on a specified discriminant field. @@ -1255,7 +1287,7 @@ export const tagsExhaustive: < */ export const not: < R, - const P extends Types.PatternPrimitive | Types.PatternBase, + const P extends ExactPattern, Ret, Args extends Array, Fn extends (_: Types.NotMatch, ...args: Args) => Ret @@ -2692,6 +2724,32 @@ export declare namespace Types { type Simplify = { [K in keyof A]: A[K] } & {} + // Tuple patterns match a prefix at runtime. For inputs with a variadic part, + // narrow each position the pattern requires and keep the rest of the input. + type NarrowArrayPattern, P extends ReadonlyArray> = number extends I["length"] + ? number extends P["length"] ? MapArrayPattern + : P["length"] extends Required

["length"] ? NarrowArrayPrefix + : MapArrayPattern + : MapArrayPattern + + type MapArrayPattern = { + readonly [K in keyof I]: K extends keyof P ? ExtractAndNarrow : I[K] + } extends infer R ? Fail extends R[keyof R] ? never + : R + : never + + type NarrowArrayPrefix< + I extends ReadonlyArray, + P extends ReadonlyArray, + Out extends ReadonlyArray = readonly [] + > = P extends readonly [infer PH, ...infer PT] ? + I extends readonly [infer IH, ...infer IT] ? + [ExtractAndNarrow] extends [infer N] ? [N] extends [never] ? never + : NarrowArrayPrefix + : never + : NarrowArrayPrefix], P, Out> + : readonly [...Out, ...I] + type ExtractAndNarrow = P extends Predicate.Refinement ? _Out extends Input ? Extract<_Out, Input> : Extract : @@ -2700,12 +2758,7 @@ export declare namespace Types { : Extract : P extends Predicate.Predicate ? Extract : Input extends infer I ? Exclude< - I extends ReadonlyArray ? P extends ReadonlyArray ? { - readonly [K in keyof I]: K extends keyof P ? ExtractAndNarrow - : I[K] - } extends infer R ? Fail extends R[keyof R] ? never - : R - : never + I extends ReadonlyArray ? P extends ReadonlyArray ? NarrowArrayPattern : never : IsPlainObject extends true ? string extends keyof I ? I extends P ? I : never diff --git a/repos/effect/packages/effect/src/Path.ts b/repos/effect/packages/effect/src/Path.ts index aca7dfc35b..61438f46a7 100644 --- a/repos/effect/packages/effect/src/Path.ts +++ b/repos/effect/packages/effect/src/Path.ts @@ -14,6 +14,7 @@ import * as Context from "./Context.ts" import * as Effect from "./Effect.ts" import { identity } from "./Function.ts" import * as Layer from "./Layer.ts" +import * as Option from "./Option.ts" import { BadArgument } from "./PlatformError.ts" /** @@ -47,10 +48,17 @@ export const TypeId = "~effect/Path" * formatting, and converting file system paths. URL conversion methods return * `Effect`s because invalid file URLs or paths can fail with `BadArgument`. * + * `resolveWithin(root, input)` resolves a relative `input` beneath `root` and + * returns `Option.none()` when the result would leave the root or when `input` + * has its own root (an absolute path, or a Windows drive or UNC prefix). The + * root itself is allowed. The check is lexical: it does not follow symlinks, + * so it is not a sandbox on its own. A relative `root` is resolved against the + * current working directory, as with `resolve`. + * * **Example** (Using path operations) * * ```ts import.meta.vitest - * import { Effect, Path } from "effect" + * import { Effect, Option, Path } from "effect" * * const program = Effect.gen(function*() { * const path = yield* Path.Path @@ -64,7 +72,8 @@ export const TypeId = "~effect/Path" * isAbsolute: path.isAbsolute("/absolute/path"), * name: path.parse("/path/to/file.txt").name, * relative: path.relative("/from/path", "/to/path"), - * resolved: path.resolve("/base", "relative", "path") + * resolved: path.resolve("/base", "relative", "path"), + * within: path.resolveWithin("/base", "../outside") * } * }) * @@ -78,6 +87,7 @@ export const TypeId = "~effect/Path" * result.name // => "file" * result.relative // => "../../to/path" * result.resolved // => "/base/relative/path" + * result.within // => Option.none() * ``` * * @stability unstable @@ -98,6 +108,7 @@ export interface Path { readonly parse: (path: string) => Path.Parsed readonly relative: (from: string, to: string) => string readonly resolve: (...pathSegments: ReadonlyArray) => string + readonly resolveWithin: (root: string, input: string) => Option.Option readonly toFileUrl: (path: string) => Effect.Effect readonly toNamespacedPath: (path: string) => string } @@ -204,8 +215,7 @@ export declare namespace Path { * import { Effect, Layer, Path } from "effect" * * // Create a custom path implementation - * const customPath: Path.Path = { - * [Path.TypeId]: Path.TypeId, + * const customPath = Path.make({ * sep: "/", * basename: (path: string, suffix?: string) => { * const base = path.split("/").pop() || "" @@ -239,7 +249,7 @@ export declare namespace Path { * resolve: (...pathSegments: ReadonlyArray) => pathSegments.join("/"), * toFileUrl: (path: string) => Effect.succeed(new URL(`file://${path}`)), * toNamespacedPath: (path: string) => path - * } + * }) * * // Provide the path service * const customPathLayer = Layer.succeed(Path.Path)(customPath) @@ -259,6 +269,42 @@ export declare namespace Path { */ export const Path: Context.Service = Context.Service("effect/Path") +/** + * Creates a `Path` service from platform path operations. + * + * **When to use** + * + * Use to build a `Path` implementation, such as a platform layer or a test + * double, without implementing the operations that can be derived from the + * others. + * + * **Details** + * + * Adds the `Path` type marker and derives `resolveWithin` from the provided + * `parse`, `resolve`, `relative`, `isAbsolute`, and `sep`, so containment + * follows the same platform rules as those operations. + * + * @see {@link layer} for the built-in POSIX `Path` service layer + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const make = (impl: Omit): Path => + Path.of({ + ...impl, + [TypeId]: TypeId, + resolveWithin(root, input) { + if (impl.parse(input).root !== "") return Option.none() + const base = impl.resolve(root) + const candidate = impl.resolve(base, input) + const relative = impl.relative(base, candidate) + return relative === ".." || relative.startsWith(`..${impl.sep}`) || impl.isAbsolute(relative) + ? Option.none() + : Option.some(candidate) + } + }) + /** * The following functions are adapted from the Node.js source code: * https://github.com/nodejs/node/blob/main/lib/internal/url.js @@ -479,8 +525,7 @@ function encodePathChars(filepath: string) { return filepath } -const posixImpl = Path.of({ - [TypeId]: TypeId, +const posixImpl = make({ resolve, normalize(path) { if (path.length === 0) return "." diff --git a/repos/effect/packages/effect/src/RequestResolver.ts b/repos/effect/packages/effect/src/RequestResolver.ts index 5df4843a8a..32d6d22ad5 100644 --- a/repos/effect/packages/effect/src/RequestResolver.ts +++ b/repos/effect/packages/effect/src/RequestResolver.ts @@ -311,16 +311,10 @@ export const makeGrouped = (options: { }) const hashGroupKey = (get: (entry: Request.Entry) => K) => { - const groupKeys = MutableHashMap.empty() - return (entry: Request.Entry): unknown => { - const key = get(entry) - const okey = MutableHashMap.get(groupKeys, key) - if (okey._tag === "Some") { - return okey.value - } - MutableHashMap.set(groupKeys, key, key) - return key - } + // Pending batches match equal keys, so they share one batch. + const batchKey = (entry: Request.Entry): unknown => get(entry) + internal.equalBatchKeys.add(batchKey) + return batchKey } /** diff --git a/repos/effect/packages/effect/src/Scheduler.ts b/repos/effect/packages/effect/src/Scheduler.ts index 816b270844..9331d063f8 100644 --- a/repos/effect/packages/effect/src/Scheduler.ts +++ b/repos/effect/packages/effect/src/Scheduler.ts @@ -160,6 +160,15 @@ class PriorityBuckets { * operation counts to decide when fibers should yield, and is the default * scheduler implementation. * + * **Gotchas** + * + * On Cloudflare Workers, request-owned scheduler timers can be discarded, + * leaving shared fibers suspended. Use `new MixedScheduler("sync")` for the + * whole application; see `HttpRouter.toWebHandler` for a recipe. + * Sync mode does not yield to the event loop: CPU-heavy work delays other + * requests, and I/O-polling loops can exhaust the CPU limit. It does not fix + * request-owned timers (such as `Effect.sleep`) or request-bound async contexts. + * * @stability stable * @category models * @since 2.0.0 diff --git a/repos/effect/packages/effect/src/Schema.ts b/repos/effect/packages/effect/src/Schema.ts index 1c4a323ad8..bfef2b661d 100644 --- a/repos/effect/packages/effect/src/Schema.ts +++ b/repos/effect/packages/effect/src/Schema.ts @@ -36,7 +36,9 @@ import * as HashMap_ from "./HashMap.ts" import * as HashSet_ from "./HashSet.ts" import * as Cookies_ from "./http/Cookies.ts" import * as Headers_ from "./http/Headers.ts" +import * as UrlParams_internal from "./http/internal/urlParams.ts" import * as UrlParams_ from "./http/UrlParams.ts" +import { NodeInspectSymbol } from "./Inspectable.ts" import * as core from "./internal/core.ts" import { effectIsExit } from "./internal/effect.ts" import * as InternalGraph from "./internal/graph.ts" @@ -56,6 +58,8 @@ import { isSchemaError as isSchemaErrorInternal, SchemaErrorTypeId } from "./int import { getStackTraceLimit, setStackTraceLimit } from "./internal/stackTraceLimit.ts" import type * as JsonPatch from "./JsonPatch.ts" import type * as JsonSchema from "./JsonSchema.ts" +import * as Dns_ from "./net/Dns.ts" +import * as Host_ from "./net/Host.ts" import * as IpInterface_ from "./net/IpInterface.ts" import * as IpNetwork_ from "./net/IpNetwork.ts" import * as NetAddress_ from "./net/NetAddress.ts" @@ -1217,6 +1221,15 @@ export class SchemaError extends Data.TaggedError("SchemaError")<{ override get message() { return SchemaIssue.defaultFormatter(this.issue) } + override toJSON() { + return { + _tag: this._tag, + message: this.message + } + } + override [NodeInspectSymbol]() { + return this.toJSON() + } override toString() { return `SchemaError(${this.message})` } @@ -4017,6 +4030,7 @@ export declare namespace StructWithRest { */ type Objects = Constraint & { readonly ast: SchemaAST.Objects + readonly Encoded: object } /** * Readonly list of record schemas that provide the additional index signatures @@ -4186,6 +4200,13 @@ export interface StructWithRest< * * **Gotchas** * + * The base schema must have an object-shaped encoded type. Whole-object + * transformations are not supported, even with an empty rest array. Apply + * transformations such as `Schema.fromJsonString` to the completed + * `StructWithRest` schema instead. Object-shaped encoded types alone do not + * guarantee compatibility: unsupported encodings are still rejected at runtime. + * Transformations on individual fields remain supported. + * * TypeScript index signatures also apply to fixed keys. `StructWithRest` does * not reject incompatible fixed fields at the call site; use * `StructWithRest.ValidateRecords` when you want an explicit type-level @@ -5946,6 +5967,9 @@ export type DecodingDefaultOptions = { function toIssueEffect( self: Effect.Effect ): Effect.Effect { + if (effectIsExit(self) && self._tag === "Success") { + return self as unknown as Exit_.Exit + } return Effect.catchCause(self, (cause) => Effect.failCauseSync(() => Cause_.map(cause, (error) => error.issue))) } /** @@ -6292,6 +6316,12 @@ type Flatten = Schemas extends readonly [infer Head, ...infer Tail] ? Head extends Union ? [...Flatten, ...Flatten] : [Head, ...Flatten] : [] +type DiscriminantKey = T extends number ? `${T}` : T +type EnsureUniqueDiscriminants, Seen = never> = Tags extends + readonly [infer Head extends PropertyKey, ...infer Tail extends ReadonlyArray] + ? [DiscriminantKey & Seen] extends [never] ? EnsureUniqueDiscriminants> + : never + : unknown type MatchCasesResult = { [K in keyof Cases]-?: NonNullable extends (...args: Array) => infer R ? R : never }[keyof Cases] @@ -6376,7 +6406,10 @@ export type toTaggedUnion< * * **Gotchas** * - * Throws if multiple members use the same discriminant property key. + * Rejects overlapping discriminant types in known member tuples at compile + * time, including nested unions. Numeric and string values such as `1` and + * `"1"` count as duplicates. Also throws at runtime if multiple members use the + * same discriminant property key. * * **Example** (Adding tagged-union utilities to an existing union) * @@ -6403,7 +6436,7 @@ export type toTaggedUnion< */ export function toTaggedUnion(tag: Tag) { return >( - self: Union + self: Union & NoInfer["discriminants"]>> ): toTaggedUnion => { const cases: Record = {} const discriminants: Array = [] @@ -7877,7 +7910,8 @@ export function isMultipleOf( * * JSON Schema: * - * This check corresponds to the `type: "integer"` constraint in JSON Schema. + * This check corresponds to `type: "integer"` with `minimum: Number.MIN_SAFE_INTEGER` + * and `maximum: Number.MAX_SAFE_INTEGER` in JSON Schema. * * Arbitrary: * @@ -7896,7 +7930,11 @@ export function isInt(annotations?: Annotations.Filter) { id: "effect/schema/isInt", payload: null }, - toJsonSchema: () => [{ type: "integer" }, true], + toJsonSchema: () => ({ + type: "integer", + minimum: globalThis.Number.MIN_SAFE_INTEGER, + maximum: globalThis.Number.MAX_SAFE_INTEGER + }), toCode: () => ({ runtime: "Schema.isInt()" }), arbitraryConstraint: { number: "integer" @@ -11978,10 +12016,10 @@ export const DateTimeZonedFromString: DateTimeZonedFromString = DateTimeZonedStr decodeTo(DateTimeZoned, dateTimeZonedFromString) ) -const netAddressFromString = , E extends { readonly message: string }>( +const netAddressFromString = ( declaration: S, - parse: (input: string) => Result_.Result, - encode: (value: S["Type"]) => string, + parse: (input: string) => Result_.Result, + encode: (value: S["Encoded"]) => string, identifier: string ) => String.pipe(decodeTo( @@ -13332,6 +13370,229 @@ export const SocketAddress: SocketAddress = declare(NetAddress_.isSocketAddress, identifier: "SocketAddress" }) +/** + * Type-level representation of {@link DomainName}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DomainName extends brand { + readonly "Rebuild": DomainName +} + +/** + * Schema for normalized DNS domain names. + * + * **Details** + * + * Only names already in normalized form (lowercase ASCII, with + * internationalized labels in `xn--` form) are accepted. Use + * {@link DomainNameFromString} to normalize arbitrary input. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DomainName: DomainName = String.check( + makeFilter(Host_.isDomainName, { expected: "a normalized domain name" }) +).pipe(brand("~effect/net/Host/DomainName")).annotate({ identifier: "DomainName" }) + +/** + * Type-level representation of {@link DomainNameFromString}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DomainNameFromString extends decodeTo { + readonly "Rebuild": DomainNameFromString +} + +/** + * Schema for DNS domain names decoded from strings, normalizing case and + * converting internationalized names to their ASCII form. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DomainNameFromString: DomainNameFromString = netAddressFromString( + DomainName, + Host_.domainNameFromString, + (name) => name, + "DomainNameFromString" +) + +/** + * Type-level representation of {@link ScopedIpv6Literal}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface ScopedIpv6Literal extends brand { + readonly "Rebuild": ScopedIpv6Literal +} + +/** + * Schema for canonical scoped IPv6 literals such as `fe80::1%eth0`. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const ScopedIpv6Literal: ScopedIpv6Literal = String.check( + makeFilter(NetAddress_.isScopedIpv6Literal, { expected: "a canonical scoped IPv6 literal" }) +).pipe(brand("~effect/net/NetAddress/ScopedIpv6Literal")).annotate({ identifier: "ScopedIpv6Literal" }) + +/** + * Type-level representation of {@link ScopedIpv6LiteralFromString}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface ScopedIpv6LiteralFromString extends decodeTo { + readonly "Rebuild": ScopedIpv6LiteralFromString +} + +/** + * Schema for scoped IPv6 literals decoded from strings, normalizing the address + * and numeric zones. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const ScopedIpv6LiteralFromString: ScopedIpv6LiteralFromString = netAddressFromString( + ScopedIpv6Literal, + NetAddress_.scopedIpv6LiteralFromString, + (literal) => literal, + "ScopedIpv6LiteralFromString" +) + +/** + * Type-level representation of {@link Host}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Host extends Union { + readonly "Rebuild": Host +} + +/** + * Schema for hosts: numeric IP addresses, scoped IPv6 literals, or domain names. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const Host: Host = Union([IpAddress, ScopedIpv6Literal, DomainName]).annotate({ identifier: "Host" }) + +/** + * Type-level representation of {@link HostFromString}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface HostFromString + extends Union +{ + readonly "Rebuild": HostFromString +} + +/** + * Schema for hosts decoded from strings. Numeric IP strings decode to IP + * addresses; other strings decode to scoped IPv6 literals or domain names. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const HostFromString: HostFromString = Union([ + IpAddressFromString, + ScopedIpv6LiteralFromString, + DomainNameFromString +]).annotate({ identifier: "HostFromString" }) + +/** + * Type-level representation of {@link HostPort}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface HostPort extends declare { + readonly "Rebuild": HostPort +} + +/** + * Schema for already-constructed unresolved host and port values. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const HostPort: HostPort = declare(Host_.isHostPort, { + identifier: "HostPort" +}) + +/** + * Type-level representation of {@link HostPortFromString}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface HostPortFromString extends decodeTo { + readonly "Rebuild": HostPortFromString +} + +/** + * Schema for unresolved endpoints encoded as `host:port` or `[IPv6]:port` + * strings. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const HostPortFromString: HostPortFromString = netAddressFromString( + HostPort, + Host_.hostPortFromString, + Host_.formatHostPort, + "HostPortFromString" +) + +/** + * Type-level representation of {@link Port}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Port extends Int { + readonly "Rebuild": Port +} + +/** + * Schema for TCP and UDP port numbers from 0 through 65535. + * + * **Details** + * + * Port 0 is accepted because it asks the operating system to choose a port + * when binding, and it matches the port range of `InetAddress` and `HostPort`. + * `Config.Port` accepts only 1 through 65535. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const Port: Port = Int.check(isBetween({ minimum: 0, maximum: 65535 }, { expected: "a port number" })) + // ----------------------------------------------------------------------------- // Duration schemas // ----------------------------------------------------------------------------- @@ -13549,6 +13810,426 @@ export const DurationFromMillis: DurationFromMillis = Number.pipe( decodeTo(Duration, durationFromMillis) ) +// ----------------------------------------------------------------------------- +// DNS schemas +// ----------------------------------------------------------------------------- + +/** + * Type-level representation of {@link DnsRecordType}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsRecordType extends Literals> {} + +/** + * Schema for supported DNS record types such as `"A"` or `"SRV"`. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsRecordType: DnsRecordType = Literals(Dns_.recordTypes) + +// Addresses in JSON records must already be canonical; normalizing input is +// left to the `*FromString` schemas. +const dnsCanonicalAddress = ( + schema: Codec, + parse: (input: string) => Result_.Result +) => + String.pipe(decodeTo( + schema, + SchemaTransformation.transformEffect({ + decode: (input, options) => { + const result = parse(input) + if (Result_.isFailure(result)) { + return Effect.fail(new SchemaIssue.InvalidValue({ message: result.failure.message }, input, options)) + } + return NetAddress_.formatIp(result.success) === input + ? Effect.succeed(result.success) + : Effect.fail(new SchemaIssue.InvalidValue({ message: "expected a canonical address" }, input, options)) + }, + encode: (address) => Effect.succeed(NetAddress_.formatIp(address)) + }) + )) + +const dnsUint8 = Int.check(isBetween({ minimum: 0, maximum: 0xff })) + +const dnsUint16 = Int.check(isBetween({ minimum: 0, maximum: 0xffff })) + +const dnsUint32 = Int.check(isBetween({ minimum: 0, maximum: 0xffffffff })) + +// SOA timers are written as whole seconds, as in zone files. +const dnsSeconds = dnsUint32.pipe(decodeTo( + Duration, + SchemaTransformation.transform({ decode: Duration_.seconds, encode: Duration_.toSeconds }) +)) + +// Each record type is an opaque value whose JSON form is a plain object tagged +// by record type, such as `{ "_tag": "MX", "exchange": "mail.example.com", "priority": 10 }`. +const dnsRecordOfType = ( + type: T, + fields: { readonly [K in keyof Dns_.RecordFields]-?: Codec[K], unknown> } +) => + declare((u): u is Dns_.RecordFor => Dns_.isDnsRecord(u) && u._tag === type, { + identifier: `Dns${type.charAt(0)}${type.slice(1).toLowerCase()}Record`, + toCodecJson: () => { + const json = TaggedStruct(type, fields) + return link>()( + json, + SchemaTransformation.transformEffect({ + decode: (input, options) => { + const { _tag, ...rest } = input as { readonly _tag: T } + const result = Dns_.makeRecord(type, rest as Dns_.RecordFields) + return Result_.isSuccess(result) + ? Effect.succeed(result.success) + : Effect.fail(new SchemaIssue.InvalidValue({ message: result.failure.message }, input, options)) + }, + // Records hold only their tag and fields as own properties. + encode: (record) => Effect.succeed({ ...record } as unknown as typeof json["Type"]) + }) + ) + } + }) + +/** + * Type-level representation of {@link DnsARecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsARecord extends declare { + readonly "Rebuild": DnsARecord +} + +/** + * Schema for already-constructed IPv4 address (`A`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsARecord: DnsARecord = dnsRecordOfType("A", { + address: dnsCanonicalAddress(Ipv4Address, NetAddress_.ipv4FromString) +}) + +/** + * Type-level representation of {@link DnsAaaaRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsAaaaRecord extends declare { + readonly "Rebuild": DnsAaaaRecord +} + +/** + * Schema for already-constructed IPv6 address (`AAAA`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsAaaaRecord: DnsAaaaRecord = dnsRecordOfType("AAAA", { + address: dnsCanonicalAddress(Ipv6Address, NetAddress_.ipv6FromString) +}) + +/** + * Type-level representation of {@link DnsCaaRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsCaaRecord extends declare { + readonly "Rebuild": DnsCaaRecord +} + +/** + * Schema for already-constructed certification authority authorization (`CAA`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsCaaRecord: DnsCaaRecord = dnsRecordOfType("CAA", { + critical: Boolean, + tag: String.check(isPattern(/^[a-z0-9]+$/i)), + value: String +}) + +/** + * Type-level representation of {@link DnsCnameRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsCnameRecord extends declare { + readonly "Rebuild": DnsCnameRecord +} + +/** + * Schema for already-constructed canonical name (`CNAME`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsCnameRecord: DnsCnameRecord = dnsRecordOfType("CNAME", { target: DomainName }) + +/** + * Type-level representation of {@link DnsMxRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsMxRecord extends declare { + readonly "Rebuild": DnsMxRecord +} + +/** + * Schema for already-constructed mail exchange (`MX`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsMxRecord: DnsMxRecord = dnsRecordOfType("MX", { exchange: DomainName, priority: dnsUint16 }) + +/** + * Type-level representation of {@link DnsNaptrRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsNaptrRecord extends declare { + readonly "Rebuild": DnsNaptrRecord +} + +/** + * Schema for already-constructed naming authority pointer (`NAPTR`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsNaptrRecord: DnsNaptrRecord = dnsRecordOfType("NAPTR", { + order: dnsUint16, + preference: dnsUint16, + flags: String, + service: String, + regexp: String, + replacement: DomainName +}) + +/** + * Type-level representation of {@link DnsNsRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsNsRecord extends declare { + readonly "Rebuild": DnsNsRecord +} + +/** + * Schema for already-constructed name server (`NS`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsNsRecord: DnsNsRecord = dnsRecordOfType("NS", { host: DomainName }) + +/** + * Type-level representation of {@link DnsPtrRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsPtrRecord extends declare { + readonly "Rebuild": DnsPtrRecord +} + +/** + * Schema for already-constructed pointer (`PTR`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsPtrRecord: DnsPtrRecord = dnsRecordOfType("PTR", { host: NonEmptyString }) + +/** + * Type-level representation of {@link DnsSoaRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsSoaRecord extends declare { + readonly "Rebuild": DnsSoaRecord +} + +/** + * Schema for already-constructed start of authority (`SOA`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsSoaRecord: DnsSoaRecord = dnsRecordOfType("SOA", { + primary: DomainName, + admin: NonEmptyString, + serial: dnsUint32, + refresh: dnsSeconds, + retry: dnsSeconds, + expire: dnsSeconds, + minimum: dnsSeconds +}) + +/** + * Type-level representation of {@link DnsSrvRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsSrvRecord extends declare { + readonly "Rebuild": DnsSrvRecord +} + +/** + * Schema for already-constructed service locator (`SRV`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsSrvRecord: DnsSrvRecord = dnsRecordOfType("SRV", { + target: DomainName, + port: dnsUint16, + priority: dnsUint16, + weight: dnsUint16 +}) + +/** + * Type-level representation of {@link DnsTlsaRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsTlsaRecord extends declare { + readonly "Rebuild": DnsTlsaRecord +} + +/** + * Schema for already-constructed TLS authentication (`TLSA`) DNS records. + * + * **Details** + * + * The default JSON serializer encodes the certificate association `data` as a + * hex string. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsTlsaRecord: DnsTlsaRecord = dnsRecordOfType("TLSA", { + certUsage: dnsUint8, + selector: dnsUint8, + matchingType: dnsUint8, + data: Uint8ArrayFromHex +}) + +/** + * Type-level representation of {@link DnsTxtRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsTxtRecord extends declare { + readonly "Rebuild": DnsTxtRecord +} + +/** + * Schema for already-constructed text (`TXT`) DNS records. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsTxtRecord: DnsTxtRecord = dnsRecordOfType("TXT", { chunks: NonEmptyArray(String) }) + +/** + * Type-level representation of {@link DnsRecord}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DnsRecord extends + Union< + readonly [ + DnsARecord, + DnsAaaaRecord, + DnsCaaRecord, + DnsCnameRecord, + DnsMxRecord, + DnsNaptrRecord, + DnsNsRecord, + DnsPtrRecord, + DnsSoaRecord, + DnsSrvRecord, + DnsTlsaRecord, + DnsTxtRecord + ] + > +{ + readonly "Rebuild": DnsRecord +} + +/** + * Schema for already-constructed DNS records of any supported record type. + * + * **Details** + * + * The default JSON serializer encodes records as objects tagged by record type, + * with addresses and names as canonical strings, SOA timers as whole seconds, + * and TLSA data as hex, such as + * `{ "_tag": "SRV", "target": "db.internal", "port": 5432, "priority": 10, "weight": 5 }`. + * Decoding accepts only canonical addresses and normalized domain names, and + * reports invalid fields with their path. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const DnsRecord: DnsRecord = Union([ + DnsARecord, + DnsAaaaRecord, + DnsCaaRecord, + DnsCnameRecord, + DnsMxRecord, + DnsNaptrRecord, + DnsNsRecord, + DnsPtrRecord, + DnsSoaRecord, + DnsSrvRecord, + DnsTlsaRecord, + DnsTxtRecord +]).annotate({ identifier: "DnsRecord" }) + // ----------------------------------------------------------------------------- // Exit schemas // ----------------------------------------------------------------------------- @@ -14553,9 +15234,9 @@ export const UrlParams: UrlParams = declare( toCodec: () => link()( ArraySchema(Tuple([String, String])), - SchemaTransformation.transform({ + SchemaTransformation.transform>({ decode: UrlParams_.make, - encode: (self) => self.params + encode: (self) => self.params.map(([key, value]) => [key, UrlParams_internal.unwrap(value)]) }) ) } @@ -15141,6 +15822,10 @@ export interface Class { .map((part) => (Arr.isCanonicalArrayIndex(part) ? globalThis.Number(part) : part)) } +const MAX_ARRAY_HOLES = 20 + /** * Builds a nested tree object from a list of bracket-path entries. * @@ -2120,6 +2122,10 @@ function bracketPathToTokens(bracketPath: string): Array { * - `""` → real empty key * - Numeric bracket segments become array indices only when they are valid * JavaScript array-index strings; otherwise they remain object keys. + * - An indexed container becomes an array only when it has at most 20 holes + * (missing indices below its highest index). Otherwise it is returned as an + * object keyed by the index strings, so untrusted input such as + * `a[4294967294]` cannot produce huge sparse arrays. * - Duplicate keys for the same path are merged into arrays. * - If a structural path conflicts with a previous leaf or a different container * type, the later structural path replaces the conflicting value. @@ -2152,43 +2158,31 @@ export function makeTreeRecord( const out: any = {} const containers = new WeakSet() const duplicates = new WeakSet() - - function getOrCreateContainer(self: any, key: PropertyKey, shouldBeArray: boolean): any { - const current = Object.hasOwn(self, key) ? self[key] : undefined - if (containers.has(current) && Array.isArray(current) === shouldBeArray) { - return current - } - const container = shouldBeArray ? [] : {} - containers.add(container) - InternalRecord.assignProperty(self, key, container) - return container - } + // Indexed containers are built as plain objects so that large indices never + // allocate sparse arrays, and are materialized once all entries are applied + const indexed = new Map() bracketPathEntries.forEach(([key, value]) => { const tokens = bracketPathToTokens(key) let cur: any = out - tokens.forEach((token, i) => { - const isLast = i === tokens.length - 1 - - // We are inside an array and see "[]" (empty token) => append - if (Array.isArray(cur) && token === "") { - if (isLast) { - cur.push(value) - } else { - // bracket path: "foo[][bar]" => push a new element and descend into it - const next = tokens[i + 1] - const shouldBeArray = typeof next === "number" || next === "" - const index = cur.length - cur = getOrCreateContainer(cur, index, shouldBeArray) - } - } else if (isLast) { - // If we're setting a value at a path that already exists - // convert it to an array to support multiple values for the same key - const hasOwn = Object.hasOwn(cur, token) - if (hasOwn && Array.isArray(cur[token]) && (containers.has(cur[token]) || duplicates.has(cur[token]))) { - cur[token].push(value) + for (let i = 0; i < tokens.length; i++) { + const state = indexed.get(cur) + // Resolve "[]" to the next index before handling leaves or containers + const token = tokens[i] === "" && state !== undefined ? state.length : tokens[i] + if (state !== undefined && typeof token === "number") { + state.length = Math.max(state.length, token + 1) + } + const hasOwn = Object.hasOwn(cur, token) + const current = hasOwn ? cur[token] : undefined + + if (i === tokens.length - 1) { + const currentState = indexed.get(current) + if (currentState !== undefined) { + InternalRecord.assignProperty(current, currentState.length++, value) + } else if (duplicates.has(current)) { + current.push(value) } else if (hasOwn) { - const values = [cur[token], value] + const values = [current, value] duplicates.add(values) InternalRecord.assignProperty(cur, token, values) } else { @@ -2196,12 +2190,30 @@ export function makeTreeRecord( } } else { const next = tokens[i + 1] - // if next is a number OR "" (from []), we are building an array const shouldBeArray = typeof next === "number" || next === "" - cur = getOrCreateContainer(cur, token, shouldBeArray) + if (containers.has(current) && indexed.has(current) === shouldBeArray) { + cur = current + } else { + const container = {} + containers.add(container) + if (shouldBeArray) { + indexed.set(container, { parent: cur, key: token, length: 0 }) + } + InternalRecord.assignProperty(cur, token, container) + cur = container + } } - }) + } }) + + // Children are created after their parents, so materializing in reverse + // creation order replaces every nested container before its parent is copied + for (const [builder, { key, length, parent }] of Array.from(indexed).reverse()) { + // A later conflicting path may have replaced the container in its parent + if (parent[key] === builder && length - Object.keys(builder).length <= MAX_ARRAY_HOLES) { + InternalRecord.assignProperty(parent, key, Object.assign(new Array(length), builder)) + } + } return out } diff --git a/repos/effect/packages/effect/src/Sink.ts b/repos/effect/packages/effect/src/Sink.ts index 0074c1290b..138e26d8ee 100644 --- a/repos/effect/packages/effect/src/Sink.ts +++ b/repos/effect/packages/effect/src/Sink.ts @@ -1825,13 +1825,24 @@ export const takeWhileFilterEffect = ( * @since 4.0.0 */ export const takeUntil = (predicate: Predicate): Sink, In, In> => - suspend(() => { - let done = false - return takeWhile((i) => { - if (done) return false - done = predicate(i) - return true - }) + fromTransform((upstream) => { + const out = Arr.empty() + return upstream.pipe( + Effect.flatMap((arr) => { + for (let i = 0; i < arr.length; i++) { + out.push(arr[i]) + if (predicate(arr[i])) { + const leftover: NonEmptyReadonlyArray | undefined = (i + 1) < arr.length + ? arr.slice(i + 1) as Arr.NonEmptyArray + : undefined + return Cause.done([out, leftover] as const) + } + } + return Effect.void + }), + Effect.forever({ disableYield: true }), + Pull.catchDone((end) => Effect.succeed, In>>(end ?? [out])) + ) }) /** @@ -1849,17 +1860,33 @@ export const takeUntil = (predicate: Predicate): Sink, In, In> export const takeUntilEffect = ( predicate: (input: In) => Effect.Effect ): Sink, In, In, E, R> => - suspend(() => { - let done = false - return takeWhileEffect((input) => { - if (done) { - return Effect.succeed(false) - } - return Effect.map(predicate(input), (b) => { - done = b - return true - }) - }) + fromTransform((upstream) => { + const out = Arr.empty() + let leftover: NonEmptyReadonlyArray | undefined = undefined + return upstream.pipe( + Effect.flatMap((arr) => { + let i = 0 + return Effect.whileLoop({ + while: () => i < arr.length, + body: () => { + const input = arr[i++] + return Effect.flatMap(predicate(input), (matched) => { + out.push(input) + if (!matched) { + return Effect.void + } + if (i < arr.length) { + leftover = arr.slice(i) as Arr.NonEmptyArray + } + return Cause.done() + }) + }, + step: constVoid + }) + }), + Effect.forever({ disableYield: true }), + Pull.catchDone(() => Effect.succeed([out, leftover] as const)) + ) }) /** diff --git a/repos/effect/packages/effect/src/Stdio.ts b/repos/effect/packages/effect/src/Stdio.ts index 858e533eab..448339061f 100644 --- a/repos/effect/packages/effect/src/Stdio.ts +++ b/repos/effect/packages/effect/src/Stdio.ts @@ -79,6 +79,12 @@ export interface Stdio { * @since 4.0.0 */ readonly stdoutIsTerminal: Effect.Effect + /** + * Whether standard error is attached to a terminal. + * + * @since 4.0.0 + */ + readonly stderrIsTerminal: Effect.Effect stdout(options?: { readonly endOnDone?: boolean | undefined }): Sink.Sink @@ -127,12 +133,13 @@ export const Stdio: Context.Service = Context.Service(TypeI */ export const make = ( options: - & Omit - & Partial> + & Omit + & Partial> ): Stdio => ({ [TypeId]: TypeId, stdinIsTerminal: Effect.succeed(false), stdoutIsTerminal: Effect.succeed(false), + stderrIsTerminal: Effect.succeed(false), ...options }) diff --git a/repos/effect/packages/effect/src/Stream.ts b/repos/effect/packages/effect/src/Stream.ts index a6d1bcdce9..e102f5f57d 100644 --- a/repos/effect/packages/effect/src/Stream.ts +++ b/repos/effect/packages/effect/src/Stream.ts @@ -11542,6 +11542,9 @@ export const mkUint8Array = (self: Stream): Effect.Effec * * See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream. * + * When `signal` aborts, the stream is interrupted even if the reader has + * stopped pulling, and the `ReadableStream` closes. + * * **Example** (Converting to a ReadableStream with services) * * ```ts import.meta.vitest @@ -11549,7 +11552,7 @@ export const mkUint8Array = (self: Stream): Effect.Effec * * const stream = Stream.make(1, 2, 3, 4, 5) * const readableStream = Stream.toReadableStreamWith(stream, Context.empty()) - * const values = await Array.fromAsync(readableStream) + * const values = await globalThis.Array.fromAsync(readableStream) * values // => [ 1, 2, 3, 4, 5 ] * ``` * @@ -11560,23 +11563,36 @@ export const mkUint8Array = (self: Stream): Effect.Effec export const toReadableStreamWith: { ( context: Context.Context, - options?: { readonly strategy?: QueuingStrategy | undefined } + options?: { + readonly strategy?: QueuingStrategy | undefined + readonly signal?: AbortSignal | undefined + } ): (self: Stream) => ReadableStream ( self: Stream, context: Context.Context, - options?: { readonly strategy?: QueuingStrategy | undefined } + options?: { + readonly strategy?: QueuingStrategy | undefined + readonly signal?: AbortSignal | undefined + } ): ReadableStream } = dual( (args) => isStream(args[0]), ( self: Stream, context: Context.Context, - options?: { readonly strategy?: QueuingStrategy | undefined } + options?: { + readonly strategy?: QueuingStrategy | undefined + readonly signal?: AbortSignal | undefined + } ): ReadableStream => { let currentResolve: (() => void) | undefined = undefined let fiber: Fiber.Fiber | undefined = undefined + let cancelled = false const latch = Latch.makeUnsafe(false) + const signal = options?.signal + // Interrupting the fiber directly also stops a consumer waiting for a pull. + const onAbort = () => fiber!.interruptUnsafe() return new ReadableStream({ start(controller) { @@ -11593,12 +11609,18 @@ export const toReadableStreamWith: { context )) fiber.addObserver((exit) => { - if (exit._tag === "Failure") { + signal?.removeEventListener("abort", onAbort) + if (cancelled) return + if (exit._tag === "Failure" && signal?.aborted !== true) { controller.error(Cause.squash(exit.cause)) } else { controller.close() } }) + if (signal !== undefined && fiber.pollUnsafe() === undefined) { + if (signal.aborted) onAbort() + else signal.addEventListener("abort", onAbort, { once: true }) + } }, pull() { return new Promise((resolve) => { @@ -11608,6 +11630,7 @@ export const toReadableStreamWith: { }, cancel() { if (!fiber) return + cancelled = true return Effect.runPromise(Effect.asVoid(Fiber.interrupt(fiber))) } }, options?.strategy) @@ -11627,7 +11650,7 @@ export const toReadableStreamWith: { * import { Stream } from "effect" * * const readableStream = Stream.toReadableStream(Stream.make(1, 2, 3)) - * const values = await Array.fromAsync(readableStream) + * const values = await globalThis.Array.fromAsync(readableStream) * values // => [ 1, 2, 3 ] * ``` * @@ -11722,7 +11745,7 @@ export const toReadableStreamEffect: { * const stream = Stream.make(1, 2, 3) * const iterable = Stream.toAsyncIterableWith(stream, Context.empty()) * - * await Array.fromAsync(iterable) // => [1, 2, 3] + * await globalThis.Array.fromAsync(iterable) // => [1, 2, 3] * ``` * * @stability stable @@ -11829,7 +11852,7 @@ export const toAsyncIterableWith: { * * const program = Effect.gen(function*() { * const iterable = yield* Stream.toAsyncIterableEffect(stream) - * return yield* Effect.promise(() => Array.fromAsync(iterable)) + * return yield* Effect.promise(() => globalThis.Array.fromAsync(iterable)) * }) * * await Effect.runPromise(program) // => [1, 2, 3] @@ -11855,7 +11878,7 @@ export const toAsyncIterableEffect = (self: Stream): Effect.Ef * * const stream = Stream.make(1, 2, 3) * - * await Array.fromAsync(Stream.toAsyncIterable(stream)) // => [1, 2, 3] + * await globalThis.Array.fromAsync(Stream.toAsyncIterable(stream)) // => [1, 2, 3] * ``` * * @stability stable diff --git a/repos/effect/packages/effect/src/String.ts b/repos/effect/packages/effect/src/String.ts index 2391f1797d..b4bb0117fd 100644 --- a/repos/effect/packages/effect/src/String.ts +++ b/repos/effect/packages/effect/src/String.ts @@ -1079,6 +1079,12 @@ export const stripMargin = (self: string): string => stripMarginWith(self, "|") /** * Converts a snake_case string to camelCase. * + * **Details** + * + * Keeps the first character, then replaces each later underscore and the + * character after it with that character uppercased. A trailing underscore is + * dropped. Input made only of an even number of underscores returns `""`. + * * **Example** (Converting snake_case to camelCase) * * ```ts import.meta.vitest @@ -1093,10 +1099,10 @@ export const stripMargin = (self: string): string => stripMarginWith(self, "|") * @since 2.0.0 */ export const snakeToCamel = (self: string): string => { - if (self.length === 0) return self + if (self.length === 0 || (self.length % 2 === 0 && self[0] === "_" && /^_+$/.test(self))) return "" let str = self[0] for (let i = 1; i < self.length; i++) { - str += self[i] === "_" ? self[++i].toUpperCase() : self[i] + str += self[i] === "_" ? self.charAt(++i).toUpperCase() : self[i] } return str } @@ -1104,6 +1110,12 @@ export const snakeToCamel = (self: string): string => { /** * Converts a snake_case string to PascalCase. * + * **Details** + * + * Uppercases the first character, then replaces each later underscore and the + * character after it with that character uppercased. A trailing underscore is + * dropped. Input made only of an even number of underscores returns `""`. + * * **Example** (Converting snake_case to PascalCase) * * ```ts import.meta.vitest @@ -1118,10 +1130,10 @@ export const snakeToCamel = (self: string): string => { * @since 2.0.0 */ export const snakeToPascal = (self: string): string => { - if (self.length === 0) return self + if (self.length === 0 || (self.length % 2 === 0 && self[0] === "_" && /^_+$/.test(self))) return "" let str = self[0].toUpperCase() for (let i = 1; i < self.length; i++) { - str += self[i] === "_" ? self[++i].toUpperCase() : self[i] + str += self[i] === "_" ? self.charAt(++i).toUpperCase() : self[i] } return str } @@ -1334,6 +1346,7 @@ const normalizeCase = ( while (result.charAt(end - 1) === "\0") { end-- } + if (start >= end) return "" // Transform each token independently. return result.slice(start, end).split("\0").map(transform).join(delimiter) diff --git a/repos/effect/packages/effect/src/TxRef.ts b/repos/effect/packages/effect/src/TxRef.ts index 7f9b4c44ee..2819ff57f2 100644 --- a/repos/effect/packages/effect/src/TxRef.ts +++ b/repos/effect/packages/effect/src/TxRef.ts @@ -13,6 +13,7 @@ * @since 4.0.0 */ import * as Effect from "./Effect.ts" +import type { TransactionMetaInner } from "./Effect.ts" import { dual } from "./Function.ts" import { pipeArguments } from "./Pipeable.ts" import type { Pipeable } from "./Pipeable.ts" @@ -140,10 +141,11 @@ export const makeUnsafe = (initial: A): TxRef => ({ }) const journalEntry = (state: Effect.Transaction["Service"], self: TxRef) => { - let entry = state.journal.get(self) + const journal = (state as TransactionMetaInner).journal + let entry = journal.get(self) if (entry === undefined) { entry = { version: self.version, value: self.value, written: false } - state.journal.set(self, entry) + journal.set(self, entry) } return entry } diff --git a/repos/effect/packages/effect/src/Utils.ts b/repos/effect/packages/effect/src/Utils.ts index d35eff6c30..e9dd6d0c8b 100644 --- a/repos/effect/packages/effect/src/Utils.ts +++ b/repos/effect/packages/effect/src/Utils.ts @@ -12,7 +12,7 @@ * @since 2.0.0 */ import type { Kind, TypeLambda } from "./HKT.ts" -import { getStackTraceLimit } from "./internal/stackTraceLimit.ts" +import { getStackTraceLimit, setStackTraceLimit } from "./internal/stackTraceLimit.ts" import type * as Types from "./Types.ts" /** @@ -209,10 +209,13 @@ const pickInternalCall = (): (body: () => A) => A => { } } - const isNotOptimizedAway = getStackTraceLimit() !== 0 && - standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true - - return isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId] + const limit = getStackTraceLimit() + if (limit === 0) return forced[InternalTypeId] + // Only the callback and internal call frames are needed for detection. + setStackTraceLimit(2) + const error = standard[InternalTypeId](() => new Error()) + setStackTraceLimit(limit) + return error.stack?.includes(InternalTypeId) === true ? standard[InternalTypeId] : forced[InternalTypeId] } /** @internal */ diff --git a/repos/effect/packages/effect/src/ai/AiError.ts b/repos/effect/packages/effect/src/ai/AiError.ts index 495e10beb7..8fbe890871 100644 --- a/repos/effect/packages/effect/src/ai/AiError.ts +++ b/repos/effect/packages/effect/src/ai/AiError.ts @@ -47,7 +47,9 @@ import * as Schema from "../Schema.ts" export const HttpRequestDetails = Schema.Struct({ method: Schema.Literals(["GET", "POST", "PATCH", "PUT", "DELETE", "HEAD", "OPTIONS", "TRACE", "QUERY"]), url: Schema.String, - urlParams: Schema.Array(Schema.Tuple([Schema.String, Schema.String])), + urlParams: Schema.Array( + Schema.Tuple([Schema.String, Schema.Union([Schema.String, Schema.Redacted(Schema.String)])]) + ), hash: Schema.optional(Schema.String), headers: Schema.Record( Schema.String, diff --git a/repos/effect/packages/effect/src/ai/AnthropicStructuredOutput.ts b/repos/effect/packages/effect/src/ai/AnthropicStructuredOutput.ts index e945865261..ff4aeff076 100644 --- a/repos/effect/packages/effect/src/ai/AnthropicStructuredOutput.ts +++ b/repos/effect/packages/effect/src/ai/AnthropicStructuredOutput.ts @@ -14,8 +14,8 @@ import type * as JsonSchema from "../JsonSchema.ts" import * as Rec from "../Record.ts" import * as Schema from "../Schema.ts" import * as InternalStructuredOutput from "./internal/structured-output.ts" -import * as LanguageModel from "./LanguageModel.ts" -import * as OpenAiStructuredOutput from "./OpenAiStructuredOutput.ts" +import type * as LanguageModel from "./LanguageModel.ts" +import type * as OpenAiStructuredOutput from "./OpenAiStructuredOutput.ts" /** * Converts a `Schema.Codec` to Anthropic structured-output JSON Schema and a diff --git a/repos/effect/packages/effect/src/ai/Chat.ts b/repos/effect/packages/effect/src/ai/Chat.ts index f8c25ac362..a68b1e37f4 100644 --- a/repos/effect/packages/effect/src/ai/Chat.ts +++ b/repos/effect/packages/effect/src/ai/Chat.ts @@ -228,7 +228,7 @@ export interface Chat { , Options>>( options: Options & { readonly toolkit?: undefined } & LanguageModel.GenerateTextOptions<{}> ): Effect.Effect< - LanguageModel.GenerateTextResponse<{}>, + LanguageModel.GenerateTextResponse<{}, LanguageModel.ExtractToolParametersModeWithoutToolkit>, LanguageModel.ExtractError, LanguageModel.LanguageModel | LanguageModel.ExtractServices > @@ -310,7 +310,7 @@ export interface Chat { , Options>>( options: Options & { readonly toolkit?: undefined } & LanguageModel.GenerateTextOptions<{}> ): Stream.Stream< - Response.StreamPart<{}>, + Response.StreamPart<{}, LanguageModel.ExtractToolParametersModeWithoutToolkit>, LanguageModel.ExtractError, LanguageModel.LanguageModel | LanguageModel.ExtractServices > diff --git a/repos/effect/packages/effect/src/ai/Decision.ts b/repos/effect/packages/effect/src/ai/Decision.ts index 0fb98663c3..1775bd80bf 100644 --- a/repos/effect/packages/effect/src/ai/Decision.ts +++ b/repos/effect/packages/effect/src/ai/Decision.ts @@ -28,9 +28,23 @@ export type TypeId = "~effect/ai/Decision" */ export const TypeId: TypeId = "~effect/ai/Decision" +/** + * Decision instructions or descriptions: a string, JSON object, or JSON array. + * + * **Details** + * + * TypeScript interfaces lack the index signature required by `Schema.JsonObject`; + * use object literals, type aliases, or Schema types instead. + * + * @stability unstable + * @category models + * @since 4.0.5 + */ +export type Description = string | Schema.JsonObject | Schema.JsonArray + /** * Decision that assigns the input one label out of a set of criteria. - * `criteria` maps labels to descriptions. + * `criteria` maps labels to descriptions; use `null` for a label without a description. * * @see {@link classify} for the constructor * @see {@link ClassifyAnswer} for the answer produced by this decision @@ -41,13 +55,14 @@ export const TypeId: TypeId = "~effect/ai/Decision" */ export interface Classify(self: Flag, description: string): Flag } = dual(2, (self: Flag, description: string) => Param.withDescription(self, description)) +/** + * Lets a flag be given without a value, in which case `value` is used. + * + * **Details** + * + * Follows GNU-style optional values, like `--color[=WHEN]`. An explicit value + * must be attached with `=` (`--watch=until-done` or `-w=until-done`). A bare + * `--watch` is parsed as `--watch=`, so `value` is validated like any + * other input. The flag never consumes the next token, so in `--watch build`, + * `build` stays a positional argument or subcommand. The flag is still + * required unless it is made optional or given a default. + * + * **Example** (Flag with an optional value) + * + * ```ts import.meta.vitest + * import { Flag } from "effect/cli" + * + * const watch = Flag.Literals("watch", ["first-failure", "until-done"]).pipe( + * Flag.withOptionalValue("first-failure"), + * Flag.optional + * ) + * // --watch => Option.some("first-failure") + * // --watch=until-done => Option.some("until-done") + * // (absent) => Option.none() + * // In help: --watch [=choice] + * watch.kind // => "flag" + * ``` + * + * @stability unstable + * @category combinators + * @since 4.1.0 + */ +export const withOptionalValue: { + (value: string): (self: Flag) => Flag + (self: Flag, value: string): Flag +} = dual(2, (self: Flag, value: string) => Param.withOptionalValue(self, value)) + // ------------------------------------------------------------------------------------- // metadata // ------------------------------------------------------------------------------------- diff --git a/repos/effect/packages/effect/src/cli/GlobalFlag.ts b/repos/effect/packages/effect/src/cli/GlobalFlag.ts index 348e208159..f1d8f44801 100644 --- a/repos/effect/packages/effect/src/cli/GlobalFlag.ts +++ b/repos/effect/packages/effect/src/cli/GlobalFlag.ts @@ -224,21 +224,29 @@ export const Wizard: Action = Action({ * * **Details** * - * Accepted values are `bash`, `zsh`, `fish`, and `sh`; `sh` is normalized to - * `bash`. + * Accepted values are `bash`, `zsh`, `fish`, `powershell`, `sh`, and `pwsh`; + * `sh` is normalized to `bash` and `pwsh` to `powershell`. * * @stability unstable * @category references * @since 4.0.0 */ -export const Completions: Action> = Action({ - flag: Flag.Literals("completions", ["bash", "zsh", "fish", "sh"] as const) - .pipe( - Flag.optional, - Flag.map((v) => Option.map(v, (s) => s === "sh" ? "bash" : s)), - Flag.withMetavar(""), - Flag.withDescription("Print shell completion script") - ), +export const Completions: Action> = Action({ + flag: Flag.ChoiceWithValue( + "completions", + [ + ["bash", "bash"], + ["zsh", "zsh"], + ["fish", "fish"], + ["powershell", "powershell"], + ["sh", "bash"], + ["pwsh", "powershell"] + ] as const + ).pipe( + Flag.optional, + Flag.withMetavar(""), + Flag.withDescription("Print shell completion script") + ), run: Effect.fnUntraced(function*(shell, { command }) { if (Option.isNone(shell)) return const descriptor = CommandDescriptor.fromCommand(command) @@ -317,7 +325,7 @@ export const BuiltIns: readonly [ Action, Action, Action, - Action>, + Action>, Setting<"log-level", Option.Option> ] = [Help, Version, Wizard, Completions, LogLevel] diff --git a/repos/effect/packages/effect/src/cli/Param.ts b/repos/effect/packages/effect/src/cli/Param.ts index 96bf81bba4..5fcc31e2f4 100644 --- a/repos/effect/packages/effect/src/cli/Param.ts +++ b/repos/effect/packages/effect/src/cli/Param.ts @@ -213,6 +213,10 @@ export interface Single extends Param { readonly primitiveType: Primitive.Primitive readonly typeName?: string | undefined readonly hidden: boolean + /** + * Raw value used for a bare flag. See `withOptionalValue`. + */ + readonly optionalValue?: string | undefined } /** @@ -362,6 +366,7 @@ export const makeSingle = (params: { readonly description?: Option.Option | undefined readonly aliases?: ReadonlyArray | undefined readonly hidden?: boolean | undefined + readonly optionalValue?: string | undefined }): Single => { const parse: Parse = (args) => params.kind === argumentKind @@ -1823,6 +1828,45 @@ export const withMetavar: { typeName: metavar }))) +/** + * Lets a flag be given without a value, in which case `value` is used. + * + * **Details** + * + * Follows GNU-style optional values. An explicit value must be attached with + * `=` (`--watch=until-done`), and a bare `--watch` is parsed as + * `--watch=`. The flag never consumes the next token. It is still + * required unless it is made optional or given a default. + * + * **Example** (Flag with an optional value) + * + * ```ts import.meta.vitest + * import { Param } from "effect/cli" + * + * const watch = Param.String(Param.flagKind, "watch").pipe( + * Param.withOptionalValue("first-failure"), + * Param.optional + * ) + * watch.kind // => "flag" + * ``` + * + * @stability unstable + * @category combinators + * @since 4.1.0 + */ +export const withOptionalValue: { + (value: string): (self: Param) => Param + (self: Param, value: string): Param +} = dual(2, ( + self: Param, + value: string +) => + transformSingle(self, (single) => + makeSingle({ + ...single, + optionalValue: value + }))) + /** * Validates parsed values against a Schema, providing detailed error messages. * diff --git a/repos/effect/packages/effect/src/cli/Prompt.ts b/repos/effect/packages/effect/src/cli/Prompt.ts index c6fba52d4b..79b18a4c46 100644 --- a/repos/effect/packages/effect/src/cli/Prompt.ts +++ b/repos/effect/packages/effect/src/cli/Prompt.ts @@ -26,6 +26,7 @@ import * as Path from "../Path.ts" import * as Predicate from "../Predicate.ts" import * as Queue from "../Queue.ts" import * as Redacted from "../Redacted.ts" +import type * as Scope from "../Scope.ts" import * as Terminal from "../Terminal.ts" import type { Covariant } from "../Types.ts" import * as Ansi from "./internal/ansi.ts" @@ -203,6 +204,11 @@ export interface Theme { readonly errorColor: string /** The color used for submitted values. */ readonly submittedColor: string + /** + * Whether prompts and the command wizard emit color and style escapes. + * Cursor movement and redraw controls are always emitted. + */ + readonly colors: boolean } /** @@ -620,7 +626,7 @@ export interface ToggleOptions extends ThemeOptions { readonly inactive?: string } -const defaultTheme: Theme = { +const defaultTheme: Omit = { prefix: "?", arrowUp: "↑", arrowDown: "↓", @@ -640,7 +646,7 @@ const defaultTheme: Theme = { submittedColor: Ansi.white } -const windowsTheme: Theme = { +const windowsTheme: Omit = { ...defaultTheme, checkboxOn: "[*]", checkboxOff: "[ ]", @@ -653,13 +659,19 @@ const windowsTheme: Theme = { /** * Creates a prompt theme using the current platform defaults. * + * **Details** + * + * Unless `colors` is provided, it is detected when the theme is created: + * colors are enabled when stdout is a TTY and `NO_COLOR` is unset or empty. + * * @stability unstable * @category constructors * @since 4.0.0 */ export const makeTheme = (options?: Partial): Theme => ({ ...(process.platform === "win32" ? windowsTheme : defaultTheme), - ...options + ...options, + colors: options?.colors ?? Ansi.detectColors() }) /** @@ -668,7 +680,13 @@ export const makeTheme = (options?: Partial): Theme => ({ * **Details** * * Provide this reference once to theme every prompt in an application. A - * prompt's `theme` option takes precedence over the context value. + * prompt's `theme` option takes precedence over the context value. The + * command wizard also reads `colors` from this reference, so provide a theme + * with `colors: false` to disable wizard styling. + * + * The default value is created with `makeTheme` the first time it is read, + * so color detection runs once per process. Changes to `NO_COLOR` after the + * first prompt do not affect the default theme. * * @stability unstable * @category services @@ -832,11 +850,10 @@ export const all: < return allTupled(arguments[0]) as any } -const annotateLine = (line: string): string => Ansi.annotate(line, Ansi.bold) -const annotateErrorLine = (line: string, color: string): string => - Ansi.annotate(line, Ansi.combine(Ansi.italicized, color)) -const annotateSymbol = (symbol: string, ...styles: Array>): string => - symbol.length === 0 ? "" : Ansi.annotate(symbol, ...styles) +const annotateErrorLine = (theme: Theme, line: string): string => + Ansi.annotate(theme.colors, line, Ansi.combine(Ansi.italicized, theme.errorColor)) +const annotateSymbol = (theme: Theme, symbol: string, ...styles: Array>): string => + symbol.length === 0 ? "" : Ansi.annotate(theme.colors, symbol, ...styles) const separateSymbol = (symbol: string, text: string): string => symbol.length === 0 ? text : symbol + " " + text const renderPagingPrefix = (theme: Theme, showArrowUp: boolean, showArrowDown: boolean): string => { const width = Math.max(theme.arrowUp.length, theme.arrowDown.length) @@ -1240,7 +1257,7 @@ export const run: ( > = Effect.fnUntraced( function*(self: Prompt) { const terminal = yield* Terminal.Terminal - const input = yield* terminal.readInput + const input = yield* Effect.cached(terminal.readInput) return yield* runWithInput(self, terminal, input) }, Effect.mapError(() => new Terminal.QuitError({})), @@ -1505,13 +1522,13 @@ const allTupled = >>(arg: T): Prompt< const runWithInput = ( prompt: Prompt, terminal: Terminal.Terminal, - input: Queue.Dequeue -): Effect.Effect => + input: Terminal.Terminal["readInput"] +): Effect.Effect => Effect.suspend(() => { const op = prompt as PromptPrimitive switch (op._tag) { case "Loop": { - return runLoop(op, terminal, input) + return Effect.flatMap(input, (queue) => runLoop(op, terminal, queue)) } case "OnSuccess": { return Effect.flatMap( @@ -1625,48 +1642,36 @@ const handleConfirmClear = (options: ConfirmOptionsReq) => { const confirmMessage = state.value ? options.placeholder.defaultConfirm! : options.placeholder.defaultDeny! - const promptText = renderConfirmOutput( - confirmMessage, - figures.prefix, - figures.pointerSmall, - options, - { plain: true } - ) + const promptText = renderPrompt(confirmMessage, options.message, figures.prefix, figures.pointerSmall, figures, { + plain: true + }) const clearOutput = eraseText(promptText, columns) const resetCurrentLine = Ansi.eraseLine + Ansi.cursorLeft return clearOutput + resetCurrentLine }) } -const renderConfirmOutput = ( - confirm: string, - leadingSymbol: string, - trailingSymbol: string, - options: ConfirmOptionsReq, - renderOptions?: RenderOptions | undefined -) => renderPrompt(confirm, options.message, leadingSymbol, trailingSymbol, renderOptions) - const renderConfirmNextFrame = Effect.fnUntraced(function*(state: ConfirmState, options: ConfirmOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) // Marking these explicitly as present with `!` because they always will be // and there is really no value in adding a `DeepRequired` type helper just // for these internal cases const confirmMessage = state.value ? options.placeholder.defaultConfirm! : options.placeholder.defaultDeny! - const confirm = Ansi.annotate(confirmMessage, figures.mutedColor) - const promptMsg = renderConfirmOutput(confirm, leadingSymbol, trailingSymbol, options) + const confirm = Ansi.annotate(figures.colors, confirmMessage, figures.mutedColor) + const promptMsg = renderPrompt(confirm, options.message, leadingSymbol, trailingSymbol, figures) return Ansi.cursorHide + promptMsg }) const renderConfirmSubmission = Effect.fnUntraced(function*(value: boolean, options: ConfirmOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) const confirmMessage = value ? options.label.confirm : options.label.deny - const promptMsg = renderConfirmOutput(confirmMessage, leadingSymbol, trailingSymbol, options) + const promptMsg = renderPrompt(confirmMessage, options.message, leadingSymbol, trailingSymbol, figures) return promptMsg + "\n" }) @@ -1714,7 +1719,9 @@ const handleDateClear = (options: DateOptionsReq) => { const figures = yield* getTheme(options) const resetCurrentLine = Ansi.eraseLine + Ansi.cursorLeft const parts = Arr.reduce(state.dateParts, "", (doc, part) => doc + part.toString()) - const promptText = renderDateOutput(figures.prefix, figures.pointerSmall, parts, options, { plain: true }) + const promptText = renderPrompt(parts, options.message, figures.prefix, figures.pointerSmall, figures, { + plain: true + }) const errorText = Option.isSome(state.error) ? Arr.match(state.error.value.split(NEWLINE_REGEXP), { onEmpty: () => "", @@ -1730,8 +1737,8 @@ const renderDateError = (state: DateState, pointer: string, theme: Theme): strin if (Option.isSome(state.error)) { const errorLines = state.error.value.split(NEWLINE_REGEXP) if (Arr.isReadonlyArrayNonEmpty(errorLines)) { - const prefix = annotateSymbol(pointer, theme.errorColor) - const lines = Arr.map(errorLines, (str) => annotateErrorLine(str, theme.errorColor)) + const prefix = annotateSymbol(theme, pointer, theme.errorColor) + const lines = Arr.map(errorLines, (str) => annotateErrorLine(theme, str)) return Ansi.cursorSavePosition + "\n" + separateSymbol(prefix, lines.join("\n")) + Ansi.cursorRestorePosition } } @@ -1746,37 +1753,29 @@ const renderParts = (state: DateState, theme: Theme, submitted: boolean = false) const partDoc = part.toString() if (currentIndex === state.cursor && !submitted) { const annotation = Ansi.combine(Ansi.underlined, theme.primaryColor) - return doc + Ansi.annotate(partDoc, annotation) + return doc + Ansi.annotate(theme.colors, partDoc, annotation) } return doc + partDoc } ) } -const renderDateOutput = ( - leadingSymbol: string, - trailingSymbol: string, - parts: string, - options: DateOptionsReq, - renderOptions?: RenderOptions | undefined -) => renderPrompt(parts, options.message, leadingSymbol, trailingSymbol, renderOptions) - const renderDateNextFrame = Effect.fnUntraced(function*(state: DateState, options: DateOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) const parts = renderParts(state, figures) - const promptMsg = renderDateOutput(leadingSymbol, trailingSymbol, parts, options) + const promptMsg = renderPrompt(parts, options.message, leadingSymbol, trailingSymbol, figures) const errorMsg = renderDateError(state, figures.pointerSmall, figures) return Ansi.cursorHide + promptMsg + errorMsg }) const renderDateSubmission = Effect.fnUntraced(function*(state: DateState, options: DateOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) const parts = renderParts(state, figures, true) - const promptMsg = renderDateOutput(leadingSymbol, trailingSymbol, parts, options) + const promptMsg = renderPrompt(parts, options.message, leadingSymbol, trailingSymbol, figures) return promptMsg + "\n" }) @@ -2364,12 +2363,13 @@ const handleFileClear = (options: FileOptionsReq) => { const resolvedPathText = separateSymbol(figures.pointerSmall, resolvedPath) const isConfirming = showConfirmation(state.confirm) const promptText = isConfirming - ? renderPrompt("(Y/n)", CONFIRM_MESSAGE, figures.prefix, figures.pointerSmall, { plain: true }) + ? renderPrompt("(Y/n)", CONFIRM_MESSAGE, figures.prefix, figures.pointerSmall, figures, { plain: true }) : renderPrompt( renderFileFilter(state, figures, { plain: true }), options.message, figures.tick, figures.ellipsis, + figures, { plain: true } @@ -2395,6 +2395,7 @@ const renderPrompt = ( message: string, leadingSymbol: string, trailingSymbol: string, + theme: Theme, options?: RenderOptions | undefined ) => { const prefix = leadingSymbol.length === 0 ? "" : leadingSymbol + " " @@ -2410,13 +2411,12 @@ const renderPrompt = ( } return output } - const annotate = options?.plain === true - ? (line: string) => line - : annotateLine return Arr.match(message.split(NEWLINE_REGEXP), { onEmpty: () => renderLine(""), onNonEmpty: (promptLines) => { - const lines = Arr.map(promptLines, (line) => annotate(line)) + const lines = options?.plain === true + ? promptLines + : Arr.map(promptLines, (line) => Ansi.annotate(theme.colors, line, Ansi.bold)) return renderLine(lines.join("\n")) } }) @@ -2438,7 +2438,7 @@ const renderPrefix = ( if (state.cursor === currentIndex) { return renderOptions?.plain === true ? figures.pointer + prefix - : annotateSymbol(figures.pointer, figures.primaryColor) + prefix + : annotateSymbol(figures, figures.pointer, figures.primaryColor) + prefix } return prefix + " ".repeat(figures.pointer.length) } @@ -2453,7 +2453,7 @@ const renderFileName = ( return file } return isSelected - ? Ansi.annotate(file, Ansi.combine(Ansi.underlined, theme.primaryColor)) + ? Ansi.annotate(theme.colors, file, Ansi.combine(Ansi.underlined, theme.primaryColor)) : file } @@ -2461,10 +2461,10 @@ const renderFileFilter = (state: FileState, theme: Theme, renderOptions?: Render const filterValue = state.query.length === 0 ? renderOptions?.plain === true ? FILE_FILTER_PLACEHOLDER - : Ansi.annotate(FILE_FILTER_PLACEHOLDER, theme.mutedColor) + : Ansi.annotate(theme.colors, FILE_FILTER_PLACEHOLDER, theme.mutedColor) : renderOptions?.plain === true ? state.query - : Ansi.annotate(state.query, Ansi.combine(Ansi.underlined, theme.primaryColor)) + : Ansi.annotate(theme.colors, state.query, Ansi.combine(Ansi.underlined, theme.primaryColor)) return `[${FILE_FILTER_LABEL}: ${filterValue}]` } @@ -2479,7 +2479,7 @@ const renderFiles = ( if (length === 0) { return renderOptions?.plain === true ? FILE_EMPTY_MESSAGE - : Ansi.annotate(FILE_EMPTY_MESSAGE, figures.mutedColor) + : Ansi.annotate(figures.colors, FILE_EMPTY_MESSAGE, figures.mutedColor) } const toDisplay = entriesToDisplay(state.cursor, length, options.maxPerPage) const documents: Array = [] @@ -2498,28 +2498,44 @@ const renderFileNextFrame = Effect.fnUntraced(function*(state: FileState, option const currentPath = yield* resolveCurrentPath(state.path, options) const selectedPath = state.files[state.cursor] const resolvedPath = selectedPath === undefined ? currentPath : path.resolve(currentPath, selectedPath) - const resolvedPathMsg = Ansi.annotate(separateSymbol(figures.pointerSmall, resolvedPath), figures.mutedColor) + const resolvedPathMsg = Ansi.annotate( + figures.colors, + separateSymbol(figures.pointerSmall, resolvedPath), + figures.mutedColor + ) if (showConfirmation(state.confirm)) { - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) - const confirm = Ansi.annotate("(Y/n)", figures.mutedColor) - const promptMsg = renderPrompt(confirm, CONFIRM_MESSAGE, leadingSymbol, trailingSymbol) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) + const confirm = Ansi.annotate(figures.colors, "(Y/n)", figures.mutedColor) + const promptMsg = renderPrompt(confirm, CONFIRM_MESSAGE, leadingSymbol, trailingSymbol, figures) return Ansi.cursorHide + promptMsg + "\n" + resolvedPathMsg } - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) - const promptMsg = renderPrompt(renderFileFilter(state, figures), options.message, leadingSymbol, trailingSymbol) + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) + const promptMsg = renderPrompt( + renderFileFilter(state, figures), + options.message, + leadingSymbol, + trailingSymbol, + figures + ) const files = renderFiles(state, state.files, figures, options) return Ansi.cursorHide + promptMsg + "\n" + resolvedPathMsg + "\n" + files }) const renderFileSubmission = Effect.fnUntraced(function*(state: FileState, value: string, options: FileOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) - const promptMsg = renderPrompt(renderFileFilter(state, figures), options.message, leadingSymbol, trailingSymbol) - return promptMsg + " " + Ansi.annotate(value, figures.submittedColor) + "\n" + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) + const promptMsg = renderPrompt( + renderFileFilter(state, figures), + options.message, + leadingSymbol, + trailingSymbol, + figures + ) + return promptMsg + " " + Ansi.annotate(figures.colors, value, figures.submittedColor) + "\n" }) const handleFileRender = (options: FileOptionsReq) => { @@ -2720,8 +2736,8 @@ const renderMultiSelectError = ( if (renderOptions?.plain === true) { return separateSymbol(pointer, errorLines.join("\n")) } - const prefix = annotateSymbol(pointer, theme.errorColor) - const lines = Arr.map(errorLines, (str) => annotateErrorLine(str, theme.errorColor)) + const prefix = annotateSymbol(theme, pointer, theme.errorColor) + const lines = Arr.map(errorLines, (str) => annotateErrorLine(theme, str)) return Ansi.cursorSavePosition + "\n" + separateSymbol(prefix, lines.join("\n")) + Ansi.cursorRestorePosition } }) @@ -2739,7 +2755,7 @@ const renderChoiceDescription = ( const text = theme.descriptionSeparator + choice.description return renderOptions?.plain === true ? text - : Ansi.annotate(text, theme.mutedColor) + : Ansi.annotate(theme.colors, text, theme.mutedColor) } return "" } @@ -2755,7 +2771,7 @@ const renderMultiSelectTitle = ( if (renderOptions?.plain === true || !isHighlighted) { return title } - return Ansi.annotate(title, Ansi.combine(Ansi.underlined, theme.primaryColor)) + return Ansi.annotate(theme.colors, title, Ansi.combine(Ansi.underlined, theme.primaryColor)) } const renderMultiSelectChoices = ( @@ -2801,7 +2817,7 @@ const renderMultiSelectChoices = ( const isSelected = state.selectedIndices.has(choiceIndex) const checkbox = isSelected ? figures.checkboxOn : figures.checkboxOff const annotatedCheckbox = isHighlighted && renderOptions?.plain !== true - ? Ansi.annotate(checkbox, figures.primaryColor) + ? Ansi.annotate(figures.colors, checkbox, figures.primaryColor) : checkbox const selectChoice = choice as SelectChoice const title = renderChoiceTitle(selectChoice, isHighlighted, figures, renderOptions) @@ -2821,9 +2837,9 @@ const renderMultiSelectNextFrame = Effect.fnUntraced( function*(state: MultiSelectState, options: SelectOptionsReq) { const figures = yield* getTheme(options) const choices = renderMultiSelectChoices(state, options, figures) - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) - const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) + const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options, figures) const error = renderMultiSelectError(state, figures.pointer, figures) return Ansi.cursorHide + withSelectHeader(promptMsg, choices) + error } @@ -2836,10 +2852,10 @@ const renderMultiSelectSubmission = Effect.fnUntraced( options.choices[index].title ) const selectedText = selectedChoices.join(", ") - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) - const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options) ?? leadingSymbol - return promptMsg + " " + Ansi.annotate(selectedText, figures.submittedColor) + "\n" + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) + const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options, figures) ?? leadingSymbol + return promptMsg + " " + Ansi.annotate(figures.colors, selectedText, figures.submittedColor) + "\n" } ) @@ -2897,7 +2913,7 @@ const handleMultiSelectClear = (options: SelectOptionsReq) => const columns = yield* terminal.columns const figures = yield* getTheme(options) const clearPrompt = Ansi.eraseLine + Ansi.cursorLeft - const promptText = renderSelectOutput(figures.prefix, figures.pointerSmall, options, { plain: true }) + const promptText = renderSelectOutput(figures.prefix, figures.pointerSmall, options, figures, { plain: true }) const choicesText = renderMultiSelectChoices(state, options, figures, { plain: true }) const errorText = renderMultiSelectError(state, figures.pointer, figures, { plain: true }) const clearOutput = clearOutputWithError(withSelectHeader(promptText, choicesText), columns, errorText) @@ -2991,7 +3007,7 @@ const renderNumberInput = ( const annotation = Option.isSome(state.error) ? theme.errorColor : Ansi.combine(Ansi.underlined, theme.primaryColor) - return Ansi.annotate(value, annotation) + return Ansi.annotate(theme.colors, value, annotation) } const renderNumberError = ( @@ -3007,8 +3023,8 @@ const renderNumberError = ( if (renderOptions?.plain === true) { return separateSymbol(pointer, errorLines.join("\n")) } - const prefix = annotateSymbol(pointer, theme.errorColor) - const lines = Arr.map(errorLines, (str) => annotateErrorLine(str, theme.errorColor)) + const prefix = annotateSymbol(theme, pointer, theme.errorColor) + const lines = Arr.map(errorLines, (str) => annotateErrorLine(theme, str)) return Ansi.cursorSavePosition + "\n" + separateSymbol(prefix, lines.join("\n")) + Ansi.cursorRestorePosition } }) @@ -3026,13 +3042,13 @@ const renderNumberOutput = ( submitted: boolean = false ) => { const value = renderNumberInput(state, submitted, theme, renderOptions) - return renderPrompt(value, options.message, leadingSymbol, trailingSymbol, renderOptions) + return renderPrompt(value, options.message, leadingSymbol, trailingSymbol, theme, renderOptions) } const renderNumberNextFrame = Effect.fnUntraced(function*(state: NumberState, options: IntOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) const errorMsg = renderNumberError(state, figures.pointerSmall, figures) const promptMsg = renderNumberOutput(state, leadingSymbol, trailingSymbol, options, figures) return promptMsg + errorMsg @@ -3040,8 +3056,8 @@ const renderNumberNextFrame = Effect.fnUntraced(function*(state: NumberState, op const renderNumberSubmission = Effect.fnUntraced(function*(nextState: NumberState, options: IntOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) const promptMsg = renderNumberOutput(nextState, leadingSymbol, trailingSymbol, options, figures, undefined, true) return promptMsg + "\n" }) @@ -3299,11 +3315,12 @@ const renderSelectOutput = ( leadingSymbol: string, trailingSymbol: string, options: SelectOptionsReq, + theme: Theme, renderOptions?: RenderOptions | undefined ): string | undefined => options.message === undefined ? undefined - : renderPrompt("", options.message, leadingSymbol, trailingSymbol, renderOptions) + : renderPrompt("", options.message, leadingSymbol, trailingSymbol, theme, renderOptions) const withSelectHeader = (header: string | undefined, body: string): string => header === undefined ? body : header + "\n" + body @@ -3317,10 +3334,10 @@ const renderAutoCompleteFilter = ( const filterValue = state.query.length === 0 ? renderOptions?.plain === true ? options.filterPlaceholder - : Ansi.annotate(options.filterPlaceholder, theme.mutedColor) + : Ansi.annotate(theme.colors, options.filterPlaceholder, theme.mutedColor) : renderOptions?.plain === true ? state.query - : Ansi.annotate(state.query, Ansi.combine(Ansi.underlined, theme.primaryColor)) + : Ansi.annotate(theme.colors, state.query, Ansi.combine(Ansi.underlined, theme.primaryColor)) return `[${options.filterLabel}: ${filterValue}]` } @@ -3333,7 +3350,7 @@ const renderAutoCompleteOutput = ( renderOptions?: RenderOptions | undefined ) => { const filter = renderAutoCompleteFilter(state, options, theme, renderOptions) - return renderPrompt(filter, options.message, leadingSymbol, trailingSymbol, renderOptions) + return renderPrompt(filter, options.message, leadingSymbol, trailingSymbol, theme, renderOptions) } const renderChoicePrefix = ( @@ -3357,11 +3374,11 @@ const renderChoicePrefix = ( if (choices[currentIndex].disabled) { const annotation = Ansi.combine(Ansi.bold, figures.mutedColor) return state === currentIndex - ? annotateSymbol(figures.pointer, annotation) + prefix + ? annotateSymbol(figures, figures.pointer, annotation) + prefix : prefix + " ".repeat(figures.pointer.length) } return state === currentIndex - ? annotateSymbol(figures.pointer, figures.primaryColor) + prefix + ? annotateSymbol(figures, figures.pointer, figures.primaryColor) + prefix : prefix + " ".repeat(figures.pointer.length) } @@ -3388,11 +3405,11 @@ const renderAutoCompleteChoicePrefix = ( if (choice.disabled) { const annotation = Ansi.combine(Ansi.bold, figures.mutedColor) return state.index === choiceIndex - ? annotateSymbol(figures.pointer, annotation) + prefix + ? annotateSymbol(figures, figures.pointer, annotation) + prefix : prefix + " ".repeat(figures.pointer.length) } return state.index === choiceIndex - ? annotateSymbol(figures.pointer, figures.primaryColor) + prefix + ? annotateSymbol(figures, figures.pointer, figures.primaryColor) + prefix : prefix + " ".repeat(figures.pointer.length) } @@ -3408,11 +3425,11 @@ const renderChoiceTitle = ( const title = choice.title if (isSelected) { return choice.disabled - ? Ansi.annotate(title, Ansi.combine(Ansi.underlined, theme.mutedColor)) - : Ansi.annotate(title, Ansi.combine(Ansi.underlined, theme.primaryColor)) + ? Ansi.annotate(theme.colors, title, Ansi.combine(Ansi.underlined, theme.mutedColor)) + : Ansi.annotate(theme.colors, title, Ansi.combine(Ansi.underlined, theme.primaryColor)) } return choice.disabled - ? Ansi.annotate(title, Ansi.combine(Ansi.strikethrough, theme.mutedColor)) + ? Ansi.annotate(theme.colors, title, Ansi.combine(Ansi.strikethrough, theme.mutedColor)) : title } @@ -3445,7 +3462,7 @@ const renderAutoCompleteChoices = ( if (state.filtered.length === 0) { return renderOptions?.plain === true ? options.emptyMessage - : Ansi.annotate(options.emptyMessage, figures.mutedColor) + : Ansi.annotate(figures.colors, options.emptyMessage, figures.mutedColor) } const cursor = autoCompleteCursor(state) const toDisplay = entriesToDisplay(cursor, state.filtered.length, options.maxPerPage) @@ -3465,9 +3482,9 @@ const renderAutoCompleteChoices = ( const renderSelectNextFrame = Effect.fnUntraced(function*(state: SelectState, options: SelectOptionsReq) { const figures = yield* getTheme(options) const choices = renderSelectChoices(state, options, figures) - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) - const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) + const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options, figures) return Ansi.cursorHide + withSelectHeader(promptMsg, choices) }) @@ -3477,8 +3494,8 @@ const renderAutoCompleteNextFrame = Effect.fnUntraced(function*( ) { const figures = yield* getTheme(options) const choices = renderAutoCompleteChoices(state, options, figures) - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) const promptMsg = renderAutoCompleteOutput(state, leadingSymbol, trailingSymbol, options, figures) return Ansi.cursorHide + promptMsg + "\n" + choices }) @@ -3486,10 +3503,10 @@ const renderAutoCompleteNextFrame = Effect.fnUntraced(function*( const renderSelectSubmission = Effect.fnUntraced(function*(state: SelectState, options: SelectOptionsReq) { const figures = yield* getTheme(options) const selected = options.choices[state].title - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) - const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options) ?? leadingSymbol - return promptMsg + " " + Ansi.annotate(selected, figures.submittedColor) + "\n" + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) + const promptMsg = renderSelectOutput(leadingSymbol, trailingSymbol, options, figures) ?? leadingSymbol + return promptMsg + " " + Ansi.annotate(figures.colors, selected, figures.submittedColor) + "\n" }) const renderAutoCompleteSubmission = Effect.fnUntraced(function*( @@ -3498,10 +3515,10 @@ const renderAutoCompleteSubmission = Effect.fnUntraced(function*( ) { const figures = yield* getTheme(options) const selected = options.choices[state.index].title - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) const promptMsg = renderAutoCompleteOutput(state, leadingSymbol, trailingSymbol, options, figures) - return promptMsg + " " + Ansi.annotate(selected, figures.submittedColor) + "\n" + return promptMsg + " " + Ansi.annotate(figures.colors, selected, figures.submittedColor) + "\n" }) const processSelectCursorUp = (state: SelectState, choices: SelectOptionsReq["choices"]) => { @@ -3587,7 +3604,7 @@ const handleSelectClear = (options: SelectOptionsReq) => const columns = yield* terminal.columns const figures = yield* getTheme(options) const clearPrompt = Ansi.eraseLine + Ansi.cursorLeft - const promptText = renderSelectOutput(figures.prefix, figures.pointerSmall, options, { plain: true }) + const promptText = renderSelectOutput(figures.prefix, figures.pointerSmall, options, figures, { plain: true }) const choicesText = renderSelectChoices(state, options, figures, { plain: true }) const clearOutput = eraseText(withSelectHeader(promptText, choicesText), columns) return clearOutput + clearPrompt @@ -3759,10 +3776,10 @@ const renderTextInput = ( return "" } case "password": { - return annotateSymbol(theme.passwordMask.repeat(text.length), annotation) + return annotateSymbol(theme, theme.passwordMask.repeat(text.length), annotation) } case "text": { - return Ansi.annotate(text, annotation) + return Ansi.annotate(theme.colors, text, annotation) } } } @@ -3780,8 +3797,8 @@ const renderTextError = ( if (renderOptions?.plain === true) { return separateSymbol(pointer, errorLines.join("\n")) } - const prefix = annotateSymbol(pointer, theme.errorColor) - const lines = Arr.map(errorLines, (str) => annotateErrorLine(str, theme.errorColor)) + const prefix = annotateSymbol(theme, pointer, theme.errorColor) + const lines = Arr.map(errorLines, (str) => annotateErrorLine(theme, str)) return Ansi.cursorSavePosition + "\n" + separateSymbol(prefix, lines.join("\n")) + Ansi.cursorRestorePosition } }) @@ -3799,13 +3816,13 @@ const renderTextOutput = ( submitted: boolean = false ) => { const value = renderTextInput(nextState, options, theme, submitted, renderOptions) - return renderPrompt(value, options.message, leadingSymbol, trailingSymbol, renderOptions) + return renderPrompt(value, options.message, leadingSymbol, trailingSymbol, theme, renderOptions) } const renderTextNextFrame = Effect.fnUntraced(function*(state: TextState, options: TextOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) const promptMsg = renderTextOutput(state, leadingSymbol, trailingSymbol, options, figures) const errorMsg = renderTextError(state, figures.pointerSmall, figures) const cursorWidth = options.type === "password" ? figures.passwordMask.length : 1 @@ -3815,8 +3832,8 @@ const renderTextNextFrame = Effect.fnUntraced(function*(state: TextState, option const renderTextSubmission = Effect.fnUntraced(function*(state: TextState, options: TextOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) const promptMsg = renderTextOutput(state, leadingSymbol, trailingSymbol, options, figures, undefined, true) return promptMsg + "\n" }) @@ -4009,7 +4026,9 @@ const handleToggleClear = Effect.fnUntraced(function*(options: ToggleOptionsReq) const figures = yield* getTheme(options) const clearPrompt = Ansi.eraseLine + Ansi.cursorLeft const toggleText = options.active + " " + separateSymbol(figures.toggleSeparator, options.inactive) - const promptText = renderPrompt(toggleText, options.message, figures.prefix, figures.pointerSmall, { plain: true }) + const promptText = renderPrompt(toggleText, options.message, figures.prefix, figures.pointerSmall, figures, { + plain: true + }) const clearOutput = eraseText(promptText, columns) return clearOutput + clearPrompt }) @@ -4020,44 +4039,35 @@ const renderToggle = ( theme: Theme, submitted: boolean = false ) => { - const separator = annotateSymbol(theme.toggleSeparator, theme.mutedColor) + const separator = annotateSymbol(theme, theme.toggleSeparator, theme.mutedColor) const selectedAnnotation = Ansi.combine( Ansi.underlined, submitted ? theme.submittedColor : theme.primaryColor ) const inactive = value ? options.inactive - : Ansi.annotate(options.inactive, selectedAnnotation) + : Ansi.annotate(theme.colors, options.inactive, selectedAnnotation) const active = value - ? Ansi.annotate(options.active, selectedAnnotation) + ? Ansi.annotate(theme.colors, options.active, selectedAnnotation) : options.active return active + " " + separateSymbol(separator, inactive) } -const renderToggleOutput = ( - toggle: string, - leadingSymbol: string, - trailingSymbol: string, - options: ToggleOptionsReq -) => { - return renderPrompt(toggle, options.message, leadingSymbol, trailingSymbol) -} - const renderToggleNextFrame = Effect.fnUntraced(function*(state: ToggleState, options: ToggleOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.prefix, figures.primaryColor) - const trailingSymbol = annotateSymbol(figures.pointerSmall, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.prefix, figures.primaryColor) + const trailingSymbol = annotateSymbol(figures, figures.pointerSmall, figures.mutedColor) const toggle = renderToggle(state, options, figures) - const promptMsg = renderToggleOutput(toggle, leadingSymbol, trailingSymbol, options) + const promptMsg = renderPrompt(toggle, options.message, leadingSymbol, trailingSymbol, figures) return Ansi.cursorHide + promptMsg }) const renderToggleSubmission = Effect.fnUntraced(function*(value: boolean, options: ToggleOptionsReq) { const figures = yield* getTheme(options) - const leadingSymbol = annotateSymbol(figures.tick, figures.successColor) - const trailingSymbol = annotateSymbol(figures.ellipsis, figures.mutedColor) + const leadingSymbol = annotateSymbol(figures, figures.tick, figures.successColor) + const trailingSymbol = annotateSymbol(figures, figures.ellipsis, figures.mutedColor) const toggle = renderToggle(value, options, figures, true) - const promptMsg = renderToggleOutput(toggle, leadingSymbol, trailingSymbol, options) + const promptMsg = renderPrompt(toggle, options.message, leadingSymbol, trailingSymbol, figures) return promptMsg + "\n" }) diff --git a/repos/effect/packages/effect/src/cli/internal/ansi.ts b/repos/effect/packages/effect/src/cli/internal/ansi.ts index 207d5825b5..581a91664a 100644 --- a/repos/effect/packages/effect/src/cli/internal/ansi.ts +++ b/repos/effect/packages/effect/src/cli/internal/ansi.ts @@ -105,9 +105,32 @@ export const blackBright = `${ESC}90m` */ export const cyanBright = `${ESC}96m` -export const annotate = (text: string, ...styles: Array>) => { - const flat = styles.flat() - return `${flat.join("")}${text}${reset}` +/** + * Wraps `text` in the given styles followed by a reset. When `colors` is + * `false` the text is returned unchanged, so callers gate color and style + * escapes in one place while cursor and erase controls stay untouched. + * + * @internal + */ +export const annotate = (colors: boolean, text: string, ...styles: Array>): string => { + if (!colors) return text + return `${styles.flat().join("")}${text}${reset}` +} + +/** + * Detects whether CLI output should use color and style escapes: stdout must + * be a TTY and `NO_COLOR` must be unset or empty. + * + * @internal + */ +export const detectColors = (): boolean => { + const globalProcess = (globalThis as any).process + return typeof globalProcess === "object" && + globalProcess !== null && + typeof globalProcess.stdout === "object" && + globalProcess.stdout !== null && + globalProcess.stdout.isTTY === true && + !globalProcess.env?.NO_COLOR } export const combine = (...styles: Array): Array => styles diff --git a/repos/effect/packages/effect/src/cli/internal/command.ts b/repos/effect/packages/effect/src/cli/internal/command.ts index af161fc6db..7b52da2484 100644 --- a/repos/effect/packages/effect/src/cli/internal/command.ts +++ b/repos/effect/packages/effect/src/cli/internal/command.ts @@ -242,10 +242,11 @@ export const toFlagDoc = ( metadata: ReturnType ): FlagDoc => { const formattedAliases = single.aliases.map((alias) => alias.length === 1 ? `-${alias}` : `--${alias}`) + const type = single.typeName ?? Primitive.getTypeName(single.primitiveType) return { name: single.name, aliases: formattedAliases, - type: single.typeName ?? Primitive.getTypeName(single.primitiveType), + type: single.optionalValue === undefined ? type : `[=${type}]`, description: appendChoiceKeys(single.description, Primitive.getChoiceKeys(single.primitiveType)), required: single.primitiveType._tag !== "Boolean" && !metadata.isOptional } diff --git a/repos/effect/packages/effect/src/cli/internal/completions/bash.ts b/repos/effect/packages/effect/src/cli/internal/completions/bash.ts index d71d0dfd12..2ccead6ce0 100644 --- a/repos/effect/packages/effect/src/cli/internal/completions/bash.ts +++ b/repos/effect/packages/effect/src/cli/internal/completions/bash.ts @@ -7,6 +7,7 @@ * @internal */ import type * as Completions from "../../Completions.ts" +import { takesSeparateValue } from "./descriptor.ts" // --------------------------------------------------------------------------- // Helpers @@ -164,7 +165,7 @@ const generateFunction = ( lines.push(``) // Build flag-value dispatch - const flagsWithValues = descriptor.flags.filter((f) => f.type._tag !== "Boolean") + const flagsWithValues = descriptor.flags.filter(takesSeparateValue) if (flagsWithValues.length > 0) { lines.push(` # Flag value completions`) lines.push(` case "$prev" in`) @@ -196,7 +197,7 @@ const generateFunction = ( lines.push(` fi`) lines.push(` case "\${words[i]}" in`) for (const flag of descriptor.flags) { - if (flag.type._tag === "Boolean") continue + if (!takesSeparateValue(flag)) continue const forms = flagNamesForWordlist(flag) lines.push(` ${forms.join("|")}) _skip_next=1 ;;`) lines.push(` ${forms.map((form) => `${form}=*`).join("|")}) ;;`) @@ -248,7 +249,7 @@ const generateFunction = ( lines.push(` --) _end_of_options=1 ;;`) for (const flag of descriptor.flags) { const forms = flagNamesForWordlist(flag) - if (flag.type._tag === "Boolean") { + if (!takesSeparateValue(flag)) { lines.push(` ${forms.join("|")}) ;;`) } else { lines.push(` ${forms.join("|")}) _skip_next=1 ;;`) diff --git a/repos/effect/packages/effect/src/cli/internal/completions/descriptor.ts b/repos/effect/packages/effect/src/cli/internal/completions/descriptor.ts index c84db2bc33..378d418b13 100644 --- a/repos/effect/packages/effect/src/cli/internal/completions/descriptor.ts +++ b/repos/effect/packages/effect/src/cli/internal/completions/descriptor.ts @@ -95,7 +95,8 @@ export const fromCommand = ( name: single.name, aliases: single.aliases, description: Option.getOrUndefined(single.description), - type: toFlagType(single as Param.Single<"flag", unknown>) + type: toFlagType(single as Param.Single<"flag", unknown>), + optionalValue: single.optionalValue !== undefined }) } } @@ -139,3 +140,11 @@ export const fromCommand = ( subcommands } } + +/** + * Whether the flag reads its value from the next word. + * + * @internal + */ +export const takesSeparateValue = (flag: Completions.FlagDescriptor): boolean => + flag.type._tag !== "Boolean" && flag.optionalValue !== true diff --git a/repos/effect/packages/effect/src/cli/internal/completions/fish.ts b/repos/effect/packages/effect/src/cli/internal/completions/fish.ts index aaca1cfca2..0aefa710b4 100644 --- a/repos/effect/packages/effect/src/cli/internal/completions/fish.ts +++ b/repos/effect/packages/effect/src/cli/internal/completions/fish.ts @@ -7,6 +7,7 @@ * @internal */ import type * as Completions from "../../Completions.ts" +import { takesSeparateValue } from "./descriptor.ts" // --------------------------------------------------------------------------- // Helpers @@ -88,7 +89,7 @@ const flagCompletionArgs = (flag: Completions.FlagDescriptor): Array => if (flag.description) { args.push(`-d '${escapeFishString(flag.description)}'`) } - const valueArgs = flagValueArgs(flag.type) + const valueArgs = takesSeparateValue(flag) ? flagValueArgs(flag.type) : undefined if (valueArgs) { args.push(valueArgs) } @@ -159,8 +160,7 @@ const generateCompletions = ( // Flag completions for (const flag of descriptor.flags) { - const isBoolean = flag.type._tag === "Boolean" - const dedup = isBoolean ? flagContainsOptCondition(flag) : valueFlagDedupCondition(flag) + const dedup = takesSeparateValue(flag) ? valueFlagDedupCondition(flag) : flagContainsOptCondition(flag) const flagCondition = condition ? `${condition}; and ${dedup}` : dedup const flagCondArg = flagCondition ? `-n '${flagCondition}'` : `` @@ -170,7 +170,7 @@ const generateCompletions = ( lines.push(parts.join(" ")) // Boolean negation - if (isBoolean) { + if (flag.type._tag === "Boolean") { const negParts = [`complete -c ${executableName}`] if (flagCondArg) negParts.push(flagCondArg) negParts.push(`-l no-${flag.name}`) diff --git a/repos/effect/packages/effect/src/cli/internal/completions/powershell.ts b/repos/effect/packages/effect/src/cli/internal/completions/powershell.ts new file mode 100644 index 0000000000..868d5a26ab --- /dev/null +++ b/repos/effect/packages/effect/src/cli/internal/completions/powershell.ts @@ -0,0 +1,325 @@ +/** + * Static PowerShell completion script generator. + * + * Produces a self-contained completion script from a `CommandDescriptor`, + * without invoking the CLI at runtime. The script sticks to Windows + * PowerShell 5.1 syntax and APIs. + * + * @internal + */ +import type * as Completions from "../../Completions.ts" + +/** + * Encode non-ASCII and control characters as `[char]` code units. Windows + * PowerShell 5.1 can misread BOM-less UTF-8 as ANSI, turning some bytes into + * PowerShell quote delimiters. + */ +const quotePs = (s: string): string => { + const parts: Array = [] + let literal = "" + for (let i = 0; i < s.length; i++) { + const code = s.charCodeAt(i) + if (code >= 0x20 && code < 0x80) { + literal += s[i] === "'" ? "''" : s[i] + continue + } + if (literal !== "" || parts.length === 0) parts.push(`'${literal}'`) + literal = "" + parts.push(`[char]0x${code.toString(16).toUpperCase().padStart(4, "0")}`) + } + if (literal !== "" || parts.length === 0) parts.push(`'${literal}'`) + return parts.length === 1 ? parts[0] : `(${parts.join(" + ")})` +} + +const psArray = (items: ReadonlyArray): string => `@(${items.map(quotePs).join(", ")})` + +const psOptional = (s: string | undefined): string => s ? quotePs(s) : "$null" + +const sanitize = (s: string): string => s.replace(/[^a-zA-Z0-9_]/g, "_") + +const flagForms = (flag: Completions.FlagDescriptor): Array => [ + `--${flag.name}`, + ...flag.aliases.map((alias) => alias.length === 1 ? `-${alias}` : `--${alias}`) +] + +const valueFields = (type: Completions.FlagType | Completions.ArgumentType): string => + `values = ${psArray(type._tag === "Choice" ? type.values : [])}; ` + + `pathType = ${type._tag === "Path" ? quotePs(type.pathType) : "$null"}` + +const flagEntry = (flag: Completions.FlagDescriptor): string => + `@{ name = ${quotePs(flag.name)}; forms = ${psArray(flagForms(flag))}; ` + + `takesValue = $${flag.type._tag !== "Boolean"}; ` + + (flag.optionalValue === true ? `optionalValue = $true; ` : "") + + `${valueFields(flag.type)}; ` + + `description = ${psOptional(flag.description)} }` + +const argumentEntry = (argument: Completions.ArgumentDescriptor): string => + `@{ name = ${quotePs(argument.name)}; variadic = $${argument.variadic}; ${valueFields(argument.type)}; ` + + `description = ${psOptional(argument.description)} }` + +const pushList = (lines: Array, field: string, entries: ReadonlyArray): void => { + if (entries.length === 0) { + lines.push(` ${field} = @()`) + return + } + lines.push(` ${field} = @(`) + for (const entry of entries) { + lines.push(` ${entry}`) + } + lines.push(` )`) +} + +/** + * Emit one context per subcommand path. Subcommands are case-sensitive, so + * contexts go in an ordinal hashtable instead of a hash literal, whose keys + * ignore case. + */ +const generateContexts = ( + dataName: string, + descriptor: Completions.CommandDescriptor, + path: ReadonlyArray, + lines: Array, + seen: Set +): void => { + const key = path.join(" ") + if (seen.has(key)) return + seen.add(key) + lines.push(`${dataName}[${quotePs(key)}] = @{`) + pushList( + lines, + "subcommands", + descriptor.subcommands.map((sub) => + `@{ name = ${quotePs(sub.name)}; description = ${psOptional(sub.description)} }` + ) + ) + pushList(lines, "flags", descriptor.flags.map(flagEntry)) + pushList(lines, "arguments", descriptor.arguments.map(argumentEntry)) + lines.push(`}`) + for (const sub of descriptor.subcommands) { + generateContexts(dataName, sub, [...path, sub.name], lines, seen) + } +} + +/** + * Replay the committed words with the CLI lexer and parser rules: `--`, short + * flag clusters, inline values, boolean literals, negative numbers, and + * subcommand selection by the first value only. + */ +const completer = (dataName: string): string => + String.raw` param($wordToComplete, $commandAst, $cursorPosition) + + $spec = ${dataName} + $results = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new() + $booleanLiterals = @('true', 'yes', 'on', '1', 'y', 'false', 'no', 'off', '0', 'n') + + $index = { + param($context) + $lookup = [hashtable]::new([System.StringComparer]::Ordinal) + foreach ($flag in $context.flags) { + foreach ($form in $flag.forms) { $lookup[$form] = $flag } + } + $lookup + } + + $add = { + param([string]$value, [string]$type, $tooltip, [string]$typed, [string]$textPrefix) + if (-not $value.StartsWith($typed, [System.StringComparison]::OrdinalIgnoreCase)) { return } + $text = $value + if ($value -notmatch '^[\w./:%+=\\-]+$') { $text = "'" + ($value -replace "['\u2018-\u201b]", '$0$0') + "'" } + $text = $textPrefix + $text + $label = $value + if (-not $label) { $label = $text } + if (-not $tooltip) { $tooltip = $label } + $results.Add([System.Management.Automation.CompletionResult]::new($text, $label, $type, $tooltip)) + } + + $addValues = { + param($entry, [string]$typed, [string]$textPrefix) + foreach ($value in $entry.values) { + if ($textPrefix -eq '' -and (& $optionLike $value)) { continue } + & $add $value 'ParameterValue' $entry.description $typed $textPrefix + } + if ($entry.pathType) { + foreach ($file in [System.Management.Automation.CompletionCompleters]::CompleteFilename($typed)) { + if ($entry.pathType -eq 'directory' -and $file.ResultType -ne 'ProviderContainer') { continue } + $results.Add([System.Management.Automation.CompletionResult]::new($textPrefix + $file.CompletionText, $file.ListItemText, $file.ResultType, $file.ToolTip)) + } + } + } + + $addFlags = { + param([string]$typed) + foreach ($flag in $context.flags) { + if ($used.ContainsKey($flag.name)) { continue } + foreach ($form in $flag.forms) { + & $add $form 'ParameterName' $flag.description $typed '' + } + if (-not $flag.takesValue) { + $tooltip = $null + if ($flag.description) { $tooltip = 'Disable ' + $flag.name } + & $add ('--no-' + $flag.name) 'ParameterName' $tooltip $typed '' + } + } + } + + # As in the CLI lexer, nothing after '--' is an option, and negative numbers + # and a lone '-' are values. + $optionLike = { + param([string]$word) + -not $endOfOptions -and $word -match '^-.' -and $word -notmatch '^-(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$' + } + + # A typed value that has no candidates completes to itself, so the engine + # does not fall back to listing files. + $keepTyped = { + if ($results.Count -eq 0 -and $current) { + $results.Add([System.Management.Automation.CompletionResult]::new($current, $current, 'ParameterValue', $current)) + } + } + + $path = '' + $context = $spec[$path] + $lookup = & $index $context + $used = [hashtable]::new([System.StringComparer]::Ordinal) + $pending = $null + $endOfOptions = $false + $position = 0 + + # The engine strips the quotes from a quoted word. + $typed = [string]$wordToComplete + if ($typed -match '^([''"])(.*?)\1?$') { $typed = $Matches[2] } + $current = $null + + $elements = $commandAst.CommandElements + for ($i = 1; $i -lt $elements.Count; $i++) { + $element = $elements[$i] + $word = $element.Extent.Text + if ($element -is [System.Management.Automation.Language.StringConstantExpressionAst]) { $word = $element.Value } + if ($element.Extent.EndOffset -ge $cursorPosition) { + if ($element -is [System.Management.Automation.Language.ConstantExpressionAst] -and $element.Extent.StartOffset -le $cursorPosition) { + $current = $element.Extent.Text + if ($element.Extent.EndOffset -eq $cursorPosition) { $typed = $word } + } + break + } + + # A flag takes the next word as its value unless it is an option or '--'; + # a boolean flag only takes a boolean literal. + $isOption = & $optionLike $word + if ($null -ne $pending) { + $flag = $pending + $pending = $null + if ($flag.takesValue) { + if (-not $isOption) { continue } + } elseif ($booleanLiterals -ccontains $word) { continue } + } + if ($endOfOptions) { $position++; continue } + if ($word -ceq '--') { $endOfOptions = $true; continue } + + if ($isOption) { + $hasValue = $word.Contains('=') + if ($hasValue) { + $forms = @($word.Substring(0, $word.IndexOf('='))) + } elseif ($word.StartsWith('--')) { + $forms = @($word) + } else { + $forms = @(foreach ($char in $word.Substring(1).ToCharArray()) { '-' + $char }) + } + foreach ($form in $forms) { + $pending = $null + $flag = $lookup[$form] + if ($null -eq $flag) { + if ($form.StartsWith('--no-')) { + $name = $form.Substring(5) + $flag = $lookup['--' + $name] + if ($null -ne $flag -and -not $flag.takesValue -and $flag.name -ceq $name) { $used[$name] = $true } + } + continue + } + $used[$flag.name] = $true + # A flag with an optional value only takes a value attached with '='. + if (-not $hasValue -and -not $flag.optionalValue) { $pending = $flag } + } + continue + } + + if ($position -eq 0 -and $context.subcommands.name -ccontains $word) { + if ($path) { $path = $path + ' ' + $word } else { $path = $word } + $context = $spec[$path] + $lookup = & $index $context + $used = [hashtable]::new([System.StringComparer]::Ordinal) + continue + } + $position++ + } + + $typedIsOption = & $optionLike $typed + if ($null -ne $pending -and $pending.takesValue -and -not $typedIsOption) { + & $addValues $pending $typed '' + & $keepTyped + return $results + } + + if ($typedIsOption) { + if ($typed -match '^(-[^=]+)=(.*)$') { + $form = $Matches[1] + $flag = $lookup[$form] + if ($null -ne $flag -and $flag.takesValue) { + & $addValues $flag $Matches[2] ($form + '=') + & $keepTyped + } + } else { + & $addFlags $typed + } + return $results + } + + if (-not $endOfOptions -and $position -eq 0) { + foreach ($sub in $context.subcommands) { + & $add $sub.name 'Command' $sub.description $typed '' + } + } + + $arguments = $context.arguments + if ($position -lt $arguments.Count) { + & $addValues $arguments[$position] $typed '' + } elseif ($arguments.Count -gt 0 -and $arguments[-1].variadic) { + & $addValues $arguments[-1] $typed '' + } + + if (-not $endOfOptions) { + & $addFlags $typed + } + return $results` + +/** @internal */ +export const generate = ( + executableName: string, + descriptor: Completions.CommandDescriptor +): string => { + const dataName = `$global:_${sanitize(executableName)}_Completions` + const lines: Array = [] + + lines.push(`###-begin-${executableName}-completions-###`) + lines.push(`#`) + lines.push(`# Static completion script for PowerShell`) + lines.push(`#`) + lines.push(`# Installation:`) + // `>>` on Windows PowerShell 5.1 appends UTF-16LE to the profile, so the + // script goes in its own file. + lines.push(`# ${executableName} --completions powershell > ${executableName}-completion.ps1`) + lines.push(`# then add this line to your $PROFILE (use the full path to the file):`) + lines.push(`# . \\${executableName}-completion.ps1`) + lines.push(`#`) + lines.push(``) + lines.push(`${dataName} = [hashtable]::new([System.StringComparer]::Ordinal)`) + generateContexts(dataName, descriptor, [], lines, new Set()) + lines.push(``) + lines.push(`Register-ArgumentCompleter -Native -CommandName ${quotePs(executableName)} -ScriptBlock {`) + lines.push(completer(dataName)) + lines.push(`}`) + lines.push(``) + lines.push(`###-end-${executableName}-completions-###`) + + return lines.join("\n") +} diff --git a/repos/effect/packages/effect/src/cli/internal/completions/zsh.ts b/repos/effect/packages/effect/src/cli/internal/completions/zsh.ts index e7a58ce8e0..334bf42189 100644 --- a/repos/effect/packages/effect/src/cli/internal/completions/zsh.ts +++ b/repos/effect/packages/effect/src/cli/internal/completions/zsh.ts @@ -14,6 +14,8 @@ import type * as Completions from "../../Completions.ts" const escapeZsh = (s: string): string => s.replace(/\\/g, "\\\\").replace(/'/g, "'\\''").replace(/:/g, "\\:") +const escapeZshExplanation = (s: string): string => escapeZsh(s).replace(/]/g, "\\]") + /** Escape choices for the second parse of a Zsh `_arguments` action. */ const escapeZshChoice = (s: string): string => s.replace(/[^A-Za-z0-9_.,/@%+-]/gu, "\\$&").replace(/'/g, "'\\''") @@ -69,22 +71,26 @@ const argAction = (type: Completions.ArgumentType): string => { */ const flagSpecs = (flag: Completions.FlagDescriptor): Array => { const specs: Array = [] - const desc = flag.description ? `[${escapeZsh(flag.description)}]` : "" - const action = valueAction(flag.type) + const desc = flag.description ? `[${escapeZshExplanation(flag.description)}]` : "" + // An optional value must follow `=` in the same word (`--name=-`), and `::` + // marks it optional. + const optional = flag.optionalValue === true && flag.type._tag !== "Boolean" + const valueSuffix = optional ? "=-" : "" + const action = optional ? `:${valueAction(flag.type)}` : valueAction(flag.type) const excl = `(${allForms(flag).join(" ")})` // Primary long name - specs.push(`'${excl}--${flag.name}${desc}${action}'`) + specs.push(`'${excl}--${flag.name}${valueSuffix}${desc}${action}'`) // Aliases for (const alias of flag.aliases) { const prefix = alias.length === 1 ? "-" : "--" - specs.push(`'${excl}${prefix}${alias}${desc}${action}'`) + specs.push(`'${excl}${prefix}${alias}${valueSuffix}${desc}${action}'`) } // Boolean negation if (flag.type._tag === "Boolean") { - const negDesc = flag.description ? `[${escapeZsh(`Disable ${flag.name}`)}]` : "" + const negDesc = flag.description ? `[${escapeZshExplanation(`Disable ${flag.name}`)}]` : "" specs.push(`'${excl}--no-${flag.name}${negDesc}'`) } diff --git a/repos/effect/packages/effect/src/cli/internal/parser.ts b/repos/effect/packages/effect/src/cli/internal/parser.ts index 627a214103..2e77922d4c 100644 --- a/repos/effect/packages/effect/src/cli/internal/parser.ts +++ b/repos/effect/packages/effect/src/cli/internal/parser.ts @@ -425,8 +425,9 @@ const asBooleanLiteral = (token: Token | undefined): string | undefined => * * Value resolution order: * 1. Inline value: --flag=value or -f=value - * 2. Boolean special case: implicit "true" or explicit boolean literal - * 3. Next token: consume following Value token if present + * 2. Optional value: the flag's configured value, without consuming a token + * 3. Boolean special case: implicit "true" or explicit boolean literal + * 4. Next token: consume following Value token if present */ const consumeFlagValue = ( cursor: TokenCursor, @@ -465,7 +466,7 @@ const consumeFlagValueWithTokens = ( } } - const literal = asBooleanLiteral(cursor.peek()) + const literal = spec.optionalValue === undefined ? asBooleanLiteral(cursor.peek()) : undefined if (literal !== undefined) { const literalToken = cursor.take() return { @@ -490,6 +491,14 @@ const consumeFlagValueWithTokens = ( } } + if (spec.optionalValue !== undefined) { + return { + _tag: "Value", + value: spec.optionalValue, + tokens: [] + } + } + // Boolean flags: check for explicit literal or default to "true" if (Primitive.isBoolean(spec.primitiveType)) { const literal = asBooleanLiteral(cursor.peek()) diff --git a/repos/effect/packages/effect/src/cli/internal/wizard.ts b/repos/effect/packages/effect/src/cli/internal/wizard.ts index f4ddbebe8f..6a55aaf9b3 100644 --- a/repos/effect/packages/effect/src/cli/internal/wizard.ts +++ b/repos/effect/packages/effect/src/cli/internal/wizard.ts @@ -34,8 +34,9 @@ export const run: ( const commandPath = options?.commandPath ?? [command.name] const selected = getCommandAtPath(command, commandPath) const commandLine = (options?.prefix ?? commandPath).map((value) => commandLineArg(value)) - yield* logCurrentCommand(commandLine) - yield* promptCommand(selected, commandLine, selected === command ? "ROOT" : selected.name) + const { colors } = yield* Prompt.Theme + yield* logCurrentCommand(commandLine, colors) + yield* promptCommand(selected, commandLine, selected === command ? "ROOT" : selected.name, colors) return { args: commandLine.map((arg) => arg.value), displayArgs: commandLine.map((arg) => arg.displayValue) @@ -63,30 +64,31 @@ const getCommandAtPath = ( const promptCommand: ( command: Command.Command.Any, commandLine: Array, - sectionName: string + sectionName: string, + colors: boolean ) => Effect.Effect = Effect.fnUntraced( - function*(command, commandLine, sectionName) { + function*(command, commandLine, sectionName, colors) { const impl = toImpl(command) const visibleSubcommands = command.subcommands.flatMap((group) => group.commands.filter((child) => !child.unlisted)) const config = visibleSubcommands.length === 0 ? impl.config : impl.contextConfig if (config.flags.length > 0) { - yield* Console.log(renderSection(sectionName, "FLAGS")) + yield* Console.log(renderSection(sectionName, "FLAGS", colors)) for (const param of config.flags) { commandLine.push(...yield* promptParam(param)) } if (config.arguments.length > 0 || visibleSubcommands.length > 0) { - yield* logCurrentCommand(commandLine) + yield* logCurrentCommand(commandLine, colors) } } if (config.arguments.length > 0) { - yield* Console.log(renderSection(sectionName, "ARGUMENTS")) + yield* Console.log(renderSection(sectionName, "ARGUMENTS", colors)) for (const param of config.arguments) { commandLine.push(...yield* promptParam(param)) } if (visibleSubcommands.length > 0) { - yield* logCurrentCommand(commandLine) + yield* logCurrentCommand(commandLine, colors) } } @@ -109,9 +111,9 @@ const promptCommand: ( yield* Console.log() commandLine.push(commandLineArg(child.name)) if (hasWizardSteps(child)) { - yield* logCurrentCommand(commandLine) + yield* logCurrentCommand(commandLine, colors) } - yield* promptCommand(child, commandLine, child.name) + yield* promptCommand(child, commandLine, child.name, colors) } ) @@ -169,8 +171,9 @@ const promptParam = Effect.fnUntraced( return values } // Inline option-looking values so the lexer cannot interpret them as flags or the -- delimiter. + // Flags with an optional value only accept an inline value. return values.flatMap((value) => - value.value.startsWith("-") && value.value.length > 1 + single.optionalValue !== undefined || (value.value.startsWith("-") && value.value.length > 1) ? [commandLineArg(`--${single.name}=${value.value}`, `--${single.name}=${value.displayValue}`)] : [commandLineArg(`--${single.name}`), value] ) @@ -244,41 +247,47 @@ const humanize = (name: string): string => { return [words[0][0].toUpperCase() + words[0].slice(1), ...words.slice(1)].join(" ") } -const logCurrentCommand = (commandLine: ReadonlyArray): Effect.Effect => - Console.log(renderCommandBlock("Current command", commandLine.map((arg) => arg.displayValue), Ansi.magenta)) +const logCurrentCommand = (commandLine: ReadonlyArray, colors: boolean): Effect.Effect => + Console.log(renderCommandBlock("Current command", commandLine.map((arg) => arg.displayValue), colors, Ansi.magenta)) -const renderSection = (commandName: string, section: string): string => - `${Ansi.annotate(commandName.toUpperCase(), Ansi.bold, Ansi.cyanBright)} ${Ansi.annotate("·", Ansi.blackBright)} ${ - Ansi.annotate(section, Ansi.bold, Ansi.white) - }` +const renderSection = (commandName: string, section: string, colors: boolean): string => + `${Ansi.annotate(colors, commandName.toUpperCase(), Ansi.bold, Ansi.cyanBright)} ${ + Ansi.annotate(colors, "·", Ansi.blackBright) + } ${Ansi.annotate(colors, section, Ansi.bold, Ansi.white)}` -export const renderIntroduction = (name: string, version: string, summary: string | undefined): string => { - const title = `${Ansi.annotate(name, Ansi.bold, Ansi.cyanBright)} ${Ansi.annotate(`v${version}`, Ansi.white)} ${ - Ansi.annotate("· Command wizard", Ansi.bold, Ansi.white) - }` +export const renderIntroduction = ( + name: string, + version: string, + summary: string | undefined, + colors: boolean +): string => { + const title = `${Ansi.annotate(colors, name, Ansi.bold, Ansi.cyanBright)} ${ + Ansi.annotate(colors, `v${version}`, Ansi.white) + } ${Ansi.annotate(colors, "· Command wizard", Ansi.bold, Ansi.white)}` return [ title, ...(summary === undefined || summary.length === 0 ? [] : [summary]), - Ansi.annotate("Build a command interactively. Press Ctrl+C to cancel.", Ansi.blackBright), + Ansi.annotate(colors, "Build a command interactively. Press Ctrl+C to cancel.", Ansi.blackBright), "" ].join("\n") } -export const renderCompletion = (commandLine: ReadonlyArray): string => - renderCommandBlock("Command ready", commandLine, Ansi.cyanBright, Ansi.green) +export const renderCompletion = (commandLine: ReadonlyArray, colors: boolean): string => + renderCommandBlock("Command ready", commandLine, colors, Ansi.cyanBright, Ansi.green) -export const renderQuit = (): string => `\n${Ansi.annotate("Wizard cancelled.", Ansi.red)}` +export const renderQuit = (colors: boolean): string => `\n${Ansi.annotate(colors, "Wizard cancelled.", Ansi.red)}` const renderCommandBlock = ( label: string, commandLine: ReadonlyArray, + colors: boolean, commandColor: string, labelColor: string = Ansi.white ): string => { const lines = wrapCommand(commandLine) return [ - Ansi.annotate(label, Ansi.bold, labelColor), - ...lines.map((line) => Ansi.annotate(line, commandColor)), + Ansi.annotate(colors, label, Ansi.bold, labelColor), + ...lines.map((line) => Ansi.annotate(colors, line, commandColor)), "" ].join("\n") } diff --git a/repos/effect/packages/effect/src/cluster/ClusterSchema.ts b/repos/effect/packages/effect/src/cluster/ClusterSchema.ts index c6744cd311..f46606f023 100644 --- a/repos/effect/packages/effect/src/cluster/ClusterSchema.ts +++ b/repos/effect/packages/effect/src/cluster/ClusterSchema.ts @@ -62,11 +62,22 @@ export const Persisted = Context.Reference("effect/cluster/ClusterSchem * The default value is `false`. When `true`, entity handling wraps server * writes with the configured storage transaction. * + * Persisted requests deliver terminal replies and mark requests processed only + * after commit or clean rollback. Success replies are saved in the transaction; + * failures are saved after rollback. If commit reports failure, a stored success + * reply is recovered. Otherwise, commit or rollback failures retry the request + * without delivering a reply. Handlers must tolerate retries. + * * **Gotchas** * * This annotation has transactional behavior only when the configured * `MessageStorage` implements it. * + * Stream chunks are saved and delivered immediately, even if the transaction + * later rolls back. A handler returning a `Deferred` commits before its reply + * is saved. Non-persisted requests save no reply; successes are delivered when + * the handler exits, and failures after the transaction exits. + * * @stability unstable * @category services * @since 4.0.0 @@ -95,6 +106,27 @@ export const Uninterruptible = Context.Reference( { defaultValue: constFalse } ) +/** + * Annotation that interrupts a cluster request when entity termination starts, + * rather than waiting for the termination grace period to expire. + * + * **Details** + * + * The default value is `false`. Use for long-lived requests that cannot finish + * on their own. Persisted requests resume under the next owner without saving + * the interruption as a reply. Non-persisted requests receive an interrupt exit. + * + * Server-side `Uninterruptible` takes precedence over this annotation. + * + * @stability unstable + * @category services + * @since 4.0.0 + */ +export const InterruptOnTermination = Context.Reference( + "effect/cluster/ClusterSchema/InterruptOnTermination", + { defaultValue: constFalse } +) + /** * Returns whether the `Uninterruptible` annotation applies to server-side * request handling for the provided context. diff --git a/repos/effect/packages/effect/src/cluster/ClusterWorkflowEngine.ts b/repos/effect/packages/effect/src/cluster/ClusterWorkflowEngine.ts index 357d061842..8e0c3be7bf 100644 --- a/repos/effect/packages/effect/src/cluster/ClusterWorkflowEngine.ts +++ b/repos/effect/packages/effect/src/cluster/ClusterWorkflowEngine.ts @@ -15,7 +15,6 @@ import * as Effect from "../Effect.ts" import * as Exit from "../Exit.ts" import * as Fiber from "../Fiber.ts" import * as Headers from "../http/Headers.ts" -import * as Latch from "../Latch.ts" import * as Layer from "../Layer.ts" import * as Option from "../Option.ts" import * as PrimaryKey from "../PrimaryKey.ts" @@ -132,7 +131,6 @@ export const make = Effect.gen(function*() { readonly context: Context.Context }>() const interruptedActivities = new Set() - const activityLatches = new Map() const deferredState = WorkflowEngine.makeDeferredState() // Rebuilds share an activation; overlapping activations have separate results. // Weak keys do not retain scopes, but contexts captured by clients, activities, @@ -284,7 +282,7 @@ export const make = Effect.gen(function*() { yield* storage.clearAddress(clockAddress) }) - const resume = Effect.fnUntraced(function*(workflow: Workflow.Any, executionId: string) { + const resume = Effect.fnUntraced(function*(workflow: Workflow.Any, executionId: string, mode: WakeMode) { const maybeReply = yield* requestReply({ workflow, entityType: `Workflow/${workflow._tag}`, @@ -293,12 +291,11 @@ export const make = Effect.gen(function*() { id: "" }) - const maybeSuspended = Option.filter( - maybeReply, - (reply) => reply.exit._tag === "Success" && reply.exit.value._tag === "Suspended" - ) + const maybeSuspended = Option.filter(maybeReply, isSuspendedReply) if (Option.isNone(maybeSuspended)) return + // Replies without `failed` retain automatic wakes for compatibility. + if (mode === "automatic" && isFailedReply(maybeSuspended.value)) return if ( !(yield* sharding.reset( Snowflake.Snowflake(maybeSuspended.value.requestId), @@ -310,6 +307,15 @@ export const make = Effect.gen(function*() { yield* sharding.pollStorage }) + // Activations load a persisted interrupt when they start, so the per-call + // check reads only memory. + const interruptPending = (instance: WorkflowEngine.WorkflowInstance["Service"]) => + Effect.map(Effect.serviceOption(CurrentActivationScope), (activation) => { + const pending = Option.isSome(activation) ? pendingByActivation.get(activation.value) : undefined + return pending?.workflowName === instance.workflow._tag && pending.executionId === instance.executionId && + pending.results.has(InterruptSignal.name) + }) + const sendResumeParent = Effect.fnUntraced(function*(options: { readonly workflowName: string readonly executionId: string @@ -330,10 +336,14 @@ export const make = Effect.gen(function*() { yield* sharding.reset(requestId.value) }, Effect.scoped) - // A child or deferred may complete while a run is still unwinding. Subscribe - // to the run's reply before reading storage so the wake cannot fall between - // the run's last read and its suspended reply. - const waitForRunReply = Effect.fnUntraced(function*(workflow: Workflow.Any, request: Entity.Request) { + // Subscribe to the run's next reply before reading storage, so a reply + // cannot fall between the read and the subscription. Returns `true` when the + // stored reply already settles the wait, `false` when a new reply arrived. + const awaitRunReply = Effect.fnUntraced(function*( + workflow: Workflow.Any, + request: Envelope.Request, + isSettled: (reply: WithExitEncoded>) => boolean + ) { const waiter = yield* storage.registerReplyHandler( new Message.OutgoingRequest({ envelope: request, @@ -345,12 +355,45 @@ export const make = Effect.gen(function*() { }) ).pipe(Effect.forkScoped({ startImmediately: true })) const reply = yield* replyForRequestId(request.requestId) - if (Option.isSome(reply)) return - yield* Fiber.join(waiter).pipe( + if (Option.isSome(reply) && isSettled(reply.value)) return true + yield* Fiber.join(waiter) + return false + }, Effect.scoped) + + // A child or deferred may complete while a run is still unwinding. Wait for + // the run's reply so the wake cannot fall between the run's last read and + // its suspended reply. + const waitForRunReply = (workflow: Workflow.Any, request: Entity.Request) => + awaitRunReply(workflow, request, () => true).pipe( + Effect.asVoid, Effect.catchTag("EntityNotAssignedToRunner", () => ClusterAbandon.interrupt), Effect.catchCause((cause) => ClusterAbandon.isCause(cause) ? ClusterAbandon.interrupt : Effect.failCause(cause)) ) - }, Effect.scoped) + + // Wake an external caller once its run publishes a reply other than + // `Suspended`. Replies are only observed on the runner that saves them, so + // callers on other runners, and any failure here, leave delivery to the + // caller's retry schedule. + const awaitComplete = (workflow: Workflow.Any, executionId: string) => + Effect.gen(function*() { + const address = entityAddressFor({ workflow, entityType: `Workflow/${workflow._tag}`, executionId }) + if (!sharding.hasShardId(address.shardId)) return yield* Effect.never + const requestId = yield* storage.requestIdForPrimaryKey({ address, tag: "run", id: "" }) + if (Option.isNone(requestId)) return yield* Effect.never + const request = Envelope.makeRequest({ + requestId: requestId.value, + address, + tag: "run", + payload: {}, + headers: Headers.empty + }) + // A replay that suspends again re-arms the wait, so it does not spend a + // step of the caller's retry schedule. + let settled = false + while (!settled) { + settled = yield* awaitRunReply(workflow, request, (reply) => !isSuspendedReply(reply)) + } + }).pipe(Effect.catchCause(() => Effect.never)) const interrupt = Effect.fnUntraced( function*(workflow: Workflow.Any, executionId: string) { @@ -369,7 +412,7 @@ export const make = Effect.gen(function*() { const nonSuspendedReply = Option.filter( reply, - (reply) => reply.exit._tag !== "Success" || reply.exit.value._tag !== "Suspended" + (reply) => !isSuspendedReply(reply) ) if (Option.isSome(nonSuspendedReply)) { return Option.none() @@ -404,7 +447,25 @@ export const make = Effect.gen(function*() { const activation = yield* CurrentActivationScope let pending = pendingByActivation.get(activation) if (!pending) { - pending = { workflowName: workflow._tag, executionId, results: new Map() } + const results = new Map>() + // A new owner must see an interrupt persisted before it took over. + // Publish the cache only once loaded, so a retried build repeats + // a failed lookup. + const interrupt = yield* Effect.orDie(requestReply({ + workflow, + entityType: `Workflow/${workflow._tag}`, + executionId, + tag: "deferred", + id: InterruptSignal.name + })) + if (Option.isSome(interrupt)) { + const decoded = decodeDeferredWithExit(interrupt.value as any) + results.set( + InterruptSignal.name, + (decoded.exit._tag === "Success" ? decoded.exit.value : decoded.exit) as Exit.Exit + ) + } + pending = { workflowName: workflow._tag, executionId, results } pendingByActivation.set(activation, pending) } // Retain awaited names through reply persistence, including suspension. @@ -412,25 +473,30 @@ export const make = Effect.gen(function*() { let currentRun: { readonly request: Entity.Request readonly instance: WorkflowEngine.WorkflowInstance["Service"] + // Activity awaits must wake the run after suspension without preempting it. + readonly activityAwaits: Map } | undefined // Concurrent wakes share one wait for the current run to publish its reply. + // Explicit wakes cannot be dropped: operator resume bypasses the gate; + // InterruptSignal enters it only on a fresh entity, with no run to wait for. const resumeGate = Semaphore.makeUnsafe(1) - const resumeCurrentRun = Effect.suspend(() => - resumeGate.withPermitsIfAvailable(1)( - currentRun ? waitForRunReply(workflow, currentRun.request) : Effect.void + const resumeCurrentRun = (mode: WakeMode) => + Effect.suspend(() => + resumeGate.withPermitsIfAvailable(1)( + currentRun ? waitForRunReply(workflow, currentRun.request) : Effect.void + ) + ).pipe( + // Release the gate before reset can start another run, so later + // completions can wake that replay. + Effect.flatMap((waited) => Option.isSome(waited) ? resume(workflow, executionId, mode) : Effect.void), + ensureSuccess ) - ).pipe( - // Release the gate before reset can start another run, so later - // completions can wake that replay. - Effect.flatMap((waited) => Option.isSome(waited) ? resume(workflow, executionId) : Effect.void), - ensureSuccess - ) return { run: (request: Entity.Request) => { const instance = WorkflowEngine.WorkflowInstance.initial(workflow, executionId) - currentRun = { request, instance } + currentRun = { request, instance, activityAwaits: new Map() } const parent = (request.payload as any)[payloadParentKey] as - | { workflowName: string; executionId: string } + | { workflowName: string; executionId: string; detached?: boolean } | undefined return execute(workflow.payloadSchema.make(request.payload) as object, executionId).pipe( Effect.onExit((exit) => { @@ -447,7 +513,9 @@ export const make = Effect.gen(function*() { !instance.abandoned && !(suspendOnFailure && exit._tag === "Failure") ) { - return parent ? ensureSuccess(sendResumeParent(parent, executionId)) : Effect.void + return parent && !parent.detached + ? ensureSuccess(sendResumeParent(parent, executionId)) + : Effect.void } return engine.deferredResult(InterruptSignal).pipe( Effect.flatMap((maybeExit) => { @@ -474,25 +542,23 @@ export const make = Effect.gen(function*() { activity(request: Entity.Request) { const payload = request.payload as { name: string; attempt: number } const activityId = `${executionId}/${payload.name}` - const instance = WorkflowEngine.WorkflowInstance.initial(workflow, executionId) + const instance = WorkflowEngine.WorkflowInstance.initial(workflow, executionId, { + awaitedDeferreds: currentRun?.activityAwaits + }) interruptedActivities.delete(activityId) - return Effect.gen(function*() { - let entry = activities.get(activityId) - while (!entry) { - const latch = Latch.makeUnsafe() - activityLatches.set(activityId, latch) - yield* latch.await - entry = activities.get(activityId) - } - const context = entry.context.pipe( - Context.add(WorkflowEngine.WorkflowInstance, instance), - Context.add(CurrentActivationScope, activation), - Context.add(Activity.CurrentAttempt, payload.attempt) - ) - return yield* entry.activity.executeEncoded.pipe( - Effect.provideContext(context) - ) - }).pipe( + const entry = activities.get(activityId) + if (!entry) { + // Replay may never register a losing race activity. Answer it + // without waiting; a later registration can reset this reply. + return Effect.succeed(new Workflow.Suspended({})).pipe(Rpc.wrap({ fork: true })) + } + const context = entry.context.pipe( + Context.add(WorkflowEngine.WorkflowInstance, instance), + Context.add(CurrentActivationScope, activation), + Context.add(Activity.CurrentAttempt, payload.attempt) + ) + return entry.activity.executeEncoded.pipe( + Effect.provideContext(context), Workflow.intoResult, Effect.catchCause((cause) => { // we only want to store interrupts as suspends when the @@ -518,18 +584,24 @@ export const make = Effect.gen(function*() { deferred: (request: Entity.Request) => { const payload = request.payload as any pending.results.set(payload.name, payload.exit) + const mode: WakeMode = payload.name === InterruptSignal.name ? "explicit" : "automatic" // Await registers before reading the cache. If this run has not // registered yet, a later await will see the result just stored. // Check when the wake runs and skip preemption too: interrupting // a later await would require waiting for its reply before reset. // A run completing its own deferred also reads it from the cache - // when it awaits later, so that completion never wakes the run. + // when it awaits later, unless an activity is already parked on it. const wake = Effect.suspend(() => currentRun && !currentRun.instance.awaitedDeferreds.has(payload.name) - ? currentRun.instance.completedDeferreds.has(payload.name) + ? currentRun.activityAwaits.has(payload.name) + // Hold an activity wake until the run has published its reply. + ? resumeCurrentRun(mode) + : currentRun.instance.completedDeferreds.has(payload.name) ? Effect.void - : ensureSuccess(resume(workflow, executionId)) - : deferredState.deferredDone(executionId, payload.name).pipe(Effect.andThen(resumeCurrentRun)) + : ensureSuccess(resume(workflow, executionId, mode)) + : deferredState.deferredDone(executionId, payload.name).pipe( + Effect.andThen(resumeCurrentRun(mode)) + ) ) // An asynchronous reply releases the RPC concurrency permit while // the wake waits; the pending request still occupies mailbox capacity. @@ -544,7 +616,7 @@ export const make = Effect.gen(function*() { ) }, - resume: () => resumeCurrentRun.pipe(Rpc.wrap({ fork: true, uninterruptible: true })) + resume: () => resumeCurrentRun("automatic").pipe(Rpc.wrap({ fork: true, uninterruptible: true })) } }), // Alongside the run, let deferred handlers briefly acquire a permit to @@ -561,7 +633,7 @@ export const make = Effect.gen(function*() { ).pipe(Effect.andThen(registration)) }), - execute: (workflow, { discard, executionId, parent, payload }) => { + execute: (workflow, { detached, discard, executionId, parent, payload }) => { ensureEntity(workflow) return RcMap.get(clients, workflow._tag).pipe( Effect.flatMap((make) => @@ -569,7 +641,10 @@ export const make = Effect.gen(function*() { parent ? { ...payload, - [payloadParentKey]: { workflowName: parent.workflow._tag, executionId: parent.executionId } + // A detached child keeps its parent for observability only. + [payloadParentKey]: detached + ? { workflowName: parent.workflow._tag, executionId: parent.executionId, detached: true } + : { workflowName: parent.workflow._tag, executionId: parent.executionId } } : payload, { discard } @@ -621,7 +696,9 @@ export const make = Effect.gen(function*() { )) }), - resume: (workflow, executionId) => ensureSuccess(resume(workflow, executionId)), + resume: (workflow, executionId) => ensureSuccess(resume(workflow, executionId, "explicit")), + + awaitComplete, activityExecute: Effect.fnUntraced( function*(activity, attempt) { @@ -629,15 +706,25 @@ export const make = Effect.gen(function*() { const instance = Context.get(services, WorkflowEngine.WorkflowInstance) yield* Effect.annotateCurrentSpan("executionId", instance.executionId) const activityId = `${instance.executionId}/${activity.name}` + // A pending interrupt replays only to rebuild compensations, so it must + // not run new activities. Finalizers run once `interrupted` is set. + if (!instance.interrupted && (yield* interruptPending(instance))) { + const reply = yield* Effect.orDie(requestReply({ + workflow: instance.workflow, + entityType: `Workflow/${instance.workflow._tag}`, + executionId: instance.executionId, + tag: "activity", + id: activityPrimaryKey(activity.name, attempt) + })) + // Suspend so `onExit` applies the interrupt to the run. + if (Option.isNone(reply) || isSuspendedReply(reply.value)) { + return new Workflow.Suspended({}) + } + } const client = (yield* RcMap.get(clientsPartial, instance.workflow._tag))(instance.executionId) while (true) { if (!activities.has(activityId)) { activities.set(activityId, { activity, context: services }) - const latch = activityLatches.get(activityId) - if (latch) { - yield* latch.open - activityLatches.delete(activityId) - } } const result = yield* Effect.orDie( client.activity({ @@ -820,6 +907,14 @@ const DeferredRpc = Rpc.make("deferred", { .annotate(ClusterSchema.Persisted, true) .annotate(ClusterSchema.Uninterruptible, true) +type WakeMode = "explicit" | "automatic" + +const isSuspendedReply = (reply: WithExitEncoded>) => + reply.exit._tag === "Success" && reply.exit.value._tag === "Suspended" + +const isFailedReply = (reply: WithExitEncoded>) => + reply.exit._tag === "Success" && reply.exit.value._tag === "Suspended" && reply.exit.value.failed === true + const decodeDeferredWithExit = Schema.decodeSync(Schema.toCodecJson(Reply.WithExit.schema(DeferredRpc))) const ResumeRpc = Rpc.make("resume", { @@ -847,7 +942,8 @@ const makeWorkflowEntity = (workflow: Workflow.Any) => ...workflow.payloadSchema.fields, [payloadParentKey]: Schema.optional(Schema.Struct({ workflowName: Schema.String, - executionId: Schema.String + executionId: Schema.String, + detached: Schema.optional(Schema.Boolean) })) }, primaryKey: () => "", diff --git a/repos/effect/packages/effect/src/cluster/MessageStorage.ts b/repos/effect/packages/effect/src/cluster/MessageStorage.ts index 3822e36126..b1876c5c0f 100644 --- a/repos/effect/packages/effect/src/cluster/MessageStorage.ts +++ b/repos/effect/packages/effect/src/cluster/MessageStorage.ts @@ -207,7 +207,12 @@ export class MessageStorage extends Context.Service Effect.Effect /** - * Used to wrap requests with transactions. + * Wraps requests in storage transactions. + * + * `WithExit` replies saved in a transaction notify callers after the outermost + * commit; stream chunks notify immediately. Replies saved in a failed + * transaction must be discarded. The wrapper may fail only with the wrapped + * effect's own failure or a defect. */ readonly withTransaction: ( effect: Effect.Effect @@ -513,6 +518,10 @@ export type EncodedRepliesOptions = { readonly cursor: Option.Option } +const TransactionNotifications = Context.Reference< + Array> | undefined +>("effect/cluster/MessageStorage/TransactionNotifications", { defaultValue: () => undefined }) + /** * Wraps a concrete message storage implementation with reply-handler management. * @@ -555,6 +564,20 @@ export const make = ( const replyHandlersShard = new Map>() return MessageStorage.of({ ...storage, + // Nested transactions defer notifications to the outermost commit. + withTransaction: (effect) => + TransactionNotifications.use((outer) => { + const notifications: Array> = [] + return storage.withTransaction(Effect.provideService(effect, TransactionNotifications, notifications)).pipe( + Effect.tap(() => + outer + ? Effect.sync(() => { + outer.push(...notifications) + }) + : Effect.orDie(Effect.forEach(notifications, identity, { discard: true })) + ) + ) + }), registerReplyHandler: (message) => { const requestId = message.envelope.requestId return Effect.callback((resume) => { @@ -619,20 +642,28 @@ export const make = ( saveReply(reply) { const requestId = reply.reply.requestId return Effect.flatMap(storage.saveReply(reply), (persisted) => { - const handlers = replyHandlers.get(requestId) - if (!handlers) { - return Effect.void - } else if (persisted.reply._tag === "WithExit") { - replyHandlers.delete(requestId) - for (let i = 0; i < handlers.length; i++) { - const handler = handlers[i] - handler.shardSet.delete(handler) - handler.resume(Effect.void) + const notify = Effect.suspend(() => { + const handlers = replyHandlers.get(requestId) + if (!handlers) { + return Effect.void + } else if (persisted.reply._tag === "WithExit") { + replyHandlers.delete(requestId) + for (let i = 0; i < handlers.length; i++) { + const handler = handlers[i] + handler.shardSet.delete(handler) + handler.resume(Effect.void) + } } - } - return handlers.length === 1 - ? handlers[0].respond(persisted) - : Effect.forEach(handlers, (handler) => handler.respond(persisted)) + return handlers.length === 1 + ? handlers[0].respond(persisted) + : Effect.forEach(handlers, (handler) => handler.respond(persisted), { discard: true }) + }) + if (persisted.reply._tag !== "WithExit") return notify + return TransactionNotifications.use((notifications) => + notifications === undefined ? notify : Effect.sync(() => { + notifications.push(notify) + }) + ) }) } }) @@ -1055,8 +1086,8 @@ export class MemoryDriver extends Context.Service()("effect/cluste journal.push(envelope) return SaveResultEncoded.Success() }), - saveReply: (reply_) => - Effect.sync(() => { + saveReply: (reply_) => { + const save = Effect.sync(() => { const reply = JSON.parse(JSON.stringify(reply_)) as Reply.Encoded const entry = requests.get(reply.requestId) if (!entry || replyIds.has(reply.id)) return @@ -1067,7 +1098,18 @@ export class MemoryDriver extends Context.Service()("effect/cluste entry.replies.push(reply) replyIds.add(reply.id) replyLatch.openUnsafe() - }), + }) + // Memory has no transaction isolation. Publish terminal replies at the + // outer commit boundary, before their queued handler notifications, so + // reply readers cannot deliver a success that may still be rolled back. + return TransactionNotifications.use((notifications) => + reply_._tag === "WithExit" && notifications + ? Effect.sync(() => { + notifications.push(save) + }) + : save + ) + }, clearReplies: (id, options) => Effect.sync(() => { const entry = requests.get(String(id)) diff --git a/repos/effect/packages/effect/src/cluster/Runners.ts b/repos/effect/packages/effect/src/cluster/Runners.ts index f0c29d54ce..7872bcaee4 100644 --- a/repos/effect/packages/effect/src/cluster/Runners.ts +++ b/repos/effect/packages/effect/src/cluster/Runners.ts @@ -14,6 +14,7 @@ import * as Context from "../Context.ts" import * as Effect from "../Effect.ts" import * as Exit from "../Exit.ts" +import * as Fiber from "../Fiber.ts" import * as Latch from "../Latch.ts" import * as Layer from "../Layer.ts" import * as Option from "../Option.ts" @@ -247,72 +248,93 @@ export const make: ( type StorageRequestEntry = { readonly latch: Latch.Latch - doneLatch: Latch.Latch | undefined readonly messages: Set> + readonly pump: Fiber.Fiber replies: Array> } const storageRequests = new Map() const waitingStorageRequests = new Map>() - const replyFromStorage = Effect.fnUntraced( - function*(message: Message.OutgoingRequest) { - let entry = storageRequests.get(message.envelope.requestId) - if (entry) { - entry.messages.add(message) - entry.doneLatch ??= Latch.makeUnsafe(false) - return yield* entry.doneLatch.await - } else { - entry = { - latch: Latch.makeUnsafe(false), - doneLatch: undefined, - replies: [], - messages: new Set([message]) - } - storageRequests.set(message.envelope.requestId, entry) - } - while (true) { - // wait for the storage loop to notify us - entry.latch.closeUnsafe() - waitingStorageRequests.set(message.envelope.requestId, message) - storageLatch.openUnsafe() - yield* entry.latch.await - - // send the replies back - for (let i = 0; i < entry.replies.length; i++) { - const reply = entry.replies[i] - // we have reached the end - if (reply._tag === "WithExit") { - for (const message of entry.messages) { - yield* message.respond(reply) - } - entry.doneLatch?.openUnsafe() - return - } + // A reset request can register a replacement entry under the same id, which + // must survive the old entry's cleanup. + const removeStorageRequest = (requestId: Snowflake.Snowflake, entry: Omit) => { + if (storageRequests.get(requestId) !== entry) return + storageRequests.delete(requestId) + waitingStorageRequests.delete(requestId) + } - entry.latch.closeUnsafe() + // The pump is owned by the shared entry rather than the first caller, so any + // waiter can be interrupted without stopping delivery to the others. + const pumpReplies = Effect.fnUntraced(function*( + requestId: Snowflake.Snowflake, + entry: Omit + ) { + while (true) { + // wait for the storage loop to notify us + entry.latch.closeUnsafe() + const message = entry.messages.values().next().value + if (!message) return + waitingStorageRequests.set(requestId, message) + storageLatch.openUnsafe() + yield* entry.latch.await + + // send the replies back + for (let i = 0; i < entry.replies.length; i++) { + const reply = entry.replies[i] + // we have reached the end + if (reply._tag === "WithExit") { + // A reply can immediately reset and resend the same request. Do not + // let that sender attach to this completed entry. + removeStorageRequest(requestId, entry) for (const message of entry.messages) { yield* message.respond(reply) } - // wait for ack - yield* entry.latch.await + return } - entry.replies = [] + + entry.latch.closeUnsafe() + for (const message of entry.messages) { + yield* message.respond(reply) + } + // wait for ack + yield* entry.latch.await } - }, - (effect, message) => - Effect.ensuring( - effect, - Effect.sync(() => { - const entry = storageRequests.get(message.envelope.requestId) - if (!entry || entry.messages.size > 1) { - entry?.messages.delete(message) - return + entry.replies = [] + } + }) + + const replyFromStorage = (message: Message.OutgoingRequest) => + Effect.uninterruptibleMask((restore) => + Effect.gen(function*() { + const requestId = message.envelope.requestId + let entry = storageRequests.get(requestId) + if (!entry) { + const state = { + latch: Latch.makeUnsafe(false), + messages: new Set>(), + replies: [] as Array> } - storageRequests.delete(message.envelope.requestId) - waitingStorageRequests.delete(message.envelope.requestId) - }) - ) - ) + entry = Object.assign(state, { pump: yield* Effect.forkIn(pumpReplies(requestId, state), runnersScope) }) + storageRequests.set(requestId, entry) + } + const current = entry + current.messages.add(message) + return yield* restore(Fiber.join(current.pump)).pipe( + Effect.ensuring(Effect.suspend(() => { + current.messages.delete(message) + if (current.messages.size === 0) { + removeStorageRequest(requestId, current) + return Fiber.interrupt(current.pump) + } + // The storage loop decodes replies using the waiting message. + if (waitingStorageRequests.get(requestId) === message) { + waitingStorageRequests.set(requestId, current.messages.values().next().value!) + } + return Effect.void + })) + ) + }) + ) const storageLatch = Latch.makeUnsafe(false) if (storage !== MessageStorage.noop) { @@ -409,22 +431,28 @@ export const make: ( }) }, notifyLocal(options) { - return notifyWith(options.message, (message, duplicate) => { + return notifyWith(options.message, (message) => { if (options.discard || message._tag === "OutgoingEnvelope") { return Effect.catchTag( options.notify(Message.incomingLocalFromOutgoing(message)), "EntityNotAssignedToRunner", () => Effect.void ) - } else if (!duplicate && options.storageOnly !== true) { - return options.notify(Message.incomingLocalFromOutgoing(message)).pipe( - Effect.andThen(storage.registerReplyHandler(message)), - Effect.catchTag("EntityNotAssignedToRunner", () => replyFromStorage(message)) - ) } + // The request can be processed as soon as it is saved, so replies are + // always read back from storage. The local reply handler only wakes the + // storage loop, so streams do not have to wait for the next poll. + const readReplies = options.storageOnly + ? replyFromStorage(message) + : Effect.raceFirst( + replyFromStorage(message), + storage.registerReplyHandler( + new Message.OutgoingRequest({ ...message, respond: () => storageLatch.open }) + ).pipe(Effect.ignore, Effect.andThen(Effect.never)) + ) return options.notify(Message.incomingLocalFromOutgoing(message)).pipe( Effect.catchTag("EntityNotAssignedToRunner", () => Effect.void), - Effect.andThen(replyFromStorage(message)) + Effect.andThen(readReplies) ) }) } diff --git a/repos/effect/packages/effect/src/cluster/Sharding.ts b/repos/effect/packages/effect/src/cluster/Sharding.ts index 43b634c655..2e088dfd7b 100644 --- a/repos/effect/packages/effect/src/cluster/Sharding.ts +++ b/repos/effect/packages/effect/src/cluster/Sharding.ts @@ -277,6 +277,13 @@ const make = Effect.gen(function*() { // the active shards are the ones that we have acquired the lock for const acquiredShards = MutableHashSet.empty() const activeShardsLatch = yield* Latch.make(false) + // open once shutdown starts handing every shard off + const handoffLatch = Latch.makeUnsafe(false) + // open once the handoff has released every shard lock + const handedOffLatch = Latch.makeUnsafe(false) + // serializes runner registration with unregistration, so a registration + // in flight cannot re-advertise a runner that is shutting down + const withRegistrationLock = Semaphore.makeUnsafe(1).withPermits(1) const events = yield* PubSub.unbounded() const getRegistrationEvents: Stream.Stream = Stream.fromPubSub(events) @@ -295,6 +302,33 @@ const make = Effect.gen(function*() { return MutableHashSet.has(acquiredShards, address.shardId) } + function isAwaitingShardLock(shardId: ShardId): boolean { + return !MutableRef.get(isShutdown) && + MutableHashSet.has(selfShards, shardId) && + !MutableHashSet.has(acquiredShards, shardId) + } + + // Requests for a shard assigned to this runner wait for its lock, for at most + // `shardLockExpiration`, instead of bouncing while the previous owner drains. + // Each notification opens the current latch and replaces it, so a waiter that + // checked its shard before a notification cannot miss it. + let shardLocksChanged = Latch.makeUnsafe(false) + const notifyShardLockWaiters = Effect.suspend(() => { + const latch = shardLocksChanged + shardLocksChanged = Latch.makeUnsafe(false) + return latch.open + }) + const awaitShardLock = (shardId: ShardId): Effect.Effect => { + const loop: Effect.Effect = Effect.suspend(() => + isAwaitingShardLock(shardId) ? Effect.andThen(shardLocksChanged.await, loop) : Effect.void + ) + return Effect.suspend(() => + isAwaitingShardLock(shardId) + ? Effect.asVoid(Effect.timeoutOption(loop, config.shardLockExpiration)) + : Effect.void + ) + } + yield* Scope.addFinalizer( shardingScope, Effect.logDebug("Shutdown complete").pipe(Effect.annotateLogs({ @@ -310,6 +344,8 @@ const make = Effect.gen(function*() { // allow them to move to another runner. const releasingShards = MutableHashSet.empty() + // Hands every held shard off on shutdown, set when this is a runner + let handoff: Effect.Effect = Effect.void // Shards whose entities must be force interrupted and locks fully released // before normal reacquisition. const forceReleasingShards = MutableHashSet.empty() @@ -321,8 +357,37 @@ const make = Effect.gen(function*() { return Effect.ignore(runnerStorage.releaseAll(selfAddress)) }) + // Shard releases fork into a child scope that closes after the shutdown + // handoff, as forks into the closing sharding scope never run. + const releaseScope = yield* Scope.fork(shardingScope) + // Interrupt the shards' entities on every entity manager that is open + const forkInterruptShards = Effect.fnUntraced(function*(shardIds: Iterable, force: boolean) { + const fibers = Arr.empty>() + for (const shardId of shardIds) { + for (const state of entityManagers.values()) { + if (state.status === "closed") continue + fibers.push( + yield* Effect.forkIn(state.manager.interruptShard(shardId, { force }), releaseScope, { + startImmediately: true + }) + ) + } + } + return fibers + }) const releaseShardsMap = yield* FiberMap.make() let forcedShardReleaseRunning = false + // Called from the acquisition loop only, so no `acquire` is in flight + const checkHandedOff = () => { + if ( + handoffLatch.isOpen() && + MutableHashSet.size(acquiredShards) === 0 && + MutableHashSet.size(releasingShards) === 0 && + !forcedShardReleasePending() + ) { + handedOffLatch.openUnsafe() + } + } // Interrupt the shards' entities, wait for lock health, run the storage // release, then clear the shards' bookkeeping. const runShardRelease = Effect.fnUntraced(function*( @@ -330,14 +395,11 @@ const make = Effect.gen(function*() { force: boolean, release: Effect.Effect ) { - const fibers = Arr.empty>() - for (const shardId of shardIds) { - for (const state of entityManagers.values()) { - if (state.status === "closed") continue - fibers.push(yield* Effect.forkScoped(state.manager.interruptShard(shardId, { force }))) - } - } - yield* Fiber.joinAll(fibers) + yield* Fiber.joinAll(yield* forkInterruptShards(shardIds, force)) + // stop the singletons of shards that are no longer acquired, and wait + // for those on the released shards + yield* startSyncSingletons + yield* awaitStoppingSingletons(shardIds) yield* shardLocksHealthyLatch.await yield* release for (const shardId of shardIds) { @@ -351,6 +413,8 @@ const make = Effect.gen(function*() { interrupt: MutableRef.get(isShutdown) }) } + // let the acquisition loop check whether the handoff has finished + if (handoffLatch.isOpen()) activeShardsLatch.openUnsafe() }) const retryShardRelease = (annotations: { readonly fiber: string; readonly shardId?: ShardId }) => @@ -402,7 +466,7 @@ const make = Effect.gen(function*() { forcedShardReleaseRunning = false activeShardsLatch.openUnsafe() })), - Effect.forkIn(shardingScope), + Effect.forkIn(releaseScope), Effect.asVoid ) }) @@ -422,9 +486,11 @@ const make = Effect.gen(function*() { yield* activeShardsLatch.await activeShardsLatch.closeUnsafe() - // if a shard is no longer assigned to this runner, we release it + // if a shard is no longer assigned to this runner, or the runner is + // handing every shard off, we release it + const handingOff = handoffLatch.isOpen() for (const shardId of acquiredShards) { - if (MutableHashSet.has(selfShards, shardId)) continue + if (!handingOff && MutableHashSet.has(selfShards, shardId)) continue MutableHashSet.remove(acquiredShards, shardId) MutableHashSet.add(releasingShards, shardId) } @@ -433,6 +499,7 @@ const make = Effect.gen(function*() { yield* Effect.forkIn(syncSingletons, shardingScope) yield* releaseShards } + checkHandedOff() if (!shardLocksHealthyLatch.isOpen()) { continue @@ -444,6 +511,11 @@ const make = Effect.gen(function*() { continue } + // a runner that is shutting down takes no new shards + if (isShutdown.current) { + continue + } + // if a shard has been assigned to this runner, we acquire it const unacquiredShards = MutableHashSet.empty() for (const shardId of selfShards) { @@ -484,13 +556,15 @@ const make = Effect.gen(function*() { MutableHashSet.add(acquiredShards, shardId) } if (acquired.length > 0) { + yield* notifyShardLockWaiters yield* storageReadLatch.open yield* Effect.forkIn(syncSingletons, shardingScope) // update metrics ClusterMetrics.shards.updateUnsafe(BigInt(MutableHashSet.size(acquiredShards)), Context.empty()) } - yield* Effect.sleep(1000) + // the shutdown handoff releases the shards acquired here without waiting + yield* Effect.raceFirst(Effect.sleep(1000), handoffLatch.await) activeShardsLatch.openUnsafe() } }).pipe( @@ -519,19 +593,11 @@ const make = Effect.gen(function*() { activeShardsLatch.openUnsafe() return Effect.gen(function*() { + yield* notifyShardLockWaiters yield* Effect.logError("Shard lock storage is unhealthy", cause) yield* Effect.forkIn(syncSingletons, shardingScope, { startImmediately: true }) - for (const shardId of affectedShards) { - for (const state of entityManagers.values()) { - if (state.status === "closed") continue - yield* Effect.forkIn( - state.manager.interruptShard(shardId, { force: true }), - shardingScope, - { startImmediately: true } - ) - } - } + yield* forkInterruptShards(affectedShards, true) activeShardsLatch.openUnsafe() }) }) @@ -598,6 +664,18 @@ const make = Effect.gen(function*() { Effect.forever, Effect.forkIn(shardingScope) ) + + // Release every held shard through the per-shard path. Their entities are + // forced to stop, so the handoff does not wait out graceful termination. + // This is best effort: the wait is bounded, and if it times out, the final + // `releaseAll` attempts to release the remaining locks. + handoff = Effect.suspend(() => { + if (handoffLatch.openUnsafe()) activeShardsLatch.openUnsafe() + return forkInterruptShards([...acquiredShards, ...releasingShards], true) + }).pipe( + Effect.andThen(Effect.timeoutOption(handedOffLatch.await, shardLockInterval)), + Effect.asVoid + ) } // --- Storage inbox --- @@ -614,6 +692,12 @@ const make = Effect.gen(function*() { const storageReadLatch = yield* Latch.make(true) const openStorageReadLatch = constant(Effect.asVoid(storageReadLatch.open)) + type PendingNotification = { + resume: (_: Effect.Effect) => void + readonly message: Message.IncomingRequest + } + const pendingNotifications = new Map() + const storageReadLock = Semaphore.makeUnsafe(1) const withStorageReadLock = storageReadLock.withPermits(1) @@ -647,7 +731,7 @@ const make = Effect.gen(function*() { if (storageEnabled && initialRunnerAddress) { const selfAddress = initialRunnerAddress - yield* Effect.gen(function*() { + const storageReadLoop = Effect.gen(function*() { yield* Effect.logDebug("Starting") yield* Effect.addFinalizer(() => Effect.logDebug("Shutting down")) @@ -904,8 +988,7 @@ const make = Effect.gen(function*() { module: "effect/cluster/Sharding", fiber: "Storage read loop", runner: selfAddress - }), - Effect.forkIn(shardingScope) + }) ) // open the storage latch every poll interval @@ -1032,20 +1115,28 @@ const make = Effect.gen(function*() { ), Effect.forkIn(shardingScope) ) + + // fork after the state the loop reads has been initialized + yield* Effect.forkIn(storageReadLoop, shardingScope) } // --- Sending messages --- - const sendLocal = | Message.Incoming>(message: M) => - Effect.suspend(function loop(): Effect.Effect< + const sendLocal = | Message.Incoming>(message: M) => { + const address = message.envelope.address + const isRequest = message._tag === "IncomingRequest" || message._tag === "OutgoingRequest" + const send = Effect.suspend(function loop(): Effect.Effect< void, | EntityNotAssignedToRunner | MailboxFull | AlreadyProcessingMessage | (M extends Message.Incoming ? never : PersistenceError) > { - const address = message.envelope.address - if (!isEntityOnLocalShards(address)) { + if ( + !isEntityOnLocalShards(address) && + // Entities draining from a released shard still accept interrupts and acks + (isRequest || !MutableHashSet.has(releasingShards, address.shardId)) + ) { return Effect.fail(new EntityNotAssignedToRunner({ address })) } const state = entityManagers.get(address.entityType) @@ -1064,12 +1155,9 @@ const make = Effect.gen(function*() { simulateRemoteSerialization: config.simulateRemoteSerialization }) as any }) - - type PendingNotification = { - resume: (_: Effect.Effect) => void - readonly message: Message.IncomingRequest + return isRequest ? Effect.andThen(awaitShardLock(address.shardId), send) : send } - const pendingNotifications = new Map() + const notifyLocal = | Message.Incoming>( message: M, discard: boolean, @@ -1087,7 +1175,7 @@ const make = Effect.gen(function*() { const state = entityManagers.get(address.entityType) if (!state) { return Effect.flatMap(waitForEntityManager(address.entityType), loop) - } else if (state.status === "closed" || !isEntityOnLocalShards(address)) { + } else if (state.status === "closed") { return Effect.fail(new EntityNotAssignedToRunner({ address })) } @@ -1129,7 +1217,10 @@ const make = Effect.gen(function*() { function sendOutgoing( message: Message.Outgoing, discard: boolean, - retries?: number + retries?: number, + // The runner serving the request, for its interrupts and acks. Later + // attempts fall back to the current shard assignment. + runner?: RunnerAddress ): Effect.Effect< void, MailboxFull | AlreadyProcessingMessage | PersistenceError | EntityNotAssignedToRunner @@ -1172,7 +1263,9 @@ const make = Effect.gen(function*() { if (shouldFail && MutableRef.get(isShutdown)) { return Effect.fail(new EntityNotAssignedToRunner({ address })) } - const maybeRunner = MutableHashMap.get(shardAssignments, address.shardId) + const maybeRunner = runner !== undefined + ? Option.some(runner) + : MutableHashMap.get(shardAssignments, address.shardId) const runnerIsLocal = Option.isSome(maybeRunner) && isLocalRunner(maybeRunner.value) if (isPersisted) { return runnerIsLocal @@ -1180,6 +1273,9 @@ const make = Effect.gen(function*() { : runnersService.notify({ address: maybeRunner, message, discard }) } else if (Option.isNone(maybeRunner)) { return Effect.fail(new EntityNotAssignedToRunner({ address })) + } else if (message._tag === "OutgoingRequest") { + const entry = clientRequests.get(message.envelope.requestId) + if (entry) entry.runner = maybeRunner.value } return runnerIsLocal ? sendLocal(message) @@ -1250,9 +1346,12 @@ const make = Effect.gen(function*() { while (true) { // Ensure the current runner is registered if (selfRunner && !isShutdown.current && !MutableHashMap.has(allRunners, selfRunner)) { - yield* Effect.logDebug("Registering runner", selfRunner) - const machineId = yield* withTimeout(runnerStorage.register(selfRunner, true)) - yield* snowflakeGen.setMachineId(machineId) + yield* withRegistrationLock(Effect.gen(function*() { + if (isShutdown.current) return + yield* Effect.logDebug("Registering runner", selfRunner) + const machineId = yield* withTimeout(runnerStorage.register(selfRunner, true)) + yield* snowflakeGen.setMachineId(machineId) + })) } const runners = yield* withTimeout(runnerStorage.getRunners) @@ -1324,6 +1423,7 @@ const make = Effect.gen(function*() { }) yield* Effect.logDebug("New shard assignments", selfShards) activeShardsLatch.openUnsafe() + yield* notifyShardLockWaiters // update metrics if (selfRunner) { @@ -1361,6 +1461,8 @@ const make = Effect.gen(function*() { readonly context: Context.Context readonly message: Message.OutgoingRequest lastChunkId?: Snowflake.Snowflake + // the runner a volatile request was last sent to + runner?: RunnerAddress } const clientRequests = new Map() @@ -1445,7 +1547,9 @@ const make = Effect.gen(function*() { }), rpc: entry.rpc }), - false + false, + undefined, + entry.runner ) } case "Interrupt": { @@ -1476,7 +1580,8 @@ const make = Effect.gen(function*() { rpc: entry.rpc }), false, - 3 + 3, + entry.runner )) } } @@ -1569,6 +1674,47 @@ const make = Effect.gen(function*() { const singletonFibers = yield* FiberMap.make() const withSingletonLock = Semaphore.makeUnsafe(1).withPermits(1) + // Singletons that are stopping. They count as running, so they are not + // restarted, and shard releases wait for them. Their teardown is awaited + // without the singleton lock, as it can register or stop other singletons. + const stoppingSingletons = MutableHashMap.empty>() + const isSingletonRegistered = (address: SingletonAddress) => { + const map = singletons.get(address.shardId) + return map !== undefined && MutableHashMap.has(map, address) + } + + // Called with the singleton lock held. Starts stopping the singleton and + // returns the wait for its teardown, to run without the lock. + const stopSingletonUnsafe = (address: SingletonAddress, activeTeardown: boolean): Effect.Effect => { + const stopping = MutableHashMap.get(stoppingSingletons, address) + if (Option.isSome(stopping)) return Fiber.join(stopping.value) + const fiber = FiberMap.getUnsafe(singletonFibers, address) + if (Option.isNone(fiber)) return Effect.void + const interrupt = Fiber.interrupt(fiber.value) + const stop = Effect.runForkWith(services)( + activeTeardown ? ActiveTeardown.aroundShard(address.shardId, interrupt) : interrupt + ) + MutableHashMap.set(stoppingSingletons, address, stop) + stop.addObserver(() => { + MutableHashMap.remove(stoppingSingletons, address) + // a registration made while the previous singleton was stopping + if (isSingletonRegistered(address)) runFork(syncSingletons) + }) + return Fiber.join(stop) + } + + // Waits for the singletons of the given shards that are still stopping + const awaitStoppingSingletons = (shardIds: ReadonlyArray) => + Effect.suspend(() => { + const stops = Arr.empty>() + MutableHashMap.forEach(stoppingSingletons, (stop, address) => { + if (shardIds.some((shardId) => Equal.equals(shardId, address.shardId))) { + stops.push(stop) + } + }) + return Fiber.joinAll(stops) + }) + const registerSingleton: Sharding["Service"]["registerSingleton"] = Effect.fnUntraced( function*(name, run, options) { const shardGroup = options?.shardGroup ?? "default" @@ -1599,32 +1745,38 @@ const make = Effect.gen(function*() { yield* PubSub.publish(events, SingletonRegistered({ address })) - // start if we are on the right shard - if (MutableHashSet.has(acquiredShards, address.shardId)) { + // start if we are on the right shard, unless a previous registration of + // this singleton is still stopping + if ( + MutableHashSet.has(acquiredShards, address.shardId) && + !MutableHashMap.has(stoppingSingletons, address) + ) { yield* Effect.logDebug("Starting singleton", address) yield* FiberMap.run(singletonFibers, address, wrappedRun) } - yield* Effect.addFinalizer(() => { - const map = singletons.get(address.shardId)! - MutableHashMap.remove(map, address) - return FiberMap.remove(singletonFibers, address) - }) + yield* Effect.addFinalizer(() => + withSingletonLock(Effect.sync(() => { + MutableHashMap.remove(singletons.get(address.shardId)!, address) + return stopSingletonUnsafe(address, false) + })).pipe(Effect.flatten) + ) }, withSingletonLock ) - const syncSingletons = withSingletonLock(Effect.gen(function*() { + // Starts and stops singletons to match the acquired shards, returning the + // waits for the stopped singletons + const startSyncSingletons = withSingletonLock(Effect.gen(function*() { + const stops = Arr.empty>() for (const [shardId, map] of singletons) { for (const [address, run] of map) { - const running = FiberMap.hasUnsafe(singletonFibers, address) + const stopping = MutableHashMap.has(stoppingSingletons, address) + const running = stopping || FiberMap.hasUnsafe(singletonFibers, address) const shouldBeRunning = MutableHashSet.has(acquiredShards, shardId) if (running && !shouldBeRunning) { - yield* Effect.logDebug("Stopping singleton", address) - yield* ActiveTeardown.aroundShard( - address.shardId, - FiberMap.remove(singletonFibers, address) - ) + if (!stopping) yield* Effect.logDebug("Stopping singleton", address) + stops.push(stopSingletonUnsafe(address, true)) } else if (!running && shouldBeRunning) { yield* Effect.logDebug("Starting singleton", address) yield* FiberMap.run(singletonFibers, address, run) @@ -1635,8 +1787,15 @@ const make = Effect.gen(function*() { BigInt(yield* FiberMap.size(singletonFibers)), Context.empty() ) + return stops })) + const syncSingletons: Effect.Effect = Effect.flatMap( + startSyncSingletons, + // wait for the stopped singletons without the lock + (stops) => Effect.all(stops, { discard: true }) + ) + // --- Entities --- const reaper = yield* EntityReaper @@ -1777,12 +1936,14 @@ const make = Effect.gen(function*() { if (isShutdown.current) return MutableRef.set(isShutdown, true) + yield* notifyShardLockWaiters if (selfRunner) { - yield* Effect.ignore(runnerStorage.unregister(selfRunner.address)) + yield* Effect.ignore(withRegistrationLock(runnerStorage.unregister(selfRunner.address))) } }) - yield* Scope.addFinalizerExit(shardingScope, shutdown) + // hand the shards off before the loops stop + yield* Scope.addFinalizerExit(shardingScope, (exit) => Effect.andThen(shutdown(exit), handoff)) const activeEntityCount = Effect.gen(function*() { let count = 0 diff --git a/repos/effect/packages/effect/src/cluster/SqlMessageStorage.ts b/repos/effect/packages/effect/src/cluster/SqlMessageStorage.ts index 8d7f9b2182..74fc016a37 100644 --- a/repos/effect/packages/effect/src/cluster/SqlMessageStorage.ts +++ b/repos/effect/packages/effect/src/cluster/SqlMessageStorage.ts @@ -8,6 +8,11 @@ * storage constructor, layers, migrations, optional table prefixes, and the row * mapping needed by encoded message storage. * + * `layer`, `layerWith`, `make`, and `makeEncoded` run the migrations before + * building the storage. To run migrations with a different connection, such as + * a schema owner in a deploy step, use `layerMigrations` there and + * `layerStorage` in the runtime. + * * Request deduplication keys that exceed the 255-character `message_id` * column are hashed with the `Crypto` service before they are written, so * composed keys of any length are supported; shorter keys are stored as @@ -24,7 +29,6 @@ import * as Hex from "../encoding/Hex.ts" import * as Layer from "../Layer.ts" import * as Option from "../Option.ts" import type * as PlatformError from "../PlatformError.ts" -import * as Schedule from "../Schedule.ts" import * as Migrator from "../sql/Migrator.ts" import * as SqlClient from "../sql/SqlClient.ts" import type { Row } from "../sql/SqlConnection.ts" @@ -73,19 +77,18 @@ export const makeEncoded: (options?: { MessageStorage.Encoded, never, SqlClient.SqlClient | Crypto.Crypto -> = Effect.fnUntraced(function*(options) { +> = (options) => Effect.andThen(runMessageMigrations(options), makeEncodedStorage(options)) + +const makeEncodedStorage = Effect.fnUntraced(function*( + options: { + readonly prefix?: string | undefined + } | undefined +) { const sql = (yield* SqlClient.SqlClient).withoutTransforms() const crypto = yield* Crypto.Crypto const prefix = options?.prefix ?? "cluster" const table = (name: string) => `${prefix}_${name}` - yield* Effect.orDie( - Migrator.make({})({ - loader: migrations(options), - table: table("migrations") - }) - ) - const messageKindAckChunk = sql.literal(String(messageKind.AckChunk)) const messageKindInterrupt = sql.literal(String(messageKind.Interrupt)) const replyKindWithExit = sql.literal(String(replyKind.WithExit)) @@ -810,69 +813,27 @@ export const make: (options?: { > = (options) => Effect.flatMap(makeEncoded(options), MessageStorage.makeEncoded) /** - * Layer that provides SQL-backed `MessageStorage` using the default table prefix - * and the default snowflake generator. - * - * **When to use** - * - * Use when a cluster should persist mailbox messages and replies in SQL using - * the default `cluster` table prefix and the standard snowflake generator. + * Migration loader for the SQL message storage tables. * * **Details** * - * The layer runs the SQL migrations through `make`, provides `MessageStorage`, - * and supplies `Snowflake.layerGenerator` internally. Callers still provide - * `SqlClient`, `ShardingConfig`, and `Crypto.Crypto`, which is used to hash - * message deduplication keys that would overflow the fixed-width - * `message_id` column. - * - * **Gotchas** - * - * This layer always uses the `cluster` table prefix. Use `layerWith` before - * deployment if you need a different stable prefix, because changing prefixes - * later points the runtime at a different set of tables. - * - * @see {@link layerWith} for the same SQL storage layer with a custom table prefix - * @see {@link make} for the lower-level service constructor that uses an existing `Snowflake.Generator` + * History is recorded in `_migrations`; the default + * prefix is `cluster`. * * @stability unstable - * @category layers - * @since 4.0.0 - */ -export const layer: Layer.Layer< - MessageStorage.MessageStorage, - never, - SqlClient.SqlClient | ShardingConfig | Crypto.Crypto -> = Layer.effect(MessageStorage.MessageStorage, make()).pipe( - Layer.provide(Snowflake.layerGenerator) -) - -/** - * Layer that provides SQL-backed `MessageStorage` using a custom table prefix. - * - * @stability unstable - * @category layers - * @since 4.0.0 + * @category migrations + * @since 4.1.0 */ -export const layerWith = (options: { - readonly prefix?: string | undefined -}): Layer.Layer => - Layer.effect(MessageStorage.MessageStorage, make(options)).pipe( - Layer.provide(Snowflake.layerGenerator) - ) - -// ------------------------------------------------------------------------------------------------- -// internal -// ------------------------------------------------------------------------------------------------- - -const migrations = (options?: { +export const migrations = (options?: { readonly prefix?: string | undefined -}) => { +}): Migrator.Loader => { const prefix = options?.prefix ?? "cluster" const table = (name: string) => `${prefix}_${name}` const messagesTable = table("messages") const repliesTable = table("replies") + // The migrator serializes PostgreSQL DDL. Propagate errors: retrying in an + // aborted transaction cannot succeed. return Migrator.fromRecord({ "0001_create_tables": Effect.gen(function*() { const sql = (yield* SqlClient.SqlClient).withoutTransforms() @@ -956,7 +917,7 @@ const migrations = (options?: { deliver_at BIGINT, UNIQUE (message_id) ) - `.pipe(Effect.ignore), + `, orElse: () => // sqlite sql` @@ -1016,18 +977,7 @@ const migrations = (options?: { CREATE INDEX IF NOT EXISTS ${sql(requestIdLookupIndex)} ON ${messagesTableSql} (request_id) ` - }).pipe( - sql.withTransaction, - Effect.tapDefect((error) => - Effect.annotateLogs(Effect.logDebug("Failed to create indexes", error), { - package: "@effect/cluster", - module: "SqlMessageStorage" - }) - ), - Effect.retry({ - schedule: Schedule.spaced(1000) - }) - ), + }), orElse: () => // sqlite Effect.all([ @@ -1121,17 +1071,7 @@ const migrations = (options?: { sql` CREATE INDEX IF NOT EXISTS ${sql(replyLookupIndex)} ON ${repliesTableSql} (request_id, kind, acked); - `.pipe( - Effect.tapDefect((error) => - Effect.annotateLogs(Effect.logDebug("Failed to create indexes", error), { - package: "@effect/cluster", - module: "SqlMessageStorage" - }) - ), - Effect.retry({ - schedule: Schedule.spaced(1000) - }) - ), + `, orElse: () => // sqlite sql` @@ -1180,6 +1120,100 @@ const migrations = (options?: { }) } +const runMessageMigrations = (options?: { + readonly prefix?: string | undefined +}): Effect.Effect => + Migrator.make({})({ + loader: migrations(options), + table: `${options?.prefix ?? "cluster"}_migrations` + }).pipe(Effect.asVoid, Effect.orDie) + +/** + * Runs the SQL message storage migrations without providing storage. + * + * **Details** + * + * Use an owner connection in a deploy step, then use `layerStorage` with a + * DML-only runtime connection. History is recorded in `_migrations`. + * Migration errors become defects. + * + * On PostgreSQL, use the role's `search_path` to select a schema. A + * schema-qualified prefix such as `app.cluster` produces an invalid index name. + * + * @stability unstable + * @category layers + * @since 4.1.0 + */ +export const layerMigrations = (options: { + readonly prefix?: string | undefined +}): Layer.Layer => Layer.effectDiscard(runMessageMigrations(options)) + +/** + * Provides SQL-backed `MessageStorage` without DDL or startup schema checks. + * + * **Details** + * + * Run `layerMigrations` separately before using this layer. + * This layer supplies `Snowflake.layerGenerator` internally. + * + * @stability unstable + * @category layers + * @since 4.1.0 + */ +export const layerStorage = (options: { + readonly prefix?: string | undefined +}): Layer.Layer => + Layer.effect( + MessageStorage.MessageStorage, + Effect.flatMap(makeEncodedStorage(options), MessageStorage.makeEncoded) + ).pipe( + Layer.provide(Snowflake.layerGenerator) + ) + +/** + * Provides SQL-backed `MessageStorage` with a custom table prefix, + * running migrations first. + * + * **Details** + * + * Migration errors become defects. Use `layerMigrations` and `layerStorage` + * to migrate separately. + * + * @stability unstable + * @category layers + * @since 4.0.0 + */ +export const layerWith = (options: { + readonly prefix?: string | undefined +}): Layer.Layer => + layerStorage(options).pipe( + Layer.provide(layerMigrations(options)) + ) + +/** + * Provides SQL-backed `MessageStorage` with the `cluster` table prefix, + * running migrations first and supplying `Snowflake.layerGenerator`. + * + * **Details** + * + * The connection needs DDL permissions. PostgreSQL takes an exclusive lock + * on the migration history table. Use `layerWith` for a custom prefix or + * `layerMigrations` and `layerStorage` to migrate separately. + * + * @stability unstable + * @category layers + * @since 4.0.0 + */ +export const layer: Layer.Layer< + MessageStorage.MessageStorage, + never, + SqlClient.SqlClient | ShardingConfig | Crypto.Crypto +> = layerWith({}) + +// ------------------------------------------------------------------------------------------------- +// internal +// ------------------------------------------------------------------------------------------------- + const messageKind = { "Request": 0, "AckChunk": 1, diff --git a/repos/effect/packages/effect/src/cluster/SqlRunnerStorage.ts b/repos/effect/packages/effect/src/cluster/SqlRunnerStorage.ts index d0c278e3f2..f5a807823d 100644 --- a/repos/effect/packages/effect/src/cluster/SqlRunnerStorage.ts +++ b/repos/effect/packages/effect/src/cluster/SqlRunnerStorage.ts @@ -3,10 +3,15 @@ * * The SQL-backed `RunnerStorage` records runners, health flags, machine ids, * and shard locks so multiple processes can coordinate which runner owns each - * shard. This module creates the required runner and lock tables, supports an + * shard. This module migrates the required runner and lock tables, supports an * optional table prefix, uses advisory locks for PostgreSQL and MySQL when * enabled, and provides constructors and layers for the storage service. * + * `layer`, `layerWith`, and `make` run the migrations before building the + * storage. To run migrations with a different connection, such as a schema + * owner in a deploy step, use `layerMigrations` there and `layerStorage` in the + * runtime. + * * @stability unstable * @since 4.0.0 */ @@ -17,6 +22,7 @@ import * as Effect from "../Effect.ts" import * as Fiber from "../Fiber.ts" import * as Layer from "../Layer.ts" import * as Scope from "../Scope.ts" +import * as Migrator from "../sql/Migrator.ts" import * as SqlClient from "../sql/SqlClient.ts" import type { Connection } from "../sql/SqlConnection.ts" import type { SqlError } from "../sql/SqlError.ts" @@ -41,36 +47,7 @@ const postgresLockNamespace = (prefix: string): number => { return hash | 0 } -/** - * Creates a SQL-backed `RunnerStorage` implementation for registered runners and - * shard locks, using the configured table prefix and advisory locks where - * supported and enabled. - * - * **When to use** - * - * Use to create a SQL-backed `RunnerStorage` value directly when building - * custom service or layer composition around the storage implementation. - * - * **Details** - * - * When `prefix` is omitted, `make` uses the `cluster` prefix, creating - * `cluster_runners` and `cluster_locks`. PostgreSQL and MySQL use advisory - * locks unless `ShardingConfig.shardLockDisableAdvisory` is enabled; other - * dialects use rows in the locks table. - * - * **Gotchas** - * - * Changing `prefix` changes both generated table names, so runners using - * different prefixes do not share registrations or shard locks. - * - * @see {@link layer} for the default SQL-backed storage layer - * @see {@link layerWith} for a SQL-backed storage layer with a custom table prefix - * - * @stability unstable - * @category constructors - * @since 4.0.0 - */ -export const make = Effect.fnUntraced(function*(options: { +const makeStorage = Effect.fnUntraced(function*(options: { readonly prefix?: string | undefined }) { const config = yield* ShardingConfig.ShardingConfig @@ -183,99 +160,9 @@ export const make = Effect.fnUntraced(function*(options: { const runnersTable = table("runners") const runnersTableSql = sql(runnersTable) - yield* sql.onDialectOrElse({ - mssql: () => - sql` - IF OBJECT_ID(N'${runnersTableSql}', N'U') IS NULL - CREATE TABLE ${runnersTableSql} ( - machine_id INT IDENTITY PRIMARY KEY, - address VARCHAR(255) NOT NULL, - runner TEXT NOT NULL, - healthy BIT NOT NULL DEFAULT 1, - last_heartbeat DATETIME NOT NULL DEFAULT GETDATE(), - UNIQUE(address) - ) - `, - mysql: () => - sql` - CREATE TABLE IF NOT EXISTS ${runnersTableSql} ( - machine_id INT AUTO_INCREMENT PRIMARY KEY, - address VARCHAR(255) NOT NULL, - runner TEXT NOT NULL, - healthy BOOLEAN NOT NULL DEFAULT TRUE, - last_heartbeat DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE(address) - ) - `, - pg: () => - sql` - CREATE TABLE IF NOT EXISTS ${runnersTableSql} ( - machine_id SERIAL PRIMARY KEY, - address VARCHAR(255) NOT NULL, - runner TEXT NOT NULL, - healthy BOOLEAN NOT NULL DEFAULT TRUE, - last_heartbeat TIMESTAMP NOT NULL DEFAULT NOW(), - UNIQUE(address) - ) - `, - orElse: () => - // sqlite - sql` - CREATE TABLE IF NOT EXISTS ${runnersTableSql} ( - machine_id INTEGER PRIMARY KEY AUTOINCREMENT, - address TEXT NOT NULL, - runner TEXT NOT NULL, - healthy INTEGER NOT NULL DEFAULT 1, - last_heartbeat DATETIME NOT NULL DEFAULT (CURRENT_TIMESTAMP), - UNIQUE(address) - ) - ` - }) - const locksTable = table("locks") const locksTableSql = sql(locksTable) - yield* sql.onDialectOrElse({ - mssql: () => - sql` - IF OBJECT_ID(N'${locksTableSql}', N'U') IS NULL - CREATE TABLE ${locksTableSql} ( - shard_id VARCHAR(50) PRIMARY KEY, - address VARCHAR(255) NOT NULL, - acquired_at DATETIME NOT NULL - ) - `, - mysql: () => - disableAdvisoryLocks ? - sql` - CREATE TABLE IF NOT EXISTS ${locksTableSql} ( - shard_id VARCHAR(50) PRIMARY KEY, - address VARCHAR(255) NOT NULL, - acquired_at DATETIME NOT NULL - ) - ` : - Effect.void, - pg: () => - disableAdvisoryLocks ? - sql` - CREATE TABLE IF NOT EXISTS ${locksTableSql} ( - shard_id VARCHAR(50) PRIMARY KEY, - address VARCHAR(255) NOT NULL, - acquired_at TIMESTAMP NOT NULL - ) - ` : - Effect.void, - orElse: () => - // sqlite - sql` - CREATE TABLE IF NOT EXISTS ${locksTableSql} ( - shard_id TEXT PRIMARY KEY, - address TEXT NOT NULL, - acquired_at DATETIME NOT NULL - ) - ` - }) - const sqlNowString = sql.onDialectOrElse({ pg: () => "NOW()", mysql: () => "NOW()", @@ -765,20 +652,213 @@ export const make = Effect.fnUntraced(function*(options: { }, withTracerDisabled) /** - * Layer that provides SQL-backed `RunnerStorage` using the default table prefix. + * Creates a SQL-backed `RunnerStorage` implementation for registered runners and + * shard locks, using the configured table prefix and advisory locks where + * supported and enabled. + * + * **When to use** + * + * Use to create a SQL-backed `RunnerStorage` value directly when building + * custom service or layer composition around the storage implementation. + * + * **Details** + * + * `make` first runs the runner storage migrations, so the connection needs + * permission to create tables. When `prefix` is omitted, `make` uses the + * `cluster` prefix, creating `cluster_runners`, `cluster_locks`, and the + * `cluster_runner_migrations` history table. PostgreSQL and MySQL use advisory + * locks unless `ShardingConfig.shardLockDisableAdvisory` is enabled; other + * dialects use rows in the locks table. + * + * **Gotchas** + * + * Changing `prefix` changes all generated table names, so runners using + * different prefixes do not share registrations or shard locks. + * + * @see {@link layer} for the default SQL-backed storage layer + * @see {@link layerWith} for a SQL-backed storage layer with a custom table prefix + * @see {@link layerStorage} for a storage layer that does not run migrations * * @stability unstable - * @category layers + * @category constructors * @since 4.0.0 */ -export const layer: Layer.Layer< - RunnerStorage.RunnerStorage, +export const make = (options: { + readonly prefix?: string | undefined +}): Effect.Effect< + RunnerStorage.RunnerStorage["Service"], SqlError, - SqlClient.SqlClient | ShardingConfig.ShardingConfig -> = Layer.effect(RunnerStorage.RunnerStorage)(make({})) + SqlClient.SqlClient | ShardingConfig.ShardingConfig | Scope.Scope +> => Effect.andThen(runRunnerMigrations(options), makeStorage(options)) /** - * Layer that provides SQL-backed `RunnerStorage` using a custom table prefix. + * Migration loader for the SQL runner storage tables. + * + * **Details** + * + * History is recorded in `_runner_migrations`; the default + * prefix is `cluster`. The locks table is created regardless of advisory lock settings. + * + * @stability unstable + * @category migrations + * @since 4.1.0 + */ +export const migrations = (options: { + readonly prefix?: string | undefined +}): Migrator.Loader => { + const prefix = options.prefix ?? "cluster" + const table = (name: string) => `${prefix}_${name}` + const runnersTable = table("runners") + const locksTable = table("locks") + + return Migrator.fromRecord({ + // Existing deployments may have these tables but no migration history. + "0001_create_tables": Effect.gen(function*() { + const sql = (yield* SqlClient.SqlClient).withoutTransforms() + const runnersTableSql = sql(runnersTable) + const locksTableSql = sql(locksTable) + + yield* sql.onDialectOrElse({ + mssql: () => + sql` + IF OBJECT_ID(N'${runnersTableSql}', N'U') IS NULL + CREATE TABLE ${runnersTableSql} ( + machine_id INT IDENTITY PRIMARY KEY, + address VARCHAR(255) NOT NULL, + runner TEXT NOT NULL, + healthy BIT NOT NULL DEFAULT 1, + last_heartbeat DATETIME NOT NULL DEFAULT GETDATE(), + UNIQUE(address) + ) + `, + mysql: () => + sql` + CREATE TABLE IF NOT EXISTS ${runnersTableSql} ( + machine_id INT AUTO_INCREMENT PRIMARY KEY, + address VARCHAR(255) NOT NULL, + runner TEXT NOT NULL, + healthy BOOLEAN NOT NULL DEFAULT TRUE, + last_heartbeat DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(address) + ) + `, + pg: () => + sql` + CREATE TABLE IF NOT EXISTS ${runnersTableSql} ( + machine_id SERIAL PRIMARY KEY, + address VARCHAR(255) NOT NULL, + runner TEXT NOT NULL, + healthy BOOLEAN NOT NULL DEFAULT TRUE, + last_heartbeat TIMESTAMP NOT NULL DEFAULT NOW(), + UNIQUE(address) + ) + `, + orElse: () => + // sqlite + sql` + CREATE TABLE IF NOT EXISTS ${runnersTableSql} ( + machine_id INTEGER PRIMARY KEY AUTOINCREMENT, + address TEXT NOT NULL, + runner TEXT NOT NULL, + healthy INTEGER NOT NULL DEFAULT 1, + last_heartbeat DATETIME NOT NULL DEFAULT (CURRENT_TIMESTAMP), + UNIQUE(address) + ) + ` + }) + + yield* sql.onDialectOrElse({ + mssql: () => + sql` + IF OBJECT_ID(N'${locksTableSql}', N'U') IS NULL + CREATE TABLE ${locksTableSql} ( + shard_id VARCHAR(50) PRIMARY KEY, + address VARCHAR(255) NOT NULL, + acquired_at DATETIME NOT NULL + ) + `, + mysql: () => + sql` + CREATE TABLE IF NOT EXISTS ${locksTableSql} ( + shard_id VARCHAR(50) PRIMARY KEY, + address VARCHAR(255) NOT NULL, + acquired_at DATETIME NOT NULL + ) + `, + pg: () => + sql` + CREATE TABLE IF NOT EXISTS ${locksTableSql} ( + shard_id VARCHAR(50) PRIMARY KEY, + address VARCHAR(255) NOT NULL, + acquired_at TIMESTAMP NOT NULL + ) + `, + orElse: () => + // sqlite + sql` + CREATE TABLE IF NOT EXISTS ${locksTableSql} ( + shard_id TEXT PRIMARY KEY, + address TEXT NOT NULL, + acquired_at DATETIME NOT NULL + ) + ` + }) + }) + }) +} + +const runRunnerMigrations = (options: { + readonly prefix?: string | undefined +}): Effect.Effect => + Migrator.make({})({ + loader: migrations(options), + // Message and runner migration ids overlap, so keep separate histories. + table: `${options.prefix ?? "cluster"}_runner_migrations` + }).pipe(Effect.asVoid, Effect.orDie) + +/** + * Runs the SQL runner storage migrations without providing storage. + * + * **Details** + * + * Use an owner connection in a deploy step, then use `layerStorage` with a + * DML-only runtime connection. History is recorded in `_runner_migrations`. + * Migration errors become defects. + * This layer does not require `ShardingConfig`. + * + * @stability unstable + * @category layers + * @since 4.1.0 + */ +export const layerMigrations = (options: { + readonly prefix?: string | undefined +}): Layer.Layer => Layer.effectDiscard(runRunnerMigrations(options)) + +/** + * Provides SQL-backed `RunnerStorage` without DDL or startup schema checks. + * + * **Details** + * + * Run `layerMigrations` separately before using this layer. + * + * @stability unstable + * @category layers + * @since 4.1.0 + */ +export const layerStorage = (options: { + readonly prefix?: string | undefined +}): Layer.Layer => + Layer.effect(RunnerStorage.RunnerStorage)(makeStorage(options)) + +/** + * Provides SQL-backed `RunnerStorage` with a custom table prefix, + * running migrations first. + * + * **Details** + * + * The connection needs DDL permissions. PostgreSQL takes an exclusive lock + * on the migration history table. Use `layerMigrations` and `layerStorage` + * to migrate separately. * * @stability unstable * @category layers @@ -788,3 +868,19 @@ export const layerWith = (options: { readonly prefix?: string | undefined }): Layer.Layer => Layer.effect(RunnerStorage.RunnerStorage)(make(options)) + +/** + * Layer that provides SQL-backed `RunnerStorage` using the default table prefix, + * running the runner storage migrations first. + * + * @see {@link layerWith} for the same layer with a custom table prefix + * + * @stability unstable + * @category layers + * @since 4.0.0 + */ +export const layer: Layer.Layer< + RunnerStorage.RunnerStorage, + SqlError, + SqlClient.SqlClient | ShardingConfig.ShardingConfig +> = layerWith({}) diff --git a/repos/effect/packages/effect/src/cluster/internal/entityManager.ts b/repos/effect/packages/effect/src/cluster/internal/entityManager.ts index 2fb7c18b1a..f36da9ae53 100644 --- a/repos/effect/packages/effect/src/cluster/internal/entityManager.ts +++ b/repos/effect/packages/effect/src/cluster/internal/entityManager.ts @@ -86,6 +86,10 @@ export interface Residency { readonly releaseUnsafe: () => void } +interface RequestTransaction { + settle?: ((outcome: Exit.Exit) => Effect.Effect) | undefined +} + // Represents the entities managed by this entity manager /** * @internal @@ -100,10 +104,13 @@ export type EntityState = { /** Excludes requests awaiting their first dispatch from replay. */ delivered: boolean sentExit: boolean + /** Treat early termination interrupts like shutdown interrupts. */ + terminating?: boolean | undefined lastSentChunk: Option.Option> sequence: number /** Set when the request should not outlive its caller. */ callerScope?: Scope.Scope | undefined + transaction?: RequestTransaction | undefined }> lastActiveCheck: number write: RpcServer.RpcServer["write"] @@ -152,9 +159,13 @@ export const make = Effect.fnUntraced(function*< entityRpcs.set(KeepAliveRpc._tag, KeepAliveRpc as any) const activeServers = new Map() + // Entities finishing their in-flight requests after removal, which still + // accept interrupts and acks + const drainingServers = new Map() const serverCloseLatches = new Map() const processedRequestIds = new Set() @@ -181,7 +192,8 @@ export const make = Effect.fnUntraced(function*< const keepAliveLatch = Latch.makeUnsafe() const closeLatches = { closed: Latch.makeUnsafe(), - force: Latch.makeUnsafe() + force: Latch.makeUnsafe(), + closing: false } yield* Scope.addFinalizer( @@ -238,7 +250,7 @@ export const make = Effect.fnUntraced(function*< ) as Effect.Effect>>) const server = yield* RpcServer.makeNoSerialization(entity.protocol, { - spanPrefix: `${entity.type}(${address.entityId})`, + spanPrefix: entity.type, spanAttributes: { ...options.spanAttributes, "entity.type": entity.type, @@ -264,22 +276,23 @@ export const make = Effect.fnUntraced(function*< // They will be retried when the entity is restarted. // Also, if the request is uninterruptible, we ignore the // interrupt. + const persisted = storageEnabled && Context.get(request.message.annotations, Persisted) if ( - storageEnabled && - Context.get(request.message.annotations, Persisted) && + persisted && Exit.hasInterrupts(response.exit) && - (isShuttingDown || isUninterruptibleForServer(request.message.annotations)) + (isShuttingDown || request.terminating || isUninterruptibleForServer(request.message.annotations)) ) { - if (!isShuttingDown) { + if (!isShuttingDown && !request.terminating) { request.sentExit = false return server.write(0, requestEnvelope(request), requestWriteOptions(request)).pipe( + Effect.setContext(handlerContext), Effect.forkIn(handlerScope) ) } activeRequests.delete(Snowflake.Snowflake(response.requestId)) return options.storage.unregisterReplyHandler(request.message.envelope.requestId) } - return retryRespond( + const save = retryRespond( 4, Effect.suspend(() => request.message.respond( @@ -290,22 +303,53 @@ export const make = Effect.fnUntraced(function*< }) ) ) - ).pipe( - Effect.flatMap(() => { - if (storageEnabled) { - processedRequestIds.add(request.message.envelope.requestId) - } - activeRequests.delete(Snowflake.Snowflake(response.requestId)) + ) + const complete = Effect.sync(() => { + if (storageEnabled) { + processedRequestIds.add(request.message.envelope.requestId) + } + activeRequests.delete(Snowflake.Snowflake(response.requestId)) - // Start the idle timer when the last request completes. - if (activeRequests.size === 0) { - state.lastActiveCheck = clock.currentTimeMillisUnsafe() - } + // Start the idle timer when the last request completes. + if (activeRequests.size === 0) { + state.lastActiveCheck = clock.currentTimeMillisUnsafe() + } + }) + const respond = Effect.orDie(Effect.andThen(save, complete)) + const transaction = request.transaction + if (!transaction) return respond + const exit = response.exit + + if (!persisted) { + if (Exit.isSuccess(exit)) return respond + transaction.settle = () => respond + return Effect.void + } - return Effect.void - }), - Effect.orDie - ) + if (Exit.isSuccess(exit)) { + transaction.settle = (outcome) => + Exit.isSuccess(outcome) ? complete : Effect.flatMap( + hasStoredExit(request.message.envelope.requestId), + (committed) => { + if (!committed) return restartFrom(outcome.cause) + // Commit succeeded despite the error; let callers read the saved reply. + return Effect.andThen( + complete, + options.storage.unregisterReplyHandler(request.message.envelope.requestId) + ) + } + ) + return Effect.orDie(save) + } + transaction.settle = (outcome) => + // Transaction wrappers can add defects, but not typed errors; interrupts may be repeated. + Exit.isSuccess(outcome) || !outcome.cause.reasons.some((reason) => + Cause.isDieReason(reason) && + !exit.cause.reasons.some((r) => Cause.isDieReason(r) && r.defect === reason.defect) + ) + ? respond + : restartFrom(outcome.cause) + return Effect.void } case "Chunk": { const request = activeRequests.get(Snowflake.Snowflake(response.requestId)) @@ -330,10 +374,7 @@ export const make = Effect.fnUntraced(function*< )) } case "Defect": { - if (!isActive()) return endLatch.open - const rebuild = writeRef.rebuildUnsafe({ from: server.write, prepare: replay }) - if (!rebuild) return Effect.void - return Effect.forkIn(restart(Cause.die(response.defect), rebuild), managerScope) + return restartFrom(Cause.die(response.defect)) } case "ClientEnd": { return endLatch.open @@ -345,6 +386,21 @@ export const make = Effect.fnUntraced(function*< Effect.setContext(Context.merge(handlerContext, handlers)) ) + // Replay if the stored reply cannot be read. + const hasStoredExit = (requestId: Snowflake.Snowflake): Effect.Effect => + options.storage.repliesForUnfiltered([requestId]).pipe( + Effect.map((replies) => replies.some((reply) => reply._tag === "WithExit")), + Effect.catchCause(() => Effect.succeed(false)) + ) + + // Do not inherit the failed handler's transaction context. + const restartFrom = (cause: Cause.Cause): Effect.Effect => { + if (!isActive()) return endLatch.open + const rebuild = writeRef.rebuildUnsafe({ from: server.write, prepare: replay }) + if (!rebuild) return Effect.void + return Effect.forkIn(Effect.setContext(restart(cause, rebuild), handlerContext), managerScope) + } + yield* Scope.addFinalizer( handlerScope, Effect.sync(() => { @@ -415,15 +471,32 @@ export const make = Effect.fnUntraced(function*< Effect.suspend(() => { activeServers.delete(address.entityId) retired.openUnsafe() + closeLatches.closing = true acquireEntity(address) + drainingServers.set(address.entityId, state) return Effect.raceFirst( - state.write(0, { _tag: "Eof" }).pipe( + Effect.gen(function*() { + for (const [requestId, request] of activeRequests) { + if ( + !request.delivered || request.sentExit || + !Context.get(request.message.annotations, ClusterSchema.InterruptOnTermination) || + isUninterruptibleForServer(request.message.annotations) + ) continue + request.terminating = true + yield* state.write(0, { _tag: "Interrupt", requestId: requestId as any, interruptors: [] }) + } + yield* state.write(0, { _tag: "Eof" }) + }).pipe( Effect.andThen(endLatch.await), Effect.timeoutOption(config.entityTerminationTimeout), Effect.interruptible ), Effect.interruptible(closeLatches.force.await) - ) + ).pipe(Effect.ensuring(Effect.sync(() => { + if (drainingServers.get(address.entityId) === state) { + drainingServers.delete(address.entityId) + } + }))) }) ) if (!options.sharding.hasShardId(address.shardId)) { @@ -458,9 +531,38 @@ export const make = Effect.fnUntraced(function*< Effect.forkIn(managerScope) ) + function sendEnvelope(server: EntityState, message: Message.IncomingEnvelope): Effect.Effect { + const entry = server.activeRequests.get(message.envelope.requestId) + if (!entry) { + return Effect.void + } else if ( + message.envelope._tag === "AckChunk" && + Option.isSome(entry.lastSentChunk) && + message.envelope.replyId !== entry.lastSentChunk.value.id + ) { + return Effect.void + } + return server.write( + 0, + message.envelope._tag === "AckChunk" + ? { _tag: "Ack", requestId: message.envelope.requestId as any } + : { + _tag: "Interrupt", + requestId: message.envelope.requestId as any, + interruptors: [] + } + ) + } + function sendLocal( message: Message.IncomingLocal ): Effect.Effect { + if (message._tag === "IncomingEnvelope") { + const draining = drainingServers.get(message.envelope.address.entityId) + if (draining?.activeRequests.has(message.envelope.requestId)) { + return sendEnvelope(draining, message) + } + } return Effect.provideService( Effect.flatMap( entities.get(message.envelope.address), @@ -557,26 +659,7 @@ export const make = Effect.fnUntraced(function*< return server.write(0, requestEnvelope(entry), requestWriteOptions(entry)) } case "IncomingEnvelope": { - const entry = server.activeRequests.get(message.envelope.requestId) - if (!entry) { - return Effect.void - } else if ( - message.envelope._tag === "AckChunk" && - Option.isSome(entry.lastSentChunk) && - message.envelope.replyId !== entry.lastSentChunk.value.id - ) { - return Effect.void - } - return server.write( - 0, - message.envelope._tag === "AckChunk" - ? { _tag: "Ack", requestId: message.envelope.requestId as any } - : { - _tag: "Interrupt", - requestId: message.envelope.requestId as any, - interruptors: [] - } - ) + return sendEnvelope(server, message) } } } @@ -596,11 +679,24 @@ export const make = Effect.fnUntraced(function*< }) const requestWriteOptions = ( - entry: { readonly message: Message.IncomingRequestLocal; readonly callerScope?: Scope.Scope | undefined } + entry: { + readonly message: Message.IncomingRequestLocal + readonly callerScope?: Scope.Scope | undefined + transaction?: RequestTransaction | undefined + } ): Parameters[2] => { - const onTransaction = Context.get(entry.message.annotations, WithTransaction) - ? options.storage.withTransaction - : undefined + const onTransaction = !Context.get(entry.message.annotations, WithTransaction) + ? undefined + : (effect: Effect.Effect) => + // Interrupts during commit must not hide the outcome from settle. + Effect.uninterruptibleMask((restore) => { + const transaction: RequestTransaction = {} + entry.transaction = transaction + return Effect.onExit(options.storage.withTransaction(restore(effect)), (outcome) => { + if (entry.transaction === transaction) entry.transaction = undefined + return transaction.settle ? transaction.settle(outcome) : Effect.void + }) + }) const onCaller = entry.callerScope && bindToCaller(entry.callerScope) if (!onCaller) return onTransaction && { onRequest: onTransaction } return { onRequest: onTransaction ? (effect) => onCaller(onTransaction(effect)) : onCaller } @@ -621,13 +717,13 @@ export const make = Effect.fnUntraced(function*< } }) } - activeServers.forEach((state) => { - if (shardId[Equal.symbol](state.address.shardId)) { - fibers.push(runFork(entities.removeIgnore(state.address))) - } - }) + // Look entities up by address: `activeServers` is keyed by entity id, + // so an entity with the same id on another shard can hide this one. serverCloseLatches.forEach((latches, address) => { if (shardId[Equal.symbol](address.shardId)) { + if (!latches.closing) { + fibers.push(runFork(entities.removeIgnore(address))) + } fibers.push(runFork(latches.closed.await)) } }) diff --git a/repos/effect/packages/effect/src/encoding/Sse.ts b/repos/effect/packages/effect/src/encoding/Sse.ts index be2cf02f45..b1720f36a2 100644 --- a/repos/effect/packages/effect/src/encoding/Sse.ts +++ b/repos/effect/packages/effect/src/encoding/Sse.ts @@ -92,6 +92,12 @@ export interface DecodeOptions { * Maximum number of string code units retained for a pending event. The default is 10 MiB. */ readonly maxEventSize?: number | undefined + /** + * Also dispatch an event that sets an `event:` name but has no `data:` + * line, with empty `data`. The WHATWG algorithm drops such events, but some + * protocols use them, such as graphql-sse's `complete`. Defaults to `false`. + */ + readonly dispatchEmptyNamedEvents?: boolean | undefined } const defaultMaxEventSize = 10 * 1024 * 1024 @@ -270,13 +276,16 @@ export const decodeDataSchema = ( */ export function makeParser(onParse: (event: AnyEvent) => void, options?: DecodeOptions): Parser { const maxEventSize = options?.maxEventSize ?? defaultMaxEventSize + const dispatchEmptyNamedEvents = options?.dispatchEmptyNamedEvents === true // Processing state let isFirstChunk: boolean - let buffer: string - let startingPosition: number - let startingFieldLength: number + // Pieces of the unterminated line, joined once when the line ends + let pending: Array + let pendingLength: number let discardTrailingNewline: boolean + // Incremented by `reset`, so `feed` can stop if `onParse` resets the parser + let generation = 0 // Event state let lastEventId: string | undefined @@ -287,10 +296,10 @@ export function makeParser(onParse: (event: AnyEvent) => void, options?: DecodeO return { feed, reset } function reset(): void { + generation++ isFirstChunk = true - buffer = "" - startingPosition = 0 - startingFieldLength = -1 + pending = [] + pendingLength = 0 discardTrailingNewline = false lastEventId = undefined @@ -299,120 +308,98 @@ export function makeParser(onParse: (event: AnyEvent) => void, options?: DecodeO } function feed(chunk: string): SseError | undefined { - buffer = buffer ? buffer + chunk : chunk - // Strip any UTF-8 byte order mark (BOM) at the start of the stream. // Note that we do not strip any non - UTF8 BOM, as eventsource streams are // always decoded as UTF8 as per the specification. - if (isFirstChunk && buffer.startsWith(BOM)) { - buffer = buffer.slice(BOM.length) + if (isFirstChunk && chunk.startsWith(BOM)) { + chunk = chunk.slice(BOM.length) } isFirstChunk = false - // Set up chunk-specific processing state - const length = buffer.length + const length = chunk.length + const currentGeneration = generation let position = 0 - // Read the current buffer byte by byte while (position < length) { - // EventSource allows for carriage return + line feed, which means we - // need to ignore a linefeed character if the previous character was a - // carriage return - // @todo refactor to reduce nesting, consider checking previous byte? - // @todo but consider multiple chunks etc + // Skip the LF of a CRLF, whose CR may have ended the previous chunk if (discardTrailingNewline) { - if (buffer[position] === "\n") { + discardTrailingNewline = false + if (chunk.charCodeAt(position) === LF) { ++position + continue } - discardTrailingNewline = false } - let lineLength = -1 - let fieldLength = startingFieldLength - let character: string - - for (let index = position + startingPosition; lineLength < 0 && index < length; ++index) { - character = buffer[index] - if (character === ":" && fieldLength < 0) { - fieldLength = index - position - } else if (character === "\r") { - discardTrailingNewline = true - lineLength = index - position - } else if (character === "\n") { - lineLength = index - position - } + let lineEnd = position + while (lineEnd < length) { + const code = chunk.charCodeAt(lineEnd) + if (code === CR || code === LF) break + ++lineEnd } - if (lineLength < 0) { - startingPosition = length - position - startingFieldLength = fieldLength + if (lineEnd === length) { + pending.push(chunk.slice(position)) + pendingLength += length - position break - } else { - startingPosition = 0 - startingFieldLength = -1 } - parseEventStreamLine(buffer, position, fieldLength, lineLength) + discardTrailingNewline = chunk.charCodeAt(lineEnd) === CR - position += lineLength + 1 - } + let line = chunk.slice(position, lineEnd) + if (pending.length > 0) { + pending.push(line) + line = pending.join("") + pending = [] + pendingLength = 0 + } + parseLine(line) + + if (generation !== currentGeneration) { + // `onParse` reset the parser, so drop the rest of this chunk + return + } - if (position === length) { - // If we consumed the entire buffer to read the event, reset the buffer - buffer = "" - } else if (position > 0) { - // If there are bytes left to process, set the buffer to the unprocessed - // portion of the buffer only - buffer = buffer.slice(position) + position = lineEnd + 1 } - if (buffer.length + data.length > maxEventSize) { + if (pendingLength + data.length > maxEventSize) { const error = new SseError({ reason: new EventTooLarge({ maxEventSize }) }) reset() return error } } - function parseEventStreamLine( - lineBuffer: string, - index: number, - fieldLength: number, - lineLength: number - ) { - if (lineLength === 0) { - // We reached the last line of this event - if (data.length > 0) { + function parseLine(line: string) { + if (line.length === 0) { + // End of event. Clear the state first so a throwing `onParse` cannot + // leak it into the next event + const named = eventName !== undefined && eventName !== "" + const event = eventName || "message" + const eventData = data + eventName = undefined + data = "" + if (eventData.length > 0 || (dispatchEmptyNamedEvents && named)) { onParse({ _tag: "Event", id: lastEventId, - event: eventName || "message", - data: data.slice(0, -1) // remove trailing newline + event, + data: eventData.slice(0, -1) // remove trailing newline }) - data = "" } - eventName = undefined return } - const noValue = fieldLength < 0 - const field = lineBuffer.slice(index, index + (noValue ? lineLength : fieldLength)) - let step = 0 - - if (noValue) { - step = lineLength - } else if (lineBuffer[index + fieldLength + 1] === " ") { - step = fieldLength + 2 - } else { - step = fieldLength + 1 + const colon = line.indexOf(":") + let field = line + let value = "" + if (colon >= 0) { + field = line.slice(0, colon) + value = line.slice(line.charCodeAt(colon + 1) === SPACE ? colon + 2 : colon + 1) } - const position = index + step - const valueLength = lineLength - step - const value = lineBuffer.slice(position, position + valueLength).toString() - if (field === "data") { - data += value ? `${value}\n` : "\n" + data += value + "\n" } else if (field === "event") { eventName = value } else if (field === "id" && !value.includes("\u0000")) { @@ -425,6 +412,9 @@ export function makeParser(onParse: (event: AnyEvent) => void, options?: DecodeO } const BOM = "\uFEFF" +const LF = 10 +const CR = 13 +const SPACE = 32 /** * Stateful Server-Sent Events parser returned by `makeParser`. @@ -693,7 +683,7 @@ export const encoder: Encoder = { if (event.event !== "message") { data += `event: ${event.event}\n` } - data += `data: ${event.data.replace(/\n/g, "\ndata: ")}\n` + data += `data: ${event.data.replace(/\r\n|\r|\n/g, "\ndata: ")}\n` return data + "\n" } case "Retry": { diff --git a/repos/effect/packages/effect/src/graphql/GraphQL.ts b/repos/effect/packages/effect/src/graphql/GraphQL.ts new file mode 100644 index 0000000000..e15ebfbac9 --- /dev/null +++ b/repos/effect/packages/effect/src/graphql/GraphQL.ts @@ -0,0 +1,494 @@ +/** + * Typed GraphQL operations for `GraphQLGroup` and `GraphQLClient.make`, + * written by hand or generated by `@effect/graphql-generator`. + * + * Includes the generator's lenient decoders, {@link otherTypename} and + * {@link enumLiterals}. + * + * @stability experimental + * @since 4.0.0 + */ +import * as internal from "../internal/graphql.ts" +import { type Pipeable, pipeArguments } from "../Pipeable.ts" +import { hasProperty } from "../Predicate.ts" +import * as Schema from "../Schema.ts" +import type { GraphQLClientError } from "./GraphQLClientError.ts" +import type * as GraphQLMiddleware from "./GraphQLMiddleware.ts" + +const TypeId = "~effect/graphql/GraphQL" + +/** + * The three kinds of GraphQL operation. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type Kind = "query" | "mutation" | "subscription" + +/** + * An operation document split into the pieces needed to rename and alias it + * without a GraphQL parser. The generator emits one for every query and + * mutation. + * + * **Details** + * + * A `body` is a {@link DocumentTemplate.Parts} array: literal text at even + * indices and, at odd indices, the variable names and fragment names that + * would be renamed if the operation were repeated under a prefix. Joining the + * pieces gives the printed document, which is what the operation sends. + * + * A fragment whose `body` has a name in it is per-slice: it references a + * variable, directly or through a fragment it spreads. Every other fragment is + * shared. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DocumentTemplate { + /** The variable definitions, in document order. */ + readonly variables: ReadonlyArray + /** The operation's directives, if it has any. */ + readonly directives?: DocumentTemplate.Parts | undefined + /** The root selections, in document order. */ + readonly selections: ReadonlyArray + /** The fragments the operation uses, in the order they follow it. */ + readonly fragments: ReadonlyArray +} + +/** + * The pieces of a {@link DocumentTemplate}. + * + * @stability experimental + * @since 4.0.0 + */ +export declare namespace DocumentTemplate { + /** + * Literal text at even indices and names to rename at odd indices. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ + export type Parts = ReadonlyArray + + /** + * A variable definition: `$name:` followed by `body`, the type, default + * value and directives as printed. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ + export interface Variable { + readonly name: string + readonly body: string + } + + /** + * A root selection. For a field, `body` is everything after its name and + * the response key is `alias ?? name`. A fragment spread or inline fragment + * has no `name`, and `body` is the whole selection. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ + export interface Selection { + readonly alias?: string | undefined + readonly name?: string | undefined + readonly body: Parts + } + + /** + * A fragment definition: `fragment` and `name`, followed by `body`, which + * starts at its type condition. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ + export interface Fragment { + readonly name: string + readonly body: Parts + } +} + +/** + * A named GraphQL document with variable and result schemas and middleware. + * Variables are encoded before sending; results are decoded from `data`. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Operation< + out K extends Kind, + out Name extends string, + out Variables extends Schema.Top, + out Result extends Schema.Top, + out Middleware = never +> extends Pipeable { + readonly [TypeId]: typeof TypeId + readonly kind: K + readonly name: Name + /** The printed document, sent as-is. It is never parsed at runtime. */ + readonly document: string + /** The template the document was joined from, if it was given as one. */ + readonly template: DocumentTemplate | undefined + readonly variables: Variables + readonly result: Result + /** Middleware attached to this operation, outermost first. */ + readonly middlewares: ReadonlyArray + readonly "~middleware"?: Middleware + /** + * Returns a copy of this operation with `middleware` attached. Operation + * middleware runs inside any group middleware; within the operation, + * middleware run in the order they were attached. + */ + middleware( + middleware: M + ): Operation +} + +/** + * Any operation, with its type parameters erased. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Any = Operation + +/** + * Extracts the union of middleware attached to an operation. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Middleware = Op extends Operation ? M : never + +/** + * The decoded variables type of an operation, which is what a client method + * takes. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Variables = Op["variables"]["Type"] + +/** + * The decoded result type of an operation. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Result = Op["result"]["Type"] + +/** + * The error type of a client method for an operation: `GraphQLClientError` + * plus the errors of every attached middleware. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Error = GraphQLClientError | GraphQLMiddleware.Error> + +/** + * The services a client method for an operation requires: the Schemas' + * encoding and decoding services plus the requirements of every attached + * middleware. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Services = + | Op["variables"]["EncodingServices"] + | Op["result"]["DecodingServices"] + | GraphQLMiddleware.Requires> + +/** + * The type of an operation after attaching middleware `M`. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type AddMiddleware = Op extends Operation + ? Operation + : never + +/** + * Tests whether a value is an {@link Operation}. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isOperation = (u: unknown): u is Any => hasProperty(u, TypeId) + +const Proto = { + [TypeId]: TypeId, + pipe() { + return pipeArguments(this, arguments) + }, + middleware(this: Any, middleware: GraphQLMiddleware.AnyService) { + return makeProto({ ...this, middlewares: [...this.middlewares, middleware] }) + } +} + +// The middleware type of an operation is phantom and its Schemas are erased to +// `Schema.Top` here, so the typed constructors below state their operation +// type with one assertion each. +const makeProto = (fields: Omit): Any => + Object.assign(Object.create(Proto), fields) + +const makeOperation = (kind: K) => +< + const Name extends string, + Result extends Schema.Top, + Variables extends Schema.Top | Schema.Struct.Fields = Schema.Struct<{}> +>( + name: Name, + options: { + readonly document: string | DocumentTemplate + readonly variables?: Variables | undefined + readonly result: Result + } +): Operation : Variables, Result> => + makeProto({ + kind, + name, + document: typeof options.document === "string" + ? options.document + : internal.joinTemplate(kind, name, options.document), + template: typeof options.document === "string" ? undefined : options.document, + variables: options.variables === undefined + ? Schema.Struct({}) + : Schema.isSchema(options.variables) + ? options.variables + : Schema.Struct(options.variables as Schema.Struct.Fields), + result: options.result, + middlewares: [] + }) as Operation : Variables, Result> + +/** + * Defines a query. The client accepts decoded variables and encodes them + * through their Schema, including custom scalar codecs. `variables` accepts + * struct fields or a Schema; omit it for an operation without variables. + * `document` accepts printed text or a {@link DocumentTemplate}, joined once + * when the operation is defined. + * + * **Example** (A query with variables) + * + * ```ts import.meta.vitest + * import { Schema } from "effect" + * import { GraphQL } from "effect/graphql" + * + * const RepoIssues = GraphQL.query("RepoIssues", { + * document: "query RepoIssues($owner:String!,$name:String!){repository(owner:$owner,name:$name){issues(first:10){nodes{number title}}}}", + * variables: { owner: Schema.String, name: Schema.String }, + * result: Schema.Struct({ + * repository: Schema.NullOr(Schema.Struct({ + * issues: Schema.Struct({ + * nodes: Schema.NullOr(Schema.Array(Schema.NullOr(Schema.Struct({ number: Schema.Int, title: Schema.String })))) + * }) + * })) + * }) + * }) + * + * RepoIssues.kind // => "query" + * RepoIssues.name // => "RepoIssues" + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const query: < + const Name extends string, + Result extends Schema.Top, + Variables extends Schema.Top | Schema.Struct.Fields = Schema.Struct<{}> +>( + name: Name, + options: { + readonly document: string | DocumentTemplate + readonly variables?: Variables | undefined + readonly result: Result + } +) => Operation<"query", Name, Variables extends Schema.Struct.Fields ? Schema.Struct : Variables, Result> = + makeOperation("query") + +/** + * Defines a mutation. Same shape as {@link query}. + * + * **Example** (A mutation) + * + * ```ts import.meta.vitest + * import { Schema } from "effect" + * import { GraphQL } from "effect/graphql" + * + * const AddComment = GraphQL.mutation("AddComment", { + * document: "mutation AddComment($subjectId:ID!,$body:String!){addComment(input:{subjectId:$subjectId,body:$body}){clientMutationId}}", + * variables: { subjectId: Schema.String, body: Schema.String }, + * result: Schema.Struct({ addComment: Schema.NullOr(Schema.Struct({ clientMutationId: Schema.NullOr(Schema.String) })) }) + * }) + * + * AddComment.kind // => "mutation" + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const mutation: < + const Name extends string, + Result extends Schema.Top, + Variables extends Schema.Top | Schema.Struct.Fields = Schema.Struct<{}> +>( + name: Name, + options: { + readonly document: string | DocumentTemplate + readonly variables?: Variables | undefined + readonly result: Result + } +) => Operation< + "mutation", + Name, + Variables extends Schema.Struct.Fields ? Schema.Struct : Variables, + Result +> = makeOperation("mutation") + +/** + * Defines a subscription. The client method for a subscription returns a + * `Stream` of decoded events instead of an `Effect`. + * + * **Example** (A subscription) + * + * ```ts import.meta.vitest + * import { Schema } from "effect" + * import { GraphQL } from "effect/graphql" + * + * const IssueUpdated = GraphQL.subscription("IssueUpdated", { + * document: "subscription IssueUpdated($id:ID!){issueUpdated(id:$id){title}}", + * variables: { id: Schema.String }, + * result: Schema.Struct({ issueUpdated: Schema.Struct({ title: Schema.String }) }) + * }) + * + * IssueUpdated.kind // => "subscription" + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const subscription: < + const Name extends string, + Result extends Schema.Top, + Variables extends Schema.Top | Schema.Struct.Fields = Schema.Struct<{}> +>( + name: Name, + options: { + readonly document: string | DocumentTemplate + readonly variables?: Variables | undefined + readonly result: Result + } +) => Operation< + "subscription", + Name, + Variables extends Schema.Struct.Fields ? Schema.Struct : Variables, + Result +> = makeOperation("subscription") + +/** + * The `__typename` Schema for the "every other type" member of a generated + * union. + * + * **Details** + * + * The type excludes selected names, allowing `__typename` narrowing. The + * decoder accepts any other string, including types added by the server + * later. Selected names are rejected so malformed selected results cannot + * fall through to the catch-all member. + * + * **Example** (The catch-all member of a union) + * + * ```ts import.meta.vitest + * import { Schema } from "effect" + * import { GraphQL } from "effect/graphql" + * + * type Node = "Issue" | "PullRequest" | "Repository" + * + * const OtherNode = Schema.Struct({ + * __typename: GraphQL.otherTypename()(["Issue"]), + * id: Schema.String + * }) + * + * Schema.decodeUnknownSync(OtherNode)({ __typename: "PullRequest", id: "1" }).__typename // => "PullRequest" + * Schema.decodeUnknownSync(OtherNode)({ __typename: "AddedLater", id: "2" }).__typename // => "AddedLater" + * Schema.is(OtherNode)({ __typename: "Issue", id: "3" }) // => false + * ``` + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const otherTypename = () => +>( + selected: Selected +): Schema.refine, Schema.String> => { + const rejected = new Set(selected) + // Type boundary: decoding is lenient by design. The guard passes any string + // other than the selected names, including names the server adds later, but + // the type only lists the names known when the code was generated. + return Schema.refine>( + (name): name is Exclude => !rejected.has(name), + { + title: "otherTypename", + message: `Expected a __typename other than ${selected.map((s) => `"${s}"`).join(", ")}` + } + )(Schema.String) +} + +/** + * The Schema for a GraphQL enum in a result position. + * + * **Details** + * + * It is typed as the declared literals but decodes any string, so a value the + * server adds later does not fail the whole query. Inputs stay strict: the + * generator uses `Schema.Literals` for enums in variables and input objects. + * + * **Example** (An enum that tolerates new values) + * + * ```ts import.meta.vitest + * import { Schema } from "effect" + * import { GraphQL } from "effect/graphql" + * + * const IssueState = GraphQL.enumLiterals(["OPEN", "CLOSED"]) + * + * Schema.decodeUnknownSync(IssueState)("OPEN") // => "OPEN" + * Schema.decodeUnknownSync(IssueState)("MERGED") // => "MERGED" + * Schema.is(IssueState)(42) // => false + * ``` + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const enumLiterals = >( + literals: Literals +): Schema.refine => + // Type boundary: decoding is lenient by design. The guard passes any string, + // including values the server adds later, but the type only lists the values + // known when the code was generated. + Schema.refine((_): _ is Literals[number] => true)(Schema.String).annotate({ + title: `enum(${literals.join(" | ")})`, + description: `One of ${literals.map((l) => `"${l}"`).join(", ")}, or any string the server adds later` + }) diff --git a/repos/effect/packages/effect/src/graphql/GraphQLClient.ts b/repos/effect/packages/effect/src/graphql/GraphQLClient.ts new file mode 100644 index 0000000000..98ff5eb541 --- /dev/null +++ b/repos/effect/packages/effect/src/graphql/GraphQLClient.ts @@ -0,0 +1,924 @@ +/** + * A typed client with one method per operation in a `GraphQLGroup`. Queries + * and mutations return an `Effect`; subscriptions return a `Stream`. The + * client encodes variables, runs middleware, calls the `GraphQLProtocol` in + * context and decodes results. + * + * Retryable subscription failures restart the middleware chain on the + * `subscriptionRetry` schedule. {@link pages} and {@link items} provide + * cursor pagination. {@link makeTest} builds a mock client for tests, and + * {@link layerTest} provides it as a service layer. See `GraphQLProtocol` + * for transport options. + * + * @stability experimental + * @since 4.0.0 + */ +import * as Cause from "../Cause.ts" +import * as Context from "../Context.ts" +import * as Duration from "../Duration.ts" +import * as Effect from "../Effect.ts" +import { identity } from "../Function.ts" +import * as Headers from "../http/Headers.ts" +import * as UrlParams from "../http/UrlParams.ts" +import * as internalGraphQL from "../internal/graphql.ts" +import { getStackTraceLimit, setStackTraceLimit } from "../internal/stackTraceLimit.ts" +import * as Layer from "../Layer.ts" +import * as Option from "../Option.ts" +import type * as Pull from "../Pull.ts" +import * as Schedule from "../Schedule.ts" +import * as Schema from "../Schema.ts" +import * as Stream from "../Stream.ts" +import * as Struct from "../Struct.ts" +import type * as Types from "../Types.ts" +import type * as GraphQL from "./GraphQL.ts" +import { + DecodeError, + GraphQLClientError, + type GraphQLError, + isGraphQLClientError, + PaginationError +} from "./GraphQLClientError.ts" +import type * as GraphQLGroup from "./GraphQLGroup.ts" +import type * as GraphQLMiddleware from "./GraphQLMiddleware.ts" +import { ExecutionResult, GraphQLProtocol, type GraphQLRequest } from "./GraphQLProtocol.ts" + +/** + * Decoded `data` and response `errors` for a `{ partial: true }` call. + * The errors array may be empty. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface PartialResult { + readonly data: A + readonly errors: ReadonlyArray +} + +type Args = {} extends Variables ? [variables?: Variables, options?: Options] + : [variables: Variables, options?: Options] + +type ArgsWithOptions = {} extends Variables ? [variables: Variables | undefined, options: Options] + : [variables: Variables, options: Options] + +/** + * The client method for a query or mutation. + * + * **Details** + * + * Called as `(variables?, options?)`. Without `partial`, or with + * `partial: false`, it returns the decoded result and fails with a + * `ResponseError` on any `errors`. With `partial: true` it returns + * `{ data, errors }`. `partial` must be a literal `true` or `false`, not + * an arbitrary `boolean`. + * + * An operation without variables is called as `client.Viewer()` or, with + * options, `client.Viewer(undefined, { headers })`. + * + * `headers` and `urlParams` are sent by the HTTP transport, ignored over + * graphql-ws, and visible to middleware either way as + * `GraphQLRequest.headers` and `GraphQLRequest.urlParams`. Header options + * accept `Headers.Input` and are normalized to `Headers.Headers` before + * middleware runs. `context` provides + * services for this call only, and removes them from the method's + * requirements. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface OperationMethod { + /** The operation this method runs. */ + readonly operation: Op + ( + ...args: ArgsWithOptions, { + readonly headers?: Headers.Input | undefined + readonly urlParams?: UrlParams.Input | undefined + readonly context?: Context.Context | undefined + readonly partial: true + }> + ): Effect.Effect>, GraphQL.Error, Exclude, R2>> + ( + ...args: Args, { + readonly headers?: Headers.Input | undefined + readonly urlParams?: UrlParams.Input | undefined + readonly context?: Context.Context | undefined + readonly partial?: false | undefined + }> + ): Effect.Effect, GraphQL.Error, Exclude, R2>> +} + +/** + * The client method for a subscription. It returns a `Stream` of decoded + * events; an event with `errors` fails the stream with a `ResponseError`, + * unless that error is retryable and the client resubscribes (see + * {@link make}). `headers`, `urlParams` and `context` work as for + * {@link OperationMethod}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface SubscriptionMethod { + /** The operation this method runs. */ + readonly operation: Op + ( + ...args: Args, { + readonly headers?: Headers.Input | undefined + readonly urlParams?: UrlParams.Input | undefined + readonly context?: Context.Context | undefined + }> + ): Stream.Stream, GraphQL.Error, Exclude, R2>> +} + +/** + * The client method type for an operation, by its kind. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type Method = Op["kind"] extends "subscription" ? SubscriptionMethod + : OperationMethod + +/** + * A client: one method per operation, keyed by operation name. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type GraphQLClient = { + readonly [Op in Ops as Op["name"]]: Method +} + +/** + * Derives the client type for all operations in a `GraphQLGroup`. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type FromGroup = GraphQLClient> + +/** + * The default subscription retry schedule: exponential from 500 milliseconds + * with factor 1.5, capped at 5 seconds, and never shorter than the server's + * `retryAfter`. + * + * @stability experimental + * @category constants + * @since 4.0.0 + */ +export const defaultSubscriptionRetry: Schedule.Schedule = Schedule.exponential( + "500 millis", + 1.5 +).pipe( + Schedule.setInputType(), + Schedule.modifyDelay(({ duration, input }) => { + const capped = Duration.min(duration, Duration.seconds(5)) + return Effect.succeed(input.retryAfter === undefined ? capped : Duration.max(capped, input.retryAfter)) + }) +) + +/** + * Builds a client from a group, requiring `GraphQLProtocol` and every + * middleware service attached to the group or its operations. + * + * **Details** + * + * Group middleware runs outside operation middleware. Within each level, + * middleware run in the order attached. + * + * `subscriptionRetry` decides how a subscription is retried after it fails + * with a retryable error: usually a `TransportError`, but also a + * `ResponseError` whose response carried a valid `Retry-After`, including an + * event with `errors` on a graphql-sse stream whose response had that header. + * It defaults to {@link defaultSubscriptionRetry}. Fatal errors are never + * retried, whatever the schedule. A retry starts a new subscription, so the + * server may send events again that the stream already emitted. + * + * **Example** (A client as a service) + * + * ```ts import.meta.vitest + * import { Context, Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql" + * + * // What the generator emits for viewer.graphql + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * const ViewerGraphQLGroup = GraphQLGroup.make(Viewer) + * + * class GitHub extends Context.Service()("app/GitHub", { + * make: GraphQLClient.make(ViewerGraphQLGroup) + * }) {} + * + * // A scripted transport; use GraphQLProtocol.layerHttp({ url }) for a real server + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: () => Effect.succeed({ body: { data: { viewer: { login: "tim" } } } }), + * subscribe: () => Stream.empty + * }) + * + * const program = GitHub.use((github) => github.Viewer()).pipe( + * Effect.provide(Layer.effect(GitHub, GitHub.make).pipe(Layer.provide(Scripted))) + * ) + * + * await Effect.runPromise(program) // => { viewer: { login: "tim" } } + * ``` + * + * **Example** (Partial results) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql" + * + * const Repos = GraphQL.query("Repos", { + * document: "query Repos{a:repository(owner:\"x\",name:\"a\"){name} b:repository(owner:\"x\",name:\"b\"){name}}", + * result: Schema.Struct({ + * a: Schema.NullOr(Schema.Struct({ name: Schema.String })), + * b: Schema.NullOr(Schema.Struct({ name: Schema.String })) + * }) + * }) + * + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: () => + * Effect.succeed({ + * body: { + * data: { a: { name: "a" }, b: null }, + * errors: [{ message: "Could not resolve to a Repository", path: ["b"] }] + * } + * }), + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(Repos)) + * // The default call fails with a ResponseError because `errors` is non-empty + * const failed = yield* Effect.flip(client.Repos()) + * // With partial: true the decoded data comes back together with the errors + * const { data, errors } = yield* client.Repos(undefined, { partial: true }) + * return [failed.reason._tag, data.a?.name, errors[0].path?.[0]] + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => ["ResponseError", "a", "b"] + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const make = ( + group: GraphQLGroup.GraphQLGroup, + options?: { + readonly subscriptionRetry?: Schedule.Schedule | undefined + } | undefined +): Effect.Effect< + GraphQLClient, + never, + GraphQLProtocol | GraphQLMiddleware.Identifier> +> => + Effect.gen(function*() { + const protocol = yield* GraphQLProtocol + const context = yield* Effect.context() + const retryPolicy = retryableOnly(options?.subscriptionRetry ?? defaultSubscriptionRetry) + return fromGroup(group, (operation) => + makeMethod(operation, middlewareChain(context, group, operation), protocol, retryPolicy)) + }) + +// Type boundary: a mapping over the operations cannot prove the mapped type's +// name/kind relationship. +const fromGroup = ( + group: GraphQLGroup.GraphQLGroup, + f: (operation: Ops) => unknown +): GraphQLClient => + Object.fromEntries(group.operations.map((operation) => [operation.name, f(operation)])) as GraphQLClient + +/** + * The middleware implementations an operation runs through, outermost first, + * typed with the errors and requirements its middleware declared. + */ +type MiddlewareChain = ReadonlyArray< + GraphQLMiddleware.Implementation< + GraphQLMiddleware.Error>, + GraphQLMiddleware.Requires> + > +> + +// Runtime tags erase middleware types; `make` requires all their identifiers. +const middlewareChain = ( + context: Context.Context, + group: GraphQLGroup.GraphQLGroup, + operation: Op +): MiddlewareChain => [...group.middlewares, ...operation.middlewares].map((tag) => Context.getUnsafe(context, tag)) + +// Steps `schedule` only for retryable `GraphQLClientError`s. Middleware +// errors and fatal errors end the retries before reaching it, so a custom +// schedule can rely on its input being a `GraphQLClientError`. +const retryableOnly = ( + schedule: Schedule.Schedule +): Schedule.Schedule => + Schedule.fromStep(Effect.map( + Schedule.toStep(schedule), + (step) => + (now: number, input: unknown): Pull.Pull<[Output | undefined, Duration.Duration], Error, Output | undefined, Env> => + isGraphQLClientError(input) && input.isRetryable ? step(now, input) : Cause.done(undefined) + )) + +// `status` and `headers` are transport metadata, never read from the body. +const decodeExecutionResult = Schema.decodeUnknownEffect(ExecutionResult.mapFields(Struct.omit(["status", "headers"]))) + +interface CallOptions { + readonly headers?: Headers.Input | undefined + readonly urlParams?: UrlParams.Input | undefined + readonly context?: Context.Context | undefined + readonly partial?: boolean | undefined +} + +// Type boundary: a call without `context` has `R2 = never` unless the caller +// names `R2` explicitly, so an empty context stands in for `Context`. +const callContext = (options: CallOptions | undefined): Context.Context => + options?.context ?? (Context.empty() as Context.Context) + +const makeMethod = ( + operation: Op, + chain: MiddlewareChain, + protocol: GraphQLProtocol["Service"], + retryPolicy: Schedule.Schedule +): OperationMethod | SubscriptionMethod => { + const { decodePartial, decodeStrict, encodeVariables, fail, schemaFail } = internalGraphQL.makeCodec(operation) + + const notGraphQL = schemaFail((description) => + new DecodeError({ description: `Not a GraphQL response: ${description}` }) + ) + + const buildRequest = (variables: GraphQL.Variables | undefined, options: CallOptions | undefined) => + encodeVariables(variables).pipe( + Effect.map((encoded): GraphQLRequest => ({ + kind: operation.kind, + query: operation.document, + operationName: operation.name, + variables: encoded, + headers: Headers.fromInput(options?.headers), + urlParams: options?.urlParams === undefined ? UrlParams.empty : UrlParams.fromInput(options.urlParams) + })) + ) + + const decodeResponse = ({ body, ...metadata }: { + readonly body: unknown + readonly status?: number | undefined + readonly headers?: Headers.Headers | undefined + }) => + decodeExecutionResult(body).pipe( + Effect.map((result): ExecutionResult => ({ ...result, ...metadata })), + Effect.catch(notGraphQL) + ) + + // Type boundary: a middleware sees the errors of the middleware further in + // as `Types.unhandled` (as in `RpcMiddleware`), and none of their + // requirements. Those errors are part of `GraphQL.Error`, so the chain + // restates its type here. Force POST and the resolved URL apply only at the + // transport boundary. + const execute = ( + index: number, + request: GraphQLRequest, + forcePost: boolean, + resolvedUrl: internalGraphQL.ResolvedUrl + ): Effect.Effect, GraphQLMiddleware.Requires>> => + index === chain.length + ? protocol.execute(request).pipe( + forcePost ? Effect.provideService(internalGraphQL.ForcePost, true) : identity, + resolvedUrl === undefined ? identity : Effect.provideService(internalGraphQL.ResolvedUrl, resolvedUrl), + Effect.mapError(fail), + Effect.flatMap(decodeResponse) + ) + : chain[index].execute({ + operation, + request, + next: (request) => + execute(index + 1, request, forcePost, resolvedUrl) as Effect.Effect< + ExecutionResult, + GraphQLClientError | Types.unhandled + > + }) as Effect.Effect, GraphQLMiddleware.Requires>> + + // Hands a resolver batch's URL to the transport only, so calls made by + // middleware resolve their own. + const run = (request: GraphQLRequest, forcePost: boolean) => + internalGraphQL.ResolvedUrl.use((resolved) => + resolved === undefined + ? execute(0, request, forcePost, undefined) + : execute(0, request, forcePost, resolved).pipe(Effect.provideService(internalGraphQL.ResolvedUrl, undefined)) + ) + + const subscribe = ( + index: number, + request: GraphQLRequest + ): Stream.Stream, GraphQLMiddleware.Requires>> => + index === chain.length + ? protocol.subscribe(request).pipe( + Stream.mapError(fail), + Stream.mapEffect(decodeResponse) + ) + : chain[index].subscribe({ + operation, + request, + next: (request) => + subscribe(index + 1, request) as Stream.Stream + }) as Stream.Stream, GraphQLMiddleware.Requires>> + + if (operation.kind === "subscription") { + const subscriptionMethod = (...[variables, options]: Args, CallOptions>) => + Stream.unwrap(Effect.map(buildRequest(variables, options), (request) => subscribe(0, request))).pipe( + Stream.mapEffect(decodeStrict), + Stream.retry(retryPolicy), + Stream.provideContext(callContext(options)) + ) + return Object.assign(subscriptionMethod, { operation }) + } + + function method( + ...args: ArgsWithOptions, CallOptions & { readonly partial: true }> + ): Effect.Effect>, GraphQL.Error, Exclude, R2>> + function method( + ...args: Args, CallOptions & { readonly partial?: false | undefined }> + ): Effect.Effect, GraphQL.Error, Exclude, R2>> + function method( + variables?: GraphQL.Variables, + options?: CallOptions + ): Effect.Effect< + GraphQL.Result | PartialResult>, + GraphQL.Error, + Exclude, R2> + > { + return buildRequest(variables, options).pipe( + Effect.flatMap((request) => run(request, false)), + Effect.flatMap( + (result): Effect.Effect< + GraphQL.Result | PartialResult>, + GraphQLClientError, + Op["result"]["DecodingServices"] + > => options?.partial === true ? decodePartial(result) : decodeStrict(result) + ), + Effect.provideContext(callContext(options)) + ) + } + internalGraphQL.rawExecutors.set(method, { execute: (request) => run(request, true), url: protocol.url }) + return Object.assign(method, { operation }) +} + +/** + * The `pageInfo` a paged connection must select. + * + * @stability experimental + * @category paging + * @since 4.0.0 + */ +export interface PageInfo { + readonly hasNextPage: boolean + readonly endCursor: string | null +} + +/** + * What the `connection` getter of {@link pages} must return. + * + * @stability experimental + * @category paging + * @since 4.0.0 + */ +export interface Connection { + readonly pageInfo: PageInfo +} + +/** + * What the `connection` getter of {@link items} must return: a connection + * that also selects `nodes`. + * + * @stability experimental + * @category paging + * @since 4.0.0 + */ +export interface NodesConnection extends Connection { + readonly nodes: ReadonlyArray | null +} + +/** + * The type `variables` is given when the operation has no `$after` variable. + * Nothing is assignable to it, so the mistake is a compile error at the call. + * + * @stability experimental + * @category paging + * @since 4.0.0 + */ +export interface MissingAfterVariable { + readonly "effect/graphql": + "GraphQLClient.pages requires the operation to declare a nullable `$after: String` variable" +} + +/** + * The type `variables` is given when the operation's `after` variable is + * required or does not accept a `string`. The helper leaves `after` out on the + * first page and sends the previous `endCursor` afterwards, so it can only + * drive an optional variable that takes a string. + * + * @stability experimental + * @category paging + * @since 4.0.0 + */ +export interface InvalidAfterVariable { + readonly "effect/graphql": "GraphQLClient.pages requires the `after` variable to be optional and to accept a string" +} + +/** + * The `variables` accepted by {@link pages} and {@link items}: the method's + * variables without `after`, which the helper supplies. + * + * **Details** + * + * The operation's `after` variable must be optional and accept a `string`. + * `after?: string | null`, from a nullable `$after: String`, and + * `after?: string`, from a `$after: String!` with a default value, are both + * accepted. A required `after` gives {@link InvalidAfterVariable}, as does one + * that does not accept a `string`; no `after` at all gives + * {@link MissingAfterVariable}. + * + * @stability experimental + * @category paging + * @since 4.0.0 + */ +export type PagingVariables = "after" extends keyof Variables + ? {} extends Pick ? string extends Variables["after"] ? Omit + : InvalidAfterVariable + : InvalidAfterVariable + : MissingAfterVariable + +/** + * Pages forward through a cursor connection, emitting one connection per + * page. + * + * **Details** + * + * Requires an optional string `$after` variable (see {@link PagingVariables}). + * The first request omits `after`; subsequent requests use the previous + * `endCursor`. Pages are fetched only when pulled, so `Stream.take` stops + * further requests. Middleware runs on each page. + * + * `connection` extracts the connection from each result. `options` is + * forwarded to every call but cannot include `partial`: errors fail the stream. + * Its `headers` accept `Headers.Input`, just as for operation calls. + * + * The stream ends after a page whose `hasNextPage` is `false`. A `null` + * connection on the first page gives an empty stream; on a later page it + * fails with a `PaginationError`, as does `hasNextPage: true` with a `null` + * or unchanged `endCursor`. + * + * Root fields that come with every page, such as GitHub's `rateLimit`, are for + * middleware to read from the raw `ExecutionResult`. + * + * **Example** (Paging issues, two per page) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql" + * + * const RepoIssues = GraphQL.query("RepoIssues", { + * document: "query RepoIssues($owner:String!,$name:String!,$after:String){repository(owner:$owner,name:$name){issues(first:2,after:$after){pageInfo{hasNextPage endCursor}nodes{number}}}}", + * variables: { owner: Schema.String, name: Schema.String, after: Schema.optional(Schema.NullOr(Schema.String)) }, + * result: Schema.Struct({ + * repository: Schema.NullOr(Schema.Struct({ + * issues: Schema.Struct({ + * pageInfo: Schema.Struct({ hasNextPage: Schema.Boolean, endCursor: Schema.NullOr(Schema.String) }), + * nodes: Schema.NullOr(Schema.Array(Schema.NullOr(Schema.Struct({ number: Schema.Int })))) + * }) + * })) + * }) + * }) + * + * // A scripted server with two pages + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: (request) => { + * const after = (request.variables as { after?: string }).after + * const page = after === undefined + * ? { pageInfo: { hasNextPage: true, endCursor: "c1" }, nodes: [{ number: 1 }, { number: 2 }] } + * : { pageInfo: { hasNextPage: false, endCursor: null }, nodes: [{ number: 3 }] } + * return Effect.succeed({ body: { data: { repository: { issues: page } } } }) + * }, + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(RepoIssues)) + * const pages = GraphQLClient.pages(client.RepoIssues, { + * variables: { owner: "Effect-TS", name: "effect" }, + * connection: (result) => result.repository?.issues + * }) + * return yield* Stream.runCollect(Stream.map(pages, (page) => page.pageInfo.endCursor)) + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => ["c1", null] + * ``` + * + * @stability experimental + * @category paging + * @since 4.0.0 + */ +export const pages = ( + method: OperationMethod, + options: { + readonly variables: PagingVariables> + readonly connection: (result: GraphQL.Result) => C | null | undefined + readonly options?: { + readonly headers?: Headers.Input | undefined + readonly urlParams?: UrlParams.Input | undefined + readonly context?: Context.Context | undefined + } | undefined + } +): Stream.Stream, Exclude, R2>> => { + // Type boundary: `method`'s strict overload, with `variables` widened. + // `PagingVariables` has already checked that `options.variables` plus an + // optional string `after` are the operation's variables, but the overloads' + // conditional parameter types over a generic `Op` cannot carry that here. + const call = method as unknown as ( + variables: unknown, + options: CallOptions | undefined + ) => Effect.Effect, GraphQL.Error, Exclude, R2>> + // The state is the cursor to send; the first page is fetched without one. + return Stream.paginate(undefined as string | undefined, (after) => + Effect.flatMap( + call(after === undefined ? options.variables : { ...options.variables, after }, options.options), + (result): Effect.Effect, Option.Option], GraphQLClientError> => { + const paginationError = (description: string) => + Effect.fail( + new GraphQLClientError({ + operation: method.operation.name, + reason: new PaginationError({ description, cursor: after ?? null }) + }) + ) + const connection = options.connection(result) + if (connection === null || connection === undefined) { + return after === undefined + ? Effect.succeed([[], Option.none()]) + : paginationError("The connection was null on a page after the first") + } + const { endCursor, hasNextPage } = connection.pageInfo + if (!hasNextPage) return Effect.succeed([[connection], Option.none()]) + if (endCursor === null) return paginationError("hasNextPage is true but endCursor is null") + if (endCursor === after) return paginationError(`endCursor "${endCursor}" did not advance`) + return Effect.succeed([[connection], Option.some(endCursor)]) + } + )) +} + +/** + * Like {@link pages}, but emits decoded entries from `nodes`, including + * `null` entries. Use `Stream.filter(Predicate.isNotNull)` to drop them. + * For connections selecting only `edges`, use {@link pages} with + * `Stream.flatMap`. + * + * **Example** (Flattening issue numbers across pages) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql" + * + * const RepoIssues = GraphQL.query("RepoIssues", { + * document: "query RepoIssues($owner:String!,$name:String!,$after:String){repository(owner:$owner,name:$name){issues(first:2,after:$after){pageInfo{hasNextPage endCursor}nodes{number}}}}", + * variables: { owner: Schema.String, name: Schema.String, after: Schema.optional(Schema.NullOr(Schema.String)) }, + * result: Schema.Struct({ + * repository: Schema.NullOr(Schema.Struct({ + * issues: Schema.Struct({ + * pageInfo: Schema.Struct({ hasNextPage: Schema.Boolean, endCursor: Schema.NullOr(Schema.String) }), + * nodes: Schema.NullOr(Schema.Array(Schema.NullOr(Schema.Struct({ number: Schema.Int })))) + * }) + * })) + * }) + * }) + * + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: (request) => { + * const after = (request.variables as { after?: string }).after + * const page = after === undefined + * ? { pageInfo: { hasNextPage: true, endCursor: "c1" }, nodes: [{ number: 1 }, null] } + * : { pageInfo: { hasNextPage: false, endCursor: null }, nodes: [{ number: 3 }] } + * return Effect.succeed({ body: { data: { repository: { issues: page } } } }) + * }, + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(RepoIssues)) + * const items = GraphQLClient.items(client.RepoIssues, { + * variables: { owner: "Effect-TS", name: "effect" }, + * connection: (result) => result.repository?.issues + * }) + * return yield* Stream.runCollect(Stream.map(items, (issue) => issue?.number ?? null)) + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => [1, null, 3] + * ``` + * + * @stability experimental + * @category paging + * @since 4.0.0 + */ +export const items = ( + method: OperationMethod, + options: { + readonly variables: PagingVariables> + readonly connection: (result: GraphQL.Result) => NodesConnection | null | undefined + readonly options?: { + readonly headers?: Headers.Input | undefined + readonly urlParams?: UrlParams.Input | undefined + readonly context?: Context.Context | undefined + } | undefined + } +): Stream.Stream, Exclude, R2>> => + Stream.flatMap(pages(method, options), (connection) => Stream.fromArray(connection.nodes ?? [])) + +/** + * The options a {@link makeTest} handler receives: the `headers` and + * `urlParams` the caller passed, unchanged. Headers accept `Headers.Input`; + * unlike real transport requests, test call options are not normalized. + * + * @stability experimental + * @category testing + * @since 4.0.0 + */ +export interface TestCallOptions { + readonly headers?: Headers.Input | undefined + readonly urlParams?: UrlParams.Input | undefined +} + +/** + * A {@link makeTest} handler for one operation. Queries and mutations return + * an `Effect` and subscriptions a `Stream` of the decoded result type. + * + * @stability experimental + * @category testing + * @since 4.0.0 + */ +export type TestHandler = Op["kind"] extends "subscription" ? ( + variables: GraphQL.Variables, + options: TestCallOptions + ) => Stream.Stream, GraphQL.Error> + : ( + variables: GraphQL.Variables, + options: TestCallOptions + ) => Effect.Effect, GraphQL.Error> + +/** + * The handlers given to {@link makeTest}, keyed by operation name. Every + * handler is optional. + * + * @stability experimental + * @category testing + * @since 4.0.0 + */ +export type TestHandlers = { + readonly [Op in Ops as Op["name"]]?: TestHandler +} + +/** + * Builds a client for tests that answers each operation from a handler, + * without a protocol. + * + * **Details** + * + * Handlers receive the caller's `variables` and options unchanged and return + * values in their decoded form. Nothing is encoded, decoded or validated, and + * no middleware runs. Called with `{ partial: true }`, a method returns + * `{ data, errors: [] }`. Subscriptions are not retried. Every method carries + * `.operation`, so {@link pages} and {@link items} work on it. + * + * Calling an operation without a handler dies with an `UnimplementedError` + * defect, so `catchTag` in the code under test cannot swallow a missing stub. + * + * Methods keep the real client's types, including middleware service + * requirements. Tests must provide those services even though mocks do not + * use them. + * + * To test partial data together with `errors`, or the encode and decode path, + * provide a scripted `GraphQLProtocol` layer to {@link make} instead. + * + * **Example** (Replacing a client service in tests) + * + * ```ts import.meta.vitest + * import { Context, Effect, Layer, Schema } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup } from "effect/graphql" + * + * const RepoIssues = GraphQL.query("RepoIssues", { + * document: "query RepoIssues($owner:String!,$name:String!){repository(owner:$owner,name:$name){issues{totalCount}}}", + * variables: { owner: Schema.String, name: Schema.String }, + * result: Schema.Struct({ + * repository: Schema.NullOr(Schema.Struct({ issues: Schema.Struct({ totalCount: Schema.Int }) })) + * }) + * }) + * const GitHubGraphQLGroup = GraphQLGroup.make(RepoIssues) + * + * class GitHub extends Context.Service()("app/GitHub", { + * make: GraphQLClient.make(GitHubGraphQLGroup) + * }) {} + * + * const GitHubTest = Layer.succeed( + * GitHub, + * GraphQLClient.makeTest(GitHubGraphQLGroup)({ + * RepoIssues: ({ name }) => Effect.succeed({ repository: { issues: { totalCount: name.length } } }) + * }) + * ) + * + * const program = GitHub.use((github) => github.RepoIssues({ owner: "Effect-TS", name: "effect" })) + * + * await Effect.runPromise(program.pipe(Effect.provide(GitHubTest))) // => { repository: { issues: { totalCount: 6 } } } + * ``` + * + * @stability experimental + * @category testing + * @since 4.0.0 + */ +export const makeTest = + (group: GraphQLGroup.GraphQLGroup) => + (handlers: TestHandlers): GraphQLClient => { + // Type boundary: the mapped type keys handlers by name, which a lookup by a + // runtime name cannot follow. + const byName = handlers as Record | undefined> + return fromGroup( + group, + (operation) => + makeTestMethod(operation, Object.hasOwn(byName, operation.name) ? byName[operation.name] : undefined) + ) + } + +/** + * Builds a mock layer for a client service using {@link makeTest}. Bind the + * service and group once to expose a `layerTest(handlers)` helper on the service. + * The group fixes the operation types before the handlers are checked. + * + * **Example** (Binding a mock layer to a client service) + * + * ```ts import.meta.vitest + * import { Context, Effect, Schema } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup } from "effect/graphql" + * + * const RepoIssues = GraphQL.query("RepoIssues", { + * document: "query RepoIssues($owner:String!,$name:String!){repository(owner:$owner,name:$name){issues{totalCount}}}", + * variables: { owner: Schema.String, name: Schema.String }, + * result: Schema.Struct({ + * repository: Schema.NullOr(Schema.Struct({ issues: Schema.Struct({ totalCount: Schema.Int }) })) + * }) + * }) + * const GitHubGraphQLGroup = GraphQLGroup.make(RepoIssues) + * + * class GitHub extends Context.Service()("app/GitHub", { + * make: GraphQLClient.make(GitHubGraphQLGroup) + * }) { + * static readonly layerTest = GraphQLClient.layerTest(GitHub, GitHubGraphQLGroup) + * } + * + * const program = GitHub.use((github) => github.RepoIssues({ owner: "Effect-TS", name: "effect" })) + * + * await Effect.runPromise(program.pipe(Effect.provide(GitHub.layerTest({ + * RepoIssues: ({ name }) => Effect.succeed({ repository: { issues: { totalCount: name.length } } }) + * })))) // => { repository: { issues: { totalCount: 6 } } } + * ``` + * + * @see {@link makeTest} for mock behavior and the middleware-services limitation. + * @stability experimental + * @category testing + * @since 4.0.0 + */ +export const layerTest = ( + service: Context.Key, + group: GraphQLGroup.GraphQLGroup & (GraphQLClient extends NoInfer ? unknown : never) +) => +(handlers: TestHandlers): Layer.Layer => + // The group constraint checks that the mock satisfies the service shape. + Layer.succeed(service, makeTest(group)(handlers) as unknown as Service) + +// Handlers are called through these erased signatures; `makeTest` has +// already checked them against the operation. +type ErasedTestHandler = (variables: unknown, options: TestCallOptions) => unknown + +const makeTestMethod = (operation: GraphQL.Any, handler: ErasedTestHandler | undefined) => { + const subscription = operation.kind === "subscription" + if (handler === undefined) { + const unimplemented = () => { + const prevLimit = getStackTraceLimit() + setStackTraceLimit(2) + const error = new Error(`GraphQLClient: Unimplemented operation "${operation.name}"`) + setStackTraceLimit(prevLimit) + error.name = "UnimplementedError" + return subscription ? Stream.die(error) : Effect.die(error) + } + return Object.assign(unimplemented, { operation }) + } + const call = (variables: unknown, options: (TestCallOptions & { readonly partial?: boolean }) | undefined) => { + const run = () => handler(variables === undefined ? {} : variables, options ?? {}) + if (subscription) return Stream.suspend(run as () => Stream.Stream) + const result = Effect.suspend(run as () => Effect.Effect) + return options?.partial === true + ? Effect.map(result, (data): PartialResult => ({ data, errors: [] })) + : result + } + return Object.assign(call, { operation }) +} diff --git a/repos/effect/packages/effect/src/graphql/GraphQLClientError.ts b/repos/effect/packages/effect/src/graphql/GraphQLClientError.ts new file mode 100644 index 0000000000..8935736a7a --- /dev/null +++ b/repos/effect/packages/effect/src/graphql/GraphQLClientError.ts @@ -0,0 +1,542 @@ +/** + * Serializable GraphQL client errors with an operation name and a + * `Schema.TaggedError` reason. + * + * @stability experimental + * @since 4.0.0 + */ +import * as Duration from "../Duration.ts" +import type * as Headers from "../http/Headers.ts" +import type * as HttpClientError from "../http/HttpClientError.ts" +import { HeadersSchema } from "../internal/graphqlHeaders.ts" +import { hasProperty } from "../Predicate.ts" +import * as Schema from "../Schema.ts" + +const TypeId = "~effect/graphql/GraphQLClientError" + +/** + * One entry of a GraphQL response's `errors` array, as described by the + * GraphQL specification. + * + * **Details** + * + * `path[0]` is the response key the error belongs to, which is the alias when + * the document used one, so callers can match an error to the field it hit. + * Unknown top-level fields are preserved as JSON values, including GitHub's + * `type` field. + * + * **Example** (Finding which alias an error belongs to) + * + * ```ts import.meta.vitest + * import { Schema } from "effect" + * import { GraphQLClientError } from "effect/graphql" + * + * const error = Schema.decodeUnknownSync(GraphQLClientError.GraphQLError)({ + * message: "Could not resolve to a Repository", + * path: ["missing", "issues"], + * type: "NOT_FOUND" + * }) + * + * error.path?.[0] // => "missing" + * ``` + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const GraphQLError = Schema.StructWithRest( + Schema.Struct({ + message: Schema.String, + locations: Schema.optional(Schema.Array(Schema.Struct({ line: Schema.Number, column: Schema.Number }))), + path: Schema.optional(Schema.Array(Schema.Union([Schema.String, Schema.Number]))), + extensions: Schema.optional(Schema.Record(Schema.String, Schema.Json)) + }), + [Schema.Record(Schema.String, Schema.Json)] +) + +/** + * The decoded type of {@link GraphQLError}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type GraphQLError = typeof GraphQLError.Type + +/** + * The server answered with a non-empty `errors` array. + * + * **Details** + * + * Queries and mutations fail even when partial `data` is present, since a + * field error's `null` cannot be distinguished from a genuine `null`. Use + * `{ partial: true }` to receive decoded `{ data, errors }` instead. + * + * On this error, `data` is raw. `GraphQLError.path[0]` identifies the response + * key (or alias). Non-2xx HTTP responses with a GraphQL body also use this + * reason rather than `TransportError`. + * + * `status` and `headers` are the HTTP status and response headers, as the + * transport reported them and middleware left them. Headers use + * `Headers.Headers` at runtime and encode as a plain string record. + * Decoding restores the normalized header collection. Both are unset over + * graphql-ws, and `status` is unset for graphql-sse events. `retryAfter` + * parses the `Retry-After` response header as whole seconds or an HTTP date, + * measured from `Date.now()` when the error is constructed. `isRetryable` is + * true for HTTP status `429` or `500`–`599`, and for any response with a + * valid `Retry-After`, whatever its status. It is false otherwise, including + * when there is no status. + * + * For queries and mutations, callers opt into retries with `Effect.retry`, + * and should wait for `retryAfter` when it is set. With + * `GraphQLClient.pages`, retry each page's call, not the stream: + * `Stream.retry` starts again from the first page. Subscriptions retry a + * retryable `ResponseError` on their own, by resubscribing. graphql-sse events + * carry the stream response's headers, so an event with `errors` is retried + * when that response had a valid `Retry-After`, and ends the stream + * otherwise. + * + * **Example** (Inspecting the errors of a failed call) + * + * ```ts import.meta.vitest + * import { GraphQLClientError } from "effect/graphql" + * + * const reason = new GraphQLClientError.ResponseError({ + * errors: [{ message: "Not found", path: ["repository"] }], + * data: { repository: null }, + * status: 200 + * }) + * + * reason.isRetryable // => false + * reason.status // => 200 + * reason.errors.map((error) => error.path?.[0]) // => ["repository"] + * ``` + * + * **Example** (Retrying a call on retryable errors) + * + * ```ts import.meta.vitest + * import { Effect } from "effect" + * import { GraphQLClientError } from "effect/graphql" + * + * const call = Effect.fail(new GraphQLClientError.GraphQLClientError({ + * operation: "Viewer", + * reason: new GraphQLClientError.ResponseError({ + * errors: [{ message: "Query timed out" }], + * status: 502 + * }) + * })) + * + * const retried = Effect.retry(call, { + * while: (error) => error.reason.isRetryable, + * times: 3 + * }) + * ``` + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class ResponseError + extends Schema.TaggedError("effect/graphql/GraphQLClientError/ResponseError")("ResponseError", { + errors: Schema.NonEmptyArray(GraphQLError), + data: Schema.optional(Schema.Json), + extensions: Schema.optional(Schema.Record(Schema.String, Schema.Json)), + status: Schema.optional(Schema.Int), + headers: Schema.optional(HeadersSchema) + }) +{ + /** + * `true` for HTTP status `429` or `500`–`599`, or when the response has a + * `Retry-After` header that parses, at any status, including a graphql-sse + * event whose stream response had one; `false` otherwise, including when + * there is no status and no `Retry-After`. Use this as the `while` predicate + * of `Effect.retry` on the call, and {@link retryAfter} as the delay when it + * is set. Subscriptions resubscribe on it. + * + * @since 4.0.0 + */ + get isRetryable(): boolean { + if (this.retryAfter !== undefined) return true + return this.status !== undefined && isRetryableStatus(this.status) + } + + readonly #retryAfter = parseRetryAfter(this.headers?.["retry-after"], Date.now()) + + /** + * The `Retry-After` response header parsed as whole seconds or an HTTP + * date. An HTTP date is measured from `Date.now()` when the error is + * constructed, so every read returns the same delay. Missing or invalid + * values yield `undefined`. `Effect.retry` does not apply this delay + * automatically. + * + * @since 4.0.0 + */ + get retryAfter(): Duration.Duration | undefined { + return this.#retryAfter + } + + override get message(): string { + return this.errors.map((error) => error.message).join("; ") + } +} + +const retryableStandardCloseCodes: ReadonlySet = new Set([1000, 1001, 1005, 1006, 1012, 1013, 1014]) + +const fatalGraphQLWsCloseCodes: ReadonlySet = new Set([4400, 4401, 4403, 4406, 4409, 4429, 4500]) + +/** + * Tests whether a WebSocket close code is fatal, meaning a `TransportError` + * carrying it is not retryable. + * + * **Details** + * + * Fatal codes are every standard `1xxx` code except `1000`, `1001`, `1005`, + * `1006`, `1012`, `1013` and `1014`, plus the graphql-ws codes `4400` (bad + * request), `4401` (unauthorized), `4403` (forbidden), `4406` (subprotocol + * not acceptable), `4409` (subscriber already exists), `4429` (too many + * initialisation requests) and `4500` (internal server error). Any other code + * is retryable. + * + * `4403` is fatal because reconnecting with the same credentials is refused + * again. + * + * **Example** (Checking close codes) + * + * ```ts import.meta.vitest + * import { GraphQLClientError } from "effect/graphql" + * + * GraphQLClientError.isFatalCloseCode(1006) // => false + * GraphQLClientError.isFatalCloseCode(1011) // => true + * GraphQLClientError.isFatalCloseCode(4401) // => true + * ``` + * + * @stability experimental + * @category predicates + * @since 4.0.0 + */ +export const isFatalCloseCode = (code: number): boolean => + code >= 1000 && code < 2000 ? !retryableStandardCloseCodes.has(code) : fatalGraphQLWsCloseCodes.has(code) + +const isRetryableStatus = (status: number): boolean => status === 429 || (status >= 500 && status < 600) + +/** + * Parses a `Retry-After` header value, either whole seconds or an HTTP date, + * into a `Duration` measured from `now` (epoch milliseconds). Anything else, + * such as `1.5` or `-1`, yields `undefined`. + */ +const parseRetryAfter = (value: string | undefined, now: number): Duration.Duration | undefined => { + if (value === undefined) return undefined + const trimmed = value.trim() + if (/^\d+$/.test(trimmed)) { + return Duration.seconds(Number(trimmed)) + } + // Every HTTP date names a day or month; `Date.parse` alone also accepts + // bare numbers such as `1.5` or `-1`. + if (!/[a-z]/i.test(trimmed)) return undefined + const date = Date.parse(trimmed) + if (Number.isNaN(date)) return undefined + return Duration.millis(Math.max(0, date - now)) +} + +/** + * The client could not get a GraphQL response from the server: a network + * failure, an HTTP response that is not a GraphQL response, or a closed + * WebSocket connection. + * + * **Details** + * + * - `status` and `headers` are only set for an HTTP response that is not a + * GraphQL response. Headers use `Headers.Headers` at runtime and encode + * as a plain string record; decoding restores the header collection. + * - `retryAfter` comes from the `Retry-After` header (whole seconds or an + * HTTP date) and is encoded as milliseconds. When it is set, the error is + * retryable at any status, unless the close code is fatal. + * - `closeCode` is set when a WebSocket connection closed. See + * {@link isFatalCloseCode} for the codes that are not retryable. + * - `fatal: true` marks a failure that retrying cannot fix, such as an + * operation on a graphql-ws transport whose scope has closed. + * - `cause` holds the original error, such as the `HttpClientError`. Once + * encoded it shrinks to `{ name, message }`, the standard `Schema.Defect` + * behaviour. + * + * **Example** (Retryability of transport failures) + * + * ```ts import.meta.vitest + * import { GraphQLClientError } from "effect/graphql" + * + * new GraphQLClientError.TransportError({ description: "ECONNREFUSED" }).isRetryable // => true + * new GraphQLClientError.TransportError({ description: "503", status: 503 }).isRetryable // => true + * new GraphQLClientError.TransportError({ description: "404", status: 404 }).isRetryable // => false + * new GraphQLClientError.TransportError({ description: "closed", closeCode: 4401 }).isRetryable // => false + * new GraphQLClientError.TransportError({ description: "shut down", fatal: true }).isRetryable // => false + * ``` + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class TransportError + extends Schema.TaggedError("effect/graphql/GraphQLClientError/TransportError")("TransportError", { + description: Schema.String, + status: Schema.optional(Schema.Int), + headers: Schema.optional(HeadersSchema), + retryAfter: Schema.optional(Schema.DurationFromMillis), + closeCode: Schema.optional(Schema.Int), + fatal: Schema.optional(Schema.Boolean), + cause: Schema.optional(Schema.Defect()) + }) +{ + /** + * `true` for a network failure (no `status`), a `429` or `500`–`599` + * status, a `retryAfter` at any status, and any close code that is not + * fatal (see {@link isFatalCloseCode}). An error marked `fatal` or with a + * fatal close code is never retryable. When retrying, wait for + * `retryAfter` when it is set. + * + * @since 4.0.0 + */ + get isRetryable(): boolean { + if (this.fatal === true) return false + if (this.closeCode !== undefined && isFatalCloseCode(this.closeCode)) return false + if (this.retryAfter !== undefined) return true + return this.status === undefined || isRetryableStatus(this.status) + } + + override get message(): string { + return this.description + } + + /** + * Converts an `HttpClientError` into a `TransportError`, reading `status`, + * `headers` (as `Headers.Headers`) and `Retry-After` from the response + * when there is one. + * + * **Details** + * + * `Retry-After` is read as whole seconds or an HTTP date; any other value + * is ignored. An HTTP date is measured from `options.now` (epoch + * milliseconds), which defaults to `Date.now()`. Transports pass the Effect + * clock's time when the response arrives. + * + * @since 4.0.0 + */ + static fromHttpClientError( + error: HttpClientError.HttpClientError, + options?: { readonly now?: number | undefined } + ): TransportError { + const response = error.response + return new TransportError({ + description: error.message, + status: response?.status, + headers: response?.headers, + retryAfter: parseRetryAfter(response?.headers["retry-after"], options?.now ?? Date.now()), + cause: error + }) + } +} + +/** + * The variables Schema rejected the input, so nothing was sent. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class EncodeError + extends Schema.TaggedError("effect/graphql/GraphQLClientError/EncodeError")("EncodeError", { + description: Schema.String + }) +{ + /** + * An `EncodeError` is never retryable. + * + * @since 4.0.0 + */ + get isRetryable(): boolean { + return false + } + + override get message(): string { + return this.description + } +} + +/** + * The response was not a GraphQL response, or `data` did not match the result + * Schema. + * + * **Details** + * + * `data: null` without `errors` also produces a `DecodeError`, since + * `ResponseError` requires a non-empty errors array. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class DecodeError + extends Schema.TaggedError("effect/graphql/GraphQLClientError/DecodeError")("DecodeError", { + description: Schema.String + }) +{ + /** + * A `DecodeError` is never retryable. + * + * @since 4.0.0 + */ + get isRetryable(): boolean { + return false + } + + override get message(): string { + return this.description + } +} + +/** + * Cursor paging could not continue. Only `GraphQLClient.pages` and + * `GraphQLClient.items` raise it, when a connection becomes `null` on a page + * after the first, or when `hasNextPage` is `true` but `endCursor` is `null` + * or did not advance. + * + * **Details** + * + * `cursor` is the last cursor that was sent, `null` on the first page. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class PaginationError + extends Schema.TaggedError("effect/graphql/GraphQLClientError/PaginationError")("PaginationError", { + description: Schema.String, + cursor: Schema.NullOr(Schema.String) + }) +{ + /** + * A `PaginationError` is never retryable. + * + * @since 4.0.0 + */ + get isRetryable(): boolean { + return false + } + + override get message(): string { + return this.description + } +} + +/** + * The union of every reason a {@link GraphQLClientError} can carry. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type Reason = ResponseError | TransportError | EncodeError | DecodeError | PaginationError + +const httpReason = (reason: Reason): ResponseError | TransportError | undefined => + reason._tag === "ResponseError" || reason._tag === "TransportError" ? reason : undefined + +/** + * The error every `GraphQLClient` method fails with. It names the operation + * and carries one of the five reasons; `cause` is the reason itself. + * + * **Example** (Retrying only what is retryable) + * + * ```ts import.meta.vitest + * import { Duration, Schema } from "effect" + * import { GraphQLClientError } from "effect/graphql" + * + * const error = new GraphQLClientError.GraphQLClientError({ + * operation: "Viewer", + * reason: new GraphQLClientError.TransportError({ + * description: "503 Service Unavailable", + * status: 503, + * retryAfter: Duration.seconds(30) + * }) + * }) + * + * error.isRetryable // => true + * error.retryAfter // => Duration.seconds(30) + * + * // Errors round-trip through their Schema + * const encoded = Schema.encodeSync(GraphQLClientError.GraphQLClientError)(error) + * Schema.decodeUnknownSync(GraphQLClientError.GraphQLClientError)(encoded).reason._tag // => "TransportError" + * ``` + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class GraphQLClientError extends Schema.TaggedError(TypeId)("GraphQLClientError", { + operation: Schema.String, + reason: Schema.Union([ResponseError, TransportError, EncodeError, DecodeError, PaginationError]) +}) { + /** + * Marks this value as a GraphQL client error for runtime guards. + * + * @stability experimental + * @since 4.0.0 + */ + readonly [TypeId] = TypeId + + /** + * The reason, exposed as the error's cause. + * + * @since 4.0.0 + */ + override readonly cause = this.reason + + /** + * Delegates to the reason's `isRetryable`. + * + * @since 4.0.0 + */ + get isRetryable(): boolean { + return this.reason.isRetryable + } + + /** + * The `Retry-After` hint of a `ResponseError` or `TransportError` reason, + * if any. Use it as the delay when retrying on {@link isRetryable}. + * + * @since 4.0.0 + */ + get retryAfter(): Duration.Duration | undefined { + return httpReason(this.reason)?.retryAfter + } + + /** + * The HTTP status of a `ResponseError` or `TransportError` reason, if any. + * + * @since 4.0.0 + */ + get status(): number | undefined { + return httpReason(this.reason)?.status + } + + /** + * The response headers of a `ResponseError` or `TransportError` reason, if + * any. + * + * @since 4.0.0 + */ + get headers(): Headers.Headers | undefined { + return httpReason(this.reason)?.headers + } + + override get message(): string { + return `${this.operation}: ${this.reason._tag}: ${this.reason.message}` + } +} + +/** + * Tests whether a value is a {@link GraphQLClientError}. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isGraphQLClientError = (u: unknown): u is GraphQLClientError => hasProperty(u, TypeId) diff --git a/repos/effect/packages/effect/src/graphql/GraphQLGroup.ts b/repos/effect/packages/effect/src/graphql/GraphQLGroup.ts new file mode 100644 index 0000000000..009724cd33 --- /dev/null +++ b/repos/effect/packages/effect/src/graphql/GraphQLGroup.ts @@ -0,0 +1,167 @@ +/** + * Groups of GraphQL operations, merged to build a client. Group middleware + * runs outside operation middleware. `@effect/graphql-generator` emits one + * group per document file. + * + * @stability experimental + * @since 4.0.0 + */ +import { type Pipeable, pipeArguments } from "../Pipeable.ts" +import { hasProperty } from "../Predicate.ts" +import type * as GraphQL from "./GraphQL.ts" +import type * as GraphQLMiddleware from "./GraphQLMiddleware.ts" + +const TypeId = "~effect/graphql/GraphQLGroup" + +/** + * A set of operations plus the middleware attached at the group level. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface GraphQLGroup extends Pipeable { + readonly [TypeId]: typeof TypeId + readonly operations: ReadonlyArray + /** Middleware attached to the group, outermost first. */ + readonly middlewares: ReadonlyArray + /** + * Attaches a middleware to every operation in the group. Group middleware + * runs outside operation middleware; several group middleware run in the + * order attached. + */ + middleware(middleware: M): GraphQLGroup> +} + +/** + * Any group, with its operations erased. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Any = GraphQLGroup + +/** + * Extracts the union of operations in a group. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Operations = G extends GraphQLGroup ? Ops : never + +/** + * Tests whether a value is a {@link GraphQLGroup}. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isGraphQLGroup = (u: unknown): u is Any => hasProperty(u, TypeId) + +const Proto = { + [TypeId]: TypeId, + pipe() { + return pipeArguments(this, arguments) + }, + middleware(this: Any, middleware: GraphQLMiddleware.AnyService) { + return makeProto(this.operations, [...this.middlewares, middleware]) + } +} + +// The operation and middleware types of a group are phantom: at runtime a +// group holds erased `GraphQL.Any` operations and `AnyService` tags, so the +// typed constructors below state their group type with one assertion each. +const makeProto = ( + operations: ReadonlyArray, + middlewares: ReadonlyArray +): Any => { + const byName = new Map() + for (const operation of operations) { + const existing = byName.get(operation.name) + if (existing !== undefined && existing !== operation) { + throw new Error(`GraphQLGroup: duplicate operation name "${operation.name}"`) + } + byName.set(operation.name, operation) + } + return Object.assign(Object.create(Proto), { operations: Array.from(byName.values()), middlewares }) +} + +/** + * Builds a group from operations. Operation names must be unique within a + * group, because they become the client's method names. + * + * **Example** (One group per `.graphql` file) + * + * ```ts import.meta.vitest + * import { Schema } from "effect" + * import { GraphQL, GraphQLGroup } from "effect/graphql" + * + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * + * const ViewerGraphQLGroup = GraphQLGroup.make(Viewer) + * + * ViewerGraphQLGroup.operations.map((op) => op.name) // => ["Viewer"] + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const make = >(...operations: Ops): GraphQLGroup => + makeProto(operations, []) as GraphQLGroup + +/** + * Merges groups into one. Middleware attached to a source group stays + * attached to that group's operations; middleware attached to the merged + * group afterwards runs outside all of it. + * + * **Example** (Auth on one file, logging on everything) + * + * ```ts import.meta.vitest + * import { Schema } from "effect" + * import { GraphQL, GraphQLGroup, GraphQLMiddleware } from "effect/graphql" + * + * class Auth extends GraphQLMiddleware.Service()("app/Auth") {} + * class Logging extends GraphQLMiddleware.Service()("app/Logging") {} + * + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * const Rate = GraphQL.query("Rate", { + * document: "query Rate{rateLimit{remaining}}", + * result: Schema.Struct({ rateLimit: Schema.Struct({ remaining: Schema.Int }) }) + * }) + * + * const all = GraphQLGroup.merge(GraphQLGroup.make(Viewer).middleware(Auth), GraphQLGroup.make(Rate)) + * .middleware(Logging) + * + * all.operations.map((op) => op.name) // => ["Viewer", "Rate"] + * all.middlewares.map((m) => m.key) // => ["app/Logging"] + * all.operations[0].middlewares.map((m) => m.key) // => ["app/Auth"] + * ``` + * + * @stability experimental + * @category combinators + * @since 4.0.0 + */ +export const merge = >( + ...groups: Groups +): GraphQLGroup> => + makeProto( + groups.flatMap((group) => + group.middlewares.length === 0 + ? group.operations + : group.operations.map((operation): GraphQL.Any => + Object.assign(Object.create(Object.getPrototypeOf(operation)), operation, { + middlewares: [...group.middlewares, ...operation.middlewares] + }) + ) + ), + [] + ) as GraphQLGroup> diff --git a/repos/effect/packages/effect/src/graphql/GraphQLMiddleware.ts b/repos/effect/packages/effect/src/graphql/GraphQLMiddleware.ts new file mode 100644 index 0000000000..88d37f4873 --- /dev/null +++ b/repos/effect/packages/effect/src/graphql/GraphQLMiddleware.ts @@ -0,0 +1,253 @@ +/** + * GraphQL-level middleware provided as `Context.Service` implementations. + * Middleware can rewrite requests and inspect raw results, including response + * extensions and HTTP headers. Provide implementations with `Layer.succeed` + * or `Layer.effect`. + * + * @stability experimental + * @since 4.0.0 + */ +import * as Context from "../Context.ts" +import * as Effect from "../Effect.ts" +import * as Stream from "../Stream.ts" +import type * as Types from "../Types.ts" +import type * as GraphQL from "./GraphQL.ts" +import type { GraphQLClientError } from "./GraphQLClientError.ts" +import type { ExecutionResult, GraphQLRequest } from "./GraphQLProtocol.ts" + +const TypeId = "~effect/graphql/GraphQLMiddleware" + +/** + * Middleware handlers for queries, mutations and subscriptions. Both + * `execute` and `subscribe` are required. + * + * **Details** + * + * `execute` runs once per query or mutation. `subscribe` runs once per + * subscription attempt (the client re-runs the whole chain when it retries a + * subscription) and can map or tap the event stream. + * + * Both receive the operation being run, the request so far, and `next`, which + * runs the rest of the chain with the given request and returns the raw + * `ExecutionResult` (or, for `subscribe`, the stream of them). Its `status` + * and `headers` are the HTTP status and response headers the transport + * reported, if any; a middleware may rewrite them, and a failed call's + * `ResponseError` carries the final values. Request and response headers + * are `Headers.Headers` values; use `Headers.set` to rewrite them. + * + * `next` fails with `GraphQLClientError`, or with the error of a middleware + * further in, which is typed as `Types.unhandled`, as in `RpcMiddleware`. + * Narrow it, for example with `Effect.catchTag("GraphQLClientError", ...)`, + * before reading `reason`. + * + * Use {@link mapRequest} when the middleware only needs to transform the + * request. + * + * **Example** (Reading a rate-limit header) + * + * ```ts import.meta.vitest + * import { Effect } from "effect" + * import { GraphQLMiddleware } from "effect/graphql" + * import { Headers } from "effect/http" + * + * const rateLimit: GraphQLMiddleware.Implementation = { + * execute: ({ next, request }) => + * Effect.tap(next(request), (result) => + * Effect.log(result.headers === undefined ? undefined : Headers.get(result.headers, "x-ratelimit-remaining")) + * ), + * subscribe: ({ next, request }) => next(request) + * } + * ``` + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Implementation { + readonly execute: (options: { + readonly operation: GraphQL.Any + readonly request: GraphQLRequest + readonly next: (request: GraphQLRequest) => Effect.Effect + }) => Effect.Effect + readonly subscribe: (options: { + readonly operation: GraphQL.Any + readonly request: GraphQLRequest + readonly next: (request: GraphQLRequest) => Stream.Stream + }) => Stream.Stream +} + +/** + * The class returned by {@link Service}: a `Context.Service` for an + * {@link Implementation}, carrying the declared `error` and `requires` types. + * + * @stability experimental + * @category services + * @since 4.0.0 + */ +export interface ServiceClass extends Context.Service> { + new(_: never): Context.ServiceClass.Shape> & { + readonly [TypeId]: { readonly error: E; readonly requires: R } + } + readonly [TypeId]: { readonly error: E; readonly requires: R } + readonly key: Key +} + +/** + * Any middleware service class, with its error and requirement types erased. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export interface AnyService extends Context.Service> { + readonly [TypeId]: { readonly error: any; readonly requires: any } +} + +/** + * Extracts the service identifier of a middleware, which is what + * `GraphQLClient.make` requires. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Identifier = M extends Context.Service ? I : never + +/** + * Extracts the error type a middleware declared. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Error = M extends { readonly [TypeId]: { readonly error: infer E } } ? E : never + +/** + * Extracts the services a middleware declared it requires per call. + * + * @stability experimental + * @category utility types + * @since 4.0.0 + */ +export type Requires = M extends { readonly [TypeId]: { readonly requires: infer R } } ? R : never + +/** + * Declares a middleware tag. `requires` are services the implementation needs + * on every call, and `error` is what it can fail with; both show up on the + * requirements and error type of every client method the middleware is + * attached to. + * + * **Example** (An auth middleware that needs the current user) + * + * ```ts import.meta.vitest + * import { Context, Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLMiddleware, GraphQLProtocol } from "effect/graphql" + * import { Headers } from "effect/http" + * + * class CurrentUser extends Context.Service()("CurrentUser") {} + * class TokenExpired extends Schema.TaggedError()("TokenExpired", {}) {} + * + * class Auth extends GraphQLMiddleware.Service()("app/Auth") {} + * + * const AuthLive = Layer.succeed( + * Auth, + * GraphQLMiddleware.mapRequest(Effect.fnUntraced(function*(request) { + * const user = yield* CurrentUser + * if (user.token === "") return yield* new TokenExpired() + * return { ...request, headers: Headers.set(request.headers, "authorization", `Bearer ${user.token}`) } + * })) + * ) + * + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: (request) => Effect.succeed({ body: { data: { viewer: { login: request.headers.authorization } } } }), + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer).middleware(Auth)) + * // CurrentUser is required by the method because Auth is attached + * return yield* client.Viewer().pipe(Effect.provideService(CurrentUser, { token: "abc" })) + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide([Scripted, AuthLive]))) // => { viewer: { login: "Bearer abc" } } + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const Service = < + Self, + Config extends { + readonly requires?: any + readonly error?: any + } = {} +>(): (key: Key) => ServiceClass< + Self, + Key, + Config extends { readonly error: infer E } ? E : never, + Config extends { readonly requires: infer R } ? R : never +> => +(key: string) => { + function ServiceClass() {} + Object.setPrototypeOf(ServiceClass, Object.getPrototypeOf(Context.Service(key))) + return Object.assign(ServiceClass, { key, [TypeId]: TypeId }) as any +} + +/** + * Builds an {@link Implementation} that transforms requests for queries, + * mutations and subscriptions. Use it to set headers, auth or extensions. + * + * **Example** (Adding a header to every request) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLMiddleware, GraphQLProtocol } from "effect/graphql" + * import { Headers } from "effect/http" + * + * class RequestId extends GraphQLMiddleware.Service()("app/RequestId") {} + * + * const RequestIdLive = Layer.succeed( + * RequestId, + * GraphQLMiddleware.mapRequest((request) => + * Effect.succeed({ ...request, headers: Headers.set(request.headers, "x-request-id", "abc") }) + * ) + * ) + * + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: (request) => + * Effect.succeed({ body: { data: { viewer: { login: request.headers["x-request-id"] } } } }), + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer).middleware(RequestId)) + * return yield* client.Viewer() + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide([Scripted, RequestIdLive]))) // => { viewer: { login: "abc" } } + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const mapRequest = ( + f: (request: GraphQLRequest, operation: GraphQL.Any) => Effect.Effect +): Implementation => ({ + execute: ({ next, operation, request }) => Effect.flatMap(f(request, operation), next), + subscribe: ({ next, operation, request }) => Stream.unwrap(Effect.map(f(request, operation), next)) +}) diff --git a/repos/effect/packages/effect/src/graphql/GraphQLProtocol.ts b/repos/effect/packages/effect/src/graphql/GraphQLProtocol.ts new file mode 100644 index 0000000000..2985d62db7 --- /dev/null +++ b/repos/effect/packages/effect/src/graphql/GraphQLProtocol.ts @@ -0,0 +1,1072 @@ +/** + * Transports for `GraphQLClient`. They accept encoded requests and return raw + * response bodies with available HTTP status and headers, without schema + * decoding or middleware. + * + * - {@link layerHttp} uses HTTP POST (or GET for queries) and graphql-sse + * subscriptions, with an optional graphql-ws subscription transport. + * - {@link layerWebSocket} multiplexes all operations over graphql-ws. + * + * {@link makeHttp} and {@link makeWebSocket} construct the same transports as effects. + * + * @stability experimental + * @since 4.0.0 + */ +import * as Cause from "../Cause.ts" +import * as Clock from "../Clock.ts" +import * as Context from "../Context.ts" +import * as Deferred from "../Deferred.ts" +import * as Duration from "../Duration.ts" +import * as Effect from "../Effect.ts" +import * as Sse from "../encoding/Sse.ts" +import * as Fiber from "../Fiber.ts" +import { constant } from "../Function.ts" +import * as Headers from "../http/Headers.ts" +import * as HttpClient from "../http/HttpClient.ts" +import * as HttpClientError from "../http/HttpClientError.ts" +import * as HttpClientRequest from "../http/HttpClientRequest.ts" +import * as HttpClientResponse from "../http/HttpClientResponse.ts" +import * as UrlParams from "../http/UrlParams.ts" +import * as internalGraphQL from "../internal/graphql.ts" +import { HeadersSchema } from "../internal/graphqlHeaders.ts" +import * as Layer from "../Layer.ts" +import * as Queue from "../Queue.ts" +import * as Result from "../Result.ts" +import * as Schema from "../Schema.ts" +import type * as Scope from "../Scope.ts" +import * as Socket from "../socket/Socket.ts" +import * as Stream from "../Stream.ts" +import type { Kind } from "./GraphQL.ts" +import { GraphQLError, TransportError } from "./GraphQLClientError.ts" + +/** + * The request a transport sends. Middleware sees and may rewrite it before it + * reaches the transport. + * + * **Details** + * + * `kind` is the operation type, which the HTTP transport uses to send queries + * as `GET` when `queryMethod: "GET"` is set. `variables` are already encoded + * through the operation's variables Schema. + * + * `headers` and `urlParams` are applied by the HTTP transport, to queries, + * mutations and graphql-sse subscriptions alike. A graphql-ws transport + * ignores both, because graphql-ws has no per-operation headers or URL. + * Request headers are normalized, immutable `Headers.Headers` values. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface GraphQLRequest { + readonly kind: Kind + readonly query: string + readonly operationName: string + readonly variables: unknown + readonly extensions?: Record | undefined + readonly headers: Headers.Headers + readonly urlParams: UrlParams.UrlParams +} + +/** + * A raw GraphQL result before schema decoding. Middleware receive it from + * `next` and can read response `extensions`, such as rate-limit costs. + * + * **Details** + * + * `status` and `headers` are transport metadata, not part of the GraphQL + * response body: the client decodes the body without them and then copies + * what the transport reported. Middleware may read or rewrite them, and a + * failed call's `ResponseError` carries the final values. Headers use + * `Headers.Headers` at runtime and encode as a plain string record. + * + * @stability experimental + * @category schemas + * @since 4.0.0 + */ +export const ExecutionResult = Schema.Struct({ + data: Schema.optional(Schema.Unknown), + errors: Schema.optional(Schema.Array(GraphQLError)), + extensions: Schema.optional(Schema.Record(Schema.String, Schema.Json)), + status: Schema.optional(Schema.Int), + headers: Schema.optional(HeadersSchema) +}) + +/** + * The decoded type of {@link ExecutionResult}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type ExecutionResult = typeof ExecutionResult.Type + +/** + * The transport service. `execute` answers a query or mutation with the raw + * JSON body, and `subscribe` turns a subscription into a stream of raw events. + * Both fail only with `TransportError`; GraphQL `errors` are left in the body + * for the client to interpret. + * + * **Details** + * + * Each answer is `{ body, status?, headers? }`. The HTTP transport sets + * `headers` on every answer, including graphql-sse events, and `status` on + * all but graphql-sse events. Headers are `Headers.Headers` values. + * graphql-ws leaves both unset. + * + * **Example** (A scripted transport for tests) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql" + * + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: () => Effect.succeed({ body: { data: { viewer: { login: "tim" } } } }), + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer)) + * return yield* client.Viewer() + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => { viewer: { login: "tim" } } + * ``` + * + * @stability experimental + * @category services + * @since 4.0.0 + */ +export class GraphQLProtocol extends Context.Service Effect.Effect<{ + readonly body: unknown + readonly status?: number | undefined + readonly headers?: Headers.Headers | undefined + }, TransportError> + readonly subscribe: (request: GraphQLRequest) => Stream.Stream<{ + readonly body: unknown + readonly status?: number | undefined + readonly headers?: Headers.Headers | undefined + }, TransportError> + /** + * Resolves the transport URL for resolver batching. Set by `layerHttp`; + * optional for custom transports. + */ + readonly url?: + | ((options: { readonly kind: Kind; readonly operationName: string }) => Effect.Effect) + | undefined +}>()("effect/graphql/GraphQLProtocol") {} + +/** + * The URL of an HTTP transport: fixed, resolved for each operation from the + * calling context, `kind` and `operationName`, or an `Effect` with no errors + * or requirements. See {@link layerHttp}. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type Url = + | string + | Effect.Effect + | ((options: { + readonly context: Context.Context + readonly kind: Kind + readonly operationName: string + }) => string) + +const graphqlResponseContentType = "application/graphql-response+json" +const jsonContentType = "application/json" +const eventStreamContentType = "text/event-stream" + +const isObject = (u: unknown): u is Record => typeof u === "object" && u !== null && !Array.isArray(u) + +// A gateway's `{ "errors": "Throttled" }` is not a GraphQL response, so its +// status and Retry-After still apply. +const isGraphQLBody = (body: unknown): boolean => + isObject(body) && ("data" in body || "errors" in body) && + (!("errors" in body) || Array.isArray(body.errors)) && + (!("data" in body) || body.data === null || isObject(body.data)) + +// The JSON body of a POST and the payload of a graphql-ws `subscribe`. +// `extensions` is dropped from the JSON when unset. +const requestBody = (request: GraphQLRequest) => ({ + query: request.query, + operationName: request.operationName, + variables: request.variables, + extensions: request.extensions +}) + +const postRequest = (url: string, request: GraphQLRequest, accept: string) => + HttpClientRequest.post(url).pipe( + HttpClientRequest.setHeaders(request.headers), + HttpClientRequest.setHeader("accept", accept), + HttpClientRequest.appendUrlParams(request.urlParams), + HttpClientRequest.bodyJsonUnsafe(requestBody(request)) + ) + +const graphqlGetParams = new Set(["query", "operationName", "variables", "extensions"]) + +// Remove all protocol params from the configured URL and caller params before +// adding the request's values, including when optional fields are unset. Split +// the URL without resolving it so relative URLs remain supported. +const getRequest = (url: string, request: GraphQLRequest, accept: string) => { + const hashIndex = url.indexOf("#") + const hash = hashIndex === -1 ? "" : url.slice(hashIndex) + const withoutHash = hashIndex === -1 ? url : url.slice(0, hashIndex) + const queryIndex = withoutHash.indexOf("?") + const baseUrl = queryIndex === -1 ? withoutHash : withoutHash.slice(0, queryIndex) + const urlParams = [ + ...UrlParams.fromInput(new URLSearchParams(queryIndex === -1 ? "" : withoutHash.slice(queryIndex + 1))), + ...request.urlParams + ].filter(([key]) => !graphqlGetParams.has(key)) + const params: Record = { query: request.query, operationName: request.operationName } + if (request.variables !== undefined) params.variables = JSON.stringify(request.variables) + if (request.extensions !== undefined) params.extensions = JSON.stringify(request.extensions) + return HttpClientRequest.get(baseUrl + hash).pipe( + HttpClientRequest.setHeaders(request.headers), + HttpClientRequest.setHeader("accept", accept), + HttpClientRequest.appendUrlParams(urlParams), + HttpClientRequest.setUrlParams(params) + ) +} + +// Reads the clock when the error arrives, so an HTTP-date `Retry-After` is +// measured from when the response was received. +const fromHttpClientError = + (clock: Clock.Clock) => + (effect: Effect.Effect): Effect.Effect => + Effect.catch(effect, (error) => + Effect.fail( + HttpClientError.isHttpClientError(error) + ? TransportError.fromHttpClientError(error, { now: clock.currentTimeMillisUnsafe() }) + : error + )) + +// Media types are case-insensitive. +const contentTypeOf = (response: HttpClientResponse.HttpClientResponse): string => + (response.headers["content-type"] ?? "").toLowerCase() + +const readResponse = ( + response: HttpClientResponse.HttpClientResponse +): Effect.Effect => { + const contentType = contentTypeOf(response) + // The GraphQL-over-HTTP media type is authoritative, whatever the status. + if (contentType.includes(graphqlResponseContentType)) { + return response.json + } + // Legacy servers answer with application/json; only a body with the + // GraphQL keys counts as a GraphQL response. + if (contentType.includes(jsonContentType)) { + return Effect.flatMap(response.json, (body) => + isGraphQLBody(body) + ? Effect.succeed(body) + : Effect.as(HttpClientResponse.filterStatusOk(response), body)) + } + return Effect.flatMap( + HttpClientResponse.filterStatusOk(response), + () => + Effect.fail( + new TransportError({ + description: `Expected a GraphQL response, received ${ + contentType === "" ? "no Content-Type" : `Content-Type ${contentType}` + }`, + status: response.status, + headers: response.headers + }) + ) + ) +} + +const readAnswer = (response: HttpClientResponse.HttpClientResponse) => + Effect.map(readResponse(response), (body) => ({ body, status: response.status, headers: response.headers })) + +const errorMessage = (cause: unknown): string => cause instanceof Error ? cause.message : String(cause) + +// The graphql-sse distinct-mode events of a `text/event-stream` body. The +// stream ends on a `complete` event, with or without a `data:` line. A body +// that ends without one means the connection was lost, so it fails with a +// retryable `TransportError`. A `retry:` line is kept and reported as +// `retryAfter` if the body fails or ends early. +const sseEvents = ( + response: HttpClientResponse.HttpClientResponse +): Stream.Stream<{ readonly body: unknown; readonly headers: Headers.Headers }, TransportError> => + Stream.suspend(() => { + const headers = response.headers + let retryAfter: Duration.Duration | undefined + let complete = false + let events: Array = [] + const parser = Sse.makeParser((event) => { + if (event._tag === "Retry") { + retryAfter = event.duration + } else { + events.push(event) + } + }, { dispatchEmptyNamedEvents: true }) + return response.stream.pipe( + Stream.decodeText(), + Stream.mapError((cause) => + new TransportError({ description: `The graphql-sse stream failed: ${cause.message}`, retryAfter, cause }) + ), + Stream.mapEffect((text) => { + const error = parser.feed(text) + if (error !== undefined) { + return Effect.fail(new TransportError({ description: error.message, cause: error })) + } + const batch = events + events = [] + return Effect.succeed(batch) + }), + Stream.flattenIterable, + Stream.takeWhile((event) => { + if (event.event === "complete") complete = true + return !complete + }), + Stream.filter((event) => event.event === "next"), + Stream.mapEffect((event) => + Effect.try({ + try: () => ({ body: JSON.parse(event.data) as unknown, headers }), + catch: (cause) => + new TransportError({ description: `Invalid graphql-sse next event: ${errorMessage(cause)}`, cause }) + }) + ), + Stream.concat(Stream.suspend(() => + complete ? Stream.empty : Stream.fail( + new TransportError({ description: "The graphql-sse stream ended without a complete event", retryAfter }) + ) + )) + ) + }) + +interface HttpOptions { + readonly url: Url + readonly queryMethod?: "GET" | "POST" | undefined + readonly subscriptions?: { + readonly webSocket: WebSocketOptions + } | undefined +} + +const makeHttpWith = (options: HttpOptions): Effect.Effect< + GraphQLProtocol["Service"], + never, + HttpClient.HttpClient | Socket.WebSocketConstructor | Scope.Scope | R +> => { + const resolve = urlResolver(options.url) + // A resolver batch carries the URL it was grouped by. + const urlOf = (request: GraphQLRequest) => + internalGraphQL.ResolvedUrl.use((resolved) => + resolved?.resolve === resolve ? Effect.succeed(resolved.url) : resolve(request) + ) + const http = Clock.clockWith((clock) => + HttpClient.HttpClient.useSync((client) => { + const execute = (request: GraphQLRequest) => + Effect.flatMap(Effect.zip(Effect.service(internalGraphQL.ForcePost), urlOf(request)), ([forcePost, url]) => { + const toRequest = options.queryMethod === "GET" && request.kind === "query" && !forcePost + ? getRequest + : postRequest + return client.execute( + toRequest(url, request, `${graphqlResponseContentType}, ${jsonContentType}`) + ).pipe( + Effect.flatMap(readAnswer), + fromHttpClientError(clock) + ) + }) + const subscribe = (request: GraphQLRequest) => + Stream.unwrap(Effect.flatMap(urlOf(request), (url) => + client.execute(postRequest(url, request, eventStreamContentType)).pipe( + Effect.flatMap((response) => { + const contentType = contentTypeOf(response) + if (contentType.includes(eventStreamContentType) && response.status >= 200 && response.status < 300) { + return Effect.succeed(sseEvents(response)) + } + // A server that rejects the subscription answers with a single + // GraphQL response, which the client reads like a query's. + return Effect.map(readAnswer(response), Stream.succeed) + }), + fromHttpClientError(clock) + ))) + return GraphQLProtocol.of({ execute, subscribe, url: resolve }) + }) + ) + const webSocket = options.subscriptions?.webSocket + return webSocket === undefined + ? http + : Effect.zipWith( + http, + makeWebSocket(webSocket), + (http, ws) => GraphQLProtocol.of({ execute: http.execute, subscribe: ws.subscribe, url: http.url }) + ) +} + +const urlResolver = (url: Url): NonNullable => { + if (typeof url === "string") return constant(Effect.succeed(url)) + if (Effect.isEffect(url)) return constant(url) + return ({ kind, operationName }) => + Effect.contextWith((context: Context.Context) => Effect.succeed(url({ context, kind, operationName }))) +} + +/** + * Builds the HTTP transport as an effect, for composing transports by hand. + * Most code uses {@link layerHttp}. + * + * **Details** + * + * Takes the same options as {@link layerHttp}, including `queryMethod`. + * Without `subscriptions`, subscriptions use graphql-sse distinct mode on + * `url`. With `subscriptions.webSocket`, `url` must be a string, subscriptions + * go over graphql-ws instead, and the effect also builds the graphql-ws + * transport, so it needs a `Socket.WebSocketConstructor` and a `Scope`. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const makeHttp: { + (options: { + readonly url: string + readonly queryMethod?: "GET" | "POST" | undefined + readonly subscriptions: { + readonly webSocket: { + readonly url: string + readonly headers?: Headers.Input | undefined + readonly connectionParams?: Effect.Effect | undefined, unknown, R> | undefined + readonly connectionAckTimeout?: Duration.Input | undefined + readonly keepAlive?: Duration.Input | false | undefined + readonly idleTimeout?: Duration.Input | undefined + } + } + }): Effect.Effect< + GraphQLProtocol["Service"], + never, + HttpClient.HttpClient | Socket.WebSocketConstructor | Scope.Scope | R + > + (options: { + readonly url: Url + readonly queryMethod?: "GET" | "POST" | undefined + readonly subscriptions?: undefined + }): Effect.Effect< + GraphQLProtocol["Service"], + never, + HttpClient.HttpClient + > +} = makeHttpWith + +/** + * The HTTP transport: queries and mutations are sent as `POST` with a JSON + * body to `url`, using the `HttpClient` in context. Subscriptions use + * graphql-sse distinct mode on the same URL, or graphql-ws when + * `subscriptions.webSocket` is set. + * + * **Details** + * + * With `queryMethod: "GET"` (default `"POST"`), queries are sent as `GET` + * with no body: `query` and `operationName` become URL params, plus + * `variables` and `extensions` as JSON when set. Mutations are always + * `POST`, and so are `GraphQLResolver.aliased` batches. A long query is not + * retried as `POST`. + * + * A request's `headers` and `urlParams`, from the call options or from + * middleware, are applied to every HTTP request. A query string already on + * `url` is kept. On `GET`, the request's `urlParams` come before the GraphQL + * params, which replace any caller param with the same name. + * + * Every response's HTTP `status` is passed to the client as + * `ExecutionResult.status`, and a call that fails with GraphQL `errors` + * reports it as `ResponseError.status`. Response headers are passed the + * same way, as `ExecutionResult.headers` and `ResponseError.headers`. + * + * A response is a GraphQL response when its `Content-Type` is + * `application/graphql-response+json`, whatever the status, or when it is + * `application/json` and the body has a list of `errors` or a `data` object + * (or `null`). Media types match case-insensitively. Anything else + * is a `TransportError` with the response `status` and `headers`, and a + * `Retry-After` header (whole seconds or an HTTP date, measured from when the + * response arrived) becomes `retryAfter`. + * + * A subscription is a `POST` with `Accept: text/event-stream`. Each `next` + * event is emitted with the response headers but no status, and the stream + * ends on a `complete` event, with or without a `data:` line. A body that + * fails, or ends without a `complete` event, is a retryable `TransportError` + * with a server `retry:` line as its `retryAfter`, so the client's + * `subscriptionRetry` resubscribes. A non-stream answer, such as a `400` with + * `errors`, is read like a query's response. Interrupting the stream aborts + * the request. + * + * With `subscriptions: { webSocket }`, subscriptions go over graphql-ws as in + * {@link layerWebSocket}, and the layer needs a `Socket.WebSocketConstructor`. + * + * To route each query, mutation and graphql-sse subscription, `url` can be a + * function of the calling fiber's context (including the call's `context` + * option), `kind` and `operationName`, or an `Effect` with no errors + * or requirements that runs in that context. Use a defaulted + * `Context.Reference` to select the server. Reading a missing service with + * `Context.get` is a defect, not a `TransportError`. Neither form can be + * combined with `subscriptions.webSocket`: the socket URL is fixed at + * connection time. + * + * **Gotchas** + * + * `GraphQLResolver` resolves each lookup's URL once, before middleware run and + * before the batched request exists, then sends each batch to the URL it was + * grouped by. A single call resolves it in the transport, after middleware. + * So the URL must depend only on the context and the operation, and + * middleware must not change `kind` or `operationName` or provide services + * the URL reads. + * + * `RequestResolver.withCache` and `RequestResolver.persisted` key on the lookup, + * not the URL, so results can leak across servers. For caching, use a separate + * client and resolver per server, for example with `LayerMap`. + * + * **Example** (Building a client over HTTP) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql" + * import { HttpClient, HttpClientResponse } from "effect/http" + * + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * + * // A stand-in for a real HttpClient layer such as FetchHttpClient.layer + * const FakeServer = Layer.succeed( + * HttpClient.HttpClient, + * HttpClient.make((request) => + * Effect.succeed(HttpClientResponse.fromWeb( + * request, + * new Response(JSON.stringify({ data: { viewer: { login: "tim" } } }), { + * headers: { "content-type": "application/graphql-response+json" } + * }) + * )) + * ) + * ) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer)) + * return yield* client.Viewer() + * }).pipe( + * Effect.provide(GraphQLProtocol.layerHttp({ url: "https://api.github.com/graphql" })), + * Effect.provide(FakeServer) + * ) + * + * await Effect.runPromise(program) // => { viewer: { login: "tim" } } + * ``` + * + * **Example** (Queries over GET with a per-call URL param) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql" + * import { HttpClient, HttpClientResponse } from "effect/http" + * + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * + * // A stand-in server that answers with the method and the `preview` param + * const FakeServer = Layer.succeed( + * HttpClient.HttpClient, + * HttpClient.make((request, url) => + * Effect.succeed(HttpClientResponse.fromWeb( + * request, + * new Response( + * JSON.stringify({ data: { viewer: { login: `${request.method} ${url.searchParams.get("preview")}` } } }), + * { headers: { "content-type": "application/graphql-response+json" } } + * ) + * )) + * ) + * ) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer)) + * return yield* client.Viewer(undefined, { urlParams: { preview: "draft-token" } }) + * }).pipe( + * Effect.provide(GraphQLProtocol.layerHttp({ url: "https://cms.example.com/graphql", queryMethod: "GET" })), + * Effect.provide(FakeServer) + * ) + * + * await Effect.runPromise(program) // => { viewer: { login: "GET draft-token" } } + * ``` + * + * **Example** (One client for github.com, GHE.com and GitHub Enterprise Server) + * + * ```ts import.meta.vitest + * import { Context, Effect, Layer, Schema } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol } from "effect/graphql" + * import { HttpClient, HttpClientResponse } from "effect/http" + * + * const Viewer = GraphQL.query("Viewer", { + * document: "query Viewer{viewer{login}}", + * result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + * }) + * + * const GitHubHost = Context.Reference("GitHubHost", { defaultValue: () => "github.com" }) + * + * const Protocol = GraphQLProtocol.layerHttp({ + * url: ({ context }) => { + * const host = Context.get(context, GitHubHost) + * if (host === "github.com") return "https://api.github.com/graphql" + * if (host.endsWith(".ghe.com")) return `https://api.${host}/graphql` + * return `https://${host}/api/graphql` + * } + * }) + * + * // Echo the request URL instead of calling GitHub. + * const FakeServer = Layer.succeed( + * HttpClient.HttpClient, + * HttpClient.make((request, url) => + * Effect.succeed(HttpClientResponse.fromWeb( + * request, + * new Response(JSON.stringify({ data: { viewer: { login: url.href } } }), { + * headers: { "content-type": "application/graphql-response+json" } + * }) + * )) + * ) + * ) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer)) + * const dotcom = yield* client.Viewer() + * const cloud = yield* client.Viewer().pipe(Effect.provideService(GitHubHost, "acme.ghe.com")) + * const server = yield* client.Viewer(undefined, { context: Context.make(GitHubHost, "github.example.com") }) + * return [dotcom, cloud, server].map((result) => result.viewer.login) + * }).pipe( + * Effect.provide(Protocol), + * Effect.provide(FakeServer) + * ) + * + * await Effect.runPromise(program) // => ["https://api.github.com/graphql", "https://api.acme.ghe.com/graphql", "https://github.example.com/api/graphql"] + * ``` + * + * **Example** (Subscriptions over graphql-ws, everything else over POST) + * + * ```ts import.meta.vitest + * import { Effect } from "effect" + * import { GraphQLProtocol } from "effect/graphql" + * + * const token = Effect.succeed("secret") + * + * // Provide an HttpClient and a Socket.WebSocketConstructor, such as + * // FetchHttpClient.layer and NodeSocket.layerWebSocketConstructor + * export const Protocol = GraphQLProtocol.layerHttp({ + * url: "https://example.com/graphql", + * subscriptions: { + * webSocket: { + * url: "wss://example.com/graphql", + * connectionParams: Effect.map(token, (token) => ({ authorization: `Bearer ${token}` })) + * } + * } + * }) + * ``` + * + * @stability experimental + * @category layers + * @since 4.0.0 + */ +export const layerHttp: { + (options: { + readonly url: string + readonly queryMethod?: "GET" | "POST" | undefined + readonly subscriptions: { + readonly webSocket: { + readonly url: string + readonly headers?: Headers.Input | undefined + readonly connectionParams?: Effect.Effect | undefined, unknown, R> | undefined + readonly connectionAckTimeout?: Duration.Input | undefined + readonly keepAlive?: Duration.Input | false | undefined + readonly idleTimeout?: Duration.Input | undefined + } + } + }): Layer.Layer + (options: { + readonly url: Url + readonly queryMethod?: "GET" | "POST" | undefined + readonly subscriptions?: undefined + }): Layer.Layer< + GraphQLProtocol, + never, + HttpClient.HttpClient + > +} = ( + options: HttpOptions +): Layer.Layer => + Layer.effect(GraphQLProtocol, makeHttpWith(options)) + +interface WebSocketOptions { + readonly url: string + readonly headers?: Headers.Input | undefined + readonly connectionParams?: Effect.Effect | undefined, unknown, R> | undefined + readonly connectionAckTimeout?: Duration.Input | undefined + readonly keepAlive?: Duration.Input | false | undefined + readonly idleTimeout?: Duration.Input | undefined +} + +interface WsMessage { + readonly type: string + readonly id?: string | undefined + readonly payload?: unknown +} + +// One WebSocket connection. `error` is set once it is lost, and the operations +// attached to it fail with it. +interface Connection { + readonly ack: Deferred.Deferred + error: TransportError | undefined + receivedFrame: boolean + fiber: Fiber.Fiber | undefined +} + +interface Operation { + readonly queue: Queue.Queue<{ readonly body: unknown }, TransportError | Cause.Done> + readonly connection: Connection +} + +const textDecoder = new TextDecoder() + +// As in graphql-ws's `validateMessage`, `error` carries at least one entry with +// a `message`. +const isFormattedErrors = (u: unknown): boolean => + Array.isArray(u) && u.length > 0 && u.every((error) => isObject(error) && "message" in error) + +const connectionError = (cause: Cause.Cause): TransportError => { + const found = Cause.findError(cause) + if (Result.isFailure(found)) { + return new TransportError({ description: "The graphql-ws connection was closed" }) + } + const error = found.success + if (error instanceof TransportError) { + return error + } + if (Socket.isSocketError(error) && error.reason._tag === "SocketCloseError") { + return new TransportError({ + description: `The graphql-ws connection closed with ${error.reason.message}`, + closeCode: error.reason.code, + cause: error + }) + } + return new TransportError({ description: `The graphql-ws connection failed: ${errorMessage(error)}`, cause: error }) +} + +/** + * Builds the graphql-ws transport as an effect, for composing transports by + * hand. Most code uses {@link layerWebSocket}, which describes the options. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const makeWebSocket = ( + options: { + readonly url: string + readonly headers?: Headers.Input | undefined + readonly connectionParams?: Effect.Effect | undefined, unknown, R> | undefined + readonly connectionAckTimeout?: Duration.Input | undefined + readonly keepAlive?: Duration.Input | false | undefined + readonly idleTimeout?: Duration.Input | undefined + } +): Effect.Effect => + Effect.gen(function*() { + const socket = yield* Socket.makeWebSocket(options.url, { + protocols: "graphql-transport-ws", + headers: options.headers === undefined ? undefined : Headers.fromInput(options.headers) + }) + const writer = yield* socket.writer + const scope = yield* Effect.scope + const context = yield* Effect.context() + const connectionParams = options.connectionParams === undefined + ? Effect.succeed(undefined) + : options.connectionParams.pipe( + Effect.provideContext(context), + Effect.mapError((cause) => + new TransportError({ description: `graphql-ws connectionParams failed: ${errorMessage(cause)}`, cause }) + ) + ) + const ackTimeout = options.connectionAckTimeout ?? Duration.seconds(10) + const keepAlive = options.keepAlive ?? Duration.seconds(10) + const idleTimeout = Duration.fromInputUnsafe(options.idleTimeout ?? 0) + + const operations = new Map() + let connection: Connection | undefined + let nextId = 0 + let active = 0 + let idleGeneration = 0 + + const send = (message: WsMessage) => + writer.write(JSON.stringify(message)).pipe( + Effect.mapError((cause) => connectionError(Cause.fail(cause))) + ) + + const lose = (conn: Connection, error: TransportError) => { + if (conn.error !== undefined) return + conn.error = error + if (connection === conn) connection = undefined + Deferred.doneUnsafe(conn.ack, Effect.fail(error)) + for (const [id, operation] of operations) { + if (operation.connection !== conn) continue + operations.delete(id) + Queue.failCauseUnsafe(operation.queue, Cause.fail(error)) + } + } + + // An invalid server message closes the connection with 4400, which is + // fatal for every operation on it. + const invalid = (reason: string, cause?: unknown) => + Effect.andThen( + Effect.ignore(writer.write(new Socket.CloseEvent(4400, "Invalid message"))), + Effect.fail( + new TransportError({ description: `Invalid graphql-ws message: ${reason}`, closeCode: 4400, cause }) + ) + ) + + const handle = (conn: Connection, frame: string | Uint8Array): Effect.Effect => { + // Any frame answers a keep-alive ping; an invalid one drops the connection anyway. + conn.receivedFrame = true + let message: WsMessage + try { + message = JSON.parse(typeof frame === "string" ? frame : textDecoder.decode(frame)) + } catch (cause) { + return invalid(errorMessage(cause), cause) + } + if (!isObject(message)) { + return invalid("expected an object") + } + switch (message.type) { + case "connection_ack": + case "ping": + case "pong": { + if (message.payload != null && !isObject(message.payload)) { + return invalid(`${message.type} with a payload that is not an object`) + } + if (message.type === "connection_ack") { + Deferred.doneUnsafe(conn.ack, Effect.void) + } + return message.type === "ping" ? send({ type: "pong" }) : Effect.void + } + case "next": + case "error": + case "complete": { + const id = message.id + if (typeof id !== "string" || id === "") { + return invalid(`${message.type} without an id`) + } + if (message.type === "next" && !isObject(message.payload)) { + return invalid("next with a payload that is not an object") + } + if (message.type === "error" && !isFormattedErrors(message.payload)) { + return invalid("error with a payload that is not a list of GraphQL errors") + } + const operation = operations.get(id) + // Unknown ids, including operations this client already completed, are dropped. + if (operation === undefined || operation.connection !== conn) return Effect.void + if (message.type === "next") { + Queue.offerUnsafe(operation.queue, { body: message.payload }) + return Effect.void + } + operations.delete(id) + if (message.type === "error") { + // The server rejected the operation; the client fails it with a ResponseError. + Queue.offerUnsafe(operation.queue, { body: { errors: message.payload } }) + } + Queue.endUnsafe(operation.queue) + return Effect.void + } + default: { + return invalid(`unknown type ${JSON.stringify(message.type)}`) + } + } + } + + const pinger = Effect.fnUntraced(function*(conn: Connection) { + if (keepAlive === false) return yield* Effect.never + while (true) { + yield* Effect.sleep(keepAlive) + if (!conn.receivedFrame) { + return yield* Effect.fail( + new TransportError({ description: "The graphql-ws server did not answer the keep-alive ping" }) + ) + } + conn.receivedFrame = false + yield* send({ type: "ping" }) + } + }) + + const run = Effect.fnUntraced( + function*(conn: Connection) { + const { pull } = yield* socket.reader + const init = Effect.flatMap(connectionParams, (payload) => send({ type: "connection_init", payload })) + const read = Effect.forever( + Effect.flatMap(pull, (frames) => Effect.forEach(frames, (frame) => handle(conn, frame), { discard: true })) + ) + const acknowledged = Deferred.await(conn.ack).pipe( + Effect.timeoutOrElse({ + duration: ackTimeout, + orElse: () => + Effect.fail(new TransportError({ description: "The graphql-ws server did not send connection_ack" })) + }) + ) + // Reading starts with `connectionParams`, so a close while it runs still + // fails the waiting operations. The ack timeout starts once + // `connection_init` is sent. + yield* Effect.all([read, init.pipe(Effect.andThen(acknowledged), Effect.andThen(pinger(conn)))], { + concurrency: 2, + discard: true + }) + }, + // Runs before the socket closes, so no write waits on a dead socket. + (effect, conn) => Effect.onError(effect, (cause) => Effect.sync(() => lose(conn, connectionError(cause)))), + (effect) => Effect.ignore(Effect.scoped(effect)) + ) + + const close = (conn: Connection) => { + lose(conn, new TransportError({ description: "The graphql-ws connection was closed" })) + return conn.fiber === undefined ? Effect.void : Fiber.interrupt(conn.fiber) + } + + const acquireConnection = Effect.suspend(() => { + if (connection !== undefined) return Effect.succeed(connection) + const conn: Connection = { + ack: Deferred.makeUnsafe(), + error: undefined, + receivedFrame: true, + fiber: undefined + } + connection = conn + return Effect.forkIn(run(conn), scope).pipe( + Effect.map((fiber) => { + conn.fiber = fiber + return conn + }) + ) + }) + + const register = Effect.suspend(() => { + // A connection forked into a closed scope is interrupted before it + // starts, so new operations fail instead of waiting for an ack. + if (scope.state._tag === "Closed") { + return Effect.fail( + new TransportError({ description: "The graphql-ws transport's scope is closed", fatal: true }) + ) + } + active++ + idleGeneration++ + return Effect.map(acquireConnection, (conn) => [String(++nextId), conn] as const) + }) + + const closeIfIdle = Effect.suspend(() => { + if (--active > 0 || connection === undefined) return Effect.void + const conn = connection + if (Duration.isZero(idleTimeout)) return close(conn) + const generation = ++idleGeneration + const closeIfStillIdle = Effect.suspend(() => + generation === idleGeneration && connection === conn ? close(conn) : Effect.void + ) + return Effect.asVoid(Effect.forkIn(Effect.delay(closeIfStillIdle, idleTimeout), scope)) + }) + + const release = (id: string, conn: Connection) => + Effect.suspend(() => + Effect.andThen( + // Only a subscribed operation the server has not completed is still in `operations`. + operations.delete(id) && conn.error === undefined + ? Effect.ignore(send({ id, type: "complete" })) + : Effect.void, + closeIfIdle + ) + ) + + const operation = (request: GraphQLRequest): Stream.Stream<{ readonly body: unknown }, TransportError> => + Stream.unwrap(Effect.gen(function*() { + const [id, conn] = yield* Effect.acquireRelease(register, ([id, conn]) => release(id, conn)) + yield* Deferred.await(conn.ack) + if (conn.error !== undefined) { + return yield* Effect.fail(conn.error) + } + const queue = yield* Queue.unbounded<{ readonly body: unknown }, TransportError | Cause.Done>() + operations.set(id, { queue, connection: conn }) + // Per-call `request.headers` and `request.urlParams` are ignored: + // graphql-ws has no per-operation headers or URL. + yield* send({ id, type: "subscribe", payload: requestBody(request) }) + return Stream.fromQueue(queue) + })) + + const execute = (request: GraphQLRequest): Effect.Effect<{ readonly body: unknown }, TransportError> => + Effect.flatMap(Stream.runHead(operation(request)), (result) => + result._tag === "Some" + ? Effect.succeed(result.value) + : Effect.fail(new TransportError({ description: "The graphql-ws operation completed without a result" }))) + + return GraphQLProtocol.of({ execute, subscribe: operation }) + }) + +/** + * The graphql-ws transport: every operation goes over one WebSocket using the + * `graphql-transport-ws` subprotocol, with the `Socket.WebSocketConstructor` + * in context. + * + * **Details** + * + * The socket connects lazily and multiplexes operations by id. It closes after + * `idleTimeout` (default 0) with no active operations, or with code `1000` + * when the layer's scope closes. + * + * - Operations wait for `connection_ack`. `connectionAckTimeout` (default + * 10 seconds) starts after sending `connection_init`. + * - `connectionParams` runs on every connection, allowing token refresh. + * Failure or a socket close during evaluation is a `TransportError`. + * - Handshake `headers` accept `Headers.Input` and are normalized before + * reaching the socket. They require a Node or Bun WebSocket constructor; + * browsers cannot set them. Per-operation `headers` and `urlParams` are ignored. + * - Results carry no HTTP `status`. + * - `keepAlive` (default 10 seconds, or `false` to disable) sends `ping`. + * No server frame in the following interval causes a retryable failure. + * Server `ping` receives `pong`. + * - Lost connections fail every active operation with a `TransportError` + * carrying the close code. See `GraphQLClientError.isFatalCloseCode` for + * non-retryable codes. The transport never replays operations; the client + * retries subscriptions and the next operation reconnects. + * - Once the layer's scope has closed, every new operation fails at once + * with a non-retryable `TransportError` marked `fatal`. + * - Messages follow graphql-ws validation. Invalid messages close the socket + * with fatal code `4400`; valid messages for unknown ids are ignored. + * - Server `error` messages become `ResponseError` values. Interrupting a + * subscription sends `complete`. + * + * **Example** (A client over graphql-ws) + * + * ```ts import.meta.vitest + * import { Effect, Layer } from "effect" + * import { GraphQLProtocol } from "effect/graphql" + * import type { Socket } from "effect/socket" + * + * // Provide a Socket.WebSocketConstructor, such as + * // Socket.layerWebSocketConstructorGlobal in a browser + * export const Protocol: Layer.Layer = + * GraphQLProtocol.layerWebSocket({ + * url: "wss://example.com/graphql", + * connectionParams: Effect.succeed({ authorization: "Bearer secret" }), + * idleTimeout: "30 seconds" + * }) + * ``` + * + * @stability experimental + * @category layers + * @since 4.0.0 + */ +export const layerWebSocket = ( + options: { + readonly url: string + readonly headers?: Headers.Input | undefined + readonly connectionParams?: Effect.Effect | undefined, unknown, R> | undefined + readonly connectionAckTimeout?: Duration.Input | undefined + readonly keepAlive?: Duration.Input | false | undefined + readonly idleTimeout?: Duration.Input | undefined + } +): Layer.Layer => + Layer.effect(GraphQLProtocol, makeWebSocket(options)) diff --git a/repos/effect/packages/effect/src/graphql/GraphQLResolver.ts b/repos/effect/packages/effect/src/graphql/GraphQLResolver.ts new file mode 100644 index 0000000000..07699bc951 --- /dev/null +++ b/repos/effect/packages/effect/src/graphql/GraphQLResolver.ts @@ -0,0 +1,728 @@ +/** + * Batch lookups through a GraphQL client method with `RequestResolver`. + * {@link ordered} matches results by position; {@link findById} matches by + * key; {@link aliased} repeats an operation under aliases in one request. + * {@link request} turns any of them into `(key) => Effect`. + * + * Client middleware still run. When a method needs services, such as a + * middleware's `requires`, `batchKey` keeps lookups with different services + * in separate batches. Compose `RequestResolver.setDelay` and + * `RequestResolver.batchN` with `.pipe` to control batching. + * + * Lookups with different protocol URLs are batched separately. See + * `GraphQLProtocol.layerHttp` for middleware and caching constraints. + * + * @stability experimental + * @since 4.0.0 + */ +import * as Arr from "../Array.ts" +import * as Cause from "../Cause.ts" +import * as Context from "../Context.ts" +import * as Effect from "../Effect.ts" +import * as Exit from "../Exit.ts" +import { dual } from "../Function.ts" +import * as Headers from "../http/Headers.ts" +import * as UrlParams from "../http/UrlParams.ts" +import * as internalGraphQL from "../internal/graphql.ts" +import * as MutableHashMap from "../MutableHashMap.ts" +import * as Request from "../Request.ts" +import * as RequestResolver from "../RequestResolver.ts" +import type * as Types from "../Types.ts" +import type * as GraphQL from "./GraphQL.ts" +import type { OperationMethod, PartialResult } from "./GraphQLClient.ts" +import { DecodeError, type GraphQLClientError, type GraphQLError } from "./GraphQLClientError.ts" +import type { ExecutionResult, GraphQLRequest } from "./GraphQLProtocol.ts" + +// ----------------------------------------------------------------------------- +// Types +// ----------------------------------------------------------------------------- + +type NonNull = Exclude + +type Step = K extends keyof NonNull ? NonNull[K] : never + +// Check one segment at a time for autocomplete without enumerating all paths. +// The path must end at a list and cannot cross one. +type CheckPath = NonNull extends ReadonlyArray ? readonly [] + : P extends readonly [infer Head, ...infer Tail] + ? readonly [Head extends keyof NonNull ? Head : keyof NonNull, ...CheckPath, Tail>] + : readonly [keyof NonNull] + +type Path = P extends CheckPath ? P : CheckPath + +type AtPath = P extends readonly [infer Head, ...infer Tail] ? AtPath, Tail> : A + +type Item = NonNull> extends ReadonlyArray ? NonNull : never + +type Typenames = Types.IsUnion extends true ? + I extends { readonly __typename: infer T extends string } ? T : never + : never + +type Narrow = [T] extends [never] ? I : Extract + +type BatchKey = [GraphQL.Services] extends [never] ? { readonly batchKey?: never } + : { readonly batchKey: (context: Context.Context>) => unknown } + +interface KeyRequest extends Request.Request { + readonly key: K +} + +// Requests are structural, so two requests with equal keys are one request. +const makeRequest = (key: K): KeyRequest => Request.of>()({ key }) + +// ----------------------------------------------------------------------------- +// Running +// ----------------------------------------------------------------------------- + +/** + * Looks up a key with an {@link ordered}, {@link findById} or {@link aliased} + * resolver, using `request(resolver)(key)` or `request(key, resolver)`. + * + * **Details** + * + * Concurrent lookups are batched. Keys equal under `Equal` and `Hash` + * are sent once per batch and share the result. + * + * **Example** (Looking up repositories by id) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol, GraphQLResolver } from "effect/graphql" + * + * const RepoNodes = GraphQL.query("RepoNodes", { + * document: "query RepoNodes($ids:[ID!]!){nodes(ids:$ids){... on Repository{name}}}", + * variables: { ids: Schema.Array(Schema.String) }, + * result: Schema.Struct({ nodes: Schema.Array(Schema.NullOr(Schema.Struct({ name: Schema.String }))) }) + * }) + * + * let calls = 0 + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: (request) => { + * calls++ + * const { ids } = request.variables as { ids: Array } + * return Effect.succeed({ body: { data: { nodes: ids.map((id) => ({ name: `repo-${id}` })) } } }) + * }, + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(RepoNodes)) + * const getRepo = GraphQLResolver.request(GraphQLResolver.ordered(client.RepoNodes, { + * variables: (ids: ReadonlyArray) => ({ ids }), + * path: ["nodes"] + * })) + * const repos = yield* Effect.forEach(["1", "2", "1"], getRepo, { concurrency: "unbounded" }) + * return [repos.map((repo) => repo.name), calls] + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => [["repo-1", "repo-2", "repo-1"], 1] + * ``` + * + * @stability experimental + * @category running + * @since 4.0.0 + */ +export const request: { + ( + resolver: RequestResolver.RequestResolver> + ): (key: K) => Effect.Effect + (key: K, resolver: RequestResolver.RequestResolver>): Effect.Effect +} = dual( + 2, + (key: K, resolver: RequestResolver.RequestResolver>): Effect.Effect => + Effect.request(makeRequest(key), resolver) +) + +// ----------------------------------------------------------------------------- +// Resolvers +// ----------------------------------------------------------------------------- + +/** + * Batches lookups for fields such as `nodes(ids:)` that return one entry per + * key in input order. + * + * **Details** + * + * `variables` maps batch keys to operation variables; annotate its parameter + * to set the key type. `path` selects a list through object fields, with + * autocomplete at each level. For `__typename` unions, `typename` narrows + * the success type and treats other types as missing. + * + * Null entries, typename mismatches and null parents fail with + * `Cause.NoSuchElementError`. GraphQL errors whose paths start with + * `[...path, i]` fail only entry `i`; its `ResponseError` contains those errors + * and the response status. Other GraphQL errors fail the batch with the same + * `ResponseError` as a non-partial call. Transport, encode and decode errors + * also fail the batch. A list length mismatch fails with `DecodeError`. + * + * `pageInfo.hasNextPage: true` on the list's parent fails the batch with + * `DecodeError` to avoid reporting unreturned entries as missing. Set the + * operation's page size at least as large as `RequestResolver.batchN`. + * + * A batch uses one lookup's services. Methods requiring services also require + * `batchKey`; only lookups with keys equal under `Equal` share a batch. Return + * the value that distinguishes those services, for example + * `(context) => Context.get(context, CurrentUser).tenantId`. Methods without + * services use one batch and do not accept `batchKey`. + * + * **Gotchas** + * + * Don't return the whole context from `batchKey`. It also holds the caller's + * span, so most lookups would get a batch of their own. + * + * A middleware that reads a `Context.Reference` with a default value doesn't + * add it to the method's services. `batchKey` isn't required for it, and + * lookups with different values can share a batch. + * + * **Example** (Looking up repositories in a `Node` union) + * + * ```ts import.meta.vitest + * import { Cause, Effect, Layer, RequestResolver, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol, GraphQLResolver } from "effect/graphql" + * + * const Repository = Schema.Struct({ __typename: Schema.Literal("Repository"), nameWithOwner: Schema.String }) + * const User = Schema.Struct({ __typename: Schema.Literal("User"), login: Schema.String }) + * + * const RepoNodes = GraphQL.query("RepoNodes", { + * document: "query RepoNodes($ids:[ID!]!){nodes(ids:$ids){__typename ...on Repository{nameWithOwner} ...on User{login}}}", + * variables: { ids: Schema.Array(Schema.String) }, + * result: Schema.Struct({ nodes: Schema.Array(Schema.NullOr(Schema.Union([Repository, User]))) }) + * }) + * + * const store: Record = { + * R_1: { __typename: "Repository", nameWithOwner: "Effect-TS/effect" }, + * U_1: { __typename: "User", login: "tim" } + * } + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: (request) => { + * const { ids } = request.variables as { ids: Array } + * return Effect.succeed({ body: { data: { nodes: ids.map((id) => store[id] ?? null) } } }) + * }, + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(RepoNodes)) + * const RepoById = GraphQLResolver.ordered(client.RepoNodes, { + * variables: (ids: ReadonlyArray) => ({ ids }), + * path: ["nodes"], + * typename: "Repository" + * }).pipe(RequestResolver.batchN(100)) + * const getRepo = GraphQLResolver.request(RepoById) + * return yield* Effect.forEach( + * ["R_1", "U_1", "R_2"], + * (id) => getRepo(id).pipe( + * Effect.map((repo) => repo.nameWithOwner), + * Effect.catchIf(Cause.isNoSuchElementError, () => Effect.succeed("missing")) + * ), + * { concurrency: "unbounded" } + * ) + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => ["Effect-TS/effect", "missing", "missing"] + * ``` + * + * @stability experimental + * @category resolvers + * @since 4.0.0 + */ +export const ordered = < + Op extends GraphQL.Any, + K, + const P extends ReadonlyArray, + T extends Typenames, P>> = never +>( + method: OperationMethod, + options: { + readonly variables: (keys: ReadonlyArray) => GraphQL.Variables + readonly path: Path, P> + readonly typename?: T | undefined + } & BatchKey +): RequestResolver.RequestResolver< + KeyRequest< + K, + Narrow, P>, T>, + GraphQL.Error | Cause.NoSuchElementError, + GraphQL.Services + > +> => { + const path = options.path as ReadonlyArray + const codec = internalGraphQL.makeCodec(method.operation) + return makeResolver( + method, + options.batchKey, + (entries) => + Effect.flatMap(callBatch(method, entries, options.variables), ({ keys, targets, result }) => { + const byIndex = new Map>() + for (const error of result.errors) { + const index = entryIndex(error, path, keys.length) + if (index === undefined) return batchError(codec, result) + const errors = byIndex.get(index) + if (errors === undefined) byIndex.set(index, [error]) + else errors.push(error) + } + const list = findList(result.data, path) + // An error in a non-null item nulls the whole list, so every entry lost its data to it. + if (list === undefined) return result.errors.length > 0 ? batchError(codec, result) : completeAll(targets) + if (list.truncated) return Effect.fail(codec.fail(truncated(path))) + if (list.items.length !== keys.length) { + return Effect.fail(codec.fail( + new DecodeError({ + description: `Expected ${keys.length} entries at ${path.join(".")}, received ${list.items.length}` + }) + )) + } + const response = internalGraphQL.partialResponses.get(result) + for (let i = 0; i < targets.length; i++) { + const errors = byIndex.get(i) + const item = list.items[i] + targets[i].completeUnsafe( + errors !== undefined + ? Exit.fail(codec.fail( + internalGraphQL.responseError({ status: response?.status, headers: response?.headers }, errors) + )) + : matchesTypename(item, options.typename) + ? Exit.succeed(item) + : constNoSuchElement + ) + } + return Effect.void + }) + ) +} + +/** + * Batches lookups by key for searches and collections that return results + * in any order. + * + * **Details** + * + * Write `key` before `variables` to infer the key type from its return type. + * `variables` maps batch keys to operation variables. Keys are compared with + * `Equal` and `Hash`. `path` and `typename` work as in {@link ordered}; + * `key` receives the narrowed item type. + * + * Missing keys, null parents, pagination and `batchKey` behave as in + * {@link ordered}. + * Any GraphQL error fails the batch with the same `ResponseError` as a + * non-partial call, since error paths cannot be matched to keys. + * + * **Example** (Finding repositories through search) + * + * ```ts import.meta.vitest + * import { Effect, Layer, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol, GraphQLResolver } from "effect/graphql" + * + * const Repository = Schema.Struct({ __typename: Schema.Literal("Repository"), nameWithOwner: Schema.String }) + * const User = Schema.Struct({ __typename: Schema.Literal("User"), login: Schema.String }) + * + * const SearchRepos = GraphQL.query("SearchRepos", { + * document: "query SearchRepos($query:String!){search(query:$query,type:REPOSITORY,first:100){pageInfo{hasNextPage} nodes{__typename ...on Repository{nameWithOwner} ...on User{login}}}}", + * variables: { query: Schema.String }, + * result: Schema.Struct({ + * search: Schema.Struct({ + * pageInfo: Schema.Struct({ hasNextPage: Schema.Boolean }), + * nodes: Schema.NullOr(Schema.Array(Schema.NullOr(Schema.Union([Repository, User])))) + * }) + * }) + * }) + * + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: (request) => { + * const { query } = request.variables as { query: string } + * const nodes = query.split(" ").map((term) => ({ __typename: "Repository", nameWithOwner: term.slice(5) })) + * return Effect.succeed({ body: { data: { search: { pageInfo: { hasNextPage: false }, nodes: nodes.reverse() } } } }) + * }, + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const client = yield* GraphQLClient.make(GraphQLGroup.make(SearchRepos)) + * const RepoByName = GraphQLResolver.findById(client.SearchRepos, { + * key: (repo) => repo.nameWithOwner, + * variables: (names) => ({ query: names.map((name) => `repo:${name}`).join(" ") }), + * path: ["search", "nodes"], + * typename: "Repository" + * }) + * const repos = yield* Effect.forEach( + * ["Effect-TS/effect", "Effect-TS/website"], + * GraphQLResolver.request(RepoByName), + * { concurrency: "unbounded" } + * ) + * return repos.map((repo) => repo.nameWithOwner) + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => ["Effect-TS/effect", "Effect-TS/website"] + * ``` + * + * @stability experimental + * @category resolvers + * @since 4.0.0 + */ +export const findById = < + Op extends GraphQL.Any, + K, + const P extends ReadonlyArray, + T extends Typenames, P>> = never +>( + method: OperationMethod, + options: { + readonly variables: (keys: ReadonlyArray) => GraphQL.Variables + readonly path: Path, P> + readonly key: (item: Narrow, P>, T>) => K + readonly typename?: T | undefined + } & BatchKey +): RequestResolver.RequestResolver< + KeyRequest< + K, + Narrow, P>, T>, + GraphQL.Error | Cause.NoSuchElementError, + GraphQL.Services + > +> => { + const path = options.path as ReadonlyArray + const codec = internalGraphQL.makeCodec(method.operation) + return makeResolver( + method, + options.batchKey, + (entries) => + Effect.flatMap(callBatch(method, entries, options.variables), ({ keys, targets, result }) => { + if (result.errors.length > 0) return batchError(codec, result) + const list = findList(result.data, path) + if (list === undefined) return completeAll(targets) + if (list.truncated) return Effect.fail(codec.fail(truncated(path))) + const pending = MutableHashMap.empty>() + for (let i = 0; i < keys.length; i++) MutableHashMap.set(pending, keys[i], targets[i]) + for (const item of list.items) { + if (!matchesTypename(item, options.typename)) continue + const key = options.key(item as Narrow, P>, T>) + const target = MutableHashMap.get(pending, key) + if (target._tag === "None") continue + MutableHashMap.remove(pending, key) + target.value.completeUnsafe(Exit.succeed(item)) + } + MutableHashMap.forEach(pending, (target) => target.completeUnsafe(constNoSuchElement)) + return Effect.void + }) + ) +} + +/** + * Batches calls to a generated query or mutation by repeating the operation + * under aliases in one request. + * + * **When to use** + * + * Use when the API has no list-key field, such as GitHub's pull requests by + * repository and number. Otherwise, {@link ordered} or {@link findById} send + * a smaller query. + * + * **Details** + * + * Use {@link request} to get `(variables) => Effect`. Variables that encode + * to the same JSON share a slice; each slice uses the operation's result Schema. + * Throws when the resolver is built if the operation has no document + * template, if an operation directive references a variable, or if a root + * selection is a fragment spread or inline fragment, since none of these can + * be repeated under aliases. + * + * Batches use `POST` even with `queryMethod: "GET"`. The default batch size + * is 10; change it with `RequestResolver.batchN`. Middleware run once per + * batch, and `batchKey` works as in {@link ordered}. Mock and custom methods + * are called once per slice instead. + * + * Errors with a matching `path[0]` fail only that slice, with the alias prefix + * removed from the error path. Errors without a matching path, transport errors + * and middleware failures fail the batch. + * + * **Gotchas** + * + * An error under a non-null root field can null the entire response, failing + * every slice. GitHub's `repository` and `pullRequest` are nullable. + * + * Middleware that hash queries must use `request.query`, not + * `operation.document`. Trusted-document allowlists don't support batching; + * query hashing does, since the same operation and slice count produce the + * same document. + * + * Mutations are allowed, but the caller cannot control root-field order. + * + * **Example** (Looking up pull requests by number) + * + * ```ts import.meta.vitest + * import { Effect, Layer, RequestResolver, Schema, Stream } from "effect" + * import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLProtocol, GraphQLResolver } from "effect/graphql" + * + * // Generated from: + * // query PullRequest($owner: String!, $name: String!, $number: Int!) { + * // repository(owner: $owner, name: $name) { pullRequest(number: $number) { title } } + * // } + * const PullRequest = GraphQL.query("PullRequest", { + * document: { + * variables: [ + * { name: "owner", body: "String!" }, + * { name: "name", body: "String!" }, + * { name: "number", body: "Int!" } + * ], + * selections: [{ + * name: "repository", + * body: ["(owner:$", "owner", ",name:$", "name", "){pullRequest(number:$", "number", "){title}}"] + * }], + * fragments: [] + * }, + * variables: { owner: Schema.String, name: Schema.String, number: Schema.Int }, + * result: Schema.Struct({ + * repository: Schema.NullOr(Schema.Struct({ + * pullRequest: Schema.NullOr(Schema.Struct({ title: Schema.String })) + * })) + * }) + * }) + * + * // A stand-in server that answers every aliased slice + * const queries: Array = [] + * const Scripted = Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + * execute: (request) => { + * queries.push(request.query) + * const data: Record = {} + * for (const [key, number] of Object.entries(request.variables as Record)) { + * const prefix = /^(_\d+_)number$/.exec(key)?.[1] + * if (prefix !== undefined) data[`${prefix}repository`] = { pullRequest: { title: `PR ${number}` } } + * } + * return Effect.succeed({ body: { data } }) + * }, + * subscribe: () => Stream.empty + * }) + * + * const program = Effect.gen(function*() { + * const github = yield* GraphQLClient.make(GraphQLGroup.make(PullRequest)) + * const PullRequests = GraphQLResolver.aliased(github.PullRequest).pipe(RequestResolver.batchN(20)) + * const getPullRequest = GraphQLResolver.request(PullRequests) + * const results = yield* Effect.forEach( + * [1, 2, 3], + * (number) => getPullRequest({ owner: "Effect-TS", name: "effect", number }), + * { concurrency: "unbounded" } + * ) + * return [results.map((result) => result.repository?.pullRequest?.title), queries.length] + * }) + * + * await Effect.runPromise(program.pipe(Effect.provide(Scripted))) // => [["PR 1", "PR 2", "PR 3"], 1] + * ``` + * + * @stability experimental + * @category resolvers + * @since 4.0.0 + */ +export const aliased = ( + method: OperationMethod, + ...[options]: {} extends BatchKey ? [options?: BatchKey] : [options: BatchKey] +): RequestResolver.RequestResolver> => { + const operation = method.operation + const template = operation.template + if (template === undefined) { + throw new Error(`GraphQLResolver.aliased: operation ${operation.name} has no document template`) + } + const unsliceable = internalGraphQL.templateUnsliceableReason(template) + if (unsliceable !== undefined) { + throw new Error(`GraphQLResolver.aliased: cannot batch operation ${operation.name}: ${unsliceable}`) + } + const codec = internalGraphQL.makeCodec(operation) + // The registered hook uses this operation's middleware errors and services. + const execute = internalGraphQL.rawExecutors.get(method)?.execute as + | ((request: GraphQLRequest) => Effect.Effect, GraphQL.Services>) + | undefined + // Generic conditional parameters prevent calling the strict overload directly. + const call = method as unknown as ( + variables: GraphQL.Variables + ) => Effect.Effect, GraphQL.Error, GraphQL.Services> + + return makeResolver>(method, options?.batchKey, (entries) => + Effect.flatMap( + Effect.forEach(entries, (entry) => Effect.exit(codec.encodeVariables(entry.request.key))), + (encoded) => { + const slices: Array> = [] + const byJson = new Map>() + for (let i = 0; i < entries.length; i++) { + const exit = encoded[i] + if (exit._tag === "Failure") { + entries[i].completeUnsafe(exit) + continue + } + const json = internalGraphQL.canonicalJson(exit.value) + const slice = byJson.get(json) + if (slice !== undefined) { + slice.entries.push(entries[i]) + continue + } + const created = { variables: entries[i].request.key, encoded: exit.value, entries: [entries[i]] } + byJson.set(json, created) + slices.push(created) + } + const complete = (slice: Slice, effect: Effect.Effect, GraphQL.Error, R>) => + Effect.map(Effect.exit(effect), (exit) => { + for (const entry of slice.entries) entry.completeUnsafe(exit) + }) + if (execute === undefined) { + return Effect.forEach(slices, (slice) => complete(slice, call(slice.variables)), { discard: true }) + } + if (!Arr.isReadonlyArrayNonEmpty(slices)) return Effect.void + const prefixes = Arr.map(slices, (_, i) => `_${i}_`) + return execute({ + kind: operation.kind, + query: internalGraphQL.renderSlices(operation.kind, operation.name, template, prefixes), + operationName: operation.name, + variables: Object.fromEntries( + slices.flatMap((slice, i) => + Object.entries(slice.encoded ?? {}).map(([name, value]) => [prefixes[i] + name, value]) + ) + ), + headers: Headers.empty, + urlParams: UrlParams.empty + }).pipe( + Effect.flatMap((result) => { + const results = internalGraphQL.splitSlices(result, template, prefixes) + return results === undefined + ? codec.failResponse(result) + : Effect.forEach(slices, (slice, i) => complete(slice, codec.decodeStrict(results[i])), { discard: true }) + }) + ) + } + )).pipe(RequestResolver.batchN(10)) +} + +type AliasedRequest = KeyRequest< + GraphQL.Variables, + GraphQL.Result, + GraphQL.Error, + GraphQL.Services +> + +interface Slice { + readonly variables: GraphQL.Variables + readonly encoded: unknown + readonly entries: Array>> +} + +// ----------------------------------------------------------------------------- +// Internals +// ----------------------------------------------------------------------------- + +const constNoSuchElement = Exit.fail(new Cause.NoSuchElementError()) + +/** + * Resolves each entry's URL in its own context, then splits the entries by URL + * and `batchKey`. Each batch runs in its first entry's context, carrying the + * URL it was grouped by, so the transport doesn't resolve it again. + */ +const makeResolver = ( + method: OperationMethod, + batchKey: ((context: Context.Context) => unknown) | undefined, + runAll: (entries: Arr.NonEmptyArray>) => Effect.Effect, any> +): RequestResolver.RequestResolver => { + const resolve = internalGraphQL.rawExecutors.get(method)?.url + const operation = { kind: method.operation.kind, operationName: method.operation.name } + const urlOf = (entry: Request.Entry) => + resolve === undefined ? Effect.succeed(undefined) : Effect.provideContext(resolve(operation), entry.context) + return RequestResolver.make((entries) => + Effect.flatMap(Effect.forEach(entries, urlOf, { concurrency: "unbounded" }), (urls) => { + // Arrays are compared structurally, so equal keys share a batch. + const batches = MutableHashMap.empty< + readonly [string | undefined, unknown], + Arr.NonEmptyArray> + >() + entries.forEach((entry, i) => { + const key = [urls[i], batchKey?.(entry.context)] as const + const batch = MutableHashMap.get(batches, key) + if (batch._tag === "Some") batch.value.push(entry) + else MutableHashMap.set(batches, key, [entry]) + }) + return Effect.forEach(batches, ([[url], entries]) => { + const context: Context.Context = entries[0].context + return Effect.provideContext( + runAll(entries), + url === undefined ? context : Context.add(context, internalGraphQL.ResolvedUrl, { resolve, url }) + ) + }, { concurrency: "unbounded", discard: true }) + }) + ) +} + +/** + * Calls the method with deduplicated keys. Each target completes all entries + * sharing its key. + */ +const callBatch = ( + method: OperationMethod, + entries: Arr.NonEmptyArray>>, + variables: (keys: ReadonlyArray) => GraphQL.Variables +) => { + const keys: Array = [] + const targets: Array>> = [] + const indices = MutableHashMap.empty() + for (const entry of entries) { + const index = MutableHashMap.get(indices, entry.request.key) + if (index._tag === "None") { + MutableHashMap.set(indices, entry.request.key, keys.length) + keys.push(entry.request.key) + targets.push(entry) + continue + } + const previous = targets[index.value] + targets[index.value] = { + ...previous, + completeUnsafe(exit) { + previous.completeUnsafe(exit) + entry.completeUnsafe(exit) + } + } + } + // Generic conditional parameters prevent calling the partial overload directly. + const call = method as unknown as ( + variables: GraphQL.Variables, + options: { readonly partial: true } + ) => Effect.Effect>, GraphQL.Error, GraphQL.Services> + return Effect.map(call(variables(keys), { partial: true }), (result) => ({ keys, targets, result })) +} + +// Fails the batch with the response's errors and transport metadata. +const batchError = ( + codec: { readonly failResponse: (result: ExecutionResult) => Effect.Effect }, + result: PartialResult +) => codec.failResponse(internalGraphQL.partialResponses.get(result) ?? { errors: result.errors }) + +const truncated = (path: ReadonlyArray) => + new DecodeError({ + description: `pageInfo.hasNextPage is true next to ${ + path.join(".") + }, so results beyond the page would be reported missing. Make the page size at least the RequestResolver.batchN size` + }) + +const completeAll = (targets: ReadonlyArray>) => { + for (const target of targets) target.completeUnsafe(constNoSuchElement) + return Effect.void +} + +const entryIndex = (error: GraphQLError, path: ReadonlyArray, length: number): number | undefined => { + const errorPath = error.path + if (errorPath === undefined || errorPath.length <= path.length) return undefined + for (let i = 0; i < path.length; i++) { + if (errorPath[i] !== path[i]) return undefined + } + const index = errorPath[path.length] + return typeof index === "number" && Number.isInteger(index) && index >= 0 && index < length ? index : undefined +} + +const findList = ( + data: unknown, + path: ReadonlyArray +): { readonly items: ReadonlyArray; readonly truncated: boolean } | undefined => { + // Path guarantees object fields leading to a list. + let parent = data as Record | null | undefined + for (let i = 0; i < path.length - 1; i++) parent = parent?.[path[i]] + const items = parent?.[path[path.length - 1]] as ReadonlyArray | null | undefined + if (items === null || items === undefined) return undefined + return { items, truncated: parent!.pageInfo?.hasNextPage === true } +} + +const matchesTypename = (item: unknown, typename: string | undefined): boolean => + item !== null && item !== undefined && + (typename === undefined || (item as { readonly __typename?: unknown }).__typename === typename) diff --git a/repos/effect/packages/effect/src/graphql/index.ts b/repos/effect/packages/effect/src/graphql/index.ts new file mode 100644 index 0000000000..a065eee13f --- /dev/null +++ b/repos/effect/packages/effect/src/graphql/index.ts @@ -0,0 +1,48 @@ +/** + * @stability experimental + * @since 4.0.0 + */ + +// @barrel: Auto-generated exports. Do not edit manually. + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as GraphQL from "./GraphQL.ts" + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as GraphQLClient from "./GraphQLClient.ts" + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as GraphQLClientError from "./GraphQLClientError.ts" + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as GraphQLGroup from "./GraphQLGroup.ts" + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as GraphQLMiddleware from "./GraphQLMiddleware.ts" + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as GraphQLProtocol from "./GraphQLProtocol.ts" + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as GraphQLResolver from "./GraphQLResolver.ts" diff --git a/repos/effect/packages/effect/src/http-api/HttpApiClient.ts b/repos/effect/packages/effect/src/http-api/HttpApiClient.ts index 6bf1a5bfcf..e5e2287a33 100644 --- a/repos/effect/packages/effect/src/http-api/HttpApiClient.ts +++ b/repos/effect/packages/effect/src/http-api/HttpApiClient.ts @@ -23,6 +23,7 @@ import * as HttpClientError from "../http/HttpClientError.ts" import * as HttpClientRequest from "../http/HttpClientRequest.ts" import type * as HttpClientResponse from "../http/HttpClientResponse.ts" import * as HttpMethod from "../http/HttpMethod.ts" +import * as internalUrlParams from "../http/internal/urlParams.ts" import * as UrlParams from "../http/UrlParams.ts" import * as InternalRecord from "../internal/record.ts" import * as Predicate from "../Predicate.ts" @@ -746,7 +747,7 @@ export const urlBuilder = (api: Api, options?: { ) for (const [key, value] of urlParams.params) { if (value !== undefined) { - url.searchParams.append(key, value) + url.searchParams.append(key, internalUrlParams.unwrap(value)) } } return url.toString() diff --git a/repos/effect/packages/effect/src/http-api/HttpApiScalar.ts b/repos/effect/packages/effect/src/http-api/HttpApiScalar.ts index ebb51b8c1f..eb585fa801 100644 --- a/repos/effect/packages/effect/src/http-api/HttpApiScalar.ts +++ b/repos/effect/packages/effect/src/http-api/HttpApiScalar.ts @@ -60,6 +60,11 @@ export type ScalarConfig = { layout?: "modern" | "classic" /** URL to a request proxy for the API client */ proxyUrl?: string + /** Authentication preferences for the API client */ + authentication?: { + /** OpenAPI security scheme names to select by default */ + preferredSecurityScheme?: string | Array> | null + } /** Browser JavaScript function expression used by Scalar for documents and test requests */ customFetch?: string /** Whether to show the sidebar */ diff --git a/repos/effect/packages/effect/src/http/FetchHttpClient.ts b/repos/effect/packages/effect/src/http/FetchHttpClient.ts index 2ea1026c3d..347058f548 100644 --- a/repos/effect/packages/effect/src/http/FetchHttpClient.ts +++ b/repos/effect/packages/effect/src/http/FetchHttpClient.ts @@ -115,12 +115,15 @@ const fetch: HttpClient.HttpClient = HttpClient.make((request, url, signal, fibe * **Gotchas** * * Fetch behavior comes from the runtime's implementation, so CORS, cookies, - * redirects, abort handling, and streaming support can vary by platform. Stream - * request bodies are sent as Web streams with `duplex: "half"`, and any - * `content-length` header is removed before calling `fetch`. + * redirects, abort handling, and streaming support can vary by platform. Trace + * propagation is on by default, and a browser preflight fails unless the + * target allows `b3` and `traceparent`. Stream request bodies are sent as Web + * streams with `duplex: "half"`, and any `content-length` header is removed + * before calling `fetch`. * * @see {@link Fetch} for supplying the fetch implementation used by this layer * @see {@link RequestInit} for default `RequestInit` options applied before request-specific fields + * @see {@link HttpClient.TracerPropagationEnabled} for leaving `b3` and `traceparent` off a browser request * * @stability unstable * @category layers diff --git a/repos/effect/packages/effect/src/http/FindMyWay/internal/router.ts b/repos/effect/packages/effect/src/http/FindMyWay/internal/router.ts index a8751a3bb0..d14dad66c6 100644 --- a/repos/effect/packages/effect/src/http/FindMyWay/internal/router.ts +++ b/repos/effect/packages/effect/src/http/FindMyWay/internal/router.ts @@ -338,13 +338,6 @@ class RouterImpl implements Router.Router { path = path.replace(FULL_PATH_REGEXP, "/") } - // This must be run before sanitizeUrl as the resulting function - // .sliceParameter must be constructed with same URL string used - // throughout the rest of this function. - if (this.options.ignoreDuplicateSlashes) { - path = removeDuplicateSlashes(path) - } - let sanitizedUrl try { sanitizedUrl = safeDecodeURI(path) @@ -355,6 +348,10 @@ class RouterImpl implements Router.Router { return undefined } + if (this.options.ignoreDuplicateSlashes) { + path = removeDuplicateSlashes(path) + } + if (this.options.ignoreTrailingSlash) { path = trimLastSlash(path) } @@ -860,7 +857,8 @@ function makeCreateParams( } } -function getClosingParenthensePosition(path: string, idx: number) { +/** @internal */ +export function getClosingParenthensePosition(path: string, idx: number) { // `path.indexOf()` will always return the first position of the closing parenthese, // but it's inefficient for grouped or wrong regexp expressions. // see issues #62 and #63 for more info diff --git a/repos/effect/packages/effect/src/http/Headers.ts b/repos/effect/packages/effect/src/http/Headers.ts index 0ec53bbcdd..876932a4a5 100644 --- a/repos/effect/packages/effect/src/http/Headers.ts +++ b/repos/effect/packages/effect/src/http/Headers.ts @@ -406,10 +406,11 @@ export const isRedactedName = ( name: string, patterns: ReadonlyArray ): boolean => { + const lowerName = name.toLowerCase() for (let i = 0; i < patterns.length; i++) { const pattern = patterns[i] if (typeof pattern === "string") { - if (pattern.toLowerCase() === name.toLowerCase()) { + if (pattern.toLowerCase() === lowerName) { return true } } else if (name.search(pattern) !== -1) { @@ -424,9 +425,9 @@ export const isRedactedName = ( * * **Details** * - * Defaults include `authorization`, `cookie`, `set-cookie`, `x-api-key` and - * `AWSAccessKeyId`, `Signature`, `sig` and `X-Goog-Signature`. Names match - * case-insensitively, and providing a new list replaces the defaults. + * Defaults include `authorization`, `cookie`, `set-cookie` and `x-api-key`. + * A custom list replaces the defaults. Matching uses `isRedactedName`. + * Use `UrlParams.CurrentRedactedNames` for query parameters. * * @stability unstable * @category services @@ -439,10 +440,6 @@ export const CurrentRedactedNames = Context.Reference< "authorization", "cookie", "set-cookie", - "x-api-key", - "AWSAccessKeyId", - "Signature", - "sig", - "X-Goog-Signature" + "x-api-key" ] }) diff --git a/repos/effect/packages/effect/src/http/HttpClient.ts b/repos/effect/packages/effect/src/http/HttpClient.ts index 814dd81137..1c333ed911 100644 --- a/repos/effect/packages/effect/src/http/HttpClient.ts +++ b/repos/effect/packages/effect/src/http/HttpClient.ts @@ -47,6 +47,7 @@ import * as HttpMethod from "./HttpMethod.ts" import * as TraceContext from "./HttpTraceContext.ts" import * as tracing from "./internal/tracing.ts" import * as Url from "./Url.ts" +import * as UrlParams from "./UrlParams.ts" const TypeId = "~effect/http/HttpClient" @@ -727,7 +728,11 @@ export const make = ( (span) => { span.attribute("http.request.method", request.method) const redactedHeaderNames = fiber.getRef(Headers.CurrentRedactedNames) - tracing.addUrlAttributes(span, url) + tracing.addUrlAttributes( + span, + url, + tracing.redactedNames(request.urlParams, fiber.getRef(UrlParams.CurrentRedactedNames)) + ) const headerFilter = fiber.getRef(TracerHeaderFilter) tracing.addHeaderAttributes(span, "request", request.headers, headerFilter, redactedHeaderNames) request = fiber.getRef(TracerPropagationEnabled) @@ -952,6 +957,9 @@ export const retry: { * Specifying a `while` predicate allows you to consider other errors as * transient, and is ignored in "response-only" mode. * + * A `Retry-After` header on a transient response, or on the response of a + * status code error, sets the minimum delay before the next attempt. + * * @stability unstable * @category error handling * @since 4.0.0 @@ -1025,14 +1033,15 @@ export const retryTransient: { ): HttpClient.With => { const isOnlySchedule = Schedule.isSchedule(options) const retryOn = isOnlySchedule ? "errors-and-responses" : options.retryOn ?? "errors-and-responses" - const schedule = isOnlySchedule ? options : options.schedule - const passthroughSchedule = schedule && Schedule.passthrough(schedule) + const schedule = withRetryAfter( + isOnlySchedule ? options : options.schedule ?? Schedule.forever + ) const times = isOnlySchedule ? undefined : options.times return transformResponse( self, flow( retryOn === "errors-only" ? identity : Effect.repeat({ - schedule: passthroughSchedule!, + schedule, times, while: isTransientResponse }), @@ -1150,6 +1159,8 @@ export declare namespace WithRateLimiter { * It can update limits by inspecting common rate limit response headers and * automatically retries HTTP `429` responses (or `HttpClientError` values * wrapping a `429` response) by forcing the retry back through the limiter. + * When a response reports the remaining budget, requests wait for the + * reported reset once that budget is exhausted. * * **Gotchas** * @@ -1200,14 +1211,36 @@ export const withRateLimiter: { return initialState } + const budgets = new Map() + const getBudget = (key: string): RateLimitBudget => { + let budget = budgets.get(key) + if (budget === undefined) { + budget = { sent: 0, observed: 0, remaining: 0, resetAt: 0 } + budgets.set(key, budget) + } + return budget + } + const onResponse = options.disableResponseInspection ? undefined - : (clock: Clock, key: string, headers: Headers.Headers, tokens: number) => { + : (clock: Clock, key: string, headers: Headers.Headers, tokens: number, sent: number) => { const current = getState(key) const next = parseRateLimiterState(current, clock, headers, tokens, headerNames) if (next.limit !== current.limit || !Duration.equals(next.window, current.window)) { states.set(key, next) } + const remaining = parseRateLimitRemaining(headers, headerNames) + const budget = getBudget(key) + // responses to earlier requests carry stale counts + if (remaining === undefined || sent <= budget.observed) { + return + } + const resetAfter = parseRateLimitWindow(clock, headers, headerNames) + budget.observed = sent + budget.remaining = remaining + if (resetAfter !== undefined) { + budget.resetAt = clock.currentTimeMillisUnsafe() + Duration.toMillis(resetAfter) + } } return transform(self, function loop(effect, request, retries = 0): Effect.Effect< @@ -1219,6 +1252,15 @@ export const withRateLimiter: { const clock = fiber.getRef(Clock) const key = resolveKey(request) const tokens = Math.max(resolveTokens(request), 1) + const budget = getBudget(key) + const now = clock.currentTimeMillisUnsafe() + // requests admitted after the observed one are not reflected in its count + if (budget.resetAt > now && budget.remaining - (budget.sent - budget.observed) < tokens) { + return Effect.flatMap(Effect.sleep(budget.resetAt - now), () => loop(effect, request, retries)) + } + // counted at admission, so requests already admitted are sent even if a + // later response exhausts the budget + const sent = budget.sent += tokens const current = getState(key) const canRetry = options.times === undefined || retries < options.times function retry(retryAfter: Duration.Duration | undefined) { @@ -1230,11 +1272,14 @@ export const withRateLimiter: { response: HttpClientResponse.HttpClientResponse, adaptive: RateLimiter.AdaptiveConsumeResult | undefined ) => { - onResponse?.(clock, key, response.headers, tokens) + onResponse?.(clock, key, response.headers, tokens, sent) if (options.disableResponseInspection || response.status !== 429) { return Effect.succeed(undefined) } - const retryAfter = parseRetryAfter(clock, getHeader(response.headers, ...headerNames.retryAfter)) + const retryAfter = parseRetryAfter( + clock.currentTimeMillisUnsafe(), + getHeader(response.headers, ...headerNames.retryAfter) + ) if (retryAfter === undefined) { return Effect.succeed(undefined) } @@ -1348,6 +1393,17 @@ interface RateLimiterState { readonly initial: boolean } +interface RateLimitBudget { + /** Total tokens admitted for the key. */ + sent: number + /** The `sent` total of the request whose remaining count was last applied. */ + observed: number + /** The remaining count reported in response to the `observed` request. */ + remaining: number + /** When the server budget resets, in epoch milliseconds. */ + resetAt: number +} + const parseRateLimiterState = ( state: RateLimiterState, clock: Clock, @@ -1403,21 +1459,24 @@ const parseRateLimitWindow = ( } const parseRetryAfter = ( - clock: Clock, + nowMillis: number, value: string | undefined ): Duration.Duration | undefined => { if (value === undefined) { return undefined } - const numeric = parseNumberHeader(value) - if (numeric !== undefined) { - return Duration.max(Duration.seconds(numeric), Duration.millis(1)) + const trimmed = value.trim() + if (/^\d+(?:\.\d+)?$/.test(trimmed)) { + const numeric = Number(trimmed) + return Number.isFinite(numeric) + ? Duration.max(Duration.seconds(numeric), Duration.millis(1)) + : undefined } - const parsedDate = Date.parse(value) + const parsedDate = Date.parse(trimmed) if (Number.isNaN(parsedDate)) { return undefined } - const millis = parsedDate - clock.currentTimeMillisUnsafe() + const millis = parsedDate - nowMillis if (millis <= 0) { return Duration.millis(1) } @@ -1695,6 +1754,18 @@ export const TracerHeaderFilter = Context.Reference< /** * Context reference that controls whether outgoing client spans are propagated to request headers. * + * **Details** + * + * When this is `true`, the client writes the compact B3 `b3` header and the + * W3C `traceparent` header. The default is on. The client span is still + * created when this is `false`. + * + * **Gotchas** + * + * A browser preflight fails when the target does not list `b3` and + * `traceparent` in `Access-Control-Allow-Headers`. Set this to `false` for + * those requests. + * * @stability unstable * @category services * @since 4.0.0 @@ -1879,6 +1950,28 @@ const isTransientHttpError = (error: unknown) => (error.reason._tag === "TransportError" || (error.reason._tag === "StatusCodeError" && isTransientResponse(error.reason.response))) +const retryAfterOf = (input: unknown, nowMillis: number): Duration.Duration | undefined => { + const response = Error.isHttpClientError(input) + ? input.response + : Predicate.hasProperty(input, HttpClientResponse.TypeId) + ? input as HttpClientResponse.HttpClientResponse + : undefined + return parseRetryAfter(nowMillis, response?.headers["retry-after"]) +} + +const withRetryAfter = ( + schedule: Schedule.Schedule +): Schedule.Schedule => + Schedule.fromStep( + Effect.map(Schedule.toStep(schedule), (step) => (now: number, input: unknown) => { + const retryAfter = retryAfterOf(input, now) + if (retryAfter === undefined) { + return step(now, input) + } + return Effect.map(step(now, input), ([output, delay]) => [output, Duration.max(delay, retryAfter)]) + }) + ) + const isTooManyRequestsHttpClientError = ( error: unknown ): error is Error.HttpClientError & { readonly reason: Error.StatusCodeError } => diff --git a/repos/effect/packages/effect/src/http/HttpClientError.ts b/repos/effect/packages/effect/src/http/HttpClientError.ts index 5eef2445b5..35bdef0c57 100644 --- a/repos/effect/packages/effect/src/http/HttpClientError.ts +++ b/repos/effect/packages/effect/src/http/HttpClientError.ts @@ -15,6 +15,7 @@ import { hasProperty } from "../Predicate.ts" import * as Schema from "../Schema.ts" import type * as HttpClientRequest from "./HttpClientRequest.ts" import type * as ClientResponse from "./HttpClientResponse.ts" +import * as UrlParams from "./UrlParams.ts" const TypeId = "~effect/http/HttpClientError" @@ -88,6 +89,9 @@ const formatReason = (tag: string) => tag.endsWith("Error") ? tag.slice(0, -5) : const formatMessage = (reason: string, description: string | undefined, info: string) => description ? `${reason}: ${description} (${info})` : `${reason} error (${info})` +const formatMethodAndUrl = (request: HttpClientRequest.HttpClientRequest) => + `${request.method} ${UrlParams.redactUrl(request.url)}` + /** * Error describing transport-level failures that occur while sending an HTTP request. * @@ -107,7 +111,7 @@ export class TransportError extends Data.TaggedError("TransportError")<{ * @since 4.0.0 */ get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } /** @@ -140,7 +144,7 @@ export class EncodeError extends Data.TaggedError("EncodeError")<{ * @since 4.0.0 */ get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } /** @@ -173,7 +177,7 @@ export class InvalidUrlError extends Data.TaggedError("InvalidUrlError")<{ * @since 4.0.0 */ get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } /** @@ -207,7 +211,7 @@ export class StatusCodeError extends Data.TaggedError("StatusCodeError")<{ * @since 4.0.0 */ get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } /** @@ -242,7 +246,7 @@ export class DecodeError extends Data.TaggedError("DecodeError")<{ * @since 4.0.0 */ get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } /** @@ -277,7 +281,7 @@ export class EmptyBodyError extends Data.TaggedError("EmptyBodyError")<{ * @since 4.0.0 */ get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } /** diff --git a/repos/effect/packages/effect/src/http/HttpClientRequest.ts b/repos/effect/packages/effect/src/http/HttpClientRequest.ts index 7b5a208229..68c9e3d133 100644 --- a/repos/effect/packages/effect/src/http/HttpClientRequest.ts +++ b/repos/effect/packages/effect/src/http/HttpClientRequest.ts @@ -30,6 +30,7 @@ import * as Stream from "../Stream.ts" import * as Headers from "./Headers.ts" import * as HttpBody from "./HttpBody.ts" import { hasBody, type HttpMethod } from "./HttpMethod.ts" +import * as compression from "./internal/compressionBody.ts" import * as bodyInternal from "./internal/httpBody.ts" import * as Url from "./Url.ts" import * as UrlParams from "./UrlParams.ts" @@ -104,7 +105,7 @@ const Proto = { return { _id: "HttpClientRequest", method: this.method, - url: this.url, + url: UrlParams.redactUrl(this.url), urlParams: this.urlParams, hash: this.hash, headers: redact(this.headers), @@ -576,14 +577,18 @@ export const updateUrl: { /** * Sets one query parameter, replacing existing values for that parameter name. * + * **Details** + * + * A `Redacted` value is sent unwrapped and stays redacted in inspection, errors and spans. + * * @stability unstable * @category combinators * @since 4.0.0 */ export const setUrlParam: { - (key: string, value: string): (self: HttpClientRequest) => HttpClientRequest - (self: HttpClientRequest, key: string, value: string): HttpClientRequest -} = dual(3, (self: HttpClientRequest, key: string, value: string): HttpClientRequest => + (key: string, value: string | Redacted.Redacted): (self: HttpClientRequest) => HttpClientRequest + (self: HttpClientRequest, key: string, value: string | Redacted.Redacted): HttpClientRequest +} = dual(3, (self: HttpClientRequest, key: string, value: string | Redacted.Redacted): HttpClientRequest => makeWith( self.method, self.url, @@ -616,14 +621,18 @@ export const setUrlParams: { /** * Appends one query parameter value without removing existing values for the same name. * + * **Details** + * + * A `Redacted` value is sent unwrapped and stays redacted in inspection, errors and spans. + * * @stability unstable * @category combinators * @since 4.0.0 */ export const appendUrlParam: { - (key: string, value: string): (self: HttpClientRequest) => HttpClientRequest - (self: HttpClientRequest, key: string, value: string): HttpClientRequest -} = dual(3, (self: HttpClientRequest, key: string, value: string): HttpClientRequest => + (key: string, value: string | Redacted.Redacted): (self: HttpClientRequest) => HttpClientRequest + (self: HttpClientRequest, key: string, value: string | Redacted.Redacted): HttpClientRequest +} = dual(3, (self: HttpClientRequest, key: string, value: string | Redacted.Redacted): HttpClientRequest => makeWith( self.method, self.url, @@ -711,6 +720,88 @@ export const setBody: { ) }) +/** + * Algorithms supported by Web `CompressionStream` for request body compression. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type CompressionAlgorithm = "gzip" | "deflate" + +/** + * Options for request body compression. + * + * @stability unstable + * @category options + * @since 4.0.0 + */ +export interface CompressionOptions { + /** + * Minimum known body length in bytes to compress. Defaults to `1024`. + * Bodies with unknown length are always compressed. + */ + readonly minSize?: number | undefined +} + +/** + * Compresses a request body using Web `CompressionStream` and sets `Content-Encoding`. + * + * **Details** + * + * Byte-array bodies (including text, JSON, and URL-encoded bodies) are compressed + * into a new `Uint8Array` body, preserving the content type and updating + * `Content-Length`. The compressed body does not retain the original lazy text. + * Stream bodies are compressed lazily and have their content length removed. + * They still require a client runtime that supports streaming request bodies + * (Fetch requires `duplex: "half"`, which Safari and Firefox do not support). + * + * Returns the original request unchanged for empty, FormData, and raw bodies, + * bodies with a known length below `options.minSize`, or requests with any + * existing `Content-Encoding` header, including `identity`. Unknown-length + * streams are always compressed. The default minimum is 1024 bytes because + * gzip can make very small bodies larger. + * + * Requires `CompressionStream` (available in browsers, Node 18+, Bun, and Deno). + * There is no typed error channel: byte compression failures are defects; + * stream failures surface when the body is sent. + * + * To compress every request, use + * `HttpClient.mapRequestEffect(HttpClientRequest.compressBody("gzip"))`. + * `HttpClient.retryTransient` re-runs preprocessing, so this recompresses on + * every retry. For large bodies, compress once before calling `client.execute`. + * + * @stability unstable + * @category combinators + * @since 4.0.0 + */ +export const compressBody: { + ( + algorithm: CompressionAlgorithm, + options?: CompressionOptions | undefined + ): (self: HttpClientRequest) => Effect.Effect + ( + self: HttpClientRequest, + algorithm: CompressionAlgorithm, + options?: CompressionOptions | undefined + ): Effect.Effect +} = dual( + (args) => isHttpClientRequest(args[0]), + ( + self: HttpClientRequest, + algorithm: CompressionAlgorithm, + options?: CompressionOptions | undefined + ): Effect.Effect => { + if (self.headers["content-encoding"] !== undefined) { + return Effect.succeed(self) + } + return Effect.map( + compression.compressBody(self.body, algorithm, options), + (body) => body === self.body ? self : setHeader(setBody(self, body), "content-encoding", algorithm) + ) + } +) + /** * Sets a `Uint8Array` request body with an optional content type. * diff --git a/repos/effect/packages/effect/src/http/HttpEffect.ts b/repos/effect/packages/effect/src/http/HttpEffect.ts index 16e0fb4e29..2de32a8e71 100644 --- a/repos/effect/packages/effect/src/http/HttpEffect.ts +++ b/repos/effect/packages/effect/src/http/HttpEffect.ts @@ -321,10 +321,11 @@ export const toWebHandlerWith = { const withoutBody = request.method === "HEAD" if (!Response.omitsBody(response, withoutBody)) { + // The transferred request scope closes when an abort interrupts the body, even if it is no longer read. response = scopeTransferToStream(response) } ;(request as any)[resolveSymbol]( - Response.toWeb(response, { withoutBody, context }) + Response.toWeb(response, { withoutBody, context, signal: (request.source as globalThis.Request).signal }) ) return Effect.void }, middleware) @@ -340,10 +341,15 @@ export const toWebHandlerWith = { - fiber.interruptUnsafe(undefined, ClientAbort.annotation) - }, { once: true }) + const signal = request.signal + if (fiber.pollUnsafe() === undefined && signal) { + const onAbort = () => fiber.interruptUnsafe(undefined, ClientAbort.annotation) + if (signal.aborted) { + onAbort() + } else { + signal.addEventListener("abort", onAbort, { once: true }) + fiber.addObserver(() => signal.removeEventListener("abort", onAbort)) + } } }) } diff --git a/repos/effect/packages/effect/src/http/HttpMiddleware.ts b/repos/effect/packages/effect/src/http/HttpMiddleware.ts index 0b818c4e1f..87b4caf755 100644 --- a/repos/effect/packages/effect/src/http/HttpMiddleware.ts +++ b/repos/effect/packages/effect/src/http/HttpMiddleware.ts @@ -11,6 +11,7 @@ * @stability unstable * @since 4.0.0 */ +import * as ByteSize from "../ByteSize.ts" import * as Cause from "../Cause.ts" import { Clock } from "../Clock.ts" import * as Context from "../Context.ts" @@ -26,6 +27,7 @@ import type { Predicate } from "../Predicate.ts" import type { ReadonlyRecord } from "../Record.ts" import { nativeTracer, ParentSpan, Tracer } from "../Tracer.ts" import * as Headers from "./Headers.ts" +import { hasBody } from "./HttpMethod.ts" import type { CompressionAlgorithm } from "./HttpPlatform.ts" import { HttpPlatform } from "./HttpPlatform.ts" import { causeResponseStripped, ClientAbort, HttpServerError, ResponseError } from "./HttpServerError.ts" @@ -35,9 +37,11 @@ import * as Response from "./HttpServerResponse.ts" import type { HttpServerResponse } from "./HttpServerResponse.ts" import * as TraceContext from "./HttpTraceContext.ts" import * as compressionInternal from "./internal/compression.ts" +import * as decompressionInternal from "./internal/decompression.ts" import * as bodyInternal from "./internal/httpBody.ts" import { appendPreResponseHandlerUnsafe } from "./internal/preResponseHandler.ts" import * as tracing from "./internal/tracing.ts" +import * as UrlParams from "./UrlParams.ts" /** * Middleware that transforms an HTTP server app effect into another HTTP server app effect. @@ -268,42 +272,37 @@ export const tracer: ( } const redactedHeaderNames = fiber.getRef(Headers.CurrentRedactedNames) const headerFilter = fiber.getRef(TracerHeaderFilter) - fiber.currentDispatcher.scheduleTask(() => { - let response: HttpServerResponse - let spanExit: Exit.Exit - if (Exit.isFailure(exit)) { - const [failureResponse, cause] = causeResponseStripped(exit.cause) - response = failureResponse - // OpenTelemetry only treats 5xx responses as server span errors; interrupts still fail the span. - spanExit = Option.isSome(cause) && (response.status >= 500 || Cause.hasInterrupts(cause.value)) - ? Exit.failCause(cause.value) - : responseSpanExit(request, response) - } else { - response = exit.value - spanExit = responseSpanExit(request, response) + // Complete the span before the request fiber exits so shutdown can flush it. + let response: HttpServerResponse + let spanExit: Exit.Exit + if (Exit.isFailure(exit)) { + const [failureResponse, cause] = causeResponseStripped(exit.cause) + response = failureResponse + // OpenTelemetry only treats 5xx responses as server span errors; interrupts still fail the span. + spanExit = Option.isSome(cause) && (response.status >= 500 || Cause.hasInterrupts(cause.value)) + ? Exit.failCause(cause.value) + : responseSpanExit(request, response) + } else { + response = exit.value + spanExit = responseSpanExit(request, response) + } + if (span.sampled) { + span.attribute("http.request.method", request.method) + const url = Request.toURL(request) + if (Option.isSome(url)) { + tracing.addUrlAttributes(span, url.value, fiber.getRef(UrlParams.CurrentRedactedNames)) + } + if (request.headers["user-agent"] !== undefined) { + span.attribute("user_agent.original", request.headers["user-agent"]) } - if (span.sampled) { - span.attribute("http.request.method", request.method) - const url = Request.toURL(request) - if (Option.isSome(url)) { - if (!request.url.startsWith("/") && (url.value.username !== "" || url.value.password !== "")) { - url.value.username = "REDACTED" - url.value.password = "REDACTED" - } - tracing.addUrlAttributes(span, url.value) - } - if (request.headers["user-agent"] !== undefined) { - span.attribute("user_agent.original", request.headers["user-agent"]) - } - tracing.addHeaderAttributes(span, "request", request.headers, headerFilter, redactedHeaderNames) - if (Option.isSome(request.remoteAddress)) { - span.attribute("client.address", request.remoteAddress.value) - } - span.attribute("http.response.status_code", response.status) - tracing.addHeaderAttributes(span, "response", response.headers, headerFilter, redactedHeaderNames) + tracing.addHeaderAttributes(span, "request", request.headers, headerFilter, redactedHeaderNames) + if (Option.isSome(request.remoteAddress)) { + span.attribute("client.address", request.remoteAddress.value) } - span.end(endTime, spanExit) - }, 0) + span.attribute("http.response.status_code", response.status) + tracing.addHeaderAttributes(span, "response", response.headers, headerFilter, redactedHeaderNames) + } + span.end(endTime, spanExit) return undefined }) return httpApp @@ -627,6 +626,86 @@ export const compression = ( }) } +/** + * Middleware that decompresses request bodies sent with a `Content-Encoding` + * of `gzip` or `deflate`. + * + * **Details** + * + * The request service is replaced with a view whose body accessors (`stream`, + * `text`, `json`, `arrayBuffer`, `urlParamsBody`, `multipart`) yield the + * decompressed body, and whose headers no longer include `Content-Encoding` + * or `Content-Length`. Decompression is lazy and only happens when the body + * is read. Stacked codings such as `deflate, gzip` are undone in reverse + * order, and `identity` members are ignored. + * + * Requests whose `Content-Encoding` includes any other coding are rejected + * with `415 Unsupported Media Type` and `Accept-Encoding: gzip, deflate`, + * without running the app. Malformed compressed data fails the body read + * with a `RequestParseError`, or a `MultipartError` with reason `Parse` when + * reading multipart data. + * + * The decompressed size is limited to `maxDecompressedSize`, falling back to + * the `MaxBodySize` reference and then to 10 MiB. Exceeding it fails the body + * read with a `RequestParseError`, or a `MultipartError` with reason + * `BodyTooLarge` when reading multipart data. The limit applies to every body + * accessor, including `stream`. + * + * Decompression uses the global `DecompressionStream`. `deflate` means the + * zlib format (RFC 1950); raw deflate data is rejected. + * + * **Gotchas** + * + * `request.source` is still the original, compressed request. + * `HttpServerRequest.toWeb` returns that compressed request only when the + * source is a Web `Request`. On other platforms, such as Node, it builds a new + * `Request` from the decompressed body and the stripped headers. + * + * @stability unstable + * @category compression + * @since 4.0.0 + */ +export const decompression = ( + options?: { + /** + * Maximum number of decompressed body bytes. Defaults to the + * `MaxBodySize` reference, or 10 MiB when that is unset. + */ + readonly maxDecompressedSize?: ByteSize.Input | undefined + } | undefined +): ( + httpApp: Effect.Effect +) => Effect.Effect => { + const maxDecompressedSize = options?.maxDecompressedSize === undefined + ? undefined + : ByteSize.fromInputUnsafe(options.maxDecompressedSize) + return ( + httpApp: Effect.Effect + ): Effect.Effect => + Effect.withFiber((fiber) => { + const request = Context.getUnsafe(fiber.context, HttpServerRequest) + const contentEncoding = request.headers["content-encoding"] + if (contentEncoding === undefined || !hasBody(request.method)) { + return httpApp + } + const codings = decompressionInternal.parseContentEncoding(contentEncoding) + if (codings === undefined) { + return Effect.succeed(Response.empty({ + status: 415, + headers: { "accept-encoding": "gzip, deflate" } + })) + } + if (codings.length === 0) { + return httpApp + } + return Effect.provideService( + httpApp, + HttpServerRequest, + new decompressionInternal.DecompressedRequest(request, codings, maxDecompressedSize) + ) + }) +} + const withVary = (response: HttpServerResponse): HttpServerResponse => { const vary = compressionInternal.varyWith(response.headers, "Accept-Encoding") return Response.setHeader(response, "vary", vary) diff --git a/repos/effect/packages/effect/src/http/HttpRouter.ts b/repos/effect/packages/effect/src/http/HttpRouter.ts index e95adbd04e..fb9430af18 100644 --- a/repos/effect/packages/effect/src/http/HttpRouter.ts +++ b/repos/effect/packages/effect/src/http/HttpRouter.ts @@ -24,6 +24,7 @@ import * as Scope from "../Scope.ts" import * as Tracer from "../Tracer.ts" import type * as Types from "../Types.ts" import * as FindMyWay from "./FindMyWay.ts" +import { getClosingParenthensePosition } from "./FindMyWay/internal/router.ts" import * as HttpEffect from "./HttpEffect.ts" import * as HttpIncomingMessage from "./HttpIncomingMessage.ts" import type * as HttpMethod from "./HttpMethod.ts" @@ -123,7 +124,12 @@ export const HttpRouter: Context.Service = Context.Servi * @since 4.0.0 */ export const make = Effect.gen(function*() { - const router = FindMyWay.make>(yield* RouterConfig) + const config = yield* RouterConfig + const ignoreDuplicateSlashes = config.ignoreDuplicateSlashes ?? true + const router = FindMyWay.make<{ + readonly route: Route + readonly prefixSegments: number | undefined + }>(config) const middleware = new Set() const addAll = >>( @@ -147,19 +153,25 @@ export const make = Effect.gen(function*() { ...routes[i], handler: applyMiddleware(routes[i].handler as Effect.Effect) }) + const handler = { + route: route as Route, + prefixSegments: Option.isSome(route.prefix) + ? countSegments(route.prefix.value, ignoreDuplicateSlashes) + : undefined + } if (route.method === "*") { if (route.path.endsWith("/*")) { - router.all(route.path, route as any) - router.all(route.path.slice(0, -2) as any, route as any) + router.all(route.path, handler) + router.all(route.path.slice(0, -2) as any, handler) } else { - router.all(route.path, route as any) + router.all(route.path, handler) } } else { if (route.path.endsWith("/*")) { - router.on(route.method, route.path, route as any) - router.on(route.method, route.path.slice(0, -2) as any, route as any) + router.on(route.method, route.path, handler) + router.on(route.method, route.path.slice(0, -2) as any, handler) } else { - router.on(route.method, route.path, route as any) + router.on(route.method, route.path, handler) } } } @@ -211,12 +223,12 @@ export const make = Effect.gen(function*() { }) ) } - const route = result.handler - if (Option.isSome(route.prefix)) { + const { route, prefixSegments } = result.handler + if (prefixSegments !== undefined) { context = Context.add( context, HttpServerRequest.HttpServerRequest, - sliceRequestUrl(request, route.prefix.value) + sliceRequestUrl(request, prefixSegments, ignoreDuplicateSlashes) ) } context = Context.add(context, HttpServerRequest.ParsedSearchParams, result.searchParams) @@ -251,9 +263,44 @@ export const make = Effect.gen(function*() { }) }) -function sliceRequestUrl(request: HttpServerRequest.HttpServerRequest, prefix: string) { - const prefexLen = prefix.length - return request.modify({ url: request.url.length <= prefexLen ? "/" : request.url.slice(prefexLen) }) +function sliceRequestUrl( + request: HttpServerRequest.HttpServerRequest, + prefixSegments: number, + ignoreDuplicateSlashes: boolean +) { + const url = request.url + let index = 0 + for (let segments = prefixSegments; segments > 0; segments--) { + if (ignoreDuplicateSlashes) { + while (url[index] === "/") index++ + } else if (url[index] === "/") { + index++ + } + while (index < url.length && !"/?;#".includes(url[index])) index++ + } + return request.modify({ url: index < url.length ? url.slice(index) : "/" }) +} + +function countSegments(prefix: string, ignoreDuplicateSlashes: boolean) { + let count = 0 + let inParamName = false + for (let i = 0; i < prefix.length; i++) { + const char = prefix[i] + if (char === "/") { + if (!ignoreDuplicateSlashes || prefix[i - 1] !== "/") count++ + inParamName = false + } else if (char === ":") { + if (prefix[i + 1] === ":") i++ + else inParamName = true + } else if (char === "-" || char === ".") { + inParamName = false + } else if (char === "(" && inParamName) { + // Slashes inside parameter regexes are not segment boundaries. + i = getClosingParenthensePosition(prefix, i) + inParamName = false + } + } + return count } /** @@ -1360,6 +1407,41 @@ export const serve = | Request.On * request arrives, in which case that request waits for the build to finish. * If the build fails, every request rejects with the build error. * + * **Gotchas** + * + * On Cloudflare Workers, build the handler at module scope: fibers started + * inside `fetch` capture that request's async context. Layer construction + * must not require request-time I/O; bindings are available from + * `cloudflare:workers` via its `env` export. + * Prefer request-local work or a Durable Object's supported lifecycle APIs, + * not indefinite background execution. For shared fibers, provide a sync + * scheduler to both layers and requests as below; see `Scheduler.MixedScheduler` + * for its limitations. Bound waits for shared work with request-local timeouts. + * + * **Example** (Opting in to the sync scheduler on Workers) + * + * ```ts + * import { Effect, Layer, Scheduler } from "effect" + * import { HttpRouter, HttpServer, HttpServerResponse } from "effect/http" + * + * const SyncScheduler = Layer.succeed( + * Scheduler.Scheduler, + * new Scheduler.MixedScheduler("sync") + * ) + * const AppLive = HttpRouter.add( + * "GET", + * "/ping", + * Effect.succeed(HttpServerResponse.text("pong")) + * ).pipe(Layer.provide(HttpServer.layerServices)) + * + * // Build once at module scope. The scheduler is also retained for requests. + * const app = HttpRouter.toWebHandler( + * AppLive.pipe(Layer.provideMerge(SyncScheduler)) + * ) + * + * export default { fetch: (request: Request) => app.handler(request) } + * ``` + * * @stability unstable * @category converting * @since 4.0.0 diff --git a/repos/effect/packages/effect/src/http/HttpServerError.ts b/repos/effect/packages/effect/src/http/HttpServerError.ts index fa9bffdffe..f06401d15c 100644 --- a/repos/effect/packages/effect/src/http/HttpServerError.ts +++ b/repos/effect/packages/effect/src/http/HttpServerError.ts @@ -23,6 +23,7 @@ import { hasProperty } from "../Predicate.ts" import type * as Request from "./HttpServerRequest.ts" import * as Respondable from "./HttpServerRespondable.ts" import * as Response from "./HttpServerResponse.ts" +import * as UrlParams from "./UrlParams.ts" const TypeId = "~effect/http/HttpServerError" @@ -107,7 +108,7 @@ export class RequestParseError extends Data.TaggedError("RequestParseError")<{ } get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } override get message() { @@ -139,7 +140,7 @@ export class RouteNotFound extends Data.TaggedError("RouteNotFound")<{ override readonly [ErrorReporter.ignore] = true get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } override get message() { @@ -174,7 +175,7 @@ export class InternalError extends Data.TaggedError("InternalError")<{ } get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } override get message() { @@ -214,7 +215,7 @@ export class ResponseError extends Data.TaggedError("ResponseError")<{ } get methodAndUrl() { - return `${this.request.method} ${this.request.url}` + return formatMethodAndUrl(this.request) } override get message() { @@ -275,6 +276,9 @@ export class ClientAbort extends Context.Service()("effect/ht ) } +const formatMethodAndUrl = (request: Request.HttpServerRequest) => + `${request.method} ${UrlParams.redactUrl(request.url)}` + const formatRequestMessage = (reason: string, description: string | undefined, info: string) => { const prefix = `${reason} (${info})` return description ? `${prefix}: ${description}` : prefix diff --git a/repos/effect/packages/effect/src/http/HttpServerRequest.ts b/repos/effect/packages/effect/src/http/HttpServerRequest.ts index b6e36d01ee..32998988b3 100644 --- a/repos/effect/packages/effect/src/http/HttpServerRequest.ts +++ b/repos/effect/packages/effect/src/http/HttpServerRequest.ts @@ -512,7 +512,7 @@ class ServerRequestImpl extends Inspectable.Class implements HttpServerRequest { return HttpIncomingMessage.inspect(this, { _id: "HttpServerRequest", method: this.method, - url: this.originalUrl + url: UrlParams.redactUrl(this.originalUrl) }) } modify( @@ -711,7 +711,7 @@ class ClientRequestImpl extends Inspectable.Class implements HttpServerRequest { return HttpIncomingMessage.inspect(this, { _id: "HttpServerRequest", method: this.method, - url: this.originalUrl + url: UrlParams.redactUrl(this.originalUrl) }) } diff --git a/repos/effect/packages/effect/src/http/HttpServerResponse.ts b/repos/effect/packages/effect/src/http/HttpServerResponse.ts index 0479fc34dd..3d07cd4ac0 100644 --- a/repos/effect/packages/effect/src/http/HttpServerResponse.ts +++ b/repos/effect/packages/effect/src/http/HttpServerResponse.ts @@ -1028,23 +1028,35 @@ export const setStatus: { export const omitsBody = (response: HttpServerResponse, withoutBody = false): boolean => withoutBody || response.status === 204 || response.status === 205 || response.status === 304 +const mergeHeaders = (target: globalThis.Headers, headers: globalThis.Headers): globalThis.Headers => { + for (const [key, value] of headers as any) { + if (key === "set-cookie") { + target.append(key, value) + } else { + target.set(key, value) + } + } + return target +} + /** * Converts an `HttpServerResponse` to a Web `Response`. * * **Details** * * Cookies are appended as `Set-Cookie` headers. Stream bodies are converted using - * the supplied context. + * the supplied context, and are interrupted when `signal` aborts. * * Bodies are omitted for statuses 204, 205, and 304, or when `withoutBody` is true * (for example, for HEAD responses). Omitted raw `ReadableStream` bodies are * cancelled without awaiting completion, and cancellation errors are ignored. * - * A raw `Response` body is returned as-is after the outer headers are merged - * into it: outer headers replace native ones, and cookies are appended. When - * its body is omitted, the bodyless `Response` keeps those merged headers and - * uses the outer status for 204, 205 and 304, or the raw `Response` status - * otherwise. + * A raw `Response` is returned as-is when there are no outer headers or cookies + * to merge. Otherwise, they are merged into a copy without modifying the raw + * response: outer headers replace native ones, and cookies are appended. When + * its body is omitted, the bodyless `Response` keeps those merged + * headers and uses the outer status for 204, 205 and 304, or the raw `Response` + * status otherwise. * * @stability unstable * @category converting @@ -1055,6 +1067,7 @@ export const toWeb = ( options?: { readonly withoutBody?: boolean | undefined readonly context?: Context.Context | undefined + readonly signal?: AbortSignal | undefined } ): Response => { const headers = new globalThis.Headers(response.headers) @@ -1069,15 +1082,13 @@ export const toWeb = ( const withoutBody = outerOmitsBody || options?.withoutBody === true if (body._tag === "Raw" && body.body instanceof Response) { const raw = body.body - for (const [key, value] of headers as any) { - if (key === "set-cookie") { - raw.headers.append(key, value) - } else { - raw.headers.set(key, value) - } - } if (!withoutBody) { - return raw + if (headers.keys().next().done) { + return raw + } + const copy = new Response(raw.body, raw) + mergeHeaders(copy.headers, headers) + return copy } // A bodyless outer status is what the caller chose to send; otherwise the // body is only omitted for HEAD and the raw Response describes the resource. @@ -1085,7 +1096,7 @@ export const toWeb = ( return new Response(undefined, { status: source.status, statusText: source.statusText as string, - headers: raw.headers + headers: mergeHeaders(new globalThis.Headers(raw.headers), headers) }) } if (withoutBody) { @@ -1131,7 +1142,8 @@ export const toWeb = ( return new Response( Stream.toReadableStreamWith( body.stream, - options?.context ?? Context.empty() + options?.context ?? Context.empty(), + { signal: options?.signal } ), { status: response.status, diff --git a/repos/effect/packages/effect/src/http/HttpStaticServer.ts b/repos/effect/packages/effect/src/http/HttpStaticServer.ts index b1be9c5189..1bf300ac94 100644 --- a/repos/effect/packages/effect/src/http/HttpStaticServer.ts +++ b/repos/effect/packages/effect/src/http/HttpStaticServer.ts @@ -13,6 +13,7 @@ import * as Effect from "../Effect.ts" import * as FileSystem from "../FileSystem.ts" import * as Layer from "../Layer.ts" +import * as Option from "../Option.ts" import * as Path from "../Path.ts" import type { PlatformError } from "../PlatformError.ts" import * as HttpPlatform from "./HttpPlatform.ts" @@ -398,16 +399,9 @@ const resolveFilePath = (path: Path.Path, root: string, url: string): string | u if (decodedPath.includes("\u0000")) { return undefined } - const normalizedPath = path.normalize(decodedPath.startsWith("/") ? decodedPath.slice(1) : decodedPath) - if (normalizedPath === ".." || normalizedPath.startsWith(`..${path.sep}`)) { - return undefined - } - const resolvedPath = path.join(root, normalizedPath) - const rootPrefix = root.endsWith(path.sep) ? root : `${root}${path.sep}` - if (resolvedPath !== root && !resolvedPath.startsWith(rootPrefix)) { - return undefined - } - return resolvedPath + // every leading separator is part of the URL, not a filesystem root + const relativePath = decodedPath.replace(path.sep === "\\" ? /^[/\\]+/ : /^\/+/, "") + return Option.getOrUndefined(path.resolveWithin(root, relativePath)) } const toRouteNotFoundError = (request: HttpServerRequest.HttpServerRequest) => diff --git a/repos/effect/packages/effect/src/http/HttpTraceContext.ts b/repos/effect/packages/effect/src/http/HttpTraceContext.ts index 0fd64e12f7..b61d35164e 100644 --- a/repos/effect/packages/effect/src/http/HttpTraceContext.ts +++ b/repos/effect/packages/effect/src/http/HttpTraceContext.ts @@ -49,7 +49,7 @@ export const toHeaders = (span: Tracer.Span): Headers.Headers => onSome: (parent) => `-${parent.spanId}` }) }`, - traceparent: `00-${span.traceId}-${span.spanId}-${span.sampled ? "01" : "00"}` + traceparent: `00-${span.traceId.padStart(32, "0")}-${span.spanId}-${span.sampled ? "01" : "00"}` }) /** @@ -93,7 +93,7 @@ export const b3: FromHeaders = (headers) => { return Option.none() } const parts = headers["b3"].split("-") - if (parts.length < 2) { + if (parts.length < 2 || isB3Ids(parts[0], parts[1]) === false) { return Option.none() } return Option.some(Tracer.externalSpan({ @@ -116,7 +116,10 @@ export const b3: FromHeaders = (headers) => { * @since 4.0.0 */ export const xb3: FromHeaders = (headers) => { - if (!(headers["x-b3-traceid"]) || !(headers["x-b3-spanid"])) { + if ( + !(headers["x-b3-traceid"]) || !(headers["x-b3-spanid"]) || + isB3Ids(headers["x-b3-traceid"], headers["x-b3-spanid"]) === false + ) { return Option.none() } return Option.some(Tracer.externalSpan({ @@ -130,6 +133,9 @@ export const xb3: FromHeaders = (headers) => { const w3cTraceId = /^[0-9a-f]{32}$/i const w3cSpanId = /^[0-9a-f]{16}$/i +const b3TraceId = /^(?:[0-9a-f]{16}|[0-9a-f]{32})$/i +const isB3Ids = (traceId: string, spanId: string): boolean => b3TraceId.test(traceId) && w3cSpanId.test(spanId) + /** * Decodes an external span safely from the W3C `traceparent` header. * diff --git a/repos/effect/packages/effect/src/http/Multipart.ts b/repos/effect/packages/effect/src/http/Multipart.ts index bc6372a025..333ea65f5f 100644 --- a/repos/effect/packages/effect/src/http/Multipart.ts +++ b/repos/effect/packages/effect/src/http/Multipart.ts @@ -689,6 +689,22 @@ const defaultWriteFile = (path: string, file: File) => (fs) => Effect.mapError(Stream.run(file.content, fs.sink(path)), toMultipartError) ) +const maxPersistedFileNameBytes = 128 +const fileNameEncoder = new TextEncoder() + +// Keeps the trailing 128 UTF-8 bytes without splitting code points. Empty and dot names fall back to "file". +const persistedFileName = (baseName: string): string => { + const codePoints = Array.from(baseName) + let fileName = "" + let bytes = 0 + for (let i = codePoints.length - 1; i >= 0; i--) { + bytes += fileNameEncoder.encode(codePoints[i]).length + if (bytes > maxPersistedFileNameBytes) break + fileName = codePoints[i] + fileName + } + return fileName === "" || fileName === "." || fileName === ".." ? "file" : fileName +} + /** * Runs a channel of byte chunks and collects all output into a single * `Uint8Array`. @@ -748,7 +764,7 @@ export const toPersisted = ( return Effect.void } const file = part - const fileName = path_.basename(file.name).slice(-128) + const fileName = persistedFileName(path_.basename(file.name)) let path = path_.join(dir, fileName) while (usedPaths.has(path)) { path = path_.join(dir, `${fileIndex++}-${fileName}`) diff --git a/repos/effect/packages/effect/src/http/Url.ts b/repos/effect/packages/effect/src/http/Url.ts index 63c4181606..7c0c9b8599 100644 --- a/repos/effect/packages/effect/src/http/Url.ts +++ b/repos/effect/packages/effect/src/http/Url.ts @@ -14,6 +14,7 @@ import * as Data from "../Data.ts" import { dual } from "../Function.ts" import * as Redacted from "../Redacted.ts" import * as Result from "../Result.ts" +import * as internal from "./internal/urlParams.ts" import * as UrlParams from "./UrlParams.ts" /** @@ -49,7 +50,7 @@ export const make = ( for (let i = 0; i < params.params.length; i++) { const [key, value] = params.params[i] if (value !== undefined) { - urlInstance.searchParams.append(key, value) + urlInstance.searchParams.append(key, internal.unwrap(value)) } } if (hash !== undefined) { diff --git a/repos/effect/packages/effect/src/http/UrlParams.ts b/repos/effect/packages/effect/src/http/UrlParams.ts index a3b8d078ee..d5ce11c845 100644 --- a/repos/effect/packages/effect/src/http/UrlParams.ts +++ b/repos/effect/packages/effect/src/http/UrlParams.ts @@ -10,6 +10,7 @@ * @since 4.0.0 */ import * as Arr from "../Array.ts" +import * as Context from "../Context.ts" import * as Equal from "../Equal.ts" import * as Equ from "../Equivalence.ts" import { dual } from "../Function.ts" @@ -21,7 +22,11 @@ import * as Option from "../Option.ts" import type { Pipeable } from "../Pipeable.ts" import { hasProperty } from "../Predicate.ts" import type { ReadonlyRecord } from "../Record.ts" +import * as Redactable from "../Redactable.ts" +import * as Redacted from "../Redacted.ts" import * as Tuple from "../Tuple.ts" +import * as Headers from "./Headers.ts" +import * as internal from "./internal/urlParams.ts" const TypeId = "~effect/http/UrlParams" @@ -30,16 +35,19 @@ const TypeId = "~effect/http/UrlParams" * * **Details** * - * Parameters are stored as ordered string key-value pairs and can contain multiple - * values for the same key. + * Parameters are ordered key-value pairs, and a key can repeat. Each value is a + * string or a `Redacted` string, which is sent unwrapped. Inspection redacts + * `Redacted` values and values whose names match `CurrentRedactedNames`. * * @stability unstable * @category models * @since 4.0.0 */ -export interface UrlParams extends Pipeable, Inspectable, Iterable { +export interface UrlParams + extends Pipeable, Inspectable, Redactable.Redactable, Iterable +{ readonly [TypeId]: typeof TypeId - readonly params: ReadonlyArray + readonly params: ReadonlyArray } /** @@ -74,7 +82,11 @@ type CoercibleRecordInput = CoercibleRecord & { } /** - * Primitive value that can be converted into a URL parameter string. + * Value that can be converted into a URL parameter string. + * + * **Details** + * + * `Redacted` values are stored wrapped and sent unwrapped. * * **Gotchas** * @@ -84,7 +96,7 @@ type CoercibleRecordInput = CoercibleRecord & { * @category models * @since 4.0.0 */ -export type Coercible = string | number | bigint | boolean | null | undefined +export type Coercible = string | number | bigint | boolean | null | undefined | Redacted.Redacted /** * @stability unstable @@ -118,12 +130,15 @@ const Proto = { [Symbol.iterator](this: UrlParams) { return this.params[Symbol.iterator]() }, - toJSON(this: UrlParams): unknown { + [Redactable.symbolRedactable](this: UrlParams, context: Context.Context): unknown { return { _id: "UrlParams", - params: Object.fromEntries(this.params) + params: Object.fromEntries(redact(this, Context.get(context, CurrentRedactedNames))) } }, + toJSON(this: UrlParams): unknown { + return Redactable.redact(this) + }, [Equal.symbol](this: UrlParams, that: UrlParams): boolean { return Equivalence(this, that) }, @@ -133,7 +148,7 @@ const Proto = { } /** - * Creates `UrlParams` from ordered string key-value pairs. + * Creates `UrlParams` from ordered key-value pairs. * * **Details** * @@ -143,7 +158,7 @@ const Proto = { * @category constructors * @since 4.0.0 */ -export const make = (params: ReadonlyArray): UrlParams => { +export const make = (params: ReadonlyArray): UrlParams => { const self = Object.create(Proto) self.params = params return self @@ -156,6 +171,7 @@ export const make = (params: ReadonlyArray): UrlParam * * Primitive values are converted to strings, arrays produce repeated parameters, * nested records use bracket notation, and `undefined` values are omitted. + * `Redacted` values are kept as-is. * * @stability unstable * @category constructors @@ -166,42 +182,44 @@ export const fromInput = (input: Input): UrlParams => { return input } const parsed = fromInputNested(input) - const out: Array<[string, string]> = [] + const out: Array<[string, string | Redacted.Redacted]> = [] for (let i = 0; i < parsed.length; i++) { if (Array.isArray(parsed[i][0])) { - const [keys, value] = parsed[i] as [Array, string] + const [keys, value] = parsed[i] as [Array, string | Redacted.Redacted] out.push([`${keys[0]}[${keys.slice(1).join("][")}]`, value]) } else { - out.push(parsed[i] as [string, string]) + out.push(parsed[i] as [string, string | Redacted.Redacted]) } } return make(out) } -const fromInputNested = (input: Input): Array<[string | Array, any]> => { +const fromInputNested = (input: Input): Array<[string | Array, string | Redacted.Redacted]> => { const entries = typeof (input as any)[Symbol.iterator] === "function" ? Arr.fromIterable(input as Iterable) : Object.entries(input) - const out: Array<[string | Array, string]> = [] + const out: Array<[string | Array, string | Redacted.Redacted]> = [] for (const [key, value] of entries) { if (Array.isArray(value)) { for (let i = 0; i < value.length; i++) { if (value[i] !== undefined) { - out.push([key, String(value[i])]) + out.push([key, coerce(value[i])]) } } - } else if (value !== null && typeof value === "object") { + } else if (value !== null && typeof value === "object" && !Redacted.isRedacted(value)) { const nested = fromInputNested(value as CoercibleRecord) for (const [k, v] of nested) { out.push([[key, ...(typeof k === "string" ? [k] : k)], v]) } } else if (value !== undefined) { - out.push([key, String(value)]) + out.push([key, coerce(value)]) } } return out } +const coerce = (value: Coercible): string | Redacted.Redacted => Redacted.isRedacted(value) ? value : String(value) + /** * Provides an order-sensitive `Equivalence` instance for `UrlParams`. * @@ -219,7 +237,7 @@ export const Equivalence: Equ.Equivalence = Equ.make((a, b ) const arrayEquivalence = Arr.makeEquivalence( - Tuple.makeEquivalence([Equ.strictEqual(), Equ.strictEqual()]) + Tuple.makeEquivalence([Equ.strictEqual(), Equal.asEquivalence()]) ) /** @@ -250,7 +268,7 @@ export const getAll: { (self: UrlParams, key: string): ReadonlyArray => Arr.reduce(self.params, [] as Array, (acc, [k, value]) => { if (k === key) { - acc.push(value) + acc.push(internal.unwrap(value)) } return acc }) @@ -279,7 +297,7 @@ export const getFirst: { 2, (self: UrlParams, key: string): Option.Option => Arr.findFirst(self.params, ([k]) => k === key).pipe( - Option.map(([, value]) => value) + Option.map(([, value]) => internal.unwrap(value)) ) ) @@ -304,7 +322,7 @@ export const getLast: { (self: UrlParams, key: string): Option.Option } = dual(2, (self: UrlParams, key: string): Option.Option => Arr.findLast(self.params, ([k]) => k === key).pipe( - Option.map(([, value]) => value) + Option.map(([, value]) => internal.unwrap(value)) )) /** @@ -326,7 +344,7 @@ export const set: { make( Arr.append( Arr.filter(self.params, ([k]) => k !== key), - [key, String(value)] + [key, coerce(value)] ) )) @@ -390,7 +408,7 @@ export const append: { } = dual(3, (self: UrlParams, key: string, value: Coercible): UrlParams => make(Arr.append( self.params, - [key, String(value)] + [key, coerce(value)] ))) /** @@ -424,11 +442,16 @@ export const remove: { /** * Serializes `UrlParams` to a URL query string without a leading question mark. * + * **Gotchas** + * + * The output contains the unwrapped values of `Redacted` parameters. + * * @stability unstable * @category converting * @since 4.0.0 */ -export const toString = (input: Input): string => new URLSearchParams(fromInput(input).params as any).toString() +export const toString = (input: Input): string => + new URLSearchParams(fromInput(input).params.map(([key, value]) => [key, internal.unwrap(value)])).toString() /** * Builds a `Record` containing all the key-value pairs in the given `UrlParams` @@ -455,7 +478,8 @@ export const toString = (input: Input): string => new URLSearchParams(fromInput( */ export const toRecord = (self: UrlParams): Record> => { const out: Record> = {} - for (const [k, value] of self.params) { + for (const [k, v] of self.params) { + const value = internal.unwrap(v) if (!Object.hasOwn(out, k)) { InternalRecord.assignProperty(out, k, value) } else { @@ -484,3 +508,159 @@ export const toRecord = (self: UrlParams): Record ReadonlyRecord> = toRecord as any + +/** + * Returns the parameter pairs with selected values wrapped in `Redacted`. + * + * **Details** + * + * Keeps `Redacted` values and wraps values whose names match `isRedactedName`, + * preserving order and repeated names. + * + * @stability unstable + * @category combinators + * @since 4.0.0 + */ +export const redact: { + ( + key: string | RegExp | ReadonlyArray + ): (self: UrlParams) => Array<[string, string | Redacted.Redacted]> + ( + self: UrlParams, + key: string | RegExp | ReadonlyArray + ): Array<[string, string | Redacted.Redacted]> +} = dual( + 2, + ( + self: UrlParams, + key: string | RegExp | ReadonlyArray + ): Array<[string, string | Redacted.Redacted]> => { + const patterns: ReadonlyArray = Array.isArray(key) ? key : [key as string | RegExp] + return self.params.map(([name, value]) => [ + name, + typeof value === "string" && isRedactedName(name, patterns) ? Redacted.make(value) : value + ]) + } +) + +/** + * Checks whether a parameter name matches one of the redaction patterns. + * + * **Details** + * + * String patterns match case-insensitively; regular expressions test the name. + * + * @stability unstable + * @category combinators + * @since 4.0.0 + */ +export const isRedactedName: (name: string, patterns: ReadonlyArray) => boolean = + Headers.isRedactedName + +/** + * Redacts URL userinfo and the values of matching query parameters. + * + * **Details** + * + * Replaces userinfo with `REDACTED:REDACTED` and query values with `REDACTED` + * when their decoded names match `isRedactedName`. Preserves all other text. + * When names are omitted, uses the current fiber's `CurrentRedactedNames`, + * falling back to the defaults outside a fiber. + * + * **Example** (Redacting a signed URL) + * + * ```ts import.meta.vitest + * import { UrlParams } from "effect/http" + * + * const url = UrlParams.redactUrl("https://bucket.test/file?Signature=abc&size=1") + * url // => "https://bucket.test/file?Signature=REDACTED&size=1" + * ``` + * + * @stability unstable + * @category combinators + * @since 4.0.0 + */ +export const redactUrl = ( + url: string, + redactedNames: ReadonlyArray = currentRedactedNames() +): string => { + if (url.includes("@")) url = redactUserinfo(url) + const queryStart = url.indexOf("?") + if (queryStart === -1 || redactedNames.length === 0) return url + const hashStart = url.indexOf("#") + if (hashStart !== -1 && hashStart < queryStart) return url + const queryEnd = hashStart === -1 ? url.length : hashStart + return url.slice(0, queryStart + 1) + redactQuery(url.slice(queryStart + 1, queryEnd), redactedNames) + + url.slice(queryEnd) +} + +const authorityStart = /^(?:(https?|ftp|wss?):[/\\]*|[a-z][a-z\d+.-]*:\/\/|[/\\]{2,})/i +const specialAuthorityEnd = /[/\\?#]/ +const authorityEnd = /[/?#]/ + +// Normalize only to locate userinfo; offsets preserve the original URL spelling. +const redactUserinfo = (url: string): string => { + let normalized = "" + const offsets: Array = [] + for (let i = 0; i < url.length; i++) { + const code = url.charCodeAt(i) + if (code === 9 || code === 10 || code === 13 || (normalized === "" && code <= 32)) continue + normalized += url[i] + offsets.push(i) + } + const authority = authorityStart.exec(normalized) + if (authority === null) return url + const start = authority[0].length + const special = authority[1] !== undefined || !authority[0].includes(":") + const rest = normalized.slice(start) + const end = rest.search(special ? specialAuthorityEnd : authorityEnd) + const userinfoEnd = (end === -1 ? rest : rest.slice(0, end)).lastIndexOf("@") + return userinfoEnd === -1 + ? url + : url.slice(0, offsets[start]) + "REDACTED:REDACTED" + url.slice(offsets[start + userinfoEnd]) +} + +const redactQuery = (query: string, redactedNames: ReadonlyArray): string => + query.split("&").map((part) => { + const index = part.indexOf("=") + return index !== -1 && isRedactedName(decodeQueryKey(part.slice(0, index)), redactedNames) + ? part.slice(0, index + 1) + "REDACTED" + : part + }).join("&") + +const decodeQueryKey = (key: string): string => { + if (!key.includes("%") && !key.includes("+")) return key + try { + return decodeURIComponent(key.replace(/\+/g, " ")) + } catch { + return key + } +} + +const currentRedactedNames = (): ReadonlyArray => + Context.get((globalThis as any)[Redactable.currentFiberTypeId]?.context ?? Context.empty(), CurrentRedactedNames) + +/** + * Query parameter names or patterns to redact in inspection, spans and errors. + * + * **Details** + * + * Defaults include `AWSAccessKeyId`, `Signature`, `sig` and `X-Goog-Signature`. + * A custom list replaces the defaults. Matching uses `isRedactedName`. + * Redaction leaves request URLs and parameter values unchanged. `Redacted` + * values are redacted regardless of this list. + * + * @stability unstable + * @category services + * @since 4.0.0 + */ +export const CurrentRedactedNames = Context.Reference< + ReadonlyArray +>("effect/http/UrlParams/CurrentRedactedNames", { + defaultValue: () => [ + "AWSAccessKeyId", + "Signature", + "sig", + "X-Goog-Signature" + ] +}) diff --git a/repos/effect/packages/effect/src/http/internal/compression.ts b/repos/effect/packages/effect/src/http/internal/compression.ts index d118a6faf1..0b1cef8bec 100644 --- a/repos/effect/packages/effect/src/http/internal/compression.ts +++ b/repos/effect/packages/effect/src/http/internal/compression.ts @@ -5,6 +5,9 @@ import type * as Headers from "../Headers.ts" import * as HttpBody from "../HttpBody.ts" import type { Compression, CompressionAlgorithm, CompressionOptions } from "../HttpPlatform.ts" import * as Response from "../HttpServerResponse.ts" +import { compressionTransformWeb, singleChunkStream } from "./compressionBody.ts" + +export { compressionTransformWeb } from "./compressionBody.ts" /** * @internal @@ -41,15 +44,6 @@ export const wrapCompression = (impl: Compression): Compression => ({ } }) -/** - * @internal - */ -export const compressionTransformWeb = - (format: string) => (stream: ReadableStream): ReadableStream => - stream.pipeThrough( - new CompressionStream(format as CompressionFormat) as unknown as ReadableWritablePair - ) - /** * @internal */ @@ -117,14 +111,6 @@ const streamBody = ( HttpBody.stream(Stream.fromReadableStream({ evaluate, onError: identity }), contentType) ) -const singleChunkStream = (data: Uint8Array): ReadableStream => - new ReadableStream({ - start(controller) { - controller.enqueue(data) - controller.close() - } - }) - const rawReadableStream = (raw: unknown): ReadableStream | undefined => { if (typeof ReadableStream !== "undefined" && raw instanceof ReadableStream) { return raw diff --git a/repos/effect/packages/effect/src/http/internal/compressionBody.ts b/repos/effect/packages/effect/src/http/internal/compressionBody.ts new file mode 100644 index 0000000000..800475644f --- /dev/null +++ b/repos/effect/packages/effect/src/http/internal/compressionBody.ts @@ -0,0 +1,56 @@ +import * as Effect from "../../Effect.ts" +import { identity } from "../../Function.ts" +import * as Stream from "../../Stream.ts" +import * as HttpBody from "../HttpBody.ts" +import type { CompressionAlgorithm, CompressionOptions } from "../HttpClientRequest.ts" + +/** + * @internal + */ +export const compressionTransformWeb = + (format: string) => (stream: ReadableStream): ReadableStream => + stream.pipeThrough( + new CompressionStream(format as CompressionFormat) as unknown as ReadableWritablePair + ) + +/** + * @internal + */ +export const singleChunkStream = (data: Uint8Array): ReadableStream => + new ReadableStream({ + start(controller) { + controller.enqueue(data) + controller.close() + } + }) + +/** + * @internal + */ +export const compressBody = ( + body: HttpBody.HttpBody, + algorithm: CompressionAlgorithm, + options?: CompressionOptions | undefined +): Effect.Effect => { + if (body._tag !== "Uint8Array" && body._tag !== "Stream") { + return Effect.succeed(body) + } + if (body.contentLength !== undefined && body.contentLength < (options?.minSize ?? 1024)) { + return Effect.succeed(body) + } + if (body._tag === "Uint8Array") { + return Effect.map( + Effect.promise(() => + new globalThis.Response(compressionTransformWeb(algorithm)(singleChunkStream(body.body))).arrayBuffer() + ), + (buffer) => HttpBody.uint8Array(new Uint8Array(buffer), body.contentType) + ) + } + return Effect.succeed(HttpBody.stream( + Stream.fromReadableStream({ + evaluate: () => compressionTransformWeb(algorithm)(Stream.toReadableStream(body.stream)), + onError: identity + }), + body.contentType + )) +} diff --git a/repos/effect/packages/effect/src/http/internal/decompression.ts b/repos/effect/packages/effect/src/http/internal/decompression.ts new file mode 100644 index 0000000000..4c47949f1e --- /dev/null +++ b/repos/effect/packages/effect/src/http/internal/decompression.ts @@ -0,0 +1,226 @@ +import * as ByteSize from "../../ByteSize.ts" +import * as Effect from "../../Effect.ts" +import * as Inspectable from "../../Inspectable.ts" +import type * as Option from "../../Option.ts" +import type { ReadonlyRecord } from "../../Record.ts" +import type * as Schema from "../../Schema.ts" +import type * as Socket from "../../socket/Socket.ts" +import * as Stream from "../../Stream.ts" +import * as Headers from "../Headers.ts" +import * as HttpIncomingMessage from "../HttpIncomingMessage.ts" +import type { HttpMethod } from "../HttpMethod.ts" +import { HttpServerError, RequestParseError } from "../HttpServerError.ts" +import * as HttpServerRequest from "../HttpServerRequest.ts" +import * as Multipart from "../Multipart.ts" +import * as UrlParams from "../UrlParams.ts" + +/** + * @internal + */ +export type Coding = "gzip" | "deflate" + +const defaultMaxDecompressedSize = ByteSize.mebibytes(10) + +/** + * Parses a `Content-Encoding` header into the codings to undo, in the order + * they were applied. `identity` members are dropped. Returns `undefined` if + * any member is unsupported. + * + * @internal + */ +export const parseContentEncoding = (header: string): ReadonlyArray | undefined => { + const codings: Array = [] + for (const member of header.split(",")) { + const coding = member.trim().toLowerCase() + if (coding === "" || coding === "identity") continue + if (coding !== "gzip" && coding !== "deflate") return undefined + codings.push(coding) + } + return codings +} + +/** + * Wraps a request so that its body accessors yield the decompressed body. + * Decompression happens lazily, when a body accessor is read. + * + * @internal + */ +export class DecompressedRequest extends Inspectable.Class implements HttpServerRequest.HttpServerRequest { + readonly [HttpServerRequest.TypeId]: typeof HttpServerRequest.TypeId + readonly [HttpIncomingMessage.TypeId]: typeof HttpIncomingMessage.TypeId + readonly inner: HttpServerRequest.HttpServerRequest + readonly codings: ReadonlyArray + readonly maxDecompressedSize: ByteSize.ByteSize | undefined + readonly headers: Headers.Headers + + constructor( + inner: HttpServerRequest.HttpServerRequest, + codings: ReadonlyArray, + maxDecompressedSize: ByteSize.ByteSize | undefined + ) { + super() + this[HttpServerRequest.TypeId] = HttpServerRequest.TypeId + this[HttpIncomingMessage.TypeId] = HttpIncomingMessage.TypeId + this.inner = inner + this.codings = codings + this.maxDecompressedSize = maxDecompressedSize + this.headers = Headers.removeMany(inner.headers, ["content-encoding", "content-length"]) + } + + toJSON(): unknown { + return HttpIncomingMessage.inspect(this, { + _id: "HttpServerRequest", + method: this.method, + url: this.originalUrl + }) + } + + modify( + options: { + readonly url?: string + readonly headers?: Headers.Headers + readonly remoteAddress?: Option.Option + } + ): HttpServerRequest.HttpServerRequest { + return new DecompressedRequest(this.inner.modify(options), this.codings, this.maxDecompressedSize) + } + + get source(): object { + return this.inner.source + } + + get url(): string { + return this.inner.url + } + + get originalUrl(): string { + return this.inner.originalUrl + } + + get method(): HttpMethod { + return this.inner.method + } + + get cookies(): ReadonlyRecord { + return this.inner.cookies + } + + get remoteAddress(): Option.Option { + return this.inner.remoteAddress + } + + get upgrade(): Effect.Effect { + return this.inner.upgrade + } + + // Platform accessors such as `NodeHttpServerRequest.toServerResponse` read + // the response handle from the request. + get response(): unknown { + return (this.inner as any).response + } + + get stream(): Stream.Stream { + return Stream.unwrap(Effect.withFiber((fiber) => { + const limit = this.maxDecompressedSize ?? fiber.getRef(HttpIncomingMessage.MaxBodySize) ?? + defaultMaxDecompressedSize + return Effect.succeed(Stream.fromReadableStream({ + evaluate: () => { + let body = Stream.toReadableStreamWith(this.inner.stream, fiber.context) + for (let i = this.codings.length - 1; i >= 0; i--) { + body = body.pipeThrough( + new DecompressionStream(this.codings[i]) as unknown as ReadableWritablePair + ) + } + let size = 0 + return body.pipeThrough( + new TransformStream({ + transform: (chunk, controller) => { + size += chunk.byteLength + if (size > limit) { + controller.error( + this.parseError(undefined, `Decompressed request body exceeds ${limit} bytes`, "BodyTooLarge") + ) + } else { + controller.enqueue(chunk) + } + } + }) + ) + }, + onError: (cause) => cause instanceof HttpServerError ? cause : this.parseError(cause) + })) + })) + } + + private bytesEffect: Effect.Effect | undefined + private get bytes(): Effect.Effect { + return this.bytesEffect ??= Effect.runSync(Effect.cached(Stream.mkUint8Array(this.stream))) + } + + get text(): Effect.Effect { + return Effect.map(this.bytes, (bytes) => textDecoder.decode(bytes)) + } + + get json(): Effect.Effect { + return Effect.flatMap(this.text, (text) => + Effect.try({ + try: () => text === "" ? null : JSON.parse(text) as Schema.Json, + catch: (cause) => this.parseError(cause) + })) + } + + get urlParamsBody(): Effect.Effect { + return Effect.flatMap(this.text, (text) => + Effect.try({ + try: () => UrlParams.fromInput(new URLSearchParams(text)), + catch: (cause) => this.parseError(cause) + })) + } + + get arrayBuffer(): Effect.Effect { + return Effect.map( + this.bytes, + (bytes) => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer + ) + } + + get multipartStream(): Stream.Stream { + return Stream.pipeThroughChannel( + Stream.mapError( + this.stream, + (cause) => Multipart.MultipartError.fromReason(multipartReasons.get(cause) ?? "InternalError", cause) + ), + Multipart.makeChannel(this.headers) + ) + } + + private multipartEffect: HttpServerRequest.HttpServerRequest["multipart"] | undefined + get multipart(): HttpServerRequest.HttpServerRequest["multipart"] { + return this.multipartEffect ??= Effect.runSync(Effect.cached(Multipart.toPersisted(this.multipartStream))) + } + + private parseError( + cause: unknown, + description?: string, + multipartReason: MultipartReason = "Parse" + ): HttpServerError { + const error = new HttpServerError({ + reason: new RequestParseError({ + request: this, + ...(description === undefined ? undefined : { description }), + ...(cause === undefined ? undefined : { cause }) + }) + }) + multipartReasons.set(error, multipartReason) + return error + } +} + +const textDecoder = new TextDecoder() + +type MultipartReason = "Parse" | "BodyTooLarge" + +// Failures caused by the client's data, keyed to the multipart reason they map +// to. Transport errors from the inner request are absent and map to +// `InternalError`. +const multipartReasons = new WeakMap() diff --git a/repos/effect/packages/effect/src/http/internal/tracing.ts b/repos/effect/packages/effect/src/http/internal/tracing.ts index 138794d878..4803a8c2c4 100644 --- a/repos/effect/packages/effect/src/http/internal/tracing.ts +++ b/repos/effect/packages/effect/src/http/internal/tracing.ts @@ -1,5 +1,6 @@ import type * as Tracer from "../../Tracer.ts" import * as Headers from "../Headers.ts" +import * as UrlParams from "../UrlParams.ts" const defaultPorts: Record = { "http:": 80, @@ -9,16 +10,17 @@ const defaultPorts: Record = { } /** - * Records the `url.*` and `server.*` attributes for a request URL. + * Records `url.*` and `server.*` attributes with URL redaction. * * @internal */ export const addUrlAttributes = ( span: Tracer.Span, - url: URL + url: URL, + redactedNames: ReadonlyArray ): void => { - const query = url.search.slice(1) - span.attribute("url.full", url.toString()) + const query = UrlParams.redactUrl(url.search, redactedNames).slice(1) + span.attribute("url.full", UrlParams.redactUrl(url.href, redactedNames)) span.attribute("url.path", url.pathname) if (query !== "") { span.attribute("url.query", query) @@ -34,6 +36,21 @@ export const addUrlAttributes = ( } } +/** + * Adds the names of `Redacted` parameters to the redacted names. + * + * @internal + */ +export const redactedNames = ( + urlParams: UrlParams.UrlParams, + redactedNames: ReadonlyArray +): ReadonlyArray => { + const keys = urlParams.params.filter(([, value]) => typeof value !== "string").map(([key]) => key) + return keys.length === 0 + ? redactedNames + : [...redactedNames, ...new URLSearchParams(keys.map((key) => [key, ""])).keys()] +} + /** @internal */ export const addHeaderAttributes = ( span: Tracer.Span, diff --git a/repos/effect/packages/effect/src/http/internal/urlParams.ts b/repos/effect/packages/effect/src/http/internal/urlParams.ts new file mode 100644 index 0000000000..9eaf19ee21 --- /dev/null +++ b/repos/effect/packages/effect/src/http/internal/urlParams.ts @@ -0,0 +1,5 @@ +import * as Redacted from "../../Redacted.ts" + +/** @internal */ +export const unwrap = (value: string | Redacted.Redacted): string => + typeof value === "string" ? value : Redacted.value(value) diff --git a/repos/effect/packages/effect/src/internal/core.ts b/repos/effect/packages/effect/src/internal/core.ts index 04d6eddc46..9fc2cbb691 100644 --- a/repos/effect/packages/effect/src/internal/core.ts +++ b/repos/effect/packages/effect/src/internal/core.ts @@ -321,6 +321,26 @@ export const causeCombine: { } ) +/** + * Appends the interrupts from `interrupts` that `self` does not contain yet. + * Unlike `causeCombine`, it never calls hash or equality methods, which can be + * user-defined, random, or throwing. + * + * @internal + */ +export const causeAddInterrupts = (self: Cause.Cause, interrupts: Cause.Cause): Cause.Cause => { + const reasons: Array> = self.reasons.slice() + for (const reason of interrupts.reasons) { + if ( + isInterruptReason(reason) && + !reasons.some((r) => isInterruptReason(r) && r.fiberId === reason.fiberId && r.annotations === reason.annotations) + ) { + reasons.push(reason) + } + } + return reasons.length === self.reasons.length ? self : new CauseImpl(reasons) +} + /** @internal */ export const causeEmpty: Cause.Cause = new CauseImpl([]) @@ -600,7 +620,7 @@ export const exitFailCause: (cause: Cause.Cause) => Exit.Exit = if (skippedHandler) { cause = causeFromReasons(cause.reasons.filter((reason) => reason._tag !== "Fail")) } - cause = causeCombine(cause, interruptedCause) + cause = causeAddInterrupts(cause, interruptedCause) annotated = true } return cont diff --git a/repos/effect/packages/effect/src/internal/dateTime.ts b/repos/effect/packages/effect/src/internal/dateTime.ts index 7ba567f987..48d9d4086b 100644 --- a/repos/effect/packages/effect/src/internal/dateTime.ts +++ b/repos/effect/packages/effect/src/internal/dateTime.ts @@ -934,10 +934,6 @@ export const subtractDuration: { mapEpochMillis(self, (millis) => millis - Duration.toMillis(Duration.fromInputUnsafe(duration))) ) -const addMillis = (date: Date, amount: number): void => { - date.setTime(date.getTime() + amount) -} - /** @internal */ export const add: { ( @@ -949,20 +945,26 @@ export const add: { ): A } = dual( 2, - (self: DateTime.DateTime, parts: Partial): DateTime.DateTime => - mutate(self, (date) => { + (self: DateTime.DateTime, parts: Partial): DateTime.DateTime => { + // time units move the instant, calendar units move the wall clock + const shifted = mutateUtc(self, (date) => { if (parts.milliseconds) { - addMillis(date, parts.milliseconds) + date.setTime(date.getTime() + parts.milliseconds) } if (parts.seconds) { - addMillis(date, parts.seconds * 1000) + date.setTime(date.getTime() + parts.seconds * 1000) } if (parts.minutes) { - addMillis(date, parts.minutes * 60 * 1000) + date.setTime(date.getTime() + parts.minutes * 60 * 1000) } if (parts.hours) { - addMillis(date, parts.hours * 60 * 60 * 1000) + date.setTime(date.getTime() + parts.hours * 60 * 60 * 1000) } + }) + if (!parts.days && !parts.weeks && !parts.months && !parts.years) { + return shifted + } + return mutate(shifted, (date) => { if (parts.days) { date.setUTCDate(date.getUTCDate() + parts.days) } @@ -989,6 +991,7 @@ export const add: { } } }) + } ) /** @internal */ diff --git a/repos/effect/packages/effect/src/internal/effect.ts b/repos/effect/packages/effect/src/internal/effect.ts index f6343b78b9..fc747b6484 100644 --- a/repos/effect/packages/effect/src/internal/effect.ts +++ b/repos/effect/packages/effect/src/internal/effect.ts @@ -49,6 +49,7 @@ import { internalCall } from "../Utils.ts" import type { Primitive } from "./core.ts" import { args, + causeAddInterrupts, causeAnnotate, causeCombine, causeEmpty, @@ -130,9 +131,9 @@ export class Interrupt extends ReasonBase<"Interrupt"> implements Cause.Interrup ) } [Hash.symbol](): number { - return Hash.combine(Hash.string(`${this._tag}:${this.fiberId}`))( - Hash.random(this.annotations) - ) + // Equality compares annotations by reference, so leave them out instead of + // hashing them randomly. + return Hash.string(`${this._tag}:${this.fiberId}`) } } @@ -566,7 +567,7 @@ export class FiberImpl implements Fiber.Fiber { cause = causeAnnotate(cause, annotations) } this._interruptedCause = this._interruptedCause - ? causeCombine(this._interruptedCause, cause) + ? causeAddInterrupts(this._interruptedCause, cause) : cause if (this.interruptible) { if (this._running) { @@ -1507,13 +1508,19 @@ const succeedPayload = function(this: { readonly payload: any }, _value: unknown // V8 includes the property name of a stored continuation in its stack trace. // Other engines need an explicit frame for the stack cleaner to cut at. const continuationMarksStack = (() => { + const limit = getStackTraceLimit() + if (limit === 0) return false const marker = "~effect/Effect/stackProbe" const probe = { [marker]: function stackProbe() { - return new Error().stack + return new Error() } } - return probe[marker]()?.includes("[as " + marker + "]") === true + // Only the probe frame is needed to detect the continuation property name. + setStackTraceLimit(1) + const error = probe[marker]() + setStackTraceLimit(limit) + return error.stack?.includes("[as " + marker + "]") === true })() const mapCont = function(this: { readonly payload: any }, value: any, fiber: FiberImpl) { const f = this.payload @@ -4453,7 +4460,7 @@ export const cachedInvalidateWithTTL: { const infiniteTTL = constant(Infinity) interface CachedRun { - fiber: FiberImpl | undefined + readonly fiber: FiberImpl awaiters: number } @@ -4470,17 +4477,19 @@ const makeCachedUnsafe = ( onExitUnsafe(fiber, () => { // Abandon the run once every caller has left, unless it already finished. if (--run.awaiters > 0 || current !== run) return - // Detach it first so new callers start a fresh run instead of joining - // one that is being interrupted. + // Detach before interruption so new callers start a fresh run. current = undefined - return fiberInterrupt(run.fiber!) + return fiberInterrupt(run.fiber) }) - return fiberJoin(run.fiber!) + return fiberJoin(run.fiber) } return [ withFiber((fiber) => { - if (current !== undefined) return join(fiber, current) + if (current !== undefined) { + // A run joining itself is not an awaiter, so external callers can still abandon it. + return fiber === current.fiber ? fiberJoin(current.fiber) : join(fiber, current) + } if ( exit !== undefined && (expiresAt === Infinity || fiber.getRef(ClockRef).currentTimeMillisUnsafe() < expiresAt) @@ -4489,10 +4498,11 @@ const makeCachedUnsafe = ( } exit = undefined const clock = fiber.getRef(ClockRef) - const run: CachedRun = { fiber: undefined, awaiters: 0 } + const run: CachedRun = { fiber: new FiberImpl(fiber.context), awaiters: 0 } current = run - run.fiber = forkUnsafe( - fiber, + // Join before evaluating, which may synchronously re-enter and interrupt other awaiters. + const joined = join(fiber, run) + run.fiber.evaluate( onExitPrimitive(self, (exit_) => { // An abandoned run must not overwrite or clear a replacement run. if (current !== run) return @@ -4502,11 +4512,9 @@ const makeCachedUnsafe = ( const duration = ttlMillis(exit_) expiresAt = duration === Infinity ? Infinity : clock.currentTimeMillisUnsafe() + duration exit = exit_ - }), - true, - true + }) as any ) - return run.fiber._exit ?? join(fiber, run) + return run.fiber._exit ?? joined }), sync(() => { exit = undefined diff --git a/repos/effect/packages/effect/src/internal/graphql.ts b/repos/effect/packages/effect/src/internal/graphql.ts new file mode 100644 index 0000000000..771ae16819 --- /dev/null +++ b/repos/effect/packages/effect/src/internal/graphql.ts @@ -0,0 +1,286 @@ +import { isReadonlyArrayNonEmpty, type NonEmptyReadonlyArray } from "../Array.ts" +import * as Context from "../Context.ts" +import * as Effect from "../Effect.ts" +import type * as GraphQL from "../graphql/GraphQL.ts" +import type { DocumentTemplate } from "../graphql/GraphQL.ts" +import type { PartialResult } from "../graphql/GraphQLClient.ts" +import { + DecodeError, + EncodeError, + GraphQLClientError, + type GraphQLError, + type Reason, + ResponseError +} from "../graphql/GraphQLClientError.ts" +import type { ExecutionResult, GraphQLProtocol, GraphQLRequest } from "../graphql/GraphQLProtocol.ts" +import * as Schema from "../Schema.ts" + +/** + * Builds a response error with raw data and transport metadata. + * + * @internal + */ +export const responseError = ( + result: ExecutionResult | undefined, + errors: NonEmptyReadonlyArray +): ResponseError => + new ResponseError({ + errors, + ...(result?.data === undefined ? {} : { data: result.data as Schema.Json }), + ...(result?.extensions === undefined ? {} : { extensions: result.extensions }), + ...(result?.status === undefined ? {} : { status: result.status }), + ...(result?.headers === undefined ? {} : { headers: result.headers }) + }) + +/** + * Raw responses for partial results, used by resolvers to preserve error + * metadata. Mock client results have no entry. + * + * @internal + */ +export const partialResponses = new WeakMap() + +/** + * Joins two printed pieces, adding a space only where two non-punctuators + * would otherwise touch. This is the generator printer's rule, so joining a + * generated template reproduces the printed document exactly. + */ +const concat = (left: string, right: string): string => + /[\w"-]$/.test(left) && /^[\w"-]/.test(right) ? `${left} ${right}` : left + right + +const concatAll = (pieces: ReadonlyArray): string => pieces.reduce(concat, "") + +/** Renders template parts, prefixing every name (the odd entries). */ +const renderParts = (parts: DocumentTemplate.Parts, prefix: string): string => + parts.map((part, i) => i % 2 === 1 ? prefix + part : part).join("") + +const isShared = (fragment: DocumentTemplate.Fragment): boolean => fragment.body.length <= 1 + +/** + * Renders the template once per prefix. The empty prefix renders it as + * written; any other prefix renames variables and per-slice fragments and + * aliases root fields to the prefixed response key. + */ +const render = ( + kind: string, + name: string, + template: DocumentTemplate, + prefixes: ReadonlyArray +): string => + concatAll([ + kind, + name, + template.variables.length === 0 ? "" : `(${ + concatAll( + prefixes.flatMap((prefix) => + template.variables.map((variable) => `$${prefix}${variable.name}:${variable.body}`) + ) + ) + })`, + template.directives === undefined ? "" : renderParts(template.directives, ""), + `{${ + concatAll(prefixes.flatMap((prefix) => + template.selections.map((selection) => { + const key = prefix === "" ? selection.alias : `${prefix}${selection.alias ?? selection.name}` + return `${key === undefined ? "" : `${key}:`}${selection.name ?? ""}${renderParts(selection.body, prefix)}` + }) + )) + }}`, + ...template.fragments.flatMap((fragment) => + (isShared(fragment) ? [""] : prefixes).map((prefix) => + concatAll(["fragment", prefix + fragment.name, renderParts(fragment.body, prefix)]) + ) + ) + ]) + +/** + * Joins a template into the document it was split from. + * + * @internal + */ +export const joinTemplate = (kind: string, name: string, template: DocumentTemplate): string => + render(kind, name, template, [""]) + +/** + * Why the template can't be sliced for any prefixes, if it can't: an operation + * directive references a variable, or a root selection is a fragment spread or + * inline fragment. + * + * @internal + */ +export const templateUnsliceableReason = (template: DocumentTemplate): string | undefined => { + if (template.directives !== undefined && template.directives.length > 1) { + return "its operation directives reference variables" + } + if (template.selections.some((selection) => selection.name === undefined)) { + return "it has a fragment spread or inline fragment at the root" + } + return undefined +} + +/** + * Renders one operation that repeats the template once per prefix. Each + * slice's variables, root response keys and per-slice fragments are renamed + * with its prefix; operation directives and shared fragments appear once. + * Prefixes must start a GraphQL name, and none may be a prefix of another. + * + * Throws rather than producing an invalid document when the template is + * unsliceable (see {@link templateUnsliceableReason}) or a renamed fragment + * would take a shared fragment's name. + * + * @internal + */ +export const renderSlices = ( + kind: string, + name: string, + template: DocumentTemplate, + prefixes: NonEmptyReadonlyArray +): string => { + const shared = new Set(template.fragments.filter(isShared).map((fragment) => fragment.name)) + const collision = template.fragments + .flatMap((fragment) => isShared(fragment) ? [] : prefixes.map((prefix) => prefix + fragment.name)) + .find((renamed) => shared.has(renamed)) + const reason = templateUnsliceableReason(template) ?? + (collision === undefined ? undefined : `fragment ${collision} would collide with a shared fragment`) + if (reason !== undefined) throw new Error(`Cannot render slices of operation ${name}: ${reason}`) + return render(kind, name, template, prefixes) +} + +/** + * Forces POST for alias batches to avoid GET URL length limits. + * + * @internal + */ +export const ForcePost = Context.Reference("effect/graphql/ForcePost", { defaultValue: () => false }) + +/** + * The URL a resolver batch was grouped by, and the protocol `url` that + * resolved it, so that transport sends the batch there without resolving it + * again. + * + * @internal + */ +export type ResolvedUrl = { + readonly resolve: GraphQLProtocol["Service"]["url"] + readonly url: string +} | undefined + +/** + * Carries a {@link ResolvedUrl} from a resolver batch to the transport. The + * client clears it while middleware run, so calls they make resolve their + * own URL. + * + * @internal + */ +export const ResolvedUrl = Context.Reference("effect/graphql/ResolvedUrl", { + defaultValue: () => undefined +}) + +/** + * JSON with object keys sorted, so equal JSON values give equal strings. + * + * @internal + */ +export const canonicalJson = (value: unknown): string => + JSON.stringify(value, (_, value) => + value !== null && typeof value === "object" && !Array.isArray(value) + ? Object.fromEntries(Object.keys(value).sort().map((key) => [key, value[key]])) + : value) + +/** + * Shared variable encoding, result decoding and client error mapping. + * + * @internal + */ +export const makeCodec = (operation: Op) => { + const fail = (reason: Reason) => new GraphQLClientError({ operation: operation.name, reason }) + const schemaFail = (make: (description: string) => Reason) => (error: Schema.SchemaError) => + Effect.fail(fail(make(error.message))) + const encode = Schema.encodeEffect(operation.variables) + const decode = Schema.decodeUnknownEffect(operation.result) + + const encodeVariables = ( + variables: GraphQL.Variables | undefined + ): Effect.Effect => + Effect.catch(encode(variables ?? {}), schemaFail((description) => new EncodeError({ description }))) + + const decodeData = ( + data: unknown + ): Effect.Effect, GraphQLClientError, Op["result"]["DecodingServices"]> => + Effect.catch(decode(data), schemaFail((description) => new DecodeError({ description }))) + + // GraphQL requires errors when data is null or missing. Check before decoding, + // since schemas such as Schema.Json accept null. + const failResponse = (result: ExecutionResult): Effect.Effect => { + const errors = result.errors ?? [] + return Effect.fail(fail( + isReadonlyArrayNonEmpty(errors) + ? responseError(result, errors) + : new DecodeError({ description: "data is null or missing without errors" }) + )) + } + + const decodeStrict = ( + result: ExecutionResult + ): Effect.Effect, GraphQLClientError, Op["result"]["DecodingServices"]> => + isReadonlyArrayNonEmpty(result.errors ?? []) || result.data === null || result.data === undefined + ? failResponse(result) + : decodeData(result.data) + + const decodePartial = ( + result: ExecutionResult + ): Effect.Effect>, GraphQLClientError, Op["result"]["DecodingServices"]> => { + if (result.data === null || result.data === undefined) return failResponse(result) + return Effect.map(decodeData(result.data), (data): PartialResult> => { + const partial = { data, errors: result.errors ?? [] } + partialResponses.set(partial, result) + return partial + }) + } + + return { fail, schemaFail, encodeVariables, failResponse, decodeStrict, decodePartial } as const +} + +/** + * Client batch runners (middleware and protocol, using POST) and URLs for + * resolver grouping. Mock and custom methods are not registered. + * + * @internal + */ +export const rawExecutors = new WeakMap Effect.Effect + readonly url: GraphQLProtocol["Service"]["url"] +}>() + +/** + * Splits a batched response, removing prefixes from root keys and error paths. + * Returns undefined if an error matches no slice or data is null or missing. + * + * @internal + */ +export const splitSlices = ( + result: ExecutionResult, + template: DocumentTemplate, + prefixes: ReadonlyArray +): ReadonlyArray | undefined => { + const sliceErrors = prefixes.map((): Array => []) + for (const error of result.errors ?? []) { + const key = error.path?.[0] + // No prefix is a prefix of another, so at most one matches. + const index = typeof key === "string" ? prefixes.findIndex((prefix) => key.startsWith(prefix)) : -1 + if (index === -1) return undefined + sliceErrors[index].push( + { ...error, path: [(key as string).slice(prefixes[index].length), ...error.path!.slice(1)] } as GraphQLError + ) + } + if (result.data === null || result.data === undefined) return undefined + const data = result.data as Record + return prefixes.map((prefix, i) => { + const sliceData: Record = {} + for (const selection of template.selections) { + const key = (selection.alias ?? selection.name)! + if (Object.hasOwn(data, prefix + key)) sliceData[key] = data[prefix + key] + } + return { ...result, data: sliceData, errors: sliceErrors[i] } + }) +} diff --git a/repos/effect/packages/effect/src/internal/graphqlHeaders.ts b/repos/effect/packages/effect/src/internal/graphqlHeaders.ts new file mode 100644 index 0000000000..49e1741a3b --- /dev/null +++ b/repos/effect/packages/effect/src/internal/graphqlHeaders.ts @@ -0,0 +1,11 @@ +import * as Headers from "../http/Headers.ts" +import * as Schema from "../Schema.ts" +import * as SchemaGetter from "../SchemaGetter.ts" + +// Keep headers branded at runtime while encoding only their string entries. +export const HeadersSchema = Schema.Record(Schema.String, Schema.String).pipe( + Schema.decodeTo(Schema.declare(Headers.isHeaders), { + decode: SchemaGetter.transform(Headers.fromInput), + encode: SchemaGetter.transform((headers) => ({ ...headers })) + }) +) diff --git a/repos/effect/packages/effect/src/internal/request.ts b/repos/effect/packages/effect/src/internal/request.ts index bd3874f227..61fe039ce2 100644 --- a/repos/effect/packages/effect/src/internal/request.ts +++ b/repos/effect/packages/effect/src/internal/request.ts @@ -4,6 +4,8 @@ import type { Effect } from "../Effect.ts" import type { Exit } from "../Exit.ts" import type { Fiber } from "../Fiber.ts" import { dual } from "../Function.ts" +import * as MutableHashMap from "../MutableHashMap.ts" +import * as Option from "../Option.ts" import type * as Request from "../Request.ts" import { makeEntry } from "../Request.ts" import type { RequestResolver } from "../RequestResolver.ts" @@ -67,10 +69,36 @@ export const requestUnsafe = ( return () => removeEntryUnsafe(options.resolver, entry) } +/** + * Pending batches of resolvers whose `batchKey` is in this set match keys with + * `Equal` instead of by reference. + * + * @internal + */ +export const equalBatchKeys = new WeakSet() + +interface BatchMap { + get(key: unknown): Batch | undefined + has(key: unknown): boolean + set(key: unknown, batch: Batch): void + delete(key: unknown): void +} + +const makeBatchMap = (resolver: RequestResolver): BatchMap => { + if (!equalBatchKeys.has(resolver.batchKey)) return new Map() + const map = MutableHashMap.empty() + return { + get: (key) => Option.getOrUndefined(MutableHashMap.get(map, key)), + has: (key) => MutableHashMap.has(map, key), + set: (key, batch) => MutableHashMap.set(map, key, batch), + delete: (key) => MutableHashMap.remove(map, key) + } +} + interface Batch { key: unknown resolver: RequestResolver - map: Map + map: BatchMap readonly entrySet: Set> readonly entries: Set> readonly delayEffect: Effect @@ -79,7 +107,7 @@ interface Batch { } const batchPool: Array = [] -const pendingBatches = new WeakMap, Map>() +const pendingBatches = new WeakMap, BatchMap>() const addEntry = ( resolver: RequestResolver, @@ -93,7 +121,7 @@ const addEntry = ( ) => { let batchMap = pendingBatches.get(resolver) if (!batchMap) { - batchMap = new Map() + batchMap = makeBatchMap(resolver) pendingBatches.set(resolver, batchMap) } let batch: Batch | undefined diff --git a/repos/effect/packages/effect/src/internal/schema/toCodeDocument.ts b/repos/effect/packages/effect/src/internal/schema/toCodeDocument.ts index f8673241b2..4546c08422 100644 --- a/repos/effect/packages/effect/src/internal/schema/toCodeDocument.ts +++ b/repos/effect/packages/effect/src/internal/schema/toCodeDocument.ts @@ -48,6 +48,8 @@ function renderEmittableAnnotation(input: unknown): string | undefined { return entries.length === 0 ? "{}" : `{ ${entries.join(", ")} }` } +const canonicalFiniteCheck = `Schema.isFinite().annotate({ "expected": "a finite number" })` + function renderAnnotations( annotations: Schema.Annotations.Annotations | undefined ): string | undefined { @@ -341,7 +343,11 @@ export function toCodeDocument( let runtime = base.runtime + runtimeAnnotate(representation.annotations) for (let index = 0; index < representation.checks.length; index++) { const check = representation.checks[index] - runtime += `.check(${compileCheck(check, [...path, "checks", index])})` + const compiledCheck = compileCheck(check, [...path, "checks", index]) + // Only collapse a bare number's leading canonical check. + runtime = runtime === "Schema.Number" && compiledCheck === canonicalFiniteCheck + ? "Schema.Finite" + : `${runtime}.check(${compiledCheck})` } return makeCode(runtime, base.Type) } diff --git a/repos/effect/packages/effect/src/internal/schema/toJsonSchemaDocument.ts b/repos/effect/packages/effect/src/internal/schema/toJsonSchemaDocument.ts index a87234b2e7..0d3889afc0 100644 --- a/repos/effect/packages/effect/src/internal/schema/toJsonSchemaDocument.ts +++ b/repos/effect/packages/effect/src/internal/schema/toJsonSchemaDocument.ts @@ -121,6 +121,37 @@ function hasNoCollisions(left: JsonSchema.JsonSchema, rightKeys: ReadonlyArray !Object.hasOwn(left, key)) } +// Every bound on one schema object applies, so a repeated bound reduces to its tighter value. +const lowerBoundKeywords = "|minimum|exclusiveMinimum|minLength|minItems|minProperties|" +const upperBoundKeywords = "|maximum|exclusiveMaximum|maxLength|maxItems|maxProperties|" + +// Tightens repeated bounds and drops an inclusive or exclusive bound implied by the other on the same side. Returns +// `undefined` for a `$ref` schema or a non-bound collision, so the caller falls back to `allOf`. +function mergeInlineCheck( + left: JsonSchema.JsonSchema, + right: JsonSchema.JsonSchema, + rightKeys: ReadonlyArray +): JsonSchema.JsonSchema | undefined { + if (typeof left.$ref === "string") return undefined + const out: JsonSchema.JsonSchema = { ...left, ...right } + for (const key of rightKeys) { + if (!Object.hasOwn(left, key)) continue + const a = left[key] + const b = right[key] + if (typeof a !== "number" || typeof b !== "number") return undefined + if (lowerBoundKeywords.includes(`|${key}|`)) out[key] = Math.max(a, b) + else if (upperBoundKeywords.includes(`|${key}|`)) out[key] = Math.min(a, b) + else return undefined + } + if (typeof out.minimum === "number" && typeof out.exclusiveMinimum === "number") { + delete out[out.exclusiveMinimum >= out.minimum ? "minimum" : "exclusiveMinimum"] + } + if (typeof out.maximum === "number" && typeof out.exclusiveMaximum === "number") { + delete out[out.exclusiveMaximum <= out.maximum ? "maximum" : "exclusiveMaximum"] + } + return out +} + // `format` and `content*` can affect validation, so they are not treated as pure annotations. const promotableAnnotationKeywords = "|title|description|default|examples|readOnly|writeOnly|" const inlineableAnnotatedCheckKeywords = inlineableCheckKeywords + promotableAnnotationKeywords @@ -149,8 +180,9 @@ function appendJsonSchema( : appendJsonSchema(base, extracted.schema, inlineCheck) } } - if (inlineCheck && hasNoCollisions(left, rightKeys)) { - return { ...left, ...right } + if (inlineCheck) { + const merged = mergeInlineCheck(left, right, rightKeys) + if (merged !== undefined) return merged } const members = Array.isArray(right.allOf) && rightKeys.length === 1 ? right.allOf : [right] if (Array.isArray(left.allOf)) { diff --git a/repos/effect/packages/effect/src/internal/version.ts b/repos/effect/packages/effect/src/internal/version.ts index dae214bd41..5ef0ed8fc9 100644 --- a/repos/effect/packages/effect/src/internal/version.ts +++ b/repos/effect/packages/effect/src/internal/version.ts @@ -1,2 +1,2 @@ /** @internal */ -export const version = "4.0.2" +export const version = "4.0.5" diff --git a/repos/effect/packages/effect/src/net/AddressResolver.ts b/repos/effect/packages/effect/src/net/AddressResolver.ts new file mode 100644 index 0000000000..9faef98a24 --- /dev/null +++ b/repos/effect/packages/effect/src/net/AddressResolver.ts @@ -0,0 +1,222 @@ +/** + * Resolves host and port endpoints to socket addresses. + * + * The `AddressResolver` service turns a `Host.HostPort` or `host:port` string + * into socket addresses. Numeric hosts are converted without a lookup. IPv6 + * literals with a named zone such as `fe80::1%eth0` get their scope ID from the host's + * network interfaces, and domain names are looked up with the `Dns` service. + * Runtime layers look up network interfaces; this module's layer requires + * only `Dns` and supports numeric zones only. + * + * @stability experimental + * @since 4.0.0 + */ +import * as Arr from "../Array.ts" +import * as Context from "../Context.ts" +import * as Effect from "../Effect.ts" +import * as Layer from "../Layer.ts" +import * as Option from "../Option.ts" +import * as Dns from "./Dns.ts" +import * as Host from "./Host.ts" +import * as NetAddress from "./NetAddress.ts" + +/** + * Service that resolves endpoints to internet and socket addresses. + * + * **Details** + * + * Every operation either returns at least one address or fails. Lookups fail + * with a `Dns.DnsError`, and hosts that cannot be converted, such as IPv6 + * literals with an unknown zone or numeric addresses outside the requested + * family, fail with a `NetAddress.NetAddressError`. + * + * @stability experimental + * @category services + * @since 4.0.0 + */ +export class AddressResolver extends Context.Service( + target: NetAddress.InetAddress | Host.HostPortInput, + options: ResolveOptions & { readonly family: F } + ): Effect.Effect< + Arr.NonEmptyReadonlyArray>>, + Dns.DnsError | NetAddress.NetAddressError + > + resolve( + target: NetAddress.InetAddress | Host.HostPortInput, + options?: ResolveOptions + ): Effect.Effect, Dns.DnsError | NetAddress.NetAddressError> + resolve( + target: NetAddress.SocketAddress | Host.HostPortInput, + options?: ResolveOptions + ): Effect.Effect, Dns.DnsError | NetAddress.NetAddressError> +}>()("effect/net/AddressResolver") {} + +/** + * Options for resolving an endpoint. Without a `family`, addresses of both + * families are returned. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface ResolveOptions { + readonly family?: NetAddress.IpFamily | undefined +} + +/** + * Looks up the IPv6 scope ID of a network interface by name. + * + * **Details** + * + * Returns `None` for interfaces that do not exist or have no IPv6 scope ID, and + * fails when the interfaces cannot be listed. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type ScopeIdLookup = (name: string) => Effect.Effect, NetAddress.NetAddressError> + +/** + * Options for creating an `AddressResolver`. + * + * **Details** + * + * `scopeId` is called whenever an IPv6 literal with a named zone such as + * `fe80::1%eth0` is resolved, so interfaces added or recreated while the + * program runs are found. Without it, only numeric zones such as `fe80::1%2` + * are supported. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface MakeOptions { + readonly scopeId?: ScopeIdLookup | undefined +} + +const inFamily = ( + address: NetAddress.InetAddress, + family: NetAddress.IpFamily | undefined +): Effect.Effect, NetAddress.NetAddressError> => + family === undefined || NetAddress.isFamily(address, family) + ? Effect.succeed(Arr.of(address)) + : Effect.fail(new NetAddress.NetAddressError({ input: address, message: `expected an ${family} address` })) + +/** + * Creates an `AddressResolver` that looks up domain names with a `Dns` + * service. + * + * **Example** (Resolving an endpoint with a static resolver) + * + * ```ts import.meta.vitest + * import { Effect, Result } from "effect" + * import { AddressResolver, Dns, NetAddress } from "effect/net" + * + * const dns = Result.getOrThrow(Dns.makeStatic({ + * hosts: { "db.internal": ["10.0.0.5"] } + * })) + * const resolver = AddressResolver.make(dns) + * + * const program = resolver.resolve("db.internal:5432").pipe( + * Effect.map((addresses) => addresses.map(NetAddress.formatInet)) + * ) + * + * await Effect.runPromise(program) // => ["10.0.0.5:5432"] + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const make = (dns: Dns.Dns["Service"], options?: MakeOptions): AddressResolver["Service"] => { + const scopeId = options?.scopeId + + const fromLiteral = ( + host: NetAddress.IpAddress | NetAddress.ScopedIpv6Literal, + port: number + ): Effect.Effect => { + if (NetAddress.isIpAddress(host)) return Effect.fromResult(NetAddress.inetAddress(host, port)) + const zone = host.slice(host.indexOf("%") + 1) + if (scopeId === undefined || /^\d+$/.test(zone)) { + return Effect.fromResult(NetAddress.inetAddressFromHostString(host, port)) + } + + return Effect.flatMap(scopeId(zone), (id) => + Effect.fromResult( + NetAddress.inetAddressFromHostString(host, port, Option.isSome(id) ? new Map([[zone, id.value]]) : undefined) + )) + } + + const resolve = ( + target: NetAddress.SocketAddress | Host.HostPortInput, + options?: ResolveOptions + ): Effect.Effect, Dns.DnsError | NetAddress.NetAddressError> => { + const family = options?.family + if (NetAddress.isUnixPathAddress(target)) return Effect.succeed(Arr.of(target)) + if (NetAddress.isInetAddress(target)) return inFamily(target, family) + if (!Host.isHostPort(target)) { + return Effect.flatMap( + Effect.fromResult(Host.hostPortFromInput(target)), + (endpoint) => resolve(endpoint, options) + ) + } + + const { host, port } = target + if (NetAddress.isIpAddress(host) || NetAddress.isScopedIpv6Literal(host)) { + return Effect.flatMap(fromLiteral(host, port), (address) => inFamily(address, family)) + } + + return Effect.flatMap(dns.lookup(host, { family }), (addresses) => { + // Lookups do not report the scope that a link-local IPv6 address needs. + const usable = addresses.filter((address) => + !(NetAddress.isIpv6Address(address) && NetAddress.isLinkLocal(address)) + ) + + return Arr.isReadonlyArrayNonEmpty(usable) + ? Effect.succeed(Arr.map(usable, (address) => NetAddress.inetAddressUnsafe(address, port))) + : Effect.fail( + new NetAddress.NetAddressError({ + input: host, + message: "only link-local IPv6 addresses were found, and lookups do not report their scope" + }) + ) + }) + } + + return AddressResolver.of({ resolve: resolve as AddressResolver["Service"]["resolve"] }) +} + +/** + * Creates a layer that provides an `AddressResolver` using the `Dns` service. + * + * @stability experimental + * @category layers + * @since 4.0.0 + */ +export const layer = (options?: MakeOptions): Layer.Layer => + Layer.effect(AddressResolver, Effect.map(Effect.service(Dns.Dns), (dns) => make(dns, options))) diff --git a/repos/effect/packages/effect/src/net/Dns.ts b/repos/effect/packages/effect/src/net/Dns.ts new file mode 100644 index 0000000000..ce89e323a5 --- /dev/null +++ b/repos/effect/packages/effect/src/net/Dns.ts @@ -0,0 +1,1035 @@ +/** + * Host name resolution, DNS queries, and DNS record values. + * + * `lookup` resolves a host name to the addresses used to connect to it, + * `resolve` queries DNS records of one type, and `reverse` looks up the names + * of an address. Runtime packages provide the `Dns` service from the host + * platform's resolver, whose `lookup` uses the operating system resolver + * (`getaddrinfo`) and therefore also reads the hosts file and other system + * sources, not only DNS. `AddressResolver` builds on `lookup` to resolve + * `host:port` endpoints. + * + * @stability experimental + * @since 4.0.0 + */ +import * as Arr from "../Array.ts" +import * as Context from "../Context.ts" +import * as Data from "../Data.ts" +import * as Duration from "../Duration.ts" +import * as Effect from "../Effect.ts" +import * as Hex from "../encoding/Hex.ts" +import * as Equal from "../Equal.ts" +import * as Hash from "../Hash.ts" +import * as Inspectable from "../Inspectable.ts" +import * as Layer from "../Layer.ts" +import { hasProperty } from "../Predicate.ts" +import type { ReadonlyRecord } from "../Record.ts" +import * as Result from "../Result.ts" +import * as Host from "./Host.ts" +import * as NetAddress from "./NetAddress.ts" + +const RecordTypeId = "~effect/net/Dns/DnsRecord" as const + +// ============================================================================= +// Records +// ============================================================================= + +interface RecordProto extends Equal.Equal, Hash.Hash, Inspectable.Inspectable { + readonly _tag: Tag + readonly [RecordTypeId]: typeof RecordTypeId +} + +/** + * An IPv4 address record. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface A extends RecordProto<"A"> { + readonly address: NetAddress.Ipv4Address +} + +/** + * An IPv6 address record. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Aaaa extends RecordProto<"AAAA"> { + readonly address: NetAddress.Ipv6Address +} + +/** + * A certification authority authorization record. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Caa extends RecordProto<"CAA"> { + readonly critical: boolean + readonly tag: string + readonly value: string +} + +/** + * A canonical name (alias) record. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Cname extends RecordProto<"CNAME"> { + readonly target: Host.DomainName +} + +/** + * A mail exchange record. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Mx extends RecordProto<"MX"> { + readonly exchange: Host.DomainName + readonly priority: number +} + +/** + * A naming authority pointer record. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Naptr extends RecordProto<"NAPTR"> { + readonly order: number + readonly preference: number + readonly flags: string + readonly service: string + readonly regexp: string + readonly replacement: Host.DomainName +} + +/** + * A name server record. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Ns extends RecordProto<"NS"> { + readonly host: Host.DomainName +} + +/** + * A pointer record, used for reverse lookups and DNS service discovery. + * + * **Details** + * + * `host` is a fully qualified name. It is a host name for reverse lookups, + * but may be a DNS-SD service instance name containing spaces or other + * characters, such as `EPSON TM-m30III._ipp._tcp.local.`. Labels are UTF-8 + * text, with dots and backslashes inside a label escaped as `\.` and `\\`. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Ptr extends RecordProto<"PTR"> { + readonly host: string +} + +/** + * A start of authority record. + * + * **Details** + * + * `admin` is the administrator mailbox written as a domain name, such as + * `hostmaster.example.com`. A dot inside the mailbox's local part is escaped, + * as in `john\.doe.example.com`, so `admin` is a plain string rather than a + * `Host.DomainName`. Labels are UTF-8 text, with dots and backslashes inside + * a label escaped as `\.` and `\\`. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Soa extends RecordProto<"SOA"> { + readonly primary: Host.DomainName + readonly admin: string + readonly serial: number + readonly refresh: Duration.Duration + readonly retry: Duration.Duration + readonly expire: Duration.Duration + readonly minimum: Duration.Duration +} + +/** + * A service location record. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Srv extends RecordProto<"SRV"> { + readonly target: Host.DomainName + readonly port: number + readonly priority: number + readonly weight: number +} + +/** + * A TLS authentication record (RFC 6698), which pins the certificate or public + * key that a TLS service presents, for DNS-Based Authentication of Named + * Entities (DANE). Records are published at a name made of the service's port + * and protocol, such as `_443._tcp.example.com`. + * + * **Details** + * + * `certUsage` says how the record constrains the certificate chain (0 to 3: + * PKIX-TA, PKIX-EE, DANE-TA, DANE-EE), `selector` whether `data` matches the + * full certificate (0) or its public key (1), and `matchingType` whether + * `data` holds the selected content itself (0) or its SHA-256 (1) or SHA-512 + * (2) digest. Unassigned values are kept as they are. + * + * **Gotchas** + * + * `data` is a copy of the bytes the record was made from, but typed arrays + * cannot be frozen; treat it as read-only, because changing it changes the + * record's equality. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Tlsa extends RecordProto<"TLSA"> { + readonly certUsage: number + readonly selector: number + readonly matchingType: number + readonly data: Uint8Array +} + +/** + * A text record. DNS stores text as one or more character strings, which are + * kept as separate chunks; protocols such as SPF read them joined, for example + * with `record.chunks.join("")`. + * + * **Details** + * + * Platform services decode each character string as UTF-8, replacing bytes + * that are not valid UTF-8 with U+FFFD, and `formatRecord` writes chunks back + * as UTF-8 bytes. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Txt extends RecordProto<"TXT"> { + readonly chunks: Arr.NonEmptyReadonlyArray +} + +/** + * Any supported DNS record value. + * + * **Details** + * + * Records are immutable values tagged by record type, compared and hashed by + * their fields. They hold the record data only: owner names and TTLs are not + * included because platform resolvers do not report them consistently. Names + * returned by platform services are fully qualified and end with a dot, so + * passing them back to the resolver does not apply search domains. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type DnsRecord = A | Aaaa | Caa | Cname | Mx | Naptr | Ns | Ptr | Soa | Srv | Tlsa | Txt + +/** + * The type of a DNS record, such as `"A"` or `"SRV"`. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type RecordType = + | "A" + | "AAAA" + | "CAA" + | "CNAME" + | "MX" + | "NAPTR" + | "NS" + | "PTR" + | "SOA" + | "SRV" + | "TLSA" + | "TXT" + +/** + * The record value for a record type. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type RecordFor = Extract + +/** + * The fields of a record type, without its `_tag`. + * + * @see {@link makeRecord} + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type RecordFields = T extends RecordType ? Omit, keyof RecordProto> + : never + +const isUint8 = (u: unknown): boolean => Number.isInteger(u) && (u as number) >= 0 && (u as number) <= 0xff +const isUint16 = (u: unknown): boolean => Number.isInteger(u) && (u as number) >= 0 && (u as number) <= 0xffff +const isUint32 = (u: unknown): boolean => Number.isInteger(u) && (u as number) >= 0 && (u as number) <= 0xffffffff +const isString = (u: unknown): u is string => typeof u === "string" +// SOA timers are 32-bit unsigned counts of seconds on the wire. +const isTimer = (u: unknown): boolean => + Duration.isDuration(u) && Duration.isFinite(u) && isUint32(Duration.toSeconds(u)) + +const recordFields: { + readonly [K in RecordType]: { readonly [F in keyof RecordFields]-?: (u: unknown) => boolean } +} = { + A: { + address: NetAddress.isIpv4Address + }, + AAAA: { + address: NetAddress.isIpv6Address + }, + CAA: { + critical: (u) => typeof u === "boolean", + tag: (u) => isString(u) && /^[a-z0-9]+$/i.test(u), + value: isString + }, + CNAME: { + target: Host.isDomainName + }, + MX: { + exchange: Host.isDomainName, + priority: isUint16 + }, + NAPTR: { + order: isUint16, + preference: isUint16, + flags: isString, + service: isString, + regexp: isString, + replacement: Host.isDomainName + }, + NS: { + host: Host.isDomainName + }, + PTR: { + host: (u) => isString(u) && u.length > 0 + }, + SOA: { + primary: Host.isDomainName, + admin: (u) => isString(u) && u.length > 0, + serial: isUint32, + refresh: isTimer, + retry: isTimer, + expire: isTimer, + minimum: isTimer + }, + SRV: { + target: Host.isDomainName, + port: isUint16, + priority: isUint16, + weight: isUint16 + }, + TLSA: { + certUsage: isUint8, + selector: isUint8, + matchingType: isUint8, + data: (u) => u instanceof Uint8Array && u.length > 0 + }, + TXT: { + chunks: (u) => Array.isArray(u) && u.length > 0 && u.every(isString) + } +} + +/** + * Every supported record type. + * + * @stability experimental + * @category constants + * @since 4.0.0 + */ +export const recordTypes: Arr.NonEmptyReadonlyArray = Object.keys(recordFields) as Array as any + +/** + * Returns `true` when a value is a supported record type. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isRecordType = (u: unknown): u is RecordType => recordTypes.includes(u as RecordType) + +/** + * Returns `true` when a value is a DNS record. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isDnsRecord = (u: unknown): u is DnsRecord => hasProperty(u, RecordTypeId) + +const RecordPrototype = { + ...Inspectable.BaseProto, + [RecordTypeId]: RecordTypeId, + [Equal.symbol](this: DnsRecord, that: Equal.Equal): boolean { + return isDnsRecord(that) && that._tag === this._tag && + Object.keys(this).every((key) => Equal.equals((this as any)[key], (that as any)[key])) + }, + [Hash.symbol](this: DnsRecord): number { + return Hash.structureKeys(this, Object.keys(this)) + }, + toString(this: DnsRecord): string { + return formatRecord(this) + }, + toJSON(this: DnsRecord): unknown { + return { ...this } + } +} + +/** + * Creates a checked DNS record of a record type from its fields. + * + * **Details** + * + * Every field is checked at runtime: addresses must belong to the record's + * address family, names must be normalized domain names, priorities, weights, + * and ports must be 16-bit unsigned integers, the SOA serial and timers must be + * 32-bit unsigned integers (the timers in whole seconds), the TLSA fields must + * be 8-bit unsigned integers with non-empty `data`, which is copied, TXT + * records need at least one chunk, and CAA property tags must be alphanumeric. + * Fields that do not belong to the record type are ignored. + * + * **Example** (Creating a service record) + * + * ```ts import.meta.vitest + * import { Result } from "effect" + * import { Dns, Host } from "effect/net" + * + * const record = Result.getOrThrow(Dns.makeRecord("SRV", { + * target: Host.domainNameFromStringUnsafe("db.internal"), + * port: 5432, + * priority: 10, + * weight: 5 + * })) + * Dns.formatRecord(record) // => "SRV 10 5 5432 db.internal" + * ``` + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const makeRecord = ( + type: T, + fields: RecordFields +): Result.Result, NetAddress.NetAddressError> => { + if (!isRecordType(type)) { + return Result.fail(new NetAddress.NetAddressError({ input: type, message: "unknown DNS record type" })) + } + const input: Record = typeof fields === "object" && fields !== null ? fields : {} + const self = Object.create(RecordPrototype) + self._tag = type + + for (const [key, check] of Object.entries<(u: unknown) => boolean>(recordFields[type])) { + const value = input[key] + if (!check(value)) { + return Result.fail(new NetAddress.NetAddressError({ input: fields, message: `invalid ${type} record ${key}` })) + } + self[key] = Array.isArray(value) + ? Object.freeze([...value]) + : value instanceof Uint8Array + ? new Uint8Array(value) + : value + } + + return Result.succeed(Object.freeze(self)) +} + +/** + * Creates a trusted DNS record of a record type from its fields, throwing on + * failure. + * + * @stability experimental + * @category unsafe + * @since 4.0.0 + */ +export const makeRecordUnsafe = (type: T, fields: RecordFields): RecordFor => + Result.getOrThrow(makeRecord(type, fields)) + +const encoder = new TextEncoder() + +const decimalEscape = (byte: number): string => `\\${byte.toString().padStart(3, "0")}` + +// Quotes a character string in DNS presentation format (RFC 1035, section 5.1): +// `"` and `\` are escaped, and bytes outside printable ASCII are written as `\DDD`. +const quote = (value: string): string => { + let out = "\"" + for (const byte of encoder.encode(value)) { + out += byte === 0x22 || byte === 0x5c + ? `\\${String.fromCharCode(byte)}` + : byte < 0x20 || byte > 0x7e + ? decimalEscape(byte) + : String.fromCharCode(byte) + } + return out + "\"" +} + +const nameSpecials = [0x22, 0x24, 0x28, 0x29, 0x3b, 0x40] + +// Writes a name held as text, such as `Ptr.host`, in DNS presentation format: +// its `\.` and `\\` escapes are kept, other special characters are escaped, and +// spaces and bytes outside printable ASCII are written as `\DDD`. +const formatName = (text: string): string => { + const bytes = encoder.encode(text) + let out = "" + for (let i = 0; i < bytes.length; i++) { + const byte = bytes[i] + if (byte === 0x5c) { + const next = bytes[i + 1] + if (next === 0x2e || next === 0x5c) { + out += `\\${String.fromCharCode(next)}` + i++ + } else { + out += "\\\\" + } + } else if (byte <= 0x20 || byte > 0x7e) { + out += decimalEscape(byte) + } else { + out += nameSpecials.includes(byte) ? `\\${String.fromCharCode(byte)}` : String.fromCharCode(byte) + } + } + return out +} + +/** + * Formats a record in DNS presentation format, prefixed by its type. + * + * @stability experimental + * @category encoding + * @since 4.0.0 + */ +export const formatRecord = (self: DnsRecord): string => { + switch (self._tag) { + case "A": + case "AAAA": + return `${self._tag} ${NetAddress.formatIp(self.address)}` + case "CAA": + return `CAA ${self.critical ? 128 : 0} ${self.tag} ${quote(self.value)}` + case "CNAME": + return `CNAME ${self.target}` + case "MX": + return `MX ${self.priority} ${self.exchange}` + case "NAPTR": + return `NAPTR ${self.order} ${self.preference} ${quote(self.flags)} ${quote(self.service)} ${ + quote(self.regexp) + } ${self.replacement}` + case "NS": + return `NS ${self.host}` + case "PTR": + return `PTR ${formatName(self.host)}` + case "SOA": + return `SOA ${self.primary} ${formatName(self.admin)} ${self.serial} ${Duration.toSeconds(self.refresh)} ${ + Duration.toSeconds(self.retry) + } ${Duration.toSeconds(self.expire)} ${Duration.toSeconds(self.minimum)}` + case "SRV": + return `SRV ${self.priority} ${self.weight} ${self.port} ${self.target}` + case "TLSA": + return `TLSA ${self.certUsage} ${self.selector} ${self.matchingType} ${Hex.encode(self.data).toUpperCase()}` + case "TXT": + return `TXT ${self.chunks.map(quote).join(" ")}` + } +} + +/** + * Returns the reverse-lookup domain name for an IP address, in `in-addr.arpa` + * for IPv4 or `ip6.arpa` for IPv6. + * + * **Example** (Building reverse-lookup names) + * + * ```ts import.meta.vitest + * import { Dns, NetAddress } from "effect/net" + * + * Dns.reverseName(NetAddress.ipFromStringUnsafe("192.0.2.1")) // => "1.2.0.192.in-addr.arpa" + * ``` + * + * @stability experimental + * @category converting + * @since 4.0.0 + */ +export const reverseName = (address: NetAddress.IpAddress): Host.DomainName => { + if (NetAddress.isIpv4Address(address)) { + return `${[...NetAddress.ipv4ToOctets(address)].reverse().join(".")}.in-addr.arpa` as Host.DomainName + } + const nibbles: Array = [] + for (const octet of NetAddress.ipv6ToOctets(address)) { + nibbles.push((octet >> 4).toString(16), (octet & 0xf).toString(16)) + } + return `${nibbles.reverse().join(".")}.ip6.arpa` as Host.DomainName +} + +// ============================================================================= +// Name servers +// ============================================================================= + +/** + * Parses the address of a name server: an IP address, which uses port 53, or + * an IP address and port. + * + * **Details** + * + * IPv6 addresses with a port are written in brackets, and IPv6 addresses + * without one are not. + * + * **Example** (Parsing name server addresses) + * + * ```ts import.meta.vitest + * import { Result } from "effect" + * import { Dns, NetAddress } from "effect/net" + * + * const format = (input: string) => Result.map(Dns.nameServerFromString(input), NetAddress.formatInet) + * + * format("192.0.2.53") // => Result.succeed("192.0.2.53:53") + * format("2001:db8::53") // => Result.succeed("[2001:db8::53]:53") + * format("[2001:db8::53]:5353") // => Result.succeed("[2001:db8::53]:5353") + * Result.isFailure(format("ns.example")) // => true + * ``` + * + * @stability experimental + * @category decoding + * @since 4.0.0 + */ +export const nameServerFromString = ( + input: string +): Result.Result => + NetAddress.inetAddressFromString( + input.startsWith("[") || /^[^:]*:\d+$/.test(input) ? input : input.includes(":") ? `[${input}]:53` : `${input}:53` + ) + +/** + * Converts a name server to the internet address to query. Strings are parsed + * like `nameServerFromString`, internet addresses and address parts with a + * port are converted like `NetAddress.inetAddressFromInput`, and other IP + * address inputs are converted like `NetAddress.ipFromInput` and use port 53. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const nameServerFromInput = ( + input: NetAddress.IpAddressInput | NetAddress.InetAddressInput +): Result.Result => + typeof input === "string" + ? nameServerFromString(input) + : "port" in input + ? NetAddress.inetAddressFromInput(input) + : Result.map(NetAddress.ipFromInput(input), (address) => NetAddress.inetAddressUnsafe(address, 53)) + +// ============================================================================= +// Errors +// ============================================================================= + +/** + * The normalized reason for a failed name resolution. + * + * **Details** + * + * - `NotFound`: no records were found, either because the name does not exist + * or because it has no records of the requested type or address family. + * Like Go's `DNSError.IsNotFound`, the two cases are not distinguished + * because not every platform resolver can tell them apart. + * - `Timeout`, `Temporary`, and `ServerFailure`: transient failures that may + * succeed when retried. + * - `Refused`: the server refused the query or could not be reached. + * - `BadName`: the name was rejected as malformed. + * - `InvalidResponse`: the platform returned data that could not be converted + * into record values. + * - `Unsupported`: the platform does not support the operation or record type. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export type DnsErrorReason = + | "NotFound" + | "Timeout" + | "Temporary" + | "Refused" + | "ServerFailure" + | "BadName" + | "InvalidResponse" + | "Unsupported" + | "Unknown" + +/** + * A failed lookup, query, or reverse lookup. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class DnsError extends Data.TaggedError("DnsError")<{ + readonly reason: DnsErrorReason + readonly method: "lookup" | "resolve" | "reverse" + readonly hostname: string + readonly recordType?: RecordType | undefined + readonly cause?: unknown +}> { + /** + * Formats the reason, operation, and name of the failed resolution. + * + * @since 4.0.0 + */ + override get message(): string { + return `${this.reason}: Dns.${this.method} (${this.hostname}${ + this.recordType === undefined ? "" : ` ${this.recordType}` + })` + } + + /** + * Whether the failure is transient and the operation may succeed if retried. + * + * @since 4.0.0 + */ + get isTemporary(): boolean { + return this.reason === "Timeout" || this.reason === "Temporary" || this.reason === "ServerFailure" + } +} + +// ============================================================================= +// Service +// ============================================================================= + +/** + * Options for address lookups. Without a `family`, addresses of both families + * are returned. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface LookupOptions { + readonly family?: NetAddress.IpFamily | undefined +} + +/** + * Service that resolves names to addresses, queries DNS records, and looks up + * the names of addresses. + * + * **Details** + * + * Every operation either returns at least one result or fails with a + * {@link DnsError}. + * + * @stability experimental + * @category services + * @since 4.0.0 + */ +export class Dns extends Context.Service( + host: Host.DomainNameInput, + options: { readonly family: F } + ): Effect.Effect>, DnsError> + lookup( + host: Host.DomainNameInput, + options?: LookupOptions + ): Effect.Effect, DnsError> + + /** + * Queries the DNS records of one type for a name. + * Names are parsed and normalized; invalid names fail with `BadName`. + */ + resolve( + name: Host.DomainNameInput, + type: T + ): Effect.Effect>, DnsError> + + /** + * Looks up the host names of an address with a reverse DNS query. + * + * **Details** + * + * Addresses given as strings are parsed; invalid addresses fail with + * `BadName`. Names that are not valid host names are skipped, including + * names with non-ASCII labels, which are not converted to their ASCII + * (`xn--`) form because that form is a different DNS name. When every + * returned name is skipped, the lookup fails with `InvalidResponse`. + */ + reverse(address: NetAddress.IpAddressInput): Effect.Effect, DnsError> +}>()("effect/net/Dns") {} + +const notFound = (method: DnsError["method"], hostname: string, recordType?: RecordType) => + Effect.fail(new DnsError({ reason: "NotFound", method, hostname, recordType })) + +const badName = (method: DnsError["method"], hostname: string, cause: unknown, recordType?: RecordType) => + Effect.fail(new DnsError({ reason: "BadName", method, hostname, recordType, cause })) + +const asciiName = /^[\w.-]+$/ + +/** + * Creates a `Dns` service from platform resolver operations. + * + * **Details** + * + * Lookup and query names are parsed and normalized, and reverse lookup + * addresses are parsed, before platform callbacks receive them. Invalid names + * and addresses fail with `BadName`. + * + * The constructor filters lookups by the requested address family, keeps only + * records of the requested type, removes duplicates, and turns empty results + * into `NotFound` failures. `reverse` receives the names of an address and + * keeps those that are valid host names, failing with `InvalidResponse` when + * there are names but none is valid. Without a `reverse` operation, the names + * are those of the PTR records at the address's `reverseName`, and failures of + * that query are reported as failures of `reverse`. + * + * Only `lookup` is required. Platforms that can resolve addresses but cannot + * query records, such as browsers, omit `resolve`; record queries, and reverse + * lookups without a `reverse` operation, then fail with `Unsupported`. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const make = (impl: { + readonly lookup: ( + host: Host.DomainName, + family: NetAddress.IpFamily | undefined + ) => Effect.Effect, DnsError> + readonly resolve?: + | ((name: Host.DomainName, type: RecordType) => Effect.Effect, DnsError>) + | undefined + readonly reverse?: + | ((address: NetAddress.IpAddress) => Effect.Effect, DnsError>) + | undefined +}): Dns["Service"] => { + const inFamily = (family: NetAddress.IpFamily | undefined) => (address: NetAddress.IpAddress): boolean => + family === undefined || NetAddress.isFamily(address, family) + + const resolveRecords = impl.resolve ?? + ((name: Host.DomainName, type: RecordType) => + Effect.fail(new DnsError({ reason: "Unsupported", method: "resolve", hostname: name, recordType: type }))) + + const reverseNames = impl.reverse ?? + ((address: NetAddress.IpAddress) => + resolveRecords(reverseName(address), "PTR").pipe( + Effect.map(Arr.flatMap((record) => record._tag === "PTR" ? [record.host] : [])), + Effect.mapError((error) => + new DnsError({ + reason: error.reason, + method: "reverse", + hostname: NetAddress.formatIp(address), + cause: error.cause + }) + ) + )) + + const lookup = (input: Host.DomainNameInput, options?: LookupOptions) => + Result.match(Host.domainNameFromInput(input), { + onFailure: (cause) => badName("lookup", input, cause), + onSuccess: (host) => + impl.lookup(host, options?.family).pipe( + Effect.flatMap((addresses) => + Arr.match(Arr.dedupe(addresses.filter(inFamily(options?.family))), { + onEmpty: () => notFound("lookup", host), + onNonEmpty: Effect.succeed + }) + ) + ) + }) + + return Dns.of({ + lookup, + resolve: (input: Host.DomainNameInput, type: T) => + Result.match(Host.domainNameFromInput(input), { + onFailure: (cause) => badName("resolve", input, cause, type), + onSuccess: (name) => + resolveRecords(name, type).pipe( + Effect.flatMap((records) => + Arr.match(Arr.dedupe(records.filter((record): record is RecordFor => record._tag === type)), { + onEmpty: () => notFound("resolve", name, type), + onNonEmpty: Effect.succeed + }) + ) + ) + }), + reverse: (input) => + Result.match(NetAddress.ipFromInput(input), { + onFailure: (cause) => badName("reverse", String(input), cause), + onSuccess: (address) => + reverseNames(address).pipe( + Effect.flatMap((names) => { + const hostname = NetAddress.formatIp(address) + // Only ASCII names: `domainNameFromString` would convert UTF-8 labels + // to a different, `xn--` name. + const hosts = Arr.dedupe( + Arr.filterMap(names.filter((name) => asciiName.test(name)), Host.domainNameFromString) + ) + return Arr.isReadonlyArrayNonEmpty(hosts) + ? Effect.succeed(hosts) + : names.length > 0 + ? Effect.fail(new DnsError({ reason: "InvalidResponse", method: "reverse", hostname })) + : notFound("reverse", hostname) + }) + ) + }) + }) +} + +// ============================================================================= +// Static resolver +// ============================================================================= + +/** + * Fixed names, addresses, and records for a static resolver. + * + * **Details** + * + * `hosts` works like a hosts file: its entries are used by `lookup` and + * `reverse`, but not by `resolve`. `records` holds DNS records by owner name and + * is used by all three operations. Names are normalized like + * `Host.domainNameFromString`, and a trailing dot is ignored. Addresses are + * converted like `NetAddress.ipFromInput`. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface StaticZone { + readonly hosts?: ReadonlyRecord> | undefined + readonly records?: ReadonlyRecord> | undefined +} + +const zoneKey = (name: string): string => name.length > 1 && name.endsWith(".") ? name.slice(0, -1) : name + +/** + * Creates a `Dns` service that answers from fixed data. + * + * **When to use** + * + * Use to test code that depends on `Dns`, or to provide fixed names on + * platforms without a resolver. + * + * **Details** + * + * Names without matching addresses or records fail with `NotFound`. CNAME + * records are returned by `CNAME` queries but are not followed. + * + * **Example** (Looking up a name with a static resolver) + * + * ```ts import.meta.vitest + * import { Effect, Result } from "effect" + * import { Dns, NetAddress } from "effect/net" + * + * const dns = Result.getOrThrow(Dns.makeStatic({ + * hosts: { "db.internal": ["10.0.0.5"] } + * })) + * + * const program = dns.lookup("db.internal").pipe( + * Effect.map((addresses) => addresses.map(NetAddress.formatIp)) + * ) + * + * await Effect.runPromise(program) // => ["10.0.0.5"] + * ``` + * + * @see {@link layerStatic} + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const makeStatic = (zone: StaticZone): Result.Result => { + const entries = new Map + readonly records: Array + }>() + const entry = (name: string) => + Result.map(Host.domainNameFromString(name), (domain) => { + const key = zoneKey(domain) + let current = entries.get(key) + if (current === undefined) { + current = { addresses: [], records: [] } + entries.set(key, current) + } + return current + }) + + for (const [name, addresses] of Object.entries(zone.hosts ?? {})) { + const result = entry(name) + if (Result.isFailure(result)) return Result.fail(result.failure) + for (const input of addresses) { + const address = NetAddress.ipFromInput(input) + if (Result.isFailure(address)) return Result.fail(address.failure) + result.success.addresses.push(address.success) + } + } + + for (const [name, records] of Object.entries(zone.records ?? {})) { + const result = entry(name) + if (Result.isFailure(result)) return Result.fail(result.failure) + for (const record of records) { + if (!isDnsRecord(record)) { + return Result.fail(new NetAddress.NetAddressError({ input: record, message: "expected a DNS record" })) + } + result.success.records.push(record) + } + } + + const recordsAt = (name: string): ReadonlyArray => entries.get(zoneKey(name))?.records ?? [] + + return Result.succeed(make({ + lookup: (host) => + Effect.sync(() => [ + ...(entries.get(zoneKey(host))?.addresses ?? []), + ...recordsAt(host).flatMap((record) => record._tag === "A" || record._tag === "AAAA" ? [record.address] : []) + ]), + resolve: (name) => Effect.sync(() => recordsAt(name)), + reverse: (address) => + Effect.sync(() => [ + ...[...entries].flatMap(([name, current]) => + current.addresses.some((candidate) => Equal.equals(candidate, address)) ? [name] : [] + ), + ...recordsAt(reverseName(address)).flatMap((record) => record._tag === "PTR" ? [record.host] : []) + ]) + })) +} + +/** + * Creates a layer that provides a `Dns` service answering from fixed data. + * + * @see {@link makeStatic} for the resolution rules + * @stability experimental + * @category layers + * @since 4.0.0 + */ +export const layerStatic = (zone: StaticZone): Layer.Layer => + Layer.effect(Dns, Effect.fromResult(makeStatic(zone))) diff --git a/repos/effect/packages/effect/src/net/Host.ts b/repos/effect/packages/effect/src/net/Host.ts new file mode 100644 index 0000000000..e54ac1c6c8 --- /dev/null +++ b/repos/effect/packages/effect/src/net/Host.ts @@ -0,0 +1,544 @@ +/** + * Host names and unresolved host and port endpoints. + * + * A `Host` is either a numeric IP address, an IPv6 literal with a zone such as + * `fe80::1%eth0`, or a DNS domain name. Numeric addresses are parsed directly + * into `NetAddress` values. The `AddressResolver` service turns a `HostPort` + * into internet addresses, looking up domain names with the `Dns` service. + * + * @stability experimental + * @since 4.0.0 + */ +import type * as Arr from "../Array.ts" +import type * as Brand from "../Brand.ts" +import * as Equal from "../Equal.ts" +import * as Hash from "../Hash.ts" +import * as Inspectable from "../Inspectable.ts" +import { hasProperty } from "../Predicate.ts" +import * as Result from "../Result.ts" +import * as NetAddress from "./NetAddress.ts" + +const TypeId = "~effect/net/Host" as const + +/** + * A syntactically valid DNS domain name in lowercase ASCII form. + * + * **Details** + * + * Names follow the rules used by Go's resolver: at most 253 characters, labels + * of 1 to 63 letters, digits, hyphens, or underscores, and no label starting or + * ending with a hyphen. Underscores are allowed so that service names such as + * `_http._tcp.example.com` are valid. The last label must not be numeric, which + * keeps IPv4-like strings out. A trailing dot marks a fully qualified name and + * is preserved. The root name `.` is valid. + * + * Internationalized names are stored in their ASCII (`xn--`) form. + * + * @see {@link domainNameFromString} for parsing and normalizing domain names + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type DomainName = Brand.Branded + +/** + * A domain name or a string to parse and normalize. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type DomainNameInput = DomainName | string + +/** + * A host as written in configuration or a URL authority: a numeric IP address, + * a scoped IPv6 literal, or a domain name. + * + * @see {@link hostFromString} for parsing hosts + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type Host = NetAddress.IpAddress | NetAddress.ScopedIpv6Literal | DomainName + +/** + * A host, or a string or any `IpAddressInput` to convert to one. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type HostInput = Host | NetAddress.IpAddressInput + +/** + * An unresolved host and port. + * + * @see {@link hostPortFromString} for parsing `host:port` strings + * @see {@link formatHostPort} for formatting `host:port` strings + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface HostPort extends Equal.Equal, Hash.Hash, Inspectable.Inspectable { + readonly _tag: "HostPort" + readonly host: Host + readonly port: number + readonly [TypeId]: typeof TypeId +} + +/** + * The host and port of an endpoint. + * + * @see {@link hostPort} for the checked constructor + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface HostPortParts { + readonly host: HostInput + readonly port: number +} + +/** + * An endpoint, or a `host:port` string or parts to convert to one. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type HostPortInput = HostPort | string | HostPortParts + +const hostError = (input: unknown, message: string): Result.Result => + Result.fail(new NetAddress.NetAddressError({ input, message })) + +const asciiNameCharacter = /^[a-z0-9_.-]$/i +const labelPattern = /^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/ +const numericLabel = /^(?:\d+|0x[0-9a-f]*)$/ + +const validateDomainName = (name: string): string | undefined => { + if (name === ".") return undefined + const relative = name.endsWith(".") ? name.slice(0, -1) : name + if (relative.length === 0) return "domain name must not be empty" + if (relative.length > 253) return "domain name must be at most 253 characters" + const labels = relative.split(".") + for (const label of labels) { + if (label.length === 0) return "domain name labels must not be empty" + if (label.length > 63) return "domain name labels must be at most 63 characters" + if (!labelPattern.test(label)) { + return "domain name labels must contain only letters, digits, hyphens, or underscores and must not start or end with a hyphen" + } + } + if (numericLabel.test(labels[labels.length - 1])) { + return "the last domain name label must not be numeric" + } + return undefined +} + +const toAsciiDomainName = (input: string): string | undefined => { + let ascii = true + for (const character of input) { + if (character.charCodeAt(0) < 0x80) { + if (!asciiNameCharacter.test(character)) return undefined + } else { + ascii = false + } + } + if (ascii) return input.toLowerCase() + try { + return new URL(`http://${input}`).hostname + } catch { + return undefined + } +} + +/** + * Returns `true` when a value is a valid, normalized domain name. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isDomainName = (u: unknown): u is DomainName => + typeof u === "string" && /^[a-z0-9_.-]+$/.test(u) && validateDomainName(u) === undefined + +/** + * Returns `true` when a value is a host. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isHost = (u: unknown): u is Host => + NetAddress.isIpAddress(u) || NetAddress.isScopedIpv6Literal(u) || isDomainName(u) + +/** + * Returns `true` when a value is an unresolved host and port. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isHostPort = (u: unknown): u is HostPort => hasProperty(u, TypeId) + +/** + * Parses and normalizes a domain name. + * + * **Details** + * + * ASCII names are lowercased. Names containing non-ASCII characters are + * converted to their ASCII (`xn--`) form using the WHATWG URL host parser, then + * validated with the same rules as ASCII names. A trailing dot is preserved. + * + * **Example** (Normalizing domain names) + * + * ```ts import.meta.vitest + * import { Result } from "effect" + * import { Host } from "effect/net" + * + * Result.getOrThrow(Host.domainNameFromString("Example.COM")) // => "example.com" + * Result.getOrThrow(Host.domainNameFromString("bücher.example")) // => "xn--bcher-kva.example" + * Result.isFailure(Host.domainNameFromString("1.2.3.4")) // => true + * ``` + * + * @stability experimental + * @category decoding + * @since 4.0.0 + */ +export const domainNameFromString = (input: string): Result.Result => { + const name = toAsciiDomainName(input) + if (name === undefined) return hostError(input, "invalid domain name") + const error = validateDomainName(name) + return error === undefined ? Result.succeed(name as DomainName) : hostError(input, error) +} + +/** + * Parses a trusted domain name, throwing on failure. + * + * @stability experimental + * @category unsafe + * @since 4.0.0 + */ +export const domainNameFromStringUnsafe = (input: string): DomainName => Result.getOrThrow(domainNameFromString(input)) + +/** + * Converts a `DomainNameInput` to a domain name, parsing and normalizing it like + * `domainNameFromString`. + * + * **Details** + * + * Domain names are strings, so every input is parsed. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const domainNameFromInput = (input: DomainNameInput): Result.Result => + domainNameFromString(input) + +/** + * Converts a trusted `DomainNameInput` to a domain name, throwing on failure. + * + * @stability experimental + * @category unsafe + * @since 4.0.0 + */ +export const domainNameFromInputUnsafe = (input: DomainNameInput): DomainName => + Result.getOrThrow(domainNameFromInput(input)) + +/** + * Parses a host as a numeric IP address, a scoped IPv6 literal, or a domain + * name, in that order. + * + * **Example** (Parsing hosts) + * + * ```ts import.meta.vitest + * import { Result } from "effect" + * import { Host, NetAddress } from "effect/net" + * + * NetAddress.isIpAddress(Result.getOrThrow(Host.hostFromString("10.0.0.5"))) // => true + * Result.getOrThrow(Host.hostFromString("fe80::1%eth0")) // => "fe80::1%eth0" + * Result.getOrThrow(Host.hostFromString("DB.internal")) // => "db.internal" + * ``` + * + * @stability experimental + * @category decoding + * @since 4.0.0 + */ +export const hostFromString = (input: string): Result.Result => { + if (input.includes("%")) return NetAddress.scopedIpv6LiteralFromString(input) + if (input.includes(":")) return NetAddress.ipFromString(input) + if (/^[\d.]+$/.test(input)) { + const address = NetAddress.ipFromString(input) + if (Result.isSuccess(address)) return address + } + return domainNameFromString(input) +} + +/** + * Parses a trusted host, throwing on failure. + * + * @stability experimental + * @category unsafe + * @since 4.0.0 + */ +export const hostFromStringUnsafe = (input: string): Host => Result.getOrThrow(hostFromString(input)) + +/** + * Converts a `HostInput` to a host, parsing strings like `hostFromString` and + * converting other inputs like `NetAddress.ipFromInput`. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const hostFromInput = (input: HostInput): Result.Result => + typeof input === "string" ? hostFromString(input) : NetAddress.ipFromInput(input) + +/** + * Converts a trusted `HostInput` to a host, throwing on failure. + * + * @stability experimental + * @category unsafe + * @since 4.0.0 + */ +export const hostFromInputUnsafe = (input: HostInput): Host => Result.getOrThrow(hostFromInput(input)) + +/** + * Formats a host without brackets. + * + * @stability experimental + * @category encoding + * @since 4.0.0 + */ +export const formatHost = (self: Host): string => typeof self === "string" ? self : NetAddress.formatIp(self) + +/** + * Returns `true` when a domain name ends with a dot, which excludes it from + * resolver search domains. + * + * @stability experimental + * @category predicates + * @since 4.0.0 + */ +export const isFullyQualified = (self: DomainName): boolean => self.endsWith(".") + +/** + * Appends the trailing dot to a domain name, unless it is already fully + * qualified. + * + * @stability experimental + * @category converting + * @since 4.0.0 + */ +export const toFullyQualified = (self: DomainName): DomainName => + isFullyQualified(self) ? self : `${self}.` as DomainName + +/** + * Removes the trailing dot of a fully qualified domain name, except from the + * root name `.`. + * + * @stability experimental + * @category converting + * @since 4.0.0 + */ +export const toRelative = (self: DomainName): DomainName => + self.length > 1 && isFullyQualified(self) ? self.slice(0, -1) as DomainName : self + +const HostPortProto = { + ...Inspectable.BaseProto, + _tag: "HostPort", + [TypeId]: TypeId, + [Equal.symbol](this: HostPort, that: Equal.Equal): boolean { + return isHostPort(that) && this.port === that.port && Equal.equals(this.host, that.host) + }, + [Hash.symbol](this: HostPort): number { + return Hash.combine(Hash.hash(this.host), Hash.number(this.port)) + }, + toString(this: HostPort): string { + return formatHostPort(this) + }, + toJSON(this: HostPort): string { + return this.toString() + } +} + +const isPort = (port: number): boolean => Number.isInteger(port) && port >= 0 && port <= 0xffff + +const makeHostPort = (host: Host, port: number): HostPort => { + const self = Object.create(HostPortProto) + self.host = host + self.port = port + return Object.freeze(self) +} + +/** + * Creates a checked host and port. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const hostPort = (host: Host, port: number): Result.Result => { + if (!isHost(host)) return hostError(host, "expected a host") + if (!isPort(port)) return hostError(port, "port must be an integer from 0 through 65535") + return Result.succeed(makeHostPort(host, port)) +} + +/** + * Creates a trusted host and port, throwing on failure. + * + * @stability experimental + * @category unsafe + * @since 4.0.0 + */ +export const hostPortUnsafe = (host: Host, port: number): HostPort => Result.getOrThrow(hostPort(host, port)) + +/** + * Parses `host:port`, `[IPv6]:port`, or `[IPv6%zone]:port`. + * + * **Details** + * + * IPv6 hosts must be bracketed and other hosts must not be. The port is + * required and must be an unpadded decimal integer from 0 through 65535. A + * zone follows the `%` directly; the percent-encoded `%25` separator of RFC + * 6874 URLs is not decoded, because `[fe80::1%253]:80` would be ambiguous. + * + * **Example** (Parsing host and port strings) + * + * ```ts import.meta.vitest + * import { Result } from "effect" + * import { Host } from "effect/net" + * + * const endpoint = Result.getOrThrow(Host.hostPortFromString("DB.internal:5432")) + * endpoint.host // => "db.internal" + * endpoint.port // => 5432 + * Host.formatHostPort(Result.getOrThrow(Host.hostPortFromString("[::1]:80"))) // => "[::1]:80" + * ``` + * + * @see {@link formatHostPort} for the inverse operation + * @stability experimental + * @category decoding + * @since 4.0.0 + */ +export const hostPortFromString = (input: string): Result.Result => { + let hostText: string + let portText: string + if (input.startsWith("[")) { + const end = input.indexOf("]") + if (end === -1 || input[end + 1] !== ":") return hostError(input, "expected [IPv6]:port") + hostText = input.slice(1, end) + portText = input.slice(end + 2) + if (!hostText.includes(":")) return hostError(input, "only IPv6 addresses use brackets") + } else { + const separator = input.lastIndexOf(":") + if (separator === -1) return hostError(input, "expected host:port") + if (input.indexOf(":") !== separator) return hostError(input, "IPv6 addresses must be bracketed") + hostText = input.slice(0, separator) + portText = input.slice(separator + 1) + } + if (!/^(0|[1-9]\d*)$/.test(portText)) { + return hostError(input, "port must be an unpadded decimal integer") + } + const port = Number(portText) + if (!isPort(port)) return hostError(input, "port must be an integer from 0 through 65535") + return Result.map(hostFromString(hostText), (host) => makeHostPort(host, port)) +} + +/** + * Parses a trusted `host:port` string, throwing on failure. + * + * @stability experimental + * @category unsafe + * @since 4.0.0 + */ +export const hostPortFromStringUnsafe = (input: string): HostPort => Result.getOrThrow(hostPortFromString(input)) + +/** + * Converts a `HostPortInput` to an endpoint, parsing strings like + * `hostPortFromString`, converting parts like `hostPort`, and returning + * endpoints unchanged. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const hostPortFromInput = (input: HostPortInput): Result.Result => { + if (isHostPort(input)) return Result.succeed(input) + if (typeof input === "string") return hostPortFromString(input) + if (!hasProperty(input, "host") || !hasProperty(input, "port")) { + return hostError(input, "expected a host and port") + } + const port = input.port + return Result.flatMap(hostFromInput(input.host), (host) => hostPort(host, port)) +} + +/** + * Converts a trusted `HostPortInput` to an endpoint, throwing on failure. + * + * @stability experimental + * @category unsafe + * @since 4.0.0 + */ +export const hostPortFromInputUnsafe = (input: HostPortInput): HostPort => Result.getOrThrow(hostPortFromInput(input)) + +/** + * Formats a host and port, bracketing IPv6 hosts. + * + * @see {@link hostPortFromString} for the inverse operation + * @stability experimental + * @category encoding + * @since 4.0.0 + */ +export const formatHostPort = (self: HostPort): string => { + const host = formatHost(self.host) + return host.includes(":") ? `[${host}]:${self.port}` : `${host}:${self.port}` +} + +/** + * The addresses of host names, as read from a hosts file. + * + * @see {@link parseHostsFile} for reading a hosts file + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type HostsTable = ReadonlyMap> + +/** + * Parses a hosts file into the addresses of each host name. Invalid entries + * are skipped. + * + * **Example** (Parsing a hosts file) + * + * ```ts import.meta.vitest + * import { Host, NetAddress } from "effect/net" + * + * const hosts = Host.parseHostsFile(` + * 127.0.0.1 localhost + * ::1 localhost ip6-localhost # loopback + * `) + * hosts.get(Host.domainNameFromStringUnsafe("localhost"))?.map(NetAddress.formatIp) // => ["127.0.0.1", "::1"] + * ``` + * + * @stability experimental + * @category decoding + * @since 4.0.0 + */ +export const parseHostsFile = (text: string): HostsTable => { + const hosts = new Map>() + for (const line of text.split(/\r?\n/)) { + const comment = line.indexOf("#") + const [first, ...names] = (comment === -1 ? line : line.slice(0, comment)).trim().split(/\s+/) + const address = NetAddress.ipFromString(first) + if (Result.isFailure(address)) continue + for (const name of names) { + const domain = domainNameFromString(name) + if (Result.isFailure(domain)) continue + const key = toRelative(domain.success) + const addresses = hosts.get(key) + if (addresses === undefined) hosts.set(key, [address.success]) + else if (!addresses.some((existing) => Equal.equals(existing, address.success))) addresses.push(address.success) + } + } + return hosts as unknown as HostsTable +} diff --git a/repos/effect/packages/effect/src/net/IpInterface.ts b/repos/effect/packages/effect/src/net/IpInterface.ts index d5e55e28de..a61f5633d6 100644 --- a/repos/effect/packages/effect/src/net/IpInterface.ts +++ b/repos/effect/packages/effect/src/net/IpInterface.ts @@ -6,7 +6,7 @@ */ import * as Equal from "../Equal.ts" import * as Hash from "../Hash.ts" -import { NodeInspectSymbol } from "../Inspectable.ts" +import * as Inspectable from "../Inspectable.ts" import { hasProperty } from "../Predicate.ts" import * as Result from "../Result.ts" import * as NetAddress from "./NetAddress.ts" @@ -23,13 +23,13 @@ const TypeId = "~effect/net/IpInterface" as const * @category models * @since 4.0.0 */ -export interface IpInterface extends Equal.Equal, Hash.Hash { +export interface IpInterface + extends Equal.Equal, Hash.Hash, Inspectable.Inspectable +{ readonly _tag: "IpInterface" readonly address: A readonly prefixLength: number readonly [TypeId]: typeof TypeId - toString(): string - toJSON(): string } /** @@ -50,6 +50,46 @@ export type Ipv4Interface = IpInterface */ export type Ipv6Interface = IpInterface +/** + * An address and prefix length, generic over the accepted address input. + * + * @see {@link make} for the checked constructor + * @stability unstable + * @category models + * @since 4.0.0 + */ +export interface IpInterfaceParts { + readonly address: A + readonly prefixLength: number +} + +/** + * An interface address, or a string or parts to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type IpInterfaceInput = IpInterface | string | IpInterfaceParts + +/** + * An IPv4 interface address, or a string or parts to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type Ipv4InterfaceInput = Ipv4Interface | string | IpInterfaceParts + +/** + * An IPv6 interface address, or a string or parts to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type Ipv6InterfaceInput = Ipv6Interface | string | IpInterfaceParts + /** * Companion types for parsing IP interface addresses. * @@ -100,6 +140,7 @@ export const isIpv6Interface = (u: unknown): u is Ipv6Interface => export const isIpInterface = (u: unknown): u is IpInterface => hasProperty(u, TypeId) const IpInterfaceProto = { + ...Inspectable.BaseProto, _tag: "IpInterface", [TypeId]: TypeId, [Equal.symbol](this: IpInterface, that: Equal.Equal): boolean { @@ -115,9 +156,6 @@ const IpInterfaceProto = { }, toJSON(this: IpInterface): string { return this.toString() - }, - [NodeInspectSymbol](this: IpInterface): string { - return this.toJSON() } } @@ -231,6 +269,78 @@ export const fromString = ( make(address, parts.prefixLength ?? NetAddress.width(address))) ) +const fromParts = ( + input: IpInterfaceParts, + toAddress: (input: I) => Result.Result +): Result.Result, NetAddress.NetAddressError> => + hasProperty(input, "address") && hasProperty(input, "prefixLength") + ? Result.flatMap(toAddress(input.address), (address) => make(address, input.prefixLength)) + : interfaceError(input, "expected an address and prefix length") + +/** + * Converts an `Ipv4InterfaceInput` to an IPv4 interface address, parsing + * strings like `ipv4FromString` with the given options, converting parts like + * `make`, and returning interface addresses unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const ipv4FromInput = ( + input: Ipv4InterfaceInput, + options?: IpInterface.ParseOptions +): Result.Result => { + if (isIpv4Interface(input)) return Result.succeed(input) + if (typeof input === "string") return ipv4FromString(input, options) + return fromParts(input, NetAddress.ipv4FromInput) +} + +/** + * Converts an `Ipv6InterfaceInput` to an IPv6 interface address, parsing + * strings like `ipv6FromString` with the given options, converting parts like + * `make`, and returning interface addresses unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const ipv6FromInput = ( + input: Ipv6InterfaceInput, + options?: IpInterface.ParseOptions +): Result.Result => { + if (isIpv6Interface(input)) return Result.succeed(input) + if (typeof input === "string") return ipv6FromString(input, options) + return fromParts(input, NetAddress.ipv6FromInput) +} + +/** + * Converts an `IpInterfaceInput` to an interface address, parsing strings like + * `fromString` with the given options, converting parts like `make`, and + * returning interface addresses unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const fromInput = ( + input: IpInterfaceInput, + options?: IpInterface.ParseOptions +): Result.Result => { + if (isIpInterface(input)) return Result.succeed(input) + if (typeof input === "string") return fromString(input, options) + return fromParts(input, NetAddress.ipFromInput) +} + +/** + * Converts a trusted `IpInterfaceInput` to an interface address, throwing on failure. + * + * @stability unstable + * @category unsafe + * @since 4.0.0 + */ +export const fromInputUnsafe = (input: IpInterfaceInput, options?: IpInterface.ParseOptions): IpInterface => + Result.getOrThrow(fromInput(input, options)) + /** * Creates a trusted interface address, throwing when its prefix length is invalid. * diff --git a/repos/effect/packages/effect/src/net/IpNetwork.ts b/repos/effect/packages/effect/src/net/IpNetwork.ts index 995546b210..7aea3066fd 100644 --- a/repos/effect/packages/effect/src/net/IpNetwork.ts +++ b/repos/effect/packages/effect/src/net/IpNetwork.ts @@ -7,7 +7,7 @@ import * as Equal from "../Equal.ts" import { dual } from "../Function.ts" import * as Hash from "../Hash.ts" -import { NodeInspectSymbol } from "../Inspectable.ts" +import * as Inspectable from "../Inspectable.ts" import { hasProperty } from "../Predicate.ts" import * as Result from "../Result.ts" import * as IpInterface from "./IpInterface.ts" @@ -25,13 +25,13 @@ const TypeId = "~effect/net/IpNetwork" as const * @category models * @since 4.0.0 */ -export interface IpNetwork extends Equal.Equal, Hash.Hash { +export interface IpNetwork + extends Equal.Equal, Hash.Hash, Inspectable.Inspectable +{ readonly _tag: "IpNetwork" readonly address: A readonly prefixLength: number readonly [TypeId]: typeof TypeId - toString(): string - toJSON(): string } /** @@ -52,6 +52,45 @@ export type Ipv4Network = IpNetwork */ export type Ipv6Network = IpNetwork +/** + * A network address and prefix length, generic over the accepted address + * input. The address must have no host bits set. + * + * @see {@link make} for the checked constructor + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type IpNetworkParts = + IpInterface.IpInterfaceParts + +/** + * An IP network prefix, or a CIDR string or parts to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type IpNetworkInput = IpNetwork | string | IpNetworkParts + +/** + * An IPv4 network prefix, or a CIDR string or parts to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type Ipv4NetworkInput = Ipv4Network | string | IpNetworkParts + +/** + * An IPv6 network prefix, or a CIDR string or parts to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type Ipv6NetworkInput = Ipv6Network | string | IpNetworkParts + /** * Returns `true` when a value is an IPv4 network prefix. * @@ -80,6 +119,7 @@ export const isIpv6Network = (u: unknown): u is Ipv6Network => isIpNetwork(u) && export const isIpNetwork = (u: unknown): u is IpNetwork => hasProperty(u, TypeId) const IpNetworkProto = { + ...Inspectable.BaseProto, _tag: "IpNetwork", [TypeId]: TypeId, [Equal.symbol](this: IpNetwork, that: Equal.Equal): boolean { @@ -93,9 +133,6 @@ const IpNetworkProto = { }, toJSON(this: IpNetwork): string { return this.toString() - }, - [NodeInspectSymbol](this: IpNetwork): string { - return this.toJSON() } } @@ -110,18 +147,14 @@ const fromInterfaceValue = (value: IpInterface.I const toBytes = (address: NetAddress.IpAddress): ReadonlyArray => NetAddress.isIpv4Address(address) ? NetAddress.ipv4ToOctets(address) : NetAddress.ipv6ToOctets(address) -type IpAddressFamily = A extends NetAddress.Ipv4Address ? NetAddress.Ipv4Address - : A extends NetAddress.Ipv6Address ? NetAddress.Ipv6Address - : never - const fromBytes = ( address: A, bytes: ReadonlyArray -): IpAddressFamily => { +): NetAddress.Family => { const array = new Uint8Array(bytes) return (NetAddress.isIpv4Address(address) ? NetAddress.ipv4FromBytesUnsafe(array) - : NetAddress.ipv6FromBytesUnsafe(array)) as IpAddressFamily + : NetAddress.ipv6FromBytesUnsafe(array)) as NetAddress.Family } const maskBytes = (bytes: ReadonlyArray, prefixLength: number): Array => { @@ -177,7 +210,7 @@ export const make = ( export const fromAddress = ( address: A, prefixLength: number -): Result.Result>, NetAddress.NetAddressError> => { +): Result.Result>, NetAddress.NetAddressError> => { return Result.map(IpInterface.make(address, prefixLength), (value) => { const masked = fromBytes(address, maskBytes(toBytes(address), prefixLength)) return fromInterfaceValue(IpInterface.makeUnsafe(masked, value.prefixLength)) @@ -194,7 +227,7 @@ export const fromAddress = ( */ export const fromInterface = ( self: IpInterface.IpInterface -): IpNetwork> => fromAddressUnsafe(self.address, self.prefixLength) +): IpNetwork> => fromAddressUnsafe(self.address, self.prefixLength) /** * Parses a strict IPv4 network prefix in CIDR notation. @@ -238,6 +271,72 @@ export const fromString = (input: string): Result.Result( + input: IpNetworkParts, + toAddress: (input: I) => Result.Result +): Result.Result, NetAddress.NetAddressError> => + hasProperty(input, "address") && hasProperty(input, "prefixLength") + ? Result.flatMap(toAddress(input.address), (address) => make(address, input.prefixLength)) + : Result.fail(new NetAddress.NetAddressError({ input, message: "expected an address and prefix length" })) + +/** + * Converts an `Ipv4NetworkInput` to an IPv4 network prefix, parsing strings + * like `ipv4FromString`, converting parts like `make`, and returning network + * prefixes unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const ipv4FromInput = (input: Ipv4NetworkInput): Result.Result => { + if (isIpv4Network(input)) return Result.succeed(input) + if (typeof input === "string") return ipv4FromString(input) + return fromParts(input, NetAddress.ipv4FromInput) +} + +/** + * Converts an `Ipv6NetworkInput` to an IPv6 network prefix, parsing strings + * like `ipv6FromString`, converting parts like `make`, and returning network + * prefixes unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const ipv6FromInput = (input: Ipv6NetworkInput): Result.Result => { + if (isIpv6Network(input)) return Result.succeed(input) + if (typeof input === "string") return ipv6FromString(input) + return fromParts(input, NetAddress.ipv6FromInput) +} + +/** + * Converts an `IpNetworkInput` to a network prefix, parsing strings like + * `fromString`, converting parts like `make`, and returning network prefixes + * unchanged. + * + * **Gotchas** + * + * Like `make`, an address with host bits set is rejected rather than truncated. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const fromInput = (input: IpNetworkInput): Result.Result => { + if (isIpNetwork(input)) return Result.succeed(input) + if (typeof input === "string") return fromString(input) + return fromParts(input, NetAddress.ipFromInput) +} + +/** + * Converts a trusted `IpNetworkInput` to a network prefix, throwing on failure. + * + * @stability unstable + * @category unsafe + * @since 4.0.0 + */ +export const fromInputUnsafe = (input: IpNetworkInput): IpNetwork => Result.getOrThrow(fromInput(input)) + /** * Creates a trusted network prefix, throwing when its address or prefix is invalid. * @@ -260,7 +359,7 @@ export const makeUnsafe = (address: A, prefixLen export const fromAddressUnsafe = ( address: A, prefixLength: number -): IpNetwork> => Result.getOrThrow(fromAddress(address, prefixLength)) +): IpNetwork> => Result.getOrThrow(fromAddress(address, prefixLength)) /** * Parses a trusted network prefix in CIDR notation, throwing on failure. @@ -298,7 +397,7 @@ export const firstAddress = (self: IpNetwork) * @category getters * @since 4.0.0 */ -export const lastAddress = (self: IpNetwork): IpAddressFamily => { +export const lastAddress = (self: IpNetwork): NetAddress.Family => { const bytes = toBytes(self.address) const networkMask = maskBytes(bytes.map(() => 0xff), self.prefixLength) return fromBytes(self.address, bytes.map((byte, index) => byte | (networkMask[index] ^ 0xff))) diff --git a/repos/effect/packages/effect/src/net/NetAddress.ts b/repos/effect/packages/effect/src/net/NetAddress.ts index 6867c3d5fb..3e840663b5 100644 --- a/repos/effect/packages/effect/src/net/NetAddress.ts +++ b/repos/effect/packages/effect/src/net/NetAddress.ts @@ -9,10 +9,11 @@ import * as Data from "../Data.ts" import * as Equal from "../Equal.ts" import { dual } from "../Function.ts" import * as Hash from "../Hash.ts" -import { NodeInspectSymbol } from "../Inspectable.ts" +import * as Inspectable from "../Inspectable.ts" import * as Option from "../Option.ts" -import { hasProperty } from "../Predicate.ts" +import { hasProperty, isTupleOf } from "../Predicate.ts" import * as Result from "../Result.ts" +import type { TupleOf } from "../Types.ts" const TypeId = "~effect/net/NetAddress" as const @@ -23,11 +24,9 @@ const TypeId = "~effect/net/NetAddress" as const * @category models * @since 4.0.0 */ -export interface Ipv4Address extends Equal.Equal, Hash.Hash { +export interface Ipv4Address extends Equal.Equal, Hash.Hash, Inspectable.Inspectable { readonly _tag: "Ipv4Address" readonly [TypeId]: typeof TypeId - toString(): string - toJSON(): string } /** @@ -37,11 +36,9 @@ export interface Ipv4Address extends Equal.Equal, Hash.Hash { * @category models * @since 4.0.0 */ -export interface Ipv6Address extends Equal.Equal, Hash.Hash { +export interface Ipv6Address extends Equal.Equal, Hash.Hash, Inspectable.Inspectable { readonly _tag: "Ipv6Address" readonly [TypeId]: typeof TypeId - toString(): string - toJSON(): string } /** @@ -53,6 +50,89 @@ export interface Ipv6Address extends Equal.Equal, Hash.Hash { */ export type IpAddress = Ipv4Address | Ipv6Address +/** + * The four octets of an IPv4 address in network order. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type Ipv4Octets = Readonly> + +/** + * The eight 16-bit segments of an IPv6 address in network order. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type Ipv6Segments = Readonly> + +/** + * The six octets of a MAC address in transmission order. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type MacAddressOctets = Readonly> + +/** + * An IPv4 address, or a string, four octets, or four network-order bytes to + * convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type Ipv4AddressInput = Ipv4Address | string | Ipv4Octets | Uint8Array + +/** + * An IPv6 address, or a string, eight 16-bit segments, or sixteen + * network-order bytes to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type Ipv6AddressInput = Ipv6Address | string | Ipv6Segments | Uint8Array + +/** + * An IP address, or any `Ipv4AddressInput` or `Ipv6AddressInput` to convert to + * one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type IpAddressInput = Ipv4AddressInput | Ipv6AddressInput + +/** + * An IPv6 literal with a zone, such as `fe80::1%eth0` or `fe80::1%3`. + * + * **Details** + * + * Named zones are kept as written because mapping an interface name to a + * numeric scope ID requires the operating system's interface table. Numeric + * zones must be unsigned 32-bit integers and are stored without leading zeros, + * and the address part is stored in canonical form. + * + * @see {@link scopedIpv6LiteralFromString} for parsing scoped IPv6 literals + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type ScopedIpv6Literal = Brand.Branded + +/** + * A scoped IPv6 literal or a string to parse as one. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type ScopedIpv6LiteralInput = ScopedIpv6Literal | string + /** * An immutable 48-bit IEEE 802 MAC address. * @@ -60,13 +140,20 @@ export type IpAddress = Ipv4Address | Ipv6Address * @category models * @since 4.0.0 */ -export interface MacAddress extends Equal.Equal, Hash.Hash { +export interface MacAddress extends Equal.Equal, Hash.Hash, Inspectable.Inspectable { readonly _tag: "MacAddress" readonly [TypeId]: typeof TypeId - toString(): string - toJSON(): string } +/** + * A MAC address, or a string or six octets to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type MacAddressInput = MacAddress | string | MacAddressOctets + const MulticastTypeId = "~effect/net/NetAddress/MulticastAddress" as const const UnicastTypeId = "~effect/net/NetAddress/UnicastAddress" as const const BroadcastTypeId = "~effect/net/NetAddress/BroadcastAddress" as const @@ -228,13 +315,11 @@ const getMacBytes = (self: MacAddress): Uint8Array => (self as any).bytes * @category models * @since 4.0.0 */ -export interface InetAddressV4 extends Equal.Equal, Hash.Hash { +export interface InetAddressV4 extends Equal.Equal, Hash.Hash, Inspectable.Inspectable { readonly _tag: "InetAddressV4" readonly address: Ipv4Address readonly port: number readonly [TypeId]: typeof TypeId - toString(): string - toJSON(): string } /** @@ -244,14 +329,12 @@ export interface InetAddressV4 extends Equal.Equal, Hash.Hash { * @category models * @since 4.0.0 */ -export interface InetAddressV6 extends Equal.Equal, Hash.Hash { +export interface InetAddressV6 extends Equal.Equal, Hash.Hash, Inspectable.Inspectable { readonly _tag: "InetAddressV6" readonly address: Ipv6Address readonly port: number readonly scopeId: number readonly [TypeId]: typeof TypeId - toString(): string - toJSON(): string } /** @@ -263,6 +346,32 @@ export interface InetAddressV6 extends Equal.Equal, Hash.Hash { */ export type InetAddress = InetAddressV4 | InetAddressV6 +/** + * The address, port, and optional IPv6 scope identifier of an internet address. + * + * **Details** + * + * A nonzero `scopeId` is only valid with an IPv6 address. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export interface InetAddressParts { + readonly address: A + readonly port: number + readonly scopeId?: number | undefined +} + +/** + * An internet address and port, or a string or parts to convert to one. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export type InetAddressInput = InetAddress | string | InetAddressParts + /** * An opaque Unix-domain filesystem socket path. * @@ -270,12 +379,10 @@ export type InetAddress = InetAddressV4 | InetAddressV6 * @category models * @since 4.0.0 */ -export interface UnixPathAddress extends Equal.Equal, Hash.Hash { +export interface UnixPathAddress extends Equal.Equal, Hash.Hash, Inspectable.Inspectable { readonly _tag: "UnixPathAddress" readonly path: string readonly [TypeId]: typeof TypeId - toString(): string - toJSON(): string } /** @@ -287,6 +394,17 @@ export interface UnixPathAddress extends Equal.Equal, Hash.Hash { */ export type SocketAddress = InetAddress | UnixPathAddress +/** + * The path of a Unix-domain socket address. + * + * @stability unstable + * @category models + * @since 4.0.0 + */ +export interface UnixPathAddressParts { + readonly path: string +} + /** * Companion types for constructing socket addresses. * @@ -300,18 +418,14 @@ export declare namespace SocketAddress { * * **Details** * - * String inputs must use `IPv4:port` or `[IPv6]:port` notation. Address - * properties must be numeric IPv4 or IPv6 literals. + * Accepts any `InetAddressInput` or a Unix path. String inputs must use + * `IPv4:port` or `[IPv6]:port` notation. * * @stability unstable * @category models * @since 4.0.0 */ - export type Input = - | SocketAddress - | string - | { readonly address: IpAddress | string; readonly port: number } - | { readonly path: string } + export type Input = SocketAddress | InetAddressInput | UnixPathAddressParts } /** @@ -338,6 +452,29 @@ export declare namespace SocketAddress { export type Family = A extends Ipv4Address | InetAddressV4 ? Ipv4Address : Ipv6Address +/** + * The name of an IP address family, spelled as in `os.networkInterfaces()` and + * socket address information on Node.js, Deno, and Bun. + * + * @see {@link familyOf} for reading the family of an address + * @see {@link FamilyAddress} for the address type of a family + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type IpFamily = "IPv4" | "IPv6" + +/** + * The IP address type for an IP address family name. `FamilyAddress` + * is `IpAddress`. + * + * @see {@link Family} for the inverse mapping from an address type + * @stability experimental + * @category models + * @since 4.0.0 + */ +export type FamilyAddress = F extends "IPv4" ? Ipv4Address : Ipv6Address + /** * The internet address type for an IP address family. * @@ -444,6 +581,49 @@ export const isIpAddress = (u: unknown): u is IpAddress => isIpv4Address(u) || i */ export const width = (address: IpAddress): 32 | 128 => isIpv4Address(address) ? 32 : 128 +/** + * Returns the family of an IP address or internet address. + * + * **Example** (Reading address families) + * + * ```ts import.meta.vitest + * import { NetAddress } from "effect/net" + * + * NetAddress.familyOf(NetAddress.ipv4Loopback) // => "IPv4" + * NetAddress.familyOf(NetAddress.inetAddressFromStringUnsafe("[::1]:80")) // => "IPv6" + * ``` + * + * @stability experimental + * @category getters + * @since 4.0.0 + */ +export const familyOf = (self: IpAddress | InetAddress): IpFamily => + isIpv4Address(self) || isInetAddressV4(self) ? "IPv4" : "IPv6" + +/** + * Returns `true` when an IP address or internet address belongs to a family, + * narrowing it to that family. + * + * @stability experimental + * @category predicates + * @since 4.0.0 + */ +export const isFamily: { + ( + family: "IPv4" + ): (self: A) => self is Extract + ( + family: "IPv6" + ): (self: A) => self is Extract + (family: IpFamily): (self: IpAddress | InetAddress) => boolean + (self: A, family: "IPv4"): self is Extract + (self: A, family: "IPv6"): self is Extract + (self: IpAddress | InetAddress, family: IpFamily): boolean +} = dual( + 2, + (self: A, family: IpFamily): self is A => familyOf(self) === family +) + /** * Returns `true` when a value is a MAC address. * @@ -499,6 +679,7 @@ export const isUnixPathAddress = (u: unknown): u is UnixPathAddress => isAddress export const isSocketAddress = (u: unknown): u is SocketAddress => isInetAddress(u) || isUnixPathAddress(u) const Ipv4Proto = { + ...Inspectable.BaseProto, _tag: "Ipv4Address", [TypeId]: TypeId, [Equal.symbol](this: Ipv4Address, that: Equal.Equal): boolean { @@ -512,13 +693,11 @@ const Ipv4Proto = { }, toJSON(this: Ipv4Address): string { return this.toString() - }, - [NodeInspectSymbol](this: Ipv4Address): string { - return this.toJSON() } } const Ipv6Proto = { + ...Inspectable.BaseProto, _tag: "Ipv6Address", [TypeId]: TypeId, [Equal.symbol](this: Ipv6Address, that: Equal.Equal): boolean { @@ -539,13 +718,11 @@ const Ipv6Proto = { }, toJSON(this: Ipv6Address): string { return this.toString() - }, - [NodeInspectSymbol](this: Ipv6Address): string { - return this.toJSON() } } const MacProto = { + ...Inspectable.BaseProto, _tag: "MacAddress", [TypeId]: TypeId, [Equal.symbol](this: MacAddress, that: Equal.Equal): boolean { @@ -559,9 +736,6 @@ const MacProto = { }, toJSON(this: MacAddress): string { return this.toString() - }, - [NodeInspectSymbol](this: MacAddress): string { - return this.toJSON() } } @@ -597,7 +771,7 @@ const packOctets = (a: number, b: number, c: number, d: number): number => ((a < const packBytes = (bytes: Uint8Array, offset: number): number => packOctets(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]) -const wordToOctets = (word: number): readonly [number, number, number, number] => [ +const wordToOctets = (word: number): Ipv4Octets => [ word >>> 24, (word >>> 16) & 0xff, (word >>> 8) & 0xff, @@ -646,6 +820,15 @@ export const ipv4Loopback: Ipv4Address = makeIpv4(0x7f000001) */ export const ipv6Loopback: Ipv6Address = makeIpv6(0, 0, 0, 1) +/** + * The loopback addresses `127.0.0.1` and `::1`. + * + * @stability unstable + * @category constants + * @since 4.0.0 + */ +export const loopbackAddresses: readonly [Ipv4Address, Ipv6Address] = [ipv4Loopback, ipv6Loopback] + /** * The unspecified IPv4 address `0.0.0.0`. * @@ -676,6 +859,15 @@ export const ipv4Broadcast: Ipv4Address = makeIpv4(0xffffffff) const addressError = (input: unknown, message: string): Result.Result => Result.fail(new NetAddressError({ input, message })) +// Checks by index because `every` skips holes in sparse arrays. +const allIntegersInRange = (values: ReadonlyArray, max: number): boolean => { + for (let i = 0; i < values.length; i++) { + const n = values[i] + if (!Number.isInteger(n) || n < 0 || n > max) return false + } + return true +} + /** * Creates an IPv4 address from four checked octets. * @@ -684,9 +876,9 @@ const addressError = (input: unknown, message: string): Result.Result => { - if (!octets.every((n) => Number.isInteger(n) && n >= 0 && n <= 255)) { + if (!allIntegersInRange(octets, 255)) { return addressError(octets, "octets must be integers from 0 through 255") } return Result.succeed(makeIpv4(packOctets(octets[0], octets[1], octets[2], octets[3]))) @@ -700,9 +892,9 @@ export const ipv4FromOctets = ( * @since 4.0.0 */ export const ipv6FromSegments = ( - segments: readonly [number, number, number, number, number, number, number, number] + segments: Ipv6Segments ): Result.Result => { - if (!segments.every((n) => Number.isInteger(n) && n >= 0 && n <= 0xffff)) { + if (!allIntegersInRange(segments, 0xffff)) { return addressError(segments, "segments must be integers from 0 through 65535") } return Result.succeed(makeIpv6( @@ -721,9 +913,9 @@ export const ipv6FromSegments = ( * @since 4.0.0 */ export const macAddressFromOctets = ( - octets: readonly [number, number, number, number, number, number] + octets: MacAddressOctets ): Result.Result => { - if (!octets.every((n) => Number.isInteger(n) && n >= 0 && n <= 255)) { + if (!allIntegersInRange(octets, 255)) { return addressError(octets, "octets must be integers from 0 through 255") } return Result.succeed(makeMac(new Uint8Array(octets))) @@ -752,6 +944,32 @@ export const macAddressFromString = (input: string): Result.Result Result.getOrThrow(macAddressFromString(input)) +/** + * Converts a `MacAddressInput` to a MAC address, parsing strings like + * `macAddressFromString`, checking octets like `macAddressFromOctets`, and + * returning MAC addresses unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const macAddressFromInput = (input: MacAddressInput): Result.Result => { + if (isMacAddress(input)) return Result.succeed(input) + if (typeof input === "string") return macAddressFromString(input) + if (Array.isArray(input) && isTupleOf(input, 6)) return macAddressFromOctets(input) + return addressError(input, "expected a MAC address, string, or 6 octets") +} + +/** + * Converts a trusted `MacAddressInput` to a MAC address, throwing on failure. + * + * @stability unstable + * @category unsafe + * @since 4.0.0 + */ +export const macAddressFromInputUnsafe = (input: MacAddressInput): MacAddress => + Result.getOrThrow(macAddressFromInput(input)) + /** * Parses a strict dotted-decimal IPv4 address. * @@ -875,6 +1093,141 @@ export const ipFromString = (input: string): Result.Result Result.getOrThrow(ipFromString(input)) +/** + * Converts an `IpAddressInput` to an IP address, returning IP addresses + * unchanged. + * + * **Details** + * + * Strings are parsed like `ipFromString`. Four octets or bytes make an IPv4 + * address, and eight segments or sixteen bytes make an IPv6 address. + * + * **Example** (Converting IP address inputs) + * + * ```ts import.meta.vitest + * import { Result } from "effect" + * import { NetAddress } from "effect/net" + * + * const address = Result.getOrThrow(NetAddress.ipFromInput("192.0.2.1")) + * NetAddress.formatIp(address) // => "192.0.2.1" + * Result.getOrThrow(NetAddress.ipFromInput(address)) === address // => true + * NetAddress.formatIp(Result.getOrThrow(NetAddress.ipFromInput([192, 0, 2, 1]))) // => "192.0.2.1" + * Result.isFailure(NetAddress.ipFromInput("example.com")) // => true + * ``` + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const ipFromInput = (input: IpAddressInput): Result.Result => { + if (isIpAddress(input)) return Result.succeed(input) + if (typeof input === "string") return ipFromString(input) + if (input instanceof Uint8Array && input.length === 4) return Result.succeed(ipv4FromBytesUnsafe(input)) + if (input instanceof Uint8Array && input.length === 16) return Result.succeed(ipv6FromBytesUnsafe(input)) + if (Array.isArray(input) && isTupleOf(input, 4)) return ipv4FromOctets(input) + if (Array.isArray(input) && isTupleOf(input, 8)) return ipv6FromSegments(input) + return addressError(input, "expected an IP address, string, 4 octets, 8 segments, or 4 or 16 bytes") +} + +/** + * Converts a trusted `IpAddressInput` to an IP address, throwing on failure. + * + * @stability unstable + * @category unsafe + * @since 4.0.0 + */ +export const ipFromInputUnsafe = (input: IpAddressInput): IpAddress => Result.getOrThrow(ipFromInput(input)) + +/** + * Converts an `Ipv4AddressInput` to an IPv4 address, parsing strings like + * `ipv4FromString`, checking octets like `ipv4FromOctets`, and returning IPv4 + * addresses unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const ipv4FromInput = (input: Ipv4AddressInput): Result.Result => { + if (isIpv4Address(input)) return Result.succeed(input) + if (typeof input === "string") return ipv4FromString(input) + if (input instanceof Uint8Array && input.length === 4) return Result.succeed(ipv4FromBytesUnsafe(input)) + if (Array.isArray(input) && isTupleOf(input, 4)) return ipv4FromOctets(input) + return addressError(input, "expected an IPv4 address, string, 4 octets, or 4 bytes") +} + +/** + * Converts an `Ipv6AddressInput` to an IPv6 address, parsing strings like + * `ipv6FromString`, checking segments like `ipv6FromSegments`, and returning + * IPv6 addresses unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const ipv6FromInput = (input: Ipv6AddressInput): Result.Result => { + if (isIpv6Address(input)) return Result.succeed(input) + if (typeof input === "string") return ipv6FromString(input) + if (input instanceof Uint8Array && input.length === 16) return Result.succeed(ipv6FromBytesUnsafe(input)) + if (Array.isArray(input) && isTupleOf(input, 8)) return ipv6FromSegments(input) + return addressError(input, "expected an IPv6 address, string, 8 segments, or 16 bytes") +} + +/** + * Returns `true` when a value is a canonical scoped IPv6 literal. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isScopedIpv6Literal = (u: unknown): u is ScopedIpv6Literal => { + if (typeof u !== "string" || !u.includes("%")) return false + const result = scopedIpv6LiteralFromString(u) + return Result.isSuccess(result) && result.success === u +} + +/** + * Parses an IPv6 literal with a numeric or named zone, such as `fe80::1%eth0`. + * + * @stability experimental + * @category decoding + * @since 4.0.0 + */ +export const scopedIpv6LiteralFromString = ( + input: string +): Result.Result => { + const separator = input.indexOf("%") + if (separator === -1) return addressError(input, "expected an IPv6 zone") + let zone = input.slice(separator + 1) + if (zone.length === 0 || /[%[\]/\s\p{Cc}]/u.test(zone)) { + return addressError(input, "invalid IPv6 scope identifier") + } + if (/^\d+$/.test(zone)) { + const scopeId = Number(zone) + if (scopeId > 0xffffffff) return addressError(input, "scope identifier must be an unsigned 32-bit integer") + zone = String(scopeId) + } + return Result.map( + ipv6FromString(input.slice(0, separator)), + (address) => `${formatIp(address)}%${zone}` as ScopedIpv6Literal + ) +} + +/** + * Converts a `ScopedIpv6LiteralInput` to a scoped IPv6 literal, parsing it + * like `scopedIpv6LiteralFromString`. + * + * **Details** + * + * Scoped IPv6 literals are strings, so every input is parsed. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const scopedIpv6LiteralFromInput = ( + input: ScopedIpv6LiteralInput +): Result.Result => scopedIpv6LiteralFromString(input) + /** * Returns the four numeric octets of an IPv4 address in a fresh tuple. * @@ -882,8 +1235,7 @@ export const ipFromStringUnsafe = (input: string): IpAddress => Result.getOrThro * @category getters * @since 4.0.0 */ -export const ipv4ToOctets = (self: Ipv4Address): readonly [number, number, number, number] => - wordToOctets(ipv4Value(self)) +export const ipv4ToOctets = (self: Ipv4Address): Ipv4Octets => wordToOctets(ipv4Value(self)) /** * Returns the eight numeric segments of an IPv6 address in a fresh tuple. @@ -892,9 +1244,7 @@ export const ipv4ToOctets = (self: Ipv4Address): readonly [number, number, numbe * @category getters * @since 4.0.0 */ -export const ipv6ToSegments = ( - self: Ipv6Address -): readonly [number, number, number, number, number, number, number, number] => { +export const ipv6ToSegments = (self: Ipv6Address): Ipv6Segments => { const { w0, w1, w2, w3 } = ipv6Words(self) return [w0 >>> 16, w0 & 0xffff, w1 >>> 16, w1 & 0xffff, w2 >>> 16, w2 & 0xffff, w3 >>> 16, w3 & 0xffff] } @@ -920,9 +1270,7 @@ export const ipv6ToOctets = ( * @category getters * @since 4.0.0 */ -export const macAddressToOctets = ( - self: MacAddress -): readonly [number, number, number, number, number, number] => { +export const macAddressToOctets = (self: MacAddress): MacAddressOctets => { const bytes = getMacBytes(self) return [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]] } @@ -1235,6 +1583,7 @@ export function toCanonical(self: IpAddress | InetAddress): IpAddress | InetAddr } const InetV4Proto = { + ...Inspectable.BaseProto, _tag: "InetAddressV4", [TypeId]: TypeId, [Equal.symbol](this: InetAddressV4, that: Equal.Equal): boolean { @@ -1248,13 +1597,11 @@ const InetV4Proto = { }, toJSON(this: InetAddressV4): string { return this.toString() - }, - [NodeInspectSymbol](this: InetAddressV4): string { - return this.toJSON() } } const InetV6Proto = { + ...Inspectable.BaseProto, _tag: "InetAddressV6", [TypeId]: TypeId, [Equal.symbol](this: InetAddressV6, that: Equal.Equal): boolean { @@ -1272,9 +1619,6 @@ const InetV6Proto = { }, toJSON(this: InetAddressV6): string { return this.toString() - }, - [NodeInspectSymbol](this: InetAddressV6): string { - return this.toJSON() } } @@ -1377,6 +1721,112 @@ export const inetAddressFromIpString = ( export const inetAddressFromIpStringUnsafe = (address: string, port: number): InetAddress => Result.getOrThrow(inetAddressFromIpString(address, port)) +/** + * Creates an internet address from a trusted native numeric host and port. + * Named IPv6 zones are resolved using the supplied interface-to-scope map. + * Use only for runtime-supplied socket addresses: this skips input validation, + * so malformed strings or ports may silently produce incorrect values. An + * unknown named IPv6 zone throws rather than losing its scope. + * + * @stability unstable + * @category unsafe + * @since 4.0.0 + */ +export const inetAddressFromNativeUnsafe = ( + host: string, + port: number, + scopeIds?: ReadonlyMap +): InetAddress => { + const zoneStart = host.indexOf("%") + const end = zoneStart === -1 ? host.length : zoneStart + if (host.indexOf(":") === -1) { + const self = Object.create(InetV4Proto) + self.address = makeIpv4(parseNativeIpv4(host, 0, end)) + self.port = port + return Object.freeze(self) + } + + let scopeId = 0 + if (zoneStart !== -1) { + const zone = host.slice(zoneStart + 1) + const resolved = numericZone.test(zone) ? Number(zone) : scopeIds?.get(zone) + if (resolved === undefined) throw new Error(`unknown IPv6 interface: ${zone}`) + scopeId = resolved + } + + let w0 = 0 + let w1 = 0 + let w2 = 0 + let w3 = 0 + let segment = 0 + let i = 0 + while (i < end) { + if (host.charCodeAt(i) === 58) { + // The rest of a compressed address is anchored at the last segment. + i += 2 + if (i === end) break + let remaining = 1 + for (let j = i; j < end; j++) { + if (host.charCodeAt(j) === 58) remaining++ + } + const dot = host.indexOf(".", i) + if (dot !== -1 && dot < end) remaining++ + segment = 8 - remaining + } + const start = i + let value = 0 + while (i < end) { + const ch = host.charCodeAt(i) + if (ch === 58 || ch === 46) break + value = (value << 4) | (ch <= 57 ? ch - 48 : (ch & 0x5f) - 55) + i++ + } + if (i < end && host.charCodeAt(i) === 46) { + w3 = parseNativeIpv4(host, start, end) + break + } + // even segments fill the high half of their 32-bit word + const shifted = value << ((1 - (segment & 1)) * 16) + switch (segment >>> 1) { + case 0: + w0 |= shifted + break + case 1: + w1 |= shifted + break + case 2: + w2 |= shifted + break + default: + w3 |= shifted + } + segment++ + if (i < end && host.charCodeAt(i + 1) !== 58) i++ + } + const self = Object.create(InetV6Proto) + self.address = makeIpv6(w0, w1, w2, w3) + self.port = port + self.scopeId = scopeId + return Object.freeze(self) +} + +const numericZone = /^\d+$/ + +const parseNativeIpv4 = (host: string, start: number, end: number): number => { + let value = 0 + let octet = 0 + for (let i = start; i < end; i++) { + const ch = host.charCodeAt(i) + if (ch === 46) { + value = (value << 8) | octet + octet = 0 + } else { + octet = octet * 10 + ch - 48 + } + } + return ((value << 8) | octet) >>> 0 +} + /** * Parses an unbracketed numeric host and port, resolving named IPv6 zones using * a supplied map of interface names to numeric scope IDs. @@ -1424,7 +1874,33 @@ export const inetAddressFromHostString = ( */ export interface NetworkInterfaceAddress { readonly family: string - readonly scopeid?: number | undefined + readonly scopeid?: number | null | undefined +} + +/** + * Returns the IPv6 scope ID of a network interface from its addresses. + * + * **Details** + * + * The first IPv6 address with a positive scope ID supplies the result. Accepts + * the addresses of one interface, such as `os.networkInterfaces()[name]` or the + * entries of `Deno.networkInterfaces()` with that name, without performing any + * operating-system lookup itself. + * + * @see {@link scopeIdsFromInterfaces} for mapping every interface at once + * @stability experimental + * @category converting + * @since 4.0.0 + */ +export const scopeIdFromInterface = ( + addresses: ReadonlyArray | undefined +): Option.Option => { + for (const address of addresses ?? []) { + if (address.family === "IPv6" && typeof address.scopeid === "number" && address.scopeid > 0) { + return Option.some(address.scopeid) + } + } + return Option.none() } /** @@ -1449,8 +1925,8 @@ export const scopeIdsFromInterfaces = ( ): Map => { const scopeIds = new Map() for (const [name, addresses] of interfaces) { - const address = addresses?.find((address) => address.family === "IPv6" && (address.scopeid ?? 0) > 0) - if (address?.scopeid !== undefined) scopeIds.set(name, address.scopeid) + const scopeId = scopeIdFromInterface(addresses) + if (Option.isSome(scopeId)) scopeIds.set(name, scopeId.value) } return scopeIds } @@ -1520,6 +1996,40 @@ export const inetAddressFromString = (input: string): Result.Result Result.getOrThrow(inetAddressFromString(input)) +/** + * Converts an `InetAddressInput` to an internet address, parsing strings like + * `inetAddressFromString`, converting parts like `inetAddressV4` and + * `inetAddressV6`, and returning internet addresses unchanged. + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const inetAddressFromInput = (input: InetAddressInput): Result.Result => { + if (isInetAddress(input)) return Result.succeed(input) + if (typeof input === "string") return inetAddressFromString(input) + if (!hasProperty(input, "address") || !hasProperty(input, "port")) { + return addressError(input, "expected an address and port") + } + const { port, scopeId } = input + return Result.flatMap(ipFromInput(input.address), (address): Result.Result => { + if (isIpv6Address(address)) return inetAddressV6(address, port, { scopeId }) + return (scopeId ?? 0) === 0 + ? inetAddressV4(address, port) + : addressError(input, "scopeId requires an IPv6 address") + }) +} + +/** + * Converts a trusted `InetAddressInput` to an internet address, throwing on failure. + * + * @stability unstable + * @category unsafe + * @since 4.0.0 + */ +export const inetAddressFromInputUnsafe = (input: InetAddressInput): InetAddress => + Result.getOrThrow(inetAddressFromInput(input)) + /** * Formats the numeric host of an internet address without brackets or a port, * preserving a nonzero IPv6 scope ID as a `%` suffix. @@ -1703,6 +2213,7 @@ export const formatUrlHostString = (host: string): string => host.includes(":") && !host.startsWith("[") ? `[${host}]` : host const UnixPathProto = { + ...Inspectable.BaseProto, _tag: "UnixPathAddress", [TypeId]: TypeId, [Equal.symbol](this: UnixPathAddress, that: Equal.Equal): boolean { @@ -1716,9 +2227,6 @@ const UnixPathProto = { }, toJSON(this: UnixPathAddress): string { return this.toString() - }, - [NodeInspectSymbol](this: UnixPathAddress): string { - return this.toJSON() } } @@ -1754,8 +2262,9 @@ export const formatUnixPath = (self: UnixPathAddress): string => `unix://${self. * * **Details** * - * Numeric IP strings are parsed without hostname resolution. Invalid IP - * literals, ports, and input shapes return a `NetAddressError`. + * Internet addresses are converted like `inetAddressFromInput`, without + * hostname resolution. Invalid IP literals, ports, and input shapes return a + * `NetAddressError`. * * @stability unstable * @category constructors @@ -1764,22 +2273,13 @@ export const formatUnixPath = (self: UnixPathAddress): string => `unix://${self. export const socketAddressFromInput = ( input: SocketAddress.Input ): Result.Result => { - if (isSocketAddress(input)) return Result.succeed(input) - if (typeof input === "string") return inetAddressFromString(input) + if (isUnixPathAddress(input)) return Result.succeed(input) if (hasProperty(input, "path")) { return typeof input.path === "string" ? Result.succeed(unixPathAddress(input.path)) : addressError(input, "path must be a string") } - if (!hasProperty(input, "address") || !hasProperty(input, "port")) { - return addressError(input, "expected an address and port or a Unix path") - } - const address = typeof input.address === "string" - ? ipFromString(input.address) - : isIpAddress(input.address) - ? Result.succeed(input.address) - : addressError(input, "address must be an IP address or numeric IP string") - return Result.flatMap(address, (address) => inetAddress(address, input.port as number)) + return inetAddressFromInput(input) } /** diff --git a/repos/effect/packages/effect/src/net/index.ts b/repos/effect/packages/effect/src/net/index.ts index c409bf51e7..22f56c45af 100644 --- a/repos/effect/packages/effect/src/net/index.ts +++ b/repos/effect/packages/effect/src/net/index.ts @@ -5,6 +5,24 @@ // @barrel: Auto-generated exports. Do not edit manually. +/** + * @stability experimental + * @since 4.0.0 + */ +export * as AddressResolver from "./AddressResolver.ts" + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as Dns from "./Dns.ts" + +/** + * @stability experimental + * @since 4.0.0 + */ +export * as Host from "./Host.ts" + /** * @stability unstable * @since 4.0.0 diff --git a/repos/effect/packages/effect/src/observability/Otlp.ts b/repos/effect/packages/effect/src/observability/Otlp.ts index 829e67aff1..6571fc8777 100644 --- a/repos/effect/packages/effect/src/observability/Otlp.ts +++ b/repos/effect/packages/effect/src/observability/Otlp.ts @@ -42,6 +42,11 @@ export const layer = (options: { readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly maxBatchSize?: number | undefined readonly tracerContext?: ((primitive: Tracer.EffectPrimitive, span: Tracer.AnySpan) => X) | undefined readonly loggerExportInterval?: Duration.Input | undefined @@ -59,6 +64,7 @@ export const layer = (options: { url: url("/v1/logs"), resource: options.resource, headers: options.headers, + compression: options.compression, exportInterval: options.loggerExportInterval, maxBatchSize: options.maxBatchSize, shutdownTimeout: options.shutdownTimeout, @@ -69,6 +75,7 @@ export const layer = (options: { url: url("/v1/metrics"), resource: options.resource, headers: options.headers, + compression: options.compression, exportInterval: options.metricsExportInterval, shutdownTimeout: options.shutdownTimeout, temporality: options.metricsTemporality @@ -77,6 +84,7 @@ export const layer = (options: { url: url("/v1/traces"), resource: options.resource, headers: options.headers, + compression: options.compression, exportInterval: options.tracerExportInterval, maxBatchSize: options.maxBatchSize, context: options.tracerContext, @@ -138,6 +146,11 @@ export const layerJson: (options: { readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly maxBatchSize?: number | undefined readonly tracerContext?: ((primitive: Tracer.EffectPrimitive, span: Tracer.AnySpan) => X) | undefined readonly loggerExportInterval?: Duration.Input | undefined @@ -165,6 +178,11 @@ export const layerProtobuf: (options: { readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly maxBatchSize?: number | undefined readonly tracerContext?: ((primitive: Tracer.EffectPrimitive, span: Tracer.AnySpan) => X) | undefined readonly loggerExportInterval?: Duration.Input | undefined diff --git a/repos/effect/packages/effect/src/observability/OtlpExporter.ts b/repos/effect/packages/effect/src/observability/OtlpExporter.ts index 5b749b8701..69d9a288b8 100644 --- a/repos/effect/packages/effect/src/observability/OtlpExporter.ts +++ b/repos/effect/packages/effect/src/observability/OtlpExporter.ts @@ -161,6 +161,12 @@ export const layerFlusher: Layer.Layer = Layer.sync(Flusher, () => { * after unhandled failures, and flushes during scope finalization up to * `shutdownTimeout`. * + * Optional gzip compression uses `HttpClientRequest.compressBody` before the + * retry loop, so retries reuse the compressed bytes. Bodies smaller than 1KB + * remain uncompressed. Compression requires runtime `CompressionStream` support; + * compression failures follow the same temporary-disable behavior as transport + * failures and do not fail flushing or shutdown. + * * @stability unstable * @category constructors * @since 4.0.0 @@ -169,6 +175,8 @@ export const make: ( options: { readonly url: string readonly headers: Headers.Input | undefined + /** Gzip uses the default 1KB minimum body size; smaller batches remain uncompressed. */ + readonly compression?: "gzip" | "none" | undefined readonly label: string readonly exportInterval: Duration.Input readonly maxBatchSize: number | "disabled" @@ -218,9 +226,12 @@ export const make: ( const items = buffer buffer = [] const [body, onSuccess] = options.body(items) - return client.execute( - HttpClientRequest.setBody(request, body) - ).pipe( + const batchRequest = HttpClientRequest.setBody(request, body) + // Compress before client.execute so transient retries reuse the encoded bytes. + const response = options.compression === "gzip" + ? HttpClientRequest.compressBody(batchRequest, "gzip").pipe(Effect.flatMap(client.execute)) + : client.execute(batchRequest) + return response.pipe( Effect.andThen(onSuccess), Effect.asVoid, Effect.withTracerEnabled(false) diff --git a/repos/effect/packages/effect/src/observability/OtlpLogger.ts b/repos/effect/packages/effect/src/observability/OtlpLogger.ts index fa5e97ce5f..0eff0f64e4 100644 --- a/repos/effect/packages/effect/src/observability/OtlpLogger.ts +++ b/repos/effect/packages/effect/src/observability/OtlpLogger.ts @@ -52,6 +52,11 @@ export const make: ( readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly exportInterval?: Duration.Input | undefined readonly maxBatchSize?: number | undefined readonly shutdownTimeout?: Duration.Input | undefined @@ -73,6 +78,7 @@ export const make: ( label: "OtlpLogger", url: options.url, headers: options.headers, + compression: options.compression, maxBatchSize: options.maxBatchSize ?? 1000, exportInterval: options.exportInterval ?? Duration.seconds(1), body: (data) => [ @@ -118,6 +124,11 @@ export const layer = (options: { readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly exportInterval?: Duration.Input | undefined readonly maxBatchSize?: number | undefined readonly shutdownTimeout?: Duration.Input | undefined @@ -131,6 +142,13 @@ export const layer = (options: { /** * Creates an OTLP logs layer from OpenTelemetry configuration. * + * **Details** + * + * Compression accepts "gzip" or "none". + * `OTEL_EXPORTER_OTLP_LOGS_COMPRESSION` takes precedence over + * `OTEL_EXPORTER_OTLP_COMPRESSION`, defaulting to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + * * @stability unstable * @category layers * @since 4.0.0 @@ -156,7 +174,17 @@ export const layerFromConfig = (options?: { return Exporter.layerFlusher } - const { baseTimeout, logsTimeout, exportTimeout, scheduleDelay, maxBatchSize } = yield* Config.all({ + const { + baseCompression, + compression, + baseTimeout, + logsTimeout, + exportTimeout, + scheduleDelay, + maxBatchSize + } = yield* Config.all({ + baseCompression: Config.option(Config.Literals(["gzip", "none"], "OTEL_EXPORTER_OTLP_COMPRESSION")), + compression: Config.option(Config.Literals(["gzip", "none"], "OTEL_EXPORTER_OTLP_LOGS_COMPRESSION")), baseTimeout: Config.option(Config.Int("OTEL_EXPORTER_OTLP_TIMEOUT")), logsTimeout: Config.option(Config.Int("OTEL_EXPORTER_OTLP_LOGS_TIMEOUT")), exportTimeout: Config.option(Config.Int("OTEL_BLRP_EXPORT_TIMEOUT")), @@ -173,6 +201,7 @@ export const layerFromConfig = (options?: { url: endpoint.toString(), resource: options?.resource, headers: options?.headers ?? (yield* OtlpEnv.headers("LOGS")), + compression: Option.getOrElse(Option.firstSomeOf([compression, baseCompression]), () => "none" as const), exportInterval: Option.getOrUndefined(exportInterval), maxBatchSize: Option.getOrUndefined(maxBatchSize), shutdownTimeout: Option.getOrUndefined(shutdownTimeout), @@ -232,7 +261,7 @@ const makeLogRecord = (options: Logger.Options, opts: { } if (options.fiber.cache.span) { - logRecord.traceId = options.fiber.cache.span.traceId + logRecord.traceId = options.fiber.cache.span.traceId.padStart(32, "0") logRecord.spanId = options.fiber.cache.span.spanId } diff --git a/repos/effect/packages/effect/src/observability/OtlpMetrics.ts b/repos/effect/packages/effect/src/observability/OtlpMetrics.ts index a9a8296ea9..9089fc9b49 100644 --- a/repos/effect/packages/effect/src/observability/OtlpMetrics.ts +++ b/repos/effect/packages/effect/src/observability/OtlpMetrics.ts @@ -12,7 +12,6 @@ * @stability unstable * @since 4.0.0 */ -import * as Arr from "../Array.ts" import { Clock } from "../Clock.ts" import * as Config from "../Config.ts" import * as Duration from "../Duration.ts" @@ -90,6 +89,11 @@ export const make: (options: { readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly exportInterval?: Duration.Input | undefined readonly shutdownTimeout?: Duration.Input | undefined readonly temporality?: AggregationTemporality | undefined @@ -228,27 +232,24 @@ export const make: (options: { break } case "Histogram": { - const size = state.state.buckets.length const currentBuckets = { - boundaries: Arr.allocate(size - 1) as Array, - counts: Arr.allocate(size) as Array + boundaries: [] as Array, + counts: [] as Array } - let idx = 0 let prev = 0 for (const [boundary, value] of state.state.buckets) { - if (idx < size - 1) { - currentBuckets.boundaries[idx] = boundary - } - currentBuckets.counts[idx] = value - prev + if (boundary === Number.POSITIVE_INFINITY) break + currentBuckets.boundaries.push(boundary) + currentBuckets.counts.push(value - prev) prev = value - idx++ } + // Derive overflow from the total count, whether or not boundaries include Infinity. + currentBuckets.counts.push(state.state.count - prev) let reportCount = state.state.count let reportSum = state.state.sum let reportBucketCounts = currentBuckets.counts - const reportMin = state.state.min - const reportMax = state.state.max + let reportExtrema = true if (isDelta) { const previousState = previousHistogramState.get(metricKey) @@ -258,17 +259,13 @@ export const make: (options: { reportBucketCounts = currentBuckets.counts.map((c, i) => Math.max(0, c - (previousState.bucketCounts[i] ?? 0)) ) - // For delta, min/max represent the interval's min/max - // We can't compute these from cumulative state, so we use current values - // Note: This is a limitation - true delta min/max would require tracking - // observations within each interval + // Cumulative extrema cannot describe a later delta interval. + reportExtrema = false } nextHistogramState.set(metricKey, { count: state.state.count, sum: state.state.sum, - bucketCounts: currentBuckets.counts.slice(), - min: state.state.min, - max: state.state.max + bucketCounts: currentBuckets.counts.slice() }) } @@ -277,8 +274,7 @@ export const make: (options: { startTimeUnixNano: intervalStartTime, timeUnixNano: nowTime, count: reportCount, - min: reportMin, - max: reportMax, + ...(reportExtrema ? { min: state.state.min, max: state.state.max } : undefined), sum: reportSum, bucketCounts: reportBucketCounts, explicitBounds: currentBuckets.boundaries @@ -396,6 +392,7 @@ export const make: (options: { label: "OtlpMetrics", url: options.url, headers: options.headers, + compression: options.compression, maxBatchSize: "disabled", exportEmpty: true, exportInterval: options.exportInterval ?? Duration.seconds(10), @@ -419,6 +416,11 @@ export const layer = (options: { readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly exportInterval?: Duration.Input | undefined readonly shutdownTimeout?: Duration.Input | undefined readonly temporality?: AggregationTemporality | undefined @@ -428,6 +430,13 @@ export const layer = (options: { /** * Creates an OTLP metrics layer from OpenTelemetry configuration. * + * **Details** + * + * Compression accepts "gzip" or "none". + * `OTEL_EXPORTER_OTLP_METRICS_COMPRESSION` takes precedence over + * `OTEL_EXPORTER_OTLP_COMPRESSION`, defaulting to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + * * @stability unstable * @category layers * @since 4.0.0 @@ -450,7 +459,17 @@ export const layerFromConfig = (options?: { return Exporter.layerFlusher } - const { baseTimeout, metricsTimeout, exportTimeout, exportInterval, temporalityPreference } = yield* Config.all({ + const { + baseCompression, + compression, + baseTimeout, + metricsTimeout, + exportTimeout, + exportInterval, + temporalityPreference + } = yield* Config.all({ + baseCompression: Config.option(Config.Literals(["gzip", "none"], "OTEL_EXPORTER_OTLP_COMPRESSION")), + compression: Config.option(Config.Literals(["gzip", "none"], "OTEL_EXPORTER_OTLP_METRICS_COMPRESSION")), baseTimeout: Config.option(Config.Int("OTEL_EXPORTER_OTLP_TIMEOUT")), metricsTimeout: Config.option(Config.Int("OTEL_EXPORTER_OTLP_METRICS_TIMEOUT")), exportTimeout: Config.option(Config.Int("OTEL_METRIC_EXPORT_TIMEOUT")), @@ -472,6 +491,7 @@ export const layerFromConfig = (options?: { url: endpoint.toString(), resource: options?.resource, headers: options?.headers ?? (yield* OtlpEnv.headers("METRICS")), + compression: Option.getOrElse(Option.firstSomeOf([compression, baseCompression]), () => "none" as const), exportInterval: Option.getOrUndefined(exportInterval), shutdownTimeout: Option.getOrUndefined(shutdownTimeout), temporality: Option.getOrUndefined(temporalityPreference) @@ -519,8 +539,6 @@ interface PreviousHistogramState { readonly count: number readonly sum: number readonly bucketCounts: Array - readonly min: number - readonly max: number } /** Properties of an InstrumentationScope. */ diff --git a/repos/effect/packages/effect/src/observability/OtlpTracer.ts b/repos/effect/packages/effect/src/observability/OtlpTracer.ts index c6f6197d58..2a6892222a 100644 --- a/repos/effect/packages/effect/src/observability/OtlpTracer.ts +++ b/repos/effect/packages/effect/src/observability/OtlpTracer.ts @@ -55,6 +55,11 @@ export const make: ( readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly exportInterval?: Duration.Input | undefined readonly maxBatchSize?: number | undefined readonly context?: ((primitive: Tracer.EffectPrimitive, span: Tracer.AnySpan) => X) | undefined @@ -76,6 +81,7 @@ export const make: ( label: "OtlpTracer", url: options.url, headers: options.headers, + compression: options.compression, exportInterval: options.exportInterval ?? Duration.seconds(5), maxBatchSize: options.maxBatchSize ?? 1000, body(spans) { @@ -128,6 +134,11 @@ export const layer: (options: { readonly attributes?: Record } | undefined readonly headers?: Headers.Input | undefined + /** + * Request compression. Defaults to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + */ + readonly compression?: "gzip" | "none" | undefined readonly exportInterval?: Duration.Input | undefined readonly maxBatchSize?: number | undefined readonly context?: ((primitive: Tracer.EffectPrimitive, span: Tracer.AnySpan) => X) | undefined @@ -141,6 +152,13 @@ export const layer: (options: { /** * Creates an OTLP traces layer from OpenTelemetry configuration. * + * **Details** + * + * Compression accepts "gzip" or "none". + * `OTEL_EXPORTER_OTLP_TRACES_COMPRESSION` takes precedence over + * `OTEL_EXPORTER_OTLP_COMPRESSION`, defaulting to "none". Gzip uses + * HttpClientRequest's default minimum body size of 1KB. + * * @stability unstable * @category layers * @since 4.0.0 @@ -165,7 +183,17 @@ export const layerFromConfig = (options?: { return Exporter.layerFlusher } - const { baseTimeout, tracesTimeout, exportTimeout, scheduleDelay, maxBatchSize } = yield* Config.all({ + const { + baseCompression, + compression, + baseTimeout, + tracesTimeout, + exportTimeout, + scheduleDelay, + maxBatchSize + } = yield* Config.all({ + baseCompression: Config.option(Config.Literals(["gzip", "none"], "OTEL_EXPORTER_OTLP_COMPRESSION")), + compression: Config.option(Config.Literals(["gzip", "none"], "OTEL_EXPORTER_OTLP_TRACES_COMPRESSION")), baseTimeout: Config.option(Config.Int("OTEL_EXPORTER_OTLP_TIMEOUT")), tracesTimeout: Config.option(Config.Int("OTEL_EXPORTER_OTLP_TRACES_TIMEOUT")), exportTimeout: Config.option(Config.Int("OTEL_BSP_EXPORT_TIMEOUT")), @@ -185,6 +213,7 @@ export const layerFromConfig = (options?: { url: endpoint.toString(), resource: options?.resource, headers: options?.headers ?? (yield* OtlpEnv.headers("TRACES")), + compression: Option.getOrElse(Option.firstSomeOf([compression, baseCompression]), () => "none" as const), exportInterval: Option.getOrUndefined(scheduleDelay), maxBatchSize: Option.getOrUndefined(maxBatchSize), context: options?.context, @@ -342,7 +371,7 @@ const makeOtlpSpan = (self: SpanImpl): OtlpSpan => { for (let i = 0; i < self.links.length; i++) { const link = self.links[i] links.push({ - traceId: link.span.traceId, + traceId: link.span.traceId.padStart(32, "0"), spanId: link.span.spanId, attributes: entriesToAttributes(Object.entries(link.attributes)), droppedAttributesCount: 0 @@ -350,7 +379,7 @@ const makeOtlpSpan = (self: SpanImpl): OtlpSpan => { } return { - traceId: self.traceId, + traceId: self.traceId.padStart(32, "0"), spanId: self.spanId, parentSpanId: Option.isSome(self.parent) ? self.parent.value.spanId : undefined, name: self.name, diff --git a/repos/effect/packages/effect/src/observability/PrometheusMetrics.ts b/repos/effect/packages/effect/src/observability/PrometheusMetrics.ts index 2b0872ca25..5b1c8383b8 100644 --- a/repos/effect/packages/effect/src/observability/PrometheusMetrics.ts +++ b/repos/effect/packages/effect/src/observability/PrometheusMetrics.ts @@ -425,6 +425,7 @@ const formatHistogram = ( // Effect buckets are [boundary, cumulativeCount] pairs for (let i = 0; i < state.buckets.length; i++) { const [boundary, cumulativeCount] = state.buckets[i] + if (boundary === Number.POSITIVE_INFINITY) continue const bucketLabels = formatLabels(metric.attributes, [["le", boundary.toString()]]) lines.push(`${name}_bucket${bucketLabels} ${cumulativeCount}`) } diff --git a/repos/effect/packages/effect/src/persistence/PersistedQueue.ts b/repos/effect/packages/effect/src/persistence/PersistedQueue.ts index 6439ca53b9..55227eaad2 100644 --- a/repos/effect/packages/effect/src/persistence/PersistedQueue.ts +++ b/repos/effect/packages/effect/src/persistence/PersistedQueue.ts @@ -34,6 +34,7 @@ import * as Scope from "../Scope.ts" import * as Migrator from "../sql/Migrator.ts" import * as SqlClient from "../sql/SqlClient.ts" import type { SqlError } from "../sql/SqlError.ts" +import type { Fragment } from "../sql/Statement.ts" import * as Redis from "./Redis.ts" /** @@ -80,11 +81,27 @@ export interface PersistedQueue { * **Details** * * If an element with the same id already exists in the queue, it will not be - * added again. De-duplication survives completion until the id is removed by + * added again, and the `delay` of the duplicate offer is ignored. + * De-duplication survives completion until the id is removed by * `layerCleanup`. + * + * `delay` postpones the first delivery. Measured by the store's clock, the + * element is never delivered before the delay elapses, and is typically + * delivered within the store's `pollInterval` after. The SQL store uses the + * database clock and rounds delays up to whole seconds. The Redis store + * compares the offering process's clock with the polling worker's, so it + * relies on those clocks agreeing. + * Retries still use the queue's `retrySchedule`, and the delay does not + * count an attempt. A zero, negative or omitted delay enqueues the element + * immediately. + * + * An infinite delay does nothing: the id is returned, but nothing is stored + * and no de-duplication record is written, so the same id can be offered + * again later. */ readonly offer: (value: A, options?: { - readonly id: string | undefined + readonly id?: string | undefined + readonly delay?: Duration.Input | undefined }) => Effect.Effect /** @@ -232,21 +249,27 @@ export const makeFactory = Effect.gen(function*() { return Effect.succeed>({ [TypeId]: TypeId, offer: (value, opts) => - Effect.flatMap( - encodeUnknown(value), - (element) => { - const id = opts?.id ?? crypto.randomUUID() - return Effect.as( - store.offer({ - name: options.name, - id, - element, - isCustomId: opts?.id !== undefined - }), - id - ) + Effect.suspend(() => { + const id = opts?.id ?? crypto.randomUUID() + const delay = positiveDelay(opts?.delay) + if (delay !== undefined && !Duration.isFinite(delay)) { + return Effect.succeed(id) } - ), + return Effect.flatMap( + encodeUnknown(value), + (element) => + Effect.as( + store.offer({ + name: options.name, + id, + element, + isCustomId: opts?.id !== undefined, + delay + }), + id + ) + ) + }), take: ( f: (value: S["Type"], metadata: { readonly id: string @@ -430,6 +453,13 @@ class DeadLetter { const isDeadLetter = (u: unknown): u is DeadLetter => Predicate.isTagged(u, "~effect/persistence/PersistedQueue/DeadLetter") +// stores only see a positive delay, so a zero or negative one is dropped here +const positiveDelay = (input: Duration.Input | undefined): Duration.Duration | undefined => { + if (input === undefined) return undefined + const delay = Duration.fromInputUnsafe(input) + return Duration.isPositive(delay) ? delay : undefined +} + const deadLetterFromCause = (cause: Cause.Cause): DeadLetter | undefined => { for (const reason of cause.reasons) { if (Cause.isFailReason(reason) && isDeadLetter(reason.error)) { @@ -452,6 +482,9 @@ const deadLetterFromCause = (cause: Cause.Cause): DeadLetter | undefine * The store persists offered elements and returns taken elements in a scope so * the finalizer can complete or retry them based on the processing exit. * + * An offered `delay` is always finite and positive, and the element must not + * be taken before it elapses. It is `undefined` for immediate elements. + * * Claiming an element counts an attempt, so the `attempts` returned by `take` * is 1-based. When the take scope closes with a success the element is marked * completed; a failure retries it according to `retryDelay` or marks it failed @@ -471,6 +504,7 @@ export class PersistedQueueStore extends Context.Service< readonly id: string readonly element: unknown readonly isCustomId: boolean + readonly delay?: Duration.Duration | undefined } ) => Effect.Effect @@ -509,6 +543,9 @@ export class PersistedQueueStore extends Context.Service< * queue's retry schedule until the configured maximum attempts is reached, * after which the element is marked as failed. * + * Delayed elements are scanned on every take loop, so the store is meant for + * development and tests rather than large delayed backlogs. + * * @stability unstable * @category layers * @since 4.0.0 @@ -558,7 +595,7 @@ export const layerStoreMemory: Layer.Layer< element: options.element, attempts: 0, state: "pending", - visibleAt: now, + visibleAt: options.delay === undefined ? now : now + Duration.toMillis(options.delay), stateChangedAt: now } queue.entries.set(options.id, entry) @@ -655,7 +692,9 @@ export const layerStoreMemory: Layer.Layer< * The store uses Redis lists, hashes, and sorted sets with worker locks, * periodically refreshes locks while items are being processed, delays retried * items with the queue's retry schedule, and moves exhausted items to a failed - * queue. + * queue. Delayed offers share the retry sorted set: they are scored with the + * offering process's clock and released by the polling worker's clock, so + * clock skew between hosts shifts their delivery. * * @stability unstable * @category constructors @@ -716,6 +755,7 @@ export const makeStoreRedis = Effect.fnUntraced(function*( const retry = redis.eval(retryRedis) const resetQueue = redis.eval(resetQueueRedis) const offer = redis.eval(offerRedis) + const offerDelayed = redis.eval(offerDelayedRedis) const take = redis.eval(takeRedis) const expireAll = redis.eval(expireAllRedis) const trimFailed = redis.eval(trimFailedRedis) @@ -856,24 +896,33 @@ export const makeStoreRedis = Effect.fnUntraced(function*( }) return PersistedQueueStore.of({ - offer: ({ element, id, isCustomId, name }) => { + offer: ({ delay, element, id, isCustomId, name }) => { const keys = keysFor(name) const payload = JSON.stringify({ id, element }) - return (isCustomId - ? offer(keys.queue, keys.ids, id, payload) - : redis.send("RPUSH", keys.queue, payload)).pipe( - Effect.mapError(({ cause }) => - new PersistedQueueError({ - message: "Failed to offer element to persisted queue", - cause - }) - ), - Effect.tap(() => - Effect.sync(() => { - queueStates.peek(name)?.nudge.openUnsafe() - }) - ) + const send = Effect.suspend(() => { + if (delay === undefined) { + return isCustomId + ? offer(keys.queue, keys.ids, id, payload) + : redis.send("RPUSH", keys.queue, payload) + } + const visibleAt = clock.currentTimeMillisUnsafe() + Duration.toMillis(delay) + return isCustomId + ? offerDelayed(keys.delayed, keys.ids, id, payload, visibleAt) + : redis.send("ZADD", keys.delayed, visibleAt.toString(), payload) + }) + return send.pipe( + Effect.mapError(({ cause }) => + new PersistedQueueError({ + message: "Failed to offer element to persisted queue", + cause + }) + ), + Effect.tap(() => + Effect.sync(() => { + queueStates.peek(name)?.nudge.openUnsafe() + }) ) + ) }, take: (options) => Effect.uninterruptibleMask((restore) => { @@ -1009,6 +1058,25 @@ end } ) +const offerDelayedRedis = Redis.script( + (...args: [keyDelayed: string, keyIds: string, id: string, payload: string, visibleAt: number]) => args, + { + lua: ` +local key_delayed = KEYS[1] +local key_ids = KEYS[2] +local id = ARGV[1] +local payload = ARGV[2] +local visible_at = ARGV[3] + +local result = redis.call("ZADD", key_ids, "NX", "+inf", id) +if result == 1 then + redis.call("ZADD", key_delayed, visible_at, payload) +end +`, + numberOfKeys: 2 + } +) + const resetQueueRedis = Redis.script( ( ...args: [ @@ -1296,6 +1364,9 @@ export const layerStoreRedis: ( * per-worker locks, refreshes active locks while scoped takes are running, and * retries or completes rows according to the processing exit. * + * Offer and retry delays are measured with the database clock and rounded up + * to whole seconds. + * * @stability unstable * @category constructors * @since 4.0.0 @@ -1360,34 +1431,46 @@ export const makeStoreSql: ( } const secondsAgo = (seconds: number) => secondsOffset(-Math.max(Math.ceil(seconds), 0)) const secondsFromNow = (seconds: number) => secondsOffset(Math.max(Math.ceil(seconds), 0)) + // Deadline for a delayed offer, which must never land before the delay + // elapses. pg reads clock_timestamp() since NOW() is fixed at transaction + // start. mysql and sqlite clocks drop the fraction of the current second, so + // they get a whole extra second to cover it. + const delayedVisibleAt = (delay: Duration.Duration) => { + const seconds = Math.ceil(Duration.toSeconds(delay)) + return sql.onDialectOrElse({ + pg: () => sql`clock_timestamp() + INTERVAL '${sql.literal(seconds.toString())} seconds'`, + mssql: () => secondsOffset(seconds), + orElse: () => secondsOffset(seconds + 1) + }) + } const expiresAt = secondsAgo(Duration.toSeconds(lockExpiration)) const offer = sql.onDialectOrElse({ - pg: () => (id: string, name: string, element: string) => + pg: () => (id: string, name: string, element: string, visibleAt: Fragment) => sql` INSERT INTO ${tableNameSql} (id, queue_name, element, state, attempts, visible_at, created_at, updated_at) - VALUES (${id}, ${name}, ${element}, 'pending', 0, ${sqlNow}, ${sqlNow}, ${sqlNow}) + VALUES (${id}, ${name}, ${element}, 'pending', 0, ${visibleAt}, ${sqlNow}, ${sqlNow}) ON CONFLICT (id, queue_name) DO NOTHING `, - mysql: () => (id: string, name: string, element: string) => + mysql: () => (id: string, name: string, element: string, visibleAt: Fragment) => sql` INSERT IGNORE INTO ${tableNameSql} (id, queue_name, element, state, attempts, visible_at, created_at, updated_at) - VALUES (${id}, ${name}, ${element}, 'pending', 0, ${sqlNow}, ${sqlNow}, ${sqlNow}) + VALUES (${id}, ${name}, ${element}, 'pending', 0, ${visibleAt}, ${sqlNow}, ${sqlNow}) `, - mssql: () => (id: string, name: string, element: string) => + mssql: () => (id: string, name: string, element: string, visibleAt: Fragment) => sql` MERGE ${tableNameSql} WITH (HOLDLOCK) AS target USING (SELECT ${id} AS id, ${name} AS queue_name) AS source ON target.id = source.id AND target.queue_name = source.queue_name WHEN NOT MATCHED THEN INSERT (id, queue_name, element, state, attempts, visible_at, created_at, updated_at) - VALUES (source.id, source.queue_name, ${element}, 'pending', 0, ${sqlNow}, ${sqlNow}, ${sqlNow}); + VALUES (source.id, source.queue_name, ${element}, 'pending', 0, ${visibleAt}, ${sqlNow}, ${sqlNow}); `, // sqlite - orElse: () => (id: string, name: string, element: string) => + orElse: () => (id: string, name: string, element: string, visibleAt: Fragment) => sql` INSERT OR IGNORE INTO ${tableNameSql} (id, queue_name, element, state, attempts, visible_at, created_at, updated_at) - VALUES (${id}, ${name}, ${element}, 'pending', 0, ${sqlNow}, ${sqlNow}, ${sqlNow}) + VALUES (${id}, ${name}, ${element}, 'pending', 0, ${visibleAt}, ${sqlNow}, ${sqlNow}) ` }) @@ -1696,20 +1779,30 @@ export const makeStoreSql: ( ) return PersistedQueueStore.of({ - offer: ({ element, id, name }) => - Effect.catchCause(Effect.suspend(() => offer(id, name, JSON.stringify(element))), (cause) => - Effect.fail( - new PersistedQueueError({ - message: "Failed to offer element to persisted queue", - cause - }) - )).pipe( - Effect.tap(() => - Effect.sync(() => { - queueStates.peek(name)?.nudge.openUnsafe() - }) + offer: ({ delay, element, id, name }) => + Effect.catchCause( + Effect.suspend(() => + offer( + id, + name, + JSON.stringify(element), + delay === undefined ? sqlNow : delayedVisibleAt(delay) ) ), + (cause) => + Effect.fail( + new PersistedQueueError({ + message: "Failed to offer element to persisted queue", + cause + }) + ) + ).pipe( + Effect.tap(() => + Effect.sync(() => { + queueStates.peek(name)?.nudge.openUnsafe() + }) + ) + ), take: (options) => { queueStates.get(options.name).maxAttempts = options.maxAttempts const loop: Effect.Effect< diff --git a/repos/effect/packages/effect/src/reactivity/AsyncResult.ts b/repos/effect/packages/effect/src/reactivity/AsyncResult.ts index 3869e5876a..5dbf1873ac 100644 --- a/repos/effect/packages/effect/src/reactivity/AsyncResult.ts +++ b/repos/effect/packages/effect/src/reactivity/AsyncResult.ts @@ -720,6 +720,12 @@ export const matchWithWaiting: { /** * Combines an iterable or record of `AsyncResult` and plain values into one `AsyncResult`, returning the first non-success result or a success of the collected values marked waiting when any input success is waiting. * + * **Details** + * + * If the first non-success result is a failure, its previous success is + * rebuilt in the combined shape from each input's current or previous value. + * It is omitted if any input has no value. + * * @stability unstable * @category combinators * @since 4.0.0 @@ -751,6 +757,11 @@ export const all = | Record>( if (!isAsyncResult(result)) { InternalRecord.assignProperty(successes, key, result) continue + } else if (isFailure(result)) { + return failure(result.cause, { + previousSuccess: combinedPreviousSuccess(entries, isIter), + waiting: result.waiting + }) as any } else if (!isSuccess(result)) { return result as any } @@ -762,6 +773,26 @@ export const all = | Record>( return success(successes, { waiting }) as any } +const combinedPreviousSuccess = ( + entries: ReadonlyArray, + isIter: boolean +): Option.Option> => { + const values: any = isIter ? [] : {} + for (let i = 0; i < entries.length; i++) { + const [key, entry] = entries[i] + if (!isAsyncResult(entry)) { + InternalRecord.assignProperty(values, key, entry) + continue + } + const entryValue = value(entry) + if (Option.isNone(entryValue)) { + return Option.none() + } + InternalRecord.assignProperty(values, key, entryValue.value) + } + return Option.some(success(values)) +} + /** * Creates a typed builder for rendering an `AsyncResult` by handling waiting, initial, success, error, defect, interrupt, and failure cases. * diff --git a/repos/effect/packages/effect/src/reactivity/AtomRegistry.ts b/repos/effect/packages/effect/src/reactivity/AtomRegistry.ts index ef4af667ca..a55ce8c4b4 100644 --- a/repos/effect/packages/effect/src/reactivity/AtomRegistry.ts +++ b/repos/effect/packages/effect/src/reactivity/AtomRegistry.ts @@ -838,7 +838,9 @@ class NodeImpl { this._value = value let failure: unknown = noFailure try { - this.invalidateChildren() + // A first value cannot replace one held by a dependent. Recovery still + // retries dependents whose reads failed before this node had a value. + if (initialized || recovered) this.invalidateChildren() } catch (error) { failure = error } diff --git a/repos/effect/packages/effect/src/rpc/RpcClient.ts b/repos/effect/packages/effect/src/rpc/RpcClient.ts index 615d168adc..3528fe62f2 100644 --- a/repos/effect/packages/effect/src/rpc/RpcClient.ts +++ b/repos/effect/packages/effect/src/rpc/RpcClient.ts @@ -1050,11 +1050,19 @@ export const makeProtocolSocket = (options?: { readonly retryPolicy?: Schedule.Schedule | undefined /** * Runs for each retried `SocketOpenError` when `retryTransientErrors` is enabled. - * A ping timeout fails in-flight calls and is not reported through this hook. - * The returned `Effect` cannot fail with a typed error or require - * services; defects are logged and ignored so retries can continue. + * A ping timeout fails in-flight calls and is reported through `onPingTimeout` + * instead. The returned `Effect` cannot fail with a typed error or + * require services; defects are logged and ignored so retries can continue. */ readonly onTransientError?: ((error: RpcClientError) => Effect.Effect) | undefined + /** + * Runs when an open connection is dropped because no server frame arrived + * within `pingTimeout`, before `ConnectionHooks.onDisconnect` and before + * in-flight calls fail with a `SocketReadError`. Defects are logged and ignored. + * + * @since 4.0.3 + */ + readonly onPingTimeout?: Effect.Effect | undefined }): Effect.Effect< Protocol["Service"], never, @@ -1070,10 +1078,12 @@ export const makeProtocolSocket = (options?: { let parser = serialization.makeUnsafe() - // `parser` is replaced on every connect, and a stateful serialization - // encodes against the connection it is writing to, so the ping is encoded - // when it is sent rather than once up front. + // Encode each ping with the current connection's parser. const pinger = yield* makePinger(Effect.suspend(() => writer.write(parser.encode(constPing)!)), options) + const onPingTimeout = Effect.ignoreCause(options?.onPingTimeout ?? Effect.void, { + log: true, + message: "RpcClient onPingTimeout hook failed" + }) let currentError: RpcClientError | undefined const broadcast = (response: FromServerEncoded) => @@ -1127,9 +1137,11 @@ export const makeProtocolSocket = (options?: { yield* Effect.suspend(() => { parser = serialization.makeUnsafe() pinger.reset() + let connected = false return Effect.gen(function*() { const { pull } = yield* socket.reader currentError = undefined + connected = true if (Option.isSome(hooks)) { yield* hooks.value.onConnect } @@ -1141,17 +1153,19 @@ export const makeProtocolSocket = (options?: { } }).pipe( Effect.scoped, - Effect.raceFirst(Effect.flatMap( - pinger.timeout, - () => - Effect.fail( - new Socket.SocketError({ - reason: new Socket.SocketReadError({ - cause: new Error("ping timeout") - }) + // The read loop never succeeds, so the race only succeeds on a ping + // timeout, after the socket has been cleaned up. + Effect.raceFirst(pinger.timeout), + Effect.andThen(() => connected ? onPingTimeout : Effect.void), + Effect.andThen(() => + Effect.fail( + new Socket.SocketError({ + reason: new Socket.SocketReadError({ + cause: new Error("ping timeout") }) - ) - )) + }) + ) + ) ) }).pipe( Option.isSome(hooks) ? Effect.ensuring(hooks.value.onDisconnect) : identity, @@ -1219,16 +1233,21 @@ const makePinger = Effect.fnUntraced(function*(writePing: Effect.Effect const interval = options?.pingInterval ?? "5 seconds" const timeoutMillis = Duration.toMillis(options?.pingTimeout ?? interval) let lastSeen = clock.currentTimeMillisUnsafe() + let awaitingResponse = false const latch = Latch.makeUnsafe() const onFrame = () => { lastSeen = clock.currentTimeMillisUnsafe() + awaitingResponse = false } const reset = () => { onFrame() latch.closeUnsafe() } yield* Effect.suspend((): Effect.Effect => { - if (clock.currentTimeMillisUnsafe() - lastSeen > timeoutMillis) return latch.open + // A late tick must send a ping before it can declare the connection silent. + // Keep the timeout measured from the last frame, including for custom timeouts. + if (awaitingResponse && clock.currentTimeMillisUnsafe() - lastSeen > timeoutMillis) return latch.open + awaitingResponse = true return writePing }).pipe( Effect.delay(interval), @@ -1262,11 +1281,19 @@ export const layerProtocolSocket = (options?: { readonly retryPolicy?: Schedule.Schedule | undefined /** * Runs for each retried `SocketOpenError` when `retryTransientErrors` is enabled. - * A ping timeout fails in-flight calls and is not reported through this hook. - * The returned `Effect` cannot fail with a typed error or require - * services; defects are logged and ignored so retries can continue. + * A ping timeout fails in-flight calls and is reported through `onPingTimeout` + * instead. The returned `Effect` cannot fail with a typed error or + * require services; defects are logged and ignored so retries can continue. */ readonly onTransientError?: ((error: RpcClientError) => Effect.Effect) | undefined + /** + * Runs when an open connection is dropped because no server frame arrived + * within `pingTimeout`, before `ConnectionHooks.onDisconnect` and before + * in-flight calls fail with a `SocketReadError`. Defects are logged and ignored. + * + * @since 4.0.3 + */ + readonly onPingTimeout?: Effect.Effect | undefined }): Layer.Layer< Protocol, never, diff --git a/repos/effect/packages/effect/src/rpc/RpcServer.ts b/repos/effect/packages/effect/src/rpc/RpcServer.ts index bda39256d4..7f38c61ab1 100644 --- a/repos/effect/packages/effect/src/rpc/RpcServer.ts +++ b/repos/effect/packages/effect/src/rpc/RpcServer.ts @@ -82,6 +82,12 @@ export interface RpcServer { * handlers for a group and sending decoded server responses through * `onFromServer`. * + * **Details** + * + * If writing a stream `Chunk` fails with anything other than an interruption, + * the request fails with that cause. `onFromServer` is assumed to have already + * answered the client and reported it, so nothing else is sent or reported. + * * @stability unstable * @category constructors * @since 4.0.0 @@ -188,7 +194,7 @@ export const makeNoSerialization: ( clients.set(clientId, client) } else if ( client.ended && - (message._tag !== "Interrupt" || !client.fibers.has(message.requestId)) + ((message._tag !== "Interrupt" && message._tag !== "Ack") || !client.fibers.has(message.requestId)) ) { return Effect.interrupt } @@ -199,7 +205,7 @@ export const makeNoSerialization: ( } case "Ack": { const latch = client.latches?.get(message.requestId) - return latch ? latch.open : Effect.void + return latch ? Effect.asVoid(latch.open) : Effect.void } case "Interrupt": { const fiber = client.fibers.get(message.requestId) @@ -279,13 +285,23 @@ export const makeNoSerialization: ( const isUninterruptible = isWrapper && result.uninterruptible // unwrap the fork data type const streamOrEffect = isWrapper ? result.value : result + // set when a chunk could not be written; the writer has already responded + let writeFailure: Cause.Cause | undefined const handler = isStream - ? (streamEffect(client, request, streamOrEffect) as Effect.Effect<{} | Deferred.Deferred>) + ? (streamEffect(client, request, streamOrEffect, (cause) => { + writeFailure = cause + }) as Effect.Effect<{} | Deferred.Deferred>) : (streamOrEffect as Effect.Effect<{} | Deferred.Deferred>) - const withMiddleware = rpc.middlewares.size > 0 - ? applyMiddleware(services, handler, metadata) - : handler + const withMiddleware = rpc.middlewares.size === 0 + ? handler + : isStream + // middleware may rewrite or swallow a chunk write failure, so restore it + ? Effect.flatMap( + Effect.exit(applyMiddleware(services, handler, metadata)), + (exit) => writeFailure ? Effect.failCause(writeFailure) : exit + ) + : applyMiddleware(services, handler, metadata) let responded = false const scope = Scope.makeUnsafe() let deferred: Deferred.Deferred | undefined = undefined @@ -304,6 +320,9 @@ export const makeNoSerialization: ( exit: exit as any }) } + } else if (writeFailure) { + // onFromServer has already answered the client and reported the failure + return Scope.closeUnsafe(scope, exit) ?? Effect.void } else if ( !disableFatalDefects && Cause.hasDies(exit.cause) && @@ -409,8 +428,17 @@ export const makeNoSerialization: ( request: Request, stream: | Stream.Stream - | Effect.Effect, any, Scope.Scope> + | Effect.Effect, any, Scope.Scope>, + onWriteFailure: (cause: Cause.Cause) => void ) => { + const writeChunk = (values: NonEmptyReadonlyArray) => + Effect.onError( + options.onFromServer({ _tag: "Chunk", clientId: client.id, requestId: request.id, values }), + (cause) => { + if (!Cause.hasInterruptsOnly(cause)) onWriteFailure(cause) + return Effect.void + } + ) let latch: Latch.Latch | undefined if (supportsAck) { client.latches ??= new Map() @@ -427,12 +455,7 @@ export const makeNoSerialization: ( while: constTrue, body: constant( Effect.flatMap(Queue.takeAll(queue), (values) => { - const write = options.onFromServer({ - _tag: "Chunk", - clientId: client.id, - requestId: request.id, - values - }) + const write = writeChunk(values) if (!latch) return write latch.closeUnsafe() return Effect.flatMap(write, () => latch.await) @@ -446,12 +469,7 @@ export const makeNoSerialization: ( ) } return Stream.runForEachArray(stream, (values) => { - const write = options.onFromServer({ - _tag: "Chunk", - clientId: client.id, - requestId: request.id, - values - }) + const write = writeChunk(values) if (!latch) return write latch.closeUnsafe() return Effect.andThen(write, latch.await) @@ -476,6 +494,57 @@ export const makeNoSerialization: ( }) }) +// Built-in JSON codecs depend only on the RPC schemas and can be shared. +// Other factories may capture state at construction, so keep them per server. +const isSharedCodecFor = (codecFor: RpcSerialization.CodecFor) => codecFor === RpcSerialization.json.codecFor + +interface RpcCodecs { + readonly decode: (u: unknown) => Effect.Effect + readonly encodeChunk: ( + u: NonEmptyReadonlyArray + ) => Effect.Effect, Schema.SchemaError> + readonly encodeExit: (u: unknown) => Effect.Effect +} + +const sharedRpcCodecs = new WeakMap() + +const rpcCodecs = (codecFor: RpcSerialization.CodecFor, rpc: Rpc.AnyWithProps): RpcCodecs => { + const shared = isSharedCodecFor(codecFor) + let codecs = shared ? sharedRpcCodecs.get(rpc) : undefined + if (codecs === undefined) { + const streamSchemas = RpcSchema.getStreamSchemas(rpc.successSchema) + codecs = { + decode: Schema.decodeUnknownEffect(codecFor(rpc.payloadSchema)) as any, + encodeChunk: Schema.encodeUnknownEffect( + codecFor( + Schema.NonEmptyArray(Option.isSome(streamSchemas) ? streamSchemas.value.success : Schema.Any) + ) + ) as any, + encodeExit: Schema.encodeUnknownEffect(codecFor(Rpc.exitSchema(rpc as any))) as any + } + if (shared) sharedRpcCodecs.set(rpc, codecs) + } + return codecs +} + +interface DefectCodecs { + readonly encodeDefectUnsafe: (defect: unknown) => unknown + readonly encodeUnknownRequestExit: (u: unknown) => Effect.Effect +} + +let sharedDefectCodecs: DefectCodecs | undefined + +const makeDefectCodecs = (codecFor: RpcSerialization.CodecFor): DefectCodecs => ({ + encodeDefectUnsafe: Schema.encodeSync(codecFor(Schema.Defect())), + // Unknown tags have no RPC schema, so use a defect-only exit schema. + encodeUnknownRequestExit: Schema.encodeUnknownEffect( + codecFor(Schema.Exit(Schema.Never, Schema.Never, Schema.Defect())) + ) as any +}) + +const defectCodecs = (codecFor: RpcSerialization.CodecFor): DefectCodecs => + isSharedCodecFor(codecFor) ? (sharedDefectCodecs ??= makeDefectCodecs(codecFor)) : makeDefectCodecs(codecFor) + // Merging the handler entry services with the request fiber services costs // O(services), so the merged context is cached per (entry, fiber context) // pair. Request fibers on persistent connections keep one context across @@ -568,11 +637,7 @@ export const make: ( supportsSpanPropagation, supportsTransferables } = yield* Protocol - const encodeDefectUnsafe = Schema.encodeSync(codecFor(Schema.Defect())) - // Unknown tags have no RPC schema, so use a defect-only exit schema. - const encodeUnknownRequestExit: Schemas["encodeExit"] = Schema.encodeUnknownEffect( - codecFor(Schema.Exit(Schema.Never, Schema.Never, Schema.Defect())) - ) as any + const { encodeDefectUnsafe, encodeUnknownRequestExit } = defectCodecs(codecFor) const services = yield* Effect.context | Rpc.Middleware>() const scope = yield* Scope.make() @@ -633,6 +698,7 @@ export const make: ( ) type Schemas = { + readonly tag: string readonly decode: (u: unknown) => Effect.Effect, Schema.SchemaError> readonly encodeChunk: ( u: NonEmptyReadonlyArray @@ -647,15 +713,9 @@ export const make: ( let schemas = schemasCache.get(rpc) if (!schemas) { const entry = Context.getOrUndefinedUnsafe(services, rpc.key) as Rpc.Handler - const streamSchemas = RpcSchema.getStreamSchemas(rpc.successSchema) schemas = { - decode: Schema.decodeUnknownEffect(codecFor(rpc.payloadSchema)) as any, - encodeChunk: Schema.encodeUnknownEffect( - codecFor( - Schema.NonEmptyArray(Option.isSome(streamSchemas) ? streamSchemas.value.success : Schema.Any) - ) - ) as any, - encodeExit: Schema.encodeUnknownEffect(codecFor(Rpc.exitSchema(rpc as any))) as any, + tag: rpc._tag, + ...rpcCodecs(codecFor, rpc), context: entry.context } schemasCache.set(rpc, schemas) @@ -686,23 +746,38 @@ export const make: ( tag: "Chunk" | "Exit" ) => { const collector = schemas.collector + let encodeFailed = false // The schema encoders evaluate eagerly, so an encode that needs no // services is already a resolved success and can skip the effect wrappers. const write = Exit.isExit(effect) && Exit.isSuccess(effect) ? send(client.id, responseEnvelope(requestId, tag, effect.value), collector && collector.clearUnsafe()) : Effect.flatMap( - Effect.provideContext( - collector ? Effect.provideService(effect, Transferable.Collector, collector) : effect, - schemas.context + Effect.catch( + Effect.provideContext( + collector ? Effect.provideService(effect, Transferable.Collector, collector) : effect, + schemas.context + ), + (error) => + Effect.withFiber((fiber) => { + const defect = Cause.die( + `Failed to encode response for RPC "${schemas.tag}": ${SchemaIssue.defaultFormatter(error.issue)}` + ) + reportCauseUnsafe(fiber, defect) + encodeFailed = true + return Effect.failCause(defect) + }) ), (value) => send(client.id, responseEnvelope(requestId, tag, value), collector && collector.clearUnsafe()) ) return Effect.catchCause(write, (cause) => { client.schemas.delete(requestId) - const defect = Cause.squash(Cause.map(cause, (e) => SchemaIssue.defaultFormatter(e.issue))) + // An encode failure ends the request with the defect, so the request + // span records it. Other failures stop the request as a cancellation. return Effect.andThen( - sendRequestDefect(client, requestId, schemas.encodeExit, defect), - server.write(client.id, { _tag: "Interrupt", requestId, interruptors: [] }) + sendRequestDefect(client, requestId, schemas.encodeExit, Cause.squash(cause)), + encodeFailed + ? Effect.failCause(cause) + : server.write(client.id, { _tag: "Interrupt", requestId, interruptors: [] }) ) }) } @@ -1074,7 +1149,7 @@ export const makeProtocolWithHttpEffect: ( RpcSerialization.RpcSerialization > = Effect.fnUntraced(function*(options = {}) { const serialization = yield* RpcSerialization.RpcSerialization - const encodeDefectUnsafe = Schema.encodeSync(serialization.codecFor(Schema.Defect())) + const { encodeDefectUnsafe } = defectCodecs(serialization.codecFor) const includesFraming = serialization.includesFraming const isBinary = !serialization.contentType.includes("json") @@ -1534,7 +1609,7 @@ const makeSocketProtocol: Effect.Effect< RpcSerialization.RpcSerialization > = Effect.gen(function*() { const serialization = yield* RpcSerialization.RpcSerialization - const encodeDefectUnsafe = Schema.encodeSync(serialization.codecFor(Schema.Defect())) + const { encodeDefectUnsafe } = defectCodecs(serialization.codecFor) const disconnects = yield* Queue.make() let clientId = 0 diff --git a/repos/effect/packages/effect/src/socket/DatagramSocket.ts b/repos/effect/packages/effect/src/socket/DatagramSocket.ts new file mode 100644 index 0000000000..9a6a52ed28 --- /dev/null +++ b/repos/effect/packages/effect/src/socket/DatagramSocket.ts @@ -0,0 +1,919 @@ +/** + * Pull-based UDP sockets with scoped native handles. + * + * Acquiring a reader opens and binds a socket owned by its scope. Only one + * reader is open at a time; another acquisition waits interruptibly for it to + * close. Use `Effect.retry` around a scoped consume loop to open a new socket + * on each retry. + * + * Writes wait while no reader is open, so a send-only client must still + * acquire a reader. + * + * **Example** (Portable request/reply client) + * + * ```ts import.meta.vitest + * import { Effect } from "effect" + * import { NetAddress } from "effect/net" + * import { DatagramSocket } from "effect/socket" + * + * const server = NetAddress.inetAddressFromIpStringUnsafe("127.0.0.1", 5353) + * + * export const request = (payload: string) => + * Effect.gen(function*() { + * const socket = yield* DatagramSocket.DatagramSocket + * const reader = yield* socket.reader + * const writer = yield* socket.writer + * yield* writer.write({ payload, address: server }) + * const [response] = yield* reader.pull + * return response.payload + * }).pipe(Effect.scoped) + * ``` + * + * @stability experimental + * @since 4.0.0 + */ +import type { NonEmptyReadonlyArray } from "../Array.ts" +import * as Context from "../Context.ts" +import * as Effect from "../Effect.ts" +import * as Fiber from "../Fiber.ts" +import { constVoid } from "../Function.ts" +import { args, contA, contAll, exitSucceed, makePrimitive, type Primitive, withFiber } from "../internal/core.ts" +import type { FiberImpl } from "../internal/effect.ts" +import * as Latch from "../Latch.ts" +import * as NetAddress from "../net/NetAddress.ts" +import * as Predicate from "../Predicate.ts" +import * as Schema from "../Schema.ts" +import * as Scope from "../Scope.ts" + +/** + * Runtime type identifier attached to `DatagramSocket` services. + * + * @stability experimental + * @category type IDs + * @since 4.0.0 + */ +export const TypeId = "~effect/socket/DatagramSocket" + +/** + * Service tag for UDP socket transports. + * + * @stability experimental + * @category services + * @since 4.0.0 + */ +export const DatagramSocket: Context.Service = Context.Service( + "effect/socket/DatagramSocket" +) + +/** + * A UDP socket with a scoped, exclusive reader. Acquiring `reader` opens and + * binds a native socket; subsequent acquisitions wait for its scope to close. + * Acquiring `writer` cannot fail, but writes wait for an open reader. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface DatagramSocket { + readonly [TypeId]: typeof TypeId + readonly reader: Effect.Effect + readonly writer: Effect.Effect +} + +/** + * A received packet. + * + * **Details** + * + * The payload is safe to retain. The sender's `address` is parsed on first + * read and cached. + * + * Reply with `writer.write({ payload, address: received })` to reuse the raw + * sender address without parsing. This requires a datagram from a platform + * adapter or `makeFromBackingSocket`. For hand-built datagrams or custom + * readers, use `{ payload, address: received.address }`. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Datagram { + readonly payload: Uint8Array + readonly address: NetAddress.InetAddress +} + +/** + * A packet to send. + * + * **Details** + * + * String payloads are encoded as UTF-8. `address` can be omitted when the + * socket has a `peer` or is connected. On a connected socket an explicit + * `InetAddress` fails the write, while a received `Datagram` is allowed and + * goes out on the connected path. + * + * Pass a received `Datagram` as the destination to reply, or as the whole + * argument to echo it. Both reuse the raw sender address and require a + * datagram from a platform adapter or `makeFromBackingSocket`. Hand-built + * datagrams and custom readers must pass an explicit `InetAddress` instead. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface OutgoingDatagram { + readonly payload: Uint8Array | string + readonly address?: NetAddress.InetAddress | Datagram | undefined +} + +/** + * The receive side of an open native socket. + * + * **Details** + * + * `pull` returns everything queued since the last pull, or waits for the next + * packet. After a terminal error, `pull` first returns the queued packets and + * then fails with the same error until the reader's scope closes. Closing the + * scope discards the queue and fails every waiting `pull` with + * `DatagramSocketClosedError`. + * + * Concurrent pulls wait in FIFO order. Each incoming packet goes to the + * oldest waiter; a terminal error fails all waiters. + * + * `address` is the bound local address, parsed on first read and cached. + * + * `dropped` counts receive-buffer overflow since this reader opened, not + * kernel or network loss or packets discarded on scope close. + * + * `joinMulticast` joins a group until its scope closes; leave failures are + * ignored. Its `interface` selects where packets arrive (ingress), not the + * platform's `multicast.interface` for sending (egress). + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Reader { + readonly pull: Effect.Effect, DatagramSocketError> + readonly address: NetAddress.InetAddress + readonly dropped: () => number + readonly joinMulticast: (options: { + readonly group: NetAddress.MulticastAddress + readonly interface?: NetAddress.MulticastInterface | undefined + readonly source?: A | undefined + }) => Effect.Effect +} + +/** + * The send side of a `DatagramSocket`. Writes wait until a reader is open, so + * a send-only client must still acquire a reader. + * + * **Details** + * + * A write completes when the runtime reports the send's result, and send + * errors fail it with a `DatagramSocketWriteError` carrying the destination + * `address`. After a terminal reader error, writes fail with that error until + * the reader's scope closes, and then wait for the next reader. + * + * `writeAll` fails with the first error, without resending. Partial delivery is + * unspecified. The error has no packet index, and its `address` is absent on Bun. + * + * There is no built-in write timeout; use `Effect.timeout`. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface Writer { + readonly write: (datagram: OutgoingDatagram) => Effect.Effect + readonly writeAll: (datagrams: NonEmptyReadonlyArray) => Effect.Effect +} + +/** + * Receive queue options. + * + * **Details** + * + * The queue is bounded in packets, with no byte cap. `capacity` defaults to + * 1024 and must be a positive safe integer. The worst-case + * memory is capacity × 64 KiB, about 64 MiB at the default. + * + * When the queue is full, `"dropping"` (the default) discards the incoming + * packet and `"sliding"` discards the oldest queued one. Both count the + * packet in `Reader.dropped`. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface ReceiveBufferOptions { + readonly capacity?: number | undefined + readonly strategy?: "dropping" | "sliding" | undefined +} + +/** + * Creates a `DatagramSocket` from its `reader` and `writer` effects. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const make = (options: { + readonly reader: DatagramSocket["reader"] + readonly writer: DatagramSocket["writer"] +}): DatagramSocket => + DatagramSocket.of({ + [TypeId]: TypeId, + reader: options.reader, + writer: options.writer + }) + +/** + * A native host and port, parsed on demand. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface BackingAddress { + readonly host: string + readonly port: number +} + +/** + * Native transport contract used by platform adapters. + * + * **Details** + * + * `address` is the raw bound address, read once at open. `scopeIds` maps IPv6 + * zone names to scope IDs, for parsing named zones and formatting + * destinations. `peer` is the default destination, and `connected` marks a + * natively connected socket, whose sends receive no destination. + * + * `send` and `sendMany` hand datagrams to the runtime and call `done` exactly + * once, synchronously or later, when the runtime reports the result. They must + * not throw. `sendMany` passes the index of the failing datagram to `done` + * when the runtime knows it, so core can attach its address. + * + * Adapters normalize native errors before passing them to core. + * Read destination `host` and `port` during the call; do not retain the record. + * + * `close` must not throw. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface BackingSocket { + readonly address: BackingAddress + readonly scopeIds?: ReadonlyMap | undefined + readonly peer?: BackingAddress | undefined + readonly connected?: boolean | undefined + readonly send: ( + payload: Uint8Array, + destination: BackingAddress | undefined, + done: (error?: DatagramSocketError) => void + ) => void + readonly sendMany: ( + payloads: ReadonlyArray, + destinations: ReadonlyArray, + done: (error?: DatagramSocketError, index?: number) => void + ) => void + readonly joinMulticast: (options: { + readonly group: NetAddress.MulticastAddress + readonly interface?: NetAddress.MulticastInterface | undefined + readonly source?: A | undefined + }) => Effect.Effect<() => Effect.Effect, DatagramSocketError> + readonly close: () => void +} + +/** + * Callbacks installed before opening the backing socket; packets may arrive + * synchronously. + * + * **Details** + * + * `onPacket` queues a received packet. `onReadError` is a terminal receive + * error and `onClose` reports the native socket closing underneath the + * reader; both are sticky. `onError` forwards errors with no write left to + * fail, such as ICMP reports, to the user's `onError` option. + * + * Each callback can be passed on its own, for example as a runtime's event + * listener. + * + * @stability experimental + * @category models + * @since 4.0.0 + */ +export interface BackingEvents { + readonly onPacket: (payload: Uint8Array, host: string, port: number) => void + readonly onReadError: (error: DatagramSocketError) => void + readonly onError: (error: DatagramSocketError) => void + readonly onClose: () => void +} + +/** + * The normalized kind of a send or receive failure. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export type IoErrorKind = "MessageTooLarge" | "Unreachable" | "ConnectionRefused" | "PermissionDenied" | "Unknown" + +/** + * Opening or binding the native socket, applying its options, or resolving + * a name failed. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class DatagramSocketOpenError + extends Schema.Error("effect/socket/DatagramSocket/OpenError")({ + _tag: Schema.tag("DatagramSocketOpenError"), + kind: Schema.Literals(["AddressInUse", "AddressNotAvailable", "PermissionDenied", "Unknown"]), + cause: Schema.Defect() + }) +{} + +/** + * A receive failed, or an ICMP report arrived with no write left to fail. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class DatagramSocketReadError + extends Schema.Error("effect/socket/DatagramSocket/ReadError")({ + _tag: Schema.tag("DatagramSocketReadError"), + kind: Schema.Literals(["MessageTooLarge", "Unreachable", "ConnectionRefused", "PermissionDenied", "Unknown"]), + cause: Schema.Defect() + }) +{} + +/** + * A send failed. `address` is the destination when it is known. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class DatagramSocketWriteError + extends Schema.Error("effect/socket/DatagramSocket/WriteError")({ + _tag: Schema.tag("DatagramSocketWriteError"), + kind: Schema.Literals(["MessageTooLarge", "Unreachable", "ConnectionRefused", "PermissionDenied", "Unknown"]), + address: Schema.optional(Schema.InetAddress), + cause: Schema.Defect() + }) +{} + +/** + * The native socket closed underneath the reader, or the reader's scope + * closed. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class DatagramSocketClosedError + extends Schema.Error("effect/socket/DatagramSocket/ClosedError")({ + _tag: Schema.tag("DatagramSocketClosedError") + }) +{} + +/** + * The runtime lacks a capability, such as source-specific multicast on Deno. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class DatagramSocketUnsupportedError + extends Schema.Error("effect/socket/DatagramSocket/UnsupportedError")({ + _tag: Schema.tag("DatagramSocketUnsupportedError"), + capability: Schema.String, + runtime: Schema.String + }) +{ + /** + * Names the runtime and the capability it lacks. + * + * @stability experimental + * @since 4.0.0 + */ + override get message() { + return `${this.runtime} does not support ${this.capability}` + } +} + +/** + * Schema for the union of `DatagramSocketError` reasons. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export const DatagramSocketErrorReason = Schema.Union([ + DatagramSocketOpenError, + DatagramSocketReadError, + DatagramSocketWriteError, + DatagramSocketClosedError, + DatagramSocketUnsupportedError +]) +/** + * The union of `DatagramSocketError` reasons. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export type DatagramSocketErrorReason = typeof DatagramSocketErrorReason.Type + +/** + * Runtime type identifier attached to `DatagramSocketError` values. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export const DatagramSocketErrorTypeId = "~effect/socket/DatagramSocket/DatagramSocketError" + +/** + * Returns `true` when a value is a `DatagramSocketError`. + * + * @stability experimental + * @category guards + * @since 4.0.0 + */ +export const isDatagramSocketError = (u: unknown): u is DatagramSocketError => + Predicate.hasProperty(u, DatagramSocketErrorTypeId) + +/** + * The error raised by `DatagramSocket` operations, wrapping a specific + * reason. Its `cause` and `message` come from the reason. + * + * @stability experimental + * @category errors + * @since 4.0.0 + */ +export class DatagramSocketError + extends Schema.TaggedError(DatagramSocketErrorTypeId)("DatagramSocketError", { + _tag: Schema.tag("DatagramSocketError"), + reason: DatagramSocketErrorReason + }) +{ + // @effect-diagnostics-next-line overriddenSchemaConstructor:off + constructor(props: { readonly reason: DatagramSocketErrorReason }) { + if ("cause" in props.reason) { + super({ ...props, cause: props.reason.cause } as any) + } else { + super(props) + } + } + readonly [DatagramSocketErrorTypeId] = DatagramSocketErrorTypeId + override get message() { + return this.reason.message + } +} + +/** + * Builds a `DatagramSocket` over a backing socket, opening a new socket for + * each reader acquisition. + * + * **Details** + * + * `open` receives the event callbacks before the handle exists, so packets can + * be queued while it opens. Core owns the receive queue and its overflow + * strategy, reader exclusivity, sticky errors, lazy address parsing, the + * writer latch and destination formatting. The handle is closed when the + * reader's scope closes. If acquisition is interrupted while `open` is still + * running, the interruption returns at once, `open` is left to finish, and + * the handle it produces is closed. The next reader waits until that open has + * settled, so two native sockets never exist at once. An adopted `acquire` + * must therefore finish in bounded time. + * + * `open` runs in the reader's scope, with the services of the fiber that + * built the socket, so an adopted `acquire` can use them and register + * finalizers that run when the reader closes. Where the fiber acquiring the + * reader has a service with the same tag, its own takes precedence. + * + * Concurrent pulls are served in the order they started waiting. + * + * `onError` receives errors with no write left to fail. It runs + * synchronously, and anything it throws is ignored. + * + * Invalid `receiveBuffer.capacity` values cause a defect; use a positive + * safe integer. + * + * @stability experimental + * @category constructors + * @since 4.0.0 + */ +export const makeFromBackingSocket = ( + open: (events: BackingEvents) => Effect.Effect, + options?: { + readonly receiveBuffer?: ReceiveBufferOptions | undefined + readonly onError?: ((error: DatagramSocketError) => void) | undefined + } | undefined +): Effect.Effect> => + withFiber((fiber) => { + const capacity = options?.receiveBuffer?.capacity ?? 1024 + if (!Number.isSafeInteger(capacity) || capacity < 1) { + throw new RangeError(`DatagramSocket receive buffer capacity must be a positive integer, received ${capacity}`) + } + return Effect.succeed( + makeFromBackingSocketWithContext( + open, + fiber.context as Context.Context, + capacity, + options?.receiveBuffer?.strategy === "sliding", + options?.onError + ) + ) + }) + +const makeFromBackingSocketWithContext = ( + open: (events: BackingEvents) => Effect.Effect, + services: Context.Context, + capacity: number, + sliding: boolean, + onError: ((error: DatagramSocketError) => void) | undefined +): DatagramSocket => { + const free = Latch.makeUnsafe(true) + const latch = Latch.makeUnsafe(false) + let current: ReaderState | undefined + + const abandon = (state: ReaderState, opening: Fiber.Fiber) => { + state.close() + // Release reader ownership only after the interrupted open settles. + opening.addObserver((exit) => { + if (exit._tag === "Success") exit.value.close() + free.openUnsafe() + }) + } + + const release = (state: ReaderState) => { + state.close() + current = undefined + latch.closeUnsafe() + free.openUnsafe() + } + + const reader: DatagramSocket["reader"] = Effect.uninterruptibleMask( + Effect.fnUntraced(function*(restore) { + while (!free.closeUnsafe()) yield* restore(free.await) + const scope = yield* Effect.scope + const state = new ReaderState(capacity, sliding, onError) + // Native opens may be uncancellable. Interrupt only the wait; `abandon` + // closes any socket returned later. + const opened = open(state.events).pipe( + Effect.updateContext((input: Context.Context) => + Context.add(Context.merge(services, input), Scope.Scope, scope) + ) + ) as Effect.Effect + const opening = yield* Effect.forkDetach(opened, { startImmediately: true }) + state.handle = yield* restore(Fiber.join(opening)).pipe( + Effect.onError(() => Effect.sync(() => abandon(state, opening))) + ) + current = state + latch.openUnsafe() + yield* Effect.addFinalizer(() => Effect.sync(() => release(state))) + return makeReader(state) + }) + ) + + const write = (datagram: OutgoingDatagram): Effect.Effect => + withFiber((fiber) => { + const state = current + return state === undefined ? latch.whenOpen(write(datagram)) : state.write(datagram, fiber) + }) + const writeAll = (datagrams: NonEmptyReadonlyArray): Effect.Effect => + withFiber((fiber) => { + const state = current + return state === undefined ? latch.whenOpen(writeAll(datagrams)) : state.writeAll(datagrams, fiber) + }) + const writer: DatagramSocket["writer"] = Effect.succeed({ write, writeAll }) + + return make({ reader, writer }) +} + +const encoder = new TextEncoder() +const encode = (payload: Uint8Array | string) => typeof payload === "string" ? encoder.encode(payload) : payload +const emptyScopeIds: ReadonlyMap = new Map() + +const closedError = () => new DatagramSocketError({ reason: new DatagramSocketClosedError() }) + +// Rejected writes return this sentinel, avoiding per-packet error type checks. +const rejected: BackingAddress = { host: "", port: 0 } + +class DatagramImpl implements Datagram, BackingAddress { + payload: Uint8Array + host: string + port: number + readonly owner: ReaderState + #address: NetAddress.InetAddress | undefined + constructor(payload: Uint8Array, host: string, port: number, owner: ReaderState) { + this.payload = payload + this.host = host + this.port = port + this.owner = owner + } + get address(): NetAddress.InetAddress { + return this.#address ??= NetAddress.inetAddressFromNativeUnsafe(this.host, this.port, this.owner.scopeIds) + } + // only for a queued record, which no pull has returned yet + reuse(payload: Uint8Array, host: string, port: number) { + this.payload = payload + this.host = host + this.port = port + this.#address = undefined + } +} + +const targetOf = (datagram: OutgoingDatagram): NetAddress.InetAddress | DatagramImpl | undefined => + "host" in datagram ? datagram as DatagramImpl : datagram.address as NetAddress.InetAddress | DatagramImpl | undefined + +class ReaderState { + readonly capacity: number + readonly sliding: boolean + readonly listener: ((error: DatagramSocketError) => void) | undefined + readonly events: BackingEvents = { + onPacket: (payload, host, port) => this.push(payload, host, port), + onReadError: (error) => this.fail(error), + onError: (error) => this.report(error), + onClose: () => this.fail(closedError()) + } + + // set when `open` completes; packets can arrive before that + handle: BackingSocket | undefined = undefined + failure: Effect.Effect | undefined = undefined + // separate from `failure`: after a sticky read error the socket is still + // open, so ICMP reports still reach `onError` + closed = false + + // Sliding overflow turns the full buffer into a ring, oldest at `head`. + buffer: Array = [] + head = 0 + dropped = 0 + + // A single consumer uses the first waiter slot without touching the array. + waiter: FiberImpl | undefined = undefined + waiters: Array = [] + readonly unpark: Primitive = unpark(this) + + bound: NetAddress.InetAddress | undefined = undefined + // one-entry cache for `write` to the same explicit address + lastTarget: NetAddress.InetAddress | undefined = undefined + lastDestination: BackingAddress | undefined = undefined + rejection: DatagramSocketError | undefined = undefined + + constructor(capacity: number, sliding: boolean, listener: ((error: DatagramSocketError) => void) | undefined) { + this.capacity = capacity + this.sliding = sliding + this.listener = listener + } + + push(payload: Uint8Array, host: string, port: number) { + if (this.failure !== undefined) return + if (this.buffer.length >= this.capacity) return this.overflow(payload, host, port) + const datagram = new DatagramImpl(payload, host, port, this) + if (this.waiter !== undefined) return this.wake(datagram) + const buffer = this.buffer + buffer[buffer.length] = datagram + } + + wake(datagram: DatagramImpl) { + const fiber = this.waiter! + this.promoteWaiter() + fiber.evaluate(exitSucceed([datagram]) as any) + } + + overflow(payload: Uint8Array, host: string, port: number) { + this.dropped++ + if (!this.sliding) return + const buffer = this.buffer + const head = this.head + buffer[head].reuse(payload, host, port) + this.head = head + 1 === buffer.length ? 0 : head + 1 + } + + take(): NonEmptyReadonlyArray { + const buffer = this.buffer + const head = this.head + this.buffer = [] + if (head === 0) return buffer as unknown as NonEmptyReadonlyArray + this.head = 0 + const length = buffer.length + const batch = new Array(length) + let j = 0 + for (let i = head; i < length; i++) batch[j++] = buffer[i] + for (let i = 0; i < head; i++) batch[j++] = buffer[i] + return batch as unknown as NonEmptyReadonlyArray + } + + park(fiber: FiberImpl) { + if (this.waiter === undefined) this.waiter = fiber + else this.waiters.push(fiber) + } + + promoteWaiter() { + this.waiter = this.waiters.length === 0 ? undefined : this.waiters.shift() + } + + removeWaiter(fiber: FiberImpl) { + if (this.waiter === fiber) return this.promoteWaiter() + if (this.waiters.length === 0) return + const index = this.waiters.indexOf(fiber) + if (index !== -1) this.waiters.splice(index, 1) + } + + failWaiters() { + const waiter = this.waiter + if (waiter === undefined) return + const failure = this.failure! + const waiters = this.waiters + this.waiter = undefined + this.waiters = [] + waiter.evaluate(failure as any) + for (let i = 0; i < waiters.length; i++) waiters[i].evaluate(failure as any) + } + + fail(error: DatagramSocketError) { + if (this.failure !== undefined) return + this.failure = Effect.fail(error) + this.failWaiters() + } + + close() { + this.closed = true + this.buffer = [] + this.head = 0 + this.failure = Effect.fail(closedError()) + this.failWaiters() + this.handle?.close() + } + + report(error: DatagramSocketError) { + const listener = this.listener + if (listener === undefined || this.closed) return + try { + listener(error) + } catch { + // Listener errors cannot fail native callbacks. + } + } + + // packets can arrive before the handle does, so they read this lazily + get scopeIds(): ReadonlyMap { + return this.handle?.scopeIds ?? emptyScopeIds + } + + get address(): NetAddress.InetAddress { + return this.bound ??= NetAddress.inetAddressFromNativeUnsafe( + this.handle!.address.host, + this.handle!.address.port, + this.scopeIds + ) + } + + // Synchronous sends avoid parking; async completions resume inline. + // Ignore completions after interruption. + write(datagram: OutgoingDatagram, fiber: FiberImpl): Effect.Effect { + if (this.failure !== undefined) return this.failure + const target = targetOf(datagram) + const destination = this.destination(target) + if (destination === rejected) return Effect.fail(this.rejection!) + const handle = this.handle! + const payload = encode(datagram.payload) + let result: Effect.Effect | undefined + let parked = false + handle.send(payload, destination, (error) => { + if (result !== undefined) return + result = error === undefined ? Effect.void : Effect.fail(this.withAddress(error, target)) + if (parked) fiber.evaluate(result as any) + }) + if (result !== undefined) return result + parked = true + return fiber.yieldWith(() => { + parked = false + }) as any + } + + writeAll( + datagrams: NonEmptyReadonlyArray, + fiber: FiberImpl + ): Effect.Effect { + if (this.failure !== undefined) return this.failure + const payloads = new Array(datagrams.length) + const destinations = new Array(datagrams.length) + for (let i = 0; i < datagrams.length; i++) { + const datagram = datagrams[i] + const destination = this.destination(targetOf(datagram)) + if (destination === rejected) return Effect.fail(this.rejection!) + payloads[i] = encode(datagram.payload) + destinations[i] = destination + } + let result: Effect.Effect | undefined + let parked = false + this.handle!.sendMany(payloads, destinations, (error, index) => { + if (result !== undefined) return + result = error === undefined + ? Effect.void + : Effect.fail(index === undefined ? error : this.withAddress(error, targetOf(datagrams[index]!))) + if (parked) fiber.evaluate(result as any) + }) + if (result !== undefined) return result + parked = true + return fiber.yieldWith(() => { + parked = false + }) as any + } + + // Returns `rejected` on failure, with the error stored in `rejection`. + destination(target: NetAddress.InetAddress | DatagramImpl | undefined): BackingAddress | undefined { + const handle = this.handle! + if (target === undefined) { + if (handle.connected) return undefined + return handle.peer ?? this.reject("DatagramSocket write has no destination and the socket has no peer") + } + if (!("_tag" in target)) return handle.connected ? undefined : target as DatagramImpl + if (handle.connected) return this.reject("an explicit address cannot be used on a connected DatagramSocket", target) + if (target === this.lastTarget) return this.lastDestination + const destination = { host: NetAddress.formatNativeHost(target, this.scopeIds), port: target.port } + this.lastTarget = target + this.lastDestination = destination + return destination + } + + reject(message: string, address?: NetAddress.InetAddress): BackingAddress { + this.rejection = new DatagramSocketError({ + reason: new DatagramSocketWriteError({ kind: "Unknown", address, cause: new Error(message) }) + }) + return rejected + } + + withAddress( + error: DatagramSocketError, + target: NetAddress.InetAddress | DatagramImpl | undefined + ): DatagramSocketError { + const reason = error.reason + if (reason._tag !== "DatagramSocketWriteError" || reason.address !== undefined) return error + const address = this.addressOf(target) + if (address === undefined) return error + return new DatagramSocketError({ + reason: new DatagramSocketWriteError({ kind: reason.kind, address, cause: reason.cause }) + }) + } + + addressOf(target: NetAddress.InetAddress | DatagramImpl | undefined): NetAddress.InetAddress | undefined { + try { + if (target !== undefined) return "_tag" in target ? target : (target as DatagramImpl).address + const peer = this.handle!.peer + return peer === undefined + ? undefined + : NetAddress.inetAddressFromNativeUnsafe(peer.host, peer.port, this.scopeIds) + } catch { + // an unknown IPv6 zone leaves the address out + return undefined + } + } +} + +// Park the fiber itself and resume it inline, avoiding `Effect.callback` allocations. +const makePull = (state: ReaderState): Reader["pull"] => + withFiber((fiber): any => { + if (state.buffer.length !== 0) { + const batch = state.take() + const cont = fiber.getCont(contA) + return cont ? cont[contA](batch, fiber) : fiber.yieldWith(exitSucceed(batch)) + } + if (state.failure !== undefined) return state.failure + state.park(fiber) + fiber._stack.push(state.unpark) + return fiber.yieldWith(constVoid) + }) + +// `contAll` removes interrupted waiters too; after a wake, removal is a no-op. +const unpark: (state: ReaderState) => Primitive = makePrimitive({ + op: "DatagramSocketUnpark", + [contAll](fiber) { + this[args].removeWaiter(fiber) + } +}) + +const makeReader = (state: ReaderState): Reader => ({ + pull: makePull(state), + get address() { + return state.address + }, + dropped: () => state.dropped, + joinMulticast: (options) => + Effect.suspend(() => { + if (state.failure !== undefined) return state.failure + return Effect.acquireRelease( + state.handle!.joinMulticast(options), + (leave) => state.closed ? Effect.void : Effect.ignoreCause(leave()) + ) + }) +}) diff --git a/repos/effect/packages/effect/src/socket/Socket.ts b/repos/effect/packages/effect/src/socket/Socket.ts index 43d8b094fd..8258a25752 100644 --- a/repos/effect/packages/effect/src/socket/Socket.ts +++ b/repos/effect/packages/effect/src/socket/Socket.ts @@ -161,6 +161,12 @@ export interface Writer { * @since 4.0.0 */ export interface TlsUpgradeOptions { + /** + * DNS hostname used for Server Name Indication (SNI) and certificate identity + * verification during client upgrades. Server upgrades ignore this option. + * When omitted, the adapter retains its existing hostname behavior. + */ + readonly servername?: string | undefined readonly key?: | Redacted.Redacted | ReadonlyArray> @@ -770,13 +776,18 @@ export interface WebSocketLike { } /** - * Common options understood by a WebSocket client implementation. + * Client options for Node and Bun WebSocket implementations, allowing + * handshake headers and subprotocols to be supplied together. * * @stability unstable * @category models * @since 4.0.0 */ export interface WebSocketClientOptions { + /** + * Subprotocols to offer in the opening handshake. + */ + readonly protocols?: string | Array | undefined /** * Headers to include in the opening handshake. * @@ -828,6 +839,7 @@ export class WebSocketConstructor extends Context.Service< /** * Layer that provides `WebSocketConstructor` using `globalThis.WebSocket`. + * Rejects client options objects, including those with handshake headers. * * @stability unstable * @category layers @@ -845,6 +857,8 @@ export const layerWebSocketConstructorGlobal: Layer.Layer /** * Creates a `Socket` backed by a `WebSocketConstructor`, dialing the * WebSocket for each reader acquisition. + * Optional handshake headers require a Node or Bun constructor; without + * headers, protocols are passed directly for browser compatibility. * * @stability unstable * @category constructors @@ -853,13 +867,21 @@ export const layerWebSocketConstructorGlobal: Layer.Layer export const makeWebSocket = (url: string | Effect.Effect, options?: { readonly openTimeout?: Duration.Input | undefined readonly protocols?: string | Array | undefined + readonly headers?: Readonly> | undefined readonly highWaterMark?: number | undefined }): Effect.Effect => WebSocketConstructor.use((makeWs) => fromWebSocket( Effect.acquireRelease( (typeof url === "string" ? Effect.succeed(url) : url).pipe( - Effect.map((url) => makeWs(url, options?.protocols)) + Effect.map((url) => + makeWs( + url, + options?.headers === undefined + ? options?.protocols + : { protocols: options.protocols, headers: options.headers } + ) + ) ), (ws) => Effect.sync(() => ws.close(1000)) ), @@ -1136,6 +1158,7 @@ const defaultHighWaterMark = 64 * 1024 /** * Creates a binary `Channel` backed by a WebSocket URL, requiring a * `WebSocketConstructor` service. + * Supports subprotocols and, with a Node or Bun constructor, handshake headers. * * @stability unstable * @category constructors @@ -1146,6 +1169,7 @@ export const makeWebSocketChannel = ( options?: { readonly openTimeout?: Duration.Input | undefined readonly protocols?: string | Array | undefined + readonly headers?: Readonly> | undefined readonly highWaterMark?: number | undefined } ): Channel.Channel< @@ -1164,6 +1188,7 @@ export const makeWebSocketChannel = ( /** * Layer that provides a `Socket` service backed by a WebSocket URL or URL * effect. + * Supports subprotocols and, with a Node or Bun constructor, handshake headers. * * @stability unstable * @category layers @@ -1174,6 +1199,7 @@ export const layerWebSocket: ( options?: { readonly openTimeout?: Duration.Input | undefined readonly protocols?: string | Array | undefined + readonly headers?: Readonly> | undefined readonly highWaterMark?: number | undefined } | undefined ) => Layer.Layer = flow(makeWebSocket, Layer.effect(Socket)) diff --git a/repos/effect/packages/effect/src/socket/index.ts b/repos/effect/packages/effect/src/socket/index.ts index 29a5c45ceb..9028de0cef 100644 --- a/repos/effect/packages/effect/src/socket/index.ts +++ b/repos/effect/packages/effect/src/socket/index.ts @@ -5,6 +5,12 @@ // @barrel: Auto-generated exports. Do not edit manually. +/** + * @stability experimental + * @since 4.0.0 + */ +export * as DatagramSocket from "./DatagramSocket.ts" + /** * @stability unstable * @since 4.0.0 diff --git a/repos/effect/packages/effect/src/sql/Migrator.ts b/repos/effect/packages/effect/src/sql/Migrator.ts index 8d09037dd5..408b724707 100644 --- a/repos/effect/packages/effect/src/sql/Migrator.ts +++ b/repos/effect/packages/effect/src/sql/Migrator.ts @@ -140,14 +140,21 @@ export const make = ({ PRIMARY KEY (migration_id) )`, pg: () => - Effect.catch( - sql`select ${table}::regclass`, - () => - sql`CREATE TABLE ${sql(table)} ( + Effect.flatMap( + migrationsTableExists(sql, table), + (exists) => + exists ? Effect.void : Effect.asVoid(sql`CREATE TABLE ${sql(table)} ( migration_id integer primary key, created_at timestamp with time zone not null default now(), name text not null -)` +)`).pipe( + Effect.catch((error) => + Effect.flatMap( + migrationsTableExists(sql, table), + (exists) => exists ? Effect.void : Effect.fail(error) + ) + ) + ) ), orElse: () => sql`CREATE TABLE IF NOT EXISTS ${sql(table)} ( @@ -328,6 +335,15 @@ export const make = ({ return completed }) +const migrationsTableExists = (sql: Client.SqlClient, table: string): Effect.Effect => { + // Match query quoting: to_regclass folds unquoted names to lowercase. + const quotedTable = sql`${sql(table)}`.compile(true)[0] + return Effect.map( + sql`SELECT 1 AS found WHERE to_regclass(${quotedTable}) IS NOT NULL`.withoutTransform, + (rows) => rows.length > 0 + ) +} + const migrationOrder = Order.make(([a], [b]) => Order.Number(a, b)) const isConstraintConflict = (error: SqlError): boolean => diff --git a/repos/effect/packages/effect/src/sql/SqlClient.ts b/repos/effect/packages/effect/src/sql/SqlClient.ts index 61d39e97b8..bf24fec618 100644 --- a/repos/effect/packages/effect/src/sql/SqlClient.ts +++ b/repos/effect/packages/effect/src/sql/SqlClient.ts @@ -9,7 +9,7 @@ * @stability unstable * @since 4.0.0 */ -import type * as Cause from "../Cause.ts" +import * as Cause from "../Cause.ts" import { Clock } from "../Clock.ts" import * as Context from "../Context.ts" import * as Effect from "../Effect.ts" @@ -275,16 +275,22 @@ export const make = Effect.fnUntraced(function*(options: SqlClient.MakeOptions) }) /** - * Builds the acquirers and failed-COMMIT cleanup for a SQLite client that + * Builds the acquirers, borrower and failed-COMMIT cleanup for a SQLite client that * shares one connection through a semaphore. * * **Details** * + * Both acquirers lease the connection into the current scope and hold the + * semaphore until that scope closes. The borrower holds the same semaphore + * until the statement finishes without creating a scope. Another fiber cannot + * begin a transaction underneath either. Effects that use the connection directly, + * such as an export, have to run inside `Effect.scoped`. + * * SQLite can keep a transaction open after COMMIT fails, for example on a * deferred foreign key violation. `onCommitFailure` rolls it back before the * connection is reused. If that ROLLBACK fails, the connection is rejected, and - * each acquisition retries the ROLLBACK once while holding the semaphore until - * it succeeds. The database is never reopened, and transactions started with a + * each acquisition or borrow retries the ROLLBACK once while holding the semaphore + * until it succeeds. The database is never reopened, and transactions started with a * plain `BEGIN` are only touched after a failed cleanup. * * Pass `isTransaction` when the driver can report whether a transaction is @@ -300,7 +306,8 @@ export const makeSqliteAcquirers = (options: { readonly semaphore: Semaphore.Semaphore readonly isTransaction?: ((conn: C) => boolean) | undefined }): { - readonly acquirer: Effect.Effect + readonly acquirer: Effect.Effect + readonly borrower: Connection.Borrower readonly transactionAcquirer: Effect.Effect readonly onCommitFailure: (conn: Connection.Connection) => Effect.Effect } => { @@ -336,15 +343,18 @@ export const makeSqliteAcquirers = (options: { }) }) + const lease = Effect.uninterruptibleMask((restore) => + Effect.flatMap(Effect.scope, (scope) => + restore(semaphore.take(1)).pipe( + Effect.andThen(Scope.addFinalizer(scope, semaphore.release(1))), + Effect.andThen(available) + )) + ) + return { - acquirer: semaphore.withPermits(1)(available), - transactionAcquirer: Effect.uninterruptibleMask((restore) => - Effect.flatMap(Effect.scope, (scope) => - restore(semaphore.take(1)).pipe( - Effect.andThen(Scope.addFinalizer(scope, semaphore.release(1))), - Effect.andThen(available) - )) - ), + acquirer: lease, + borrower: (f) => semaphore.withPermit(Effect.flatMap(available, f)), + transactionAcquirer: lease, onCommitFailure: (conn) => Effect.tapCause(rollback(conn as C), (cause) => Effect.sync(() => poison(cause))) } } @@ -359,6 +369,18 @@ const isNoTransactionError = (error: SqlError): boolean => { return /no transaction is active/i.test(message) } +/** + * A failed COMMIT cleanup leaves the connection in an unsafe state, so both the + * COMMIT error and the cleanup error are promoted to defects: typed recovery + * must not be able to hide them. + */ +const failuresToDefects = (cause: Cause.Cause): Cause.Cause => + Cause.fromReasons(cause.reasons.map((reason) => + Cause.isFailReason(reason) + ? Cause.makeDieReason(reason.error).annotate(Cause.reasonAnnotations(reason)) + : reason + )) + /** * Builds a transaction wrapper that begins top-level transactions, uses * savepoints for nested transactions, commits on success, and rolls back on @@ -424,15 +446,19 @@ export const makeWithTransaction = (options: { ) ), (exit) => { - let effect: Effect.Effect + let effect: Effect.Effect if (Exit.isSuccess(exit)) { if (id === 0) { span.event("effect.sql.transaction.commit", clock.currentTimeNanosUnsafe()) const onCommitFailure = options.onCommitFailure - effect = Effect.orDie(options.commit(conn)) - if (onCommitFailure) { - effect = Effect.onError(effect, () => Effect.orDie(onCommitFailure(conn))) - } + effect = onCommitFailure + ? Effect.catchCause(options.commit(conn), (commitCause) => + Effect.matchCauseEffect(onCommitFailure(conn), { + onFailure: (cleanupCause) => + Effect.failCause(failuresToDefects(Cause.combine(commitCause, cleanupCause))), + onSuccess: () => Effect.failCause(commitCause) + })) + : options.commit(conn) } else { span.event("effect.sql.transaction.savepoint", clock.currentTimeNanosUnsafe()) effect = Effect.void diff --git a/repos/effect/packages/effect/src/testing/TestClock.ts b/repos/effect/packages/effect/src/testing/TestClock.ts index d4a4951c88..95934b9dcc 100644 --- a/repos/effect/packages/effect/src/testing/TestClock.ts +++ b/repos/effect/packages/effect/src/testing/TestClock.ts @@ -13,14 +13,14 @@ */ import * as Arr from "../Array.ts" import * as Clock from "../Clock.ts" +import * as Context from "../Context.ts" import * as Data from "../Data.ts" import * as Duration from "../Duration.ts" import * as Effect from "../Effect.ts" import * as Fiber from "../Fiber.ts" -import { flow } from "../Function.ts" import * as Latch from "../Latch.ts" import * as Layer from "../Layer.ts" -import * as Order from "../Order.ts" +import * as Scheduler from "../Scheduler.ts" import * as Semaphore from "../Semaphore.ts" /** @@ -40,6 +40,9 @@ import * as Semaphore from "../Semaphore.ts" * the time is set to on or after the time they are scheduled to run. Fork the * effect being tested, then adjust the clock time, and finally verify that the * expected effects have been performed. + * The ordered execution of sleeps registered after multiple scheduler hops + * requires fibers running under {@link layer}; providing a clock from + * {@link make} by hand does not install the tracking scheduler. * * **Example** (Testing timeouts deterministically) * @@ -142,7 +145,8 @@ export declare namespace TestClock { /** * Options used when constructing a `TestClock`. `warningDelay` controls how * long the live clock waits before logging a warning when a test uses time - * without advancing the test clock. + * without advancing the test clock, or when a fiber woken by the test clock + * keeps running without suspending. * * **Example** (Configuring the warning delay) * @@ -170,7 +174,8 @@ export declare namespace TestClock { export interface Options { /** * The amount of time to wait before displaying a warning message when a - * test is using time but is not advancing the `TestClock`. + * test is using time but is not advancing the `TestClock`, or when a fiber + * woken by `adjust` or `setTime` keeps running without suspending. */ readonly warningDelay?: Duration.Input } @@ -197,15 +202,30 @@ const warningMessage = "A test is using time, but is not advancing the test " + "clock, which may result in the test hanging. Use TestClock.adjust to " + "manually advance the time." +/** + * The warning message that will be displayed if a fiber woken by the + * `TestClock` does not suspend within the warning delay. + */ +const busyWarningMessage = "A fiber woken by the test clock is still running " + + "without suspending, so the test clock stopped waiting for it. Sleeps it " + + "starts later may be scheduled relative to a later time." + +/** + * The live clock of each `TestClock`, so a `TestClock` constructed while + * another one is the current clock uses the outer clock's live clock instead + * of the outer `TestClock`, which only advances when adjusted. + */ +const liveClocks = new WeakMap() + +interface WakeTracker { + pending: number + onIdle: (() => void) | undefined +} + const defaultOptions: Required = { warningDelay: "1 second" } -const SleepOrder = Order.flip(Order.Struct({ - timestamp: Order.Number, - sequence: Order.Number -})) - const nanosPerMilli = BigInt(1_000_000) const millisToNanos = (millis: number): bigint => { @@ -217,6 +237,14 @@ const millisToNanos = (millis: number): bigint => { /** * Creates a `TestClock` with optional configuration. * + * **Gotchas** + * + * The guarantee that sleeps registered after multiple scheduler hops run in + * order applies only to fibers running under {@link layer}, which + * `@effect/vitest`'s `it.effect` uses. Providing a clock from `make` by hand + * waits only one scheduler turn after each woken sleep. Prefer `layer` when + * forked fibers sleep. + * * **Example** (Creating a test clock) * * ```ts import.meta.vitest @@ -245,18 +273,21 @@ const millisToNanos = (millis: number): bigint => { * @category constructors * @since 4.0.0 */ -export const make = Effect.fnUntraced(function*( +export const make = (options?: TestClock.Options) => Effect.map(makeWithScheduler(options), ([testClock]) => testClock) + +const makeWithScheduler = Effect.fnUntraced(function*( options?: TestClock.Options ) { const config = { ...defaultOptions, ...options } - let sequence = 0 + // Sorted by descending timestamp, so `pop` wakes the earliest sleep first const sleeps: Array<{ - readonly sequence: number readonly timestamp: number readonly latch: Latch.Latch }> = [] - const liveClock = yield* Clock.clockWith(Effect.succeed) + const currentClock = yield* Clock.clockWith(Effect.succeed) + const liveClock = liveClocks.get(currentClock) ?? currentClock const warningSemaphore = yield* Semaphore.make(1) + const parentScheduler = yield* Scheduler.Scheduler let currentTimestamp: number = new Date(0).getTime() let currentWallNanos = BigInt(0) @@ -332,17 +363,97 @@ export const make = Effect.fnUntraced(function*( const millis = Duration.toMillis(duration) const end = currentTimestamp + millis if (end <= currentTimestamp) return - const latch = Latch.makeUnsafe() - sleeps.push({ - sequence: sequence++, - timestamp: end, - latch - }) - sleeps.sort(SleepOrder) - yield* warningStart - yield* latch.await + yield* Effect.acquireUseRelease( + Effect.sync(() => { + const entry = { timestamp: end, latch: Latch.makeUnsafe() } + // Insert before entries with an equal timestamp, so they wake in + // registration order + let low = 0 + let high = sleeps.length + while (low < high) { + const mid = (low + high) >>> 1 + if (sleeps[mid].timestamp > end) low = mid + 1 + else high = mid + } + sleeps.splice(low, 0, entry) + return entry + }), + (entry) => Effect.andThen(warningStart, entry.latch.await), + (entry) => + Effect.sync(() => { + // The entry is already gone if `run` popped it + const index = sleeps.indexOf(entry) + if (index !== -1) sleeps.splice(index, 1) + }) + ) }) + /** + * Tasks scheduled while waking a sleeper, and tasks scheduled by those tasks, + * are counted by that wake's tracker so `run` can wait for the woken fiber, + * and any fibers it resumes or forks, to suspend before checking the next + * sleep. + */ + let currentTracker: WakeTracker | undefined = undefined + + function runTracked(tracker: WakeTracker, f: () => void): void { + const previous = currentTracker + currentTracker = tracker + try { + f() + } finally { + currentTracker = previous + } + } + + const scheduler: Scheduler.Scheduler = { + executionMode: parentScheduler.executionMode, + shouldYield: (fiber) => parentScheduler.shouldYield(fiber), + makeDispatcher() { + const dispatcher = parentScheduler.makeDispatcher() + return { + scheduleTask(task, priority) { + const tracker = currentTracker + if (tracker === undefined) { + return dispatcher.scheduleTask(task, priority) + } + tracker.pending++ + dispatcher.scheduleTask(() => { + try { + runTracked(tracker, task) + } finally { + if (--tracker.pending === 0) tracker.onIdle?.() + } + }, priority) + }, + flush() { + dispatcher.flush() + } + } + } + } + + const wake = (latch: Latch.Latch) => + Effect.suspend(() => { + const tracker: WakeTracker = { pending: 0, onIdle: undefined } + runTracked(tracker, () => latch.openUnsafe()) + if (tracker.pending === 0) return Effect.yieldNow + return Effect.callback((resume) => { + if (tracker.pending === 0) return resume(Effect.void) + tracker.onIdle = () => resume(Effect.void) + return Effect.sync(() => { + tracker.onIdle = undefined + }) + }).pipe( + Effect.timeoutOrElse({ + duration: config.warningDelay, + orElse: () => Effect.logWarning(busyWarningMessage) + }), + withLive, + Effect.andThen(Effect.yieldNow) + ) + }) + const runSemaphore = yield* Semaphore.make(1) const run = Effect.fnUntraced(function*( step: (currentTimestamp: number) => number, @@ -366,8 +477,7 @@ export const make = Effect.fnUntraced(function*( if (Arr.lastNonEmpty(sleeps).timestamp > endTimestamp) break const entry = sleeps.pop()! advanceTo(entry.timestamp) - entry.latch.openUnsafe() - yield* Effect.yieldNow + yield* wake(entry.latch) } advanceTo(endTimestamp) if (adjustmentNanos !== undefined && Number.isFinite(endTimestamp)) { @@ -391,7 +501,7 @@ export const make = Effect.fnUntraced(function*( yield* Effect.addFinalizer(() => warningDone) - return { + const testClock = { currentTimeMillisUnsafe, currentTimeNanosUnsafe, monotonicTimeNanosUnsafe, @@ -403,6 +513,8 @@ export const make = Effect.fnUntraced(function*( sleep, withLive } + liveClocks.set(testClock, liveClock) + return [testClock, scheduler] as const }) /** @@ -438,10 +550,13 @@ export const make = Effect.fnUntraced(function*( * @category layers * @since 4.0.0 */ -export const layer: (options?: TestClock.Options) => Layer.Layer = flow( - make, - Layer.effect(Clock.Clock) -) as any +export const layer = (options?: TestClock.Options): Layer.Layer => + Layer.effectContext( + Effect.map(makeWithScheduler(options), ([testClock, scheduler]) => + Context.make(Clock.Clock, testClock).pipe( + Context.add(Scheduler.Scheduler, scheduler) + )) + ) as any /** * Retrieves the `TestClock` service for this test and uses it to run the diff --git a/repos/effect/packages/effect/src/testing/TestCrypto.ts b/repos/effect/packages/effect/src/testing/TestCrypto.ts new file mode 100644 index 0000000000..99fe9ca621 --- /dev/null +++ b/repos/effect/packages/effect/src/testing/TestCrypto.ts @@ -0,0 +1,94 @@ +/** + * Provides a deterministic implementation of the Effect `Crypto` service for + * tests. + * + * Random bytes, numbers, shuffles, UUIDs, and ULIDs are derived from a seeded + * pseudo-random generator. Digest operations are delegated to an underlying + * platform `Crypto` service. + * + * @stability unstable + * @since 4.0.0 + */ +import * as Crypto from "../Crypto.ts" +import * as Effect from "../Effect.ts" +import * as Layer from "../Layer.ts" +import * as Random from "../Random.ts" + +/** + * Creates a deterministic `Crypto` service using a seeded pseudo-random + * generator. + * + * **When to use** + * + * Use to construct a `Crypto` service whose random operations are reproducible + * in tests while preserving the digest implementation of a platform `Crypto` + * service. + * + * **Details** + * + * The effect requires an existing `Crypto` service and delegates digest + * operations to it. Each evaluation starts a new random sequence from `seed`; + * every other random operation is derived from that sequence. + * + * **Gotchas** + * + * The generated values are deterministic and must not be used for + * security-sensitive purposes. The sequence depends on the order in which + * random operations are evaluated. UUIDv7 and ULID values also include the + * current `Clock` time, which must be controlled separately when their complete + * output needs to be reproducible. + * + * @see {@link layer} for providing the service as a layer + * + * @stability unstable + * @category constructors + * @since 4.0.0 + */ +export const make: ( + seed: string | number +) => Effect.Effect = Effect.fnUntraced( + function*(_seed: string | number) { + const crypto = yield* Crypto.Crypto + const seededRandom = yield* Random.Random + return Crypto.make({ + randomBytes: (size) => { + const bytes = new Uint8Array(size) + for (let i = 0; i < size; i++) { + bytes[i] = Math.floor(seededRandom.nextDoubleUnsafe() * 256) + } + return bytes + }, + digest: crypto.digest + }) + }, + (effect, seed) => Random.withSeed(effect, seed) +) + +/** + * Creates a layer that provides deterministic `Crypto` random operations from + * a seed. + * + * **When to use** + * + * Use to provide reproducible random bytes, numbers, shuffles, UUIDs, and ULIDs + * to an Effect program under test. + * + * **Details** + * + * The layer requires an existing platform `Crypto` service whose digest + * implementation is retained. Each layer build starts the random sequence from + * `seed`. + * + * **Gotchas** + * + * UUIDv7 and ULID values also depend on the current `Clock`. Provide a test + * clock when their complete output needs to be reproducible. + * + * @see {@link make} for constructing the service directly + * + * @stability unstable + * @category layers + * @since 4.0.0 + */ +export const layer = (seed: string | number): Layer.Layer => + Layer.effect(Crypto.Crypto, make(seed)) diff --git a/repos/effect/packages/effect/src/testing/index.ts b/repos/effect/packages/effect/src/testing/index.ts index 12aca49b53..8f16634067 100644 --- a/repos/effect/packages/effect/src/testing/index.ts +++ b/repos/effect/packages/effect/src/testing/index.ts @@ -17,6 +17,12 @@ export * as TestClock from "./TestClock.ts" */ export * as TestConsole from "./TestConsole.ts" +/** + * @stability unstable + * @since 4.0.0 + */ +export * as TestCrypto from "./TestCrypto.ts" + /** * @stability unstable * @since 4.0.0 diff --git a/repos/effect/packages/effect/src/workflow/Activity.ts b/repos/effect/packages/effect/src/workflow/Activity.ts index fb883b8ced..fbd0237887 100644 --- a/repos/effect/packages/effect/src/workflow/Activity.ts +++ b/repos/effect/packages/effect/src/workflow/Activity.ts @@ -336,6 +336,7 @@ const makeExecute = Effect.fnUntraced(function*< (_) => _._tag === "Suspended" ) if (result._tag === "Suspended") { + if (result.failed) instance.failed = true return yield* Workflow.suspend(instance) } return yield* result.exit diff --git a/repos/effect/packages/effect/src/workflow/DurableDeferred.ts b/repos/effect/packages/effect/src/workflow/DurableDeferred.ts index d3c48698c6..61742708a8 100644 --- a/repos/effect/packages/effect/src/workflow/DurableDeferred.ts +++ b/repos/effect/packages/effect/src/workflow/DurableDeferred.ts @@ -10,7 +10,6 @@ * @stability unstable * @since 4.0.0 */ -import * as Arr from "../Array.ts" import type { NonEmptyReadonlyArray } from "../Array.ts" import type * as Brand from "../Brand.ts" import * as Cause from "../Cause.ts" @@ -18,8 +17,9 @@ import * as Context from "../Context.ts" import * as Effect from "../Effect.ts" import * as Base64Url from "../encoding/Base64Url.ts" import * as Exit from "../Exit.ts" -import * as Filter from "../Filter.ts" +import * as Fiber from "../Fiber.ts" import { dual } from "../Function.ts" +import * as Latch from "../Latch.ts" import * as Option from "../Option.ts" import * as Schema from "../Schema.ts" import * as SchemaGetter from "../SchemaGetter.ts" @@ -134,6 +134,25 @@ const CurrentAttempt = Context.Reference( { defaultValue: () => 1 } ) +/** Awaits registered under the instance copy of a `recordHeld` body. */ +const awaitOwners = new WeakMap>() + +const registerAwait = (instance: WorkflowInstance["Service"], name: string) => { + instance.awaitedDeferreds.set(name, (instance.awaitedDeferreds.get(name) ?? 0) + 1) + awaitOwners.get(instance)?.push(name) +} + +const releaseAwaits = (instance: WorkflowInstance["Service"], names: Array) => { + for (const name of names) { + const count = instance.awaitedDeferreds.get(name)! - 1 + if (count === 0) { + instance.awaitedDeferreds.delete(name) + } else { + instance.awaitedDeferreds.set(name, count) + } + } +} + const await_: ( self: DurableDeferred ) => Effect.Effect< @@ -150,7 +169,7 @@ const await_: => - Effect.contextWith( - (context: Context.Context) => { - const engine = Context.get(context, EngineTag) - const parentInstance = Context.get(context, InstanceTag) - const instance = { ...parentInstance } - return Effect.onExit( - Effect.provideService(effect, InstanceTag, instance), - Effect.fnUntraced(function*(exit) { - if (Exit.isFailure(exit)) { - const [interrupts, reasons] = Arr.partition( - exit.cause.reasons, - Filter.fromPredicate(Cause.isInterruptReason) - ) - if (interrupts.length === exit.cause.reasons.length) { - // An interrupt-only exit is never a result: the effect was - // suspended, preempted or interrupted, so record nothing. - if (instance.suspended) { - parentInstance.suspended = true - } - return - } else if (interrupts.length > 0) { - exit = Exit.failCause(Cause.fromReasons(reasons)) - } + > => recordHeld(effect, self, false) +) + +/** + * Records `exit` into `self`. An interrupt-only exit is never a result: the + * effect was suspended, preempted or interrupted, so nothing is recorded. + * Interrupts mixed into a failure are dropped from the recorded cause. + */ +const recordExit = ( + engine: WorkflowEngine["Service"], + instance: WorkflowInstance["Service"], + self: DurableDeferred, + exit: Exit.Exit +) => { + if (Exit.isFailure(exit)) { + if (Cause.hasInterruptsOnly(exit.cause)) return Effect.void + if (Cause.hasInterrupts(exit.cause)) { + exit = Exit.failCause(Cause.fromReasons( + exit.cause.reasons.filter((reason) => !Cause.isInterruptReason(reason)) + )) + } + } + return engine.deferredDone(self, { + workflowName: instance.workflow._tag, + executionId: instance.executionId, + deferredName: self.name, + exit + }) +} + +/** + * Runs `effect` as one activity of the enclosing workflow and records its exit + * into `self`, returning a previously recorded exit instead when `checkCache` + * is set. The hold spans the lookup, `effect` and the write, so a parked + * sibling cannot suspend the run before the continuation starts. + */ +const recordHeld = Effect.fnUntraced(function*( + effect: Effect.Effect, + self: DurableDeferred, + checkCache: boolean +): Effect.fn.Return { + const engine = yield* EngineTag + const instance = yield* InstanceTag + const exit = yield* Workflow.wrapActivityResult( + Effect.gen(function*() { + if (checkCache) { + const cached = yield* engine.deferredResult(self) + if (Option.isSome(cached)) return cached + } + // `effect` counts on its own activity state, so a durable await inside + // it waits for its own siblings and not for the hold above. The copy + // starts unsuspended: a parked arm of an enclosing race leaves that + // copy marked suspended while only interrupting its own fiber. + const local: WorkflowInstance["Service"] = { + ...instance, + suspended: false, + activityState: { count: 0, latch: Latch.makeUnsafe() } + } + // A losing branch parked on a durable wait has already exited when the + // race settles, so this body owns the waits registered beneath it. + const owned: Array = [] + awaitOwners.set(local, owned) + // A parked `effect` interrupts the fiber it runs on. The child fiber + // keeps that from skipping the suspension handling below. + const fiber = yield* effect.pipe( + Effect.provideService(InstanceTag, local), + Effect.onExit((exit) => recordExit(engine, instance, self, exit)), + Effect.forkChild({ startImmediately: true }) + ) + return yield* Effect.onInterrupt(Fiber.await(fiber), () => Fiber.interrupt(fiber)).pipe( + Effect.map((exit) => + local.suspended && Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause) + ? Option.none() + : Option.some(exit) + ), + // The waits are over once the body has a result. Otherwise every branch + // parked, or an enclosing race interrupted the body, and the waits move + // to the enclosing owner, if any, to be released when that race settles. + Effect.onExit((result) => + Effect.sync(() => { + if (Exit.isSuccess(result) && Option.isSome(result.value)) { + releaseAwaits(instance, owned) + } else { + awaitOwners.get(instance)?.push(...owned) } - yield* engine.deferredDone(self, { - workflowName: instance.workflow._tag, - executionId: instance.executionId, - deferredName: self.name, - exit - }) }) ) - } - ) -) + ) + }), + // Every branch of `effect` parked: release the hold and let the enclosing + // activities finish before suspending. External preemption does not wait. + Option.isNone + ) + if (Option.isNone(exit)) { + return yield* Workflow.suspend(instance) + } + return yield* exit.value +}) /** * Runs effects as a durable race, returning a previously persisted result when @@ -298,17 +393,7 @@ export const raceAll = < success: options.success, error: options.error }) - return Effect.gen(function*() { - const engine = yield* EngineTag - const exit = yield* engine.deferredResult(deferred) - if (Option.isSome(exit)) { - return yield* exit.value - } - return yield* into( - Effect.raceAll(options.effects), - deferred - ) - }) + return recordHeld(Effect.raceAll(options.effects), deferred, true) } /** diff --git a/repos/effect/packages/effect/src/workflow/Workflow.ts b/repos/effect/packages/effect/src/workflow/Workflow.ts index 9cc8f8ffc3..43dec17496 100644 --- a/repos/effect/packages/effect/src/workflow/Workflow.ts +++ b/repos/effect/packages/effect/src/workflow/Workflow.ts @@ -78,11 +78,26 @@ export interface Workflow< /** * Execute the workflow with the given payload. + * + * **Details** + * + * `discard: true` returns the execution ID without waiting for the result. + * The child remains linked to its parent for completion wakes and interruption. + * + * With `discard: true, detached: true`, the child neither wakes its parent + * nor gets interrupted with it. The cluster engine retains the parent for + * observability. + * + * **Gotchas** + * + * Do not await a detached execution later. Executing the same payload joins + * it, but its completion will not wake the awaiting workflow. */ readonly execute: ( payload: Payload["~type.make.in"], options?: { readonly discard?: Discard + readonly detached?: [Discard] extends [true] ? boolean | undefined : undefined } ) => Effect.Effect< Discard extends true ? string : Success["Type"], @@ -248,7 +263,7 @@ export interface AnyWithProps extends Any { readonly errorSchema: Schema.Top readonly execute: ( payload: any, - options?: { readonly discard?: boolean } + options?: { readonly discard?: boolean; readonly detached?: boolean | undefined } ) => Effect.Effect readonly resume: ( executionId: string @@ -352,7 +367,7 @@ const Proto = { execute( this: AnyWithProps, fields: any, - opts?: { readonly discard?: Discard } | undefined + opts?: { readonly discard?: Discard; readonly detached?: boolean | undefined } | undefined ) { return Effect.suspend(() => { const payload = this.payloadSchema.make(fields) @@ -366,6 +381,7 @@ const Proto = { executionId, payload, discard: opts?.discard, + detached: opts?.detached, suspendedRetrySchedule: this.suspendedRetrySchedule }) )) @@ -617,6 +633,11 @@ export class Complete extends Data.TaggedClass("Complete")<{ * Represents a suspended workflow execution, optionally carrying the cause that * triggered suspension. * + * **Details** + * + * `failed` marks this execution's own `SuspendOnFailure` and requires explicit + * `resume` or `interrupt`. Inherited child failures do not set it. + * * @stability unstable * @category schemas * @since 4.0.0 @@ -625,7 +646,8 @@ export class Suspended extends Schema.Class( "effect/workflow/Workflow/Suspended" )({ _tag: Schema.tag("Suspended"), - cause: Schema.optional(Schema.Cause(Schema.Never, Schema.Defect())) + cause: Schema.optional(Schema.Cause(Schema.Never, Schema.Defect())), + failed: Schema.optional(Schema.Boolean) }) { /** * Marks this value as a workflow result for runtime guards. @@ -697,11 +719,13 @@ export const intoResult = ( Effect.interruptible, suspendOnFailure ? Effect.catchCause((cause) => { - if (instance.abandoned) { + if (instance.abandoned || instance.interrupted) { return Effect.failCause(cause) } instance.suspended = true + // Ordinary suspension is a self-interrupt and also reaches here. if (!Cause.hasInterruptsOnly(cause)) { + instance.failed = true instance.cause = Cause.die(Cause.squash(cause)) } return Effect.interrupt @@ -720,7 +744,9 @@ export const intoResult = ( const abandoned = instance.abandoned && !instance.interrupted && hasInterruptsOnly instance.abandoned = abandoned if (instance.suspended && hasInterruptsOnly && !abandoned) { - return Effect.succeed(new Suspended({ cause: instance.cause })) + return Effect.succeed( + new Suspended(instance.failed ? { cause: instance.cause, failed: true } : { cause: instance.cause }) + ) } if (!instance.interrupted && hasInterruptsOnly) { // External interrupts exit without a result. When the cluster has diff --git a/repos/effect/packages/effect/src/workflow/WorkflowEngine.ts b/repos/effect/packages/effect/src/workflow/WorkflowEngine.ts index 288499f3cc..6254362750 100644 --- a/repos/effect/packages/effect/src/workflow/WorkflowEngine.ts +++ b/repos/effect/packages/effect/src/workflow/WorkflowEngine.ts @@ -12,6 +12,7 @@ */ import * as Cause from "../Cause.ts" import * as Context from "../Context.ts" +import * as Deferred from "../Deferred.ts" import * as Effect from "../Effect.ts" import * as Exit from "../Exit.ts" import * as Fiber from "../Fiber.ts" @@ -75,6 +76,17 @@ export class WorkflowEngine extends Context.Service< /** * Execute a registered workflow. + * + * **Details** + * + * Unless `discard` is set, a caller outside any workflow waits for the + * result. While the execution is suspended, the caller retries on + * `suspendedRetrySchedule`; engines that observe the final result wake it + * sooner. `ClusterWorkflowEngine` does so only for callers on the runner + * that owns the execution. + * + * `detached: true` requires `discard: true` and skips parent completion + * wakes and interruption linkage. Otherwise, it is a defect. */ readonly execute: < Name extends string, @@ -88,6 +100,7 @@ export class WorkflowEngine extends Context.Service< readonly executionId: string readonly payload: Payload["Type"] readonly discard?: Discard | undefined + readonly detached?: boolean | undefined readonly suspendedRetrySchedule?: | Schedule.Schedule | undefined @@ -271,8 +284,17 @@ export class WorkflowInstance extends Context.Service< */ cause: Cause.Cause | undefined - /** Deferred names this run parked on; their completions preempt the run. */ - readonly awaitedDeferreds: Set + /** + * Whether this workflow or an activity hit `SuspendOnFailure`, excluding + * inherited child failures. + */ + failed: boolean + + /** + * Deferred names this run waits on, counted per live wait; their + * completions preempt the run. + */ + readonly awaitedDeferreds: Map /** Deferred names this run completed itself; their completions need not wake it. */ readonly completedDeferreds: Set @@ -286,17 +308,26 @@ export class WorkflowInstance extends Context.Service< static initial( workflow: Workflow.Any, executionId: string, - scope = Scope.makeUnsafe() + options?: { + readonly scope?: Scope.Closeable | undefined + /** + * Awaited deferred names shared with the run this instance belongs to. + * An activity instance registers its durable waits there so the run + * can be woken once it suspends, without those waits preempting it. + */ + readonly awaitedDeferreds?: Map | undefined + } ): WorkflowInstance["Service"] { return WorkflowInstance.of({ executionId, workflow, - scope, + scope: options?.scope ?? Scope.makeUnsafe(), suspended: false, interrupted: false, abandoned: false, cause: undefined, - awaitedDeferreds: new Set(), + failed: false, + awaitedDeferreds: options?.awaitedDeferreds ?? new Map(), completedDeferreds: new Set(), activityState: { count: 0, @@ -394,6 +425,8 @@ export interface Encoded { readonly payload: object readonly discard: Discard readonly parent?: WorkflowInstance["Service"] | undefined + /** Skip parent completion wakes and interruption linkage. */ + readonly detached?: boolean | undefined } ) => Effect.Effect< Discard extends true ? void : Workflow.Result @@ -414,6 +447,22 @@ export interface Encoded { workflow: Workflow.Any, executionId: string ) => Effect.Effect + + /** + * Waits until a suspended execution has a result other than `Suspended`. + * + * **Gotchas** + * + * External callers race this with their `suspendedRetrySchedule`, so it may + * never complete when the engine cannot observe the result. Completing while + * the execution is still suspended skips the sleep and spends a step of that + * schedule. A hook that keeps completing early makes the caller spin. + */ + readonly awaitComplete?: ( + workflow: Workflow.Any, + executionId: string + ) => Effect.Effect + readonly activityExecute: ( activity: Activity.Any, attempt: number @@ -486,11 +535,15 @@ export const makeUnsafe = (options: Encoded): WorkflowEngine["Service"] => readonly executionId: string readonly payload: Payload["Type"] readonly discard?: Discard | undefined + readonly detached?: boolean | undefined readonly suspendedRetrySchedule?: | Schedule.Schedule | undefined } ) { + if (opts.detached && !opts.discard) { + return yield* Effect.die(`${self._tag}.execute: detached requires discard`) + } const payload = opts.payload const executionId = opts.executionId const suspendedRetrySchedule = opts.suspendedRetrySchedule ?? defaultRetrySchedule @@ -499,7 +552,7 @@ export const makeUnsafe = (options: Encoded): WorkflowEngine["Service"] => // link interruption with parent workflow const parentInstance = yield* Effect.serviceOption(WorkflowInstance) - if (Option.isSome(parentInstance)) { + if (Option.isSome(parentInstance) && !opts.detached) { const instance = parentInstance.value yield* Effect.addFinalizer(() => { if (!instance.interrupted || (Option.isSome(result) && result.value._tag === "Complete")) { @@ -512,7 +565,8 @@ export const makeUnsafe = (options: Encoded): WorkflowEngine["Service"] => executionId, payload: payload as object, discard: opts.discard ?? false, - parent: Option.getOrUndefined(parentInstance) + parent: Option.getOrUndefined(parentInstance), + detached: opts.detached }) as Effect.Effect> if (opts.discard) { @@ -548,7 +602,10 @@ export const makeUnsafe = (options: Encoded): WorkflowEngine["Service"] => ) ) ) - yield* sleep + // Completion wakes the caller early; the schedule is the fallback. + yield* options.awaitComplete + ? Effect.raceFirst(sleep, options.awaitComplete(self, executionId)) + : sleep } }), poll: options.poll, @@ -644,6 +701,11 @@ const defaultRetrySchedule = Schedule.min([ Schedule.spaced(30000) ]) +type WakeMode = "explicit" | "automatic" + +const isUnwakeable = (result: Workflow.Result, mode: WakeMode) => + result._tag === "Complete" || (mode === "automatic" && result.failed === true) + /** * Layer that provides an in-memory `WorkflowEngine`. * @@ -683,8 +745,11 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng readonly parent: string | undefined instance: WorkflowInstance["Service"] interrupted: boolean - resumeRequested: boolean + // The strongest wake requested while a run was still finishing. + resumeRequested: WakeMode | undefined fiber: Fiber.Fiber> | undefined + // Completed once a run succeeds with `Complete`, after which it cannot resume. + readonly done: Deferred.Deferred } const executions = new Map() @@ -695,21 +760,22 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng const deferredState = makeDeferredState() - const resume = Effect.fnUntraced(function*(executionId: string): Effect.fn.Return { + const resume = Effect.fnUntraced(function*(executionId: string, mode: WakeMode): Effect.fn.Return { const state = executions.get(executionId) if (!state) return const exit = state.fiber?.pollUnsafe() - if (exit && exit._tag === "Success" && exit.value._tag === "Complete") { + if (exit && exit._tag === "Success" && isUnwakeable(exit.value, mode)) { return } else if (state.fiber && !exit) { - // A child can finish while the parent is still releasing its activity. - // Preserve the wake until that run has published its suspended result. - if (!state.resumeRequested) { - state.resumeRequested = true + // Queue wakes until the run finishes cleanup; explicit wakes take priority. + const requested = state.resumeRequested + state.resumeRequested = mode === "explicit" ? mode : requested ?? mode + if (requested === undefined) { yield* Fiber.await(state.fiber).pipe( Effect.flatMap(() => { - state.resumeRequested = false - return resume(executionId) + const mode = state.resumeRequested! + state.resumeRequested = undefined + return resume(executionId, mode) }), Effect.forkIn(scope) ) @@ -721,7 +787,7 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng const instance = WorkflowInstance.initial( state.instance.workflow, state.instance.executionId, - state.instance.scope + { scope: state.instance.scope } ) state.instance = instance state.fiber = yield* state.execute(state.payload, state.instance.executionId).pipe( @@ -740,7 +806,12 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng if (!state.parent || result._tag !== "Complete") { return Effect.void } - return Effect.forkIn(resume(state.parent), scope) + return Effect.forkIn(resume(state.parent, "automatic"), scope) + }), + Effect.onExit((exit) => { + return Exit.isSuccess(exit) && exit.value._tag === "Complete" + ? Deferred.succeed(state.done, void 0) + : Effect.void }), Effect.forkIn(entry.scope) ) @@ -771,12 +842,13 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng execute: entry.execute, instance: WorkflowInstance.initial(workflow, options.executionId), interrupted: false, - resumeRequested: false, + resumeRequested: undefined, fiber: undefined, - parent: options.parent?.executionId + done: Deferred.makeUnsafe(), + parent: options.detached ? undefined : options.parent?.executionId } executions.set(options.executionId, state) - yield* resume(options.executionId) + yield* resume(options.executionId, "explicit") } if (options.discard) return // Capture together so a wake that swaps in a replay cannot desync them. @@ -788,11 +860,16 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng } return (yield* exit) as any }), + awaitComplete: (_workflow, executionId) => + Effect.suspend(() => { + const state = executions.get(executionId) + return state ? Deferred.await(state.done) : Effect.never + }), interrupt: Effect.fnUntraced(function*(_workflow, executionId) { const state = executions.get(executionId) if (!state) return state.interrupted = true - yield* resume(executionId) + yield* resume(executionId, "explicit") }), interruptUnsafe: Effect.fnUntraced(function*(_workflow, executionId) { const state = executions.get(executionId) @@ -803,7 +880,7 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng } }), resume(_workflow, executionId) { - return resume(executionId) + return resume(executionId, "explicit") }, activityExecute: Effect.fnUntraced(function*(activity, attempt) { const instance = yield* WorkflowInstance @@ -820,13 +897,19 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng state = { exit: undefined } activities.set(activityId, state) } + // A pending interrupt replays only to rebuild compensations, so it must + // not run new activities. Finalizers run once `interrupted` is set. + if (executions.get(instance.executionId)?.interrupted && !instance.interrupted) { + return new Workflow.Suspended({}) + } const activityInstance = WorkflowInstance.initial(instance.workflow, instance.executionId) activityInstance.interrupted = instance.interrupted return yield* activity.executeEncoded.pipe( Workflow.intoResult, Effect.provideService(WorkflowInstance, activityInstance), Effect.onExit((exit) => { - state.exit = exit + // A preempted activity must run again on the next replay. + state.exit = Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause) ? undefined : exit return Effect.void }) ) @@ -857,7 +940,7 @@ export const layerMemory: Layer.Layer = Layer.effect(WorkflowEng deferredResults.set(id, options.exit) const wake = Effect.andThen( deferredState.deferredDone(options.executionId, options.deferredName), - resume(options.executionId) + resume(options.executionId, "automatic") ) return Effect.flatMap(Effect.serviceOption(WorkflowInstance), (instance) => // A workflow finalizer cannot wait for its own run's cleanup. diff --git a/repos/effect/packages/effect/test/Channel.test.ts b/repos/effect/packages/effect/test/Channel.test.ts index a005b99ab2..4144e9324b 100644 --- a/repos/effect/packages/effect/test/Channel.test.ts +++ b/repos/effect/packages/effect/test/Channel.test.ts @@ -33,6 +33,26 @@ describe("Channel", () => { }) describe("constructors", () => { + it.live("fromAsyncIterable awaits idle iterator cleanup on early close", () => + Effect.gen(function*() { + let finalized = false + async function* source() { + try { + yield [1] as const + yield [2] as const + } finally { + await new Promise((resolve) => setTimeout(resolve, 10)) + finalized = true + } + } + yield* Channel.fromAsyncIterable(source(), (error) => error).pipe( + Stream.fromChannel, + Stream.take(1), + Stream.runDrain + ) + assert.strictEqual(finalized, true) + })) + for ( const [name, constructor] of [["callback", Channel.callback], ["callbackArray", Channel.callbackArray]] as const ) { diff --git a/repos/effect/packages/effect/test/ConfigProvider.test.ts b/repos/effect/packages/effect/test/ConfigProvider.test.ts index e8f7d80f99..8fbb180844 100644 --- a/repos/effect/packages/effect/test/ConfigProvider.test.ts +++ b/repos/effect/packages/effect/test/ConfigProvider.test.ts @@ -851,10 +851,12 @@ DB_PASS=\${PASSWORD} ` SOURCE=a$&b$'c$\`d TARGET=\${SOURCE} +ESCAPED=\\$SOURCE/$SOURCE `, { expandVariables: true } ) await assertSuccess(provider, ["TARGET"], ConfigProvider.makeValue("a$&b$'c$`d")) + await assertSuccess(provider, ["ESCAPED"], ConfigProvider.makeValue("$SOURCE/a$&b$'c$`d")) }) it("expansion defaults are used only for empty or unset variables", async () => { @@ -862,15 +864,21 @@ TARGET=\${SOURCE} ` SET=actual EMPTY= +EXPANDS_EMPTY=$EMPTY +BRACED=a}b FROM_SET=\${SET:-fallback} FROM_EMPTY=\${EMPTY:-fallback} FROM_UNSET=\${UNSET:-fallback} +FROM_EXPANDS_EMPTY=\${EXPANDS_EMPTY:-fallback} +NESTED=\${UNSET:-\${BRACED}} `, { expandVariables: true } ) await assertSuccess(provider, ["FROM_SET"], ConfigProvider.makeValue("actual")) await assertSuccess(provider, ["FROM_EMPTY"], ConfigProvider.makeValue("fallback")) await assertSuccess(provider, ["FROM_UNSET"], ConfigProvider.makeValue("fallback")) + await assertSuccess(provider, ["FROM_EXPANDS_EMPTY"], ConfigProvider.makeValue("fallback")) + await assertSuccess(provider, ["NESTED"], ConfigProvider.makeValue("a}b")) }) it("does not expand missing inherited variables", async () => { @@ -879,6 +887,45 @@ FROM_UNSET=\${UNSET:-fallback} }) await assertMissing(provider, ["VALUE"]) }) + + it("expands self and circular references to empty values", async () => { + const provider = ConfigProvider.fromDotEnvContents( + ` +PATH=$PATH:/opt/bin +A=$B +B=$A +SELF_DEFAULT=\${SELF_DEFAULT:-fallback} +`, + { expandVariables: true } + ) + await assertSuccess(provider, ["PATH"], ConfigProvider.makeValue(":/opt/bin")) + await assertMissing(provider, ["A"]) + await assertSuccess(provider, ["SELF_DEFAULT"], ConfigProvider.makeValue("fallback")) + }) + + it("does not scan expanded text again", async () => { + const provider = ConfigProvider.fromDotEnvContents( + ` +USER=app +HOME_DIR=/home/$USER +LOG_DIR=\${HOME_DIR}_logs +NAME=$USER\${SUFFIX:-_v1} +LITERAL=$USER/$ +`, + { expandVariables: true } + ) + await assertSuccess(provider, ["LOG_DIR"], ConfigProvider.makeValue("/home/app_logs")) + await assertSuccess(provider, ["NAME"], ConfigProvider.makeValue("app_v1")) + await assertSuccess(provider, ["LITERAL"], ConfigProvider.makeValue("app/$")) + }) + + it("expands long sequences of adjacent references without overflowing", async () => { + const provider = ConfigProvider.fromDotEnvContents( + `A=a\nVALUE=${"$A".repeat(20_000)}`, + { expandVariables: true } + ) + await assertSuccess(provider, ["VALUE"], ConfigProvider.makeValue("a".repeat(20_000))) + }) }) describe("fromDotEnv", () => { diff --git a/repos/effect/packages/effect/test/Context.test.ts b/repos/effect/packages/effect/test/Context.test.ts index 19695642cc..90e8621e7b 100644 --- a/repos/effect/packages/effect/test/Context.test.ts +++ b/repos/effect/packages/effect/test/Context.test.ts @@ -5,6 +5,10 @@ import * as Option from "effect/Option" import * as Redactable from "effect/Redactable" import { describe, it } from "vitest" +interface ContextInternals { + readonly _flat: unknown +} + describe("Context", () => { const A = Context.Service("ContextTest/A") const B = Context.Service("ContextTest/B") @@ -98,19 +102,21 @@ describe("Context", () => { }) it("distinguishes an undefined service from an absent service", () => { - const Undefined = Context.Service("ContextTest/Undefined", { fiberCached: true }) + const Undefined = Context.Service("ContextTest/Undefined", { fiberCached: true }) const Missing = Context.Service("ContextTest/Missing") const Ref = Context.Reference("ContextTest/UndefinedRef", { defaultValue: () => "default", fiberCached: true }) - const context = Context.make(Undefined, undefined).pipe(Context.add(Ref, undefined)) + const context = Context.make(Undefined, 1).pipe(Context.add(Undefined, undefined), Context.add(Ref, undefined)) assertTrue(Context.getOption(context, Undefined)._tag === "Some") assertTrue(Context.getOption(context, Missing)._tag === "None") strictEqual(Context.getUnsafe(context, Undefined), undefined) strictEqual(Context.getOrElse(context, Undefined, () => 1), undefined) deepStrictEqual(Context.getOption(context, Ref), Option.some(undefined)) + deepStrictEqual([...Context.pick(Undefined)(context).mapUnsafe], [[Undefined.key, undefined]]) + deepStrictEqual([...Context.pick(Missing)(context).mapUnsafe], []) strictEqual(Context.get(context, Ref), undefined) }) @@ -130,6 +136,50 @@ describe("Context", () => { assertTrue(Context.hasSameCache(Context.empty(), context)) }) + it("rebases a shadowing overlay chain from a cold or warm parent", () => { + const keys = Array.from({ length: 8 }, (_, i) => Context.Service(`ContextTest/Rebase${i}`)) + const base = Context.make(A, 1).pipe(Context.add(B, 2)) + const flat = Context.makeUnsafe(new Map(base.mapUnsafe)) + // Build a depth-8 chain so the next add rebases. + let parent = Context.add(flat, A, 10) + for (let i = 0; i < 7; i++) { + parent = Context.add(parent, keys[i], i) + } + const expected = [[A.key, 10], [B.key, 2], ...keys.slice(0, 7).map((key, i) => [key.key, i]), [C.key, 3]] + + const cold = Context.add(parent, C, 3) + deepStrictEqual([...cold.mapUnsafe], expected) + + const parentEntries = [...parent.mapUnsafe] + const warm = Context.add(parent, C, 3) + deepStrictEqual([...warm.mapUnsafe], expected) + deepStrictEqual([...parent.mapUnsafe], parentEntries) + strictEqual(Context.getOption(parent, C)._tag, "None") + }) + + it("rebases a large base without warming the pre-rebase context's flat cache", () => { + const baseSize = 50 + const baseKeys = Array.from({ length: baseSize }, (_, i) => Context.Service(`ContextTest/Rebase${i}`)) + const base = Context.makeUnsafe(new Map(baseKeys.map((key, i) => [key.key, i]))) + const pushKeys = Array.from({ length: 9 }, (_, i) => Context.Service(`ContextTest/Push${i}`)) + + let preRebase: Context.Context = base + for (let i = 0; i < pushKeys.length - 1; i++) { + preRebase = Context.add(preRebase, pushKeys[i], i) + } + const context = Context.add(preRebase, pushKeys[pushKeys.length - 1], pushKeys.length - 1) + + strictEqual((preRebase as any as ContextInternals)._flat, undefined) + + strictEqual(context.mapUnsafe.size, baseSize + pushKeys.length) + for (let i = 0; i < baseKeys.length; i++) { + strictEqual(Context.getUnsafe(context, baseKeys[i]), i) + } + for (let i = 0; i < pushKeys.length; i++) { + strictEqual(Context.getUnsafe(context, pushKeys[i]), i) + } + }) + it("flattens after repeated base fall-throughs", () => { const context = Context.make(A, 1).pipe(Context.add(B, 2)) const impl = context as any @@ -214,9 +264,20 @@ describe("Context", () => { deepStrictEqual([...merged.mapUnsafe], [[A.key, 3], [B.key, 2], [C.key, 4]]) }) - it("pick and omit retain source ordering", () => { - const source = Context.make(A, 1).pipe(Context.add(B, 2), Context.add(C, 3)) + it("pick and omit preserve services and source ordering", () => { + const source = Context.make(A, 1).pipe(Context.add(B, 2), Context.add(C, 0), Context.add(C, 3)) + const impl = source as any as ContextInternals + strictEqual(impl._flat, undefined) + const empty = Context.pick()(source) + strictEqual(impl._flat, undefined) + const picked = Context.pick(C)(source) + strictEqual(impl._flat, undefined) + deepStrictEqual([...picked.mapUnsafe], [[C.key, 3]]) + deepStrictEqual([...empty.mapUnsafe], []) + assertFalse(Context.hasSameCache(source, picked)) + assertFalse(Context.hasSameCache(source, empty)) + deepStrictEqual([...source.mapUnsafe], [[A.key, 1], [B.key, 2], [C.key, 3]]) deepStrictEqual([...Context.pick(C, A)(source).mapUnsafe], [[A.key, 1], [C.key, 3]]) deepStrictEqual([...Context.omit(B)(source).mapUnsafe], [[A.key, 1], [C.key, 3]]) }) @@ -230,6 +291,7 @@ describe("Context", () => { } }) const context = Context.empty() + deepStrictEqual([...Context.pick(Ref)(context).mapUnsafe], []) strictEqual(calls, 0) const first = Context.get(context, Ref) diff --git a/repos/effect/packages/effect/test/Crypto.test.ts b/repos/effect/packages/effect/test/Crypto.test.ts index 109aad9d8d..0a76d7ee9c 100644 --- a/repos/effect/packages/effect/test/Crypto.test.ts +++ b/repos/effect/packages/effect/test/Crypto.test.ts @@ -96,16 +96,38 @@ describe("Crypto", () => { it.effect("randomUUIDv4 formats UUID bytes from randomBytes", () => Effect.gen(function*() { const crypto = yield* Crypto.Crypto - const uuid = yield* crypto.randomUUIDv4 + const uuid = yield* crypto.randomUUIDv4() assert.strictEqual(uuid, "00010203-0405-4607-8809-0a0b0c0d0e0f") + const hex = yield* crypto.randomUUIDv4({ format: "hex" }) + assert.strictEqual(hex, "00010203-0405-4607-8809-0a0b0c0d0e0f") }).pipe(Effect.provideService(Crypto.Crypto, testCrypto))) it.effect("randomUUIDv7 formats UUID bytes with the Clock timestamp", () => Effect.gen(function*() { yield* TestClock.setTime(0x0123456789ab) const crypto = yield* Crypto.Crypto - const uuid = yield* crypto.randomUUIDv7 + const uuid = yield* crypto.randomUUIDv7() assert.strictEqual(uuid, "01234567-89ab-7607-8809-0a0b0c0d0e0f") + const hex = yield* crypto.randomUUIDv7({ format: "hex" }) + assert.strictEqual(hex, "01234567-89ab-7607-8809-0a0b0c0d0e0f") + }).pipe(Effect.provideService(Crypto.Crypto, testCrypto))) + + it.effect("randomUUIDv4 returns 16 bytes with the version and variant bits set", () => + Effect.gen(function*() { + const crypto = yield* Crypto.Crypto + const bytes = yield* crypto.randomUUIDv4({ format: "bytes" }) + assert.deepStrictEqual(bytes, Uint8Array.of(0, 1, 2, 3, 4, 5, 0x46, 7, 0x88, 9, 10, 11, 12, 13, 14, 15)) + }).pipe(Effect.provideService(Crypto.Crypto, testCrypto))) + + it.effect("randomUUIDv7 returns 16 bytes containing the Clock timestamp, version and variant", () => + Effect.gen(function*() { + yield* TestClock.setTime(0x0123456789ab) + const crypto = yield* Crypto.Crypto + const bytes = yield* crypto.randomUUIDv7({ format: "bytes" }) + assert.deepStrictEqual( + bytes, + Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0x76, 7, 0x88, 9, 10, 11, 12, 13, 14, 15) + ) }).pipe(Effect.provideService(Crypto.Crypto, testCrypto))) it.effect("randomULID encodes the Clock timestamp and random bytes", () => diff --git a/repos/effect/packages/effect/test/DateTime.test.ts b/repos/effect/packages/effect/test/DateTime.test.ts index 30f975d8ea..01cec4da4d 100644 --- a/repos/effect/packages/effect/test/DateTime.test.ts +++ b/repos/effect/packages/effect/test/DateTime.test.ts @@ -105,6 +105,33 @@ describe("DateTime", () => { const future = Option.map(now, (value) => DateTime.add(value, { years: 1 })) assertSome(Option.map(future, DateTime.formatIso), "2025-02-28T00:00:00.000Z") })) + + it("clips fractional time units separately", () => { + strictEqual( + DateTime.toEpochMillis(DateTime.add(DateTime.makeUnsafe(1000), { milliseconds: 0.5, seconds: 0.0005 })), + 1000 + ) + }) + + it("adds and subtracts elapsed time in the repeated DST hour", () => { + const secondOneThirty = DateTime.makeZonedUnsafe("2025-11-02T06:30:00.000Z", { + timeZone: "America/New_York" + }) + strictEqual( + DateTime.formatIso(DateTime.add(secondOneThirty, { minutes: 1, seconds: 1, milliseconds: 1 })), + "2025-11-02T06:31:01.001Z" + ) + strictEqual(DateTime.formatIso(DateTime.subtract(secondOneThirty, { hours: 1 })), "2025-11-02T05:30:00.000Z") + }) + + it("adds elapsed hours before calendar days across DST", () => { + const beforeGap = DateTime.makeZonedUnsafe("2025-03-08T17:00:00.000Z", { + timeZone: "America/New_York" + }) + strictEqual(DateTime.formatIso(DateTime.add(beforeGap, { hours: 24 })), "2025-03-09T17:00:00.000Z") + strictEqual(DateTime.formatIso(DateTime.add(beforeGap, { days: 1 })), "2025-03-09T16:00:00.000Z") + strictEqual(DateTime.formatIso(DateTime.add(beforeGap, { days: 1, hours: 24 })), "2025-03-10T17:00:00.000Z") + }) }) describe("endOf", () => { @@ -498,6 +525,17 @@ describe("DateTime", () => { })) }) + describe("toDate", () => { + it("stores zoned wall-clock time in UTC fields", () => { + const zoned = DateTime.makeZonedUnsafe("2024-07-01T12:00:00Z", { + timeZone: "Europe/London" + }) + + strictEqual(DateTime.toDate(zoned).toISOString(), "2024-07-01T13:00:00.000Z") + strictEqual(DateTime.toDateUtc(zoned).toISOString(), "2024-07-01T12:00:00.000Z") + }) + }) + describe("nowAsDate", () => { it.effect("should return the current Date", () => Effect.gen(function*() { diff --git a/repos/effect/packages/effect/test/Duration.test.ts b/repos/effect/packages/effect/test/Duration.test.ts index e666f8708f..f0c969ad05 100644 --- a/repos/effect/packages/effect/test/Duration.test.ts +++ b/repos/effect/packages/effect/test/Duration.test.ts @@ -113,6 +113,11 @@ describe("Duration", () => { ) }) + it("fromInputUnsafe normalizes infinite nanosecond totals", () => { + deepStrictEqual(Duration.fromInputUnsafe([1e300, 1]), Duration.infinity) + deepStrictEqual(Duration.fromInputUnsafe({ seconds: -Infinity, nanoseconds: 1 }), Duration.negativeInfinity) + }) + it("fromInput", () => { const millis100 = Duration.millis(100) assertSome(Duration.fromInput(millis100), millis100) @@ -240,6 +245,7 @@ describe("Duration", () => { assertFalse(Equal.equals(Duration.infinity, Duration.negativeInfinity)) assertTrue(HashSet.has(HashSet.make(millisTagged), nanosTagged)) + assertTrue(Equal.equals(Duration.millis(2 ** 1023), Duration.nanos(1_000_000n << 1023n))) }) it("Hash.symbol handles finite millis too large to convert to nanos", () => { @@ -345,6 +351,18 @@ describe("Duration", () => { it("times", () => { deepStrictEqual(Duration.times(Duration.seconds(1), 60), Duration.minutes(1)) deepStrictEqual(Duration.times(Duration.nanos(2n), 10), Duration.nanos(20n)) + deepStrictEqual(Duration.times(Duration.nanos(3n), 1.5), Duration.nanos(5n)) + deepStrictEqual( + Duration.times(Duration.nanos(5_000_000n), 0.0000003), + Duration.times(Duration.millis(5), 0.0000003) + ) + deepStrictEqual(Duration.times(Duration.nanos(3n), -0.5), Duration.nanos(-2n)) + deepStrictEqual(Duration.times(Duration.nanos(9007199254740993n), 0.5), Duration.nanos(4503599627370497n)) + deepStrictEqual(Duration.times(Duration.nanos(9007199254740991n), 1.5), Duration.nanos(13510798882111487n)) + deepStrictEqual(Duration.times(Duration.nanos(3002399751580334n), 1.5), Duration.nanos(4503599627370501n)) + deepStrictEqual(Duration.times(Duration.nanos(10n ** 400n), 0.5), Duration.nanos(10n ** 400n / 2n)) + deepStrictEqual(Duration.times(Duration.nanos(1n), Infinity), Duration.infinity) + deepStrictEqual(Duration.times(Duration.nanos(1n), NaN), Duration.zero) deepStrictEqual(Duration.times(Duration.infinity, 60), Duration.infinity) }) @@ -547,6 +565,8 @@ describe("Duration", () => { strictEqual(Duration.millis(0.0000015).pipe(Duration.toNanosUnsafe), 2n) strictEqual(Duration.millis(-0.0000015).pipe(Duration.toNanosUnsafe), -2n) strictEqual(Duration.millis(100).pipe(Duration.toNanosUnsafe), 100_000_000n) + strictEqual(Duration.millis(2 ** 1023).pipe(Duration.toNanosUnsafe), 1_000_000n << 1023n) + strictEqual(Duration.millis(1_760_450_000_123).pipe(Duration.toNanosUnsafe), 1_760_450_000_123_000_000n) }) it("toHrTime", () => { diff --git a/repos/effect/packages/effect/test/Effect.test.ts b/repos/effect/packages/effect/test/Effect.test.ts index e10953d517..f9b6e31371 100644 --- a/repos/effect/packages/effect/test/Effect.test.ts +++ b/repos/effect/packages/effect/test/Effect.test.ts @@ -2,15 +2,18 @@ import { assert, describe, it, vi } from "@effect/vitest" import { assertExitFailure } from "@effect/vitest/utils" import { Cause, + Clock, Context, Data, Deferred, Duration, Effect, Effectable, + Equal, Exit, Fiber, type Filter, + Hash, Latch, Layer, Logger, @@ -2148,6 +2151,74 @@ describe("Effect", () => { }) describe("interruption", () => { + it("interrupting a fiber does not call Math.random", async () => { + // The bug made the runtime retry forever while Math.random kept throwing, + // so stop throwing after a while to keep a regression bounded. + let calls = 0 + const random = Math.random + const spy = vi.spyOn(Math, "random").mockImplementation(() => { + calls++ + if (calls > 1_000) return random() + throw new Error("Math.random is not allowed") + }) + // Fresh objects, so no earlier test has cached a random reference hash. + class DefectError extends Error { + override toString() { + return "DefectError" + } + } + try { + const exit = await Effect.runPromise(Effect.gen(function*() { + const latch = yield* Latch.make() + const child = yield* latch.await.pipe( + Effect.andThen(Effect.die(new DefectError())), + Effect.uninterruptible, + Effect.forkChild({ startImmediately: true }) + ) + // The child resumes after these synchronous interrupts. + yield* latch.open + child.interruptUnsafe(undefined, Context.make(ATag, "A")) + child.interruptUnsafe(undefined, Context.make(ATag, "A")) + return yield* Fiber.await(child) + })) + assert.strictEqual(calls, 0) + assert.isTrue(Exit.isFailure(exit) && Cause.hasDies(exit.cause) && Cause.hasInterrupts(exit.cause)) + } finally { + spy.mockRestore() + } + }) + + it.effect("a defect that throws when hashed still terminates an interrupted fiber", () => + Effect.gen(function*() { + // Throw a bounded number of times so a retrying runtime still finishes. + const limit = 1_000 + let hashCalls = 0 + const defect = { + [Hash.symbol]() { + if (++hashCalls <= limit) throw defect + return 0 + }, + [Equal.symbol](that: unknown) { + return that === defect + } + } + let finalized = 0 + const child = yield* Effect.never.pipe( + Effect.onInterrupt(() => Effect.die(defect)), + Effect.ensuring(Effect.sync(() => finalized++)), + Effect.forkChild + ) + yield* Effect.yieldNow + const exit = yield* Fiber.interrupt(child).pipe(Effect.andThen(Fiber.await(child))) + assert.isBelow(hashCalls, limit) + assert.strictEqual(finalized, 1) + assert.isTrue( + Exit.isFailure(exit) && + exit.cause.reasons.some((reason) => reason._tag === "Die" && reason.defect === defect) && + Cause.hasInterrupts(exit.cause) + ) + })) + it.effect("skipped handlers drop failures and keep defects when interrupted", () => Effect.gen(function*() { const latch = yield* Latch.make() @@ -4170,6 +4241,112 @@ describe("Effect", () => { assert.deepStrictEqual(negativeZero.pollUnsafe(), Exit.succeed(-Infinity), "-0 over 0 never woke its waiter") })) }) + + describe("transaction metadata", () => { + it.effect("starts with zero durations when the clock advances between reads", () => + Effect.gen(function*() { + const clock = yield* Clock.Clock + let now = 1000 + const currentTimeMillisUnsafe = () => now++ + yield* Effect.tx(Effect.gen(function*() { + const metadata = yield* Effect.Transaction + assert.deepStrictEqual([metadata.elapsed, metadata.elapsedSincePrevious], [0, 0]) + assert.strictEqual(metadata.start, metadata.now) + })).pipe(Effect.provideService(Clock.Clock, { + ...clock, + currentTimeMillisUnsafe, + currentTimeMillis: Effect.sync(currentTimeMillisUnsafe) + })) + })) + + it.effect("tracks nested metadata across retries and conflicts", () => + Effect.gen(function*() { + const ref = TxRef.makeUnsafe(0) + const started = yield* Deferred.make() + const readyForConflict = yield* Deferred.make() + const resume = yield* Deferred.make() + const snapshots = yield* Ref.make< + Array<{ + readonly attempt: number + readonly retryReason: Effect.TransactionRetryReason | undefined + readonly start: number + readonly now: number + readonly elapsed: number + readonly elapsedSincePrevious: number + readonly nestedSame: boolean + }> + >([]) + + const fiber = yield* Effect.forkChild(Effect.tx(Effect.gen(function*() { + const outer = yield* Effect.Transaction + const nestedSame = yield* Effect.tx(Effect.gen(function*() { + const inner = yield* Effect.Transaction + return inner === outer + })) + yield* Ref.update(snapshots, (current) => [ + ...current, + { + attempt: outer.attempt, + retryReason: outer.retryReason, + start: outer.start, + now: outer.now, + elapsed: outer.elapsed, + elapsedSincePrevious: outer.elapsedSincePrevious, + nestedSame + } + ]) + yield* TxRef.get(ref) + if (outer.attempt === 1) { + yield* Deferred.succeed(started, undefined) + return yield* Effect.txRetry + } + if (outer.attempt === 2) { + yield* Deferred.succeed(readyForConflict, undefined) + yield* Deferred.await(resume) + } + }))) + + yield* Deferred.await(started) + yield* TestClock.adjust("1 second") + yield* TxRef.set(ref, 1) + yield* Deferred.await(readyForConflict) + yield* TestClock.adjust("500 millis") + yield* TxRef.set(ref, 2) + yield* Deferred.succeed(resume, undefined) + yield* Fiber.join(fiber) + const recorded = yield* Ref.get(snapshots) + + assert.deepStrictEqual(recorded, [ + { + attempt: 1, + retryReason: undefined, + start: 0, + now: 0, + elapsed: 0, + elapsedSincePrevious: 0, + nestedSame: true + }, + { + attempt: 2, + retryReason: "retry", + start: 0, + now: 1000, + elapsed: 1000, + elapsedSincePrevious: 1000, + nestedSame: true + }, + { + attempt: 3, + retryReason: "conflict", + start: 0, + now: 1500, + elapsed: 1500, + elapsedSincePrevious: 500, + nestedSame: true + } + ]) + })) + }) }) describe("Effect.fn", () => { @@ -4471,6 +4648,25 @@ describe("Effect", () => { assert.deepStrictEqual(yield* Fiber.awaitAll(fibers), [Exit.succeed(1), Exit.succeed(1), Exit.succeed(1)]) })) + it.effect("shares the in-flight run when the body synchronously wakes a re-entrant caller", () => + Effect.gen(function*() { + const gate = yield* Deferred.make() + const cached = yield* Effect.cached( + Effect.gen(function*() { + yield* Deferred.succeed(gate, void 0) + return 42 + }) + ) + + const waiter = yield* Deferred.await(gate).pipe( + Effect.andThen(cached), + Effect.forkChild({ startImmediately: true }) + ) + + assert.strictEqual(yield* cached, 42) + assert.strictEqual(yield* Fiber.join(waiter), 42) + })) + it.effect("replays failures", () => Effect.gen(function*() { let count = 0 diff --git a/repos/effect/packages/effect/test/FileSystem.test-utils.ts b/repos/effect/packages/effect/test/FileSystem.test-utils.ts index 19fa02fbc8..95931d2a2d 100644 --- a/repos/effect/packages/effect/test/FileSystem.test-utils.ts +++ b/repos/effect/packages/effect/test/FileSystem.test-utils.ts @@ -10,6 +10,8 @@ export interface TestLayerOptions { readonly accessOnDirectory?: boolean /** Whether a scoped temporary file removes its containing directory. Deno removes only the file. Defaults to `true`. */ readonly tempFileScopedRemovesDirectory?: boolean + /** Whether `open` can refuse to follow a symlink at the final path component. Defaults to `true`. */ + readonly noFollow?: boolean } export const testLayer = (layer: Layer.Layer, options: TestLayerOptions = {}) => { @@ -562,4 +564,65 @@ export const testLayer = (layer: Layer.Layer, options: Test Effect.scoped ) }))) + + it("noFollow rejects symlinks or fails explicitly when unsupported", () => + runPromise( + Effect.gen(function*() { + const fs = yield* Fs.FileSystem + const directory = yield* fs.makeTempDirectoryScoped() + const path = `${directory}/target` + yield* fs.writeFileString(path, "target") + if (options.noFollow !== false) { + yield* fs.open(path, { noFollow: true }) + yield* fs.symlink(path, `${directory}/link`) + } + const result = yield* Effect.result(fs.open( + options.noFollow === false ? path : `${directory}/link`, + { noFollow: true } + )) + expect(result).toMatchObject({ + _tag: "Failure", + failure: { reason: { _tag: options.noFollow === false ? "BadArgument" : "BadResource" } } + }) + }).pipe(Effect.scoped) + )) + + it("concurrent positional reads preserve the cursor", () => + runPromise( + Effect.gen(function*() { + const fs = yield* Fs.FileSystem + const file = yield* fs.open(`${__dirname}/fixtures/text.txt`) + yield* file.seek(BigInt(6), "start") + const buffer = new Uint8Array(5) + const [count, allocated] = yield* Effect.all([ + file.read(buffer, { position: BigInt(12) }), + file.readAlloc(4, { position: BigInt(18) }).pipe(Effect.flatMap(Effect.fromOption)) + ], { concurrency: "unbounded" }) + assert.strictEqual(count, 5) + assert.strictEqual(new TextDecoder().decode(buffer), "dolar") + assert.strictEqual(new TextDecoder().decode(allocated), "sit ") + const next = yield* file.readAlloc(5).pipe(Effect.flatMap(Effect.fromOption)) + assert.strictEqual(new TextDecoder().decode(next), "ipsum") + }).pipe(Effect.scoped) + )) + + it.each(["read", "readAlloc"] as const)( + "%s rejects a negative position", + (method) => + runPromise( + Effect.gen(function*() { + const fs = yield* Fs.FileSystem + const file = yield* fs.open(`${__dirname}/fixtures/text.txt`) + const result = yield* Effect.result( + method === "read" + ? Effect.asVoid(file.read(new Uint8Array(1), { position: BigInt(-1) })) + : Effect.asVoid(file.readAlloc(1, { position: BigInt(-1) })) + ) + expect(result).toMatchObject({ + _tag: "Failure", + failure: { reason: { _tag: "BadArgument", method } } + }) + }).pipe(Effect.scoped) + ) + ) } diff --git a/repos/effect/packages/effect/test/Path.test.ts b/repos/effect/packages/effect/test/Path.test.ts new file mode 100644 index 0000000000..18c0b9c735 --- /dev/null +++ b/repos/effect/packages/effect/test/Path.test.ts @@ -0,0 +1,22 @@ +import { describe, it } from "@effect/vitest" +import { assertNone, assertSome } from "@effect/vitest/utils" +import * as Effect from "effect/Effect" +import * as Path from "effect/Path" + +describe("Path", () => { + it.effect("resolveWithin keeps POSIX paths lexically inside the root", () => + Effect.gen(function*() { + const path = yield* Path.Path + + assertSome(path.resolveWithin("/srv/app", "src/index.ts"), "/srv/app/src/index.ts") + assertSome(path.resolveWithin("/srv/app/", "src/index.ts"), "/srv/app/src/index.ts") + assertSome(path.resolveWithin("/srv/app", "."), "/srv/app") + assertSome(path.resolveWithin("/srv/app", ""), "/srv/app") + assertSome(path.resolveWithin("/srv/app", "..foo"), "/srv/app/..foo") + assertSome(path.resolveWithin("/", "etc/passwd"), "/etc/passwd") + + assertNone(path.resolveWithin("/srv/app", "../app-other/x.ts")) + assertNone(path.resolveWithin("/srv/app", "a/../../b")) + assertNone(path.resolveWithin("/srv/app", "/etc/passwd")) + }).pipe(Effect.provide(Path.layer))) +}) diff --git a/repos/effect/packages/effect/test/RequestResolver.test.ts b/repos/effect/packages/effect/test/RequestResolver.test.ts new file mode 100644 index 0000000000..0b89aa1a08 --- /dev/null +++ b/repos/effect/packages/effect/test/RequestResolver.test.ts @@ -0,0 +1,63 @@ +import { assert, describe, it } from "@effect/vitest" +import { Data, Deferred, Effect, Exit, Fiber, Request, RequestResolver } from "effect" + +class Key extends Data.Class<{ id: number }> {} +class GetValue extends Request.Class<{ key: Key }, number> {} + +describe("RequestResolver.makeGrouped", () => { + it.effect("keeps equal keys batched across derived resolvers and releases them before the next window", () => + Effect.gen(function*() { + const gate = yield* Deferred.make() + const batches: Array<{ key: Key; size: number }> = [] + const resolver = RequestResolver.makeGrouped({ + key: ({ request }) => request.key, + resolver: (entries, key) => + Effect.sync(() => { + batches.push({ key, size: entries.length }) + for (const entry of entries) entry.completeUnsafe(Exit.succeed(key.id)) + }) + }).pipe(RequestResolver.setDelayEffect(Effect.andThen(Effect.yieldNow, Deferred.await(gate)))) + const first = yield* Effect.request(new GetValue({ key: new Key({ id: 1 }) }), resolver).pipe( + Effect.forkChild({ startImmediately: true }) + ) + // Running a derived resolver must not split the delayed resolver's pending batch. + yield* Effect.request(new GetValue({ key: new Key({ id: 1 }) }), RequestResolver.batchN(resolver, 1)) + const rest = yield* Effect.forEach( + [1, 2], + (id) => + Effect.request(new GetValue({ key: new Key({ id }) }), resolver).pipe( + Effect.forkChild({ startImmediately: true }) + ) + ) + yield* Deferred.succeed(gate, undefined) + const values = yield* Effect.forEach([first, ...rest], Fiber.join) + assert.deepStrictEqual(values, [1, 1, 2]) + assert.deepStrictEqual(batches.map(({ size }) => size), [1, 2, 1]) + + const next = new Key({ id: 1 }) + yield* Effect.request(new GetValue({ key: next }), resolver) + assert.strictEqual(batches[3].key, next) + })) + + it.effect("releases the key when the last pending request is interrupted", () => + Effect.gen(function*() { + const keys: Array = [] + const resolver = RequestResolver.makeGrouped({ + key: ({ request }) => request.key, + resolver: (entries, key) => + Effect.sync(() => { + keys.push(key) + for (const entry of entries) entry.completeUnsafe(Exit.succeed(key.id)) + }) + }) + const fiber = yield* Effect.request(new GetValue({ key: new Key({ id: 1 }) }), resolver).pipe( + Effect.forkChild({ startImmediately: true }) + ) + yield* Fiber.interrupt(fiber) + const next = new Key({ id: 1 }) + yield* Effect.request(new GetValue({ key: next }), resolver) + + assert.strictEqual(keys.length, 1) + assert.strictEqual(keys[0], next) + })) +}) diff --git a/repos/effect/packages/effect/test/Sink.test.ts b/repos/effect/packages/effect/test/Sink.test.ts index 39c9e1a247..86f600e4db 100644 --- a/repos/effect/packages/effect/test/Sink.test.ts +++ b/repos/effect/packages/effect/test/Sink.test.ts @@ -303,6 +303,40 @@ describe("Sink", () => { })) }) + describe("takeUntil", () => { + it.effect("takeUntil preserves leftovers and stops at the match", () => + Effect.gen(function*() { + const result = yield* Stream.make(1, 2, 3, 4).pipe( + Stream.concat(Stream.fail("pulled past the match")), + Stream.transduce(Sink.takeUntil((n) => n % 2 === 0)), + Stream.take(2), + Stream.runCollect + ) + deepStrictEqual(result, [[1, 2], [3, 4]]) + })) + + it.effect("takeUntilEffect preserves leftovers and stops at the match", () => + Effect.gen(function*() { + for (const chunkSize of [1, 4]) { + const inputs: Array = [] + const result = yield* Stream.make(1, 2, 3, 4).pipe( + Stream.rechunk(chunkSize), + Stream.concat(Stream.fail("pulled past the match")), + Stream.transduce(Sink.takeUntilEffect((n) => + Effect.sync(() => { + inputs.push(n) + return n % 2 === 0 + }) + )), + Stream.take(2), + Stream.runCollect + ) + deepStrictEqual(result, [[1, 2], [3, 4]]) + deepStrictEqual(inputs, [1, 2, 3, 4]) + } + })) + }) + describe("withDuration", () => { it.effect("uses monotonic time when wall time moves backward", () => Effect.gen(function*() { diff --git a/repos/effect/packages/effect/test/StackCapture.test.ts b/repos/effect/packages/effect/test/StackCapture.test.ts index 24244827e4..26a86aebf3 100644 --- a/repos/effect/packages/effect/test/StackCapture.test.ts +++ b/repos/effect/packages/effect/test/StackCapture.test.ts @@ -1,5 +1,6 @@ import { assert, describe, it } from "@effect/vitest" import { Effect, References } from "effect" +import { vi } from "vitest" const withCaptureDisabled = (run: () => A): A => { const limit = Error.stackTraceLimit @@ -30,6 +31,61 @@ const countErrors = (run: () => void): number => { } describe("stack capture", { concurrent: false }, () => { + it("module loading bounds probes and restores the stack trace limit", async () => { + const original = globalThis.Error + const previous = original.stackTraceLimit + const limits: Array = [] + vi.resetModules() + original.stackTraceLimit = 10 + globalThis.Error = new Proxy(original, { + construct(target, args, newTarget) { + limits.push(target.stackTraceLimit) + return Reflect.construct(target, args, newTarget) + } + }) + try { + await import("effect/Utils") + assert.deepStrictEqual(limits.splice(0), [2]) + assert.strictEqual(original.stackTraceLimit, 10) + await import("effect/internal/effect") + assert.deepStrictEqual(limits, [1]) + assert.strictEqual(original.stackTraceLimit, 10) + } finally { + globalThis.Error = original + original.stackTraceLimit = previous + vi.resetModules() + } + }) + + it("module loading skips stack formatting at limit zero", async () => { + const original = globalThis.Error + const limit = original.stackTraceLimit + let stackReads = 0 + vi.resetModules() + original.stackTraceLimit = 0 + globalThis.Error = new Proxy(original, { + construct(target, args, newTarget) { + return new Proxy(Reflect.construct(target, args, newTarget), { + get(target, key, receiver) { + if (key === "stack") { + stackReads++ + } + return Reflect.get(target, key, receiver) + } + }) + } + }) + try { + // A dynamic import after clearing the cache exercises the load-time probe. + await import("effect/internal/effect") + } finally { + globalThis.Error = original + original.stackTraceLimit = limit + vi.resetModules() + } + assert.strictEqual(stackReads, 0) + }) + it("Effect.fn skips definition capture at limit zero", () => { const count = withCaptureDisabled(() => countErrors(() => Effect.fn("test")(() => Effect.void))) assert.strictEqual(count, 0) diff --git a/repos/effect/packages/effect/test/Stdio.test.ts b/repos/effect/packages/effect/test/Stdio.test.ts index bfb56fb185..ebbbbc2feb 100644 --- a/repos/effect/packages/effect/test/Stdio.test.ts +++ b/repos/effect/packages/effect/test/Stdio.test.ts @@ -1,13 +1,28 @@ import { assert, describe, it } from "@effect/vitest" import * as Effect from "effect/Effect" +import * as Sink from "effect/Sink" import * as Stdio from "effect/Stdio" +import * as Stream from "effect/Stream" describe("Stdio", () => { + it.effect("make defaults stderr terminal state to false", () => + Effect.gen(function*() { + const stdio = Stdio.make({ + args: Effect.succeed([]), + stdin: Stream.empty, + stdout: () => Sink.drain, + stderr: () => Sink.drain, + stdoutIsTerminal: Effect.succeed(true) + }) + assert.isFalse(yield* stdio.stderrIsTerminal) + })) + it.effect("layerTest defaults terminal state to false", () => Effect.gen(function*() { const stdio = yield* Stdio.Stdio assert.isFalse(yield* stdio.stdinIsTerminal) assert.isFalse(yield* stdio.stdoutIsTerminal) + assert.isFalse(yield* stdio.stderrIsTerminal) }).pipe(Effect.provide(Stdio.layerTest({})))) it.effect("layerTest allows terminal state overrides", () => @@ -15,8 +30,10 @@ describe("Stdio", () => { const stdio = yield* Stdio.Stdio assert.isTrue(yield* stdio.stdinIsTerminal) assert.isTrue(yield* stdio.stdoutIsTerminal) + assert.isTrue(yield* stdio.stderrIsTerminal) }).pipe(Effect.provide(Stdio.layerTest({ stdinIsTerminal: Effect.succeed(true), - stdoutIsTerminal: Effect.succeed(true) + stdoutIsTerminal: Effect.succeed(true), + stderrIsTerminal: Effect.succeed(true) })))) }) diff --git a/repos/effect/packages/effect/test/Stream.test.ts b/repos/effect/packages/effect/test/Stream.test.ts index dc4b64634b..84cd7f48ae 100644 --- a/repos/effect/packages/effect/test/Stream.test.ts +++ b/repos/effect/packages/effect/test/Stream.test.ts @@ -5514,6 +5514,25 @@ describe("Stream", () => { deepStrictEqual(result, [4]) })) + it.live.each(["timeout", "timeoutOrElse"] as const)( + "%s finishes when an async iterator pull never settles", + (kind) => + Effect.gen(function*() { + async function* source() { + yield "a" + await new Promise(() => undefined) + } + const result = yield* Stream.fromAsyncIterable(source(), (error) => error).pipe( + kind === "timeout" ? Stream.timeout("10 millis") : Stream.timeoutOrElse({ + duration: "10 millis", + orElse: () => Stream.succeed("fallback") + }), + Stream.runCollect + ) + deepStrictEqual(result, kind === "timeout" ? ["a"] : ["a", "fallback"]) + }) + ) + it.effect("timeoutOrElse - should not apply timeout after switch", () => Effect.gen(function*() { const fiber = yield* pipe( diff --git a/repos/effect/packages/effect/test/String.test.ts b/repos/effect/packages/effect/test/String.test.ts index 3ee1777bbf..6409aeca60 100644 --- a/repos/effect/packages/effect/test/String.test.ts +++ b/repos/effect/packages/effect/test/String.test.ts @@ -598,6 +598,11 @@ describe("String", () => { it("handles an empty string", () => { strictEqual(S.snakeToCamel(""), "") }) + + it("handles trailing and separator-only inputs", () => { + strictEqual(S.snakeToCamel("foo_"), "foo") + strictEqual(S.snakeToCamel("__"), "") + }) }) describe("snakeToPascal", () => { @@ -609,6 +614,11 @@ describe("String", () => { it("handles an empty string", () => { strictEqual(S.snakeToPascal(""), "") }) + + it("handles trailing and separator-only inputs", () => { + strictEqual(S.snakeToPascal("foo_"), "Foo") + strictEqual(S.snakeToPascal("__"), "") + }) }) describe("snakeToKebab", () => { @@ -674,6 +684,17 @@ describe("String", () => { strictEqual(S.noCase("field2value"), "field 2 value") strictEqual(S.noCase("field2Value"), "field 2 value") }) + + it("does not transform a word for inputs without words", () => { + const parts: Array = [] + const transform = (part: string) => { + parts.push(part) + return part + } + strictEqual(S.noCase("", { transform }), "") + strictEqual(S.noCase("---", { transform }), "") + deepStrictEqual(parts, []) + }) }) describe("pascalCase", () => { diff --git a/repos/effect/packages/effect/test/TestClock.test.ts b/repos/effect/packages/effect/test/TestClock.test.ts index 54fa0ddfbe..2f76af33ed 100644 --- a/repos/effect/packages/effect/test/TestClock.test.ts +++ b/repos/effect/packages/effect/test/TestClock.test.ts @@ -1,10 +1,41 @@ import { assert, describe, it } from "@effect/vitest" +import * as Clock from "effect/Clock" import * as Duration from "effect/Duration" import * as Effect from "effect/Effect" import * as Exit from "effect/Exit" +import * as Fiber from "effect/Fiber" +import * as Scheduler from "effect/Scheduler" import * as TestClock from "effect/testing/TestClock" describe("TestClock", () => { + for (const cancellation of ["interrupted sleep", "successful timeout"] as const) { + it.effect(`adjust - skips the cancelled deadline (${cancellation})`, () => + Effect.gen(function*() { + const testClock = yield* TestClock.make() + if (cancellation === "interrupted sleep") { + const sleeper = yield* testClock.sleep(Duration.minutes(1)).pipe( + Effect.forkChild({ startImmediately: true }) + ) + yield* Effect.yieldNow + yield* Fiber.interrupt(sleeper) + } else { + yield* Effect.timeout(Effect.yieldNow, "1 minute").pipe( + Effect.provideService(Clock.Clock, testClock) + ) + } + + // Record the clock whenever adjustment yields to other fibers + const observed = new Set() + yield* Effect.sync(() => observed.add(testClock.currentTimeMillisUnsafe())).pipe( + Effect.andThen(Effect.yieldNow), + Effect.forever, + Effect.forkChild + ) + yield* testClock.adjust("2 minutes") + assert.isFalse(observed.has(60_000)) + })) + } + it.effect("sleep - does not require passage of wall time", () => Effect.gen(function*() { let elapsed = false @@ -131,6 +162,72 @@ describe("TestClock", () => { assert.strictEqual(testClock.monotonicTimeNanosUnsafe(), 2_000_000_000n) })) + it.effect("adjust - runs sleeps registered after a yield", () => + Effect.gen(function*() { + let ticks = 0 + const fiber = yield* Effect.sleep("1 second").pipe( + Effect.andThen(Effect.sync(() => { + ticks++ + })), + Effect.andThen(Effect.yieldNow), + Effect.forever, + Effect.forkChild + ) + yield* TestClock.adjust("5 seconds") + yield* Fiber.interrupt(fiber) + assert.strictEqual(ticks, 5) + })) + + it.effect("setTime - runs sleeps registered after a fork and join", () => + Effect.gen(function*() { + let ticks = 0 + const fiber = yield* Effect.sleep("1 second").pipe( + Effect.andThen(Effect.sync(() => { + ticks++ + })), + Effect.andThen(Effect.forkChild(Effect.yieldNow).pipe(Effect.flatMap(Fiber.join))), + Effect.forever, + Effect.forkChild + ) + yield* TestClock.setTime(5_000) + yield* Fiber.interrupt(fiber) + assert.strictEqual(ticks, 5) + })) + + it.effect("adjust - completes when a nested clock wakes a busy fiber", () => + Effect.gen(function*() { + let later = false + yield* Effect.sleep("1 second").pipe( + Effect.andThen(Effect.forever(Effect.yieldNow)), + Effect.forkChild + ) + yield* Effect.sleep("2 seconds").pipe( + Effect.andThen(Effect.sync(() => { + later = true + })), + Effect.forkChild + ) + yield* TestClock.adjust("5 seconds") + assert.isTrue(later) + }).pipe(Effect.provide(TestClock.layer({ warningDelay: "10 millis" })))) + + it.effect("adjust - waits for woken fibers when the advancing fiber yields on its operation budget", () => + Effect.gen(function*() { + let done = false + yield* Effect.sleep("1 second").pipe( + Effect.andThen(Effect.yieldNow), + Effect.andThen(Effect.sync(() => { + done = true + })), + Effect.forkChild + ) + yield* TestClock.adjust("1 second") + assert.isTrue(done) + }).pipe( + Effect.provide(TestClock.layer({ warningDelay: Duration.infinity })), + Effect.provideService(Scheduler.MaxOpsBeforeYield, 4) + )) + // `it.effect` and `it.live` provide an ambient Scope, defeating the #2244 regression guard. it("layer - can adjust when provided without an ambient Scope", () => Effect.gen(function*() { diff --git a/repos/effect/packages/effect/test/ai/AiError.test.ts b/repos/effect/packages/effect/test/ai/AiError.test.ts index 0c63c81eb3..dfa3cc54b9 100644 --- a/repos/effect/packages/effect/test/ai/AiError.test.ts +++ b/repos/effect/packages/effect/test/ai/AiError.test.ts @@ -1,9 +1,22 @@ import { assert, describe, it } from "@effect/vitest" -import { Duration, Effect, Schema } from "effect" +import { Duration, Effect, Redacted, Schema } from "effect" import { AiError } from "effect/ai" +import { HttpClientError, HttpClientRequest } from "effect/http" describe("AiError", () => { describe("reason types", () => { + describe("NetworkError", () => { + it("preserves redacted query params from request errors", () => { + const request = HttpClientRequest.get("https://example.com").pipe( + HttpClientRequest.setUrlParam("remote", Redacted.make("param-secret")) + ) + const error = AiError.NetworkError.fromRequestError(new HttpClientError.TransportError({ request })) + const output = JSON.stringify(error) + assert.include(output, "remote") + assert.notInclude(output, "param-secret") + }) + }) + describe("RateLimitError", () => { it("should be retryable", () => { const error = new AiError.RateLimitError({}) diff --git a/repos/effect/packages/effect/test/ai/Chat.test.ts b/repos/effect/packages/effect/test/ai/Chat.test.ts index 516728bc8a..9c473eb819 100644 --- a/repos/effect/packages/effect/test/ai/Chat.test.ts +++ b/repos/effect/packages/effect/test/ai/Chat.test.ts @@ -1,5 +1,5 @@ import { assert, describe, it } from "@effect/vitest" -import { Effect, Layer, Predicate, Ref, Schema } from "effect" +import { Effect, Layer, Predicate, Ref, Schema, Stream } from "effect" import { Chat, IdGenerator, Prompt, Tool, Toolkit } from "effect/ai" import { Persistence } from "effect/persistence" import { TestClock } from "effect/testing" @@ -16,6 +16,34 @@ const PersistenceLayer = Layer.provideMerge( ) describe("Chat", () => { + it.effect("keeps partial assistant text when streamText is interrupted", () => + Effect.gen(function*() { + const chat = yield* Chat.empty + + yield* chat.streamText({ prompt: "hi" }).pipe( + Stream.take(2), + Stream.runDrain, + TestUtils.withLanguageModel({ + streamText: () => + Stream.fromIterable( + [ + { type: "text-start", id: "t1" }, + { type: "text-delta", id: "t1", delta: "Hello" }, + { type: "text-end", id: "t1" } + ] as const + ).pipe(Stream.rechunk(1)) + }) + ) + + assert.deepStrictEqual( + yield* Ref.get(chat.history), + Prompt.make([ + { role: "user", content: "hi" }, + { role: "assistant", content: [{ type: "text", text: "Hello" }] } + ]) + ) + })) + it.effect("does not replay a completed approved tool", () => { let executions = 0 const toolkit = Toolkit.make(Tool.make("Counter", { diff --git a/repos/effect/packages/effect/test/ai/DecisionModel.test.ts b/repos/effect/packages/effect/test/ai/DecisionModel.test.ts index cb58a61fc4..58aeb65e60 100644 --- a/repos/effect/packages/effect/test/ai/DecisionModel.test.ts +++ b/repos/effect/packages/effect/test/ai/DecisionModel.test.ts @@ -105,7 +105,11 @@ describe("Decision", () => { technical: "bugs", sales: "pricing" }) - assert.deepStrictEqual(TicketTriage.decisions.frustration.criteria, ["calm", "frustrated", "angry"]) + assert.deepStrictEqual(TicketTriage.decisions.frustration.criteria, [ + { label: "calm", description: "calm" }, + { label: "frustrated", description: "frustrated" }, + { label: "angry", description: "angry" } + ]) assert.deepStrictEqual(TicketTriage.decisions.urgent.criteria, { false: "No time pressure", true: "Needs action now" @@ -672,6 +676,30 @@ describe("Decision validation contracts", () => { it("rate rejects duplicate levels", () => { assert.throws(() => Decision.rate({ instructions: "Rate", criteria: ["low", "high", "low"] })) + assert.throws(() => + Decision.rate({ instructions: "Rate", criteria: ["low", { label: "low", description: { what: "Also low" } }] }) + ) + }) + + it.effect("rate validates and labels answers by the labels of structured levels", () => { + const definition = Decision.make({ + input: Schema.String, + decisions: { + severity: Decision.rate({ + instructions: { question: "How severe?" }, + criteria: ["low", { label: "high", description: { impact: "outage" } }] + }) + } + }) + + return Effect.gen(function*() { + const { answers } = yield* DecisionModel.decide(definition, { input: "Export fails" }) + + assert.strictEqual(answers.severity.label, "high") + assert.deepStrictEqual(answers.severity.probabilities, { low: 0.1, high: 0.9 }) + }).pipe(Effect.provide(succeedWith({ + severity: { _tag: "Rate", rating: 0.9, probabilities: { low: 0.1, high: 0.9 } } + }))) }) it.effect("rate derives the argmax label without a provider label", () => diff --git a/repos/effect/packages/effect/test/ai/LanguageModel.test.ts b/repos/effect/packages/effect/test/ai/LanguageModel.test.ts index 11b6f708af..8637f92c5e 100644 --- a/repos/effect/packages/effect/test/ai/LanguageModel.test.ts +++ b/repos/effect/packages/effect/test/ai/LanguageModel.test.ts @@ -69,6 +69,38 @@ describe("LanguageModel", () => { response: undefined } + for (const method of ["generateText", "streamText"] as const) { + it.effect(`${method} uses current tool schemas and handlers across requests`, () => + Effect.gen(function*() { + const run = (tool: typeof MyTool, result: string, disableToolCallResolution = false) => { + const toolkit = Toolkit.make(tool) + const options = { prompt: "hi", toolkit, disableToolCallResolution } + return (method === "generateText" + ? LanguageModel.generateText(options).pipe(Effect.map((response) => response.toolResults[0])) + : LanguageModel.streamText(options).pipe( + Stream.runCollect, + Effect.map((parts) => parts.find((part) => part.type === "tool-result")) + )).pipe( + Effect.provide(toolkit.toLayer({ MyTool: () => Effect.succeed({ testSuccess: result }) })) + ) + } + for (const result of ["first", "second"]) { + const toolResult = yield* run(MyTool, result) + assertDefined(toolResult) + deepStrictEqual(toolResult.result, { testSuccess: result }) + } + yield* run(MyTool, "unused", true) + const changed = MyTool.setParameters( + Schema.Struct({ testParam: Schema.String.check(Schema.isPattern(/^changed$/)) }) + ) + const error = yield* run(changed, "unused", true).pipe(Effect.flip) + strictEqual(error.reason._tag, "InvalidOutputError") + }).pipe(TestUtils.withLanguageModel({ + generateText: [{ type: "tool-call", id: "call", name: "MyTool", params: { testParam: "test-param" } }], + streamText: [{ type: "tool-call", id: "call", name: "MyTool", params: { testParam: "test-param" } }] + }))) + } + describe("generateText", () => { it.effect("records resolved request options on a client span", () => LanguageModel.generateText({ prompt: "hi" }).pipe( @@ -411,6 +443,40 @@ describe("LanguageModel", () => { deepStrictEqual(response.toolCalls[0]!.params, { testParam: "test-param" }) strictEqual(yield* Ref.get(calls), 0) })) + + it.effect("ignores deferred tool call validation when tool call resolution is enabled", () => + Effect.gen(function*() { + const error = yield* LanguageModel.generateText({ + prompt: [], + toolkit: MyToolkit, + toolCallValidation: "deferred" + }).pipe( + TestUtils.withLanguageModel({ + generateText: [{ type: "tool-call", id: "call_1", name: "Write", params: { path: "a" } }] + }), + Effect.provide(MyToolkitLayer), + Effect.flip + ) + + strictEqual(error.reason._tag, "InvalidOutputError") + })) + + it.effect("returns tool calls without a toolkit when tool call validation is deferred", () => + Effect.gen(function*() { + const response = yield* LanguageModel.generateText({ + prompt: [], + disableToolCallResolution: true, + toolCallValidation: "deferred" + }).pipe( + TestUtils.withLanguageModel({ + generateText: [{ type: "tool-call", id: "call_1", name: "Write", params: { path: "a" } }] + }) + ) + + deepStrictEqual(response.toolCalls.map(({ name, params }) => ({ name, params })), [ + { name: "Write", params: { path: "a" } } + ]) + })) }) describe("streamText", () => { @@ -1287,6 +1353,31 @@ describe("LanguageModel", () => { strictEqual(yield* Ref.get(active), 0) strictEqual(yield* Ref.get(maxActive), 1) })) + + it.effect("validates provider-executed tool calls when tool call validation is deferred", () => + Effect.gen(function*() { + const error = yield* LanguageModel.streamText({ + prompt: [], + toolkit: MyToolkit, + disableToolCallResolution: true, + toolCallValidation: "deferred" + }).pipe( + Stream.runDrain, + TestUtils.withLanguageModel({ + streamText: [{ + type: "tool-call", + id: "call_1", + name: "MyTool", + params: { testParam: 42 }, + providerExecuted: true + }] + }), + Effect.provide(MyToolkitLayer), + Effect.flip + ) + + strictEqual(error.reason._tag, "InvalidOutputError") + })) }) describe("generateObject", () => { @@ -2108,6 +2199,107 @@ describe("LanguageModel", () => { }) describe("tool approval", () => { + for (const method of ["generateText", "streamText"] as const) { + it.effect(`resolves only pending approvals in mixed approval history (${method})`, () => + Effect.gen(function*() { + const executed: Array = [] + let capturedPrompt: LanguageModel.ProviderOptions["prompt"] | undefined + const prompt: Array = [] + + for ( + const [id, approved, resolved] of [ + ["previous-approved", true, true], + ["previous-denied", false, true], + ["pending-approved", true, false], + ["pending-denied", false, false] + ] as const + ) { + prompt.push( + Prompt.assistantMessage({ + content: [ + Prompt.toolCallPart({ + id, + name: "ApprovalTool", + params: { action: id }, + providerExecuted: false + }), + Prompt.toolApprovalRequestPart({ approvalId: id, toolCallId: id }) + ] + }), + Prompt.toolMessage({ + content: [ + Prompt.toolApprovalResponsePart({ approvalId: id, approved, reason: "User declined" }), + ...(resolved + ? [Prompt.toolResultPart({ + id, + name: "ApprovalTool", + result: { result: id }, + isFailure: !approved, + providerExecuted: false + })] + : []) + ] + }) + ) + } + + const options = { prompt, toolkit: ApprovalToolkit } + yield* (method === "generateText" + ? LanguageModel.generateText(options) + : LanguageModel.streamText(options).pipe(Stream.runDrain)).pipe( + TestUtils.withLanguageModel({ + generateText: (opts) => { + capturedPrompt = opts.prompt + return Effect.succeed([finishPart]) + }, + streamText: (opts) => { + capturedPrompt = opts.prompt + return [finishPart] + } + }), + Effect.provide(ApprovalToolkit.toLayer({ + ApprovalTool: ({ action }) => + Effect.sync(() => { + executed.push(action) + return { result: "approved-result" } + }), + DynamicApprovalTool: () => Effect.succeed({ result: "dynamic-result" }) + })) + ) + + deepStrictEqual(executed, ["pending-approved"]) + assertDefined(capturedPrompt) + const parts = capturedPrompt.content.flatMap(( + message + ) => message.role === "assistant" || message.role === "tool" ? message.content : []) + deepStrictEqual(parts.filter((part) => part.type === "tool-approval-request"), []) + deepStrictEqual(parts.filter((part) => part.type === "tool-approval-response"), []) + deepStrictEqual(parts.filter((part) => part.type === "tool-call").map((part) => part.id), [ + "previous-approved", + "previous-denied", + "pending-approved", + "pending-denied" + ]) + deepStrictEqual( + parts.filter((part) => part.type === "tool-result").map((part) => ({ + id: part.id, + result: part.result, + isFailure: part.isFailure + })), + [ + { id: "previous-approved", result: { result: "previous-approved" }, isFailure: false }, + { id: "previous-denied", result: { result: "previous-denied" }, isFailure: true }, + { id: "pending-approved", result: { result: "approved-result" }, isFailure: false }, + { + id: "pending-denied", + result: { type: "execution-denied", reason: "User declined" }, + isFailure: true + } + ] + ) + })) + } + it.effect("emits tool-approval-request when tool has needsApproval: true", () => Effect.gen(function*() { const parts: Array, "opaque">> = [] diff --git a/repos/effect/packages/effect/test/ai/McpServer/LayerHttpRequestScoped.test.ts b/repos/effect/packages/effect/test/ai/McpServer/LayerHttpRequestScoped.test.ts new file mode 100644 index 0000000000..1ae13563ef --- /dev/null +++ b/repos/effect/packages/effect/test/ai/McpServer/LayerHttpRequestScoped.test.ts @@ -0,0 +1,364 @@ +import { assert, describe, it } from "@effect/vitest" +import * as McpProtocol from "effect/ai/McpProtocol" +import * as McpSchema from "effect/ai/McpSchema" +import * as McpServer from "effect/ai/McpServer" +import * as Context from "effect/Context" +import * as Deferred from "effect/Deferred" +import * as Effect from "effect/Effect" +import * as HttpRouter from "effect/http/HttpRouter" +import * as Layer from "effect/Layer" +import * as Predicate from "effect/Predicate" +import * as Schema from "effect/Schema" +import * as BaseProtocolTest from "./McpConformance/BaseProtocolTest.ts" +import * as CompletionTest from "./McpConformance/CompletionTest.ts" +import { layer as makeMcpConformanceLayer } from "./McpConformance/McpConformance.ts" +import * as MultiRoundTripTest from "./McpConformance/MultiRoundTripTest.ts" +import * as PromptsTest from "./McpConformance/PromptsTest.ts" +import * as ResourcesTest from "./McpConformance/ResourcesTest.ts" +import * as ToolsTest from "./McpConformance/ToolsTest.ts" +import { makeHttpHarness, MCP_ENDPOINT } from "./TestUtils/McpHttpHarness.ts" +import { makeMcpSseReader, readMcpHttpResponse } from "./TestUtils/McpHttpResponse.ts" +import { makeServerLayer } from "./TestUtils/McpServerLayer.ts" +import { makeWorkerdHarness } from "./TestUtils/McpWorkerdHarness.ts" + +const protocol = McpProtocol.v2026_07_28 +const conformance = makeMcpConformanceLayer(protocol, { mode: "request" }) + +describe("McpServer.layerHttpRequestScoped conformance", () => { + BaseProtocolTest.statelessModernSuite(protocol, conformance) + ToolsTest.suite(protocol, conformance) + ToolsTest.statelessModernSuite(protocol, conformance) + ResourcesTest.suite(protocol, conformance) + PromptsTest.suite(protocol, conformance, { additionalPromptNames: ["MrtrPrompt"] }) + CompletionTest.suite(protocol, conformance) + MultiRoundTripTest.suite(protocol, conformance) +}) + +const progressToken = "progress-1" + +const callTool = ( + name: string, + id: number, + args: Record = {}, + metadata: Record = {} +) => ({ + body: { + jsonrpc: "2.0", + id, + method: "tools/call", + params: { + name, + arguments: args, + _meta: { + progressToken, + ...metadata, + "io.modelcontextprotocol/protocolVersion": protocol.protocolVersion, + "io.modelcontextprotocol/clientCapabilities": {}, + "io.modelcontextprotocol/clientInfo": { name: "test", version: "1.0.0" } + } + } + }, + headers: { + accept: "application/json, text/event-stream", + "content-type": "application/json", + "MCP-Protocol-Version": protocol.protocolVersion, + "Mcp-Method": "tools/call", + "Mcp-Name": name + } +}) + +const sseMessages = (body: string): Array> => + body.split("\n").filter((line) => line.startsWith("data: ")).map((line) => JSON.parse(line.slice(6))) + +const toolRegistration = ( + name: string, + handle: (server: McpServer.McpServer["Service"], args: any) => Effect.Effect +) => + Layer.effectDiscard(Effect.gen(function*() { + const server = yield* McpServer.McpServer + yield* server.addTool({ + tool: new McpSchema.Tool({ name, inputSchema: { type: "object" } }), + annotations: Context.empty(), + handle: (args) => handle(server, args) + }) + })) + +const toolLayer = ( + name: string, + handle: (server: McpServer.McpServer["Service"], args: any) => Effect.Effect +) => + toolRegistration(name, handle).pipe( + Layer.provideMerge(makeServerLayer({ name: "RequestMode", protocols: [protocol], mode: "request" })) + ) + +const reportProgress = (server: McpServer.McpServer["Service"]) => + server.notifications["notifications/progress"]({ progressToken, progress: 1 }).pipe( + Effect.as(new McpSchema.CallToolResult({ content: [{ type: "text", text: "done" }] })) + ) + +describe("McpServer.layerHttpRequestScoped", () => { + it.live("should expose tools registered after the first POST in later lists and discovery", () => + Effect.gen(function*() { + const serverReady = yield* Deferred.make() + const harness = yield* makeHttpHarness( + Layer.effectDiscard(Effect.gen(function*() { + yield* Deferred.succeed(serverReady, yield* McpServer.McpServer) + })).pipe( + Layer.provideMerge(makeServerLayer({ name: "LateRegistration", protocols: [protocol], mode: "request" })) + ) + ) + let id = 0 + const post = Effect.fnUntraced(function*(method: "tools/list" | "server/discover") { + const response = yield* harness.post({ + jsonrpc: "2.0", + id: ++id, + method, + params: { + _meta: { + "io.modelcontextprotocol/protocolVersion": protocol.protocolVersion, + "io.modelcontextprotocol/clientCapabilities": {}, + "io.modelcontextprotocol/clientInfo": { name: "test", version: "1.0.0" } + } + } + }, { + "MCP-Protocol-Version": protocol.protocolVersion, + "Mcp-Method": method + }) + assert.strictEqual(response.status, 200) + const message = Schema.decodeUnknownSync(Schema.Struct({ result: Schema.JsonObject }))( + yield* readMcpHttpResponse(response) + ) + return message.result + }) + + assert.deepStrictEqual((yield* post("tools/list")).tools, []) + const before = yield* post("server/discover") + assert(Predicate.isObject(before.capabilities)) + assert.notProperty(before.capabilities, "tools") + + const server = yield* Deferred.await(serverReady) + yield* server.addTool({ + tool: new McpSchema.Tool({ name: "LateTool", inputSchema: { type: "object" } }), + annotations: Context.empty(), + handle: () => Effect.succeed(new McpSchema.CallToolResult({ content: [] })) + }) + + assert.deepStrictEqual((yield* post("tools/list")).tools, [ + { name: "LateTool", inputSchema: { type: "object" } } + ]) + const after = yield* post("server/discover") + assert(Predicate.isObject(after.capabilities)) + assert.deepStrictEqual(after.capabilities.tools, { listChanged: false }) + }).pipe(Effect.timeout("2 seconds"))) + + // https://github.com/Effect-TS/effect/issues/9026 + it.live("should let each request's services override the layer services seen by tools", () => + Effect.gen(function*() { + const Label = Context.Reference("test/RequestScoped/Label", { defaultValue: () => "default" }) + const { dispose, handler } = HttpRouter.toWebHandler( + toolLayer("Label", () => + Effect.gen(function*() { + return new McpSchema.CallToolResult({ content: [{ type: "text", text: yield* Label }] }) + })).pipe(Layer.provide(Layer.succeed(Label)("layer"))), + { disableLogger: true } + ) + yield* Effect.addFinalizer(() => Effect.promise(dispose)) + const call = (override?: string) => { + const { body, headers } = callTool("Label", 1) + return Effect.promise(() => + handler( + new Request(MCP_ENDPOINT, { method: "POST", headers, body: JSON.stringify(body) }), + override === undefined ? undefined : Label.context(override) + ) + ).pipe(Effect.flatMap(readMcpHttpResponse)) + } + + for (const override of [undefined, "first", "second"]) { + assert.nestedPropertyVal(yield* call(override), "result.content[0].text", override ?? "layer") + } + })) + + it.live("should serve each POST when timers from completed requests never fire", () => + Effect.gen(function*() { + const worker = yield* makeWorkerdHarness(toolLayer("ReportProgress", reportProgress)) + // The first request builds the server and completes without serving MCP. + const first = yield* worker.request(new Request(MCP_ENDPOINT, { method: "GET" })) + assert.strictEqual(first.status, 405) + + for (const id of [1, 2]) { + const { body, headers } = callTool("ReportProgress", id) + const response = yield* worker.request( + new Request(MCP_ENDPOINT, { method: "POST", headers, body: JSON.stringify(body) }) + ).pipe(Effect.timeoutOrElse({ + duration: "1 second", + orElse: () => Effect.die(`POST ${id} stalled`) + })) + assert.deepStrictEqual(sseMessages(response.body).map((message) => message.method ?? message.id), [ + "notifications/progress", + id + ]) + } + })) + + it.live("should interrupt the handler when the client aborts its POST", () => + Effect.gen(function*() { + const entered = yield* Deferred.make() + const interrupted = yield* Deferred.make() + const { dispose, handler } = HttpRouter.toWebHandler( + toolLayer("Block", () => + Deferred.succeed(entered, undefined).pipe( + Effect.andThen(Effect.never), + Effect.onInterrupt(() => Deferred.succeed(interrupted, undefined)) + )), + { disableLogger: true } + ) + yield* Effect.addFinalizer(() => Effect.promise(dispose)) + const abort = new AbortController() + const { body, headers } = callTool("Block", 1) + const response = handler( + new Request(MCP_ENDPOINT, { method: "POST", headers, body: JSON.stringify(body), signal: abort.signal }) + ) + response.catch(() => undefined) + + yield* Deferred.await(entered) + abort.abort() + yield* Deferred.await(interrupted).pipe(Effect.timeout("1 second")) + })) + + for (const cancel of ["abort", "body"] as const) { + it.live(`should interrupt a streaming handler when the client cancels by ${cancel} after headers`, () => + Effect.gen(function*() { + const interrupted = yield* Deferred.make() + const { dispose, handler } = HttpRouter.toWebHandler( + toolLayer("ProgressThenBlock", (server) => + reportProgress(server).pipe( + Effect.andThen(Effect.never), + Effect.onInterrupt(() => Deferred.succeed(interrupted, undefined)) + )), + { disableLogger: true } + ) + yield* Effect.addFinalizer(() => Effect.promise(dispose)) + const abort = new AbortController() + const { body, headers } = callTool("ProgressThenBlock", 1) + const response = yield* Effect.promise(() => + handler( + new Request(MCP_ENDPOINT, { method: "POST", headers, body: JSON.stringify(body), signal: abort.signal }) + ) + ) + const reader = makeMcpSseReader(response) + yield* Effect.addFinalizer(() => reader.cancel) + assert.strictEqual((yield* reader.take()).method, "notifications/progress") + + if (cancel === "abort") abort.abort() + else yield* reader.cancel + yield* Deferred.await(interrupted).pipe(Effect.timeout("1 second")) + })) + } + + it.live("should interrupt a streaming handler when the client aborts while its unread body is full", () => + Effect.gen(function*() { + const headersSent = yield* Deferred.make() + const backpressured = yield* Deferred.make() + const interrupted = yield* Deferred.make() + const { dispose, handler } = HttpRouter.toWebHandler( + toolLayer("ProgressUnread", (server) => + Effect.gen(function*() { + yield* reportProgress(server) + yield* Deferred.await(headersSent) + // Later chunks arrive while the client reads nothing, so the body stops pulling. + yield* reportProgress(server) + yield* reportProgress(server) + yield* Deferred.succeed(backpressured, undefined) + return yield* Effect.never + }).pipe(Effect.onInterrupt(() => Deferred.succeed(interrupted, undefined)))), + { disableLogger: true } + ) + yield* Effect.addFinalizer(() => Effect.promise(dispose)) + const abort = new AbortController() + const { body, headers } = callTool("ProgressUnread", 1) + const response = yield* Effect.promise(() => + handler( + new Request(MCP_ENDPOINT, { method: "POST", headers, body: JSON.stringify(body), signal: abort.signal }) + ) + ) + yield* Effect.addFinalizer(() => Effect.promise(() => response.body!.cancel())) + yield* Deferred.succeed(headersSent, undefined) + yield* Deferred.await(backpressured) + // Let the body stream take the next chunk and wait for a pull that never comes. + yield* Effect.sleep("50 millis") + + abort.abort() + yield* Deferred.await(interrupted).pipe(Effect.timeout("1 second")) + })) + + it.live("should deliver overlapping requests only their own notifications", () => + Effect.gen(function*() { + const arrived = { a: yield* Deferred.make(), b: yield* Deferred.make() } + const harness = yield* makeHttpHarness(toolLayer("Overlap", (server, { marker }: { marker: "a" | "b" }) => + Effect.gen(function*() { + // Both requests are in flight before either emits a notification. + yield* Deferred.succeed(arrived[marker], undefined) + yield* Deferred.await(arrived[marker === "a" ? "b" : "a"]) + yield* server.notifications["notifications/progress"]({ progressToken, progress: 1, message: marker }) + yield* server.notifications["notifications/message"]({ level: "info", data: marker }) + if (marker === "a") { + yield* server.notifications["notifications/tools/list_changed"]({}) + } + return new McpSchema.CallToolResult({ content: [{ type: "text", text: marker }] }) + }))) + + const responses = yield* Effect.forEach(["a", "b"] as const, (marker) => { + // Both requests reuse the same JSON-RPC id and progress token. + const { body, headers } = callTool("Overlap", 1, { marker }, { + "io.modelcontextprotocol/logLevel": "debug" + }) + return harness.post(body, headers).pipe( + Effect.flatMap((response) => + Effect.promise(() => response.text()) + ), + Effect.map((body) => [marker, sseMessages(body)] as const) + ) + }, { concurrency: "unbounded" }).pipe(Effect.timeout("2 seconds")) + + for (const [marker, messages] of responses) { + assert.deepStrictEqual( + messages.map((message) => [message.method ?? message.id, message.params ?? message.result.content]), + [ + ["notifications/progress", { progressToken, progress: 1, message: marker }], + ["notifications/message", { level: "info", data: marker }], + [1, [{ type: "text", text: marker }]] + ] + ) + } + })) + + it.live("should keep layerHttp notifications when a request-scoped endpoint shares the server", () => + Effect.gen(function*() { + const harness = yield* makeHttpHarness( + toolRegistration("ReportProgress", reportProgress).pipe( + Layer.provideMerge(Layer.merge( + makeServerLayer({ name: "DefaultMode", protocols: [protocol] }), + McpServer.layerHttpRequestScoped({ + name: "RequestMode", + version: "1.0.0", + path: "/request", + protocols: [protocol] + }) + )) + ) + ) + for (const path of ["/mcp", "/request"]) { + const { body, headers } = callTool("ReportProgress", 1) + const response = yield* Effect.promise(() => + harness.handler( + new Request(new URL(path, MCP_ENDPOINT), { method: "POST", headers, body: JSON.stringify(body) }) + ) + ) + const messages = sseMessages(yield* Effect.promise(() => response.text())) + assert.deepStrictEqual(messages.map((message) => message.method ?? message.id), [ + "notifications/progress", + 1 + ], path) + } + }).pipe(Effect.timeout("2 seconds"))) +}) diff --git a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/ElicitationTest.ts b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/ElicitationTest.ts index 4d8877dcfb..c35456eb31 100644 --- a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/ElicitationTest.ts +++ b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/ElicitationTest.ts @@ -82,6 +82,64 @@ export const suite = ( ) => it.layer(layer)(`Mcp Conformance (${protocol.protocolVersion})`, (it) => { describe("Elicitation", () => { + // https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/cancellation + it.effect("MUST cancel the pending HTTP elicitation when its tool call is cancelled", () => + Effect.gen(function*() { + const toolkit = Toolkit.make(Tool.make("Approve", { + parameters: Tool.EmptyParams, + success: Schema.Struct({ approved: Schema.Boolean }), + dependencies: [McpSchema.McpServerClient] + })) + const registration = McpServer.toolkit(toolkit).pipe(Layer.provide( + toolkit.toLayer({ + Approve: () => + McpServer.elicit({ + message: "Approve this operation", + schema: Schema.Struct({ approved: Schema.Boolean }) + }).pipe(Effect.orDie) + }) + )) + const harness = yield* makeHttpHarness(registration.pipe(Layer.provideMerge( + makeServerLayer({ name: "ElicitationCancellationConformance", protocols: [protocol] }) + ))) + const initialized = yield* harness.post({ + jsonrpc: "2.0", + id: "initialize", + method: "initialize", + params: { + protocolVersion: protocol.protocolVersion, + capabilities: { elicitation: {} }, + clientInfo: { name: "approval-client", version: "1.0.0" } + } + }) + yield* readMcpHttpResponse(initialized) + const sessionId = initialized.headers.get("Mcp-Session-Id") + assert.isNotNull(sessionId) + const headers = { "Mcp-Session-Id": sessionId, "Mcp-Protocol-Version": protocol.protocolVersion } + yield* harness.post({ jsonrpc: "2.0", method: "notifications/initialized" }, headers) + const response = yield* harness.post({ + jsonrpc: "2.0", + id: "approval-tool", + method: "tools/call", + params: { name: "Approve", arguments: {} } + }, headers) + const stream = makeMcpSseReader(response) + yield* Effect.addFinalizer(() => stream.cancel) + const reverse = yield* stream.take() + assert.strictEqual(reverse.method, "elicitation/create") + assert.isDefined(reverse.id) + const cancelled = yield* harness.post({ + jsonrpc: "2.0", + method: "notifications/cancelled", + params: { requestId: "approval-tool" } + }, headers) + assert.strictEqual(cancelled.status, 202) + const remaining = yield* stream.drain().pipe(Effect.timeout("1 second")) + assert.deepStrictEqual(remaining.map((message) => message.method), ["notifications/cancelled"]) + assert.propertyVal(remaining[0].params, "requestId", reverse.id) + assert.isFalse(remaining.some((message) => message.method?.startsWith("@effect/rpc/"))) + })) + for (const responseSession of ["missing", "unknown", "unrelated", "owner"] as const) { // https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#session-management // A reverse response must belong to the session that requested the input. diff --git a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/McpConformance.ts b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/McpConformance.ts index 4aacd91650..5f2504bdc9 100644 --- a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/McpConformance.ts +++ b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/McpConformance.ts @@ -205,13 +205,17 @@ export class McpConformance extends Context.Service -export const layer = (protocol: McpProtocol.ProtocolAdapter) => +export const layer = ( + protocol: McpProtocol.ProtocolAdapter, + options?: { readonly mode?: "server" | "request" | undefined } +) => Layer.effect( McpConformance, Effect.gen(function*() { const defaultHarness = yield* makeHttpHarness(makeServerLayer({ name: SERVER_NAME, - protocols: [protocol] + protocols: [protocol], + mode: options?.mode })) const observations = yield* Ref.make({ toolInvocations: 0, @@ -219,7 +223,7 @@ export const layer = (protocol: McpProtocol.ProtocolAdapter) => resourceTemplateInvocations: 0 }) const requestCount = yield* Ref.make(0) - const featuresHarness = yield* makeHttpHarness(makeFeaturesServerLayer(protocol, observations)) + const featuresHarness = yield* makeHttpHarness(makeFeaturesServerLayer(protocol, observations, options?.mode)) const post = ( harness: typeof defaultHarness, body: unknown, diff --git a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/McpConformanceFixtures.ts b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/McpConformanceFixtures.ts index a73c3602af..b6602957df 100644 --- a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/McpConformanceFixtures.ts +++ b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/McpConformanceFixtures.ts @@ -462,7 +462,8 @@ const ContextCompletionPrompt = McpServer.prompt({ export const makeFeaturesServerLayer = ( protocol: McpProtocol.ProtocolAdapter, - observations: Ref.Ref + observations: Ref.Ref, + mode?: "server" | "request" ) => Layer.mergeAll( makeTestToolkitLayer(observations, protocol.protocolVersion), @@ -549,6 +550,7 @@ export const makeFeaturesServerLayer = ( name: "McpConformance", instructions: "Follow the test server instructions.", protocols: [protocol], - extensions: { "example/lifecycle": { enabled: true } } + extensions: { "example/lifecycle": { enabled: true } }, + mode })) ) diff --git a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/SubscriptionsTest.ts b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/SubscriptionsTest.ts index 984cb02afe..1226f1467c 100644 --- a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/SubscriptionsTest.ts +++ b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/SubscriptionsTest.ts @@ -634,7 +634,10 @@ export const suite = (protocol: McpProtocol.ProtocolAdapter, layer: McpConforman params: { _meta: httpMetadata(protocol) } }, { "MCP-Protocol-Version": protocol.protocolVersion, "Mcp-Method": "tools/list" }) assert.match(tools.headers.get("content-type") ?? "", /^application\/json/) - const listed = yield* Effect.promise(() => tools.json()) + const listed = (yield* Effect.promise(() => tools.json())) as { + readonly id: string + readonly result: { readonly tools: ReadonlyArray } + } assert.strictEqual(listed.id, "tools-during-subscription") assert.deepStrictEqual(listed.result.tools, [ { name: "http-subscription-baseline", inputSchema: { type: "object", properties: {} } } diff --git a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/UtilitiesTest.ts b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/UtilitiesTest.ts index 0dd9a581bd..fe6ee9bf48 100644 --- a/repos/effect/packages/effect/test/ai/McpServer/McpConformance/UtilitiesTest.ts +++ b/repos/effect/packages/effect/test/ai/McpServer/McpConformance/UtilitiesTest.ts @@ -8,6 +8,7 @@ import * as Effect from "effect/Effect" import * as Exit from "effect/Exit" import * as Fiber from "effect/Fiber" import * as Layer from "effect/Layer" +import * as Queue from "effect/Queue" import { initializeHttpSession, makeHttpHarness } from "../TestUtils/McpHttpHarness.ts" import { makeMcpSseReader } from "../TestUtils/McpHttpResponse.ts" import { makeServerLayer } from "../TestUtils/McpServerLayer.ts" @@ -404,6 +405,7 @@ export const statefulLegacySuite = (protocol: McpProtocol.ProtocolAdapter, layer assert.isFalse(yield* Deferred.isDone(otherInterrupted)) })) + // https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#sending-messages-to-the-server it.effect("should close without a reply when a tool is cancelled before emitting HTTP output", () => Effect.gen(function*() { const entered = yield* Deferred.make() @@ -436,6 +438,8 @@ export const statefulLegacySuite = (protocol: McpProtocol.ProtocolAdapter, layer assert.strictEqual(cancelled.status, 202) yield* Deferred.await(interrupted).pipe(Effect.timeout("1 second")) const response = yield* Fiber.join(pending).pipe(Effect.timeout("1 second")) + assert.strictEqual(response.status, 200) + assert.strictEqual(response.headers.get("content-type"), "text/event-stream") assert.strictEqual(yield* Effect.promise(() => response.text()), "") })) @@ -509,6 +513,38 @@ export const statefulLegacySuite = (protocol: McpProtocol.ProtocolAdapter, layer assert.strictEqual(yield* Deferred.isDone(otherInterrupted), cancelled === "all") })) } + + it.effect("should close without a reply when every batch request is cancelled before emitting HTTP output", () => + Effect.gen(function*() { + const entered = yield* Queue.unbounded() + const registration = Layer.effectDiscard(McpServer.McpServer.use((server) => + server.addTool({ + tool: new McpSchema.Tool({ name: "Wait", inputSchema: { type: "object" } }), + annotations: Context.empty(), + handle: () => Queue.offer(entered, void 0).pipe(Effect.andThen(Effect.never)) + }) + )) + const harness = yield* makeHttpHarness(registration.pipe(Layer.provideMerge(serverLayer))) + const headers = yield* initializeHttpSession(harness, protocol) + const pending = yield* harness.post( + [1, 2].map((id) => ({ + jsonrpc: "2.0", + id, + method: "tools/call", + params: { name: "Wait", arguments: {} } + })), + headers + ).pipe(Effect.forkChild) + yield* Queue.takeN(entered, 2) + yield* harness.post( + [1, 2].map((requestId) => ({ jsonrpc: "2.0", method: "notifications/cancelled", params: { requestId } })), + headers + ) + const response = yield* Fiber.join(pending).pipe(Effect.timeout("1 second")) + assert.strictEqual(response.status, 200) + assert.strictEqual(response.headers.get("content-type"), "text/event-stream") + assert.strictEqual(yield* Effect.promise(() => response.text()), "") + })) } }) }) diff --git a/repos/effect/packages/effect/test/ai/McpServer/McpServer.test.ts b/repos/effect/packages/effect/test/ai/McpServer/McpServer.test.ts index 05dd823f3a..7e7bc1ba71 100644 --- a/repos/effect/packages/effect/test/ai/McpServer/McpServer.test.ts +++ b/repos/effect/packages/effect/test/ai/McpServer/McpServer.test.ts @@ -538,6 +538,8 @@ describe("McpServer", () => { const outboundMessage = yield* Queue.take(outbound) assert.strictEqual(outboundMessage._tag, clientId === 1 ? "Request" : "Exit") if (clientId === 1) { + assert(outboundMessage._tag === "Request") + assert.strictEqual(outboundMessage.tag, "elicitation/create") yield* send(clientId, { _tag: "Request", id: "", @@ -547,8 +549,12 @@ describe("McpServer", () => { headers: [] }) yield* Deferred.await(cancelled) - // The reverse client emits a control Interrupt; consume it before the next connection. - assert.strictEqual((yield* Queue.take(outbound))._tag, "Interrupt") + // Consume the MCP cancellation before the next connection. + const cancellation = yield* Queue.take(outbound) + assert(cancellation._tag === "Request") + assert.strictEqual(cancellation.tag, "notifications/cancelled") + assert.strictEqual(cancellation.isNotification, true) + assert.deepStrictEqual(cancellation.payload, { requestId: outboundMessage.id }) } yield* send(clientId, { _tag: "Eof" }) connected.delete(clientId) @@ -2163,6 +2169,72 @@ describe("McpServer", () => { })) }) + for ( + const [label, makeLayer] of [ + ["allowSubscriptions is false", () => + McpServer.layerHttp({ + name: "SubscriptionsTest", + version: "1.0.0", + path: "/mcp", + protocols: [McpProtocol.v2026_07_28], + allowSubscriptions: false + })], + ["request scoped", () => + McpServer.layerHttpRequestScoped({ + name: "SubscriptionsTest", + version: "1.0.0", + path: "/mcp", + protocols: [McpProtocol.v2026_07_28] + })] + ] as const + ) { + it.effect(`disables HTTP subscription discovery and listening when ${label}`, () => + Effect.gen(function*() { + const harness = yield* makeHttpHarness( + Layer.effectDiscard(Effect.gen(function*() { + const server = yield* McpServer.McpServer + yield* server.addTool({ + tool: new McpSchema.Tool({ name: "Test", inputSchema: { type: "object" } }), + annotations: Context.empty(), + handle: () => Effect.succeed(new McpSchema.CallToolResult({ content: [] })) + }) + })).pipe(Layer.provideMerge(makeLayer())) + ) + const post = (method: string, params: Record = {}) => + harness.post({ + jsonrpc: "2.0", + id: 1, + method, + params: { + ...params, + _meta: { + "io.modelcontextprotocol/protocolVersion": "2026-07-28", + "io.modelcontextprotocol/clientCapabilities": {} + } + } + }, { "mcp-protocol-version": "2026-07-28", "mcp-method": method }) + + assert.nestedPropertyVal( + yield* readMcpHttpResponse(yield* post("server/discover")), + "result.capabilities.tools.listChanged", + false + ) + const response = yield* post("subscriptions/listen", { notifications: { toolsListChanged: true } }) + // A live subscription never reaches EOF; inspect only its first frame. + if (response.headers.get("content-type")?.includes("text/event-stream")) { + const reader = makeMcpSseReader(response) + yield* Effect.addFinalizer(() => reader.cancel) + const message = yield* reader.take() + assert.strictEqual(message.id, 1) + assert.deepInclude(message.error, { code: -32601 }) + } else { + const message = yield* readMcpHttpResponse(response) + assert.propertyVal(message, "id", 1) + assert.nestedPropertyVal(message, "error.code", -32601) + } + })) + } + it.effect("rejects unsupported HTTP methods without disturbing an initialized session", () => Effect.gen(function*() { const { client, httpClient } = yield* makeTestClient @@ -2564,6 +2636,41 @@ describe("McpServer", () => { }) describe("list-change notification scheduling", () => { + it.live("should not replay startup tool changes to the first HTTP subscription", () => + Effect.gen(function*() { + const kit = Toolkit.make(Tool.make("ping", { success: Schema.String })) + const harness = yield* makeHttpHarness( + McpServer.toolkit(kit).pipe( + Layer.provide(kit.toLayer({ ping: () => Effect.succeed("pong") })), + Layer.provide(makeServerLayer({ name: "StartupNotifications", protocols: [McpProtocol.v2026_07_28] })) + ) + ) + const subscription = makeMcpSseReader( + yield* harness.post({ + jsonrpc: "2.0", + id: 2, + method: "subscriptions/listen", + params: { + notifications: { toolsListChanged: true }, + _meta: { + "io.modelcontextprotocol/protocolVersion": "2026-07-28", + "io.modelcontextprotocol/clientCapabilities": {}, + "io.modelcontextprotocol/clientInfo": { name: "test", version: "1.0.0" } + } + } + }, { "mcp-protocol-version": "2026-07-28", "mcp-method": "subscriptions/listen" }) + ) + yield* Effect.addFinalizer(() => subscription.cancel) + assert.deepInclude(yield* subscription.take(), { + method: "notifications/subscriptions/acknowledged", + params: { + notifications: { toolsListChanged: true }, + _meta: { "io.modelcontextprotocol/subscriptionId": 2 } + } + }) + assert.deepStrictEqual(yield* subscription.take().pipe(Effect.timeoutOption("100 millis")), Option.none()) + })) + it.effect("should coalesce notifications when one registration kind changes repeatedly in a scheduling window", () => Effect.gen(function*() { const fixture = yield* makeMcpStdioHarness(McpProtocol.v2026_07_28) diff --git a/repos/effect/packages/effect/test/ai/McpServer/TestUtils/McpServerLayer.ts b/repos/effect/packages/effect/test/ai/McpServer/TestUtils/McpServerLayer.ts index 625d38b68d..c3573c4662 100644 --- a/repos/effect/packages/effect/test/ai/McpServer/TestUtils/McpServerLayer.ts +++ b/repos/effect/packages/effect/test/ai/McpServer/TestUtils/McpServerLayer.ts @@ -21,19 +21,28 @@ export const makeServerLayer = (options: { readonly extensions?: Readonly> | undefined readonly allowedOrigins?: ReadonlyArray | undefined readonly allowSessionTermination?: boolean | undefined -}) => - McpServer.layerHttp({ + readonly mode?: "server" | "request" | undefined +}) => { + const common = { name: options.name, version: options.version ?? "1.0.0", instructions: options.instructions, - path: "/mcp", + path: "/mcp" as const, protocols: options.protocols ?? [McpProtocol.v2025_06_18], allowedOrigins: ["https://allowed.example"], - extensions: options.extensions, - allowSessionTermination: options.allowSessionTermination - }).pipe( + extensions: options.extensions + } + const layer = options.mode === "request" + ? McpServer.layerHttpRequestScoped({ + ...common, + // Request-mode callers supply stateless adapters. + protocols: common.protocols as Parameters[0]["protocols"] + }) + : McpServer.layerHttp({ ...common, allowSessionTermination: options.allowSessionTermination }) + return layer.pipe( Layer.provideMerge(Layer.succeed( References.CurrentLoggers, new Set([noopLogger]) )) ) +} diff --git a/repos/effect/packages/effect/test/ai/McpServer/TestUtils/McpWorkerdHarness.ts b/repos/effect/packages/effect/test/ai/McpServer/TestUtils/McpWorkerdHarness.ts new file mode 100644 index 0000000000..c166386ece --- /dev/null +++ b/repos/effect/packages/effect/test/ai/McpServer/TestUtils/McpWorkerdHarness.ts @@ -0,0 +1,58 @@ +import * as Effect from "effect/Effect" +import * as HttpRouter from "effect/http/HttpRouter" +import * as Layer from "effect/Layer" +import * as Scheduler from "effect/Scheduler" +import { AsyncLocalStorage } from "node:async_hooks" + +export interface WorkerdResponse { + readonly status: number + readonly headers: Headers + readonly body: string +} + +/** + * Serves requests like a Cloudflare Workers isolate: the app is built while + * the first request is served, and a timer belongs to the request that set it. + * Once a request has finished sending its body, its pending timers never fire. + */ +export const makeWorkerdHarness = Effect.fnUntraced(function*( + serverLayer: Layer.Layer +) { + const owners = new AsyncLocalStorage<{ completed: boolean }>() + const scheduler = new Scheduler.MixedScheduler("async", (task) => { + const owner = owners.getStore() + const timer = setTimeout(() => { + if (owner?.completed !== true) task() + }, 0) + return () => clearTimeout(timer) + }) + const appLayer = serverLayer.pipe( + Layer.provideMerge(Layer.succeed(Scheduler.Scheduler, scheduler)) + ) + let app: { + readonly handler: (request: Request) => Promise + readonly dispose: () => Promise + } | undefined + yield* Effect.addFinalizer(() => Effect.promise(() => app?.dispose() ?? Promise.resolve())) + + const request = (input: Request): Effect.Effect => + Effect.promise((signal) => { + const owner = { completed: false } + signal.addEventListener("abort", () => { + owner.completed = true + }) + return owners.run(owner, async () => { + try { + app ??= HttpRouter.toWebHandler(appLayer, { disableLogger: true }) + const response = await app.handler(input) + // A Workers request completes once its whole body, including SSE, is sent. + const body = await response.text() + return { status: response.status, headers: response.headers, body } + } finally { + owner.completed = true + } + }) + }) + + return { request } as const +}) diff --git a/repos/effect/packages/effect/test/ai/McpServer/Workerd.test.ts b/repos/effect/packages/effect/test/ai/McpServer/Workerd.test.ts new file mode 100644 index 0000000000..01f60510a9 --- /dev/null +++ b/repos/effect/packages/effect/test/ai/McpServer/Workerd.test.ts @@ -0,0 +1,95 @@ +import { assert, describe, it } from "@effect/vitest" +import * as Effect from "effect/Effect" +import * as esbuild from "esbuild" +import { Miniflare } from "miniflare" +import { fileURLToPath } from "node:url" + +const workerPath = fileURLToPath(new URL("./fixtures/workerd.ts", import.meta.url)) + +const bundle = Effect.promise(() => + esbuild.build({ + entryPoints: [workerPath], + bundle: true, + format: "esm", + platform: "browser", + target: "es2022", + conditions: ["workerd", "worker", "browser"], + write: false + }) +).pipe(Effect.map((result) => result.outputFiles[0].text), Effect.cached, Effect.runSync) + +const makeWorker = Effect.gen(function*() { + const contents = yield* bundle + return yield* Effect.acquireRelease( + Effect.sync(() => + new Miniflare({ + workers: [{ + config: { + name: "mcp", + compatibilityDate: "2026-09-11", + compatibilityFlags: ["nodejs_compat"], + manifest: { mainModule: "index.mjs", modules: { "index.mjs": { type: "esm", contents } } } + } + }] + }) + ), + (miniflare) => Effect.promise(() => miniflare.dispose()) + ) +}) + +const progressCall = (id: number): RequestInit => ({ + method: "POST", + headers: { + accept: "application/json, text/event-stream", + "content-type": "application/json", + "MCP-Protocol-Version": "2026-07-28", + "Mcp-Method": "tools/call", + "Mcp-Name": "ReportProgress" + }, + body: JSON.stringify({ + jsonrpc: "2.0", + id, + method: "tools/call", + params: { + name: "ReportProgress", + arguments: {}, + _meta: { + progressToken: "progress-1", + "io.modelcontextprotocol/protocolVersion": "2026-07-28", + "io.modelcontextprotocol/clientCapabilities": {}, + "io.modelcontextprotocol/clientInfo": { name: "test", version: "1.0.0" } + } + } + }) +}) + +// https://github.com/Effect-TS/effect/issues/9026 +describe("McpServer.layerHttpRequestScoped on workerd", () => { + for (const first of ["GET", "warm-up POST"] as const) { + it.live(`should serve repeated progress calls after a ${first} builds the app`, () => + Effect.gen(function*() { + const worker = yield* makeWorker + const fetch = (init: RequestInit) => + Effect.promise(async () => { + const response = await worker.dispatchFetch("http://localhost/mcp", init as any) + return { status: response.status, body: await response.text() } + }).pipe(Effect.timeoutOrElse({ duration: "5 seconds", orElse: () => Effect.die("request stalled") })) + + const built = yield* fetch(first === "GET" ? { method: "GET" } : progressCall(0)) + assert.strictEqual(built.status, first === "GET" ? 405 : 200, built.body) + + for (const id of [1, 2]) { + const response = yield* fetch(progressCall(id)) + // workerd answers 500 when it detects that a request can never complete. + assert.strictEqual(response.status, 200, response.body) + const messages = response.body.split("\n") + .filter((line) => line.startsWith("data: ")) + .map((line) => JSON.parse(line.slice(6))) + assert.deepStrictEqual(messages.map((message) => message.method ?? message.id), [ + "notifications/progress", + id + ]) + } + }), { timeout: 60_000 }) + } +}) diff --git a/repos/effect/packages/effect/test/ai/McpServer/fixtures/workerd.ts b/repos/effect/packages/effect/test/ai/McpServer/fixtures/workerd.ts new file mode 100644 index 0000000000..bec9a93746 --- /dev/null +++ b/repos/effect/packages/effect/test/ai/McpServer/fixtures/workerd.ts @@ -0,0 +1,36 @@ +import * as McpProtocol from "effect/ai/McpProtocol" +import * as McpSchema from "effect/ai/McpSchema" +import * as McpServer from "effect/ai/McpServer" +import * as Context from "effect/Context" +import * as Effect from "effect/Effect" +import * as HttpRouter from "effect/http/HttpRouter" +import * as Layer from "effect/Layer" + +const ReportProgress = Layer.effectDiscard(Effect.gen(function*() { + const server = yield* McpServer.McpServer + yield* server.addTool({ + tool: new McpSchema.Tool({ name: "ReportProgress", inputSchema: { type: "object" } }), + annotations: Context.empty(), + handle: () => + server.notifications["notifications/progress"]({ progressToken: "progress-1", progress: 1 }).pipe( + Effect.as(new McpSchema.CallToolResult({ content: [{ type: "text", text: "done" }] })) + ) + }) +})) + +const app = ReportProgress.pipe(Layer.provideMerge(McpServer.layerHttpRequestScoped({ + name: "Workerd", + version: "1.0.0", + path: "/mcp", + protocols: [McpProtocol.v2026_07_28] +}))) + +let handler: ((request: Request) => Promise) | undefined + +export default { + fetch(request: Request): Promise { + // Build the app while serving the isolate's first request, as Workers apps commonly do. + handler ??= HttpRouter.toWebHandler(app, { disableLogger: true }).handler + return handler(request) + } +} diff --git a/repos/effect/packages/effect/test/ai/OpenAiStructuredOutput.test.ts b/repos/effect/packages/effect/test/ai/OpenAiStructuredOutput.test.ts index a974271dad..334f721660 100644 --- a/repos/effect/packages/effect/test/ai/OpenAiStructuredOutput.test.ts +++ b/repos/effect/packages/effect/test/ai/OpenAiStructuredOutput.test.ts @@ -365,10 +365,14 @@ describe("toCodecOpenAI", () => { describe("Int", () => { it("Int", () => { assertJsonSchema(Schema.Int, { - "type": "integer" + "type": "integer", + "minimum": globalThis.Number.MIN_SAFE_INTEGER, + "maximum": globalThis.Number.MAX_SAFE_INTEGER }) assertJsonSchema(Schema.Int.annotate({ description: "description" }), { "type": "integer", + "minimum": globalThis.Number.MIN_SAFE_INTEGER, + "maximum": globalThis.Number.MAX_SAFE_INTEGER, "description": "description" }) }) @@ -376,6 +380,8 @@ describe("toCodecOpenAI", () => { it("Int + string format", () => { assertJsonSchema(Schema.Int.annotate({ format: "duration" }), { "type": "integer", + "minimum": globalThis.Number.MIN_SAFE_INTEGER, + "maximum": globalThis.Number.MAX_SAFE_INTEGER, "description": "a value with a format of duration" }) }) @@ -383,6 +389,8 @@ describe("toCodecOpenAI", () => { it("Int + unsupported format", () => { assertJsonSchema(Schema.Int.annotate({ format: "int32" }), { "type": "integer", + "minimum": globalThis.Number.MIN_SAFE_INTEGER, + "maximum": globalThis.Number.MAX_SAFE_INTEGER, "description": "a value with a format of int32" }) }) @@ -390,6 +398,7 @@ describe("toCodecOpenAI", () => { it("Int + isGreaterThan", () => { assertJsonSchema(Schema.Int.check(Schema.isGreaterThan(1)), { "type": "integer", + "maximum": globalThis.Number.MAX_SAFE_INTEGER, "description": "a value greater than 1", "exclusiveMinimum": 1 }) @@ -443,7 +452,11 @@ describe("toCodecOpenAI", () => { assertJsonSchema(Schema.Union([Schema.NonEmptyString, Schema.Int]), { "anyOf": [ { "type": "string", "description": "a value with a length of at least 1" }, - { "type": "integer" } + { + "type": "integer", + "minimum": globalThis.Number.MIN_SAFE_INTEGER, + "maximum": globalThis.Number.MAX_SAFE_INTEGER + } ] }) }) diff --git a/repos/effect/packages/effect/test/ai/Prompt.test.ts b/repos/effect/packages/effect/test/ai/Prompt.test.ts index 3a734a3d8f..0fa562b319 100644 --- a/repos/effect/packages/effect/test/ai/Prompt.test.ts +++ b/repos/effect/packages/effect/test/ai/Prompt.test.ts @@ -78,6 +78,40 @@ describe("Prompt", () => { }) describe("fromResponseParts", () => { + it("keeps text before an interleaved tool call", () => { + assert.deepStrictEqual( + Prompt.fromResponseParts([ + Response.makePart("text-start", { id: "t1" }), + Response.makePart("text-delta", { id: "t1", delta: "Hello" }), + Response.makePart("tool-call", { + id: "call-1", + name: "get_weather", + params: {}, + providerExecuted: false + }), + Response.makePart("text-end", { id: "t1" }) + ]), + Prompt.make([{ + role: "assistant", + content: [ + { type: "text", text: "Hello" }, + { type: "tool-call", id: "call-1", name: "get_weather", params: {}, providerExecuted: false } + ] + }]) + ) + }) + + it("omits unended reasoning and empty unended text", () => { + assert.deepStrictEqual( + Prompt.fromResponseParts([ + Response.makePart("text-start", { id: "t1" }), + Response.makePart("reasoning-start", { id: "r1" }), + Response.makePart("reasoning-delta", { id: "r1", delta: "Unsigned thinking" }) + ]), + Prompt.empty + ) + }) + it("preserves file-only responses as assistant messages", () => { const file = Response.makePart("file", { data: new Uint8Array([0, 127, 128, 255]), diff --git a/repos/effect/packages/effect/test/cli/Command.test.ts b/repos/effect/packages/effect/test/cli/Command.test.ts index 377ec74205..667e882191 100644 --- a/repos/effect/packages/effect/test/cli/Command.test.ts +++ b/repos/effect/packages/effect/test/cli/Command.test.ts @@ -1,6 +1,6 @@ import { assert, describe, expect, it } from "@effect/vitest" import { Context, Effect, Fiber, FileSystem, Layer, Option, Path, Redacted, Runtime, Stdio } from "effect" -import { Argument, CliConfig, CliError, CliOutput, Command, Flag, GlobalFlag } from "effect/cli" +import { Argument, CliConfig, CliError, CliOutput, Command, Flag, GlobalFlag, Prompt } from "effect/cli" import { toImpl } from "effect/cli/internal/command" import { ChildProcessSpawner } from "effect/process" import { TestConsole } from "effect/testing" @@ -47,6 +47,21 @@ const TestLayerWithoutFormatter = Layer.mergeAll( ) describe("Command", () => { + it.effect("omits styles from wizard headings and command blocks when colors are disabled", () => + Effect.gen(function*() { + const command = Command.make("greet", { name: Flag.String("name") }, () => Effect.void) + + const fiber = yield* Command.runWith(command, { version: "1.0.0" })(["--wizard"]).pipe(Effect.forkChild) + yield* MockTerminal.inputText("Alice") + yield* MockTerminal.inputKey("enter") + yield* MockTerminal.inputKey("enter") + yield* Fiber.join(fiber) + + const logs = (yield* TestConsole.logLines).join("\n") + assert.include(logs, "$ greet --name Alice") + assert.notMatch(logs, new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`)) + }).pipe(Effect.provide([TestLayer, Layer.succeed(Prompt.Theme, Prompt.makeTheme({ colors: false }))]))) + describe("annotations", () => { it.effect("should expose annotations in help docs", () => Effect.gen(function*() { @@ -350,11 +365,23 @@ describe("Command", () => { assert.isFalse(invoked) assert.isTrue( stderr.some((line) => - String(line).includes("Missing value for flag --completions. Expected: bash | zsh | fish | sh") + String(line).includes( + "Missing value for flag --completions. Expected: bash | zsh | fish | powershell | sh | pwsh" + ) ) ) }).pipe(Effect.provide(TestLayer))) + it.effect("should print PowerShell completions for --completions pwsh", () => + Effect.gen(function*() { + const command = Command.make("demo") + + yield* Command.runWith(command, { version: "1.0.0" })(["--completions", "pwsh"]) + + const stdout = (yield* TestConsole.logLines).join("\n") + assert.include(stdout, "Register-ArgumentCompleter -Native -CommandName 'demo'") + }).pipe(Effect.provide(TestLayer))) + const missingValueCases: ReadonlyArray<{ readonly flag: Flag.Flag readonly name: string @@ -406,6 +433,62 @@ describe("Command", () => { ) }).pipe(Effect.provide(TestLayer))) + describe("withOptionalValue", () => { + const watchFlag = Flag.Literals("watch", ["first-failure", "until-done"]).pipe( + Flag.withAlias("w"), + Flag.withOptionalValue("first-failure") + ) + + it.effect("uses the optional value for a bare flag without consuming the next token", () => + Effect.gen(function*() { + const captured: Array = [] + const command = Command.make("app", { + watch: watchFlag, + files: Argument.String("file").pipe(Argument.variadic()) + }, (config) => Effect.sync(() => captured.push(config))) + const run = Command.runWith(command, { version: "1.0.0" }) + + yield* run(["-w", "until-done"]) + yield* run(["--watch=until-done"]) + + assert.deepStrictEqual(captured, [ + { watch: "first-failure", files: ["until-done"] }, + { watch: "until-done", files: [] } + ]) + }).pipe(Effect.provide(TestLayer))) + + it.effect("does not consume a boolean literal after a negated flag", () => + Effect.gen(function*() { + const captured: Array = [] + const command = Command.make("app", { + watch: Flag.Boolean("watch").pipe(Flag.withOptionalValue("true")), + files: Argument.String("file").pipe(Argument.variadic()) + }, (config) => Effect.sync(() => captured.push(config))) + + yield* Command.runWith(command, { version: "1.0.0" })(["--no-watch", "false"]) + + assert.deepStrictEqual(captured, [{ watch: false, files: ["false"] }]) + }).pipe(Effect.provide(TestLayer))) + + it.effect("emits the wizard value inline", () => + Effect.gen(function*() { + const captured: Array> = [] + const target = Command.make("app", { watch: watchFlag }) + const command = Command.make("launcher", {}, () => + Effect.flatMap(Command.wizard(target), (args) => + Effect.sync(() => { + captured.push(args) + }))) + + const fiber = yield* Command.runWith(command, { version: "1.0.0" })([]).pipe(Effect.forkChild) + yield* MockTerminal.inputKey("down") + yield* MockTerminal.inputKey("enter") + yield* Fiber.join(fiber) + + assert.deepStrictEqual(captured, [["app", "--watch=until-done"]]) + }).pipe(Effect.provide(TestLayer))) + }) + it.effect("should execute handler with parsed config", () => Effect.gen(function*() { const path = yield* Path.Path diff --git a/repos/effect/packages/effect/test/cli/Help.test.ts b/repos/effect/packages/effect/test/cli/Help.test.ts index 2d05ebb7fb..989d3fade6 100644 --- a/repos/effect/packages/effect/test/cli/Help.test.ts +++ b/repos/effect/packages/effect/test/cli/Help.test.ts @@ -38,6 +38,17 @@ const runCommand = Effect.fnUntraced( } ) +describe("CliOutput.displayWidth", () => { + it("measures terminal cells", () => { + assert.strictEqual(CliOutput.displayWidth(""), 0) + assert.strictEqual(CliOutput.displayWidth("file"), 4) + assert.strictEqual(CliOutput.displayWidth("ファイル"), 8) + assert.strictEqual(CliOutput.displayWidth("e\u0301"), 1) + assert.strictEqual(CliOutput.displayWidth("1️⃣"), 2) + assert.strictEqual(CliOutput.displayWidth("\u001B[31mファイル\u001B[0m"), 8) + }) +}) + describe("Command help output", () => { it("marks omittable flags as not required in structured help", () => { const command = Command.make("app", { @@ -50,6 +61,14 @@ describe("Command help output", () => { assert.deepStrictEqual(help.flags.map((flag) => flag.required), [true, false, false]) }) + it("renders the type of a flag with an optional value as optional", () => { + const command = Command.make("app", { + watch: Flag.Literals("watch", ["first-failure", "until-done"]).pipe(Flag.withOptionalValue("first-failure")) + }) + const help = toImpl(command).buildHelpDoc(["app"]) + assert.deepStrictEqual(help.flags.map((flag) => flag.type), ["[=choice]"]) + }) + it("marks omittable arguments as not required in structured help", () => { const requiredVariadic = Command.make("app", { files: Argument.String("files").pipe(Argument.variadic({ min: 1 })) @@ -91,7 +110,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none) SUBCOMMANDS @@ -341,7 +360,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none) EXAMPLES @@ -386,7 +405,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none)" `) }).pipe(Effect.provide(TestLayer))) @@ -417,7 +436,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none)" `) }).pipe(Effect.provide(TestLayer))) @@ -446,7 +465,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none)" `) }).pipe(Effect.provide(TestLayer))) @@ -478,7 +497,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none)" `) }).pipe(Effect.provide(TestLayer))) @@ -505,7 +524,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none) SUBCOMMANDS @@ -540,7 +559,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none)" `) }).pipe(Effect.provide(TestLayer))) @@ -641,7 +660,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none) SUBCOMMANDS @@ -684,7 +703,7 @@ describe("Command help output", () => { --help, -h Show help information --version, -v Show version information --wizard Start wizard mode for a command - --completions Print shell completion script (choices: bash, zsh, fish, sh) + --completions Print shell completion script (choices: bash, zsh, fish, powershell, sh, pwsh) --log-level Sets the minimum log level (choices: all, trace, debug, info, warn, warning, error, fatal, none) SUBCOMMANDS diff --git a/repos/effect/packages/effect/test/cli/Prompt.test.ts b/repos/effect/packages/effect/test/cli/Prompt.test.ts index a4a5c917c4..0ebf0ff4c7 100644 --- a/repos/effect/packages/effect/test/cli/Prompt.test.ts +++ b/repos/effect/packages/effect/test/cli/Prompt.test.ts @@ -1,16 +1,35 @@ import { assert, describe, it } from "@effect/vitest" -import { Data, DateTime, Deferred, Effect, Fiber, FileSystem, Layer, Match, Path, Queue, Redacted } from "effect" +import { + Data, + DateTime, + Deferred, + Effect, + Fiber, + FileSystem, + Layer, + Match, + Path, + Queue, + Redacted, + Terminal +} from "effect" import { Prompt } from "effect/cli" +import { afterEach, vi } from "vitest" import * as MockTerminal from "./services/MockTerminal.ts" const FileSystemLayer = FileSystem.layerNoop({}) const PathLayer = Path.layer const TerminalLayer = MockTerminal.layer +// Styling assertions assume a color-capable terminal, independent of the test +// process environment. +const ThemeLayer = Layer.succeed(Prompt.Theme, Prompt.makeTheme({ colors: true })) + const TestLayer = Layer.mergeAll( FileSystemLayer, PathLayer, - TerminalLayer + TerminalLayer, + ThemeLayer ) const Action = Data.taggedEnum() @@ -49,6 +68,44 @@ const toRawFrames = (lines: ReadonlyArray) => const findFrame = (frames: ReadonlyArray, text: string) => frames.find((frame) => frame.includes(text)) +describe("Prompt colors", () => { + describe("makeTheme detection", { concurrent: false }, () => { + const isTTY = Object.getOwnPropertyDescriptor(process.stdout, "isTTY") + + afterEach(() => { + vi.unstubAllEnvs() + if (isTTY === undefined) { + delete (process.stdout as { isTTY?: boolean }).isTTY + } else { + Object.defineProperty(process.stdout, "isTTY", isTTY) + } + }) + + it("disables colors when NO_COLOR is set on a TTY", () => { + Object.defineProperty(process.stdout, "isTTY", { value: true, configurable: true }) + vi.stubEnv("NO_COLOR", "1") + + assert.isFalse(Prompt.makeTheme().colors) + }) + }) + + it.effect("omits styles when the context theme disables colors", () => + Effect.gen(function*() { + yield* MockTerminal.inputKey("enter") + yield* Prompt.run(Prompt.Select({ + message: "Choose a color", + choices: [{ title: "Blue", value: "blue" }] + })) + + const output = (yield* MockTerminal.displayLines).join("\n") + assert.include(output, "Choose a color") + assert.notMatch(output, new RegExp(`${escape}\\[[0-9;]*m`)) + }).pipe( + Effect.provideService(Prompt.Theme, Prompt.makeTheme({ colors: false })), + Effect.provide(TestLayer) + )) +}) + describe("Prompt.Date", () => { it.effect("renders two-digit years, teen ordinals, and noon meridiem correctly", () => Effect.gen(function*() { @@ -116,6 +173,31 @@ describe("Prompt.Date", () => { }).pipe(Effect.provide(TestLayer))) }) +describe("Prompt.succeed", () => { + it.effect("does not acquire terminal input", () => + Effect.gen(function*() { + const terminal = yield* Terminal.Terminal + let acquisitions = 0 + const result = yield* Prompt.run(Prompt.succeed("x")).pipe( + Effect.provideService( + Terminal.Terminal, + Terminal.make({ + ...terminal, + readInput: Effect.andThen( + Effect.sync(() => { + acquisitions++ + }), + terminal.readInput + ) + }) + ) + ) + + assert.strictEqual(result, "x") + assert.strictEqual(acquisitions, 0) + }).pipe(Effect.provide(TestLayer))) +}) + describe("Prompt.all", () => { it.effect("supports an empty record", () => Effect.gen(function*() { @@ -252,6 +334,7 @@ describe("Prompt.String", () => { Effect.provideService( Prompt.Theme, Prompt.makeTheme({ + colors: true, primaryColor: `${escape}[31m`, mutedColor: `${escape}[34m`, successColor: `${escape}[33m`, diff --git a/repos/effect/packages/effect/test/cli/completions/completions.test.ts b/repos/effect/packages/effect/test/cli/completions/completions.test.ts index d48ba776ac..c03a325365 100644 --- a/repos/effect/packages/effect/test/cli/completions/completions.test.ts +++ b/repos/effect/packages/effect/test/cli/completions/completions.test.ts @@ -4,6 +4,7 @@ import * as Completions from "effect/cli/Completions" import * as Bash from "effect/cli/internal/completions/bash" import { fromCommand } from "effect/cli/internal/completions/descriptor" import * as Fish from "effect/cli/internal/completions/fish" +import * as PowerShell from "effect/cli/internal/completions/powershell" import * as Zsh from "effect/cli/internal/completions/zsh" import { ComprehensiveCli } from "../fixtures/ComprehensiveCli.ts" @@ -124,6 +125,14 @@ const emptyCmd = Command.make("noop").pipe( Command.withDescription("Does nothing") ) +const leaf = (name: string, flag: string): Completions.CommandDescriptor => ({ + name, + description: undefined, + flags: [{ name: flag, aliases: [], description: undefined, type: { _tag: "Boolean" } }], + arguments: [], + subcommands: [] +}) + const choicesHelperSource = (script: string): string => { const start = script.indexOf("_deploy--choices()") const end = script.indexOf("\n}\n", start) @@ -465,6 +474,14 @@ describe("Zsh completions", () => { ) }) + it("escapes a closing bracket in flag descriptions", () => { + const cmd = Command.make("deploy", { + level: Flag.Literals("level", ["debug", "info"]).pipe(Flag.withDescription("Log level [info]")) + }) + const script = Zsh.generate("deploy", fromCommand(cmd)) + assert.include(script, `'(--level)--level[Log level [info\\]]:value:(debug info)'`) + }) + it("uses alternative argument sets for positional arguments and subcommands", () => { const desc = fromCommand(withOptionalDirectoryAndSubcommands) const script = Zsh.generate("example", desc) @@ -550,13 +567,6 @@ describe("Zsh completions", () => { describe("Fish completions", () => { it("scopes nested completions by the full command path", () => { - const leaf = (name: string, flag: string): Completions.CommandDescriptor => ({ - name, - description: undefined, - flags: [{ name: flag, aliases: [], description: undefined, type: { _tag: "Boolean" } }], - arguments: [], - subcommands: [] - }) const descriptor: Completions.CommandDescriptor = { name: "tool", description: undefined, @@ -782,6 +792,103 @@ describe("Fish completions", () => { }) }) +// --------------------------------------------------------------------------- +// PowerShell completions +// --------------------------------------------------------------------------- + +describe("PowerShell completions", () => { + it("registers a native completer with a context per subcommand path", () => { + const script = PowerShell.generate("top", fromCommand(nested3Levels)) + assert.include(script, `Register-ArgumentCompleter -Native -CommandName 'top'`) + assert.include(script, `['sub'] = @{`) + assert.include(script, `['sub action'] = @{`) + assert.include(script, `@{ name = 'action'; description = 'Perform action' }`) + }) + + it("emits flag forms, choice values and path types", () => { + const simple = PowerShell.generate("greet", fromCommand(simpleCmd)) + assert.include( + linesWith(simple, "name = 'loud'"), + `forms = @('--loud', '-l'); takesValue = $false` + ) + assert.include(linesWith(simple, "name = 'times'"), `forms = @('--times'); takesValue = $true`) + + const choices = PowerShell.generate("deploy", fromCommand(withChoices)) + assert.include(choices, `values = @('dev', 'staging', 'prod')`) + assert.include(choices, `values = @('us-east', 'eu-west', 'ap-south')`) + + const paths = PowerShell.generate("process", fromCommand(withPaths)) + assert.include(paths, `pathType = 'file'`) + assert.include(paths, `pathType = 'directory'`) + assert.include(paths, `[System.Management.Automation.CompletionCompleters]::CompleteFilename($typed)`) + assert.include(paths, `$entry.pathType -eq 'directory' -and $file.ResultType -ne 'ProviderContainer'`) + }) + + it("offers only positional values after --", () => { + const script = PowerShell.generate("server", fromCommand(withSubcommands)) + assert.include(script, `if ($endOfOptions) { $position++; continue }`) + assert.include(script, `if ($word -ceq '--') { $endOfOptions = $true; continue }`) + assert.include(script, `if (-not $endOfOptions) {`) + }) + + it("does not treat an option as a pending flag value", () => { + const script = PowerShell.generate("server", fromCommand(withSubcommands)) + assert.match(script, /if \(\$flag\.takesValue\) \{\s+if \(-not \$isOption\) \{ continue \}/) + assert.include(script, "if ($null -ne $pending -and $pending.takesValue -and -not $typedIsOption) {") + }) + + it("completes a negative number as a value, not a flag", () => { + const script = PowerShell.generate("server", fromCommand(withSubcommands)) + assert.notInclude(script, "$typed.StartsWith('-')") + assert.include(script, "if ($typedIsOption) {") + }) + + it("offers option-shaped choices only where the CLI reads them as values", () => { + const script = PowerShell.generate("server", fromCommand(withSubcommands)) + assert.include(script, "& $optionLike $value") + }) + + it("tracks used flags case-sensitively", () => { + const script = PowerShell.generate("server", fromCommand(withSubcommands)) + assert.notInclude(script, "$used = @{}") + assert.include(script, "$used = [hashtable]::new([System.StringComparer]::Ordinal)") + }) + + it("emits non-ASCII text as [char] code units", () => { + const script = PowerShell.generate("deploy", fromCommand(withTrickyChoices)) + assert.notMatch(script, /[^\n\x20-\x7e]/) + assert.include(script, `('a' + [char]0xD83D + [char]0xDE00 + 'b')`) + }) + + it("preserves line breaks in choice values", () => { + const cmd = Command.make("tool", { mode: Flag.Literals("mode", ["line\nbreak"]) }) + const script = PowerShell.generate("tool", fromCommand(cmd)) + assert.include(script, `values = @(('line' + [char]0x000A + 'break'))`) + }) + + it("escapes values for single-quoted PowerShell literals", () => { + const script = PowerShell.generate("deploy", fromCommand(withTrickyChoices)) + assert.include(script, `'it''s-fine'`) + assert.include(script, `'foo'''`) + assert.include(script, `'o''clock'`) + assert.include(script, `'$HOME'`) + }) + + it("keeps case-distinct subcommand contexts and emits a repeated path once", () => { + const script = PowerShell.generate("tool", { + name: "tool", + description: undefined, + flags: [], + arguments: [], + subcommands: [leaf("config", "lower"), leaf("config", "lower"), leaf("Config", "upper")] + }) + assert.lengthOf(script.match(/\['config'\] = @\{/g) ?? [], 1) + assert.lengthOf(script.match(/\['Config'\] = @\{/g) ?? [], 1) + assert.lengthOf(script.match(/forms = @\('--lower'\)/g) ?? [], 1) + assert.lengthOf(script.match(/forms = @\('--upper'\)/g) ?? [], 1) + }) +}) + // --------------------------------------------------------------------------- // Completions dispatcher // --------------------------------------------------------------------------- @@ -804,6 +911,12 @@ describe("Completions", () => { const script = Completions.generate("greet", "fish", desc) assert.include(script, "complete -c greet") }) + + it("dispatches to powershell generator", () => { + const desc = fromCommand(simpleCmd) + const script = Completions.generate("greet", "powershell", desc) + assert.include(script, `Register-ArgumentCompleter -Native -CommandName 'greet'`) + }) }) // --------------------------------------------------------------------------- @@ -913,3 +1026,26 @@ describe("Completions integration", () => { assert.include(script, "__fish_seen_subcommand_from git") }) }) + +describe("Flags with an optional value", () => { + it("do not take the next word as the flag value", () => { + const descriptor = fromCommand(Command.make("app", { + watch: Flag.Literals("watch", ["first-failure", "until-done"]).pipe( + Flag.withAlias("w"), + Flag.withDescription("Watch mode"), + Flag.withOptionalValue("first-failure") + ), + file: Argument.Literals("file", ["one", "two"]) + })) + + const bash = Bash.generate("app", descriptor) + assert.notInclude(bash, "--watch|-w)\n") + assert.include(bash, "--watch|-w) ;;") + assert.include( + Zsh.generate("app", descriptor), + `'(--watch -w)--watch=-[Watch mode]::value:(first-failure until-done)'` + ) + assert.notInclude(Fish.generate("app", descriptor), "-a 'first-failure until-done'") + assert.include(PowerShell.generate("app", descriptor), "optionalValue = $true;") + }) +}) diff --git a/repos/effect/packages/effect/test/cluster/ClusterWorkflowEngine.test.ts b/repos/effect/packages/effect/test/cluster/ClusterWorkflowEngine.test.ts index 69dd948289..f1d2792acb 100644 --- a/repos/effect/packages/effect/test/cluster/ClusterWorkflowEngine.test.ts +++ b/repos/effect/packages/effect/test/cluster/ClusterWorkflowEngine.test.ts @@ -12,6 +12,7 @@ import { Logger, Option, Result, + Schedule, Schema, Scope, Tracer @@ -21,6 +22,9 @@ import { ClusterSchema, ClusterWorkflowEngine, Entity, + EntityAddress, + EntityId, + EntityType, MessageStorage, RunnerHealth, Runners, @@ -40,6 +44,188 @@ import { } from "effect/workflow/WorkflowEngine" describe.concurrent("ClusterWorkflowEngine", () => { + it.effect("wakes an activity deferred completed before a parallel sibling lets the workflow suspend", () => + Effect.gen(function*() { + const gate = DurableDeferred.make("EarlyActivityWake/Gate", { success: Schema.String }) + const workflow = Workflow.make("EarlyActivityWake", { + payload: {}, + success: Schema.Array(Schema.String), + idempotencyKey: () => "one" + }) + const siblingStarted = yield* Latch.make() + const releaseSibling = yield* Latch.make() + const activityParked = yield* Latch.make() + const awaitGate = Activity.make({ + name: "await-gate", + success: Schema.String, + execute: siblingStarted.await.pipe( + Effect.andThen(DurableDeferred.await(gate)), + Effect.onInterrupt(() => activityParked.open) + ) + }) + const block = Activity.make({ + name: "block", + success: Schema.String, + execute: siblingStarted.open.pipe(Effect.andThen(releaseSibling.await), Effect.as("blocked")) + }) + let activations = 0 + const context = yield* Layer.build( + workflow.toLayer(() => { + activations++ + // Yield the activities themselves so both run through the workflow engine. + return Effect.all([awaitGate, block], { concurrency: "unbounded" }) + }).pipe(Layer.provideMerge(makeTestWorkflowEngine())) + ) + yield* Effect.gen(function*() { + const sharding = yield* Sharding.Sharding + const executionId = yield* workflow.execute({}, { discard: true }) + yield* activityParked.await + for (let i = 0; i < 5; i++) { + yield* TestClock.adjust(1) + yield* sharding.pollStorage + } + assert.isTrue(Option.isNone(yield* workflow.poll(executionId))) + const completion = yield* DurableDeferred.succeed(gate, { + token: DurableDeferred.tokenFromExecutionId(gate, { workflow, executionId }), + value: "done" + }).pipe(Effect.forkChild({ startImmediately: true })) + // Deliver the callback while the sibling still prevents the parent from suspending. + for (let i = 0; i < 5; i++) { + yield* TestClock.adjust(1) + yield* sharding.pollStorage + } + assert.isTrue(Option.isNone(yield* workflow.poll(executionId))) + yield* releaseSibling.open + assert.deepStrictEqual( + yield* pollUntil(workflow, executionId, "Complete"), + new Workflow.Complete({ exit: Exit.succeed(["done", "blocked"]) }) + ) + yield* Fiber.join(completion) + assert.strictEqual(activations, 2) + }).pipe(Effect.provide(context)) + })) + + it.effect("answers an orphaned activity after restart even when replay never registers it", () => + Effect.gen(function*() { + const release = DurableDeferred.make("OrphanActivity/Release") + const workflow = Workflow.make("OrphanActivity", { + payload: {}, + success: Schema.Void, + idempotencyKey: () => "one" + }) + const storage = yield* makeSharedStorage + const storageLayer = Layer.succeed(MessageStorage.MessageStorage, storage) + const layer = (crash = false) => + workflow.toLayer(() => DurableDeferred.await(release)).pipe( + Layer.provideMerge(makeTestWorkflowEngine({ + storageLayer: crash ? unansweredActivityStorage(storage) : storageLayer + })) + ) + const executionId = yield* workflow.executionId({}) + const requestId = yield* Effect.gen(function*() { + yield* workflow.execute({}, { discard: true }) + yield* pollUntil(workflow, executionId, "Suspended") + // Crash residue: the losing request is durable, but its Interrupt is absent. + return yield* sendUnregisteredActivity(workflow._tag, executionId) + }).pipe(Effect.provide(layer(true))) + assert.deepStrictEqual(yield* storage.repliesForUnfiltered([requestId]), []) + + yield* Effect.gen(function*() { + yield* (yield* Sharding.Sharding).pollStorage + assert.deepStrictEqual(yield* activityReply(storage, requestId), Exit.succeed(new Workflow.Suspended({}))) + yield* DurableDeferred.succeed(release, { + token: DurableDeferred.tokenFromExecutionId(release, { workflow, executionId }), + value: undefined + }) + assert.deepStrictEqual( + yield* pollUntil(workflow, executionId, "Complete"), + new Workflow.Complete({ exit: Exit.void }) + ) + assert.deepStrictEqual(yield* activityReply(storage, requestId), Exit.succeed(new Workflow.Suspended({}))) + }).pipe(Effect.provide(layer())) + })) + + it.effect("retries an early activity registered while its Suspended reply is still being persisted", () => + Effect.gen(function*() { + const workflow = Workflow.make("EarlyActivity", { + payload: {}, + success: Schema.Number, + idempotencyKey: () => "one" + }) + const register = yield* Latch.make() + const savingReply = yield* Latch.make() + const releaseReply = yield* Latch.make() + const registrationRequested = yield* Latch.make() + let executions = 0 + let activityRequests = 0 + const activity = Activity.make({ + name: "loser", + success: Schema.Number, + execute: Effect.sync(() => ++executions) + }) + const storage = yield* makeSharedStorage + const storageLayer = Layer.succeed(MessageStorage.MessageStorage, { + ...storage, + saveReply: (reply) => { + if (reply.rpc._tag === "activity" && !savingReply.isOpen()) { + assert(reply.reply._tag === "WithExit") + assert(reply.reply.exit._tag === "Success") + assert(Schema.is(Workflow.Suspended)(reply.reply.exit.value)) + return savingReply.open.pipe( + Effect.andThen(releaseReply.await), + Effect.andThen(storage.saveReply(reply)) + ) + } + return storage.saveReply(reply) + }, + saveRequest: (request) => + storage.saveRequest(request).pipe( + Effect.tap(() => { + if (request.rpc._tag !== "activity") return Effect.void + // Bound a broken reset/resend loop so this regression fails instead of exhausting memory. + assert.isAtMost(++activityRequests, 20, "activity reset/resend must not livelock on Suspended") + return registrationRequested.open + }) + ) + }) + const executionId = yield* workflow.executionId({}) + const requestId = yield* sendUnregisteredActivity(workflow._tag, executionId).pipe(Effect.provide( + workflow.toLayer(() => activity).pipe(Layer.provideMerge(makeTestWorkflowEngine({ + storageLayer: unansweredActivityStorage(storage) + }))) + )) + assert.deepStrictEqual(yield* storage.repliesForUnfiltered([requestId]), []) + yield* Effect.gen(function*() { + yield* workflow.execute({}, { discard: true }) + yield* (yield* Sharding.Sharding).pollStorage + for (let i = 0; i < 200 && !savingReply.isOpen(); i++) yield* TestClock.adjust(1) + assert.isTrue(savingReply.isOpen()) + assert.deepStrictEqual(yield* storage.repliesForUnfiltered([requestId]), []) + assert.strictEqual(executions, 0) + yield* register.open + // The replay has registered and requested the same activity before the early reply commits. + for (let i = 0; i < 200 && !registrationRequested.isOpen(); i++) yield* TestClock.adjust(1) + assert.isTrue(registrationRequested.isOpen()) + assert.deepStrictEqual(yield* storage.repliesForUnfiltered([requestId]), []) + assert.strictEqual(executions, 0) + yield* releaseReply.open + assert.deepStrictEqual( + yield* pollUntil(workflow, executionId, "Complete"), + new Workflow.Complete({ exit: Exit.succeed(1) }) + ) + assert.strictEqual(executions, 1) + // Registration must reset the stored Suspended reply, not allocate a new attempt. + assert.deepStrictEqual( + yield* activityReply(storage, requestId), + Exit.succeed(new Workflow.Complete({ exit: Exit.succeed(1) })) + ) + }).pipe(Effect.provide( + workflow.toLayer(() => register.await.pipe(Effect.andThen(activity))).pipe( + Layer.provideMerge(makeTestWorkflowEngine({ storageLayer })) + ) + )) + })) + it.effect("does not replay for an unawaited deferred checkpoint", () => Effect.gen(function*() { const checkpoint = DurableDeferred.make("UnawaitedCheckpoint/Checkpoint") @@ -79,6 +265,74 @@ describe.concurrent("ClusterWorkflowEngine", () => { }).pipe(Effect.provide(context)) })) + it.effect("advances a durable race continuation while a sibling is parked", () => + expectContinuesBesideParkedSibling( + "ParkedSiblingRace", + DurableDeferred.raceAll({ + name: "race", + success: Schema.String, + error: Schema.Never, + effects: [ + Workflow.wrapActivityResult(Effect.as(Effect.sleep(1000), "timer"), () => false), + DurableDeferred.await(DurableDeferred.make("ParkedSiblingRace/Cancel")).pipe(Effect.as("cancel")) + ] + }) + ), 20_000) + + it.effect( + "advances a DurableDeferred.into continuation while a sibling is parked", + () => + expectContinuesBesideParkedSibling( + "ParkedSiblingInto", + // Not an activity: `into` itself keeps the run active until the exit is recorded. + Effect.as(Effect.sleep(1000), "timer").pipe( + DurableDeferred.into(DurableDeferred.make("ParkedSiblingInto/Result", { success: Schema.String })) + ) + ), + 20_000 + ) + + it.effect( + "lets an active sibling finish before a DurableDeferred.into body parks the run", + () => + Effect.gen(function*() { + const gate = DurableDeferred.make("ActiveSiblingInto/Gate", { success: Schema.String }) + const result = DurableDeferred.make("ActiveSiblingInto/Result", { success: Schema.String }) + const workflow = Workflow.make("ActiveSiblingInto", { + payload: {}, + success: Schema.String, + idempotencyKey: () => "one" + }) + const nextStepRuns: Array = [] + const context = yield* Layer.build( + workflow.toLayer(() => + Effect.all([ + Workflow.wrapActivityResult(Effect.sleep(100), () => false).pipe( + Effect.andThen(nextStepActivity(nextStepRuns, "sibling")) + ), + DurableDeferred.await(gate).pipe(DurableDeferred.into(result)) + ], { concurrency: "unbounded" }).pipe(Effect.map(([sibling, value]) => `${sibling}:${value}`)) + ).pipe(Layer.provideMerge(makeTestWorkflowEngine())) + ) + yield* Effect.gen(function*() { + const executionId = yield* workflow.execute({}, { discard: true }) + // The parked body must not suspend the run while the sibling is counted. + yield* pollUntil(workflow, executionId, "Suspended") + assert.deepStrictEqual(nextStepRuns, ["sibling"]) + yield* DurableDeferred.succeed(gate, { + token: DurableDeferred.tokenFromExecutionId(gate, { workflow, executionId }), + value: "gate" + }) + assert.deepStrictEqual( + yield* pollUntil(workflow, executionId, "Complete"), + new Workflow.Complete({ exit: Exit.succeed("sibling:next:gate") }) + ) + assert.deepStrictEqual(nextStepRuns, ["sibling"]) + }).pipe(Effect.provide(context)) + }), + 20_000 + ) + it.effect("retries a deferred wake after a transient run reset failure", () => Effect.gen(function*() { const gate = DurableDeferred.make("ResetRetry/Gate", { success: Schema.String }) @@ -478,6 +732,84 @@ describe.concurrent("ClusterWorkflowEngine", () => { }), 30_000) } + it.effect("wakes a suspended caller when its workflow completes", () => + Effect.gen(function*() { + const retrying = yield* Latch.make() + const gate = DurableDeferred.make("CompletionWake/Gate", { success: Schema.String }) + const workflow = Workflow.make("CompletionWake", { + payload: {}, + success: Schema.String, + idempotencyKey: () => "one", + // The retry stays the fallback, but is too slow to deliver within the test. + suspendedRetrySchedule: Schedule.spaced("1 hour").pipe(Schedule.tap(() => retrying.open)) + }) + const context = yield* Layer.build( + workflow.toLayer(() => DurableDeferred.await(gate)).pipe(Layer.provideMerge(makeTestWorkflowEngine())) + ) + yield* Effect.gen(function*() { + const executionId = yield* workflow.executionId({}) + const fiber = yield* workflow.execute({}).pipe(Effect.forkChild({ startImmediately: true })) + yield* pollUntil(workflow, executionId, "Suspended") + yield* advanceUntil(() => retrying.isOpen(), "caller must wait on its retry schedule") + yield* DurableDeferred.succeed(gate, { + token: DurableDeferred.tokenFromExecutionId(gate, { workflow, executionId }), + value: "done" + }) + yield* pollUntil(workflow, executionId, "Complete") + yield* advanceUntil(() => fiber.pollUnsafe() !== undefined, "completion must wake the caller", 1, 1000) + assert.strictEqual(yield* Fiber.join(fiber), "done") + }).pipe(Effect.provide(context)) + })) + + it.effect("delivers a completion through the retry schedule when the wake is lost", () => + Effect.gen(function*() { + let dropWakes = false + let handlers = 0 + const gate = DurableDeferred.make("LostWake/Gate", { success: Schema.String }) + const workflow = Workflow.make("LostWake", { + payload: {}, + success: Schema.String, + idempotencyKey: () => "one", + // Once the caller first waits, no reply notification reaches it. + suspendedRetrySchedule: Schedule.spaced("10 seconds").pipe(Schedule.tap(() => + Effect.sync(() => { + dropWakes = true + }) + )) + }) + const storageLayer = Layer.effect( + MessageStorage.MessageStorage, + Effect.map(Effect.service(MessageStorage.MessageStorage), (storage) => ({ + ...storage, + registerReplyHandler: (message) => + Effect.suspend(() => { + handlers++ + return dropWakes ? Effect.never : storage.registerReplyHandler(message) + }).pipe(Effect.ensuring(Effect.sync(() => handlers--))) + })) + ).pipe(Layer.provide(MessageStorage.layerMemory)) + const context = yield* Layer.build( + workflow.toLayer(() => DurableDeferred.await(gate)).pipe( + Layer.provideMerge(makeTestWorkflowEngine({ storageLayer })) + ) + ) + yield* Effect.gen(function*() { + const executionId = yield* workflow.executionId({}) + const fiber = yield* workflow.execute({}).pipe(Effect.forkChild({ startImmediately: true })) + yield* pollUntil(workflow, executionId, "Suspended") + yield* advanceUntil(() => dropWakes, "caller must wait on its retry schedule") + yield* DurableDeferred.succeed(gate, { + token: DurableDeferred.tokenFromExecutionId(gate, { workflow, executionId }), + value: "done" + }) + yield* pollUntil(workflow, executionId, "Complete") + assert.isUndefined(fiber.pollUnsafe(), "a lost wake must leave the caller on its schedule") + yield* advanceUntil(() => fiber.pollUnsafe() !== undefined, "the schedule must deliver the completion", 1000) + assert.strictEqual(yield* Fiber.join(fiber), "done") + assert.strictEqual(handlers, 0, "the caller must release its reply handlers") + }).pipe(Effect.provide(context)) + })) + it.effect("executes, resumes, deduplicates, and polls a suspended workflow", () => Effect.gen(function*() { const sharding = yield* Sharding.Sharding @@ -742,7 +1074,7 @@ describe.concurrent("ClusterWorkflowEngine", () => { ) it.effect( - "DurableDeferred.raceAll replays the run when a losing deferred completes late", + "DurableDeferred.raceAll does not replay the run when a losing deferred completes late", () => Effect.gen(function*() { const flags = yield* Flags @@ -769,8 +1101,8 @@ describe.concurrent("ClusterWorkflowEngine", () => { } expect(yield* Fiber.join(fiber)).toEqual("activity:tail") - // The late completion preempts the tail; the replay re-executes it. - expect(flags.get("losing-deferred-tail-runs")).toEqual(2) + // The race already settled, so the late completion must not preempt the tail. + expect(flags.get("losing-deferred-tail-runs")).toEqual(1) }).pipe(Effect.provide(TestWorkflowLayer)), 20_000 ) @@ -1337,6 +1669,227 @@ describe.concurrent("ClusterWorkflowEngine", () => { }).pipe(Effect.provide(Layer.mergeAll(ParentLayer, ChildLayer).pipe(Layer.provideMerge(TestWorkflowLayer)))) })) + it.effect("keeps a failure-suspended workflow parked when a discarded child completes", () => + Effect.gen(function*() { + let failures = 0 + const ChildGate = DurableDeferred.make("FailureParkedChildGate") + const Parent = Workflow.make("FailureParked", { + payload: {}, + idempotencyKey: () => "parent" + }).annotate(Workflow.SuspendOnFailure, true) + const Child = Workflow.make("FailureParkedChild", { + payload: {}, + idempotencyKey: () => "child" + }) + const ParentLayer = Parent.toLayer(Effect.fnUntraced(function*() { + yield* Child.execute({}, { discard: true }) + yield* Activity.make({ + name: "fail", + execute: Effect.suspend(() => { + failures++ + return Effect.die("boom") + }) + }) + })) + const ChildLayer = Child.toLayer(() => DurableDeferred.await(ChildGate)) + yield* Effect.gen(function*() { + const sharding = yield* Sharding.Sharding + const settle = Effect.gen(function*() { + for (let i = 0; i < 20; i++) { + yield* TestClock.adjust(1) + yield* sharding.pollStorage + } + }) + yield* TestClock.adjust(1) + const executionId = yield* Parent.execute({}, { discard: true }) + const childId = yield* Child.executionId({}) + yield* pollUntil(Parent, executionId, "Suspended") + + yield* DurableDeferred.succeed(ChildGate, { + token: DurableDeferred.tokenFromExecutionId(ChildGate, { workflow: Child, executionId: childId }), + value: void 0 + }) + yield* pollUntil(Child, childId, "Complete") + yield* settle + assert.strictEqual(failures, 1, "only an explicit resume may replay the failed activity") + + yield* Parent.resume(executionId) + yield* settle + assert.strictEqual(failures, 2) + }).pipe(Effect.provide(Layer.mergeAll(ParentLayer, ChildLayer).pipe(Layer.provideMerge(TestWorkflowLayer)))) + })) + + it.effect("persists a detached child's parent without waking it", () => + Effect.gen(function*() { + let parentRuns = 0 + const ParentGate = DurableDeferred.make("DetachedParentGate") + const ChildGate = DurableDeferred.make("DetachedChildGate") + const Parent = Workflow.make("DetachedParent", { + payload: {}, + idempotencyKey: () => "parent" + }) + const Child = Workflow.make("DetachedChild", { + payload: {}, + idempotencyKey: () => "child" + }) + const ParentLayer = Parent.toLayer(Effect.fnUntraced(function*() { + parentRuns++ + yield* Child.execute({}, { discard: true, detached: true }) + yield* DurableDeferred.await(ParentGate) + })) + const ChildLayer = Child.toLayer(() => DurableDeferred.await(ChildGate)) + yield* Effect.gen(function*() { + const sharding = yield* Sharding.Sharding + const driver = yield* MessageStorage.MemoryDriver + yield* TestClock.adjust(1) + const executionId = yield* Parent.execute({}, { discard: true }) + const childId = yield* Child.executionId({}) + yield* pollUntil(Parent, executionId, "Suspended") + assert.strictEqual(parentRuns, 1) + + // The parent stays recorded on the child for observability. + const childRun = Array.from(driver.requests.values()).find(({ envelope }) => + envelope._tag === "Request" && envelope.tag === "run" && + envelope.address.entityType === `Workflow/${Child._tag}` + ) + assert(childRun && childRun.envelope._tag === "Request") + assert.deepStrictEqual( + (childRun.envelope.payload as Record)[ + "~effect/cluster/ClusterWorkflowEngine/payloadParentKey" + ], + { workflowName: Parent._tag, executionId, detached: true } + ) + + yield* DurableDeferred.succeed(ChildGate, { + token: DurableDeferred.tokenFromExecutionId(ChildGate, { workflow: Child, executionId: childId }), + value: void 0 + }) + yield* pollUntil(Child, childId, "Complete") + for (let i = 0; i < 20; i++) { + yield* TestClock.adjust(1) + yield* sharding.pollStorage + } + assert.strictEqual(parentRuns, 1, "a detached child must not wake its parent") + }).pipe(Effect.provide(Layer.mergeAll(ParentLayer, ChildLayer).pipe(Layer.provideMerge(TestWorkflowLayer)))) + })) + + it.effect("interrupts a failure-suspended workflow", () => + Effect.gen(function*() { + let attempts = 0 + const Failing = Workflow.make("FailureInterrupted", { + payload: {}, + idempotencyKey: () => "failing" + }).annotate(Workflow.SuspendOnFailure, true) + const FailingLayer = Failing.toLayer(() => + Activity.make({ + name: "fail", + execute: Effect.suspend(() => { + attempts++ + return Effect.die("boom") + }) + }) + ) + yield* Effect.gen(function*() { + yield* TestClock.adjust(1) + const executionId = yield* Failing.execute({}, { discard: true }) + yield* pollUntil(Failing, executionId, "Suspended") + yield* Failing.interrupt(executionId) + const result = yield* pollUntil(Failing, executionId, "Complete") + assert(result._tag === "Complete" && Exit.hasInterrupts(result.exit)) + assert.strictEqual(attempts, 1, "interrupt must not re-run the failed activity") + }).pipe(Effect.provide(FailingLayer.pipe(Layer.provideMerge(TestWorkflowLayer)))) + })) + + it.effect("interrupts a workflow parked inside an activity", () => + Effect.gen(function*() { + const Gate = DurableDeferred.make("ActivityParkedGate") + const Parent = Workflow.make("ActivityParkedParent", { + payload: {}, + idempotencyKey: () => "parent" + }) + const Child = Workflow.make("ActivityParkedChild", { + payload: {}, + idempotencyKey: () => "child" + }) + // The activity's stored reply is `Suspended` while it awaits the child. + const ParentLayer = Parent.toLayer(() => Activity.make({ name: "await-child", execute: Child.execute({}) })) + const ChildLayer = Child.toLayer(() => DurableDeferred.await(Gate)) + yield* Effect.gen(function*() { + yield* TestClock.adjust(1) + const executionId = yield* Parent.execute({}, { discard: true }) + yield* pollUntil(Parent, executionId, "Suspended") + yield* Parent.interrupt(executionId) + const result = yield* pollUntil(Parent, executionId, "Complete") + assert(result._tag === "Complete" && Exit.hasInterrupts(result.exit)) + }).pipe(Effect.provide(Layer.mergeAll(ParentLayer, ChildLayer).pipe(Layer.provideMerge(TestWorkflowLayer)))) + })) + + it.effect("applies a persisted interrupt when a fresh owner replays a failure-suspended workflow", () => + Effect.gen(function*() { + let attempts = 0 + const Failing = Workflow.make("FailureInterruptedRecovery", { + payload: {}, + idempotencyKey: () => "failing" + }).annotate(Workflow.SuspendOnFailure, true) + const storage = yield* makeSharedStorage + // The first owner records the interrupt and resets the run, but crashes + // before the reset run is redelivered. + let crashed = false + const crashingStorage = Layer.succeed(MessageStorage.MessageStorage, { + ...storage, + unprocessedMessages: (shardIds, options) => + Effect.map( + storage.unprocessedMessages(shardIds, options), + (messages) => + crashed + ? messages.filter((message) => message.envelope._tag !== "Request" || message.envelope.tag !== "run") + : messages + ) + }) + const layer = (storageLayer: Layer.Layer) => + Failing.toLayer(() => + Activity.make({ + name: "flaky", + // A retry would succeed, so a replay that runs it completes normally. + execute: Effect.suspend(() => ++attempts === 1 ? Effect.die("boom") : Effect.void) + }) + ).pipe(Layer.provideMerge(makeTestWorkflowEngine({ storageLayer }))) + const executionId = yield* Failing.executionId({}) + + yield* Effect.gen(function*() { + yield* TestClock.adjust(1) + yield* Failing.execute({}, { discard: true }) + yield* pollUntil(Failing, executionId, "Suspended") + crashed = true + yield* Failing.interrupt(executionId) + let result = yield* Failing.poll(executionId) + for (let i = 0; i < 2000 && Option.isSome(result); i++) { + yield* TestClock.adjust(1) + result = yield* Failing.poll(executionId) + } + assert(Option.isNone(result), "the interrupt must reset the run") + }).pipe(Effect.provide(layer(crashingStorage))) + + // The fresh owner's first read of the persisted interrupt fails once. + let lookupFailed = false + const flakyStorage = Layer.succeed(MessageStorage.MessageStorage, { + ...storage, + requestIdForPrimaryKey: (options) => { + if (!lookupFailed && options.tag === "deferred" && options.id === "Workflow/InterruptSignal") { + lookupFailed = true + return Effect.fail(new ClusterError.PersistenceError({ cause: "transient interrupt lookup failure" })) + } + return storage.requestIdForPrimaryKey(options) + } + }) + yield* Effect.gen(function*() { + const result = yield* pollUntil(Failing, executionId, "Complete") + assert(lookupFailed, "the interrupt lookup must fail once") + assert(result._tag === "Complete" && Exit.hasInterrupts(result.exit), "the replay must complete as interrupted") + assert.strictEqual(attempts, 1, "a fresh owner must not re-run the failed activity") + }).pipe(Effect.provide(layer(flakyStorage))) + })) + it.effect("coalesces parked child wakeups while parent cleanup is pending", () => Effect.gen(function*() { const cleaningUp = yield* Latch.make() @@ -1863,6 +2416,59 @@ describe.concurrent("ClusterWorkflowEngine", () => { }).pipe(Effect.provide(TestWorkflowLayer))) }) +const RecoveryActivityRpc = Rpc.make("activity", { + payload: { name: Schema.String, attempt: Schema.Int, withTransaction: Schema.Boolean }, + primaryKey: ({ name, attempt }) => `${name}/${attempt}`, + success: Workflow.Result({ success: Schema.Any, error: Schema.Any }) +}).annotate(ClusterSchema.Persisted, true) + +// Shared across runners so a later runner sees the previous runner's residue. +const makeSharedStorage = Effect.map( + Layer.build(MessageStorage.layerMemory.pipe(Layer.provide(ShardingConfig.layerDefaults))), + (context) => Context.get(context, MessageStorage.MessageStorage) +) + +// Preserve the unanswered request across runner teardown, even once recovery is fixed. +const unansweredActivityStorage = (storage: MessageStorage.MessageStorage["Service"]) => + Layer.succeed(MessageStorage.MessageStorage, { + ...storage, + saveReply: (reply) => reply.rpc._tag === "activity" ? Effect.never : storage.saveReply(reply) + }) + +const sendUnregisteredActivity = (workflowName: string, executionId: string) => + Effect.gen(function*() { + const entity = Entity.make(`Workflow/${workflowName}`, [RecoveryActivityRpc]) + const client = yield* entity.client + yield* client(executionId).activity({ name: "loser", attempt: 1, withTransaction: false }, { discard: true }) + const sharding = yield* Sharding.Sharding + const storage = yield* MessageStorage.MessageStorage + const entityId = EntityId.make(executionId) + const requestId = yield* storage.requestIdForPrimaryKey({ + address: EntityAddress.make({ + entityType: EntityType.make(entity.type), + entityId, + shardId: sharding.getShardId(entityId, "default") + }), + tag: "activity", + id: "loser/1" + }) + assert(Option.isSome(requestId)) + return requestId.value + }) + +const activityReply = (storage: MessageStorage.MessageStorage["Service"], requestId: Snowflake.Snowflake) => + Effect.gen(function*() { + for (let i = 0; i < 200; i++) { + const replies = yield* storage.repliesForUnfiltered([requestId]) + const reply = replies[replies.length - 1] + if (reply?._tag === "WithExit") { + return Schema.decodeUnknownSync(Schema.toCodecJson(Rpc.exitSchema(RecoveryActivityRpc)))(reply.exit) + } + yield* TestClock.adjust(1) + } + assert.fail("unregistered activity must receive a terminal Suspended reply without waiting for registration") + }) + const makeTestWorkflowEngine = (options?: { readonly config?: Partial | undefined readonly shardingLayer?: typeof Sharding.layer | undefined @@ -1912,6 +2518,65 @@ const pollUntil = ( return result.value }) +const nextStepActivity = (runs: Array, label: string) => + Activity.make({ + name: "next-step", + success: Schema.String, + execute: Effect.sync(() => { + runs.push(label) + return `${label}:next` + }) + }) + +/** + * Runs `body` and then a `next-step` activity beside a branch parked on an + * unrelated durable event. `next-step` must run before that event arrives, + * and exactly once. Deferred writes made by `body` are delayed to stand in + * for a persistence round trip. + */ +const expectContinuesBesideParkedSibling = ( + name: string, + body: Effect.Effect +) => + Effect.gen(function*() { + const workflow = Workflow.make(name, { + payload: {}, + success: Schema.String, + idempotencyKey: () => "one" + }) + const event = DurableDeferred.make(`${name}/Event`) + const nextStepRuns: Array = [] + const context = yield* Layer.build( + workflow.toLayer(() => + Effect.gen(function*() { + const engine = yield* WorkflowEngine + const delayed = Effect.provideService(body, WorkflowEngine, { + ...engine, + deferredDone: (deferred, done) => Effect.delay(engine.deferredDone(deferred, done), 10) + }) + const [result] = yield* Effect.all([ + Effect.flatMap(delayed, (value) => nextStepActivity(nextStepRuns, value)), + DurableDeferred.await(event) + ], { concurrency: "unbounded" }) + return result + }) + ).pipe(Layer.provideMerge(makeTestWorkflowEngine())) + ) + yield* Effect.gen(function*() { + const executionId = yield* workflow.execute({}, { discard: true }) + yield* advanceUntil(() => nextStepRuns.length > 0, "next-step must run before the event", 10, 300) + yield* DurableDeferred.succeed(event, { + token: DurableDeferred.tokenFromExecutionId(event, { workflow, executionId }), + value: undefined + }) + assert.deepStrictEqual( + yield* pollUntil(workflow, executionId, "Complete"), + new Workflow.Complete({ exit: Exit.succeed("timer:next") }) + ) + assert.deepStrictEqual(nextStepRuns, ["timer"]) + }).pipe(Effect.provide(context)) + }) + const advanceUntil = (ready: () => boolean, message: string, step = 1, rounds = 2000) => Effect.gen(function*() { for (let i = 0; i < rounds && !ready(); i++) yield* TestClock.adjust(step) diff --git a/repos/effect/packages/effect/test/cluster/Runners.test.ts b/repos/effect/packages/effect/test/cluster/Runners.test.ts index 94e1d598ff..bd200c2137 100644 --- a/repos/effect/packages/effect/test/cluster/Runners.test.ts +++ b/repos/effect/packages/effect/test/cluster/Runners.test.ts @@ -1,5 +1,5 @@ import { assert, describe, it } from "@effect/vitest" -import { Cause, Context, Deferred, Effect, Exit, Layer, Option, Queue, Schema, Stream } from "effect" +import { Cause, Context, Deferred, Effect, Exit, Fiber, Layer, Option, Queue, Schema, Stream } from "effect" import { ClusterError, ClusterSchema, @@ -11,7 +11,7 @@ import { HttpRunner, Message, MessageStorage, - type Reply, + Reply, RunnerAddress, RunnerHealth, Runners, @@ -312,6 +312,89 @@ describe.concurrent("Runners.makeRpc", () => { Layer.provide(TestShardingConfig) ) + const layerLocalRunners = ( + wrap: (storage: MessageStorage.MessageStorage["Service"]) => MessageStorage.MessageStorage["Service"] = (storage) => + storage + ) => + Runners.layerNoop.pipe( + Layer.provideMerge( + Layer.effect(MessageStorage.MessageStorage)( + Effect.map(MessageStorage.MessageStorage, wrap) + ).pipe(Layer.provide(MessageStorage.layerMemory)) + ), + Layer.provideMerge(Snowflake.layerGenerator), + Layer.provide(ShardingConfig.layer({ entityReplyPollInterval: "1 hour" })) + ) + + const saveReply = ( + storage: MessageStorage.MessageStorage["Service"], + message: Message.OutgoingRequest, + id: Snowflake.Snowflake + ) => + storage.saveReply( + new Reply.ReplyWithContext({ + reply: new Reply.WithExit({ id, requestId: message.envelope.requestId, exit: Exit.succeed(42) }), + rpc: message.rpc, + context: message.context + }) + ) + + it.effect("delivers a persisted local reply completed before saveRequest returns", () => { + let complete: Effect.Effect = Effect.void + return Effect.gen(function*() { + const runners = yield* Runners.Runners + const storage = yield* MessageStorage.MessageStorage + const snowflake = yield* Snowflake.Generator + const replies: Array> = [] + const message = makeOutgoingRequest(TestRpcPersisted, snowflake.nextUnsafe(), (reply) => + Effect.sync(() => { + if (reply._tag === "WithExit") replies.push(reply.exit) + })) + complete = saveReply(storage, message, snowflake.nextUnsafe()).pipe(Effect.orDie) + const pending = yield* runners.notifyLocal({ message, discard: false, notify: () => Effect.void }).pipe( + Effect.timeoutOption("1 second"), + Effect.forkScoped + ) + yield* TestClock.adjust("1 second") + assert.isTrue(Option.isSome(yield* Fiber.join(pending)), "the caller must complete") + assert.deepStrictEqual(replies, [Exit.succeed(42)]) + }).pipe(Effect.provide(layerLocalRunners((storage) => ({ + ...storage, + saveRequest: (message) => storage.saveRequest(message).pipe(Effect.tap(() => complete)) + })))) + }) + + it.effect("keeps a duplicate local waiter alive when the first caller cancels", () => + Effect.gen(function*() { + const runners = yield* Runners.Runners + const storage = yield* MessageStorage.MessageStorage + const snowflake = yield* Snowflake.Generator + const requestId = snowflake.nextUnsafe() + const firstReplies: Array> = [] + const duplicateReplies: Array> = [] + const first = makeOutgoingRequest(TestRpcPersisted, requestId, (reply) => + Effect.sync(() => { + firstReplies.push(reply) + })) + const duplicate = makeOutgoingRequest(TestRpcPersisted, requestId, (reply) => + Effect.sync(() => { + if (reply._tag === "WithExit") duplicateReplies.push(reply.exit) + })) + const notify = (message: Message.OutgoingRequest) => + runners.notifyLocal({ message, discard: false, notify: () => Effect.void }) + const a = yield* notify(first).pipe(Effect.forkScoped) + yield* TestClock.adjust(0) + const b = yield* notify(duplicate).pipe(Effect.timeoutOption("1 second"), Effect.forkScoped) + yield* TestClock.adjust(0) + yield* Fiber.interrupt(a) + yield* saveReply(storage, first, snowflake.nextUnsafe()) + // Drain runnable work without reaching the one-hour polling deadline. + yield* TestClock.adjust(0) + assert.deepStrictEqual(firstReplies, []) + assert.deepStrictEqual(duplicateReplies, [Exit.succeed(42)]) + assert.isTrue(Option.isSome(yield* Fiber.join(b)), "the surviving caller must complete without polling") + }).pipe(Effect.provide(layerLocalRunners()))) + it.effect("uses the client protocol codec for simulated remote serialization", () => { let codecCalls = 0 const codecFor = ((schema: S) => { diff --git a/repos/effect/packages/effect/test/cluster/Sharding.test.ts b/repos/effect/packages/effect/test/cluster/Sharding.test.ts index c2f63a21b7..93b5146fa0 100644 --- a/repos/effect/packages/effect/test/cluster/Sharding.test.ts +++ b/repos/effect/packages/effect/test/cluster/Sharding.test.ts @@ -6,6 +6,7 @@ import { Context, Deferred, Effect, + Equal, Exit, Fiber, Latch, @@ -18,6 +19,7 @@ import { Result, Schedule, Schema, + Scope, Stream } from "effect" import { @@ -46,7 +48,7 @@ import * as EntityManager from "effect/cluster/internal/entityManager" import { EntityReaper } from "effect/cluster/internal/entityReaper" import * as ActiveTeardown from "effect/cluster/internal/interruptors" import { Headers } from "effect/http" -import { Rpc, type RpcGroup } from "effect/rpc" +import { Rpc, type RpcGroup, type RpcSerialization } from "effect/rpc" import { TestClock } from "effect/testing" import { CallerId, @@ -59,6 +61,8 @@ import { } from "./TestEntity.ts" // Isolate the long-lived stream from concurrent shard-metric tests. +// Use a nonzero assignment refresh interval when advancing through claim expiry +// so the runner-storage sync loop does not busy-poll between clock ticks. describe("Sharding claim release regressions", { concurrent: false }, () => { it.effect("keeps the claim of an active request replayed after an entity defect", () => Effect.gen(function*() { @@ -94,7 +98,7 @@ describe("Sharding claim release regressions", { concurrent: false }, () => { }) }), { defectRetryPolicy: Schedule.forever } - ).pipe(Layer.provideMerge(CappedSharding({}, (storage) => ({ + ).pipe(Layer.provideMerge(CappedSharding({ refreshAssignmentsInterval: 60_000 }, (storage) => ({ ...storage, resetRequests: (ids) => Effect.gen(function*() { @@ -173,7 +177,7 @@ describe("Sharding claim release regressions", { concurrent: false }, () => { yield* Queue.offer(started, starts) return yield* Effect.never }).pipe(Effect.ensuring(Effect.sync(() => active--))) - }).pipe(Layer.provideMerge(CappedSharding({}, (storage) => ({ + }).pipe(Layer.provideMerge(CappedSharding({ refreshAssignmentsInterval: 60_000 }, (storage) => ({ ...storage, resetRequests: (ids) => Effect.gen(function*() { @@ -273,7 +277,7 @@ describe("Sharding claim release regressions", { concurrent: false }, () => { expect(values).toEqual([0]) assert.strictEqual(released.length, 0, "active stream claim must not be released after a chunk") assert.strictEqual(claimed.length, 1, "active stream must not be reclaimed on every poll") - }).pipe(Effect.provide(CappedSharding({}, (storage) => ({ + }).pipe(Effect.provide(CappedSharding({ refreshAssignmentsInterval: 60_000 }, (storage) => ({ ...storage, saveEnvelope: (message) => storage.saveEnvelope(message).pipe( @@ -362,9 +366,8 @@ describe("Sharding claim release regressions", { concurrent: false }, () => { }) })))) })) -}) -describe.concurrent("Sharding", () => { + // Keep the ten-minute clock advance out of the concurrent Sharding batch. it.effect("redelivers a request reset while an asynchronous storage read is pending", () => Effect.gen(function*() { const readStarted = yield* Deferred.make() @@ -408,7 +411,7 @@ describe.concurrent("Sharding", () => { 1, "reset request was claimed but not redelivered before claim expiry" ) - }).pipe(Effect.provide(CappedSharding({ refreshAssignmentsInterval: 1000 }, (storage) => ({ + }).pipe(Effect.provide(CappedSharding({ refreshAssignmentsInterval: 60_000 }, (storage) => ({ ...storage, unprocessedMessages: (shardIds, options) => Effect.gen(function*() { @@ -423,7 +426,9 @@ describe.concurrent("Sharding", () => { }) })))) })) +}) +describe.concurrent("Sharding", () => { for (const pauseReply of [false, true]) { it.effect( pauseReply @@ -1711,8 +1716,168 @@ describe.concurrent("Sharding", () => { Layer.provide(TestShardingConfig) ))) })) + + it.effect("WithTransaction persists a failure reply after rollback", () => + Effect.gen(function*() { + const state = yield* TestEntityState + const makeClient = yield* TestEntity.client + yield* TestClock.adjust(1) + const client = makeClient("1") + + const first = yield* Effect.flip(client.FailWithTransaction({ id: 1 })) + assert.strictEqual(first._tag, "BoomError") + + // The retry must be answered from storage without rerunning the handler. + const retry = yield* client.FailWithTransaction({ id: 1 }).pipe( + Effect.flip, + Effect.timeout(5000), + Effect.forkChild + ) + yield* TestClock.adjust(5000) + const second = yield* Fiber.join(retry) + assert.strictEqual(second._tag, "BoomError") + assert.strictEqual(Queue.sizeUnsafe(state.envelopes), 1) + }).pipe(Effect.provide(TestShardingWithoutStorage.pipe( + // Replies saved inside a failed transaction are discarded, like a SQL + // rollback. + Layer.updateService(MessageStorage.MessageStorage, (storage) => { + let saved: Array = [] + return { + ...storage, + withTransaction: (effect) => + storage.withTransaction(effect).pipe( + Effect.onExit((exit) => { + const rolledBack = saved + saved = [] + return Exit.isFailure(exit) + ? Effect.forEach(rolledBack, (id) => Effect.orDie(storage.clearReplies(id)), { discard: true }) + : Effect.void + }) + ), + saveReply: (reply) => + MessageStorage.MemoryTransaction.use((inTransaction) => { + if (inTransaction) saved.push(reply.reply.requestId) + return storage.saveReply(reply) + }) + } + }), + Layer.provide(MessageStorage.layerMemory), + Layer.provide(TestShardingConfig) + )))) + + it.effect("WithTransaction persists a client interrupt instead of replaying the request", () => + Effect.gen(function*() { + const driver = yield* MessageStorage.MemoryDriver + const state = yield* TestEntityState + const makeClient = yield* TestEntity.client + yield* TestClock.adjust(1) + + const fiber = yield* makeClient("1").NeverWithTransaction().pipe(Effect.forkChild({ startImmediately: true })) + yield* TestClock.adjust(1) + yield* Fiber.interrupt(fiber) + + yield* TestClock.adjust(1) + expect(driver.replyIds.size).toEqual(1) + expect(Queue.sizeUnsafe(state.envelopes)).toEqual(1) + }).pipe(Effect.provide(TestSharding))) + + it.effect("WithTransaction delivers a success only after commit", () => + Effect.gen(function*() { + const committing = Latch.makeUnsafe() + const commit = Latch.makeUnsafe() + yield* Effect.gen(function*() { + const makeClient = yield* TestEntity.client + yield* TestClock.adjust(1) + const result = yield* makeClient("1").WithTransaction({ id: 1 }).pipe(Effect.forkChild) + + yield* committing.await + yield* TestClock.adjust(1000) + assert.isUndefined(result.pollUnsafe()) + + yield* commit.open + assert.isTrue(yield* Fiber.join(result)) + }).pipe(Effect.provide(TestShardingWithoutStorage.pipe( + Layer.provide(RollbackMemoryStorage((transaction) => + Effect.tap(transaction, () => Effect.andThen(committing.open, commit.await)) + )), + Layer.provide(TestShardingConfig) + ))) + })) + + it.effect("WithTransaction replays the request without replying when COMMIT dies", () => + Effect.gen(function*() { + const state = yield* TestEntityState + const makeClient = yield* TestEntity.client + yield* TestClock.adjust(1) + + // Count handler runs when the reply arrives: only the replay may reply. + const result = yield* makeClient("1").WithTransaction({ id: 1 }).pipe( + Effect.map((value) => [value, Queue.sizeUnsafe(state.envelopes)] as const), + Effect.forkChild + ) + yield* TestClock.adjust(5000) + assert.deepStrictEqual(yield* Fiber.join(result), [true, 2]) + }).pipe(Effect.provide(TestShardingWithoutStorage.pipe( + Layer.provide(RollbackMemoryStorage((transaction, attempt) => + attempt === 1 ? Effect.andThen(transaction, Effect.die("COMMIT failed")) : transaction + )), + Layer.provide(TestShardingConfig) + )))) + + it.effect("WithTransaction replays the request without replying when ROLLBACK dies", () => + Effect.gen(function*() { + const state = yield* TestEntityState + const makeClient = yield* TestEntity.client + yield* TestClock.adjust(1) + + // Count handler runs when the reply arrives: only the replay may reply. + const result = yield* makeClient("1").FailWithTransaction({ id: 1 }).pipe( + Effect.flip, + Effect.map((error) => [error._tag, Queue.sizeUnsafe(state.envelopes)] as const), + Effect.forkChild + ) + yield* TestClock.adjust(5000) + assert.deepStrictEqual(yield* Fiber.join(result), ["BoomError", 2]) + }).pipe(Effect.provide(TestShardingWithoutStorage.pipe( + Layer.provide(RollbackMemoryStorage((transaction, attempt) => + attempt === 1 ? Effect.catchCause(transaction, () => Effect.die("ROLLBACK failed")) : transaction + )), + Layer.provide(TestShardingConfig) + )))) }) +// Memory storage that discards replies saved inside a failed transaction, like +// a SQL rollback. `wrap` runs around each transaction with its 1-based attempt. +const RollbackMemoryStorage = ( + wrap: (transaction: Effect.Effect, attempt: number) => Effect.Effect +) => + Layer.effect( + MessageStorage.MessageStorage, + Effect.gen(function*() { + const { encoded } = yield* MessageStorage.MemoryDriver + let attempts = 0 + let saved: Array = [] + return yield* MessageStorage.makeEncoded({ + ...encoded, + withTransaction: (effect) => + Effect.suspend(() => wrap(encoded.withTransaction(effect), ++attempts)).pipe( + Effect.onExit((exit) => { + const rolledBack = saved + saved = [] + return Exit.isFailure(exit) + ? Effect.forEach(rolledBack, (id) => Effect.orDie(encoded.clearReplies(id)), { discard: true }) + : Effect.void + }) + ), + saveReply: (reply) => + MessageStorage.MemoryTransaction.use((inTransaction) => { + if (inTransaction) saved.push(Snowflake.Snowflake(reply.requestId)) + return encoded.saveReply(reply) + }) + }) + }) + ).pipe(Layer.provide([MessageStorage.MemoryDriver.layer, Snowflake.layerGenerator])) + const DefectRecoveryRun = Rpc.make("run", { payload: { id: Schema.String }, success: Schema.String @@ -1921,6 +2086,61 @@ describe.concurrent("Sharding defect recovery", () => { assert.isTrue(Exit.hasInterrupts(exit), "queued arrival must be interrupted") yield* Deferred.succeed(acquired, undefined) }).pipe(Effect.provide(BlockedRebuildSharding))) + + it.effect("interrupts an entity whose id is also active on a shard that was interrupted first", () => + Effect.gen(function*() { + const run = Rpc.make("run") + const entity = Entity.make("DuplicateEntityId", [run]) + const sharding = yield* Sharding.Sharding + let stopped = 0 + const manager = yield* EntityManager.make( + entity, + Effect.as( + Effect.addFinalizer(() => Effect.sync(() => stopped++)), + entity.of({ run: () => Effect.void }) + ), + { + // both shards belong to this runner + sharding: { ...sharding, hasShardId: () => true }, + storage: MessageStorage.noop, + runnerAddress: RunnerAddress.make("localhost", 1234), + residency: { admitUnsafe: () => true, releaseUnsafe: () => {} }, + maxIdleTime: Infinity + } + ) + const entityId = EntityId.make("duplicate") + const activate = Effect.fnUntraced(function*(shardId: ShardId.ShardId) { + yield* manager.sendLocal( + new Message.IncomingRequestLocal({ + envelope: Envelope.makeRequest({ + requestId: yield* sharding.getSnowflake, + address: EntityAddress.make({ shardId, entityType: EntityType.make(entity.type), entityId }), + tag: "run", + payload: undefined, + headers: Headers.empty + }), + lastSentReply: Option.none(), + annotations: Context.empty(), + respond: () => Effect.void + }) + ) + }) + const defaultShard = ShardId.make("default", 1) + const workflowShard = ShardId.make("workflow", 1) + yield* TestClock.adjust(1) + yield* activate(defaultShard) + yield* activate(workflowShard) + yield* TestClock.adjust(1) + + const interruptWorkflow = yield* manager.interruptShard(workflowShard).pipe(Effect.forkChild) + yield* TestClock.adjust(1000) + assert.deepStrictEqual(interruptWorkflow.pollUnsafe(), Exit.void) + assert.strictEqual(stopped, 1) + const interruptDefault = yield* manager.interruptShard(defaultShard).pipe(Effect.forkChild) + yield* TestClock.adjust(1000) + assert.deepStrictEqual(interruptDefault.pollUnsafe(), Exit.void) + assert.strictEqual(stopped, 2) + }).pipe(Effect.provide(BlockedRebuildSharding))) }) const ActiveTeardownCaller = Entity.make("ActiveTeardownCaller", [ @@ -1988,8 +2208,8 @@ describe.concurrent("Sharding active teardowns", () => { runnerAddress: Option.some(RunnerAddress.make("localhost", 1234)), shardsPerGroup: 1, entityTerminationTimeout: 0, - entityMessagePollInterval: 10, - refreshAssignmentsInterval: 10, + entityMessagePollInterval: 1000, + refreshAssignmentsInterval: 1000, sendRetryInterval: 10 })) ) @@ -2008,8 +2228,10 @@ describe.concurrent("Sharding active teardowns", () => { assert.strictEqual(Queue.sizeUnsafe(state.envelopes), 1) storageState.assignSelf = false + // The acquisition loop waits one second between passes. Advance by + // that interval instead of repeatedly waking 10ms polling loops. while (sharding.hasShardId(shardId)) { - yield* TestClock.adjust(10) + yield* TestClock.adjust(1000) } while ((yield* sharding.activeEntityCount) > 0) { yield* TestClock.adjust(1) @@ -2146,6 +2368,7 @@ const ReapStormEntity = Entity.make("ReapStormEntity", [ const ReapStormEntityLayer = ReapStormEntity.toLayer({ Ping: () => Effect.void }) describe.concurrent("Sharding residency cap", () => { + // Repeated TestClock adjustments need wall-clock headroom under concurrent Deno CI load. it.effect("bounds resident entities to maxResidentEntities", () => Effect.gen(function*() { yield* TestClock.adjust(1) @@ -2170,7 +2393,7 @@ describe.concurrent("Sharding residency cap", () => { const users = yield* Fiber.joinAll(fibers) assert.deepStrictEqual(users.map((user) => user.id), [1, 2, 3, 4, 5, 6]) - }).pipe(Effect.provide(CappedSharding({ maxResidentEntities: 2, entityMaxIdleTime: 1000 })))) + }).pipe(Effect.provide(CappedSharding({ maxResidentEntities: 2, entityMaxIdleTime: 1000 }))), 20_000) it.effect("volatile sends to new entities fail with MailboxFull at the cap", () => Effect.gen(function*() { @@ -2698,6 +2921,97 @@ describe("Sharding shard lock failover", { concurrent: false }, () => { }).pipe(Effect.provide(layer), Effect.scoped) })) + it.effect("interrupts opted-in streams on reassignment but respects Uninterruptible", () => + Effect.gen(function*() { + const entity = Entity.make(TestEntity.type, [ + terminationRpc("StreamWithKey").annotate(ClusterSchema.Persisted, false), + terminationRpc("RequestWithKey") + .annotate(ClusterSchema.Persisted, false) + .annotate(ClusterSchema.Uninterruptible, "server") + ]).annotateRpcs(ClusterSchema.InterruptOnTermination, true) + const storageState = makeFailoverStorageState() + const started = yield* Queue.make() + const finish = yield* Deferred.make() + const entityLayer = entity.toLayer({ + StreamWithKey: () => Stream.fromEffect(Queue.offer(started, void 0).pipe(Effect.andThen(Effect.never))), + RequestWithKey: () => Queue.offer(started, void 0).pipe(Effect.andThen(Deferred.await(finish))) + }, { concurrency: "unbounded" }) + + yield* Effect.gen(function*() { + const sharding = yield* Sharding.Sharding + yield* waitForTerminationOwnership(sharding, true) + // Let the acquisition backoff finish before testing reassignment. + yield* TestClock.adjust(1000) + const client = (yield* entity.client)("termination-stream") + const stream = yield* client.StreamWithKey({ key: "run" }).pipe( + Stream.runDrain, + Effect.forkChild({ startImmediately: true }) + ) + const protectedRequest = yield* client.RequestWithKey({ key: "run" }).pipe( + Effect.forkChild({ startImmediately: true }) + ) + yield* Queue.take(started) + yield* Queue.take(started) + storageState.assignSelf = false + yield* waitForTerminationOwnership(sharding, false) + yield* TestClock.adjust(100) + const earlyExit = stream.pollUnsafe() + const protectedExit = protectedRequest.pollUnsafe() + const held = storageState.releaseCalls.length === 0 + yield* Deferred.succeed(finish, void 0) + yield* TestClock.adjust(100) + const earlyReleases = storageState.releaseCalls.slice() + // Finish a broken implementation's grace period before asserting. + yield* TestClock.adjust(1000) + assert(earlyExit && Exit.hasInterrupts(earlyExit)) + assert.isUndefined(protectedExit) + assert.isTrue(held) + assert.deepStrictEqual(protectedRequest.pollUnsafe(), Exit.void) + assert.deepStrictEqual(earlyReleases, [ShardId.make("default", 1)]) + }).pipe(Effect.provide(TerminationSharding(entityLayer, storageState)), Effect.scoped) + })) + + it.effect("resumes an opted-in persisted request after early shard release", () => + Effect.gen(function*() { + const entity = Entity.make(TestEntity.type, [terminationRpc("RequestWithKey")]) + .annotateRpcs(ClusterSchema.InterruptOnTermination, true) + const storageState = makeFailoverStorageState() + const started = yield* Queue.make() + const finish = yield* Deferred.make() + const entityLayer = entity.toLayer({ + RequestWithKey: ({ requestId }) => Queue.offer(started, requestId).pipe(Effect.andThen(Deferred.await(finish))) + }) + + yield* Effect.gen(function*() { + const sharding = yield* Sharding.Sharding + yield* waitForTerminationOwnership(sharding, true) + yield* TestClock.adjust(1000) + const client = (yield* entity.client)("termination-persisted") + const running = yield* client.RequestWithKey({ key: "run" }).pipe( + Effect.forkChild({ startImmediately: true }) + ) + const requestId = yield* Queue.take(started) + storageState.assignSelf = false + yield* waitForTerminationOwnership(sharding, false) + yield* TestClock.adjust(100) + const earlyReleases = storageState.releaseCalls.slice() + yield* TestClock.adjust(1000) + assert.deepStrictEqual(earlyReleases, [ShardId.make("default", 1)]) + assert.isUndefined(running.pollUnsafe()) + + // A replay with the same ID and successful completion proves termination + // neither saved a terminal reply nor marked the request processed. + storageState.assignSelf = true + yield* waitForTerminationOwnership(sharding, true) + yield* sharding.pollStorage + yield* TestClock.adjust(10) + assert.deepStrictEqual(Queue.takeUnsafe(started), Exit.succeed(requestId)) + yield* Deferred.succeed(finish, void 0) + yield* TestClock.adjust(100) + assert.deepStrictEqual(running.pollUnsafe(), Exit.void) + }).pipe(Effect.provide(TerminationSharding(entityLayer, storageState)), Effect.scoped) + })) + it.effect("keeps the graceful timeout for normal shard reassignment", () => Effect.gen(function*() { const storageState = makeFailoverStorageState() @@ -2773,6 +3087,95 @@ describe("Sharding shard lock failover", { concurrent: false }, () => { }).pipe(Effect.provide(layer), Effect.scoped) })) + it.effect("delivers a client interrupt to a request still draining on the lock holder", () => + Effect.gen(function*() { + const storageState = makeFailoverStorageState() + yield* Effect.gen(function*() { + const state = yield* TestEntityState + const sharding = yield* Sharding.Sharding + const client = (yield* TestEntity.client)("1") + const shardId = sharding.getShardId(EntityId.make("1"), "default") + while (!sharding.hasShardId(shardId)) { + yield* TestClock.adjust(10) + } + const request = yield* client.NeverVolatile().pipe(Effect.forkChild({ startImmediately: true })) + yield* Queue.take(state.envelopes) + storageState.assignSelf = false + while (sharding.hasShardId(shardId)) { + yield* TestClock.adjust(10) + } + assert.strictEqual(storageState.releaseCalls.length, 0, "the shard lock must still be held") + + yield* Fiber.interrupt(request).pipe(Effect.forkChild({ startImmediately: true })) + yield* TestClock.adjust(100) + assert.strictEqual(Queue.sizeUnsafe(state.interrupts), 1) + }).pipe(Effect.provide(GracefulHandoffSharding(storageState)), Effect.scoped) + })) + + it.effect("acknowledges stream chunks from a request still draining on the lock holder", () => + Effect.gen(function*() { + const storageState = makeFailoverStorageState() + yield* Effect.gen(function*() { + const sharding = yield* Sharding.Sharding + const client = (yield* TestEntity.client)("1") + const shardId = sharding.getShardId(EntityId.make("1"), "default") + while (!sharding.hasShardId(shardId)) { + yield* TestClock.adjust(10) + } + // With one buffered chunk, the second is acknowledged only once the first is consumed. + const users = yield* client.GetAllUsersVolatile({ ids: [1, 2] }, { asQueue: true, streamBufferSize: 1 }) + yield* TestClock.adjust(1) + storageState.assignSelf = false + while (sharding.hasShardId(shardId)) { + yield* TestClock.adjust(10) + } + + const consumed = yield* Stream.fromQueue(users).pipe( + Stream.runCollect, + Effect.forkChild({ startImmediately: true }) + ) + yield* TestClock.adjust(100) + const exit = consumed.pollUnsafe() + assert.deepStrictEqual(exit && Exit.map(exit, (users) => users.map((user) => user.id)), Exit.succeed([1, 2])) + }).pipe(Effect.provide(GracefulHandoffSharding(storageState)), Effect.scoped) + })) + + it.effect("holds a remote request on the new owner until it acquires the shard lock", () => + Effect.gen(function*() { + const storageState = makeFailoverStorageState({ lockHeldElsewhere: true }) + yield* Effect.gen(function*() { + const sharding = yield* Sharding.Sharding + const entityId = EntityId.make("1") + const shardId = sharding.getShardId(entityId, "default") + while (storageState.acquireCalls.length === 0) { + yield* TestClock.adjust(10) + } + const delivery = yield* sharding.send( + new Message.IncomingRequest({ + envelope: { + _tag: "Request", + requestId: Snowflake.Snowflake(BigInt(1)), + address: EntityAddress.make({ shardId, entityType: EntityType.make(TestEntity.type), entityId }), + tag: "GetUserVolatile", + payload: { id: 1 }, + headers: Headers.empty + }, + lastSentReply: Option.none(), + respond: () => Effect.void, + codecFor: Schema.toCodecJson as RpcSerialization.CodecFor + }) + ).pipe(Effect.forkChild({ startImmediately: true })) + yield* TestClock.adjust(10) + assert.isUndefined(delivery.pollUnsafe(), "delivery must wait for the shard lock") + + storageState.lockHeldElsewhere = false + while (!sharding.hasShardId(shardId)) { + yield* TestClock.adjust(10) + } + assert.deepStrictEqual(yield* Fiber.await(delivery), Exit.void) + }).pipe(Effect.provide(GracefulHandoffSharding(storageState)), Effect.scoped) + })) + it.effect("does not wait for entity construction before a forced shard release", () => Effect.gen(function*() { const storageState = makeFailoverStorageState() @@ -2992,15 +3395,210 @@ describe("Sharding shard lock failover", { concurrent: false }, () => { })) }) +const terminationRpc = ["_tag"]>(tag: Tag) => + TestEntity.protocol.requests.get(tag)! as Extract, { readonly _tag: Tag }> + +const TerminationSharding = (entityLayer: Layer.Layer, state: FailoverStorageState) => + entityLayer.pipe( + Layer.provideMerge(Sharding.layer), + Layer.provide(Layer.effect( + RunnerStorage.RunnerStorage, + Effect.map(Clock.Clock, (clock) => makeFailoverStorage(state, clock)) + )), + Layer.provide(RunnerHealth.layerNoop), + Layer.provide(Runners.layerNoop), + Layer.provideMerge(MessageStorage.layerMemory), + Layer.provide(ShardingConfig.layer({ + runnerAddress: Option.some(RunnerAddress.make("localhost", 1234)), + shardsPerGroup: 1, + shardLockExpiration: 3000, + shardLockRefreshInterval: 100, + entityTerminationTimeout: 1000, + entityMessagePollInterval: 10, + entityReplyPollInterval: 10, + refreshAssignmentsInterval: 10, + sendRetryInterval: 10 + })) + ) + +const waitForTerminationOwnership = Effect.fnUntraced( + function*(sharding: Sharding.Sharding["Service"], owned: boolean) { + const shardId = ShardId.make("default", 1) + for (let i = 0; i < 100; i++) { + if (sharding.hasShardId(shardId) === owned) return + yield* TestClock.adjust(10) + } + assert.strictEqual(sharding.hasShardId(shardId), owned) + } +) +const GatedTeardownEntity = Entity.make("GatedTeardownEntity", [ + Rpc.make("Activate").annotate(ClusterSchema.Persisted, false) +]) + +describe("Sharding shard handoff", { concurrent: false }, () => { + const allShards = [ShardId.make("default", 1), ShardId.make("default", 2)] + const makeOwnedScope = Effect.acquireRelease(Scope.make(), (scope) => Scope.close(scope, Exit.void)) + // Open teardown gates before closing scopes, including on assertion failure. + const makeGate = Effect.acquireRelease(Effect.sync(() => Latch.makeUnsafe()), (gate) => gate.open) + const advanceUntil = (done: () => boolean) => + Effect.gen(function*() { + for (let i = 0; i < 100 && !done(); i++) { + yield* TestClock.adjust(10) + } + assert.isTrue(done()) + }) + const buildSharding = Effect.fnUntraced(function*( + storageState: FailoverStorageState, + config?: Partial, + existingScope?: Scope.Closeable + ) { + const scope = existingScope ?? (yield* makeOwnedScope) + const context = yield* Layer.buildWithScope( + Sharding.layer.pipe( + Layer.provide(Layer.effect( + RunnerStorage.RunnerStorage, + Effect.map(Clock.Clock, (clock) => makeFailoverStorage(storageState, clock)) + )), + Layer.provide(RunnerHealth.layerNoop), + Layer.provide(Runners.layerNoop), + Layer.provide([MessageStorage.layerMemory, Snowflake.layerGenerator]), + Layer.provide(ShardingConfig.layer({ + runnerAddress: Option.some(RunnerAddress.make("localhost", 1234)), + shardsPerGroup: 2, + entityTerminationTimeout: 0, + entityMessagePollInterval: 10, + refreshAssignmentsInterval: 10, + ...config + })) + ), + scope + ) + return { context, scope, sharding: Context.get(context, Sharding.Sharding) } + }) + + it.effect("waits for entity teardown before handing off without acquiring newly freed shards", () => + Effect.gen(function*() { + const [heldShard, freedShard] = allShards + const storageState = makeFailoverStorageState({ acquireDenied: [freedShard] }) + const registrationScope = yield* makeOwnedScope + // Keep assignments unchanged while a peer's lock becomes available. + const { context, scope, sharding } = yield* buildSharding(storageState, { refreshAssignmentsInterval: 60_000 }) + const gate = yield* makeGate + yield* advanceUntil(() => sharding.hasShardId(heldShard)) + yield* sharding.registerEntity( + GatedTeardownEntity, + Effect.as(Effect.addFinalizer(() => gate.await), GatedTeardownEntity.of({ Activate: () => Effect.void })) + ).pipe(Effect.provideService(Scope.Scope, registrationScope)) + let entityId = 0 + while (!Equal.equals(sharding.getShardId(EntityId.make(String(entityId)), "default"), heldShard)) { + entityId++ + } + const makeClient = yield* GatedTeardownEntity.client.pipe(Effect.provideContext(context)) + yield* makeClient(String(entityId)).Activate() + + const closing = yield* Effect.forkChild(Scope.close(scope, Exit.void)) + yield* advanceUntil(() => storageState.runner === undefined) + const acquires = storageState.acquireCalls.length + storageState.acquireDenied.length = 0 + yield* TestClock.adjust(3000) + assert.isUndefined(closing.pollUnsafe()) + assert.isUndefined(storageState.runner) + assert.deepStrictEqual(storageState.acquireCalls.slice(acquires), []) + assert.deepStrictEqual(storageState.releaseCalls, []) + assert.deepStrictEqual(storageState.releaseAllCalls, []) + + yield* gate.open + yield* advanceUntil(() => closing.pollUnsafe() !== undefined) + assert.deepStrictEqual(closing.pollUnsafe(), Exit.void) + assert.deepStrictEqual(storageState.releaseCalls, [heldShard]) + assert.deepStrictEqual(storageState.releaseAllCalls.map((call) => call.releases), [1]) + }).pipe(Effect.scoped)) + + it.effect("waits for singleton teardown before handing off their shards", () => + Effect.gen(function*() { + const storageState = makeFailoverStorageState() + const registrationScope = yield* makeOwnedScope + const runningRegistrationScope = yield* makeOwnedScope + const { scope, sharding } = yield* buildSharding(storageState) + const gate = yield* makeGate + yield* advanceUntil(() => allShards.every((shardId) => sharding.hasShardId(shardId))) + const started = Latch.makeUnsafe() + const stopping = Latch.makeUnsafe() + yield* sharding.registerSingleton( + "ClosingSingleton", + Effect.andThen(started.open, Effect.addFinalizer(() => Effect.andThen(stopping.open, gate.await))) + ).pipe(Effect.provideService(Scope.Scope, registrationScope)) + yield* started.await + // a singleton on the other shard that is still running at shutdown + const closingShard = sharding.getShardId(EntityId.make("ClosingSingleton"), "default") + let runningName = 0 + while (Equal.equals(sharding.getShardId(EntityId.make(`Running${runningName}`), "default"), closingShard)) { + runningName++ + } + const runningStarted = Latch.makeUnsafe() + yield* sharding.registerSingleton( + `Running${runningName}`, + Effect.andThen(runningStarted.open, Effect.addFinalizer(() => gate.await)) + ).pipe(Effect.provideService(Scope.Scope, runningRegistrationScope)) + yield* runningStarted.await + yield* Effect.forkChild(Scope.close(registrationScope, Exit.void)) + yield* stopping.await + + const closing = yield* Effect.forkChild(Scope.close(scope, Exit.void)) + yield* TestClock.adjust(100) + assert.isUndefined(closing.pollUnsafe()) + assert.deepStrictEqual(storageState.releaseCalls, []) + assert.deepStrictEqual(storageState.releaseAllCalls, []) + + yield* gate.open + yield* advanceUntil(() => closing.pollUnsafe() !== undefined) + assert.deepStrictEqual(closing.pollUnsafe(), Exit.void) + assert.deepStrictEqual(storageState.releaseAllCalls.map((call) => call.releases), [2]) + }).pipe(Effect.scoped)) + + it.effect("closes a singleton registration whose singleton registered another singleton", () => + Effect.gen(function*() { + // Await cleanup, but keep a regressed uninterruptible teardown bounded. + const makeDetachedScope = Effect.acquireRelease( + Scope.make(), + (scope) => + Effect.gen(function*() { + const closing = yield* Effect.forkDetach(Scope.close(scope, Exit.void)) + yield* advanceUntil(() => closing.pollUnsafe() !== undefined) + assert.deepStrictEqual(closing.pollUnsafe(), Exit.void) + }) + ) + const storageState = makeFailoverStorageState() + const shardingScope = yield* makeDetachedScope + const registrationScope = yield* makeDetachedScope + const { sharding } = yield* buildSharding(storageState, undefined, shardingScope) + yield* advanceUntil(() => allShards.every((shardId) => sharding.hasShardId(shardId))) + const childRegistered = Latch.makeUnsafe() + yield* sharding.registerSingleton( + "ParentSingleton", + Effect.andThen(sharding.registerSingleton("ChildSingleton", Effect.never), childRegistered.open) + ).pipe(Effect.provideService(Scope.Scope, registrationScope)) + yield* childRegistered.await + + const closing = yield* Effect.forkDetach(Scope.close(registrationScope, Exit.void)) + yield* advanceUntil(() => closing.pollUnsafe() !== undefined) + assert.deepStrictEqual(closing.pollUnsafe(), Exit.void) + }).pipe(Effect.scoped)) +}) + interface FailoverStorageState { blackholed: boolean /** Hang only non-empty refreshes, so the empty liveness probe can succeed. */ blackholeNonEmptyRefresh: boolean assignSelf: boolean + /** Fail lock acquisition, as when another runner still holds the locks. */ + lockHeldElsewhere: boolean otherRunnerHealthy: boolean /** Test clock duration `releaseAll` stays in flight for. */ releaseAllDuration: number runner: Runner.Runner | undefined + /** Shards `acquire` does not grant, as if another runner holds them. */ + readonly acquireDenied: Array readonly acquireCalls: Array<{ readonly shards: Array readonly completedReleaseAlls: number @@ -3010,7 +3608,7 @@ interface FailoverStorageState { readonly shards: Array }> readonly releaseCalls: Array - readonly releaseAllCalls: Array<{ completed: boolean }> + readonly releaseAllCalls: Array<{ completed: boolean; readonly releases: number }> } const makeFailoverStorageState = ( @@ -3019,9 +3617,11 @@ const makeFailoverStorageState = ( blackholed: false, blackholeNonEmptyRefresh: false, assignSelf: true, + lockHeldElsewhere: false, otherRunnerHealthy: false, releaseAllDuration: 0, runner: undefined, + acquireDenied: [], acquireCalls: [], refreshCalls: [], releaseCalls: [], @@ -3041,7 +3641,10 @@ const makeFailoverStorage = (state: FailoverStorageState, clock: Clock.Clock) => state.runner = runner return MachineId.make(1) }), - unregister: () => Effect.void, + unregister: () => + Effect.sync(() => { + state.runner = undefined + }), setRunnerHealth: () => Effect.void, acquire: (_address, shardIds) => Effect.sync(() => { @@ -3050,7 +3653,9 @@ const makeFailoverStorage = (state: FailoverStorageState, clock: Clock.Clock) => shards, completedReleaseAlls: state.releaseAllCalls.filter((call) => call.completed).length }) - return shards + return state.lockHeldElsewhere ? + [] : + shards.filter((shardId) => !state.acquireDenied.some((denied) => Equal.equals(denied, shardId))) }), refresh: (_address, shardIds) => Effect.suspend(() => { @@ -3069,7 +3674,7 @@ const makeFailoverStorage = (state: FailoverStorageState, clock: Clock.Clock) => }), releaseAll: () => Effect.suspend(() => { - const call = { completed: false } + const call = { completed: false, releases: state.releaseCalls.length } state.releaseAllCalls.push(call) return Effect.andThen( Effect.sleep(state.releaseAllDuration), @@ -3086,6 +3691,27 @@ const otherRunner = Runner.make({ weight: 1 }) +const GracefulHandoffSharding = (storageState: FailoverStorageState) => + TestEntityNoState.pipe( + Layer.provideMerge(Sharding.layer), + Layer.provide(Layer.effect( + RunnerStorage.RunnerStorage, + Effect.map(Clock.Clock, (clock) => makeFailoverStorage(storageState, clock)) + )), + Layer.provide(RunnerHealth.layerNoop), + Layer.provideMerge(TestEntityState.layer), + Layer.provide(Runners.layerNoop), + Layer.provide([MessageStorage.layerMemory, Snowflake.layerGenerator]), + Layer.provide(ShardingConfig.layer({ + runnerAddress: Option.some(RunnerAddress.make("localhost", 1234)), + shardsPerGroup: 1, + entityTerminationTimeout: 1000, + entityMessagePollInterval: 10, + refreshAssignmentsInterval: 10, + sendRetryInterval: 10 + })) + ) + class RegistrationContext extends Context.Service()( "effect/test/cluster/RegistrationContext" ) {} @@ -3434,3 +4060,53 @@ describe("Sharding singleton cancellation", { concurrent: false }, () => { }).pipe(Effect.provide(SingletonReassignmentSharding(storageState)), Effect.scoped) })) }) + +const PendingLockSharding = (storageState: FailoverStorageState) => + TestEntityNoState.pipe( + Layer.provideMerge(Sharding.layer), + Layer.provide(Layer.effect( + RunnerStorage.RunnerStorage, + Effect.map(Clock.Clock, (clock) => makeFailoverStorage(storageState, clock)) + )), + Layer.provide(RunnerHealth.layerNoop), + Layer.provideMerge(TestEntityState.layer), + Layer.provide(Runners.layerNoop), + Layer.provide(MessageStorage.layerMemory), + Layer.provide(ShardingConfig.layer({ + runnerAddress: Option.some(RunnerAddress.make("localhost", 1234)), + shardsPerGroup: 1, + entityMessagePollInterval: 10, + refreshAssignmentsInterval: 10, + sendRetryInterval: 10 + })) + ) + +describe("Sharding persisted sends to a shard awaiting its lock", { concurrent: false }, () => { + it.effect("persists a discard send and delivers it once the shard lock is acquired", () => + Effect.gen(function*() { + const storageState = makeFailoverStorageState({ lockHeldElsewhere: true }) + yield* Effect.gen(function*() { + const state = yield* TestEntityState + const sharding = yield* Sharding.Sharding + const shardId = sharding.getShardId(EntityId.make("1"), "default") + while (storageState.acquireCalls.length === 0) { + yield* TestClock.adjust(10) + } + const client = (yield* TestEntity.client)("1") + const send = yield* client.GetUser({ id: 1 }, { discard: true }).pipe( + Effect.forkChild({ startImmediately: true }) + ) + yield* TestClock.adjust(100) + assert.deepStrictEqual(send.pollUnsafe(), Exit.void, "a discard send returns once persisted") + assert.strictEqual(Queue.sizeUnsafe(state.envelopes), 0, "delivery must wait for the shard lock") + + storageState.lockHeldElsewhere = false + while (!sharding.hasShardId(shardId)) { + yield* TestClock.adjust(10) + } + yield* sharding.pollStorage + yield* TestClock.adjust(10) + assert.strictEqual(Queue.sizeUnsafe(state.envelopes), 1) + }).pipe(Effect.provide(PendingLockSharding(storageState)), Effect.scoped) + })) +}) diff --git a/repos/effect/packages/effect/test/cluster/TestEntity.ts b/repos/effect/packages/effect/test/cluster/TestEntity.ts index a7d66ac8ac..aca2559573 100644 --- a/repos/effect/packages/effect/test/cluster/TestEntity.ts +++ b/repos/effect/packages/effect/test/cluster/TestEntity.ts @@ -43,10 +43,21 @@ export const TestEntity = Entity.make("TestEntity", [ payload: { ids: Schema.Array(Schema.Number) }, stream: true }), + Rpc.make("GetAllUsersVolatile", { + success: User, + payload: { ids: Schema.Array(Schema.Number) }, + stream: true + }).annotate(ClusterSchema.Persisted, false), Rpc.make("WithTransaction", { success: Schema.Boolean, payload: { id: Schema.Number } - }).annotate(ClusterSchema.Dynamic, Context.add(ClusterSchema.WithTransaction, true)) + }).annotate(ClusterSchema.Dynamic, Context.add(ClusterSchema.WithTransaction, true)), + Rpc.make("FailWithTransaction", { + error: BoomError, + payload: { id: Schema.Number }, + primaryKey: ({ id }) => String(id) + }).annotate(ClusterSchema.Dynamic, Context.add(ClusterSchema.WithTransaction, true)), + Rpc.make("NeverWithTransaction").annotate(ClusterSchema.Dynamic, Context.add(ClusterSchema.WithTransaction, true)) ]).annotateRpcs(ClusterSchema.Persisted, true) export class TestEntityState extends Context.Service()("TestEntityState", { @@ -132,7 +143,21 @@ export const TestEntityNoState = TestEntity.toLayer( Stream.rechunk(1) ) }, - WithTransaction: () => MemoryTransaction + GetAllUsersVolatile: (envelope) => + Stream.fromIterable(envelope.payload.ids.map((id) => new User({ id, name: `User ${id}` }))).pipe( + Stream.rechunk(1) + ), + WithTransaction: (envelope) => + Effect.suspend(() => { + Queue.offerUnsafe(state.envelopes, envelope) + return MemoryTransaction + }), + FailWithTransaction: (envelope) => + Effect.suspend(() => { + Queue.offerUnsafe(state.envelopes, envelope) + return Effect.fail(new BoomError({ cause: "boom" })) + }), + NeverWithTransaction: never }) }), { defectRetryPolicy: Schedule.forever } diff --git a/repos/effect/packages/effect/test/encoding/Base64.test.ts b/repos/effect/packages/effect/test/encoding/Base64.test.ts index b2b68cf5bf..4a4fb333bc 100644 --- a/repos/effect/packages/effect/test/encoding/Base64.test.ts +++ b/repos/effect/packages/effect/test/encoding/Base64.test.ts @@ -3,6 +3,18 @@ import { Result } from "effect" import * as Base64 from "effect/encoding/Base64" describe("Base64", () => { + it("encodes and decodes binary subarrays with and without padding", () => { + const bytes = new Uint8Array([42, 251, 255, 128, 42]) + const vectors = ["", "+w==", "+/8=", "+/+A"] + + for (const [length, encoded] of vectors.entries()) { + const view = bytes.subarray(1, 1 + length) + assert.strictEqual(Base64.encode(view), encoded) + assert.deepStrictEqual(Result.getOrThrow(Base64.decode(encoded)), view) + } + assert.deepStrictEqual(bytes, new Uint8Array([42, 251, 255, 128, 42])) + }) + it("encodes strings and bytes", () => { assert.strictEqual(Base64.encode("hello"), "aGVsbG8=") assert.strictEqual(Base64.encode(new Uint8Array([72, 101, 108, 108, 111])), "SGVsbG8=") diff --git a/repos/effect/packages/effect/test/encoding/Sse.test.ts b/repos/effect/packages/effect/test/encoding/Sse.test.ts index 2296f98c8c..8407f5d6d4 100644 --- a/repos/effect/packages/effect/test/encoding/Sse.test.ts +++ b/repos/effect/packages/effect/test/encoding/Sse.test.ts @@ -22,7 +22,8 @@ describe("Sse", () => { const events: Array = [] const parser = Sse.makeParser((event) => events.push(event)) - parser.feed("data: first\r") + parser.feed("data: fir") + parser.feed("st\r") parser.feed("\ndata: second\n\n") assert.deepStrictEqual(events, [{ @@ -65,6 +66,16 @@ describe("Sse", () => { assert.deepStrictEqual(events, [input]) }) + it("roundtrips CR, CRLF and LF data lines, preserving a trailing empty line", () => { + const input: Sse.Event = { _tag: "Event", event: "message", id: undefined, data: "10%\r50%\r\ndone\n" } + const events: Array = [] + const parser = Sse.makeParser((event) => events.push(event)) + + parser.feed(Sse.encoder.write(input)) + + assert.deepStrictEqual(events, [{ ...input, data: "10%\n50%\ndone\n" }]) + }) + it("strips a UTF-8 BOM from the start of an SSE stream", () => { const events: Array = [] const parser = Sse.makeParser((event) => events.push(event)) @@ -89,6 +100,53 @@ describe("Sse", () => { assert.strictEqual((events[0] as Sse.Event).event, "message") }) + it("parses a long line split across many chunks", () => { + const events: Array = [] + const parser = Sse.makeParser((event) => events.push(event)) + const value = "x".repeat(10_000) + const input = `event: big\ndata: ${value}\n\n` + + for (let i = 0; i < input.length; i += 7) { + parser.feed(input.slice(i, i + 7)) + } + + assert.deepStrictEqual(events, [{ + _tag: "Event", + event: "big", + id: undefined, + data: value + }]) + }) + + it("discards the rest of the chunk when reset from onParse", () => { + const events: Array = [] + const parser = Sse.makeParser((event) => { + if (event._tag === "Event") { + events.push(event.data) + if (event.data === "a") parser.reset() + } + }) + + parser.feed("data: a\n\ndata: b\n\n") + parser.feed("data: fresh\n\n") + + assert.deepStrictEqual(events, ["a", "fresh"]) + }) + + it("discards the current event and remaining chunk when onParse throws", () => { + const events: Array = [] + const error = new Error("onParse failed") + const parser = Sse.makeParser((event) => { + if (event._tag === "Event" && event.data === "a") throw error + events.push(event) + }) + + assert.throws(() => parser.feed("event: custom\ndata: a\n\ndata: b\n\n"), Error, "onParse failed") + parser.feed("data: c\n\n") + + assert.deepStrictEqual(events, [{ _tag: "Event", event: "message", id: undefined, data: "c" }]) + }) + it("ignores retry values that are not ASCII digits", () => { const events: Array = [] for (const value of ["123x", "+123", "-123", "1.5"]) { @@ -167,6 +225,22 @@ describe("Sse", () => { assert.strictEqual(error.reason.maxEventSize, 4) })) + it("counts buffered data and fragmented pending lines toward maxEventSize and recovers", () => { + const events: Array = [] + const parser = Sse.makeParser((event) => events.push(event), { maxEventSize: 10 }) + + assert.isUndefined(parser.feed("data: a\n")) + assert.isUndefined(parser.feed("data:")) + assert.isUndefined(parser.feed(" bc")) + const error = parser.feed("d") + assert.instanceOf(error, Sse.SseError) + assert.instanceOf(error.reason, Sse.EventTooLarge) + assert.strictEqual(error.reason.maxEventSize, 10) + + assert.isUndefined(parser.feed("\uFEFFdata: x\n\n")) + assert.deepStrictEqual(events, [{ _tag: "Event", event: "message", id: undefined, data: "x" }]) + }) + it.effect("fails when pending data exceeds maxEventSize", () => Effect.gen(function*() { const error = yield* Stream.make("data: a\n", "data: b\n").pipe( diff --git a/repos/effect/packages/effect/test/graphql/GraphQL.test.ts b/repos/effect/packages/effect/test/graphql/GraphQL.test.ts new file mode 100644 index 0000000000..c06bbc6c1f --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQL.test.ts @@ -0,0 +1,68 @@ +import { assert, describe, it } from "@effect/vitest" +import { Effect, Schema } from "effect" +import { GraphQL, GraphQLMiddleware } from "effect/graphql" +import { renderSlices } from "effect/internal/graphql" + +class Auth extends GraphQLMiddleware.Service()("Auth") {} + +// A pull request lookup. Odd entries in a `body` are names renamed per slice: +// `PR` references `$withBody`, so it is per-slice; `Author` is shared. The +// root `__typename` checks that joining keeps the printer's spacing. +const pullRequestTemplate: GraphQL.DocumentTemplate = { + variables: [ + { name: "owner", body: "String!" }, + { name: "number", body: "Int!" }, + { name: "withBody", body: "Boolean!=false" } + ], + selections: [ + { name: "__typename", body: [""] }, + { + alias: "repo", + name: "repository", + body: ["(owner:$", "owner", ",name:\"effect\"){pullRequest(number:$", "number", "){...", "PR", "}}"] + } + ], + fragments: [ + { name: "PR", body: ["on PullRequest{title body@include(if:$", "withBody", ")...Author}"] }, + { name: "Author", body: ["on PullRequest{author{login}}"] } + ] +} + +describe("GraphQL", () => { + it("middleware returns a new operation and leaves the original unchanged", () => { + const Viewer = GraphQL.query("Viewer", { document: "query Viewer{viewer{login}}", result: Schema.Struct({}) }) + const authed = Viewer.middleware(Auth) + assert.deepStrictEqual(authed.middlewares, [Auth]) + assert.deepStrictEqual(Viewer.middlewares, []) + }) + + it("an operation built from a template sends the joined document", () => { + const PullRequest = GraphQL.query("PullRequest", { document: pullRequestTemplate, result: Schema.Struct({}) }) + assert.strictEqual( + PullRequest.document, + "query PullRequest($owner:String!$number:Int!$withBody:Boolean!=false){__typename repo:repository(owner:$owner,name:\"effect\"){pullRequest(number:$number){...PR}}}fragment PR on PullRequest{title body@include(if:$withBody)...Author}fragment Author on PullRequest{author{login}}" + ) + assert.strictEqual(PullRequest.template, pullRequestTemplate) + }) + + it("renderSlices aliases root fields and renames variables and per-slice fragments", () => { + assert.strictEqual( + renderSlices("query", "PullRequest", pullRequestTemplate, ["_0_", "_1_"]), + "query PullRequest($_0_owner:String!$_0_number:Int!$_0_withBody:Boolean!=false$_1_owner:String!$_1_number:Int!$_1_withBody:Boolean!=false){_0___typename:__typename _0_repo:repository(owner:$_0_owner,name:\"effect\"){pullRequest(number:$_0_number){..._0_PR}}_1___typename:__typename _1_repo:repository(owner:$_1_owner,name:\"effect\"){pullRequest(number:$_1_number){..._1_PR}}}fragment _0_PR on PullRequest{title body@include(if:$_0_withBody)...Author}fragment _1_PR on PullRequest{title body@include(if:$_1_withBody)...Author}fragment Author on PullRequest{author{login}}" + ) + }) + + it.effect("otherTypename accepts any type name except the selected ones", () => + Effect.gen(function*() { + const decode = Schema.decodeUnknownEffect(GraphQL.otherTypename<"Issue" | "PullRequest">()(["Issue"])) + assert.strictEqual(yield* decode("PullRequest"), "PullRequest") + assert.strictEqual(yield* decode("AddedLater"), "AddedLater") + assert.instanceOf(yield* Effect.flip(decode("Issue")), Schema.SchemaError) + })) + + it.effect("enumLiterals accepts a value the server added later", () => + Effect.gen(function*() { + const decode = Schema.decodeUnknownEffect(GraphQL.enumLiterals(["OPEN", "CLOSED"])) + assert.strictEqual(yield* decode("MERGED"), "MERGED") + })) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLClient.makeTest.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLClient.makeTest.test.ts new file mode 100644 index 0000000000..afee4d223c --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLClient.makeTest.test.ts @@ -0,0 +1,118 @@ +import { assert, describe, it } from "@effect/vitest" +import { Context, DateTime, Effect, Schema, Stream } from "effect" +import { GraphQL, GraphQLClient, GraphQLGroup } from "effect/graphql" +import { IssuesGroup } from "./fixtures.ts" + +const viewerResult = Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + +// Variables that may be `null` as a whole. +const NullableVariables = GraphQL.query("NullableVariables", { + document: "query NullableVariables{viewer{login}}", + variables: Schema.NullOr(Schema.Struct({ login: Schema.String })), + result: viewerResult +}) + +// A valid operation name that is also an `Object.prototype` method. +const ToString = GraphQL.query("toString", { document: "query toString{viewer{login}}", result: viewerResult }) + +const issue = (number: number) => ({ + number, + title: `#${number}`, + createdAt: DateTime.makeUnsafe("2026-01-01T00:00:00Z") +}) + +const page = ( + nodes: ReadonlyArray>, + pageInfo: { hasNextPage: boolean; endCursor: string | null } +) => ({ repository: { issues: { pageInfo, nodes } } }) + +const variables = { owner: "Effect-TS", name: "effect" } + +describe("GraphQLClient.makeTest", () => { + it.effect("a handled query returns the handler's value and receives the caller's variables", () => + Effect.gen(function*() { + const result = page([issue(1)], { hasNextPage: false, endCursor: null }) + const received: Array = [] + const client = GraphQLClient.makeTest(IssuesGroup)({ + RepoIssues: (variables) => { + received.push(variables) + return Effect.succeed(result) + } + }) + const since = DateTime.makeUnsafe("2026-01-01T00:00:00Z") + const called = { ...variables, since } + + assert.strictEqual(yield* client.RepoIssues(called), result) + assert.strictEqual(received[0], called) + + const nullable = GraphQLClient.makeTest(GraphQLGroup.make(NullableVariables))({ + NullableVariables: (variables) => { + received.push(variables) + return Effect.succeed({ viewer: { login: "tim" } }) + } + }) + yield* nullable.NullableVariables(null) + assert.strictEqual(received[1], null) + })) + + it.effect("partial: true returns the handler's value as data with no errors", () => + Effect.gen(function*() { + const result = page([issue(1)], { hasNextPage: false, endCursor: null }) + const client = GraphQLClient.makeTest(IssuesGroup)({ + RepoIssues: () => Effect.succeed(result) + }) + + const partial = yield* client.RepoIssues(variables, { partial: true }) + assert.strictEqual(partial.data, result) + assert.deepStrictEqual(partial.errors, []) + })) + + it.effect("an operation without a handler dies with an UnimplementedError", () => + Effect.gen(function*() { + const client = GraphQLClient.makeTest(IssuesGroup)({}) + + const defect = yield* client.RepoIssues(variables).pipe(Effect.catchDefect(Effect.fail), Effect.flip) + assert.instanceOf(defect, Error) + assert.strictEqual(defect.name, "UnimplementedError") + assert.strictEqual(defect.message, `GraphQLClient: Unimplemented operation "RepoIssues"`) + + const inherited = GraphQLClient.makeTest(GraphQLGroup.make(ToString))({}) + const inheritedDefect = yield* inherited.toString().pipe(Effect.catchDefect(Effect.fail), Effect.flip) + assert.instanceOf(inheritedDefect, Error) + assert.strictEqual(inheritedDefect.name, "UnimplementedError") + })) + + it.effect("GraphQLClient.pages drives a mock method across two pages", () => + Effect.gen(function*() { + const cursors: Array = [] + const client = GraphQLClient.makeTest(IssuesGroup)({ + RepoIssues: ({ after }) => { + cursors.push(after) + return Effect.succeed( + after === "c1" + ? page([issue(2)], { hasNextPage: false, endCursor: null }) + : page([issue(1)], { hasNextPage: true, endCursor: "c1" }) + ) + } + }) + + const pages = yield* Stream.runCollect( + GraphQLClient.pages(client.RepoIssues, { variables, connection: (r) => r.repository?.issues }) + ) + assert.deepStrictEqual(pages.map((p) => p.nodes?.map((i) => i?.number)), [[1], [2]]) + assert.deepStrictEqual(cursors, [undefined, "c1"]) + })) + + it.effect("layerTest provides the mock client through the service tag", () => + Effect.gen(function*() { + class Issues extends Context.Service()("test/Issues", { make: GraphQLClient.make(IssuesGroup) }) { + static readonly layerTest = GraphQLClient.layerTest(Issues, IssuesGroup) + } + + const result = page([issue(1)], { hasNextPage: false, endCursor: null }) + const actual = yield* Issues.use((client) => client.RepoIssues(variables)).pipe( + Effect.provide(Issues.layerTest({ RepoIssues: () => Effect.succeed(result) })) + ) + assert.strictEqual(actual, result) + })) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLClient.pages.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLClient.pages.test.ts new file mode 100644 index 0000000000..8c9696b965 --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLClient.pages.test.ts @@ -0,0 +1,111 @@ +import { assert, describe, it } from "@effect/vitest" +import { Effect, type Layer, Ref, Stream } from "effect" +import { GraphQLClient } from "effect/graphql" +import type * as GraphQLProtocol from "effect/graphql/GraphQLProtocol" +import * as UrlParams from "effect/http/UrlParams" +import { expectReason, IssuesGroup, protocolLayer } from "./fixtures.ts" + +const issue = (number: number) => ({ number, title: `#${number}`, createdAt: "2026-01-01T00:00:00Z" }) + +const page = (nodes: ReadonlyArray, pageInfo: { hasNextPage: boolean; endCursor: string | null }) => ({ + data: { repository: { issues: { pageInfo, nodes } } } +}) + +const noRepository = { data: { repository: null } } + +/** Scripts one response per `after` cursor; the first page is keyed `start`. */ +const pagedLayer = (pages: Record) => + Effect.gen(function*() { + const requests = yield* Ref.make>([]) + const layer = protocolLayer({ + execute: (request) => + Effect.as( + Ref.update(requests, (all) => [...all, request]), + { body: pages[(request.variables as { after?: string | null }).after ?? "start"] } + ) + }) + return { layer, requests } + }) + +const twoPages = { + start: page([issue(1), null], { hasNextPage: true, endCursor: "c1" }), + c1: page([issue(2)], { hasNextPage: false, endCursor: null }) +} + +const variables = { owner: "Effect-TS", name: "effect" } + +const makeClient = (layer: Layer.Layer) => GraphQLClient.make(IssuesGroup).pipe(Effect.provide(layer)) + +describe("GraphQLClient.pages / items", () => { + it.effect("pages passes endCursor as $after until hasNextPage is false", () => + Effect.gen(function*() { + const { layer, requests } = yield* pagedLayer(twoPages) + const client = yield* makeClient(layer) + const pages = yield* Stream.runCollect( + GraphQLClient.pages(client.RepoIssues, { variables, connection: (r) => r.repository?.issues }) + ) + assert.deepStrictEqual(pages.map((p) => p.pageInfo.endCursor), ["c1", null]) + assert.deepStrictEqual( + (yield* Ref.get(requests)).map((r) => (r.variables as { after?: string | null }).after), + [undefined, "c1"] + ) + })) + + it.effect("items flattens nodes across pages and keeps null entries", () => + Effect.gen(function*() { + const { layer } = yield* pagedLayer(twoPages) + const client = yield* makeClient(layer) + const items = yield* Stream.runCollect( + GraphQLClient.items(client.RepoIssues, { variables, connection: (r) => r.repository?.issues }) + ) + assert.deepStrictEqual(items.map((i) => i === null ? null : i.number), [1, null, 2]) + })) + + it.effect("options are forwarded to every page request", () => + Effect.gen(function*() { + const { layer, requests } = yield* pagedLayer(twoPages) + const client = yield* makeClient(layer) + yield* Stream.runDrain(GraphQLClient.pages(client.RepoIssues, { + variables, + connection: (r) => r.repository?.issues, + options: { headers: { "x-page-run": "1" }, urlParams: { preview: "t" } } + })) + const sent = yield* Ref.get(requests) + assert.deepStrictEqual(sent.map((r) => r.headers["x-page-run"]), ["1", "1"]) + assert.deepStrictEqual(sent.map((r) => UrlParams.getAll(r.urlParams, "preview")), [["t"], ["t"]]) + })) + + it.effect("a null connection on the first page is an empty stream", () => + Effect.gen(function*() { + const { layer } = yield* pagedLayer({ start: noRepository }) + const client = yield* makeClient(layer) + const pages = yield* Stream.runCollect( + GraphQLClient.pages(client.RepoIssues, { variables, connection: (r) => r.repository?.issues }) + ) + assert.deepStrictEqual(pages, []) + })) + + it.effect("a null connection on a later page is a PaginationError naming the cursor used", () => + Effect.gen(function*() { + const { layer } = yield* pagedLayer({ ...twoPages, c1: noRepository }) + const client = yield* makeClient(layer) + const reason = yield* Stream.runCollect( + GraphQLClient.pages(client.RepoIssues, { variables, connection: (r) => r.repository?.issues }) + ).pipe(expectReason("PaginationError")) + assert.strictEqual(reason.cursor, "c1") + })) + + it.effect("a cursor that does not advance is a PaginationError instead of a refetch", () => + Effect.gen(function*() { + const { layer, requests } = yield* pagedLayer({ + ...twoPages, + c1: page([issue(2)], { hasNextPage: true, endCursor: "c1" }) + }) + const client = yield* makeClient(layer) + const reason = yield* Stream.runCollect( + GraphQLClient.pages(client.RepoIssues, { variables, connection: (r) => r.repository?.issues }) + ).pipe(expectReason("PaginationError")) + assert.strictEqual(reason.cursor, "c1") + assert.strictEqual((yield* Ref.get(requests)).length, 2) + })) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLClient.subscriptions.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLClient.subscriptions.test.ts new file mode 100644 index 0000000000..25de84b4be --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLClient.subscriptions.test.ts @@ -0,0 +1,138 @@ +import { assert, describe, it } from "@effect/vitest" +import { Cause, Duration, Effect, Fiber, Layer, Ref, Schedule, Stream } from "effect" +import { GraphQLClient, GraphQLMiddleware } from "effect/graphql" +import { TransportError } from "effect/graphql/GraphQLClientError" +import { TestClock } from "effect/testing" +import { expectReason, IssuesGroup, protocolLayer } from "./fixtures.ts" + +const event = (title: string) => ({ data: { issueUpdated: { title } } }) + +const lost = (fields?: Partial[0]>) => + Stream.fail(new TransportError({ description: "connection lost", ...fields })) + +/** + * A protocol whose `subscribe` hands out one scripted stream per attempt and + * counts the attempts. + */ +const scriptedLayer = (attempts: ReadonlyArray>) => + Effect.gen(function*() { + const count = yield* Ref.make(0) + const layer = protocolLayer({ + subscribe: () => + Stream.unwrap( + Effect.map( + Ref.updateAndGet(count, (n) => n + 1), + (n) => Stream.map(attempts[n - 1] ?? Stream.die(`attempt ${n} not scripted`), (body) => ({ body })) + ) + ) + }) + return { layer, attempts: Ref.get(count) } + }) + +const subscribe = ( + layer: Layer.Layer, + options?: Parameters[1] +) => + GraphQLClient.make(IssuesGroup, options).pipe( + Effect.map((client) => client.IssueUpdated({ id: "I_1" })), + Effect.provide(layer), + Stream.unwrap + ) + +describe("GraphQLClient subscriptions", () => { + it.effect("emits each decoded event and ends when the transport completes", () => + Effect.gen(function*() { + const { layer } = yield* scriptedLayer([Stream.make(event("a"), event("b"))]) + const events = yield* Stream.runCollect(subscribe(layer)) + assert.deepStrictEqual(events, [{ issueUpdated: { title: "a" } }, { issueUpdated: { title: "b" } }]) + })) + + it.effect("an event with errors fails the stream with ResponseError without retrying", () => + Effect.gen(function*() { + const received = yield* Ref.make>([]) + const { layer, attempts } = yield* scriptedLayer([ + Stream.make(event("a"), { data: null, errors: [{ message: "gone" }] }, event("c")) + ]) + const reason = yield* Stream.runForEach( + subscribe(layer), + (e) => Ref.update(received, (all) => [...all, e.issueUpdated.title]) + ).pipe(expectReason("ResponseError")) + assert.deepStrictEqual(reason.errors, [{ message: "gone" }]) + assert.isUndefined(reason.status) + assert.isFalse(reason.isRetryable) + assert.deepStrictEqual(yield* Ref.get(received), ["a"]) + assert.strictEqual(yield* attempts, 1) + })) + + it.effect("retries a retryable TransportError on the default schedule (500ms, then x1.5)", () => + Effect.gen(function*() { + const { layer, attempts } = yield* scriptedLayer([lost(), lost(), Stream.make(event("a"))]) + const fiber = yield* Stream.runCollect(subscribe(layer)).pipe(Effect.forkChild) + yield* TestClock.adjust("499 millis") + assert.strictEqual(yield* attempts, 1) + yield* TestClock.adjust("1 millis") + assert.strictEqual(yield* attempts, 2) + yield* TestClock.adjust("749 millis") + assert.strictEqual(yield* attempts, 2) + yield* TestClock.adjust("1 millis") + assert.strictEqual(yield* attempts, 3) + assert.deepStrictEqual(yield* Fiber.join(fiber), [{ issueUpdated: { title: "a" } }]) + })) + + it.effect("waits for retryAfter when the transport reports one", () => + Effect.gen(function*() { + const { layer, attempts } = yield* scriptedLayer([ + lost({ retryAfter: Duration.seconds(2) }), + Stream.make(event("a")) + ]) + const fiber = yield* Stream.runCollect(subscribe(layer)).pipe(Effect.forkChild) + yield* TestClock.adjust("1999 millis") + assert.strictEqual(yield* attempts, 1) + yield* TestClock.adjust("1 millis") + assert.strictEqual(yield* attempts, 2) + yield* Fiber.join(fiber) + })) + + it.effect("a fatal close code fails the stream without retrying", () => + Effect.gen(function*() { + const { layer, attempts } = yield* scriptedLayer([lost({ closeCode: 4401 }), Stream.make(event("a"))]) + const reason = yield* Stream.runCollect(subscribe(layer)).pipe(expectReason("TransportError")) + assert.strictEqual(reason.closeCode, 4401) + assert.strictEqual(yield* attempts, 1) + })) + + it.effect("fails with the last TransportError once subscriptionRetry is exhausted", () => + Effect.gen(function*() { + const { layer, attempts } = yield* scriptedLayer([lost(), lost({ description: "lost again" }), lost()]) + const fiber = yield* Stream.runCollect(subscribe(layer, { subscriptionRetry: Schedule.recurs(1) })) + .pipe(expectReason("TransportError"), Effect.forkChild) + yield* TestClock.adjust("1 minute") + assert.strictEqual((yield* Fiber.join(fiber)).description, "lost again") + assert.strictEqual(yield* attempts, 2) + })) + + it.effect("a middleware failure is not retried and does not step subscriptionRetry", () => + Effect.gen(function*() { + const failure = { message: "subscription denied" } + class Reject extends GraphQLMiddleware.Service()("test/Reject") {} + const subscribes = yield* Ref.make(0) + const steps = yield* Ref.make(0) + const RejectLive = Layer.succeed(Reject, { + execute: ({ next, request }) => next(request), + subscribe: () => Stream.unwrap(Effect.as(Ref.update(subscribes, (n) => n + 1), Stream.fail(failure))) + }) + const subscriptionRetry = Schedule.fromStep( + Effect.succeed(() => Effect.andThen(Ref.update(steps, (n) => n + 1), Cause.done(undefined))) + ) + const error = yield* GraphQLClient.make(IssuesGroup.middleware(Reject), { subscriptionRetry }).pipe( + Effect.map((client) => client.IssueUpdated({ id: "I_1" })), + Effect.provide([protocolLayer({}), RejectLive]), + Stream.unwrap, + Stream.runCollect, + Effect.flip + ) + assert.strictEqual(error, failure) + assert.strictEqual(yield* Ref.get(subscribes), 1) + assert.strictEqual(yield* Ref.get(steps), 0) + })) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLClient.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLClient.test.ts new file mode 100644 index 0000000000..f78598ffad --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLClient.test.ts @@ -0,0 +1,195 @@ +import { assert, describe, it } from "@effect/vitest" +import { Context, DateTime, Effect, Layer, Ref, Schema } from "effect" +import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLMiddleware } from "effect/graphql" +import * as Headers from "effect/http/Headers" +import { executeLayer, expectReason, IssuesGroup, RepoIssues, Viewer, ViewerGroup } from "./fixtures.ts" + +class CurrentUser extends Context.Service()("test/CurrentUser") {} +class TokenExpired extends Schema.TaggedError()("TokenExpired", { user: Schema.String }) {} + +class Auth extends GraphQLMiddleware.Service()("test/Auth") {} +class OpA extends GraphQLMiddleware.Service()("test/OpA") {} +class OpB extends GraphQLMiddleware.Service()("test/OpB") {} +class GroupA extends GraphQLMiddleware.Service()("test/GroupA") {} +class GroupB extends GraphQLMiddleware.Service()("test/GroupB") {} + +const AuthLive = Layer.succeed( + Auth, + GraphQLMiddleware.mapRequest(Effect.fnUntraced(function*(request) { + assert.isTrue(Headers.isHeaders(request.headers)) + assert.notProperty(request.headers, "X-Request-Id") + const user = yield* CurrentUser + if (user.id === "expired") return yield* new TokenExpired({ user: user.id }) + return { ...request, headers: Headers.set(request.headers, "authorization", `Bearer ${user.id}`) } + })) +) + +const viewerData = { data: { viewer: { login: "tim" } } } + +const variables = { owner: "Effect-TS", name: "effect" } + +const partialIssues = { + data: { + repository: { + issues: { + pageInfo: { hasNextPage: false, endCursor: null }, + nodes: [{ number: 1, title: "Hi", createdAt: "2026-01-01T00:00:00Z" }, null] + } + } + }, + errors: [{ type: "NOT_FOUND", message: "Not found", path: ["repository", "issues", "nodes", 1] }] +} + +const repoIssuesClient = (result: unknown) => + executeLayer(result).pipe( + Effect.flatMap(({ layer }) => GraphQLClient.make(IssuesGroup).pipe(Effect.provide(layer))) + ) + +describe("GraphQLClient", () => { + describe("middleware", () => { + it.effect("group middleware runs outside operation middleware, attach order within a level", () => + Effect.gen(function*() { + const log = yield* Ref.make>([]) + const record = (name: string) => + GraphQLMiddleware.mapRequest((request) => Effect.as(Ref.update(log, (all) => [...all, name]), request)) + + const group = GraphQLGroup.make(Viewer.middleware(OpA).middleware(OpB)) + .middleware(GroupA) + .middleware(GroupB) + const { layer } = yield* executeLayer(viewerData) + + yield* GraphQLClient.make(group).pipe( + Effect.flatMap((client) => client.Viewer()), + Effect.provide([ + layer, + Layer.succeed(OpA, record("OpA")), + Layer.succeed(OpB, record("OpB")), + Layer.succeed(GroupA, record("GroupA")), + Layer.succeed(GroupB, record("GroupB")) + ]) + ) + assert.deepStrictEqual(yield* Ref.get(log), ["GroupA", "GroupB", "OpA", "OpB"]) + })) + + it.effect("mapRequest transforms the request and its errors reach the caller", () => + Effect.gen(function*() { + const { layer, requests } = yield* executeLayer(viewerData) + const client = yield* GraphQLClient.make(ViewerGroup.middleware(Auth)).pipe(Effect.provide([layer, AuthLive])) + + yield* client.Viewer().pipe(Effect.provideService(CurrentUser, { id: "tim" })) + assert.strictEqual((yield* Ref.get(requests))[0].headers["authorization"], "Bearer tim") + + const error = yield* client.Viewer().pipe(Effect.provideService(CurrentUser, { id: "expired" }), Effect.flip) + assert.instanceOf(error, TokenExpired) + assert.strictEqual((yield* Ref.get(requests)).length, 1) + })) + + it.effect("per-call context provides services and headers are normalized before middleware", () => + Effect.gen(function*() { + const { layer, requests } = yield* executeLayer(viewerData) + const client = yield* GraphQLClient.make(ViewerGroup.middleware(Auth)).pipe(Effect.provide([layer, AuthLive])) + yield* client.Viewer(undefined, { + context: Context.make(CurrentUser, { id: "ctx" }), + headers: [["X-Request-Id", "abc"]] + }) + assert.deepStrictEqual( + (yield* Ref.get(requests))[0].headers, + Headers.fromInput({ + authorization: "Bearer ctx", + "x-request-id": "abc" + }) + ) + })) + + it.effect("middleware see the transport status from next and may rewrite it; ResponseError carries it", () => + Effect.gen(function*() { + class Status extends GraphQLMiddleware.Service()("test/Status") {} + const StatusLive = Layer.succeed(Status, { + execute: ({ next, request }) => + Effect.map(next(request), (result) => ({ ...result, status: result.status === 401 ? 403 : 500 })), + subscribe: ({ next, request }) => next(request) + }) + const { layer } = yield* executeLayer({ errors: [{ message: "denied" }] }, 401) + const reason = yield* GraphQLClient.make(ViewerGroup.middleware(Status)).pipe( + Effect.flatMap((client) => client.Viewer()), + Effect.provide([layer, StatusLive]), + expectReason("ResponseError") + ) + assert.strictEqual(reason.status, 403) + })) + }) + + it.effect("encodes variables through the custom scalar codec", () => + Effect.gen(function*() { + const { layer, requests } = yield* executeLayer({ data: { repository: null } }) + yield* GraphQLClient.make(IssuesGroup).pipe( + Effect.flatMap((client) => + client.RepoIssues({ ...variables, since: DateTime.makeUnsafe("2026-01-01T00:00:00Z") }) + ), + Effect.provide(layer) + ) + const [request] = yield* Ref.get(requests) + assert.strictEqual(request.operationName, "RepoIssues") + assert.strictEqual(request.query, RepoIssues.document) + assert.deepStrictEqual(request.variables, { ...variables, since: "2026-01-01T00:00:00.000Z" }) + })) + + it.effect("a rejected input is an EncodeError and nothing is sent", () => + Effect.gen(function*() { + const First = GraphQL.query("First", { + document: "query First($first:Int!){viewer{login}}", + variables: { first: Schema.Int.check(Schema.isGreaterThan(0)) }, + result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) + }) + const { layer, requests } = yield* executeLayer(viewerData) + yield* GraphQLClient.make(GraphQLGroup.make(First)).pipe( + Effect.flatMap((client) => client.First({ first: 0 })), + Effect.provide(layer), + expectReason("EncodeError") + ) + assert.deepStrictEqual(yield* Ref.get(requests), []) + })) + + it.effect("a response with errors fails with ResponseError carrying the raw data and errors", () => + Effect.gen(function*() { + const client = yield* repoIssuesClient(partialIssues) + const reason = yield* expectReason("ResponseError")(client.RepoIssues(variables)) + assert.deepStrictEqual(reason.data, partialIssues.data) + assert.deepStrictEqual(reason.errors, partialIssues.errors) + })) + + it.effect("data that does not match the result schema is a DecodeError", () => + Effect.gen(function*() { + const { layer } = yield* executeLayer({ data: { viewer: { login: 42 } } }) + yield* GraphQLClient.make(ViewerGroup).pipe( + Effect.flatMap((client) => client.Viewer()), + Effect.provide(layer), + expectReason("DecodeError") + ) + })) + + describe("partial: true", () => { + it.effect("returns decoded data alongside the errors", () => + Effect.gen(function*() { + const client = yield* repoIssuesClient(partialIssues) + const { data, errors } = yield* client.RepoIssues(variables, { partial: true }) + assert.strictEqual(data.repository!.issues!.nodes![0]!.title, "Hi") + assert.deepStrictEqual(errors, partialIssues.errors) + })) + + it.effect("data: null plus errors is a ResponseError", () => + Effect.gen(function*() { + const client = yield* repoIssuesClient({ data: null, errors: [{ message: "boom" }] }) + yield* expectReason("ResponseError")(client.RepoIssues(variables, { partial: true })) + })) + }) + + it.effect("data: null with no errors is a DecodeError even when the result codec accepts null", () => + Effect.gen(function*() { + const Raw = GraphQL.query("Raw", { document: "query Raw{__typename}", result: Schema.Json }) + const { layer } = yield* executeLayer({ data: null }) + const client = yield* GraphQLClient.make(GraphQLGroup.make(Raw)).pipe(Effect.provide(layer)) + yield* expectReason("DecodeError")(client.Raw()) + yield* expectReason("DecodeError")(client.Raw(undefined, { partial: true })) + })) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLClientError.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLClientError.test.ts new file mode 100644 index 0000000000..a8a0042274 --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLClientError.test.ts @@ -0,0 +1,85 @@ +import { assert, describe, it } from "@effect/vitest" +import { Duration, Effect, Schema } from "effect" +import { GraphQLClientError, GraphQLError, ResponseError, TransportError } from "effect/graphql/GraphQLClientError" +import * as Headers from "effect/http/Headers" + +describe("GraphQLClientError", () => { + it("decoding a GitHub error preserves its top-level type", () => { + const error = { + type: "NOT_FOUND", + path: ["repository"], + locations: [{ line: 1, column: 3 }], + message: "Could not resolve to a Repository with the name 'Effect-TS/missing'." + } + assert.deepStrictEqual(Schema.decodeUnknownSync(GraphQLError)(error), error) + }) + + it.effect("round trips both error headers as JSON records, encoding retryAfter as milliseconds", () => + Effect.gen(function*() { + const headers = Headers.fromInput({ "X-RateLimit-Remaining": "0" }) + for ( + const reason of [ + new TransportError({ description: "503", status: 503, retryAfter: Duration.seconds(30), headers }), + new ResponseError({ errors: [{ message: "Rate limited" }], status: 200, headers }) + ] + ) { + const error = new GraphQLClientError({ operation: "Viewer", reason }) + const encoded = yield* Schema.encodeEffect(GraphQLClientError)(error) + if (encoded.reason._tag !== "TransportError" && encoded.reason._tag !== "ResponseError") { + assert.fail("Expected an encoded transport or response error") + } + assert.deepStrictEqual(encoded.reason.headers, { "x-ratelimit-remaining": "0" }) + const decoded = yield* Schema.decodeUnknownEffect(GraphQLClientError)(JSON.parse(JSON.stringify(encoded))) + assert.strictEqual(decoded.reason._tag, reason._tag) + if (decoded.reason._tag !== "TransportError" && decoded.reason._tag !== "ResponseError") { + assert.fail("Expected a decoded transport or response error") + } + assert.isTrue(Headers.isHeaders(decoded.reason.headers)) + assert.deepStrictEqual(decoded.reason.headers, headers) + if (reason._tag === "TransportError") { + assert.strictEqual((encoded.reason as { retryAfter?: number }).retryAfter, 30_000) + assert.deepStrictEqual(decoded.retryAfter, Duration.seconds(30)) + } + } + })) + + it("TransportError is retryable for 429, 5xx and non-fatal close codes", () => { + const transport = (fields: { status?: number; closeCode?: number }) => + new TransportError({ description: "transport", ...fields }).isRetryable + assert.isTrue(transport({ status: 429 })) + assert.isTrue(transport({ status: 503 })) + assert.isFalse(transport({ status: 400 })) + assert.isFalse(transport({ status: 600 })) + assert.isTrue(transport({ closeCode: 1006 })) + assert.isFalse(transport({ closeCode: 4401 })) + assert.isFalse(transport({ closeCode: 4500 })) + assert.isFalse(transport({ closeCode: 1011 })) + }) + + it("a Retry-After that is neither whole seconds nor an HTTP date is ignored", () => { + for (const retryAfter of ["1.5", "-1"]) { + const reason = new ResponseError({ + errors: [{ message: "Bad request" }], + status: 400, + headers: Headers.fromInput({ "retry-after": retryAfter }) + }) + assert.isUndefined(reason.retryAfter, retryAfter) + assert.isFalse(reason.isRetryable, retryAfter) + } + }) + + it("a 403 with Retry-After is retryable, and its status and headers are on the error", () => { + const headers = Headers.fromInput({ "retry-after": "30" }) + for ( + const reason of [ + new ResponseError({ errors: [{ message: "Rate limited" }], status: 403, headers }), + new TransportError({ description: "403", status: 403, headers, retryAfter: Duration.seconds(30) }) + ] + ) { + const error = new GraphQLClientError({ operation: "Viewer", reason }) + assert.isTrue(error.isRetryable) + assert.strictEqual(error.status, 403) + assert.deepStrictEqual(error.headers, headers) + } + }) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLProtocol.sse.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLProtocol.sse.test.ts new file mode 100644 index 0000000000..1d600b601e --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLProtocol.sse.test.ts @@ -0,0 +1,167 @@ +import { assert, describe, it } from "@effect/vitest" +import { Deferred, Duration, Effect, Fiber, Layer, Stream } from "effect" +import { GraphQLClient, GraphQLProtocol } from "effect/graphql" +import { TransportError } from "effect/graphql/GraphQLClientError" +import * as Headers from "effect/http/Headers" +import * as HttpClient from "effect/http/HttpClient" +import * as HttpClientResponse from "effect/http/HttpClientResponse" +import * as UrlParams from "effect/http/UrlParams" +import { TestClock } from "effect/testing" +import { expectReason, graphqlResponse, httpClientLayer, IssuesGroup, IssueUpdated } from "./fixtures.ts" + +const url = "http://localhost/graphql" + +const event = (title: string) => ({ data: { issueUpdated: { title } } }) + +const subscription: GraphQLProtocol.GraphQLRequest = { + kind: "subscription", + query: IssueUpdated.document, + operationName: "IssueUpdated", + variables: { id: "I_1" }, + headers: Headers.fromInput({ authorization: "Bearer t" }), + urlParams: UrlParams.fromInput({ preview: "t" }) +} + +/** + * A `text/event-stream` body that sends `chunks`, then fails with `error` or + * stays open. + */ +const eventStream = (chunks: ReadonlyArray, error?: Error) => + new Response( + new ReadableStream({ + start(controller) { + for (const chunk of chunks) controller.enqueue(new TextEncoder().encode(chunk)) + }, + pull(controller) { + // Error only after the queued chunks are read; erroring in start discards them. + if (error !== undefined) controller.error(error) + } + }), + { headers: { "content-type": "text/event-stream" } } + ) + +const next = (payload: unknown) => `event: next\ndata: ${JSON.stringify(payload)}\n\n` + +const subscribe = (layer: Layer.Layer) => + GraphQLProtocol.makeHttp({ url }).pipe( + Effect.map((protocol) => protocol.subscribe(subscription)), + Effect.provide(layer), + Stream.unwrap + ) + +describe("GraphQLProtocol.layerHttp subscriptions (graphql-sse distinct mode)", () => { + it.effect("POSTs with Accept: text/event-stream and emits next events, without a status, until complete", () => + Effect.gen(function*() { + let seen: { headers: Record; body: unknown; url: URL } | undefined + const events = yield* subscribe(httpClientLayer((request, bodyText, url) => { + seen = { headers: request.headers, body: JSON.parse(bodyText!), url } + return eventStream([next(event("a")), next(event("b")), "event: complete\ndata:\n\n"]) + })).pipe(Stream.runCollect) + assert.deepStrictEqual(events, [ + { body: event("a"), headers: Headers.fromInput({ "content-type": "text/event-stream" }) }, + { body: event("b"), headers: Headers.fromInput({ "content-type": "text/event-stream" }) } + ]) + assert.include(seen!.headers["accept"], "text/event-stream") + assert.strictEqual(seen!.headers["authorization"], "Bearer t") + assert.strictEqual(seen!.url.searchParams.get("preview"), "t") + assert.deepStrictEqual(seen!.body, { + query: IssueUpdated.document, + operationName: "IssueUpdated", + variables: { id: "I_1" } + }) + })) + + it.effect("a body that ends without a complete event is a retryable TransportError", () => + Effect.gen(function*() { + const error = yield* subscribe( + httpClientLayer(() => new Response(next(event("a")), { headers: { "content-type": "text/event-stream" } })) + ).pipe(Stream.runDrain, Effect.flip) + assert.instanceOf(error, TransportError) + assert.isTrue(error.isRetryable) + })) + + it.live("a complete event without a data: line ends the stream", () => + Effect.gen(function*() { + const events = yield* subscribe(httpClientLayer(() => eventStream([next(event("a")), "event: complete\n\n"]))) + .pipe( + Stream.runCollect, + Effect.timeout("2 seconds") + ) + assert.deepStrictEqual(events.map((answer) => answer.body), [event("a")]) + })) + + it.effect("a retry: line becomes retryAfter when the stream then fails", () => + Effect.gen(function*() { + const error = yield* subscribe( + httpClientLayer(() => eventStream([next(event("a")), "retry: 3000\n\n"], new Error("connection reset"))) + ).pipe(Stream.runDrain, Effect.flip) + assert.instanceOf(error, TransportError) + assert.isTrue(error.isRetryable) + assert.deepStrictEqual(error.retryAfter, Duration.seconds(3)) + })) + + it.effect("a GraphQL error response instead of a stream fails the client stream with ResponseError", () => + Effect.gen(function*() { + const layer = GraphQLProtocol.layerHttp({ url }).pipe( + Layer.provide(httpClientLayer(() => graphqlResponse({ errors: [{ message: "denied" }] }, { status: 400 }))) + ) + const reason = yield* GraphQLClient.make(IssuesGroup).pipe( + Effect.map((client) => client.IssueUpdated({ id: "I_1" })), + Effect.provide(layer), + Stream.unwrap, + Stream.runDrain, + expectReason("ResponseError") + ) + assert.deepStrictEqual(reason.errors, [{ message: "denied" }]) + assert.strictEqual(reason.status, 400) + })) + + it.effect("a client stream refused with 403 and Retry-After reconnects after the delay", () => + Effect.gen(function*() { + let attempts = 0 + const layer = GraphQLProtocol.layerHttp({ url }).pipe( + Layer.provide(httpClientLayer(() => + ++attempts === 1 + ? new Response(JSON.stringify({ message: "You have exceeded a secondary rate limit" }), { + status: 403, + headers: { "content-type": "application/json", "retry-after": "2" } + }) + : eventStream([next(event("a")), "event: complete\ndata:\n\n"]) + )) + ) + const fiber = yield* GraphQLClient.make(IssuesGroup).pipe( + Effect.map((client) => client.IssueUpdated({ id: "I_1" })), + Effect.provide(layer), + Stream.unwrap, + Stream.runCollect, + Effect.forkChild + ) + yield* TestClock.adjust("1999 millis") + assert.strictEqual(attempts, 1) + yield* TestClock.adjust("1 millis") + assert.deepStrictEqual(yield* Fiber.join(fiber), [{ issueUpdated: { title: "a" } }]) + assert.strictEqual(attempts, 2) + })) + + it.effect("interrupting the stream aborts the request", () => + Effect.gen(function*() { + let signal: AbortSignal | undefined + const layer = Layer.succeed( + HttpClient.HttpClient, + HttpClient.make((request, _url, abort) => { + signal = abort + return Effect.succeed(HttpClientResponse.fromWeb(request, eventStream([next(event("a"))]))) + }) + ) + const received = yield* Deferred.make() + const fiber = yield* subscribe(layer).pipe( + Stream.runForEach(() => Deferred.succeed(received, void 0)), + Effect.forkChild + ) + // Join too, so a stream that fails before its first event fails the test. + yield* Deferred.await(received).pipe(Effect.raceFirst(Fiber.join(fiber))) + assert.isFalse(signal!.aborted) + yield* Fiber.interrupt(fiber) + assert.isTrue(signal!.aborted) + })) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLProtocol.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLProtocol.test.ts new file mode 100644 index 0000000000..ffcbb783c7 --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLProtocol.test.ts @@ -0,0 +1,286 @@ +import { assert, describe, it } from "@effect/vitest" +import { Context, Duration, Effect, Layer, Schema, Stream } from "effect" +import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLMiddleware, GraphQLProtocol } from "effect/graphql" +import * as Headers from "effect/http/Headers" +import * as HttpClient from "effect/http/HttpClient" +import * as HttpClientError from "effect/http/HttpClientError" +import { + expectReason, + graphqlResponse, + httpClientLayer, + IssueUpdated, + layerHttp, + RepoIssues, + Viewer, + ViewerGroup +} from "./fixtures.ts" + +const viewerData = { data: { viewer: { login: "tim" } } } + +const AddStar = GraphQL.mutation("AddStar", { + document: "mutation AddStar{addStar{ok}}", + result: Schema.Struct({ addStar: Schema.Struct({ ok: Schema.Boolean }) }) +}) + +const GitHubHost = Context.Reference("test/GitHubHost", { defaultValue: () => "api.github.com" }) + +/** Every value of every URL param, so a duplicated or missing param shows. */ +const urlParams = (url: URL) => + Object.fromEntries([...new Set(url.searchParams.keys())].map((key) => [key, url.searchParams.getAll(key)])) + +const callViewer = (handler: Parameters[0]) => + GraphQLClient.make(ViewerGroup).pipe( + Effect.flatMap((client) => client.Viewer()), + Effect.provide(layerHttp(handler)) + ) + +const unavailable = (retryAfter: string) => + new Response("down", { status: 503, headers: { "retry-after": retryAfter, "content-type": "text/plain" } }) + +describe("GraphQLProtocol.layerHttp", () => { + it.effect("POSTs the document, operation name and variables as JSON with per-call headers and URL params", () => + Effect.gen(function*() { + let seen: { method: string; headers: Record; body: unknown; url: URL } | undefined + const result = yield* GraphQLClient.make(ViewerGroup).pipe( + Effect.flatMap((client) => + client.Viewer(undefined, { headers: { "x-request-id": "abc" }, urlParams: { preview: "t" } }) + ), + Effect.provide(layerHttp((request, bodyText, url) => { + seen = { method: request.method, headers: request.headers, body: JSON.parse(bodyText!), url } + return graphqlResponse(viewerData) + })) + ) + assert.deepStrictEqual(result, { viewer: { login: "tim" } }) + assert.strictEqual(seen!.method, "POST") + assert.deepStrictEqual(urlParams(seen!.url), { preview: ["t"] }) + assert.strictEqual(seen!.headers["x-request-id"], "abc") + assert.include(seen!.headers["accept"], "application/graphql-response+json") + assert.deepStrictEqual(seen!.body, { query: Viewer.document, operationName: "Viewer", variables: {} }) + })) + + it.effect("queryMethod GET sends a query as URL params over the URL's and caller's; a mutation is still POSTed", () => + Effect.gen(function*() { + const seen: Array<{ method: string; accept: string | undefined; bodyText: string | undefined; url: URL }> = [] + const layer = GraphQLProtocol.layerHttp({ + url: "http://localhost/graphql?tenant=a&query=stale&operationName=Stale", + queryMethod: "GET" + }).pipe( + Layer.provide(httpClientLayer((request, bodyText, url) => { + seen.push({ method: request.method, accept: request.headers["accept"], bodyText, url }) + return graphqlResponse( + request.method === "GET" ? { data: { repository: null } } : { data: { addStar: { ok: true } } } + ) + })) + ) + const client = yield* GraphQLClient.make(GraphQLGroup.make(RepoIssues, AddStar)).pipe(Effect.provide(layer)) + const variables = { owner: "Effect-TS", name: "effect" } + yield* client.RepoIssues(variables, { urlParams: { preview: "t", query: "ignored" } }) + yield* client.AddStar() + + const [query, mutation] = seen + assert.strictEqual(query.method, "GET") + assert.isUndefined(query.bodyText) + assert.include(query.accept, "application/graphql-response+json") + assert.deepStrictEqual(urlParams(query.url), { + tenant: ["a"], + preview: ["t"], + query: [RepoIssues.document], + operationName: ["RepoIssues"], + variables: [JSON.stringify(variables)] + }) + assert.strictEqual(mutation.method, "POST") + assert.strictEqual(JSON.parse(mutation.bodyText!).operationName, "AddStar") + })) + + it.effect("a url function routes queries, mutations and graphql-sse subscriptions by context and operation", () => + Effect.gen(function*() { + const seen: Array = [] + const layer = GraphQLProtocol.layerHttp({ + url: ({ context, kind, operationName }) => + `http://${Context.get(context, GitHubHost)}/graphql?route=${kind}.${operationName}`, + queryMethod: "GET" + }).pipe( + Layer.provide(httpClientLayer((request, _, url) => { + seen.push(`${request.method} ${url.host} ${urlParams(url).route}`) + return request.headers["accept"] === "text/event-stream" + ? new Response("event: complete\ndata:\n\n", { headers: { "content-type": "text/event-stream" } }) + : graphqlResponse(request.method === "GET" ? viewerData : { data: { addStar: { ok: true } } }) + })) + ) + const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer, AddStar, IssueUpdated)).pipe( + Effect.provide(layer) + ) + + yield* client.Viewer() + yield* client.Viewer().pipe(Effect.provideService(GitHubHost, "api.acme.ghe.com")) + yield* client.AddStar(undefined, { context: Context.make(GitHubHost, "ghes.example.com") }) + yield* client.IssueUpdated({ id: "I_1" }).pipe( + Stream.runDrain, + Effect.provideService(GitHubHost, "api.acme.ghe.com") + ) + + assert.deepStrictEqual(seen, [ + "GET api.github.com query.Viewer", + "GET api.acme.ghe.com query.Viewer", + "POST ghes.example.com mutation.AddStar", + "POST api.acme.ghe.com subscription.IssueUpdated" + ]) + })) + + it.effect("an Effect url is resolved asynchronously in the context of each query, mutation and subscription", () => + Effect.gen(function*() { + const seen: Array = [] + const layer = GraphQLProtocol.layerHttp({ + url: Effect.gen(function*() { + yield* Effect.promise(() => Promise.resolve()) + return `http://${yield* GitHubHost}/graphql` + }) + }).pipe( + Layer.provide(httpClientLayer((request, bodyText, url) => { + seen.push(`${url.host} ${JSON.parse(bodyText!).operationName}`) + return request.headers["accept"] === "text/event-stream" + ? new Response("event: complete\ndata:\n\n", { headers: { "content-type": "text/event-stream" } }) + : graphqlResponse({ data: { viewer: { login: "tim" }, addStar: { ok: true } } }) + })) + ) + const client = yield* GraphQLClient.make(GraphQLGroup.make(Viewer, AddStar, IssueUpdated)).pipe( + Effect.provide(layer) + ) + + yield* client.Viewer() + yield* client.Viewer().pipe(Effect.provideService(GitHubHost, "api.acme.ghe.com")) + yield* client.AddStar(undefined, { context: Context.make(GitHubHost, "ghes.example.com") }) + yield* client.IssueUpdated({ id: "I_1" }).pipe( + Stream.runDrain, + Effect.provideService(GitHubHost, "api.acme.ghe.com") + ) + + assert.deepStrictEqual(seen, [ + "api.github.com Viewer", + "api.acme.ghe.com Viewer", + "ghes.example.com AddStar", + "api.acme.ghe.com IssueUpdated" + ]) + })) + + it.effect("accepts an application/json body with GraphQL keys, matching the media type case-insensitively", () => + Effect.gen(function*() { + for (const contentType of ["application/json", "Application/JSON; charset=utf-8"]) { + const result = yield* callViewer(() => graphqlResponse(viewerData, { contentType })) + assert.deepStrictEqual(result, { viewer: { login: "tim" } }) + } + })) + + it.effect("a 200 application/json body without data or errors is a DecodeError", () => + Effect.gen(function*() { + yield* callViewer(() => graphqlResponse({ ok: true }, { contentType: "application/json" })).pipe( + expectReason("DecodeError") + ) + })) + + for (const [status, isRetryable] of [[502, true], [400, false]] as const) { + it.effect(`a ${status} with a GraphQL body is a ResponseError with isRetryable: ${isRetryable}`, () => + Effect.gen(function*() { + const reason = yield* callViewer(() => + graphqlResponse({ data: null, errors: [{ message: "Query failed" }] }, { status }) + ).pipe(expectReason("ResponseError")) + assert.deepStrictEqual(reason.errors, [{ message: "Query failed" }]) + assert.strictEqual(reason.status, status) + assert.strictEqual(reason.isRetryable, isRetryable) + })) + } + + it.effect("a 429 with a GraphQL body is a ResponseError carrying a numeric Retry-After", () => + Effect.gen(function*() { + const reason = yield* callViewer(() => + new Response(JSON.stringify({ data: null, errors: [{ message: "Rate limited" }] }), { + status: 429, + headers: { "content-type": "application/graphql-response+json", "retry-after": "30" } + }) + ).pipe(expectReason("ResponseError")) + assert.strictEqual(reason.status, 429) + assert.deepStrictEqual(reason.retryAfter, Duration.seconds(30)) + assert.isTrue(reason.isRetryable) + })) + + it.effect("HTTP response headers reach middleware through next and ResponseError", () => + Effect.gen(function*() { + class RateLimit extends GraphQLMiddleware.Service()("test/RateLimit") {} + let seen: GraphQLProtocol.ExecutionResult | undefined + const headers = { "content-type": "application/graphql-response+json", "x-ratelimit-remaining": "0" } + const body = JSON.stringify({ errors: [{ message: "Rate limited", extensions: { code: "RATE_LIMITED" } }] }) + const reason = yield* GraphQLClient.make(ViewerGroup.middleware(RateLimit)).pipe( + Effect.flatMap((client) => client.Viewer()), + Effect.provide([ + layerHttp(() => new Response(body, { headers })), + Layer.succeed(RateLimit, { + execute: ({ next, request }) => Effect.tap(next(request), (result) => Effect.sync(() => seen = result)), + subscribe: ({ next, request }) => next(request) + }) + ]), + expectReason("ResponseError") + ) + assert.deepStrictEqual(seen?.headers, Headers.fromInput(headers)) + assert.deepStrictEqual(reason.headers, Headers.fromInput(headers)) + })) + + it.effect("an application/json 429 whose errors is not a list is a TransportError carrying its Retry-After", () => + Effect.gen(function*() { + const reason = yield* callViewer(() => + new Response(JSON.stringify({ errors: "Throttled" }), { + status: 429, + headers: { "content-type": "application/json", "retry-after": "5" } + }) + ).pipe(expectReason("TransportError")) + assert.strictEqual(reason.status, 429) + assert.deepStrictEqual(reason.retryAfter, Duration.seconds(5)) + })) + + it.effect("a non-GraphQL 403 is a TransportError carrying response headers without Retry-After", () => + Effect.gen(function*() { + const headers = { "content-type": "text/plain", "x-ratelimit-remaining": "0", "x-ratelimit-reset": "1791768600" } + const reason = yield* callViewer(() => new Response("Secondary rate limit", { status: 403, headers })).pipe( + expectReason("TransportError") + ) + assert.strictEqual(reason.status, 403) + assert.deepStrictEqual(reason.headers, Headers.fromInput(headers)) + })) + + it.effect("a non-GraphQL 503 is a TransportError carrying a numeric Retry-After", () => + Effect.gen(function*() { + const reason = yield* callViewer(() => unavailable("30")).pipe(expectReason("TransportError")) + assert.strictEqual(reason.status, 503) + assert.deepStrictEqual(reason.retryAfter, Duration.seconds(30)) + assert.isTrue(HttpClientError.isHttpClientError(reason.cause)) + })) + + it.effect("an HTTP-date Retry-After is measured from the Effect clock", () => + Effect.gen(function*() { + // it.effect runs under TestClock, whose current time is the Unix epoch. + const reason = yield* callViewer(() => unavailable(new Date(45_000).toUTCString())).pipe( + expectReason("TransportError") + ) + assert.deepStrictEqual(reason.retryAfter, Duration.seconds(45)) + })) + + it.effect("a network failure is a retryable TransportError without status", () => + Effect.gen(function*() { + const failing = Layer.succeed( + HttpClient.HttpClient, + HttpClient.make((request) => + Effect.fail( + new HttpClientError.HttpClientError({ + reason: new HttpClientError.TransportError({ request, description: "ECONNREFUSED" }) + }) + ) + ) + ) + const reason = yield* GraphQLClient.make(ViewerGroup).pipe( + Effect.flatMap((client) => client.Viewer()), + Effect.provide(GraphQLProtocol.layerHttp({ url: "http://localhost/graphql" }).pipe(Layer.provide(failing))), + expectReason("TransportError") + ) + assert.isUndefined(reason.status) + assert.isTrue(reason.isRetryable) + })) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLProtocol.webSocket.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLProtocol.webSocket.test.ts new file mode 100644 index 0000000000..35648d71ae --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLProtocol.webSocket.test.ts @@ -0,0 +1,250 @@ +import { assert, describe, it } from "@effect/vitest" +import { Deferred, type Duration, Effect, Exit, Fiber, Layer, Queue, Ref, Scope, Stream } from "effect" + +import { GraphQLClient, GraphQLMiddleware, GraphQLProtocol } from "effect/graphql" +import { TransportError } from "effect/graphql/GraphQLClientError" +import * as Headers from "effect/http/Headers" +import * as UrlParams from "effect/http/UrlParams" +import { TestClock } from "effect/testing" +import { expectReason, IssuesGroup, IssueUpdated, Viewer, type WsMessage, wsServer } from "./fixtures.ts" + +const url = "ws://localhost/graphql" + +const event = (title: string) => ({ data: { issueUpdated: { title } } }) + +const subscription = (id: string): GraphQLProtocol.GraphQLRequest => ({ + kind: "subscription", + query: IssueUpdated.document, + operationName: "IssueUpdated", + variables: { id }, + headers: Headers.empty, + urlParams: UrlParams.empty +}) + +interface Options { + readonly connectionParams?: Effect.Effect | undefined, unknown> + readonly connectionAckTimeout?: Duration.Input + readonly keepAlive?: Duration.Input | false + readonly idleTimeout?: Duration.Input +} + +const makeProtocol = (server: Effect.Success, options?: Options) => + GraphQLProtocol.makeWebSocket({ url, ...options }).pipe(Effect.provide(server.layer)) + +/** Starts a subscription and accepts its connection, returning the failure fiber. */ +const acceptedSubscription = (server: Effect.Success, options?: Options) => + Effect.gen(function*() { + const protocol = yield* makeProtocol(server, options) + const fiber = yield* protocol.subscribe(subscription("A")).pipe(Stream.runDrain, Effect.flip, Effect.forkChild) + const { connection } = yield* server.accept + const subscribe = yield* Queue.take(connection.received) + return { fiber, connection, subscribe } + }) + +describe("GraphQLProtocol.makeWebSocket", () => { + it.effect("subscribes only after connection_ack and routes events by operation id", () => + Effect.gen(function*() { + const server = yield* wsServer + const protocol = yield* makeProtocol(server, { connectionParams: Effect.succeed({ token: "t1" }) }) + const a = yield* protocol.subscribe(subscription("A")).pipe(Stream.runCollect, Effect.forkChild) + const b = yield* protocol.subscribe(subscription("B")).pipe(Stream.runCollect, Effect.forkChild) + + const connection = yield* Queue.take(server.connections) + assert.deepStrictEqual(connection.options, "graphql-transport-ws") + assert.deepStrictEqual(yield* Queue.take(connection.received), { + type: "connection_init", + payload: { token: "t1" } + }) + yield* TestClock.adjust("1 second") + assert.strictEqual(yield* Queue.size(connection.received), 0) + + yield* connection.send({ type: "connection_ack" }) + const ids: Record = {} + for (const message of [yield* Queue.take(connection.received), yield* Queue.take(connection.received)]) { + assert.strictEqual(message.type, "subscribe") + ids[(message.payload as { variables: { id: string } }).variables.id] = message.id! + } + + yield* connection.send({ id: ids.B, type: "next", payload: event("b") }) + yield* connection.send({ id: ids.A, type: "next", payload: event("a") }) + yield* connection.send({ id: ids.A, type: "complete" }) + yield* connection.send({ id: ids.B, type: "complete" }) + assert.deepStrictEqual(yield* Fiber.join(a), [{ body: event("a") }]) + assert.deepStrictEqual(yield* Fiber.join(b), [{ body: event("b") }]) + })) + + it.effect("a missing connection_ack is a TransportError", () => + Effect.gen(function*() { + const server = yield* wsServer + const protocol = yield* makeProtocol(server, { connectionAckTimeout: "5 seconds" }) + const fiber = yield* protocol.subscribe(subscription("A")).pipe(Stream.runDrain, Effect.flip, Effect.forkChild) + yield* Queue.take(server.connections) + yield* TestClock.adjust("5 seconds") + assert.instanceOf(yield* Fiber.join(fiber), TransportError) + })) + + it.effect("a close while connectionParams is pending fails the waiting operation", () => + Effect.gen(function*() { + const server = yield* wsServer + const protocol = yield* makeProtocol(server, { connectionParams: Effect.never }) + const fiber = yield* protocol.subscribe(subscription("A")).pipe(Stream.runDrain, Effect.flip, Effect.forkChild) + const connection = yield* Queue.take(server.connections) + yield* connection.close(1006) + yield* TestClock.adjust("1 minute") + assert.isDefined(fiber.pollUnsafe()) + assert.strictEqual((yield* Fiber.join(fiber)).closeCode, 1006) + })) + + // Shape is checked before the id lookup, so an unknown id does not excuse it. + const invalidMessages: ReadonlyArray = [ + { type: "not-a-graphql-message" }, + { type: "next", id: "unknown", payload: [] } + ] + for (const invalid of invalidMessages) { + it.effect(`an invalid message ${JSON.stringify(invalid)} closes the connection with 4400`, () => + Effect.gen(function*() { + const server = yield* wsServer + const { connection, fiber } = yield* acceptedSubscription(server) + yield* connection.send(invalid) + const error = yield* Fiber.join(fiber) + assert.strictEqual(error.closeCode, 4400) + assert.isFalse(error.isRetryable) + assert.strictEqual(yield* Deferred.await(connection.closed), 4400) + })) + } + + it.effect("1002 is a fatal close", () => + Effect.gen(function*() { + const server = yield* wsServer + const { connection, fiber } = yield* acceptedSubscription(server) + yield* connection.close(1002) + const error = yield* Fiber.join(fiber) + assert.strictEqual(error.closeCode, 1002) + assert.isFalse(error.isRetryable) + })) + + it.effect("answers ping with pong, pings every keepAlive and treats a missed frame as a retryable close", () => + Effect.gen(function*() { + const server = yield* wsServer + const { connection, fiber } = yield* acceptedSubscription(server, { keepAlive: "10 seconds" }) + yield* connection.send({ type: "ping" }) + assert.deepStrictEqual(yield* Queue.take(connection.received), { type: "pong" }) + + yield* TestClock.adjust("10 seconds") + assert.deepStrictEqual(yield* Queue.take(connection.received), { type: "ping" }) + yield* TestClock.adjust("10 seconds") + assert.isTrue((yield* Fiber.join(fiber)).isRetryable) + })) + + it.effect("interrupting a subscription sends a client complete", () => + Effect.gen(function*() { + const server = yield* wsServer + const { connection, fiber, subscribe } = yield* acceptedSubscription(server) + yield* Fiber.interrupt(fiber) + assert.deepStrictEqual(yield* Queue.take(connection.received), { id: subscribe.id, type: "complete" }) + })) + + it.effect("a lost connection fails in-flight queries, and the next operation reconnects with fresh connectionParams", () => + Effect.gen(function*() { + const server = yield* wsServer + const tokens = yield* Ref.make(0) + const protocol = yield* makeProtocol(server, { + connectionParams: Effect.map(Ref.updateAndGet(tokens, (n) => n + 1), (n) => ({ token: n })) + }) + const query: GraphQLProtocol.GraphQLRequest = { + kind: "query", + query: Viewer.document, + operationName: "Viewer", + variables: {}, + headers: Headers.empty, + urlParams: UrlParams.empty + } + + const inFlight = yield* protocol.execute(query).pipe(Effect.flip, Effect.forkChild) + const first = yield* server.accept + assert.deepStrictEqual(first.init.payload, { token: 1 }) + yield* Queue.take(first.connection.received) + yield* first.connection.close(1006) + assert.isTrue((yield* Fiber.join(inFlight)).isRetryable) + + const retried = yield* protocol.execute(query).pipe(Effect.forkChild) + const second = yield* server.accept + assert.deepStrictEqual(second.init.payload, { token: 2 }) + const subscribe = yield* Queue.take(second.connection.received) + yield* second.connection.send({ id: subscribe.id, type: "next", payload: { data: { viewer: { login: "tim" } } } }) + yield* second.connection.send({ id: subscribe.id, type: "complete" }) + assert.deepStrictEqual(yield* Fiber.join(retried), { body: { data: { viewer: { login: "tim" } } } }) + })) + + it.effect("an operation started after the scope closed fails with a non-retryable TransportError", () => + Effect.gen(function*() { + const server = yield* wsServer + const scope = yield* Scope.make() + const protocol = yield* makeProtocol(server).pipe(Scope.provide(scope)) + yield* Scope.close(scope, Exit.void) + const fiber = yield* protocol.subscribe(subscription("A")).pipe( + Stream.runDrain, + Effect.flip, + Effect.timeout("5 seconds"), + Effect.forkChild + ) + yield* TestClock.adjust("5 seconds") + const error = yield* Fiber.join(fiber) + assert.instanceOf(error, TransportError) + assert.isFalse(error.isRetryable) + })) + + it.effect("connects on the first operation and closes idleTimeout after the last one", () => + Effect.gen(function*() { + const server = yield* wsServer + const protocol = yield* makeProtocol(server, { idleTimeout: "30 seconds", keepAlive: false }) + yield* TestClock.adjust("1 minute") + assert.strictEqual(yield* Queue.size(server.connections), 0) + + const fiber = yield* protocol.subscribe(subscription("A")).pipe(Stream.runCollect, Effect.forkChild) + const { connection } = yield* server.accept + const subscribe = yield* Queue.take(connection.received) + yield* connection.send({ id: subscribe.id, type: "complete" }) + yield* Fiber.join(fiber) + + yield* TestClock.adjust("29 seconds") + assert.isFalse(yield* Deferred.isDone(connection.closed)) + yield* TestClock.adjust("1 second") + assert.strictEqual(yield* Deferred.await(connection.closed), 1000) + })) +}) + +describe("GraphQLProtocol.layerWebSocket with GraphQLClient", () => { + it.effect("a retryable close resubscribes through the middleware chain; a server error is a ResponseError", () => + Effect.gen(function*() { + class Count extends GraphQLMiddleware.Service()("test/Count") {} + const subscribes = yield* Ref.make(0) + const CountLive = Layer.succeed(Count, { + execute: ({ next, request }) => next(request), + subscribe: ({ next, request }) => Stream.unwrap(Effect.as(Ref.update(subscribes, (n) => n + 1), next(request))) + }) + const server = yield* wsServer + const context = yield* Layer.build( + Layer.merge(GraphQLProtocol.layerWebSocket({ url }).pipe(Layer.provide(server.layer)), CountLive) + ) + const client = yield* GraphQLClient.make(IssuesGroup.middleware(Count)).pipe(Effect.provide(context)) + const fiber = yield* client.IssueUpdated({ id: "I_1" }).pipe( + Stream.runCollect, + expectReason("ResponseError"), + Effect.forkChild + ) + + const first = yield* server.accept + yield* Queue.take(first.connection.received) + yield* first.connection.close(1006) + // The client's default schedule waits 500ms before resubscribing. + yield* TestClock.adjust("500 millis") + + const second = yield* server.accept + const subscribe = yield* Queue.take(second.connection.received) + yield* second.connection.send({ id: subscribe.id, type: "error", payload: [{ message: "denied" }] }) + const reason = yield* Fiber.join(fiber) + assert.deepStrictEqual(reason.errors, [{ message: "denied" }]) + assert.strictEqual(yield* Ref.get(subscribes), 2) + })) +}) diff --git a/repos/effect/packages/effect/test/graphql/GraphQLResolver.test.ts b/repos/effect/packages/effect/test/graphql/GraphQLResolver.test.ts new file mode 100644 index 0000000000..41f93109b3 --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/GraphQLResolver.test.ts @@ -0,0 +1,532 @@ +import { assert, describe, it } from "@effect/vitest" +import { Cause, Context, Effect, Layer, Ref, Schema } from "effect" +import { GraphQL, GraphQLClient, GraphQLGroup, GraphQLMiddleware, GraphQLResolver } from "effect/graphql" +import { GraphQLClientError, type ResponseError } from "effect/graphql/GraphQLClientError" +import * as GraphQLProtocol from "effect/graphql/GraphQLProtocol" +import * as Headers from "effect/http/Headers" +import { graphqlResponse, httpClientLayer, protocolLayer } from "./fixtures.ts" + +const Repository = Schema.Struct({ __typename: Schema.Literal("Repository"), nameWithOwner: Schema.String }) +const User = Schema.Struct({ __typename: Schema.Literal("User"), login: Schema.String }) +const Node = Schema.Union([Repository, User]) + +const RepoNodes = GraphQL.query("RepoNodes", { + document: + "query RepoNodes($ids:[ID!]!){nodes(ids:$ids){__typename ...on Repository{nameWithOwner} ...on User{login}}}", + variables: { ids: Schema.Array(Schema.String) }, + result: Schema.Struct({ nodes: Schema.Array(Schema.NullOr(Node)) }) +}) + +const SearchRepos = GraphQL.query("SearchRepos", { + document: + "query SearchRepos($query:String!){search(query:$query,type:REPOSITORY,first:100){pageInfo{hasNextPage endCursor} nodes{__typename ...on Repository{nameWithOwner} ...on User{login}}}}", + variables: { query: Schema.String }, + result: Schema.Struct({ + search: Schema.Struct({ + pageInfo: Schema.Struct({ hasNextPage: Schema.Boolean, endCursor: Schema.NullOr(Schema.String) }), + nodes: Schema.NullOr(Schema.Array(Schema.NullOr(Node))) + }) + }) +}) + +// Generated operations carry a document template, which `aliased` repeats +// once per slice. +const PullRequest = GraphQL.query("PullRequest", { + document: { + variables: [{ name: "name", body: "String!" }, { name: "number", body: "Int!" }], + selections: [{ + name: "repository", + body: ["(owner:\"Effect-TS\",name:$", "name", "){pullRequest(number:$", "number", "){title}}"] + }], + fragments: [] + }, + variables: { name: Schema.String, number: Schema.Int }, + result: Schema.Struct({ + repository: Schema.NullOr(Schema.Struct({ pullRequest: Schema.NullOr(Schema.Struct({ title: Schema.String })) })) + }) +}) + +// `$after` is optional, so `{ name }` and `{ name, after: undefined }` encode alike. +const RepoIssues = GraphQL.query("RepoIssues", { + document: { + variables: [{ name: "name", body: "String!" }, { name: "after", body: "String" }], + selections: [{ + name: "repository", + body: ["(owner:\"Effect-TS\",name:$", "name", "){issues(after:$", "after", "){totalCount}}"] + }], + fragments: [] + }, + variables: { name: Schema.String, after: Schema.optional(Schema.NullOr(Schema.String)) }, + result: Schema.Struct({ + repository: Schema.NullOr(Schema.Struct({ issues: Schema.Struct({ totalCount: Schema.Int }) })) + }) +}) + +class CurrentUser extends Context.Service()("test/CurrentUser") {} +class Auth extends GraphQLMiddleware.Service()("test/Auth") {} + +const AuthLive = Layer.succeed( + Auth, + GraphQLMiddleware.mapRequest(Effect.fnUntraced(function*(request) { + const user = yield* CurrentUser + return { ...request, headers: Headers.set(request.headers, "authorization", `Bearer ${user.tenant}`) } + })) +) + +const repo = (nameWithOwner: string) => ({ __typename: "Repository" as const, nameWithOwner }) + +/** Answers each request with `respond(variables)` and records the requests. */ +const makeClient = (respond: (variables: any) => unknown, headers?: Headers.Headers) => + Effect.gen(function*() { + const requests = yield* Ref.make>([]) + const layer = protocolLayer({ + execute: (request) => + Effect.as(Ref.update(requests, (all) => [...all, request]), { + body: respond(request.variables), + status: 200, + headers + }) + }) + const client = yield* GraphQLClient.make(GraphQLGroup.make(RepoNodes, SearchRepos, PullRequest, RepoIssues)).pipe( + Effect.provide(layer) + ) + return { client, requests } + }) + +/** Requests every key concurrently and returns each entry's success or failure. */ +const resolveAll = (keys: ReadonlyArray, get: (key: K) => Effect.Effect) => + Effect.forEach( + keys, + (key) => Effect.map(Effect.result(get(key)), (r) => r._tag === "Success" ? r.success : r.failure), + { concurrency: "unbounded" } + ) + +const byId = (client: Effect.Success>["client"]) => + GraphQLResolver.request(GraphQLResolver.ordered(client.RepoNodes, { + variables: (ids: ReadonlyArray) => ({ ids }), + path: ["nodes"], + typename: "Repository" + })) + +const byName = (client: Effect.Success>["client"]) => + GraphQLResolver.request(GraphQLResolver.findById(client.SearchRepos, { + key: (repo) => repo.nameWithOwner, + variables: (names) => ({ query: names.map((name) => `repo:${name}`).join(" ") }), + path: ["search", "nodes"], + typename: "Repository" + })) + +const searchNames = (variables: { query: string }) => variables.query.split(" ").map((term) => term.slice(5)) + +const searchResult = (nodes: ReadonlyArray, hasNextPage = false) => ({ + data: { search: { pageInfo: { hasNextPage, endCursor: null }, nodes } } +}) + +/** Splits batched variables (`_0_name`, `_1_name`, …) into each slice's variables, keyed by prefix. */ +const slices = (variables: unknown): Record> => { + const out: Record> = {} + for (const [key, value] of Object.entries(variables as Record)) { + const [, prefix, name] = /^(_\d+_)(.+)$/.exec(key)! + out[prefix] ??= {} + out[prefix][name] = value + } + return out +} + +/** Answers every slice with `respond(variables)` under its aliased `repository` field. */ +const answerSlices = (variables: unknown, respond: (variables: any) => unknown) => + Object.fromEntries( + Object.entries(slices(variables)).map(([prefix, slice]) => [`${prefix}repository`, respond(slice)]) + ) + +const pullRequest = (variables: { readonly name: string; readonly number: number }) => ({ + pullRequest: { title: `${variables.name}#${variables.number}` } +}) + +const getPullRequest = (client: Effect.Success>["client"]) => + GraphQLResolver.request(GraphQLResolver.aliased(client.PullRequest)) + +const lookups = [{ name: "effect", number: 1 }, { name: "effect", number: 2 }] + +describe("GraphQLResolver", () => { + describe("ordered", () => { + it.effect("batches concurrent keys into one call; a null item or a typename mismatch is a miss", () => + Effect.gen(function*() { + const store: Record = { + R_1: repo("Effect-TS/effect"), + U_1: { __typename: "User", login: "tim" } + } + const { client, requests } = yield* makeClient((variables) => ({ + data: { nodes: variables.ids.map((id: string) => store[id] ?? null) } + })) + + const results = yield* resolveAll(["R_1", "R_2", "U_1", "R_1"], byId(client)) + + const sent = yield* Ref.get(requests) + assert.strictEqual(sent.length, 1) + assert.deepStrictEqual([...(sent[0].variables as { ids: Array }).ids].sort(), ["R_1", "R_2", "U_1"]) + assert.deepStrictEqual(results[0], repo("Effect-TS/effect")) + assert.deepStrictEqual(results[3], repo("Effect-TS/effect")) + assert.instanceOf(results[1], Cause.NoSuchElementError) + assert.instanceOf(results[2], Cause.NoSuchElementError) + })) + + it.effect("an error at [...path, i] fails only entry i, keeping the response status and headers", () => + Effect.gen(function*() { + const { client } = yield* makeClient((variables) => { + const failed = variables.ids.indexOf("R_2") + return { + data: { nodes: variables.ids.map((id: string) => id === "R_2" ? null : repo(id)) }, + errors: [{ message: "Could not resolve", path: ["nodes", failed] }] + } + }, Headers.fromInput({ "retry-after": "60" })) + + const [ok, failed] = yield* resolveAll(["R_1", "R_2"], byId(client)) + + assert.deepStrictEqual(ok, repo("R_1")) + assert.instanceOf(failed, GraphQLClientError) + assert.strictEqual(failed.reason._tag, "ResponseError") + const reason = failed.reason as ResponseError + assert.deepStrictEqual(reason.errors.map((error) => error.message), ["Could not resolve"]) + assert.strictEqual(reason.status, 200) + assert.strictEqual(reason.headers?.["retry-after"], "60") + assert.isTrue(failed.isRetryable) + })) + + it.effect("an error at any other path fails the batch", () => + Effect.gen(function*() { + const { client } = yield* makeClient((variables) => ({ + data: { nodes: variables.ids.map(repo) }, + errors: [{ message: "Rate limited", path: ["rateLimit"] }] + })) + + const results = yield* resolveAll(["R_1", "R_2"], byId(client)) + + for (const result of results) { + assert.instanceOf(result, GraphQLClientError) + assert.strictEqual(result.reason._tag, "ResponseError") + } + })) + }) + + describe("ordered, when an error nulls the whole list", () => { + const NullableNodes = GraphQL.query("NullableNodes", { + document: "query NullableNodes($ids:[ID!]!){nodes(ids:$ids){__typename ...on Repository{nameWithOwner}}}", + variables: { ids: Schema.Array(Schema.String) }, + result: Schema.Struct({ nodes: Schema.NullOr(Schema.Array(Repository)) }) + }) + + it.effect("every entry fails with the ResponseError instead of NoSuchElementError", () => + Effect.gen(function*() { + const client = yield* GraphQLClient.make(GraphQLGroup.make(NullableNodes)).pipe( + Effect.provide(protocolLayer({ + execute: () => + Effect.succeed({ + body: { data: { nodes: null }, errors: [{ message: "boom", path: ["nodes", 1, "nameWithOwner"] }] }, + status: 200 + }) + })) + ) + const get = GraphQLResolver.request(GraphQLResolver.ordered(client.NullableNodes, { + variables: (ids: ReadonlyArray) => ({ ids }), + path: ["nodes"] + })) + for (const failed of yield* resolveAll(["R_1", "R_2"], get)) { + assert.instanceOf(failed, GraphQLClientError) + assert.strictEqual(failed.reason._tag, "ResponseError") + } + })) + }) + + describe("findById", () => { + it.effect("matches out-of-order results on a nested path by key; a missing key is a miss", () => + Effect.gen(function*() { + const { client } = yield* makeClient((variables) => + searchResult(searchNames(variables).filter((name) => name !== "a/missing").map(repo).reverse()) + ) + + const results = yield* resolveAll(["Effect-TS/effect", "a/missing", "Effect-TS/website"], byName(client)) + + assert.deepStrictEqual(results[0], repo("Effect-TS/effect")) + assert.instanceOf(results[1], Cause.NoSuchElementError) + assert.deepStrictEqual(results[2], repo("Effect-TS/website")) + })) + + it.effect("hasNextPage: true on the list's parent fails the batch", () => + Effect.gen(function*() { + const { client } = yield* makeClient((variables) => searchResult(searchNames(variables).map(repo), true)) + + const results = yield* resolveAll(["Effect-TS/effect", "Effect-TS/website"], byName(client)) + + for (const result of results) { + assert.instanceOf(result, GraphQLClientError) + assert.strictEqual(result.reason._tag, "DecodeError") + } + })) + }) + + describe("batchKey", () => { + it.effect("splits a batch by key and calls each group with its own services", () => + Effect.gen(function*() { + const requests = yield* Ref.make>([]) + const layer = protocolLayer({ + execute: (request) => + Effect.as(Ref.update(requests, (all) => [...all, request]), { + body: { data: { nodes: (request.variables as { ids: Array }).ids.map(repo) } }, + status: 200 + }) + }) + const client = yield* GraphQLClient.make(GraphQLGroup.make(RepoNodes).middleware(Auth)).pipe( + Effect.provide([layer, AuthLive]) + ) + const get = GraphQLResolver.request(GraphQLResolver.ordered(client.RepoNodes, { + variables: (ids: ReadonlyArray) => ({ ids }), + path: ["nodes"], + batchKey: (context) => Context.get(context, CurrentUser).tenant + })) + const getAs = (tenant: string, id: string) => Effect.provideService(get(id), CurrentUser, { tenant }) + + const results = yield* Effect.all([getAs("a", "R_1"), getAs("b", "R_2"), getAs("a", "R_3")], { + concurrency: "unbounded" + }) + + assert.deepStrictEqual(results, [repo("R_1"), repo("R_2"), repo("R_3")]) + const sent = yield* Ref.get(requests) + assert.deepStrictEqual( + sent.map((request) => + `${request.headers["authorization"]}: ${[...(request.variables as { ids: Array }).ids].sort()}` + ).sort(), + ["Bearer a: R_1,R_3", "Bearer b: R_2"] + ) + })) + }) + + describe("url", () => { + const GitHubHost = Context.Reference("test/GitHubHost", { defaultValue: () => "api.github.com" }) + + /** Looks up R_1 and R_3 on the default host and R_2 on another, returning what each request sent. */ + const lookUpOnTwoHosts = (url: Parameters[0]["url"]) => + Effect.gen(function*() { + const sent: Array = [] + const layer = GraphQLProtocol.layerHttp({ url }).pipe( + Layer.provide(httpClientLayer((_, bodyText, url) => { + const { ids } = JSON.parse(bodyText!).variables as { ids: Array } + sent.push(`${url.host}: ${[...ids].sort()}`) + return graphqlResponse({ data: { nodes: ids.map(repo) } }) + })) + ) + const client = yield* GraphQLClient.make(GraphQLGroup.make(RepoNodes)).pipe(Effect.provide(layer)) + const get = GraphQLResolver.request(GraphQLResolver.ordered(client.RepoNodes, { + variables: (ids: ReadonlyArray) => ({ ids }), + path: ["nodes"] + })) + + const results = yield* Effect.all([ + get("R_1"), + Effect.provideService(get("R_2"), GitHubHost, "api.acme.ghe.com"), + get("R_3") + ], { concurrency: "unbounded" }) + + assert.deepStrictEqual(results, [repo("R_1"), repo("R_2"), repo("R_3")]) + return sent.sort() + }) + + const urls = [ + [ + "function", + ({ context }: { readonly context: Context.Context }) => + `http://${Context.get(context, GitHubHost)}/graphql` + ], + [ + "Effect resolved asynchronously", + Effect.gen(function*() { + yield* Effect.promise(() => Promise.resolve()) + return `http://${yield* GitHubHost}/graphql` + }) + ] + ] as const + + for (const [form, url] of urls) { + it.effect(`${form}: lookups whose URLs differ go in separate batches; lookups with the same URL share one`, () => + Effect.gen(function*() { + const sent = yield* lookUpOnTwoHosts(url) + assert.deepStrictEqual(sent, ["api.acme.ghe.com: R_2", "api.github.com: R_1,R_3"]) + })) + } + + it.effect("a batch is sent to the URL its lookups resolved to, without evaluating the URL again", () => + Effect.gen(function*() { + let evaluations = 0 + const sent = yield* lookUpOnTwoHosts(Effect.gen(function*() { + evaluations++ + return `http://${yield* GitHubHost}/graphql` + })) + assert.deepStrictEqual(sent, ["api.acme.ghe.com: R_2", "api.github.com: R_1,R_3"]) + // Once per lookup, and not again when each batch is sent. + assert.strictEqual(evaluations, 3) + })) + + it.effect("a direct call made while a batch is sent resolves its own URL", () => + Effect.gen(function*() { + class Nested extends GraphQLMiddleware.Service()("test/Nested") {} + const sent: Array = [] + const layer = GraphQLProtocol.layerHttp({ + url: Effect.map(Effect.service(GitHubHost), (host) => `http://${host}/graphql`) + }).pipe( + Layer.provide(httpClientLayer((_, bodyText, url) => { + const { ids } = JSON.parse(bodyText!).variables as { ids: Array } + sent.push(`${url.host}: ${ids}`) + return graphqlResponse({ data: { nodes: ids.map(repo) } }) + })) + ) + // Both clients share one transport. The batched client's middleware + // calls the same operation directly on another host. + const batched = yield* Effect.gen(function*() { + const direct = yield* GraphQLClient.make(GraphQLGroup.make(RepoNodes)) + return yield* GraphQLClient.make(GraphQLGroup.make(RepoNodes).middleware(Nested)).pipe( + Effect.provideService(Nested, { + execute: ({ next, request }) => + Effect.andThen( + Effect.orDie( + direct.RepoNodes({ ids: ["R_9"] }, { context: Context.make(GitHubHost, "api.acme.ghe.com") }) + ), + next(request) + ), + subscribe: ({ next, request }) => next(request) + }) + ) + }).pipe(Effect.provide(layer)) + const get = GraphQLResolver.request(GraphQLResolver.ordered(batched.RepoNodes, { + variables: (ids: ReadonlyArray) => ({ ids }), + path: ["nodes"] + })) + + assert.deepStrictEqual(yield* get("R_1"), repo("R_1")) + assert.deepStrictEqual(sent, ["api.acme.ghe.com: R_9", "api.github.com: R_1"]) + })) + }) + + describe("aliased", () => { + it.effect("concurrent lookups make one POST whose document repeats the operation under aliases", () => + Effect.gen(function*() { + const sent: Array<{ readonly method: string; readonly body: any }> = [] + // Queries go over GET, but a batch must not. + const layer = GraphQLProtocol.layerHttp({ url: "http://localhost/graphql", queryMethod: "GET" }).pipe( + Layer.provide(httpClientLayer((request, bodyText) => { + const body = bodyText === undefined ? undefined : JSON.parse(bodyText) + sent.push({ method: request.method, body }) + return graphqlResponse({ data: answerSlices(body?.variables ?? {}, pullRequest) }) + })) + ) + const client = yield* GraphQLClient.make(GraphQLGroup.make(PullRequest)).pipe(Effect.provide(layer)) + const keys = [1, 2, 3].map((number) => ({ name: "effect", number })) + + const results = yield* Effect.forEach( + keys, + GraphQLResolver.request(GraphQLResolver.aliased(client.PullRequest)), + { concurrency: "unbounded" } + ) + + assert.deepStrictEqual(results, keys.map((key) => ({ repository: pullRequest(key) }))) + assert.strictEqual(sent.length, 1) + assert.strictEqual(sent[0].method, "POST") + assert.strictEqual( + sent[0].body.query, + "query PullRequest($_0_name:String!$_0_number:Int!$_1_name:String!$_1_number:Int!$_2_name:String!$_2_number:Int!){_0_repository:repository(owner:\"Effect-TS\",name:$_0_name){pullRequest(number:$_0_number){title}}_1_repository:repository(owner:\"Effect-TS\",name:$_1_name){pullRequest(number:$_1_number){title}}_2_repository:repository(owner:\"Effect-TS\",name:$_2_name){pullRequest(number:$_2_number){title}}}" + ) + assert.deepStrictEqual(Object.values(slices(sent[0].body.variables)).map((slice) => slice.number).sort(), [ + 1, + 2, + 3 + ]) + })) + + it.effect("an error at path[0] fails only its slice, with the path un-prefixed", () => + Effect.gen(function*() { + const { client } = yield* makeClient((variables) => { + const prefix = Object.entries(slices(variables)).find(([, slice]) => slice.number === 2)![0] + return { + data: answerSlices(variables, (slice) => slice.number === 2 ? { pullRequest: null } : pullRequest(slice)), + errors: [{ message: "Could not resolve", path: [`${prefix}repository`, "pullRequest"] }] + } + }) + + const [ok, failed] = yield* resolveAll(lookups, getPullRequest(client)) + + assert.deepStrictEqual(ok, { repository: pullRequest(lookups[0]) }) + assert.instanceOf(failed, GraphQLClientError) + assert.strictEqual(failed.reason._tag, "ResponseError") + const reason = failed.reason as ResponseError + assert.deepStrictEqual(reason.errors.map((error) => error.path), [["repository", "pullRequest"]]) + })) + + it.effect("rejects a template it can't slice when the resolver is built, not on the first lookup", () => + Effect.gen(function*() { + const RootSpread = GraphQL.query("RootSpread", { + document: { variables: [], selections: [{ body: ["...on Query{__typename}"] }], fragments: [] }, + result: Schema.Struct({ __typename: Schema.String }) + }) + const client = yield* GraphQLClient.make(GraphQLGroup.make(RootSpread)).pipe( + Effect.provide(protocolLayer({ execute: () => Effect.die("not sent") })) + ) + assert.throws( + () => GraphQLResolver.aliased(client.RootSpread), + /fragment spread or inline fragment at the root/ + ) + })) + + it.effect("an error without a path fails the batch", () => + Effect.gen(function*() { + const { client } = yield* makeClient((variables) => ({ + data: answerSlices(variables, pullRequest), + errors: [{ message: "Rate limited" }] + })) + + const results = yield* resolveAll(lookups, getPullRequest(client)) + + for (const result of results) { + assert.instanceOf(result, GraphQLClientError) + assert.strictEqual(result.reason._tag, "ResponseError") + } + })) + + it.effect("lookups whose encoded variables are equal share one slice", () => + Effect.gen(function*() { + const issues = { totalCount: 1 } + const { client, requests } = yield* makeClient((variables) => ({ + data: answerSlices(variables, () => ({ issues })) + })) + + // Not `Equal`, but both encode to `{"name":"effect"}`. + const results = yield* resolveAll( + [{ name: "effect" }, { name: "effect", after: undefined }], + GraphQLResolver.request(GraphQLResolver.aliased(client.RepoIssues)) + ) + + assert.deepStrictEqual(results, [{ repository: { issues } }, { repository: { issues } }]) + const sent = yield* Ref.get(requests) + assert.strictEqual(sent.length, 1) + assert.deepStrictEqual(Object.keys(slices(sent[0].variables)), ["_0_"]) + })) + + it.effect("over a makeTest client, the handler is called once per slice", () => + Effect.gen(function*() { + const received: Array<{ readonly name: string; readonly number: number }> = [] + const client = GraphQLClient.makeTest(GraphQLGroup.make(PullRequest))({ + PullRequest: (variables) => { + received.push(variables) + return Effect.succeed({ repository: pullRequest(variables) }) + } + }) + + const results = yield* Effect.forEach( + lookups, + GraphQLResolver.request(GraphQLResolver.aliased(client.PullRequest)), + { concurrency: "unbounded" } + ) + + assert.deepStrictEqual(results, lookups.map((key) => ({ repository: pullRequest(key) }))) + assert.deepStrictEqual(received.map((variables) => variables.number).sort(), [1, 2]) + })) + }) +}) diff --git a/repos/effect/packages/effect/test/graphql/fixtures.ts b/repos/effect/packages/effect/test/graphql/fixtures.ts new file mode 100644 index 0000000000..5abd8f1c31 --- /dev/null +++ b/repos/effect/packages/effect/test/graphql/fixtures.ts @@ -0,0 +1,233 @@ +/** + * Shared fixtures for the `effect/graphql` runtime tests. + * + * The operations below stand in for what `@effect/graphql-generator` emits for a + * GitHub-style schema, including a custom scalar codec (`DateTime`). + */ +import { assert } from "@effect/vitest" +import { Deferred, Effect, Layer, Queue, Ref, Schema, Stream } from "effect" +import { GraphQL, GraphQLGroup } from "effect/graphql" +import { GraphQLClientError } from "effect/graphql/GraphQLClientError" +import * as GraphQLProtocol from "effect/graphql/GraphQLProtocol" +import * as HttpBody from "effect/http/HttpBody" +import * as HttpClient from "effect/http/HttpClient" +import type * as HttpClientRequest from "effect/http/HttpClientRequest" +import * as HttpClientResponse from "effect/http/HttpClientResponse" +import * as Socket from "effect/socket/Socket" + +// ----------------------------------------------------------------------------- +// Stand-in for generated output +// ----------------------------------------------------------------------------- + +const Issue = Schema.Struct({ + number: Schema.Int, + title: Schema.String, + createdAt: Schema.DateTimeUtcFromString +}) + +export const RepoIssues = GraphQL.query("RepoIssues", { + document: + "query RepoIssues($owner:String!,$name:String!,$after:String,$since:DateTime){repository(owner:$owner,name:$name){issues(first:2,after:$after,filterBy:{since:$since}){pageInfo{hasNextPage endCursor}nodes{number title createdAt}}}}", + variables: { + owner: Schema.String, + name: Schema.String, + after: Schema.optional(Schema.NullOr(Schema.String)), + since: Schema.optional(Schema.NullOr(Schema.DateTimeUtcFromString)) + }, + result: Schema.Struct({ + repository: Schema.NullOr(Schema.Struct({ + issues: Schema.NullOr(Schema.Struct({ + pageInfo: Schema.Struct({ hasNextPage: Schema.Boolean, endCursor: Schema.NullOr(Schema.String) }), + nodes: Schema.NullOr(Schema.Array(Schema.NullOr(Issue))) + })) + })) + }) +}) + +export const Viewer = GraphQL.query("Viewer", { + document: "query Viewer{viewer{login}}", + result: Schema.Struct({ viewer: Schema.Struct({ login: Schema.String }) }) +}) + +export const IssueUpdated = GraphQL.subscription("IssueUpdated", { + document: "subscription IssueUpdated($id:ID!){issueUpdated(id:$id){title}}", + variables: { id: Schema.String }, + result: Schema.Struct({ issueUpdated: Schema.Struct({ title: Schema.String }) }) +}) + +export const IssuesGroup = GraphQLGroup.make(RepoIssues, IssueUpdated) +export const ViewerGroup = GraphQLGroup.make(Viewer) + +// ----------------------------------------------------------------------------- +// Transport doubles +// ----------------------------------------------------------------------------- + +/** + * A `GraphQLProtocol` layer with scripted behaviour. Tests that exercise the + * client (middleware, partial results, paging, subscriptions) use this instead + * of HTTP so they stay about the client. + */ +export const protocolLayer = (service: { + readonly execute?: GraphQLProtocol.GraphQLProtocol["Service"]["execute"] + readonly subscribe?: GraphQLProtocol.GraphQLProtocol["Service"]["subscribe"] +}) => + Layer.succeed(GraphQLProtocol.GraphQLProtocol, { + execute: service.execute ?? (() => Effect.die("execute not scripted")), + subscribe: service.subscribe ?? (() => Stream.die("subscribe not scripted")) + }) + +/** + * A protocol whose `execute` always answers with the same raw body, and HTTP + * `status` when given, and records every request it received. + */ +export const executeLayer = (body: unknown, status?: number) => + Effect.gen(function*() { + const requests = yield* Ref.make>([]) + const layer = protocolLayer({ + execute: (request) => + Effect.as( + Ref.update(requests, (all) => [...all, request]), + status === undefined ? { body } : { body, status } + ) + }) + return { layer, requests } + }) + +/** + * An `HttpClient` that answers every request from `handler`, with the request + * body text and the final URL exposed so tests can assert on what went over + * the wire. + */ +export const httpClientLayer = ( + handler: (request: HttpClientRequest.HttpClientRequest, bodyText: string | undefined, url: URL) => Response +) => + Layer.succeed( + HttpClient.HttpClient, + HttpClient.make((request, url) => + Effect.sync(() => + HttpClientResponse.fromWeb( + request, + handler(request, request.body instanceof HttpBody.Uint8Array ? request.body.text : undefined, url) + ) + ) + ) + ) + +export const graphqlResponse = (body: unknown, init?: { status?: number; contentType?: string }) => + new Response(JSON.stringify(body), { + status: init?.status ?? 200, + headers: { "content-type": init?.contentType ?? "application/graphql-response+json" } + }) + +export const layerHttp = ( + handler: (request: HttpClientRequest.HttpClientRequest, bodyText: string | undefined, url: URL) => Response +) => GraphQLProtocol.layerHttp({ url: "http://localhost/graphql" }).pipe(Layer.provide(httpClientLayer(handler))) + +/** + * A graphql-ws message as it goes over the wire. + */ +export interface WsMessage { + readonly type: string + readonly id?: string | undefined + readonly payload?: unknown +} + +/** + * The server end of one in-memory WebSocket opened by the transport. + */ +interface WsConnection { + readonly url: string + readonly options: Socket.WebSocketConstructorOptions | undefined + /** Every frame the client sent, parsed. */ + readonly received: Queue.Queue + /** The code the client closed with, once it does. */ + readonly closed: Deferred.Deferred + readonly send: (message: WsMessage) => Effect.Effect + readonly close: (code: number, reason?: string) => Effect.Effect +} + +/** + * A `Socket.WebSocketConstructor` whose sockets are in-memory queue pairs. + * Each socket the transport opens shows up on `connections`, already open, + * for the test to script the server side. + */ +export const wsServer = Effect.gen(function*() { + const connections = yield* Queue.unbounded() + const layer = Layer.succeed( + Socket.WebSocketConstructor, + (url, options) => { + const inbox = Effect.runSync(Queue.unbounded()) + const closedWith = Effect.runSync(Deferred.make()) + let listeners: Array<{ + readonly type: string + readonly listener: (event: Socket.WebSocketEvent) => void + readonly once: boolean + }> = [] + const dispatch = (type: string, event: Socket.WebSocketEvent) => { + for (const entry of listeners.filter((entry) => entry.type === type)) { + if (entry.once) listeners = listeners.filter((other) => other !== entry) + entry.listener(event) + } + } + const ws = { + readyState: 1, + addEventListener(type, listener, options) { + listeners.push({ type, listener, once: options?.once === true }) + }, + removeEventListener(type, listener) { + listeners = listeners.filter((entry) => entry.type !== type || entry.listener !== listener) + }, + send(data) { + Queue.offerUnsafe(inbox, JSON.parse(typeof data === "string" ? data : new TextDecoder().decode(data))) + }, + close(code = 1005, reason) { + if (ws.readyState >= 2) return + ws.readyState = 3 + Deferred.doneUnsafe(closedWith, Effect.succeed(code)) + dispatch("close", { code, reason: reason ?? "" }) + } + } satisfies Socket.WebSocketLike & { readyState: number } + Queue.offerUnsafe(connections, { + url, + options, + received: inbox, + closed: closedWith, + send: (message) => Effect.sync(() => dispatch("message", { data: JSON.stringify(message) })), + close: (code, reason) => + Effect.sync(() => { + if (ws.readyState >= 2) return + ws.readyState = 3 + dispatch("close", { code, reason: reason ?? "" }) + }) + }) + return ws + } + ) + /** + * Takes the next connection, reads its `connection_init` and acknowledges it. + */ + const accept = Effect.gen(function*() { + const connection = yield* Queue.take(connections) + const init = yield* Queue.take(connection.received) + assert.strictEqual(init.type, "connection_init") + yield* connection.send({ type: "connection_ack" }) + return { connection, init } + }) + return { layer, connections, accept } +}) + +// ----------------------------------------------------------------------------- +// Assertions +// ----------------------------------------------------------------------------- + +/** + * Runs `effect`, asserts it fails with a `GraphQLClientError` whose reason has + * `tag`, and returns that reason narrowed. + */ +export const expectReason = + (tag: Tag) => (effect: Effect.Effect) => + Effect.map(Effect.flip(effect), (error) => { + assert.instanceOf(error, GraphQLClientError) + assert.strictEqual(error.reason._tag, tag) + return error.reason as Extract + }) diff --git a/repos/effect/packages/effect/test/http/FindMyWay/querystring.test.ts b/repos/effect/packages/effect/test/http/FindMyWay/querystring.test.ts index 74180d0cb9..5fa32e67d4 100644 --- a/repos/effect/packages/effect/test/http/FindMyWay/querystring.test.ts +++ b/repos/effect/packages/effect/test/http/FindMyWay/querystring.test.ts @@ -36,3 +36,11 @@ it("handles %", () => { "%": "" }) }) + +it("normalizes duplicate path slashes without changing query slashes", () => { + const router = Router.make() + router.on("GET", "/user/:id", true) + const result = router.find("GET", "//user//1?u=https://x.com/y") + assert.deepStrictEqual(result?.params, { id: "1" }) + assert.deepStrictEqual(result?.searchParams, { u: "https://x.com/y" }) +}) diff --git a/repos/effect/packages/effect/test/http/HttpClient.test.ts b/repos/effect/packages/effect/test/http/HttpClient.test.ts index 74662c69bc..3058dd8c47 100644 --- a/repos/effect/packages/effect/test/http/HttpClient.test.ts +++ b/repos/effect/packages/effect/test/http/HttpClient.test.ts @@ -1,10 +1,11 @@ import { assert, describe, it, vi } from "@effect/vitest" import { strictEqual } from "@effect/vitest/utils" -import { Clock, Duration, Effect, Fiber, Layer, Ref, Schema, Stream } from "effect" -import { Cookies, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/http" +import { Clock, Deferred, Duration, Effect, Fiber, Layer, Redacted, Ref, Schedule, Schema, Stream } from "effect" +import { Cookies, HttpClient, HttpClientError, HttpClientRequest, HttpClientResponse, UrlParams } from "effect/http" import { RateLimiter } from "effect/persistence" import { TestClock } from "effect/testing" import * as Tracer from "effect/Tracer" +import { inspect } from "node:util" import { collectGarbage } from "../utils/gc.ts" const makeStatusClient = Effect.fnUntraced(function*(status: number) { @@ -18,6 +19,19 @@ const makeStatusClient = Effect.fnUntraced(function*(status: number) { return { attempts, client } as const }) +const makeSequenceClient = Effect.fnUntraced(function*( + responses: ReadonlyArray<{ readonly status: number; readonly headers?: Record }> +) { + const attempts = yield* Ref.make(0) + const client = HttpClient.make((request) => + Effect.map( + Ref.getAndUpdate(attempts, (n) => n + 1), + (n) => HttpClientResponse.fromWeb(request, new Response(null, responses[Math.min(n, responses.length - 1)])) + ) + ) + return { attempts, client } as const +}) + const makeRedirectClient = Effect.fnUntraced(function*(status: number, location: string | ReadonlyArray) { const locations = typeof location === "string" ? [location] : location const requests = yield* Ref.make>([]) @@ -272,6 +286,166 @@ Missing key assert.strictEqual(clientSpan.attributes.get("http.request.header.x-phase-filter"), undefined) assert.strictEqual(clientSpan.attributes.get("http.response.header.x-phase-filter"), "response") })) + + it.effect("redacts sensitive query params in url attributes", () => + Effect.gen(function*() { + let clientSpan: Tracer.NativeSpan | undefined + let sentUrl: string | undefined + const tracer = Tracer.make({ + span(options) { + clientSpan = new Tracer.NativeSpan(options) + return clientSpan + } + }) + const client = HttpClient.make((request, url) => { + sentUrl = url.toString() + return Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null))) + }) + + yield* client.get("http://test/path?Signature=sig-secret&page=1", { + urlParams: { "X-Goog-Signature": "goog-secret" } + }).pipe(Effect.provideService(Tracer.Tracer, tracer)) + + assert(clientSpan !== undefined) + assert.strictEqual( + clientSpan.attributes.get("url.full"), + "http://test/path?Signature=REDACTED&page=1&X-Goog-Signature=REDACTED" + ) + assert.strictEqual( + clientSpan.attributes.get("url.query"), + "Signature=REDACTED&page=1&X-Goog-Signature=REDACTED" + ) + assert.strictEqual(sentUrl, "http://test/path?Signature=sig-secret&page=1&X-Goog-Signature=goog-secret") + })) + + it.effect("redacts userinfo in url.full", () => + Effect.gen(function*() { + let clientSpan: Tracer.NativeSpan | undefined + const tracer = Tracer.make({ + span(options) { + clientSpan = new Tracer.NativeSpan(options) + return clientSpan + } + }) + const client = HttpClient.make((request) => + Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null))) + ) + + yield* client.get("http://user:password@test/path").pipe(Effect.provideService(Tracer.Tracer, tracer)) + + assert(clientSpan !== undefined) + assert.strictEqual(clientSpan.attributes.get("url.full"), "http://REDACTED:REDACTED@test/path") + })) + + it.effect("redacts Redacted query params in url attributes", () => + Effect.gen(function*() { + let clientSpan: Tracer.NativeSpan | undefined + let sentUrl: string | undefined + const tracer = Tracer.make({ + span(options) { + clientSpan = new Tracer.NativeSpan(options) + return clientSpan + } + }) + const client = HttpClient.make((request, url) => { + sentUrl = url.toString() + return Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null))) + }) + + yield* HttpClientRequest.get("http://test/path?page=1#frag").pipe( + HttpClientRequest.appendUrlParam("remote", Redacted.make("param-secret")), + HttpClientRequest.appendUrlParam("\uD800", Redacted.make("surrogate-secret")), + HttpClientRequest.appendUrlParam("q", "visible"), + client.execute, + Effect.provideService(Tracer.Tracer, tracer) + ) + + assert(clientSpan !== undefined) + assert.strictEqual( + clientSpan.attributes.get("url.full"), + "http://test/path?page=1&remote=REDACTED&%EF%BF%BD=REDACTED&q=visible#frag" + ) + assert.strictEqual( + clientSpan.attributes.get("url.query"), + "page=1&remote=REDACTED&%EF%BF%BD=REDACTED&q=visible" + ) + assert.strictEqual( + sentUrl, + "http://test/path?page=1&remote=param-secret&%EF%BF%BD=surrogate-secret&q=visible#frag" + ) + })) + + const makeCapturingClient = () => { + let sent: HttpClientRequest.HttpClientRequest | undefined + const client = HttpClient.make((request) => { + sent = request + return Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null))) + }) + return { client, sent: () => sent } + } + + it.effect("sends trace headers by default", () => + Effect.gen(function*() { + const { client, sent } = makeCapturingClient() + + yield* client.get("http://test/") + + const request = sent() + assert(request !== undefined) + assert.strictEqual(typeof request.headers.b3, "string") + assert.strictEqual(typeof request.headers.traceparent, "string") + })) + + it.effect("omits trace headers when propagation is disabled and keeps the client span", () => + Effect.gen(function*() { + const { client, sent } = makeCapturingClient() + let clientSpan: Tracer.NativeSpan | undefined + const tracer = Tracer.make({ + span(options) { + clientSpan = new Tracer.NativeSpan(options) + return clientSpan + } + }) + + yield* client.get("http://test/").pipe( + Effect.provideService(HttpClient.TracerPropagationEnabled, false), + Effect.provideService(Tracer.Tracer, tracer) + ) + + const request = sent() + assert(request !== undefined) + assert.isUndefined(request.headers.b3) + assert.isUndefined(request.headers.traceparent) + assert(clientSpan !== undefined) + })) + }) + + describe("HttpClientError", () => { + it.effect("does not expose Redacted query params", () => + Effect.gen(function*() { + const client = HttpClient.make((request) => + Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null, { status: 500 }))) + ).pipe(HttpClient.filterStatusOk) + + const error = yield* client.get("http://test/path", { + urlParams: { remote: Redacted.make("param-secret"), q: "visible" } + }).pipe(Effect.flip) + + for (const output of [JSON.stringify(error), String(error), inspect(error, { depth: 10 })]) { + assert.notInclude(output, "param-secret") + } + assert.include(JSON.stringify(error), "visible") + })) + + it.effect("redacts query params in messages using the current redacted names", () => + Effect.gen(function*() { + const request = HttpClientRequest.get("http://test/path?token=token-secret&sig=sig-visible") + const error = new HttpClientError.HttpClientError({ + reason: new HttpClientError.TransportError({ request }) + }) + + strictEqual(error.message, "Transport error (GET http://test/path?token=REDACTED&sig=sig-visible)") + }).pipe(Effect.provideService(UrlParams.CurrentRedactedNames, ["token"]))) }) describe("followRedirects", () => { @@ -413,6 +587,43 @@ Missing key yield* retryClient.get("http://test/").pipe(Effect.ignore) strictEqual(yield* Ref.get(attempts), 1) })) + + it.effect.each([ + { name: "seconds", header: "1", status: 503, delay: 1_000 }, + { name: "a five-minute Retry-After", header: "300", status: 429, delay: 300_000 }, + { name: "HTTP date on an errors-only retry", header: "date", status: 429, delay: 30_000 }, + { name: "a longer schedule", header: "5", status: 503, delay: 60_000, scheduled: true }, + { name: "no header", status: 503, delay: 0 } + ])( + "honors the retry delay for $name", + ({ delay, header, scheduled, status }) => + Effect.gen(function*() { + const retryAfter = header === "date" + ? new Date((yield* Clock.currentTimeMillis) + 30_000).toUTCString() + : header + const { attempts, client } = yield* makeSequenceClient([ + { status, headers: retryAfter === undefined ? {} : { "retry-after": retryAfter } }, + { status: 200 } + ]) + const retryClient = (header === "date" ? HttpClient.filterStatusOk(client) : client).pipe( + HttpClient.retryTransient({ + retryOn: header === "date" ? "errors-only" : "errors-and-responses", + times: 1, + ...(scheduled ? { schedule: Schedule.spaced("1 minute") } : {}) + }) + ) + const fiber = yield* retryClient.get("http://test/").pipe( + Effect.forkChild({ startImmediately: true }) + ) + + if (delay > 0) { + yield* TestClock.adjust(Duration.millis(delay - 1)) + strictEqual(yield* Ref.get(attempts), 1) + yield* TestClock.adjust("1 millis") + } + strictEqual((yield* Fiber.join(fiber)).status, 200) + }) + ) }) describe("stream", () => { @@ -606,9 +817,234 @@ Missing key strictEqual(yield* Ref.get(attempts), 1) - yield* TestClock.adjust("10 seconds") + yield* TestClock.adjust("59 seconds") + strictEqual(yield* Ref.get(attempts), 1) + + yield* TestClock.adjust("1 second") + yield* Fiber.join(fiber) + strictEqual(yield* Ref.get(attempts), 2) + }).pipe(Effect.provide(RateLimiterTestLayer))) + + it.effect("tracks remaining headers when the limit header is also present", () => + Effect.gen(function*() { + const attempts = yield* Ref.make(0) + const client = HttpClient.make((request) => + Effect.map( + Ref.updateAndGet(attempts, (n) => n + 1), + (attempt) => + HttpClientResponse.fromWeb( + request, + attempt === 1 + ? new Response(null, { + status: 200, + headers: { + "ratelimit-limit": "800", + "ratelimit-remaining": "1", + "ratelimit-reset-after": "60" + } + }) + : new Response(null, { status: 200 }) + ) + ) + ).pipe( + HttpClient.withRateLimiter({ + limiter: yield* RateLimiter.RateLimiter, + key: "reported-remaining", + limit: 800, + window: "1 minute" + }) + ) + + yield* client.get("http://test/") + yield* client.get("http://test/") + const fiber = yield* client.get("http://test/").pipe(Effect.forkChild({ startImmediately: true })) + + yield* TestClock.adjust("59 seconds") + strictEqual(yield* Ref.get(attempts), 2) + + yield* TestClock.adjust("1 second") + yield* Fiber.join(fiber) + strictEqual(yield* Ref.get(attempts), 3) + }).pipe(Effect.provide(RateLimiterTestLayer))) + + it.effect("retries a 429 at the reported reset when remaining is exhausted", () => + Effect.gen(function*() { + const attempts = yield* Ref.make(0) + const client = HttpClient.make((request) => + Effect.map( + Ref.updateAndGet(attempts, (n) => n + 1), + (attempt) => + HttpClientResponse.fromWeb( + request, + attempt === 1 + ? new Response(null, { + status: 429, + headers: { + "ratelimit-limit": "800", + "ratelimit-remaining": "0", + "ratelimit-reset-after": "60" + } + }) + : new Response(null, { status: 200 }) + ) + ) + ).pipe( + HttpClient.withRateLimiter({ + limiter: yield* RateLimiter.RateLimiter, + key: "reported-429", + limit: 800, + window: "1 minute", + times: 1, + disableAdaptiveLearning: true + }) + ) + + const fiber = yield* client.get("http://test/").pipe(Effect.forkChild({ startImmediately: true })) + + yield* TestClock.adjust("59 seconds") + strictEqual(yield* Ref.get(attempts), 1) + + yield* TestClock.adjust("1 second") + const response = yield* Fiber.join(fiber) + strictEqual(response.status, 200) + strictEqual(yield* Ref.get(attempts), 2) + }).pipe(Effect.provide(RateLimiterTestLayer))) + + it.effect("ignores stale remaining headers from out-of-order responses", () => + Effect.gen(function*() { + const attempts = yield* Ref.make(0) + const releaseFirst = yield* Deferred.make() + const client = HttpClient.make((request) => + Effect.flatMap( + Ref.updateAndGet(attempts, (n) => n + 1), + (attempt) => { + const response = (headers: Record = {}) => + HttpClientResponse.fromWeb(request, new Response(null, { status: 200, headers })) + if (attempt === 1) { + return Effect.as( + Deferred.await(releaseFirst), + response({ "ratelimit-remaining": "5", "ratelimit-reset-after": "60" }) + ) + } + return Effect.succeed( + attempt === 2 + ? response({ "ratelimit-remaining": "0", "ratelimit-reset-after": "60" }) + : response() + ) + } + ) + ).pipe( + HttpClient.withRateLimiter({ + limiter: yield* RateLimiter.RateLimiter, + key: "stale-remaining", + limit: 800, + window: "1 minute" + }) + ) + + const first = yield* client.get("http://test/").pipe(Effect.forkChild({ startImmediately: true })) + yield* client.get("http://test/") + yield* Deferred.succeed(releaseFirst, undefined) + yield* Fiber.join(first) + + const fiber = yield* client.get("http://test/").pipe(Effect.forkChild({ startImmediately: true })) + + yield* TestClock.adjust("59 seconds") + strictEqual(yield* Ref.get(attempts), 2) + + yield* TestClock.adjust("1 second") yield* Fiber.join(fiber) + strictEqual(yield* Ref.get(attempts), 3) + }).pipe(Effect.provide(RateLimiterTestLayer))) + + it.effect("counts requests sent after the reporting request against its remaining", () => + Effect.gen(function*() { + const attempts = yield* Ref.make(0) + const releaseFirst = yield* Deferred.make() + const client = HttpClient.make((request) => + Effect.flatMap( + Ref.updateAndGet(attempts, (n) => n + 1), + (attempt) => + attempt === 1 + ? Effect.as( + Deferred.await(releaseFirst), + HttpClientResponse.fromWeb( + request, + new Response(null, { + status: 200, + headers: { "ratelimit-remaining": "1", "ratelimit-reset-after": "60" } + }) + ) + ) + : Effect.succeed(HttpClientResponse.fromWeb(request, new Response(null, { status: 200 }))) + ) + ).pipe( + HttpClient.withRateLimiter({ + limiter: yield* RateLimiter.RateLimiter, + key: "in-flight-remaining", + limit: 800, + window: "1 minute" + }) + ) + + const first = yield* client.get("http://test/").pipe(Effect.forkChild({ startImmediately: true })) + yield* client.get("http://test/") + yield* Deferred.succeed(releaseFirst, undefined) + yield* Fiber.join(first) + + const fiber = yield* client.get("http://test/").pipe(Effect.forkChild({ startImmediately: true })) + + yield* TestClock.adjust("59 seconds") strictEqual(yield* Ref.get(attempts), 2) + + yield* TestClock.adjust("1 second") + yield* Fiber.join(fiber) + strictEqual(yield* Ref.get(attempts), 3) + }).pipe(Effect.provide(RateLimiterTestLayer))) + + it.effect("paces requests started while remaining is exhausted with the limiter after reset", () => + Effect.gen(function*() { + const attempts = yield* Ref.make(0) + const client = HttpClient.make((request) => + Effect.map( + Ref.updateAndGet(attempts, (n) => n + 1), + (attempt) => + HttpClientResponse.fromWeb( + request, + attempt === 1 + ? new Response(null, { + status: 200, + headers: { + "ratelimit-limit": "2", + "ratelimit-remaining": "0", + "ratelimit-reset-after": "60" + } + }) + : new Response(null, { status: 200 }) + ) + ) + ).pipe( + HttpClient.withRateLimiter({ + limiter: yield* RateLimiter.RateLimiter, + key: "exhausted-pacing", + limit: 2, + window: "1 minute", + disableAdaptiveLearning: true + }) + ) + + yield* client.get("http://test/") + const fibers = yield* Effect.forEach( + [1, 2, 3], + () => client.get("http://test/").pipe(Effect.forkChild({ startImmediately: true })) + ) + + yield* TestClock.adjust("60 seconds") + strictEqual(yield* Ref.get(attempts), 3) + + yield* TestClock.adjust("60 seconds") + yield* Fiber.joinAll(fibers) + strictEqual(yield* Ref.get(attempts), 4) }).pipe(Effect.provide(RateLimiterTestLayer))) it.effect("inspects custom remaining and reset-after headers", () => @@ -652,7 +1088,7 @@ Missing key strictEqual(yield* Ref.get(attempts), 1) - yield* TestClock.adjust("10 seconds") + yield* TestClock.adjust("1 minute") yield* Fiber.join(fiber) strictEqual(yield* Ref.get(attempts), 2) }).pipe(Effect.provide(RateLimiterTestLayer))) @@ -856,6 +1292,45 @@ Missing key strictEqual(yield* Ref.get(attempts), 3) }).pipe(Effect.provide(RateLimiterTestLayer))) + it.effect("waits until a Retry-After HTTP date", () => + Effect.gen(function*() { + const retryAt = new Date((yield* Clock.currentTimeMillis) + 30_000).toUTCString() + const attempts = yield* Ref.make(0) + const client = HttpClient.make((request) => + Effect.map( + Ref.updateAndGet(attempts, (n) => n + 1), + (attempt) => + HttpClientResponse.fromWeb( + request, + new Response(null, { + status: attempt === 1 ? 429 : 200, + headers: { "retry-after": retryAt } + }) + ) + ) + ).pipe( + HttpClient.withRateLimiter({ + limiter: yield* RateLimiter.RateLimiter, + key: "http-date-retry-after", + limit: 100, + window: "1 minute", + times: 1, + disableAdaptiveLearning: true + }) + ) + + const fiber = yield* client.get("http://test/").pipe(Effect.forkChild) + + yield* TestClock.adjust("29 seconds") + strictEqual(yield* Ref.get(attempts), 1) + + yield* TestClock.adjust("1 second") + const response = yield* Fiber.join(fiber) + + strictEqual(response.status, 200) + strictEqual(yield* Ref.get(attempts), 2) + }).pipe(Effect.provide(RateLimiterTestLayer))) + it.effect("uses a custom Retry-After header", () => Effect.gen(function*() { const attempts = yield* Ref.make(0) diff --git a/repos/effect/packages/effect/test/http/HttpClientRequest.test.ts b/repos/effect/packages/effect/test/http/HttpClientRequest.test.ts index 5d3dd08fb2..eaae8da822 100644 --- a/repos/effect/packages/effect/test/http/HttpClientRequest.test.ts +++ b/repos/effect/packages/effect/test/http/HttpClientRequest.test.ts @@ -1,10 +1,109 @@ import { describe, it } from "@effect/vitest" -import { assertNone, assertSome, assertTrue, deepStrictEqual, strictEqual } from "@effect/vitest/utils" -import { ByteSize, Effect, FileSystem, Stream } from "effect" +import { assertFalse, assertNone, assertSome, assertTrue, deepStrictEqual, strictEqual } from "@effect/vitest/utils" +import { ByteSize, Effect, FileSystem, Formatter, Redacted, Stream } from "effect" import { Headers, HttpBody, HttpClientRequest } from "effect/http" import * as Option from "effect/Option" +import { inspect } from "node:util" +import { gunzipSync, inflateSync } from "node:zlib" describe("HttpClientRequest", () => { + describe("compressBody", () => { + const url = "https://example.com" + const text = "hello compression ".repeat(100) + const bytes = new TextEncoder().encode(text) + + it.each( + [ + { name: "bytes", body: HttpBody.uint8Array(bytes, "application/custom"), expected: text, algorithm: "gzip" }, + { name: "lazy text", body: HttpBody.text(text), expected: text, algorithm: "gzip" }, + { name: "JSON", body: HttpBody.jsonUnsafe({ text }), expected: JSON.stringify({ text }), algorithm: "gzip" }, + { name: "deflate", body: HttpBody.uint8Array(bytes), expected: text, algorithm: "deflate" } + ] as const + )("round-trips $name as compressed bytes", async ({ algorithm, body, expected }) => { + const original = HttpClientRequest.post(url).pipe(HttpClientRequest.setBody(body)) + const effect: Effect.Effect = HttpClientRequest.compressBody( + original, + algorithm + ) + const request = await Effect.runPromise(effect) + strictEqual(request.body._tag, "Uint8Array") + if (request.body._tag !== "Uint8Array") { + throw new Error("Expected a compressed Uint8Array body") + } + const decompress = algorithm === "gzip" ? gunzipSync : inflateSync + strictEqual(decompress(request.body.body).toString(), expected) + strictEqual(request.body.text, undefined) + strictEqual(request.body.contentType, body.contentType) + strictEqual(request.body.contentLength, request.body.body.byteLength) + strictEqual(request.headers["content-type"], body.contentType) + strictEqual(request.headers["content-encoding"], algorithm) + strictEqual(request.headers["content-length"], String(request.body.body.byteLength)) + const web = await Effect.runPromise(HttpClientRequest.toWeb(request)) + strictEqual(decompress(new Uint8Array(await web.arrayBuffer())).toString(), expected) + strictEqual(await Effect.runPromise(HttpClientRequest.compressBody(request, algorithm)), request) + }) + + it.each([ + { text: "a".repeat(1023), options: undefined, compressed: false }, + { text: "a".repeat(1024), options: undefined, compressed: true }, + { text: "éé", options: { minSize: 5 }, compressed: false }, + { text: "éé", options: { minSize: 4 }, compressed: true } + ])("applies the byte threshold at $options with $text.length characters", async ({ compressed, options, text }) => { + const original = HttpClientRequest.post(url).pipe(HttpClientRequest.bodyText(text)) + const request = await Effect.runPromise(original.pipe(HttpClientRequest.compressBody("gzip", options))) + if (compressed) { + strictEqual(request.headers["content-encoding"], "gzip") + strictEqual(request.body._tag, "Uint8Array") + if (request.body._tag === "Uint8Array") { + strictEqual(gunzipSync(request.body.body).toString(), text) + } + } else { + strictEqual(request, original) + strictEqual(request.headers["content-encoding"], undefined) + } + }) + + it.effect("leaves unsupported bodies and existing content encodings unchanged", () => + Effect.gen(function*() { + for (const body of [HttpBody.empty, HttpBody.formData(new FormData()), HttpBody.raw(bytes)]) { + const original = HttpClientRequest.post(url).pipe(HttpClientRequest.setBody(body)) + const request = yield* HttpClientRequest.compressBody(original, "gzip", { minSize: 0 }) + strictEqual(request, original) + strictEqual(request.headers["content-encoding"], undefined) + } + for (const encoding of ["identity", "deflate", "gzip"]) { + const original = HttpClientRequest.post(url).pipe( + HttpClientRequest.bodyText(text), + HttpClientRequest.setHeader("Content-Encoding", encoding) + ) + strictEqual(yield* HttpClientRequest.compressBody(original, "gzip"), original) + } + })) + + it.each([ + { name: "known length", text, contentLength: bytes.byteLength }, + { name: "unknown length below minSize", text: "tiny", contentLength: undefined } + ])("compresses a stream with $name without a content length", async ({ contentLength, text }) => { + const source = new TextEncoder().encode(text) + const original = HttpClientRequest.post(url).pipe( + HttpClientRequest.bodyStream(Stream.make(source.subarray(0, 2), source.subarray(2)), { + contentType: "text/plain", + contentLength + }) + ) + const request = await Effect.runPromise(original.pipe(HttpClientRequest.compressBody("gzip"))) + strictEqual(request.body._tag, "Stream") + strictEqual(request.headers["content-length"], undefined) + strictEqual(request.headers["content-encoding"], "gzip") + strictEqual(request.headers["content-type"], "text/plain") + if (request.body._tag === "Stream") { + strictEqual(request.body.contentLength, undefined) + const compressed = await Effect.runPromise(Stream.mkUint8Array(request.body.stream)) + strictEqual(gunzipSync(compressed).toString(), text) + } + }) + }) + describe("bodyFile", () => { const oversized = 9007199254740993n const fileSystem = (size: bigint) => @@ -217,6 +316,31 @@ describe("HttpClientRequest", () => { }) }) + describe("toJSON", () => { + it("redacts sensitive query params in url and urlParams", () => { + const request = HttpClientRequest.get("https://api.test/path?Signature=url-secret&page=1", { + urlParams: { sig: "param-secret", q: "visible" } + }) + + strictEqual((request.toJSON() as { readonly url: string }).url, "https://api.test/path?Signature=REDACTED&page=1") + const output = Formatter.format(request) + assertFalse(output.includes("url-secret")) + assertFalse(output.includes("param-secret")) + assertTrue(output.includes("visible")) + }) + + it("hides Redacted url params from inspection", () => { + const request = HttpClientRequest.get("https://api.test/path").pipe( + HttpClientRequest.setUrlParam("remote", Redacted.make("param-secret")), + HttpClientRequest.appendUrlParam("q", "visible") + ) + for (const output of [JSON.stringify(request), String(request), inspect(request)]) { + assertFalse(output.includes("param-secret")) + assertTrue(output.includes("visible")) + } + }) + }) + describe("web conversions", () => { it.effect("fromWeb", () => Effect.gen(function*() { diff --git a/repos/effect/packages/effect/test/http/HttpDecompression.test.ts b/repos/effect/packages/effect/test/http/HttpDecompression.test.ts new file mode 100644 index 0000000000..811b0f253d --- /dev/null +++ b/repos/effect/packages/effect/test/http/HttpDecompression.test.ts @@ -0,0 +1,228 @@ +import { afterAll, assert, describe, it } from "@effect/vitest" +import * as ByteSize from "effect/ByteSize" +import * as Effect from "effect/Effect" +import * as HttpEffect from "effect/http/HttpEffect" +import * as HttpIncomingMessage from "effect/http/HttpIncomingMessage" +import * as HttpMiddleware from "effect/http/HttpMiddleware" +import * as HttpRouter from "effect/http/HttpRouter" +import * as HttpServer from "effect/http/HttpServer" +import * as HttpServerRequest from "effect/http/HttpServerRequest" +import * as HttpServerResponse from "effect/http/HttpServerResponse" +import * as Layer from "effect/Layer" +import * as Stream from "effect/Stream" + +const bigJson = JSON.stringify({ text: "All work and no play makes Jack a dull boy. ".repeat(100) }) + +type Format = "gzip" | "deflate" +type DecompressionOptions = Parameters[0] + +const compress = async (data: string | Uint8Array, formats: ReadonlyArray): Promise => { + let body = new Blob([data as BlobPart]).stream() + for (const format of formats) { + body = body.pipeThrough(new CompressionStream(format)) + } + return new Uint8Array(await new Response(body).arrayBuffer()) +} + +const post = ( + handler: (request: Request) => Promise, + body: Uint8Array | string, + headers?: Record, + path = "/" +) => + handler( + new Request(`http://localhost${path}`, { + method: "POST", + body: body as BodyInit, + ...(headers === undefined ? {} : { headers }) + }) + ) + +const readers = { + json: (request: HttpServerRequest.HttpServerRequest) => Effect.map(request.json, (json) => JSON.stringify(json)), + text: (request: HttpServerRequest.HttpServerRequest) => request.text, + arrayBuffer: (request: HttpServerRequest.HttpServerRequest) => + Effect.map(request.arrayBuffer, (buffer) => new TextDecoder().decode(buffer)), + stream: (request: HttpServerRequest.HttpServerRequest) => + Effect.map(Stream.mkUint8Array(request.stream), (bytes) => new TextDecoder().decode(bytes)) +} as const + +type Accessor = keyof typeof readers + +// Echoes the body read through `accessor`, along with the request's +// Content-Encoding and Content-Length as the app sees them. +const echo = (accessor: Accessor) => (request: HttpServerRequest.HttpServerRequest) => + Effect.map(readers[accessor](request), (body) => + HttpServerResponse.text(body, { + headers: { + "x-content-encoding": request.headers["content-encoding"] ?? "", + "x-content-length": request.headers["content-length"] ?? "" + } + })) + +const echoApp = (accessor: Accessor) => HttpServerRequest.HttpServerRequest.use(echo(accessor)) + +const disposers: Array<() => Promise> = [] + +afterAll(() => Promise.all(disposers.map((dispose) => dispose()))) + +const makeHandler = ( + app: Effect.Effect, + options?: DecompressionOptions, + maxBodySize?: ByteSize.ByteSize +) => { + const { dispose, handler } = HttpEffect.toWebHandlerLayer( + app, + Layer.merge(HttpServer.layerServices, Layer.succeed(HttpIncomingMessage.MaxBodySize, maxBodySize)), + { middleware: HttpMiddleware.decompression(options) } + ) + disposers.push(dispose) + return handler +} + +describe("HttpDecompression", () => { + for (const accessor of ["json", "text", "arrayBuffer", "stream"] as const) { + it(`decompresses a gzip body read via ${accessor} and hides the encoding headers`, async () => { + const response = await post( + makeHandler(echoApp(accessor)), + await compress(bigJson, ["gzip"]), + { "content-type": "application/json", "content-encoding": "gzip" } + ) + assert.strictEqual(response.status, 200) + assert.strictEqual(await response.text(), bigJson) + assert.strictEqual(response.headers.get("x-content-encoding"), "") + assert.strictEqual(response.headers.get("x-content-length"), "") + }) + } + + for (const formats of [["deflate"], ["deflate", "gzip"]] as const) { + it(`decodes Content-Encoding: ${formats.join(", ")}`, async () => { + const response = await post( + makeHandler(echoApp("text")), + await compress(bigJson, formats), + { "content-encoding": formats.join(", ") } + ) + assert.strictEqual(response.status, 200) + assert.strictEqual(await response.text(), bigJson) + }) + } + + it("passes through bodies without a coding or with identity", async () => { + const handler = makeHandler(echoApp("text")) + + const plain = await post(handler, bigJson) + assert.strictEqual(plain.status, 200) + assert.strictEqual(await plain.text(), bigJson) + + const identity = await post(handler, bigJson, { "content-encoding": "identity" }) + assert.strictEqual(identity.status, 200) + assert.strictEqual(await identity.text(), bigJson) + }) + + it("rejects unsupported codings with 415 before running the app", async () => { + let ran = false + const app = Effect.sync(() => { + ran = true + return HttpServerResponse.empty() + }) + const response = await post(makeHandler(app), bigJson, { "content-encoding": "br" }) + assert.strictEqual(response.status, 415) + assert.strictEqual(response.headers.get("accept-encoding"), "gzip, deflate") + assert.isFalse(ran) + }) + + it("fails corrupt gzip bodies with 400", async () => { + const response = await post(makeHandler(echoApp("text")), "not gzip", { "content-encoding": "gzip" }) + assert.strictEqual(response.status, 400) + }) + + for (const accessor of ["text", "stream"] as const) { + it(`enforces maxDecompressedSize when reading via ${accessor}`, async () => { + const body = await compress(bigJson, ["gzip"]) + // the limit must apply to the inflated size, not the size on the wire + assert.isBelow(body.length, 1024) + const response = await post( + makeHandler(echoApp(accessor), { maxDecompressedSize: 1024 }), + body, + { "content-encoding": "gzip" } + ) + assert.strictEqual(response.status, 400) + }) + } + + it("falls back to the MaxBodySize reference", async () => { + const response = await post( + makeHandler( + echoApp("text"), + undefined, + ByteSize.bytes(1024) + ), + await compress(bigJson, ["gzip"]), + { "content-encoding": "gzip" } + ) + assert.strictEqual(response.status, 400) + }) + + it("maps multipart decompression failures to client errors", async () => { + const multipart = new FormData() + multipart.append("text", bigJson) + const encoded = new Response(multipart) + const headers = { "content-type": encoded.headers.get("content-type")!, "content-encoding": "gzip" } + const body = new Uint8Array(await encoded.arrayBuffer()) + const handler = makeHandler( + HttpServerRequest.HttpServerRequest.use((request) => + Effect.as(Stream.runDrain(request.multipartStream), HttpServerResponse.empty()) + ), + { maxDecompressedSize: 1024 } + ) + + const corrupt = await post(handler, "not gzip", headers) + assert.strictEqual(corrupt.status, 400) + + const tooLarge = await post(handler, await compress(body, ["gzip"]), headers) + assert.strictEqual(tooLarge.status, 413) + }) + + it("cancels the request body when a stream read stops early", async () => { + const compressed = await compress(bigJson, ["gzip"]) + let onCancel!: () => void + const cancelled = new Promise((resolve) => { + onCancel = resolve + }) + // never closes, so the upstream only finishes if cancellation propagates + const body = new ReadableStream({ + start(controller) { + controller.enqueue(compressed) + }, + cancel() { + onCancel() + } + }) + const handler = makeHandler( + HttpServerRequest.HttpServerRequest.use((request) => + Effect.as(Stream.runHead(request.stream), HttpServerResponse.empty()) + ) + ) + const response = await handler( + new Request("http://localhost/", { + method: "POST", + body, + headers: { "content-encoding": "gzip" }, + duplex: "half" + } as RequestInit) + ) + assert.strictEqual(response.status, 204) + await cancelled + }) + + it("decompresses bodies for routes under a prefixed router", async () => { + const { dispose, handler } = HttpRouter.toWebHandler( + HttpRouter.use((router) => router.prefixed("/api").add("POST", "/echo", echo("text"))), + { middleware: HttpMiddleware.decompression(), disableLogger: true } + ) + disposers.push(dispose) + const response = await post(handler, await compress(bigJson, ["gzip"]), { "content-encoding": "gzip" }, "/api/echo") + assert.strictEqual(response.status, 200) + assert.strictEqual(await response.text(), bigJson) + }) +}) diff --git a/repos/effect/packages/effect/test/http/HttpEffect.test.ts b/repos/effect/packages/effect/test/http/HttpEffect.test.ts index c1aa0bfe0a..96f6ea6139 100644 --- a/repos/effect/packages/effect/test/http/HttpEffect.test.ts +++ b/repos/effect/packages/effect/test/http/HttpEffect.test.ts @@ -160,6 +160,75 @@ describe("HttpEffect", () => { strictEqual(response.headers.get("content-length"), "9007199254740993") }) + test.each(["before the request", "while the handler starts"] as const)( + "an abort %s interrupts the handler as a client abort", + async (when) => { + const controller = new AbortController() + if (when === "before the request") controller.abort() + let interrupted = false + const handler = HttpEffect.toWebHandler( + Effect.sync(() => { + if (when === "while the handler starts") controller.abort() + }).pipe( + Effect.andThen(Effect.never), + Effect.onInterrupt(() => + Effect.sync(() => { + interrupted = true + }) + ), + // Handlers are uninterruptible unless they opt in, as router routes do. + Effect.interruptible + ) + ) + const response = await handler(new Request("http://localhost:3000/", { signal: controller.signal })) + strictEqual(response.status, 499) + strictEqual(interrupted, true) + } + ) + + test.each(["after reading a chunk", "while the unread body is full"] as const)( + "an abort %s releases the request scope owned by a streamed body", + async (when) => { + const controller = new AbortController() + let finalized = false + let pulledSecond = false + const handler = HttpEffect.toWebHandler(Effect.gen(function*() { + yield* Effect.addFinalizer(() => + Effect.sync(() => { + finalized = true + }) + ) + return HttpServerResponse.stream( + Stream.make("first").pipe( + Stream.concat(Stream.fromEffect(Effect.sync(() => { + pulledSecond = true + return "second" + }))), + Stream.concat(Stream.never), + Stream.encodeText + ) + ) + })) + const waitFor = (predicate: () => boolean) => + new Promise((resolve) => { + const deadline = Date.now() + 1000 + const poll = () => predicate() || Date.now() > deadline ? resolve() : setImmediate(poll) + poll() + }) + const response = await handler(new Request("http://localhost:3000/", { signal: controller.signal })) + if (when === "after reading a chunk") { + await response.body!.getReader().read() + } else { + // The body has taken its second chunk and now waits for a read that never comes. + await waitFor(() => pulledSecond) + } + + controller.abort() + await waitFor(() => finalized) + strictEqual(finalized, true) + } + ) + test("stream scope", async () => { let order = 0 let streamFinalized = 0 diff --git a/repos/effect/packages/effect/test/http/HttpMiddleware.test.ts b/repos/effect/packages/effect/test/http/HttpMiddleware.test.ts index 9d042244ba..3355593ff4 100644 --- a/repos/effect/packages/effect/test/http/HttpMiddleware.test.ts +++ b/repos/effect/packages/effect/test/http/HttpMiddleware.test.ts @@ -357,6 +357,35 @@ describe("HttpMiddleware", () => { assert.strictEqual(serverSpan.attributes.get("http.response.header.x-response-secret"), undefined) })) + it.effect("redacts sensitive query params in url attributes", () => + Effect.gen(function*() { + let serverSpan: Tracer.NativeSpan | undefined + let handlerUrl: string | undefined + const tracer = Tracer.make({ + span(options) { + serverSpan = new Tracer.NativeSpan(options) + return serverSpan + } + }) + const request = HttpServerRequest.fromWeb( + new Request("http://localhost/todos?sig=sig-secret&foo=bar") + ) + + yield* HttpMiddleware.tracer(Effect.gen(function*() { + handlerUrl = (yield* HttpServerRequest.HttpServerRequest).url + return HttpServerResponse.empty() + })).pipe( + Effect.provideService(HttpServerRequest.HttpServerRequest, request), + Effect.provideService(Tracer.Tracer, tracer) + ) + yield* Effect.yieldNow + + assert(serverSpan !== undefined) + assert.strictEqual(serverSpan.attributes.get("url.full"), "http://localhost/todos?sig=REDACTED&foo=bar") + assert.strictEqual(serverSpan.attributes.get("url.query"), "sig=REDACTED&foo=bar") + assert.strictEqual(handlerUrl, "/todos?sig=sig-secret&foo=bar") + })) + it.effect("skips attributes for unsampled spans", () => Effect.gen(function*() { let serverSpan: Tracer.NativeSpan | undefined diff --git a/repos/effect/packages/effect/test/http/HttpRouter.test.ts b/repos/effect/packages/effect/test/http/HttpRouter.test.ts index 39ffdd002c..816c357385 100644 --- a/repos/effect/packages/effect/test/http/HttpRouter.test.ts +++ b/repos/effect/packages/effect/test/http/HttpRouter.test.ts @@ -64,6 +64,38 @@ describe("HttpRouter", () => { })) } + for ( + const { prefix, requestUrl, expected } of [ + { prefix: "/tenants/:tenant", requestUrl: "/tenants/a/users?x=1", expected: "/users?x=1" }, + { prefix: "/tenants/:tenant([^/]+)", requestUrl: "/tenants/acme/users?x=1", expected: "/users?x=1" }, + { prefix: "/café", requestUrl: "/caf%C3%A9/users", expected: "/users" } + ] + ) { + it.effect(`removes the matched ${prefix} prefix from ${requestUrl}`, () => + Effect.gen(function*() { + const routes = HttpRouter.use((router) => router.prefixed(prefix).add("GET", "/users", echoUrl)) + + const body = yield* fetchText(routes, requestUrl) + + assert.strictEqual(body, expected) + })) + } + + for (const ignoreDuplicateSlashes of [true, false]) { + it.effect(`preserves the local URL with ignoreDuplicateSlashes=${ignoreDuplicateSlashes}`, () => + Effect.gen(function*() { + const routes = HttpRouter.use((router) => router.prefixed("/api//v1").add("GET", "/users", echoUrl)).pipe( + Layer.provide( + Layer.succeed(HttpRouter.RouterConfig)(ignoreDuplicateSlashes ? {} : { ignoreDuplicateSlashes }) + ) + ) + + const body = yield* fetchText(routes, ignoreDuplicateSlashes ? "/api/v1/users?x=1" : "/api//v1/users?x=1") + + assert.strictEqual(body, "/users?x=1") + })) + } + it.effect("nests a prefixed sub-router beneath a prefixed parent router", () => Effect.gen(function*() { const routes = HttpRouter.use((router) => router.prefixed("/app").add("GET", "/users", echoUrl)).pipe( diff --git a/repos/effect/packages/effect/test/http/HttpServerError.test.ts b/repos/effect/packages/effect/test/http/HttpServerError.test.ts index 16cdb6c104..3264e9631d 100644 --- a/repos/effect/packages/effect/test/http/HttpServerError.test.ts +++ b/repos/effect/packages/effect/test/http/HttpServerError.test.ts @@ -14,6 +14,7 @@ import { import * as HttpServerRequest from "effect/http/HttpServerRequest" import * as Respondable from "effect/http/HttpServerRespondable" import * as HttpServerResponse from "effect/http/HttpServerResponse" +import * as UrlParams from "effect/http/UrlParams" const makeRequest = (method: string, url: string) => HttpServerRequest.fromWeb(new Request(url, { method })) const makeResponse = (status: number) => HttpServerResponse.empty({ status }) @@ -32,6 +33,16 @@ describe("HttpServerError", () => { assert.strictEqual(routeNotFound.message, "RouteNotFound (POST /widgets)") }) + it.effect("redacts query params using the current redacted names", () => + Effect.gen(function*() { + const request = makeRequest("GET", "http://example.com/widgets?token=token-secret&sig=sig-visible") + + assert.strictEqual( + new RouteNotFound({ request }).message, + "RouteNotFound (GET /widgets?token=REDACTED&sig=sig-visible)" + ) + }).pipe(Effect.provideService(UrlParams.CurrentRedactedNames, ["token"]))) + it("formats response reason messages", () => { const request = makeRequest("GET", "http://example.com/tea") const response = makeResponse(418) diff --git a/repos/effect/packages/effect/test/http/HttpServerResponse.test.ts b/repos/effect/packages/effect/test/http/HttpServerResponse.test.ts index c86e904661..84ff55f17a 100644 --- a/repos/effect/packages/effect/test/http/HttpServerResponse.test.ts +++ b/repos/effect/packages/effect/test/http/HttpServerResponse.test.ts @@ -4,6 +4,18 @@ import { Cookies, HttpBody, HttpClientRequest, HttpClientResponse, HttpServerRes const TestValue = Context.Reference("test/TestValue", { defaultValue: () => 0 }) +// Bun leaves `Response.redirect` headers mutable, unlike Node, Deno and workerd +const immutableHeaders = (response: Response): Response => { + for (const method of ["append", "set"]) { + Object.defineProperty(response.headers, method, { + value: () => { + throw new TypeError("immutable") + } + }) + } + return response +} + describe("HttpServerResponse", () => { describe("toWeb", () => { it.each([ @@ -44,13 +56,22 @@ describe("HttpServerResponse", () => { ) it("preserves raw Response metadata for HEAD", () => { - const native = new Response("body", { - status: 202, - statusText: "Accepted by upstream", - headers: { "x-probe": "native", "set-cookie": "sid=abc" } - }) + const native = immutableHeaders( + new Response("body", { + status: 202, + statusText: "Accepted by upstream", + headers: { "x-probe": "native", "x-shared": "native", "set-cookie": "sid=abc" } + }) + ) + // A locked body fails the test if HEAD copies the response + native.body!.getReader() const web = HttpServerResponse.toWeb( - HttpServerResponse.raw(native, { status: 200, statusText: "Outer status" }), + HttpServerResponse.raw(native, { + status: 200, + statusText: "Outer status", + headers: { "x-shared": "outer" }, + cookies: Cookies.setAllUnsafe(Cookies.empty, [["a", "1", {}]]) + }), { withoutBody: true } ) @@ -58,10 +79,11 @@ describe("HttpServerResponse", () => { assert.strictEqual(web.status, 202) assert.strictEqual(web.statusText, "Accepted by upstream") assert.strictEqual(web.headers.get("x-probe"), "native") - assert.deepStrictEqual(web.headers.getSetCookie(), ["sid=abc"]) + assert.strictEqual(web.headers.get("x-shared"), "outer") + assert.deepStrictEqual(web.headers.getSetCookie(), ["sid=abc", "a=1"]) }) - it("returns the raw Response with merged headers for GET", async () => { + it("merges headers for GET without modifying the raw Response", async () => { const native = new Response("body", { status: 202, statusText: "Accepted by upstream", @@ -74,16 +96,34 @@ describe("HttpServerResponse", () => { }) ) - assert.strictEqual(web, native) assert.strictEqual(web.status, 202) assert.strictEqual(web.statusText, "Accepted by upstream") assert.strictEqual(web.headers.get("x-probe"), "native") assert.strictEqual(web.headers.get("x-outer"), "outer") assert.strictEqual(web.headers.get("x-shared"), "outer") assert.deepStrictEqual(web.headers.getSetCookie(), ["sid=abc; Path=/; HttpOnly", "a=1", "b=2"]) + assert.strictEqual(native.headers.get("x-probe"), "native") + assert.strictEqual(native.headers.get("x-outer"), null) + assert.strictEqual(native.headers.get("x-shared"), "native") + assert.deepStrictEqual(native.headers.getSetCookie(), ["sid=abc; Path=/; HttpOnly"]) assert.strictEqual(await web.text(), "body") }) + it("merges outer headers into a raw Response with immutable headers", () => { + const native = immutableHeaders(Response.redirect("http://localhost/target", 302)) + const web = HttpServerResponse.toWeb( + HttpServerResponse.raw(native, { + headers: { "x-outer": "outer" }, + cookies: Cookies.setAllUnsafe(Cookies.empty, [["a", "1", {}]]) + }) + ) + + assert.strictEqual(web.status, 302) + assert.strictEqual(web.headers.get("location"), "http://localhost/target") + assert.strictEqual(web.headers.get("x-outer"), "outer") + assert.deepStrictEqual(web.headers.getSetCookie(), ["a=1"]) + }) + it.each([ { status: 200, withoutBody: true }, { status: 304, withoutBody: false } diff --git a/repos/effect/packages/effect/test/http/HttpStaticServer.test.ts b/repos/effect/packages/effect/test/http/HttpStaticServer.test.ts index 4ab34911bb..af96f607cf 100644 --- a/repos/effect/packages/effect/test/http/HttpStaticServer.test.ts +++ b/repos/effect/packages/effect/test/http/HttpStaticServer.test.ts @@ -136,3 +136,18 @@ describe("HttpStaticServer precision", () => { }).pipe(Effect.provide(precisionServices(size, calls))) }) }) + +describe("HttpStaticServer paths", () => { + it.effect("serves a path with repeated leading slashes from the root", () => { + const calls: Array<{ path: string; options: FileOptions }> = [] + return Effect.gen(function*() { + const app = yield* HttpStaticServer.make({ root: "/root" }) + const response = yield* app.pipe(Effect.provideService( + HttpServerRequest.HttpServerRequest, + HttpServerRequest.fromWeb(new Request("http://localhost//nested/file.txt")) + )) + assert.strictEqual(response.status, 200) + assert.deepStrictEqual(calls.map((call) => call.path), ["/root/nested/file.txt"]) + }).pipe(Effect.provide(precisionServices(10n, calls))) + }) +}) diff --git a/repos/effect/packages/effect/test/http/HttpTraceContext.test.ts b/repos/effect/packages/effect/test/http/HttpTraceContext.test.ts index 918a96a9eb..f0376cde07 100644 --- a/repos/effect/packages/effect/test/http/HttpTraceContext.test.ts +++ b/repos/effect/packages/effect/test/http/HttpTraceContext.test.ts @@ -1,6 +1,6 @@ import { describe, it } from "@effect/vitest" -import { strictEqual } from "@effect/vitest/utils" -import { Option } from "effect" +import { assertNone, strictEqual } from "@effect/vitest/utils" +import { Effect, Option, Tracer } from "effect" import { Headers, HttpTraceContext } from "effect/http" const traceId = "80f198ee56343ba864fe8b2a57d3eff7" @@ -32,6 +32,28 @@ describe("HttpTraceContext", () => { }, true) }) + it.each([ + { b3: `${traceId.slice(16)}-${spanId}-1` }, + { "X-B3-TraceId": traceId.slice(16), "X-B3-SpanId": spanId } + ])("accepts a 64-bit B3 trace-id: %j", (headers) => { + const span = Option.getOrThrow(HttpTraceContext.fromHeaders(Headers.fromInput(headers))) + strictEqual(span.traceId, traceId.slice(16)) + strictEqual(span.spanId, spanId) + }) + + it.each([ + { b3: `