@effect-uai/responses 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/OpenAIDeepResearch.d.mts +54 -0
  2. package/dist/OpenAIDeepResearch.d.mts.map +1 -0
  3. package/dist/OpenAIDeepResearch.mjs +121 -0
  4. package/dist/OpenAIDeepResearch.mjs.map +1 -0
  5. package/dist/OpenAIEmbedding.mjs +1 -1
  6. package/dist/OpenAIEmbedding.mjs.map +1 -1
  7. package/dist/Responses.d.mts +33 -3
  8. package/dist/Responses.d.mts.map +1 -1
  9. package/dist/Responses.mjs +71 -34
  10. package/dist/Responses.mjs.map +1 -1
  11. package/dist/ResponsesTools.d.mts +85 -0
  12. package/dist/ResponsesTools.d.mts.map +1 -0
  13. package/dist/ResponsesTools.mjs +126 -0
  14. package/dist/ResponsesTools.mjs.map +1 -0
  15. package/dist/codec.d.mts +42 -3
  16. package/dist/codec.d.mts.map +1 -1
  17. package/dist/codec.mjs +58 -17
  18. package/dist/codec.mjs.map +1 -1
  19. package/dist/codec.test.d.mts +1 -0
  20. package/dist/codec.test.mjs +93 -0
  21. package/dist/codec.test.mjs.map +1 -0
  22. package/dist/index.d.mts +5 -3
  23. package/dist/index.mjs +5 -3
  24. package/dist/{magic-string.es-PAZgLX4h.mjs → magic-string.es-CaWgF-3p.mjs} +1 -1
  25. package/dist/{magic-string.es-PAZgLX4h.mjs.map → magic-string.es-CaWgF-3p.mjs.map} +1 -1
  26. package/dist/models.d.mts +10 -1
  27. package/dist/models.d.mts.map +1 -1
  28. package/dist/region.test.mjs +1 -13630
  29. package/dist/region.test.mjs.map +1 -1
  30. package/dist/responsesTools.test.d.mts +1 -0
  31. package/dist/responsesTools.test.mjs +138 -0
  32. package/dist/responsesTools.test.mjs.map +1 -0
  33. package/dist/streamEvents.d.mts +142 -0
  34. package/dist/streamEvents.d.mts.map +1 -1
  35. package/dist/streamEvents.mjs +27 -2
  36. package/dist/streamEvents.mjs.map +1 -1
  37. package/dist/test.DNmyFkvJ-CPKukVWS.mjs +13633 -0
  38. package/dist/test.DNmyFkvJ-CPKukVWS.mjs.map +1 -0
  39. package/package.json +12 -4
  40. package/src/OpenAIDeepResearch.ts +266 -0
  41. package/src/OpenAIEmbedding.ts +1 -1
  42. package/src/Responses.ts +117 -36
  43. package/src/ResponsesTools.ts +158 -0
  44. package/src/codec.test.ts +87 -0
  45. package/src/codec.ts +92 -36
  46. package/src/index.ts +2 -0
  47. package/src/models.ts +14 -0
  48. package/src/responsesTools.test.ts +146 -0
  49. package/src/streamEvents.ts +58 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Responses.mjs","names":[],"sources":["../src/Responses.ts"],"sourcesContent":["import { Context, Effect, Layer, Match, Option, Redacted, Schema, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport * as StructuredFormat from \"@effect-uai/core/StructuredFormat\"\nimport {\n type CommonRequest,\n LanguageModel,\n type LanguageModelService,\n turnFromStream,\n} from \"@effect-uai/core/LanguageModel\"\nimport * as SSE from \"@effect-uai/core/SSE\"\nimport { descriptorsOf } from \"@effect-uai/core/Tool\"\nimport type { Turn, TurnEvent } from \"@effect-uai/core/Turn\"\nimport { itemsToInput } from \"./codec.js\"\nimport type { OpenAIModel } from \"./models.js\"\nimport { type OpenAiRegion, resolveHost } from \"./region.js\"\nimport {\n KnownProviderEvent,\n ProviderEvent,\n eventToDeltas,\n makeCallIdLookup,\n} from \"./streamEvents.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type ResponsesRequest = Omit<CommonRequest, \"model\"> & {\n /**\n * Narrows `CommonRequest.model` (`string`) to the typed `OpenAIModel`\n * literal union for autocomplete.\n */\n readonly model: OpenAIModel\n readonly reasoning?: { readonly effort: \"low\" | \"medium\" | \"high\" }\n readonly store?: boolean\n readonly previousResponseId?: string\n readonly instructions?: string\n readonly parallelToolCalls?: boolean\n readonly metadata?: Readonly<Record<string, string>>\n readonly user?: string\n readonly safetyIdentifier?: string\n readonly promptCacheKey?: string\n readonly truncation?: \"auto\" | \"disabled\"\n /**\n * Free-form JSON output: model emits valid JSON without schema\n * constraints. Mutually exclusive with `structured` (schema wins if\n * both are set).\n */\n readonly responseFormat?: { readonly type: \"json_object\" }\n /**\n * Answer length / level-of-detail hint. GPT-5+ models honour it;\n * earlier models ignore.\n */\n readonly verbosity?: \"low\" | \"medium\" | \"high\"\n}\n\nexport type ResponsesService = {\n /**\n * Stream the provider's native event vocabulary (post-SSE-decode).\n * Use this when you need full vendor fidelity. For provider-portable\n * code, use `streamTurn` instead.\n */\n readonly streamNative: (\n request: ResponsesRequest,\n ) => Stream.Stream<ProviderEvent, AiError.AiError>\n /**\n * Stream canonical `TurnEvent`s. Implemented as\n * `streamNative |> toCanonical`.\n */\n readonly streamTurn: (request: ResponsesRequest) => Stream.Stream<TurnEvent, AiError.AiError>\n /**\n * Drain a single turn and return the assembled `Turn`. Derived from\n * `streamTurn` — Responses doesn't expose a native non-streaming\n * complete endpoint we'd want to take advantage of.\n */\n readonly turn: (request: ResponsesRequest) => Effect.Effect<Turn, AiError.AiError>\n /**\n * Project a stream of native `ProviderEvent`s into canonical `TurnEvent`s.\n * Exposed for cases where consumers want to compose with `streamNative`\n * directly (e.g. tap into natives + still get canonical downstream).\n */\n readonly toCanonical: <E, R>(\n s: Stream.Stream<ProviderEvent, E, R>,\n ) => Stream.Stream<TurnEvent, E, R>\n}\n\n/**\n * Provider-typed service tag. Yield this when you want Responses-specific\n * options (`reasoning.effort`, `store`, `previousResponseId`) at the call\n * site. Yield the generic `LanguageModel` tag for provider-portable code -\n * both are registered by `layer`.\n */\nexport class Responses extends Context.Service<Responses, ResponsesService>()(\n \"@betalyra/effect-uai/providers/responses/Responses\",\n) {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n readonly region?: OpenAiRegion\n}\n\n// ---------------------------------------------------------------------------\n// Request body\n// ---------------------------------------------------------------------------\n\nconst jsonSchemaFormat = (\n format: StructuredFormat.StructuredFormat<unknown>,\n): Record<string, unknown> => ({\n type: \"json_schema\",\n name: format.name,\n schema: format.schema[\"~standard\"].jsonSchema.input({ target: \"draft-2020-12\" }),\n ...(format.description !== undefined && { description: format.description }),\n ...(format.strict !== undefined && { strict: format.strict }),\n})\n\nconst buildText = (request: ResponsesRequest): Record<string, unknown> | undefined => {\n const format =\n request.structured !== undefined ? jsonSchemaFormat(request.structured) : request.responseFormat\n const text: Record<string, unknown> = {}\n if (format !== undefined) text.format = format\n if (request.verbosity !== undefined) text.verbosity = request.verbosity\n return Object.keys(text).length === 0 ? undefined : text\n}\n\nconst buildBody = (request: ResponsesRequest): Record<string, unknown> => {\n const text = buildText(request)\n const tools = descriptorsOf(request.tools)\n return {\n model: request.model,\n input: itemsToInput(request.history),\n stream: true,\n ...(tools.length > 0 && {\n tools: tools.map((t) => ({\n type: \"function\",\n name: t.name,\n description: t.description,\n parameters: t.inputSchema,\n ...(t.strict !== undefined && { strict: t.strict }),\n })),\n }),\n ...(request.toolChoice !== undefined && { tool_choice: request.toolChoice }),\n ...(request.temperature !== undefined && { temperature: request.temperature }),\n ...(request.maxOutputTokens !== undefined && {\n max_output_tokens: request.maxOutputTokens,\n }),\n ...(request.reasoning !== undefined && { reasoning: request.reasoning }),\n ...(request.store !== undefined && { store: request.store }),\n ...(request.previousResponseId !== undefined && {\n previous_response_id: request.previousResponseId,\n }),\n ...(request.instructions !== undefined && { instructions: request.instructions }),\n ...(request.topP !== undefined && { top_p: request.topP }),\n ...(request.parallelToolCalls !== undefined && {\n parallel_tool_calls: request.parallelToolCalls,\n }),\n ...(request.metadata !== undefined && { metadata: request.metadata }),\n ...(request.user !== undefined && { user: request.user }),\n ...(request.safetyIdentifier !== undefined && {\n safety_identifier: request.safetyIdentifier,\n }),\n ...(request.promptCacheKey !== undefined && {\n prompt_cache_key: request.promptCacheKey,\n }),\n ...(request.truncation !== undefined && { truncation: request.truncation }),\n ...(text !== undefined && { text }),\n }\n}\n\n// ---------------------------------------------------------------------------\n// SSE event → provider event\n// ---------------------------------------------------------------------------\n\nconst decodeKnown = Schema.decodeUnknownEffect(KnownProviderEvent)\n\nconst makeUnknown = (raw: unknown): ProviderEvent => ({ type: \"_unknown\", raw })\n\n/**\n * Lift events that carry a terminal failure signal (`error`,\n * `response.failed`) to a typed `AiError`. Other events are not failures\n * and produce `Option.none`.\n */\nconst eventToError = Match.type<ProviderEvent>().pipe(\n Match.discriminators(\"type\")({\n error: (e): AiError.AiError => new AiError.Unavailable({ provider: \"responses\", raw: e }),\n \"response.failed\": (e): AiError.AiError => {\n const code = e.response.error?.code\n const message = e.response.error?.message\n return new AiError.GenerationFailed({\n provider: \"responses\",\n ...(code !== undefined && code !== null && { code }),\n ...(message !== undefined && message !== null && { message }),\n raw: e,\n })\n },\n }),\n Match.option,\n)\n\nconst parseJsonUnknown = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))\n\nconst sseEventToProviderEvent = (ev: SSE.Event): Effect.Effect<ProviderEvent> =>\n parseJsonUnknown(ev.data).pipe(\n Effect.flatMap((parsed) =>\n decodeKnown(parsed).pipe(Effect.orElseSucceed(() => makeUnknown(parsed))),\n ),\n Effect.orElseSucceed(() => makeUnknown(ev.data)),\n )\n\n// ---------------------------------------------------------------------------\n// Service implementation\n// ---------------------------------------------------------------------------\n\nconst httpStatusError = (status: number, body: string): AiError.AiError => {\n const provider = \"responses\"\n const raw = body\n if (status === 429) return new AiError.RateLimited({ provider, raw })\n if (status === 408 || status === 504) return new AiError.Timeout({ provider, raw })\n if (status === 401) return new AiError.AuthFailed({ provider, subtype: \"auth\", raw })\n if (status === 403) return new AiError.AuthFailed({ provider, subtype: \"permission\", raw })\n if (status === 402) return new AiError.AuthFailed({ provider, subtype: \"billing\", raw })\n if (status === 413) return new AiError.ContextLengthExceeded({ provider, raw })\n if (status >= 500) return new AiError.Unavailable({ provider, status, raw })\n return new AiError.InvalidRequest({ provider, raw })\n}\n\nconst buildNativeStream = (cfg: Config) => {\n const url = `${resolveHost(cfg)}/responses`\n return (\n request: ResponsesRequest,\n ): Stream.Stream<ProviderEvent, AiError.AiError, HttpClient.HttpClient> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.bearerToken(cfg.apiKey),\n HttpClientRequest.bodyJsonUnsafe(buildBody(request)),\n HttpClientRequest.accept(\"text/event-stream\"),\n )\n const response = yield* client\n .execute(httpRequest)\n .pipe(\n Effect.mapError(\n (cause) => new AiError.Unavailable({ provider: \"responses\", raw: cause }),\n ),\n )\n if (response.status >= 400) {\n const body = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(httpStatusError(response.status, body))\n }\n\n return response.stream.pipe(\n Stream.mapError(\n (cause) => new AiError.Unavailable({ provider: \"responses\", raw: cause }),\n ),\n SSE.fromBytes,\n Stream.mapEffect(sseEventToProviderEvent),\n Stream.flatMap((event) =>\n Option.match(eventToError(event), {\n onNone: () => Stream.succeed(event),\n onSome: Stream.fail,\n }),\n ),\n )\n }),\n )\n}\n\n/**\n * Project a stream of native `ProviderEvent`s into canonical `TurnEvent`s.\n * Threads a fresh `CallIdLookup` per stream so `function_call_arguments.delta`\n * can be tagged with the right `call_id`.\n */\nexport const toCanonical = <E, R>(\n s: Stream.Stream<ProviderEvent, E, R>,\n): Stream.Stream<TurnEvent, E, R> =>\n Stream.unwrap(\n Effect.sync(() => {\n const lookup = makeCallIdLookup()\n return s.pipe(Stream.flatMap((event) => Stream.fromIterable(eventToDeltas(event, lookup))))\n }),\n )\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\n/**\n * Build a `ResponsesService` value. For Layer-based setup, prefer `layer`.\n */\nexport const make = (cfg: Config): Effect.Effect<ResponsesService, never, HttpClient.HttpClient> =>\n Effect.map(HttpClient.HttpClient.asEffect(), (client) => {\n const streamNative: ResponsesService[\"streamNative\"] = (request) =>\n buildNativeStream(cfg)(request).pipe(Stream.provideService(HttpClient.HttpClient, client))\n const streamTurn: ResponsesService[\"streamTurn\"] = (request) =>\n toCanonical(streamNative(request))\n return {\n streamNative,\n streamTurn,\n turn: turnFromStream(streamTurn),\n toCanonical,\n }\n })\n\n/**\n * Layer that registers both the provider-specific `Responses` tag and the\n * generic `LanguageModel` tag, sharing one underlying implementation.\n *\n * The generic tag accepts `CommonRequest`; the typed tag accepts the full\n * `ResponsesRequest` surface.\n */\nexport const layer = (\n cfg: Config,\n): Layer.Layer<Responses | LanguageModel, never, HttpClient.HttpClient> => {\n const typed = Layer.effect(Responses, make(cfg))\n const generic = Layer.effect(\n LanguageModel,\n Effect.map(\n make(cfg),\n (s): LanguageModelService => ({\n streamTurn: (request) => s.streamTurn(request as ResponsesRequest),\n turn: (request) => s.turn(request as ResponsesRequest),\n }),\n ),\n )\n return Layer.merge(typed, generic)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Responses.mjs","names":[],"sources":["../src/Responses.ts"],"sourcesContent":["import { Context, Effect, Layer, Match, Option, Redacted, Result, Schema, Stream } from \"effect\"\nimport { HttpClient, HttpClientRequest, HttpClientResponse } from \"effect/unstable/http\"\nimport * as AiError from \"@effect-uai/core/AiError\"\nimport * as StructuredFormat from \"@effect-uai/core/StructuredFormat\"\nimport {\n type CommonRequest,\n LanguageModel,\n type LanguageModelService,\n turnFromStream,\n} from \"@effect-uai/core/LanguageModel\"\nimport * as SSE from \"@effect-uai/core/SSE\"\nimport { descriptorsOf, providerToolsOf } from \"@effect-uai/core/Tool\"\nimport type { Turn, TurnEvent } from \"@effect-uai/core/Turn\"\nimport { itemsToInput } from \"./codec.js\"\nimport { renderProviderTools } from \"./ResponsesTools.js\"\n\nexport {\n codeInterpreterTool,\n fileSearchTool,\n webSearchTool,\n type WebSearchOptions,\n type WebSearchFilters,\n type UserLocation,\n} from \"./ResponsesTools.js\"\nimport type { OpenAIModel } from \"./models.js\"\nimport { type OpenAiRegion, resolveHost } from \"./region.js\"\nimport {\n KnownProviderEvent,\n ProviderEvent,\n eventToDeltas,\n makeCallIdLookup,\n} from \"./streamEvents.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type ResponsesRequest = Omit<CommonRequest, \"model\"> & {\n /**\n * Narrows `CommonRequest.model` (`string`) to the typed `OpenAIModel`\n * literal union for autocomplete.\n */\n readonly model: OpenAIModel\n readonly reasoning?: { readonly effort: \"low\" | \"medium\" | \"high\" }\n readonly store?: boolean\n readonly previousResponseId?: string\n readonly instructions?: string\n readonly parallelToolCalls?: boolean\n readonly metadata?: Readonly<Record<string, string>>\n readonly user?: string\n readonly safetyIdentifier?: string\n readonly promptCacheKey?: string\n readonly truncation?: \"auto\" | \"disabled\"\n /**\n * Vendor-specific body fields merged into the request as-is.\n *\n * The Responses dialect is spoken by gateways as well as by OpenAI, and a\n * gateway carries its own parameters — Requesty's `{ requesty: { auto_cache:\n * true } }`, for example. Modelling each one would tie this provider to a\n * catalogue of gateways it cannot see; passing them through keeps the typed\n * surface OpenAI's and the untyped surface open.\n *\n * Merged over the built body, so a field named here wins over the one this\n * provider would have sent. Per-request keys win over the layer's\n * {@link Config.extraBody}.\n */\n readonly extraBody?: Readonly<Record<string, unknown>>\n /**\n * Free-form JSON output: model emits valid JSON without schema\n * constraints. Mutually exclusive with `structured` (schema wins if\n * both are set).\n */\n readonly responseFormat?: { readonly type: \"json_object\" }\n /**\n * Answer length / level-of-detail hint. GPT-5+ models honour it;\n * earlier models ignore.\n */\n readonly verbosity?: \"low\" | \"medium\" | \"high\"\n}\n\nexport type ResponsesService = {\n /**\n * Stream the provider's native event vocabulary (post-SSE-decode).\n * Use this when you need full vendor fidelity. For provider-portable\n * code, use `streamTurn` instead.\n */\n readonly streamNative: (\n request: ResponsesRequest,\n ) => Stream.Stream<ProviderEvent, AiError.AiError>\n /**\n * Stream canonical `TurnEvent`s. Implemented as\n * `streamNative |> toCanonical`.\n */\n readonly streamTurn: (request: ResponsesRequest) => Stream.Stream<TurnEvent, AiError.AiError>\n /**\n * Drain a single turn and return the assembled `Turn`. Derived from\n * `streamTurn` — Responses doesn't expose a native non-streaming\n * complete endpoint we'd want to take advantage of.\n */\n readonly turn: (request: ResponsesRequest) => Effect.Effect<Turn, AiError.AiError>\n /**\n * Project a stream of native `ProviderEvent`s into canonical `TurnEvent`s.\n * Exposed for cases where consumers want to compose with `streamNative`\n * directly (e.g. tap into natives + still get canonical downstream).\n */\n readonly toCanonical: <E, R>(\n s: Stream.Stream<ProviderEvent, E, R>,\n ) => Stream.Stream<TurnEvent, E, R>\n}\n\n/**\n * Provider-typed service tag. Yield this when you want Responses-specific\n * options (`reasoning.effort`, `store`, `previousResponseId`) at the call\n * site. Yield the generic `LanguageModel` tag for provider-portable code -\n * both are registered by `layer`.\n */\nexport class Responses extends Context.Service<Responses, ResponsesService>()(\n \"@betalyra/effect-uai/providers/responses/Responses\",\n) {}\n\nexport type Config = {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\n readonly region?: OpenAiRegion\n /**\n * Vendor-specific body fields sent on every request from this layer — the\n * place for a gateway's standing configuration, so call sites do not repeat\n * it. Overridden per request by {@link ResponsesRequest.extraBody}.\n */\n readonly extraBody?: Readonly<Record<string, unknown>>\n}\n\n// ---------------------------------------------------------------------------\n// Request body\n// ---------------------------------------------------------------------------\n\nconst jsonSchemaFormat = (\n format: StructuredFormat.StructuredFormat<unknown>,\n): Record<string, unknown> => ({\n type: \"json_schema\",\n name: format.name,\n schema: format.schema[\"~standard\"].jsonSchema.input({ target: \"draft-2020-12\" }),\n ...(format.description !== undefined && { description: format.description }),\n ...(format.strict !== undefined && { strict: format.strict }),\n})\n\nconst buildText = (request: ResponsesRequest): Record<string, unknown> | undefined => {\n const format =\n request.structured !== undefined ? jsonSchemaFormat(request.structured) : request.responseFormat\n const text: Record<string, unknown> = {}\n if (format !== undefined) text.format = format\n if (request.verbosity !== undefined) text.verbosity = request.verbosity\n return Object.keys(text).length === 0 ? undefined : text\n}\n\nconst buildBody = (\n request: ResponsesRequest,\n providerToolWire: ReadonlyArray<Record<string, unknown>>,\n cfg: Config,\n): Record<string, unknown> => {\n const text = buildText(request)\n const functionTools = descriptorsOf(request.tools).map((t) => ({\n type: \"function\",\n name: t.name,\n description: t.description,\n parameters: t.inputSchema,\n ...(t.strict !== undefined && { strict: t.strict }),\n }))\n const tools = [...functionTools, ...providerToolWire]\n return {\n model: request.model,\n input: itemsToInput(request.history),\n stream: true,\n ...(tools.length > 0 && { tools }),\n ...(request.toolChoice !== undefined && { tool_choice: request.toolChoice }),\n ...(request.temperature !== undefined && { temperature: request.temperature }),\n ...(request.maxOutputTokens !== undefined && {\n max_output_tokens: request.maxOutputTokens,\n }),\n ...(request.reasoning !== undefined && { reasoning: request.reasoning }),\n ...(request.store !== undefined && { store: request.store }),\n ...(request.previousResponseId !== undefined && {\n previous_response_id: request.previousResponseId,\n }),\n ...(request.instructions !== undefined && { instructions: request.instructions }),\n ...(request.topP !== undefined && { top_p: request.topP }),\n ...(request.parallelToolCalls !== undefined && {\n parallel_tool_calls: request.parallelToolCalls,\n }),\n ...(request.metadata !== undefined && { metadata: request.metadata }),\n ...(request.user !== undefined && { user: request.user }),\n ...(request.safetyIdentifier !== undefined && {\n safety_identifier: request.safetyIdentifier,\n }),\n ...(request.promptCacheKey !== undefined && {\n prompt_cache_key: request.promptCacheKey,\n }),\n ...(request.truncation !== undefined && { truncation: request.truncation }),\n ...(text !== undefined && { text }),\n ...cfg.extraBody,\n ...request.extraBody,\n }\n}\n\n// ---------------------------------------------------------------------------\n// SSE event → provider event\n// ---------------------------------------------------------------------------\n\nconst decodeKnown = Schema.decodeUnknownEffect(KnownProviderEvent)\n\nconst makeUnknown = (raw: unknown): ProviderEvent => ({ type: \"_unknown\", raw })\n\n/**\n * Lift events that carry a terminal failure signal (`error`,\n * `response.failed`) to a typed `AiError`. Other events are not failures\n * and produce `Option.none`.\n */\nconst eventToError = Match.type<ProviderEvent>().pipe(\n Match.discriminators(\"type\")({\n error: (e): AiError.AiError => {\n const detail = e.error\n const message = detail?.message ?? e.message\n const code = detail?.code ?? e.code\n const param = detail?.param\n // A top-level SSE `error` is usually a request rejection (bad model,\n // missing access, malformed body): non-retryable, so `InvalidRequest`.\n return detail?.type === \"invalid_request_error\"\n ? new AiError.InvalidRequest({\n provider: \"responses\",\n ...(param != null && { param }),\n raw: e,\n })\n : new AiError.GenerationFailed({\n provider: \"responses\",\n ...(code != null && { code }),\n ...(message != null && { message }),\n raw: e,\n })\n },\n \"response.failed\": (e): AiError.AiError => {\n const code = e.response.error?.code\n const message = e.response.error?.message\n return new AiError.GenerationFailed({\n provider: \"responses\",\n ...(code !== undefined && code !== null && { code }),\n ...(message !== undefined && message !== null && { message }),\n raw: e,\n })\n },\n }),\n Match.option,\n)\n\nconst parseJsonUnknown = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Unknown))\n\nconst sseEventToProviderEvent = (ev: SSE.Event): Effect.Effect<ProviderEvent> =>\n parseJsonUnknown(ev.data).pipe(\n Effect.flatMap((parsed) =>\n decodeKnown(parsed).pipe(Effect.orElseSucceed(() => makeUnknown(parsed))),\n ),\n Effect.orElseSucceed(() => makeUnknown(ev.data)),\n )\n\n// ---------------------------------------------------------------------------\n// Service implementation\n// ---------------------------------------------------------------------------\n\nexport const httpStatusError = (status: number, body: string): AiError.AiError => {\n const provider = \"responses\"\n const raw = body\n if (status === 429) return new AiError.RateLimited({ provider, raw })\n if (status === 408 || status === 504) return new AiError.Timeout({ provider, raw })\n if (status === 401) return new AiError.AuthFailed({ provider, subtype: \"auth\", raw })\n if (status === 403) return new AiError.AuthFailed({ provider, subtype: \"permission\", raw })\n if (status === 402) return new AiError.AuthFailed({ provider, subtype: \"billing\", raw })\n if (status === 413) return new AiError.ContextLengthExceeded({ provider, raw })\n if (status >= 500) return new AiError.Unavailable({ provider, status, raw })\n return new AiError.InvalidRequest({ provider, raw })\n}\n\n/**\n * Decode an already-executed `/responses` HTTP response into the native\n * `ProviderEvent` stream: fail on a >=400 status, else SSE-decode the body and\n * lift terminal `error` / `response.failed` events to a typed `AiError`. Shared\n * by the streaming turn path (POST) and the deep-research resume stream (GET\n * `?stream=true`).\n */\nexport const providerEventsOfResponse = (\n response: HttpClientResponse.HttpClientResponse,\n): Stream.Stream<ProviderEvent, AiError.AiError> =>\n Stream.unwrap(\n Effect.gen(function* () {\n if (response.status >= 400) {\n const body = yield* response.text.pipe(Effect.orElseSucceed(() => \"\"))\n return Stream.fail(httpStatusError(response.status, body))\n }\n return response.stream.pipe(\n Stream.mapError((cause) => new AiError.Unavailable({ provider: \"responses\", raw: cause })),\n SSE.fromBytes,\n Stream.mapEffect(sseEventToProviderEvent),\n Stream.flatMap((event) =>\n Option.match(eventToError(event), {\n onNone: () => Stream.succeed(event),\n onSome: Stream.fail,\n }),\n ),\n )\n }),\n )\n\nconst buildNativeStream = (cfg: Config) => {\n const url = `${resolveHost(cfg)}/responses`\n return (\n request: ResponsesRequest,\n ): Stream.Stream<ProviderEvent, AiError.AiError, HttpClient.HttpClient> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const providerToolWire = yield* Result.match(\n renderProviderTools(providerToolsOf(request.tools)),\n {\n onFailure: (e) =>\n Effect.fail(\n new AiError.Unsupported({\n provider: \"responses\",\n capability: e.capability,\n reason: e.reason,\n }),\n ),\n onSuccess: (wire) => Effect.succeed(wire),\n },\n )\n const httpRequest = HttpClientRequest.post(url).pipe(\n HttpClientRequest.bearerToken(cfg.apiKey),\n HttpClientRequest.bodyJsonUnsafe(buildBody(request, providerToolWire, cfg)),\n HttpClientRequest.accept(\"text/event-stream\"),\n )\n const response = yield* client\n .execute(httpRequest)\n .pipe(\n Effect.mapError(\n (cause) => new AiError.Unavailable({ provider: \"responses\", raw: cause }),\n ),\n )\n return providerEventsOfResponse(response)\n }),\n )\n}\n\n/**\n * Project a stream of native `ProviderEvent`s into canonical `TurnEvent`s.\n * Threads a fresh `CallIdLookup` per stream so `function_call_arguments.delta`\n * can be tagged with the right `call_id`.\n */\nexport const toCanonical = <E, R>(\n s: Stream.Stream<ProviderEvent, E, R>,\n): Stream.Stream<TurnEvent, E, R> =>\n Stream.unwrap(\n Effect.sync(() => {\n const lookup = makeCallIdLookup()\n return s.pipe(Stream.flatMap((event) => Stream.fromIterable(eventToDeltas(event, lookup))))\n }),\n )\n\n// ---------------------------------------------------------------------------\n// Constructors\n// ---------------------------------------------------------------------------\n\n/**\n * Build a `ResponsesService` value. For Layer-based setup, prefer `layer`.\n */\nexport const make = (cfg: Config): Effect.Effect<ResponsesService, never, HttpClient.HttpClient> =>\n Effect.map(HttpClient.HttpClient, (client) => {\n const streamNative: ResponsesService[\"streamNative\"] = (request) =>\n buildNativeStream(cfg)(request).pipe(Stream.provideService(HttpClient.HttpClient, client))\n const streamTurn: ResponsesService[\"streamTurn\"] = (request) =>\n toCanonical(streamNative(request))\n return {\n streamNative,\n streamTurn,\n turn: turnFromStream(streamTurn),\n toCanonical,\n }\n })\n\n/**\n * Layer that registers both the provider-specific `Responses` tag and the\n * generic `LanguageModel` tag, sharing one underlying implementation.\n *\n * The generic tag accepts `CommonRequest`; the typed tag accepts the full\n * `ResponsesRequest` surface.\n */\nexport const layer = (\n cfg: Config,\n): Layer.Layer<Responses | LanguageModel, never, HttpClient.HttpClient> => {\n const typed = Layer.effect(Responses, make(cfg))\n const generic = Layer.effect(\n LanguageModel,\n Effect.map(\n make(cfg),\n (s): LanguageModelService => ({\n streamTurn: (request) => s.streamTurn(request as ResponsesRequest),\n turn: (request) => s.turn(request as ResponsesRequest),\n }),\n ),\n )\n return Layer.merge(typed, generic)\n}\n"],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import { Result, Schema } from "effect";
2
+ import * as Tool from "@effect-uai/core/Tool";
3
+
4
+ //#region src/ResponsesTools.d.ts
5
+ declare namespace ResponsesTools_d_exports {
6
+ export { ResponsesToolConfig, ToolRenderError, UserLocation, WebSearchFilters, WebSearchOptions, codeInterpreterTool, fileSearchTool, renderProviderTools, webSearchTool };
7
+ }
8
+ declare const UserLocation: Schema.Struct<{
9
+ readonly city: Schema.optional<Schema.String>;
10
+ readonly region: Schema.optional<Schema.String>;
11
+ readonly country: Schema.optional<Schema.String>;
12
+ readonly timezone: Schema.optional<Schema.String>;
13
+ }>;
14
+ type UserLocation = typeof UserLocation.Type;
15
+ declare const WebSearchFilters: Schema.Struct<{
16
+ readonly allowedDomains: Schema.optional<Schema.$Array<Schema.String>>;
17
+ readonly blockedDomains: Schema.optional<Schema.$Array<Schema.String>>;
18
+ }>;
19
+ type WebSearchFilters = typeof WebSearchFilters.Type;
20
+ /** Discriminated config for a Responses hosted tool. */
21
+ declare const ResponsesToolConfig: Schema.Union<readonly [Schema.Struct<{
22
+ readonly kind: Schema.Literal<"web_search">;
23
+ readonly filters: Schema.optional<Schema.Struct<{
24
+ readonly allowedDomains: Schema.optional<Schema.$Array<Schema.String>>;
25
+ readonly blockedDomains: Schema.optional<Schema.$Array<Schema.String>>;
26
+ }>>;
27
+ readonly userLocation: Schema.optional<Schema.Struct<{
28
+ readonly city: Schema.optional<Schema.String>;
29
+ readonly region: Schema.optional<Schema.String>;
30
+ readonly country: Schema.optional<Schema.String>;
31
+ readonly timezone: Schema.optional<Schema.String>;
32
+ }>>;
33
+ readonly searchContextSize: Schema.optional<Schema.Literals<readonly ["low", "medium", "high"]>>;
34
+ }>, Schema.Struct<{
35
+ readonly kind: Schema.Literal<"code_interpreter">;
36
+ readonly fileIds: Schema.optional<Schema.$Array<Schema.String>>;
37
+ }>, Schema.Struct<{
38
+ readonly kind: Schema.Literal<"file_search">;
39
+ readonly vectorStoreIds: Schema.$Array<Schema.String>;
40
+ }>]>;
41
+ type ResponsesToolConfig = typeof ResponsesToolConfig.Type;
42
+ type WebSearchOptions = {
43
+ readonly filters?: WebSearchFilters;
44
+ readonly userLocation?: UserLocation;
45
+ readonly searchContextSize?: "low" | "medium" | "high";
46
+ };
47
+ /** OpenAI-hosted web search. */
48
+ declare const webSearchTool: (opts?: WebSearchOptions) => Tool.ProviderTool<"web_search", Record<string, never>, "openai", {
49
+ readonly filters?: WebSearchFilters;
50
+ readonly userLocation?: UserLocation;
51
+ readonly searchContextSize?: "low" | "medium" | "high";
52
+ readonly kind: "web_search";
53
+ }>;
54
+ /** OpenAI-hosted code interpreter (Python sandbox). */
55
+ declare const codeInterpreterTool: (opts?: {
56
+ readonly fileIds?: ReadonlyArray<string>;
57
+ }) => Tool.ProviderTool<"code_interpreter", Record<string, never>, "openai", {
58
+ readonly fileIds?: ReadonlyArray<string>;
59
+ readonly kind: "code_interpreter";
60
+ }>;
61
+ /** OpenAI-hosted file search over the given vector stores. */
62
+ declare const fileSearchTool: (opts: {
63
+ readonly vectorStoreIds: ReadonlyArray<string>;
64
+ }) => Tool.ProviderTool<"file_search", Record<string, never>, "openai", {
65
+ readonly kind: "file_search";
66
+ readonly vectorStoreIds: readonly string[];
67
+ }>;
68
+ /**
69
+ * A provider tool this adapter cannot render — a foreign `provider` or an
70
+ * unrecognized `config`. Carried as data so `Responses.ts` can lift it into a
71
+ * typed `AiError.Unsupported`.
72
+ */
73
+ type ToolRenderError = {
74
+ readonly capability: string;
75
+ readonly reason: string;
76
+ };
77
+ /**
78
+ * Render a toolkit's Responses provider tools to native `tools` entries. Fails
79
+ * with a `ToolRenderError` on the first foreign or unrecognized tool rather
80
+ * than dropping it.
81
+ */
82
+ declare const renderProviderTools: (tools: ReadonlyArray<Tool.ProviderTool<string, any, string, any>>) => Result.Result<ReadonlyArray<Record<string, unknown>>, ToolRenderError>;
83
+ //#endregion
84
+ export { ResponsesToolConfig, ToolRenderError, UserLocation, WebSearchFilters, WebSearchOptions, codeInterpreterTool, fileSearchTool, renderProviderTools, ResponsesTools_d_exports as t, webSearchTool };
85
+ //# sourceMappingURL=ResponsesTools.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResponsesTools.d.mts","names":[],"sources":["../src/ResponsesTools.ts"],"mappings":";;;;;;;cAYM,YAAA,EAAY,MAAA,CAAA,MAAA;EAAA;;;;;KAMN,YAAA,UAAsB,YAAA,CAAa,IAAA;AAAA,cAEzC,gBAAA,EAAgB,MAAA,CAAA,MAAA;EAAA;;;KAIV,gBAAA,UAA0B,gBAAA,CAAiB,IAAA;;cAoB1C,mBAAA,EAAmB,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;KAKpB,mBAAA,UAA6B,mBAAA,CAAoB,IAAA;AAAA,KAEjD,gBAAA;EAAA,SACD,OAAA,GAAU,gBAAA;EAAA,SACV,YAAA,GAAe,YAAA;EAAA,SACf,iBAAA;AAAA;;cAIE,aAAA,GAAiB,IAAA,GAAM,gBAAA,KAAqB,IAAA,CAAA,YAAA,eAAA,MAAA;EAAA,mBANpC,gBAAA;EAAA,wBACK,YAAA;EAAA;;;;cAeb,mBAAA,GAAuB,IAAA;EAAA,SAAiB,OAAA,GAAU,aAAA;AAAA,MAA4B,IAAA,CAAA,YAAA,qBAAA,MAAA;EAAA,mBAA5B,aAAA;EAAA;;;cAUlD,cAAA,GAAkB,IAAA;EAAA,SAAiB,cAAA,EAAgB,aAAA;AAAA,MAAuB,IAAA,CAAA,YAAA,gBAAA,MAAA;EAAA;;;;;;;;KAc3E,eAAA;EAAA,SACD,UAAA;EAAA,SACA,MAAA;AAAA;;;;;;cA4DE,mBAAA,GACX,KAAA,EAAO,aAAA,CAAc,IAAA,CAAK,YAAA,gCACzB,MAAA,CAAO,MAAA,CAAO,aAAA,CAAc,MAAA,oBAA0B,eAAA"}
@@ -0,0 +1,126 @@
1
+ import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
2
+ import { Match, Result, Schema } from "effect";
3
+ import * as Tool from "@effect-uai/core/Tool";
4
+ //#region src/ResponsesTools.ts
5
+ var ResponsesTools_exports = /* @__PURE__ */ __exportAll({
6
+ ResponsesToolConfig: () => ResponsesToolConfig,
7
+ codeInterpreterTool: () => codeInterpreterTool,
8
+ fileSearchTool: () => fileSearchTool,
9
+ renderProviderTools: () => renderProviderTools,
10
+ webSearchTool: () => webSearchTool
11
+ });
12
+ const UserLocation = Schema.Struct({
13
+ city: Schema.optional(Schema.String),
14
+ region: Schema.optional(Schema.String),
15
+ country: Schema.optional(Schema.String),
16
+ timezone: Schema.optional(Schema.String)
17
+ });
18
+ const WebSearchFilters = Schema.Struct({
19
+ allowedDomains: Schema.optional(Schema.Array(Schema.String)),
20
+ blockedDomains: Schema.optional(Schema.Array(Schema.String))
21
+ });
22
+ const WebSearchConfig = Schema.Struct({
23
+ kind: Schema.Literal("web_search"),
24
+ filters: Schema.optional(WebSearchFilters),
25
+ userLocation: Schema.optional(UserLocation),
26
+ searchContextSize: Schema.optional(Schema.Literals([
27
+ "low",
28
+ "medium",
29
+ "high"
30
+ ]))
31
+ });
32
+ const CodeInterpreterConfig = Schema.Struct({
33
+ kind: Schema.Literal("code_interpreter"),
34
+ fileIds: Schema.optional(Schema.Array(Schema.String))
35
+ });
36
+ const FileSearchConfig = Schema.Struct({
37
+ kind: Schema.Literal("file_search"),
38
+ vectorStoreIds: Schema.Array(Schema.String)
39
+ });
40
+ /** Discriminated config for a Responses hosted tool. */
41
+ const ResponsesToolConfig = Schema.Union([
42
+ WebSearchConfig,
43
+ CodeInterpreterConfig,
44
+ FileSearchConfig
45
+ ]);
46
+ /** OpenAI-hosted web search. */
47
+ const webSearchTool = (opts = {}) => Tool.provider({
48
+ name: "web_search",
49
+ description: "Search the web, executed by OpenAI.",
50
+ inputSchema: Tool.noInput,
51
+ provider: "openai",
52
+ config: {
53
+ kind: "web_search",
54
+ ...opts
55
+ }
56
+ });
57
+ /** OpenAI-hosted code interpreter (Python sandbox). */
58
+ const codeInterpreterTool = (opts = {}) => Tool.provider({
59
+ name: "code_interpreter",
60
+ description: "Run Python in a sandbox, executed by OpenAI.",
61
+ inputSchema: Tool.noInput,
62
+ provider: "openai",
63
+ config: {
64
+ kind: "code_interpreter",
65
+ ...opts
66
+ }
67
+ });
68
+ /** OpenAI-hosted file search over the given vector stores. */
69
+ const fileSearchTool = (opts) => Tool.provider({
70
+ name: "file_search",
71
+ description: "Retrieve from uploaded files, executed by OpenAI.",
72
+ inputSchema: Tool.noInput,
73
+ provider: "openai",
74
+ config: {
75
+ kind: "file_search",
76
+ vectorStoreIds: opts.vectorStoreIds
77
+ }
78
+ });
79
+ const filtersWire = (f) => ({
80
+ ...f.allowedDomains !== void 0 && { allowed_domains: f.allowedDomains },
81
+ ...f.blockedDomains !== void 0 && { blocked_domains: f.blockedDomains }
82
+ });
83
+ const userLocationWire = (loc) => ({
84
+ type: "approximate",
85
+ ...loc.city !== void 0 && { city: loc.city },
86
+ ...loc.region !== void 0 && { region: loc.region },
87
+ ...loc.country !== void 0 && { country: loc.country },
88
+ ...loc.timezone !== void 0 && { timezone: loc.timezone }
89
+ });
90
+ const configToWire = Match.type().pipe(Match.discriminatorsExhaustive("kind")({
91
+ web_search: (c) => ({
92
+ type: "web_search",
93
+ ...c.filters !== void 0 && { filters: filtersWire(c.filters) },
94
+ ...c.userLocation !== void 0 && { user_location: userLocationWire(c.userLocation) },
95
+ ...c.searchContextSize !== void 0 && { search_context_size: c.searchContextSize }
96
+ }),
97
+ code_interpreter: (c) => ({
98
+ type: "code_interpreter",
99
+ container: c.fileIds !== void 0 ? {
100
+ type: "auto",
101
+ file_ids: c.fileIds
102
+ } : { type: "auto" }
103
+ }),
104
+ file_search: (c) => ({
105
+ type: "file_search",
106
+ vector_store_ids: c.vectorStoreIds
107
+ })
108
+ }));
109
+ const decodeConfig = Schema.decodeUnknownResult(ResponsesToolConfig);
110
+ const renderOne = (tool) => tool.provider !== "openai" ? Result.fail({
111
+ capability: `providerTool:${tool.provider}`,
112
+ reason: `tool "${tool.name}" is hosted by "${tool.provider}", not openai`
113
+ }) : decodeConfig(tool.config).pipe(Result.map(configToWire), Result.mapError(() => ({
114
+ capability: "providerTool",
115
+ reason: `unrecognized Responses provider tool config on "${tool.name}"`
116
+ })));
117
+ /**
118
+ * Render a toolkit's Responses provider tools to native `tools` entries. Fails
119
+ * with a `ToolRenderError` on the first foreign or unrecognized tool rather
120
+ * than dropping it.
121
+ */
122
+ const renderProviderTools = (tools) => Result.all(tools.map(renderOne));
123
+ //#endregion
124
+ export { ResponsesToolConfig, codeInterpreterTool, fileSearchTool, renderProviderTools, ResponsesTools_exports as t, webSearchTool };
125
+
126
+ //# sourceMappingURL=ResponsesTools.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResponsesTools.mjs","names":[],"sources":["../src/ResponsesTools.ts"],"sourcesContent":["import { Match, Result, Schema } from \"effect\"\nimport * as Tool from \"@effect-uai/core/Tool\"\n\n// ---------------------------------------------------------------------------\n// OpenAI Responses provider-hosted tools. Each is a `Tool.provider` whose\n// `config` carries the wire `type` string plus its options; the renderer maps\n// it to a native entry appended to the `tools` array alongside function tools.\n// The `inputSchema` is never sent (provider tools are partitioned out of the\n// function declarations), so `Tool.noInput` suffices.\n// Reference: https://developers.openai.com/api/docs/guides/tools\n// ---------------------------------------------------------------------------\n\nconst UserLocation = Schema.Struct({\n city: Schema.optional(Schema.String),\n region: Schema.optional(Schema.String),\n country: Schema.optional(Schema.String),\n timezone: Schema.optional(Schema.String),\n})\nexport type UserLocation = typeof UserLocation.Type\n\nconst WebSearchFilters = Schema.Struct({\n allowedDomains: Schema.optional(Schema.Array(Schema.String)),\n blockedDomains: Schema.optional(Schema.Array(Schema.String)),\n})\nexport type WebSearchFilters = typeof WebSearchFilters.Type\n\nconst WebSearchConfig = Schema.Struct({\n kind: Schema.Literal(\"web_search\"),\n filters: Schema.optional(WebSearchFilters),\n userLocation: Schema.optional(UserLocation),\n searchContextSize: Schema.optional(Schema.Literals([\"low\", \"medium\", \"high\"])),\n})\n\nconst CodeInterpreterConfig = Schema.Struct({\n kind: Schema.Literal(\"code_interpreter\"),\n fileIds: Schema.optional(Schema.Array(Schema.String)),\n})\n\nconst FileSearchConfig = Schema.Struct({\n kind: Schema.Literal(\"file_search\"),\n vectorStoreIds: Schema.Array(Schema.String),\n})\n\n/** Discriminated config for a Responses hosted tool. */\nexport const ResponsesToolConfig = Schema.Union([\n WebSearchConfig,\n CodeInterpreterConfig,\n FileSearchConfig,\n])\nexport type ResponsesToolConfig = typeof ResponsesToolConfig.Type\n\nexport type WebSearchOptions = {\n readonly filters?: WebSearchFilters\n readonly userLocation?: UserLocation\n readonly searchContextSize?: \"low\" | \"medium\" | \"high\"\n}\n\n/** OpenAI-hosted web search. */\nexport const webSearchTool = (opts: WebSearchOptions = {}) =>\n Tool.provider({\n name: \"web_search\",\n description: \"Search the web, executed by OpenAI.\",\n inputSchema: Tool.noInput,\n provider: \"openai\",\n config: { kind: \"web_search\", ...opts } as const,\n })\n\n/** OpenAI-hosted code interpreter (Python sandbox). */\nexport const codeInterpreterTool = (opts: { readonly fileIds?: ReadonlyArray<string> } = {}) =>\n Tool.provider({\n name: \"code_interpreter\",\n description: \"Run Python in a sandbox, executed by OpenAI.\",\n inputSchema: Tool.noInput,\n provider: \"openai\",\n config: { kind: \"code_interpreter\", ...opts } as const,\n })\n\n/** OpenAI-hosted file search over the given vector stores. */\nexport const fileSearchTool = (opts: { readonly vectorStoreIds: ReadonlyArray<string> }) =>\n Tool.provider({\n name: \"file_search\",\n description: \"Retrieve from uploaded files, executed by OpenAI.\",\n inputSchema: Tool.noInput,\n provider: \"openai\",\n config: { kind: \"file_search\", vectorStoreIds: opts.vectorStoreIds } as const,\n })\n\n/**\n * A provider tool this adapter cannot render — a foreign `provider` or an\n * unrecognized `config`. Carried as data so `Responses.ts` can lift it into a\n * typed `AiError.Unsupported`.\n */\nexport type ToolRenderError = {\n readonly capability: string\n readonly reason: string\n}\n\nconst filtersWire = (f: WebSearchFilters): Record<string, unknown> => ({\n ...(f.allowedDomains !== undefined && { allowed_domains: f.allowedDomains }),\n ...(f.blockedDomains !== undefined && { blocked_domains: f.blockedDomains }),\n})\n\nconst userLocationWire = (loc: UserLocation): Record<string, unknown> => ({\n type: \"approximate\",\n ...(loc.city !== undefined && { city: loc.city }),\n ...(loc.region !== undefined && { region: loc.region }),\n ...(loc.country !== undefined && { country: loc.country }),\n ...(loc.timezone !== undefined && { timezone: loc.timezone }),\n})\n\nconst configToWire = Match.type<ResponsesToolConfig>().pipe(\n Match.discriminatorsExhaustive(\"kind\")({\n web_search: (c): Record<string, unknown> => ({\n type: \"web_search\",\n ...(c.filters !== undefined && { filters: filtersWire(c.filters) }),\n ...(c.userLocation !== undefined && { user_location: userLocationWire(c.userLocation) }),\n ...(c.searchContextSize !== undefined && { search_context_size: c.searchContextSize }),\n }),\n code_interpreter: (c): Record<string, unknown> => ({\n type: \"code_interpreter\",\n container: c.fileIds !== undefined ? { type: \"auto\", file_ids: c.fileIds } : { type: \"auto\" },\n }),\n file_search: (c): Record<string, unknown> => ({\n type: \"file_search\",\n vector_store_ids: c.vectorStoreIds,\n }),\n }),\n)\n\nconst decodeConfig = Schema.decodeUnknownResult(ResponsesToolConfig)\n\nconst renderOne = (\n tool: Tool.ProviderTool<string, any, string, any>,\n): Result.Result<Record<string, unknown>, ToolRenderError> =>\n tool.provider !== \"openai\"\n ? Result.fail({\n capability: `providerTool:${tool.provider}`,\n reason: `tool \"${tool.name}\" is hosted by \"${tool.provider}\", not openai`,\n })\n : decodeConfig(tool.config).pipe(\n Result.map(configToWire),\n Result.mapError(\n (): ToolRenderError => ({\n capability: \"providerTool\",\n reason: `unrecognized Responses provider tool config on \"${tool.name}\"`,\n }),\n ),\n )\n\n/**\n * Render a toolkit's Responses provider tools to native `tools` entries. Fails\n * with a `ToolRenderError` on the first foreign or unrecognized tool rather\n * than dropping it.\n */\nexport const renderProviderTools = (\n tools: ReadonlyArray<Tool.ProviderTool<string, any, string, any>>,\n): Result.Result<ReadonlyArray<Record<string, unknown>>, ToolRenderError> =>\n Result.all(tools.map(renderOne))\n"],"mappings":"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"}
package/dist/codec.d.mts CHANGED
@@ -4,8 +4,29 @@ import { HistoryItem } from "@effect-uai/core/Items";
4
4
 
5
5
  //#region src/codec.d.ts
6
6
  declare namespace codec_d_exports {
7
- export { WireOutputItem, WireResponseCompleted, itemsToInput, turnFromCompleted, wireItemToItem };
7
+ export { WireAnnotation, WireOutputItem, WireResponseCompleted, itemsToInput, turnFromCompleted, wireItemToItem };
8
8
  }
9
+ declare const WireAnnotation: Schema.Union<readonly [Schema.Struct<{
10
+ readonly type: Schema.Literal<"url_citation">;
11
+ readonly url: Schema.String;
12
+ readonly start_index: Schema.Number;
13
+ readonly end_index: Schema.Number;
14
+ readonly title: Schema.String;
15
+ }>, Schema.Struct<{
16
+ readonly type: Schema.Literal<"file_citation">;
17
+ readonly file_id: Schema.String;
18
+ readonly index: Schema.Number;
19
+ }>, Schema.Struct<{
20
+ readonly type: Schema.Literal<"container_file_citation">;
21
+ readonly container_id: Schema.String;
22
+ readonly file_id: Schema.String;
23
+ readonly start_index: Schema.Number;
24
+ readonly end_index: Schema.Number;
25
+ }>, Schema.Struct<{
26
+ readonly type: Schema.Literal<"file_path">;
27
+ readonly file_id: Schema.String;
28
+ readonly index: Schema.Number;
29
+ }>]>;
9
30
  declare const WireOutputItem: Schema.Union<readonly [Schema.Struct<{
10
31
  readonly type: Schema.Literal<"message">;
11
32
  readonly id: Schema.optional<Schema.String>;
@@ -52,6 +73,15 @@ declare const WireOutputItem: Schema.Union<readonly [Schema.Struct<{
52
73
  readonly text: Schema.String;
53
74
  }>>>;
54
75
  readonly encrypted_content: Schema.optional<Schema.String>;
76
+ }>, Schema.Struct<{
77
+ readonly type: Schema.Literal<"web_search_call">;
78
+ readonly id: Schema.optional<Schema.String>;
79
+ }>, Schema.Struct<{
80
+ readonly type: Schema.Literal<"code_interpreter_call">;
81
+ readonly id: Schema.optional<Schema.String>;
82
+ }>, Schema.Struct<{
83
+ readonly type: Schema.Literal<"file_search_call">;
84
+ readonly id: Schema.optional<Schema.String>;
55
85
  }>]>;
56
86
  type WireOutputItem = typeof WireOutputItem.Type;
57
87
  declare const WireResponseCompleted: Schema.Struct<{
@@ -103,6 +133,15 @@ declare const WireResponseCompleted: Schema.Struct<{
103
133
  readonly text: Schema.String;
104
134
  }>>>;
105
135
  readonly encrypted_content: Schema.optional<Schema.String>;
136
+ }>, Schema.Struct<{
137
+ readonly type: Schema.Literal<"web_search_call">;
138
+ readonly id: Schema.optional<Schema.String>;
139
+ }>, Schema.Struct<{
140
+ readonly type: Schema.Literal<"code_interpreter_call">;
141
+ readonly id: Schema.optional<Schema.String>;
142
+ }>, Schema.Struct<{
143
+ readonly type: Schema.Literal<"file_search_call">;
144
+ readonly id: Schema.optional<Schema.String>;
106
145
  }>]>>>>;
107
146
  readonly usage: Schema.optional<Schema.NullOr<Schema.Struct<{
108
147
  readonly input_tokens: Schema.optional<Schema.Number>;
@@ -126,8 +165,8 @@ declare const WireResponseCompleted: Schema.Struct<{
126
165
  type WireResponseCompleted = typeof WireResponseCompleted.Type;
127
166
  /** Convert our `HistoryItem[]` history into the Responses API `input` array. */
128
167
  declare const itemsToInput: (items: ReadonlyArray<HistoryItem>) => ReadonlyArray<Record<string, unknown>>;
129
- declare const wireItemToItem: (wire: WireOutputItem) => HistoryItem;
168
+ declare const wireItemToItem: (wire: WireOutputItem) => ReadonlyArray<HistoryItem>;
130
169
  declare const turnFromCompleted: (payload: WireResponseCompleted) => Turn;
131
170
  //#endregion
132
- export { WireOutputItem, WireResponseCompleted, itemsToInput, codec_d_exports as t, turnFromCompleted, wireItemToItem };
171
+ export { WireAnnotation, WireOutputItem, WireResponseCompleted, itemsToInput, codec_d_exports as t, turnFromCompleted, wireItemToItem };
133
172
  //# sourceMappingURL=codec.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"codec.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":";;;;;;;;cAoFa,cAAA,EAAc,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KACf,cAAA,UAAwB,cAAA,CAAe,IAAA;AAAA,cA6BtC,qBAAA,EAAqB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KActB,qBAAA,UAA+B,qBAAA,CAAsB,IAAA;;cA0EpD,YAAA,GACX,KAAA,EAAO,aAAA,CAAc,WAAA,MACpB,aAAA,CAAc,MAAA;AAAA,cAiBJ,cAAA,GAAkB,IAAA,EAAM,cAAA,KAAiB,WAAA;AAAA,cA8DzC,iBAAA,GAAqB,OAAA,EAAS,qBAAA,KAAwB,IAAA"}
1
+ {"version":3,"file":"codec.d.mts","names":[],"sources":["../src/codec.ts"],"mappings":";;;;;;;;cAqCa,cAAA,EAAc,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;cAkEd,cAAA,EAAc,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAQf,cAAA,UAAwB,cAAA,CAAe,IAAA;AAAA,cA6BtC,qBAAA,EAAqB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KActB,qBAAA,UAA+B,qBAAA,CAAsB,IAAA;;cA8FpD,YAAA,GACX,KAAA,EAAO,aAAA,CAAc,WAAA,MACpB,aAAA,CAAc,MAAA;AAAA,cAiBJ,cAAA,GAAkB,IAAA,EAAM,cAAA,KAAiB,aAAA,CAAc,WAAA;AAAA,cAwEvD,iBAAA,GAAqB,OAAA,EAAS,qBAAA,KAAwB,IAAA"}
package/dist/codec.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
2
- import { Encoding, Match, Option, Schema } from "effect";
2
+ import { Encoding, Match, Option, Result, Schema, pipe } from "effect";
3
3
  //#region src/codec.ts
4
4
  var codec_exports = /* @__PURE__ */ __exportAll({
5
+ WireAnnotation: () => WireAnnotation,
5
6
  WireOutputItem: () => WireOutputItem,
6
7
  WireResponseCompleted: () => WireResponseCompleted,
7
8
  itemsToInput: () => itemsToInput,
@@ -71,10 +72,25 @@ const WireReasoning = Schema.Struct({
71
72
  summary: Schema.optional(Schema.Array(WireSummaryText)),
72
73
  encrypted_content: Schema.optional(Schema.String)
73
74
  });
75
+ const WireWebSearchCall = Schema.Struct({
76
+ type: Schema.Literal("web_search_call"),
77
+ id: Schema.optional(Schema.String)
78
+ });
79
+ const WireCodeInterpreterCall = Schema.Struct({
80
+ type: Schema.Literal("code_interpreter_call"),
81
+ id: Schema.optional(Schema.String)
82
+ });
83
+ const WireFileSearchCall = Schema.Struct({
84
+ type: Schema.Literal("file_search_call"),
85
+ id: Schema.optional(Schema.String)
86
+ });
74
87
  const WireOutputItem = Schema.Union([
75
88
  WireMessage,
76
89
  WireFunctionCall,
77
- WireReasoning
90
+ WireReasoning,
91
+ WireWebSearchCall,
92
+ WireCodeInterpreterCall,
93
+ WireFileSearchCall
78
94
  ]);
79
95
  const WireInputTokensDetails = Schema.Struct({ cached_tokens: Schema.optional(Schema.NullOr(Schema.Number)) });
80
96
  const WireOutputTokensDetails = Schema.Struct({ reasoning_tokens: Schema.optional(Schema.NullOr(Schema.Number)) });
@@ -98,11 +114,33 @@ const WireResponseCompleted = Schema.Struct({
98
114
  error: Schema.optional(Schema.NullOr(WireResponseError))
99
115
  });
100
116
  /**
101
- * If an item carries `providerData` from a prior OpenAI turn, re-emit it
102
- * verbatim - preserves `encrypted_content`, item ids, and any field this
103
- * codec doesn't model.
117
+ * The item shapes we stash for round-tripping. Narrower than
118
+ * `WireOutputItem`: the provider-hosted call variants are dropped from the
119
+ * turn, so they are never stored. Composed from the internal `Wire*` structs,
120
+ * which keeps the wire model out of the package's public surface.
104
121
  */
105
- const passthrough = (item) => item.providerData !== void 0 && typeof item.providerData === "object" && item.providerData !== null ? item.providerData : void 0;
122
+ const StoredItem = Schema.Union([
123
+ WireMessage,
124
+ WireFunctionCall,
125
+ WireReasoning
126
+ ]);
127
+ const ProviderDataResponses = Schema.Struct({ responses: StoredItem });
128
+ const decodeResponsesData = Schema.decodeUnknownResult(ProviderDataResponses);
129
+ /**
130
+ * If an item carries `providerData.responses` from a prior turn on this API,
131
+ * re-emit it verbatim - preserves `encrypted_content` and item ids, which a
132
+ * fresh encode from our `HistoryItem` shape cannot reconstruct.
133
+ *
134
+ * Namespaced because `providerData` is a shared slot: an item routed through
135
+ * another provider first (dynamic fallback) carries that provider's key, and
136
+ * re-emitting the whole object would send that provider's data as the wire
137
+ * item and drop the real content. Anything that fails to decode is not ours,
138
+ * so we fall back to encoding the item normally.
139
+ */
140
+ const passthrough = (item) => pipe(decodeResponsesData(item.providerData), Result.match({
141
+ onSuccess: (data) => data.responses,
142
+ onFailure: () => void 0
143
+ }));
106
144
  /**
107
145
  * OpenAI's `input_image` content block carries a single `image_url` field;
108
146
  * inline bytes get encoded as a `data:` URI. Either form (URL or data URI)
@@ -168,26 +206,29 @@ const wireMessageContentToBlock = Match.type().pipe(Match.discriminatorsExhausti
168
206
  })
169
207
  }));
170
208
  const wireItemToItem = (wire) => Match.value(wire).pipe(Match.discriminatorsExhaustive("type")({
171
- message: (m) => ({
209
+ message: (m) => [{
172
210
  type: "message",
173
211
  role: m.role,
174
212
  content: m.content.map(wireMessageContentToBlock),
175
- providerData: m
176
- }),
177
- function_call: (f) => ({
213
+ providerData: { responses: m }
214
+ }],
215
+ function_call: (f) => [{
178
216
  type: "function_call",
179
217
  call_id: f.call_id,
180
218
  name: f.name,
181
219
  arguments: f.arguments,
182
- providerData: f
183
- }),
184
- reasoning: (r) => ({
220
+ providerData: { responses: f }
221
+ }],
222
+ reasoning: (r) => [{
185
223
  type: "reasoning",
186
224
  ...r.id !== void 0 && { id: r.id },
187
225
  ...r.summary !== void 0 && { summary: r.summary.map((s) => s.text).join("\n") },
188
226
  ...r.encrypted_content !== void 0 && { signature: r.encrypted_content },
189
- providerData: r
190
- })
227
+ providerData: { responses: r }
228
+ }],
229
+ web_search_call: () => [],
230
+ code_interpreter_call: () => [],
231
+ file_search_call: () => []
191
232
  }));
192
233
  const reasonToStop = Match.type().pipe(Match.when("max_output_tokens", () => "max_tokens"), Match.when("refusal", () => "refusal"), Match.when("content_filter", () => "content_filter"), Match.when("max_tool_calls", () => "max_tool_calls"), Match.option);
193
234
  const hasRefusalContent = (payload) => (payload.output ?? []).some((i) => i.type === "message" && i.content.some((c) => c.type === "refusal"));
@@ -201,7 +242,7 @@ const turnFromCompleted = (payload) => {
201
242
  const cached = cachedTokens(payload);
202
243
  const reasoning = reasoningTokens(payload);
203
244
  return {
204
- items: (payload.output ?? []).map(wireItemToItem),
245
+ items: (payload.output ?? []).flatMap(wireItemToItem),
205
246
  usage: {
206
247
  ...payload.usage?.input_tokens !== void 0 && { input_tokens: payload.usage.input_tokens },
207
248
  ...payload.usage?.output_tokens !== void 0 && { output_tokens: payload.usage.output_tokens },
@@ -213,6 +254,6 @@ const turnFromCompleted = (payload) => {
213
254
  };
214
255
  };
215
256
  //#endregion
216
- export { WireOutputItem, WireResponseCompleted, itemsToInput, codec_exports as t, turnFromCompleted, wireItemToItem };
257
+ export { WireAnnotation, WireOutputItem, WireResponseCompleted, itemsToInput, codec_exports as t, turnFromCompleted, wireItemToItem };
217
258
 
218
259
  //# sourceMappingURL=codec.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"codec.mjs","names":[],"sources":["../src/codec.ts"],"sourcesContent":["import { Encoding, Match, Option, Schema } from \"effect\"\nimport type { ContentBlock, InputImage, HistoryItem } from \"@effect-uai/core/Items\"\nimport type { Turn } from \"@effect-uai/core/Turn\"\n\n// ---------------------------------------------------------------------------\n// Wire schemas - minimal subset of the Responses API output we consume.\n// Reference: https://www.openresponses.org/specification\n// ---------------------------------------------------------------------------\n\nconst WireUrlCitation = Schema.Struct({\n type: Schema.Literal(\"url_citation\"),\n url: Schema.String,\n start_index: Schema.Number,\n end_index: Schema.Number,\n title: Schema.String,\n})\n\nconst WireFileCitation = Schema.Struct({\n type: Schema.Literal(\"file_citation\"),\n file_id: Schema.String,\n index: Schema.Number,\n})\n\nconst WireContainerFileCitation = Schema.Struct({\n type: Schema.Literal(\"container_file_citation\"),\n container_id: Schema.String,\n file_id: Schema.String,\n start_index: Schema.Number,\n end_index: Schema.Number,\n})\n\nconst WireFilePath = Schema.Struct({\n type: Schema.Literal(\"file_path\"),\n file_id: Schema.String,\n index: Schema.Number,\n})\n\nconst WireAnnotation = Schema.Union([\n WireUrlCitation,\n WireFileCitation,\n WireContainerFileCitation,\n WireFilePath,\n])\n\nconst WireOutputTextContent = Schema.Struct({\n type: Schema.Literal(\"output_text\"),\n text: Schema.String,\n annotations: Schema.optional(Schema.NullOr(Schema.Array(WireAnnotation))),\n})\n\nconst WireRefusalContent = Schema.Struct({\n type: Schema.Literal(\"refusal\"),\n refusal: Schema.String,\n})\n\nconst WireMessageContent = Schema.Union([WireOutputTextContent, WireRefusalContent])\n\nconst WireSummaryText = Schema.Struct({\n type: Schema.Literal(\"summary_text\"),\n text: Schema.String,\n})\n\nconst WireMessage = Schema.Struct({\n type: Schema.Literal(\"message\"),\n id: Schema.optional(Schema.String),\n role: Schema.Literal(\"assistant\"),\n content: Schema.Array(WireMessageContent),\n})\n\nconst WireFunctionCall = Schema.Struct({\n type: Schema.Literal(\"function_call\"),\n id: Schema.optional(Schema.String),\n call_id: Schema.String,\n name: Schema.String,\n arguments: Schema.String,\n})\n\nconst WireReasoning = Schema.Struct({\n type: Schema.Literal(\"reasoning\"),\n id: Schema.optional(Schema.String),\n summary: Schema.optional(Schema.Array(WireSummaryText)),\n encrypted_content: Schema.optional(Schema.String),\n})\n\nexport const WireOutputItem = Schema.Union([WireMessage, WireFunctionCall, WireReasoning])\nexport type WireOutputItem = typeof WireOutputItem.Type\n\nconst WireInputTokensDetails = Schema.Struct({\n cached_tokens: Schema.optional(Schema.NullOr(Schema.Number)),\n})\n\nconst WireOutputTokensDetails = Schema.Struct({\n reasoning_tokens: Schema.optional(Schema.NullOr(Schema.Number)),\n})\n\nconst WireUsage = Schema.Struct({\n input_tokens: Schema.optional(Schema.Number),\n output_tokens: Schema.optional(Schema.Number),\n total_tokens: Schema.optional(Schema.Number),\n input_tokens_details: Schema.optional(Schema.NullOr(WireInputTokensDetails)),\n output_tokens_details: Schema.optional(Schema.NullOr(WireOutputTokensDetails)),\n})\n\nconst WireResponseError = Schema.Struct({\n code: Schema.optional(Schema.NullOr(Schema.String)),\n message: Schema.optional(Schema.NullOr(Schema.String)),\n})\n\n// Many Responses-API fields are emitted as explicit `null` rather than\n// missing - `Schema.optional` alone (T | undefined) doesn't cover that, so\n// we lift each through `NullOr` first. Used by `response.completed`,\n// `response.incomplete`, and `response.failed` events; not every field is\n// populated on every event (e.g. `error` only on failed, `incomplete_details`\n// only on incomplete).\nexport const WireResponseCompleted = Schema.Struct({\n id: Schema.optional(Schema.NullOr(Schema.String)),\n status: Schema.optional(Schema.NullOr(Schema.String)),\n output: Schema.optional(Schema.NullOr(Schema.Array(WireOutputItem))),\n usage: Schema.optional(Schema.NullOr(WireUsage)),\n incomplete_details: Schema.optional(\n Schema.NullOr(\n Schema.Struct({\n reason: Schema.optional(Schema.NullOr(Schema.String)),\n }),\n ),\n ),\n error: Schema.optional(Schema.NullOr(WireResponseError)),\n})\nexport type WireResponseCompleted = typeof WireResponseCompleted.Type\n\n// ---------------------------------------------------------------------------\n// History → request body input\n// ---------------------------------------------------------------------------\n\n/**\n * If an item carries `providerData` from a prior OpenAI turn, re-emit it\n * verbatim - preserves `encrypted_content`, item ids, and any field this\n * codec doesn't model.\n */\nconst passthrough = (item: HistoryItem): Record<string, unknown> | undefined =>\n item.providerData !== undefined &&\n typeof item.providerData === \"object\" &&\n item.providerData !== null\n ? (item.providerData as Record<string, unknown>)\n : undefined\n\n/**\n * OpenAI's `input_image` content block carries a single `image_url` field;\n * inline bytes get encoded as a `data:` URI. Either form (URL or data URI)\n * is fine - the model just dereferences `image_url`.\n */\nconst imageSourceToUrl = Match.type<InputImage[\"source\"]>().pipe(\n Match.tag(\"url\", (s) => s.url),\n Match.tag(\"base64\", (s) => `data:${s.mimeType};base64,${s.base64}`),\n Match.tag(\"bytes\", (s) => `data:${s.mimeType};base64,${Encoding.encodeBase64(s.bytes)}`),\n Match.exhaustive,\n)\n\nconst contentBlockToInput = Match.type<ContentBlock>().pipe(\n Match.discriminatorsExhaustive(\"type\")({\n input_text: (b) => ({ type: \"input_text\", text: b.text }),\n input_image: (b) => ({\n type: \"input_image\",\n image_url: imageSourceToUrl(b.source),\n }),\n output_text: (b) => ({ type: \"output_text\", text: b.text }),\n refusal: (b) => ({ type: \"refusal\", refusal: b.text }),\n }),\n)\n\nconst itemToInput = (item: HistoryItem): Record<string, unknown> =>\n passthrough(item) ??\n Match.value(item).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m) => ({\n type: \"message\",\n role: m.role,\n content: m.content.map(contentBlockToInput),\n }),\n function_call: (f) => ({\n type: \"function_call\",\n call_id: f.call_id,\n name: f.name,\n arguments: f.arguments,\n }),\n function_call_output: (o) => ({\n type: \"function_call_output\",\n call_id: o.call_id,\n output: o.output,\n }),\n reasoning: (r) => ({\n type: \"reasoning\",\n ...(r.id !== undefined && { id: r.id }),\n ...(r.summary !== undefined && {\n summary: [{ type: \"summary_text\", text: r.summary }],\n }),\n ...(r.signature !== undefined && { encrypted_content: r.signature }),\n }),\n }),\n )\n\n/** Convert our `HistoryItem[]` history into the Responses API `input` array. */\nexport const itemsToInput = (\n items: ReadonlyArray<HistoryItem>,\n): ReadonlyArray<Record<string, unknown>> => items.map(itemToInput)\n\n// ---------------------------------------------------------------------------\n// Wire output items → our Items\n// ---------------------------------------------------------------------------\n\nconst wireMessageContentToBlock = Match.type<typeof WireMessageContent.Type>().pipe(\n Match.discriminatorsExhaustive(\"type\")({\n output_text: (c): ContentBlock => ({\n type: \"output_text\",\n text: c.text,\n ...(c.annotations !== undefined && c.annotations !== null && { annotations: c.annotations }),\n }),\n refusal: (c): ContentBlock => ({ type: \"refusal\", text: c.refusal }),\n }),\n)\n\nexport const wireItemToItem = (wire: WireOutputItem): HistoryItem =>\n Match.value(wire).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m) => ({\n type: \"message\" as const,\n role: m.role,\n content: m.content.map(wireMessageContentToBlock),\n providerData: m,\n }),\n function_call: (f) => ({\n type: \"function_call\" as const,\n call_id: f.call_id,\n name: f.name,\n arguments: f.arguments,\n providerData: f,\n }),\n reasoning: (r) => ({\n type: \"reasoning\" as const,\n ...(r.id !== undefined && { id: r.id }),\n ...(r.summary !== undefined && {\n summary: r.summary.map((s) => s.text).join(\"\\n\"),\n }),\n ...(r.encrypted_content !== undefined && { signature: r.encrypted_content }),\n providerData: r,\n }),\n }),\n )\n\n// ---------------------------------------------------------------------------\n// response.completed → Turn\n// ---------------------------------------------------------------------------\n\nconst reasonToStop = Match.type<string>().pipe(\n Match.when(\"max_output_tokens\", () => \"max_tokens\" as const),\n Match.when(\"refusal\", () => \"refusal\" as const),\n Match.when(\"content_filter\", () => \"content_filter\" as const),\n Match.when(\"max_tool_calls\", () => \"max_tool_calls\" as const),\n Match.option,\n)\n\nconst hasRefusalContent = (payload: WireResponseCompleted): boolean =>\n (payload.output ?? []).some(\n (i) => i.type === \"message\" && i.content.some((c) => c.type === \"refusal\"),\n )\n\nconst stopReasonFromCompleted = (payload: WireResponseCompleted): Turn[\"stop_reason\"] =>\n Option.match(reasonToStop(payload.incomplete_details?.reason ?? \"\"), {\n onSome: (s) => s,\n onNone: () =>\n hasRefusalContent(payload)\n ? (\"refusal\" as const)\n : (payload.output ?? []).some((i) => i.type === \"function_call\")\n ? (\"tool_calls\" as const)\n : (\"stop\" as const),\n })\n\nconst cachedTokens = (payload: WireResponseCompleted): number | undefined =>\n payload.usage?.input_tokens_details?.cached_tokens ?? undefined\n\nconst reasoningTokens = (payload: WireResponseCompleted): number | undefined =>\n payload.usage?.output_tokens_details?.reasoning_tokens ?? undefined\n\nexport const turnFromCompleted = (payload: WireResponseCompleted): Turn => {\n const cached = cachedTokens(payload)\n const reasoning = reasoningTokens(payload)\n return {\n items: (payload.output ?? []).map(wireItemToItem),\n usage: {\n ...(payload.usage?.input_tokens !== undefined && {\n input_tokens: payload.usage.input_tokens,\n }),\n ...(payload.usage?.output_tokens !== undefined && {\n output_tokens: payload.usage.output_tokens,\n }),\n ...(payload.usage?.total_tokens !== undefined && {\n total_tokens: payload.usage.total_tokens,\n }),\n ...(cached !== undefined && {\n input_tokens_details: { cached_tokens: cached },\n }),\n ...(reasoning !== undefined && {\n output_tokens_details: { reasoning_tokens: reasoning },\n }),\n },\n stop_reason: stopReasonFromCompleted(payload),\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"codec.mjs","names":[],"sources":["../src/codec.ts"],"sourcesContent":["import { Encoding, Match, Option, Result, Schema, pipe } from \"effect\"\nimport type { ContentBlock, InputImage, HistoryItem } from \"@effect-uai/core/Items\"\nimport type { Turn } from \"@effect-uai/core/Turn\"\n\n// ---------------------------------------------------------------------------\n// Wire schemas - minimal subset of the Responses API output we consume.\n// Reference: https://www.openresponses.org/specification\n// ---------------------------------------------------------------------------\n\nconst WireUrlCitation = Schema.Struct({\n type: Schema.Literal(\"url_citation\"),\n url: Schema.String,\n start_index: Schema.Number,\n end_index: Schema.Number,\n title: Schema.String,\n})\n\nconst WireFileCitation = Schema.Struct({\n type: Schema.Literal(\"file_citation\"),\n file_id: Schema.String,\n index: Schema.Number,\n})\n\nconst WireContainerFileCitation = Schema.Struct({\n type: Schema.Literal(\"container_file_citation\"),\n container_id: Schema.String,\n file_id: Schema.String,\n start_index: Schema.Number,\n end_index: Schema.Number,\n})\n\nconst WireFilePath = Schema.Struct({\n type: Schema.Literal(\"file_path\"),\n file_id: Schema.String,\n index: Schema.Number,\n})\n\nexport const WireAnnotation = Schema.Union([\n WireUrlCitation,\n WireFileCitation,\n WireContainerFileCitation,\n WireFilePath,\n])\n\nconst WireOutputTextContent = Schema.Struct({\n type: Schema.Literal(\"output_text\"),\n text: Schema.String,\n annotations: Schema.optional(Schema.NullOr(Schema.Array(WireAnnotation))),\n})\n\nconst WireRefusalContent = Schema.Struct({\n type: Schema.Literal(\"refusal\"),\n refusal: Schema.String,\n})\n\nconst WireMessageContent = Schema.Union([WireOutputTextContent, WireRefusalContent])\n\nconst WireSummaryText = Schema.Struct({\n type: Schema.Literal(\"summary_text\"),\n text: Schema.String,\n})\n\nconst WireMessage = Schema.Struct({\n type: Schema.Literal(\"message\"),\n id: Schema.optional(Schema.String),\n role: Schema.Literal(\"assistant\"),\n content: Schema.Array(WireMessageContent),\n})\n\nconst WireFunctionCall = Schema.Struct({\n type: Schema.Literal(\"function_call\"),\n id: Schema.optional(Schema.String),\n call_id: Schema.String,\n name: Schema.String,\n arguments: Schema.String,\n})\n\nconst WireReasoning = Schema.Struct({\n type: Schema.Literal(\"reasoning\"),\n id: Schema.optional(Schema.String),\n summary: Schema.optional(Schema.Array(WireSummaryText)),\n encrypted_content: Schema.optional(Schema.String),\n})\n\n// Provider-hosted tool call items (web search, code interpreter, file search).\n// The provider executes them, not us — we model them only so a grounded\n// `response.completed` still decodes and assembles a Turn; they are dropped\n// from the turn's items in Phase 1. Surfacing them is a follow-up.\nconst WireWebSearchCall = Schema.Struct({\n type: Schema.Literal(\"web_search_call\"),\n id: Schema.optional(Schema.String),\n})\n\nconst WireCodeInterpreterCall = Schema.Struct({\n type: Schema.Literal(\"code_interpreter_call\"),\n id: Schema.optional(Schema.String),\n})\n\nconst WireFileSearchCall = Schema.Struct({\n type: Schema.Literal(\"file_search_call\"),\n id: Schema.optional(Schema.String),\n})\n\nexport const WireOutputItem = Schema.Union([\n WireMessage,\n WireFunctionCall,\n WireReasoning,\n WireWebSearchCall,\n WireCodeInterpreterCall,\n WireFileSearchCall,\n])\nexport type WireOutputItem = typeof WireOutputItem.Type\n\nconst WireInputTokensDetails = Schema.Struct({\n cached_tokens: Schema.optional(Schema.NullOr(Schema.Number)),\n})\n\nconst WireOutputTokensDetails = Schema.Struct({\n reasoning_tokens: Schema.optional(Schema.NullOr(Schema.Number)),\n})\n\nconst WireUsage = Schema.Struct({\n input_tokens: Schema.optional(Schema.Number),\n output_tokens: Schema.optional(Schema.Number),\n total_tokens: Schema.optional(Schema.Number),\n input_tokens_details: Schema.optional(Schema.NullOr(WireInputTokensDetails)),\n output_tokens_details: Schema.optional(Schema.NullOr(WireOutputTokensDetails)),\n})\n\nconst WireResponseError = Schema.Struct({\n code: Schema.optional(Schema.NullOr(Schema.String)),\n message: Schema.optional(Schema.NullOr(Schema.String)),\n})\n\n// Many Responses-API fields are emitted as explicit `null` rather than\n// missing - `Schema.optional` alone (T | undefined) doesn't cover that, so\n// we lift each through `NullOr` first. Used by `response.completed`,\n// `response.incomplete`, and `response.failed` events; not every field is\n// populated on every event (e.g. `error` only on failed, `incomplete_details`\n// only on incomplete).\nexport const WireResponseCompleted = Schema.Struct({\n id: Schema.optional(Schema.NullOr(Schema.String)),\n status: Schema.optional(Schema.NullOr(Schema.String)),\n output: Schema.optional(Schema.NullOr(Schema.Array(WireOutputItem))),\n usage: Schema.optional(Schema.NullOr(WireUsage)),\n incomplete_details: Schema.optional(\n Schema.NullOr(\n Schema.Struct({\n reason: Schema.optional(Schema.NullOr(Schema.String)),\n }),\n ),\n ),\n error: Schema.optional(Schema.NullOr(WireResponseError)),\n})\nexport type WireResponseCompleted = typeof WireResponseCompleted.Type\n\n// ---------------------------------------------------------------------------\n// History → request body input\n// ---------------------------------------------------------------------------\n\n/**\n * The item shapes we stash for round-tripping. Narrower than\n * `WireOutputItem`: the provider-hosted call variants are dropped from the\n * turn, so they are never stored. Composed from the internal `Wire*` structs,\n * which keeps the wire model out of the package's public surface.\n */\nconst StoredItem = Schema.Union([WireMessage, WireFunctionCall, WireReasoning])\ntype StoredItem = typeof StoredItem.Type\n\nconst ProviderDataResponses = Schema.Struct({ responses: StoredItem })\nconst decodeResponsesData = Schema.decodeUnknownResult(ProviderDataResponses)\n\n/**\n * If an item carries `providerData.responses` from a prior turn on this API,\n * re-emit it verbatim - preserves `encrypted_content` and item ids, which a\n * fresh encode from our `HistoryItem` shape cannot reconstruct.\n *\n * Namespaced because `providerData` is a shared slot: an item routed through\n * another provider first (dynamic fallback) carries that provider's key, and\n * re-emitting the whole object would send that provider's data as the wire\n * item and drop the real content. Anything that fails to decode is not ours,\n * so we fall back to encoding the item normally.\n */\nconst passthrough = (item: HistoryItem): StoredItem | undefined =>\n pipe(\n decodeResponsesData(item.providerData),\n Result.match({\n onSuccess: (data) => data.responses,\n onFailure: (): StoredItem | undefined => undefined,\n }),\n )\n\n/**\n * OpenAI's `input_image` content block carries a single `image_url` field;\n * inline bytes get encoded as a `data:` URI. Either form (URL or data URI)\n * is fine - the model just dereferences `image_url`.\n */\nconst imageSourceToUrl = Match.type<InputImage[\"source\"]>().pipe(\n Match.tag(\"url\", (s) => s.url),\n Match.tag(\"base64\", (s) => `data:${s.mimeType};base64,${s.base64}`),\n Match.tag(\"bytes\", (s) => `data:${s.mimeType};base64,${Encoding.encodeBase64(s.bytes)}`),\n Match.exhaustive,\n)\n\nconst contentBlockToInput = Match.type<ContentBlock>().pipe(\n Match.discriminatorsExhaustive(\"type\")({\n input_text: (b) => ({ type: \"input_text\", text: b.text }),\n input_image: (b) => ({\n type: \"input_image\",\n image_url: imageSourceToUrl(b.source),\n }),\n output_text: (b) => ({ type: \"output_text\", text: b.text }),\n refusal: (b) => ({ type: \"refusal\", refusal: b.text }),\n }),\n)\n\nconst itemToInput = (item: HistoryItem): Record<string, unknown> =>\n passthrough(item) ??\n Match.value(item).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m) => ({\n type: \"message\",\n role: m.role,\n content: m.content.map(contentBlockToInput),\n }),\n function_call: (f) => ({\n type: \"function_call\",\n call_id: f.call_id,\n name: f.name,\n arguments: f.arguments,\n }),\n function_call_output: (o) => ({\n type: \"function_call_output\",\n call_id: o.call_id,\n output: o.output,\n }),\n reasoning: (r) => ({\n type: \"reasoning\",\n ...(r.id !== undefined && { id: r.id }),\n ...(r.summary !== undefined && {\n summary: [{ type: \"summary_text\", text: r.summary }],\n }),\n ...(r.signature !== undefined && { encrypted_content: r.signature }),\n }),\n }),\n )\n\n/** Convert our `HistoryItem[]` history into the Responses API `input` array. */\nexport const itemsToInput = (\n items: ReadonlyArray<HistoryItem>,\n): ReadonlyArray<Record<string, unknown>> => items.map(itemToInput)\n\n// ---------------------------------------------------------------------------\n// Wire output items → our Items\n// ---------------------------------------------------------------------------\n\nconst wireMessageContentToBlock = Match.type<typeof WireMessageContent.Type>().pipe(\n Match.discriminatorsExhaustive(\"type\")({\n output_text: (c): ContentBlock => ({\n type: \"output_text\",\n text: c.text,\n ...(c.annotations !== undefined && c.annotations !== null && { annotations: c.annotations }),\n }),\n refusal: (c): ContentBlock => ({ type: \"refusal\", text: c.refusal }),\n }),\n)\n\nexport const wireItemToItem = (wire: WireOutputItem): ReadonlyArray<HistoryItem> =>\n Match.value(wire).pipe(\n Match.discriminatorsExhaustive(\"type\")({\n message: (m): ReadonlyArray<HistoryItem> => [\n {\n type: \"message\" as const,\n role: m.role,\n content: m.content.map(wireMessageContentToBlock),\n providerData: { responses: m },\n },\n ],\n function_call: (f): ReadonlyArray<HistoryItem> => [\n {\n type: \"function_call\" as const,\n call_id: f.call_id,\n name: f.name,\n arguments: f.arguments,\n providerData: { responses: f },\n },\n ],\n reasoning: (r): ReadonlyArray<HistoryItem> => [\n {\n type: \"reasoning\" as const,\n ...(r.id !== undefined && { id: r.id }),\n ...(r.summary !== undefined && {\n summary: r.summary.map((s) => s.text).join(\"\\n\"),\n }),\n ...(r.encrypted_content !== undefined && { signature: r.encrypted_content }),\n providerData: { responses: r },\n },\n ],\n // Hosted-tool calls are provider-executed; drop from the turn (Phase 1).\n web_search_call: (): ReadonlyArray<HistoryItem> => [],\n code_interpreter_call: (): ReadonlyArray<HistoryItem> => [],\n file_search_call: (): ReadonlyArray<HistoryItem> => [],\n }),\n )\n\n// ---------------------------------------------------------------------------\n// response.completed → Turn\n// ---------------------------------------------------------------------------\n\nconst reasonToStop = Match.type<string>().pipe(\n Match.when(\"max_output_tokens\", () => \"max_tokens\" as const),\n Match.when(\"refusal\", () => \"refusal\" as const),\n Match.when(\"content_filter\", () => \"content_filter\" as const),\n Match.when(\"max_tool_calls\", () => \"max_tool_calls\" as const),\n Match.option,\n)\n\nconst hasRefusalContent = (payload: WireResponseCompleted): boolean =>\n (payload.output ?? []).some(\n (i) => i.type === \"message\" && i.content.some((c) => c.type === \"refusal\"),\n )\n\nconst stopReasonFromCompleted = (payload: WireResponseCompleted): Turn[\"stop_reason\"] =>\n Option.match(reasonToStop(payload.incomplete_details?.reason ?? \"\"), {\n onSome: (s) => s,\n onNone: () =>\n hasRefusalContent(payload)\n ? (\"refusal\" as const)\n : (payload.output ?? []).some((i) => i.type === \"function_call\")\n ? (\"tool_calls\" as const)\n : (\"stop\" as const),\n })\n\nconst cachedTokens = (payload: WireResponseCompleted): number | undefined =>\n payload.usage?.input_tokens_details?.cached_tokens ?? undefined\n\nconst reasoningTokens = (payload: WireResponseCompleted): number | undefined =>\n payload.usage?.output_tokens_details?.reasoning_tokens ?? undefined\n\nexport const turnFromCompleted = (payload: WireResponseCompleted): Turn => {\n const cached = cachedTokens(payload)\n const reasoning = reasoningTokens(payload)\n return {\n items: (payload.output ?? []).flatMap(wireItemToItem),\n usage: {\n ...(payload.usage?.input_tokens !== undefined && {\n input_tokens: payload.usage.input_tokens,\n }),\n ...(payload.usage?.output_tokens !== undefined && {\n output_tokens: payload.usage.output_tokens,\n }),\n ...(payload.usage?.total_tokens !== undefined && {\n total_tokens: payload.usage.total_tokens,\n }),\n ...(cached !== undefined && {\n input_tokens_details: { cached_tokens: cached },\n }),\n ...(reasoning !== undefined && {\n output_tokens_details: { reasoning_tokens: reasoning },\n }),\n },\n stop_reason: stopReasonFromCompleted(payload),\n }\n}\n"],"mappings":"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"}