@effect-uai/responses 0.1.0 → 0.3.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.
package/src/codec.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { Match, Option, Schema } from "effect"
2
- import type { ContentBlock, Item } from "@effect-uai/core/Items"
3
- import { matchType } from "@effect-uai/core/Match"
1
+ import { Encoding, Match, Option, Schema } from "effect"
2
+ import type { ContentBlock, InputImage, Item } from "@effect-uai/core/Items"
4
3
  import type { Turn } from "@effect-uai/core/Turn"
5
4
 
6
5
  // ---------------------------------------------------------------------------
@@ -145,48 +144,59 @@ const passthrough = (item: Item): Record<string, unknown> | undefined =>
145
144
  ? (item.providerData as Record<string, unknown>)
146
145
  : undefined
147
146
 
148
- const contentBlockToInput = Match.type<ContentBlock>().pipe(
149
- matchType("input_text", (b) => ({ type: "input_text", text: b.text })),
150
- matchType("input_image", (b) => ({
151
- type: "input_image",
152
- image_url:
153
- b.source._tag === "url"
154
- ? b.source.url
155
- : `data:${b.source.media_type};base64,${b.source.data}`,
156
- })),
157
- matchType("output_text", (b) => ({ type: "output_text", text: b.text })),
158
- matchType("refusal", (b) => ({ type: "refusal", refusal: b.text })),
147
+ /**
148
+ * OpenAI's `input_image` content block carries a single `image_url` field;
149
+ * inline bytes get encoded as a `data:` URI. Either form (URL or data URI)
150
+ * is fine - the model just dereferences `image_url`.
151
+ */
152
+ const imageSourceToUrl = Match.type<InputImage["source"]>().pipe(
153
+ Match.tag("url", (s) => s.url),
154
+ Match.tag("base64", (s) => `data:${s.mimeType};base64,${s.base64}`),
155
+ Match.tag("bytes", (s) => `data:${s.mimeType};base64,${Encoding.encodeBase64(s.bytes)}`),
159
156
  Match.exhaustive,
160
157
  )
161
158
 
159
+ const contentBlockToInput = Match.type<ContentBlock>().pipe(
160
+ Match.discriminatorsExhaustive("type")({
161
+ input_text: (b) => ({ type: "input_text", text: b.text }),
162
+ input_image: (b) => ({
163
+ type: "input_image",
164
+ image_url: imageSourceToUrl(b.source),
165
+ }),
166
+ output_text: (b) => ({ type: "output_text", text: b.text }),
167
+ refusal: (b) => ({ type: "refusal", refusal: b.text }),
168
+ }),
169
+ )
170
+
162
171
  const itemToInput = (item: Item): Record<string, unknown> =>
163
172
  passthrough(item) ??
164
173
  Match.value(item).pipe(
165
- matchType("message", (m) => ({
166
- type: "message",
167
- role: m.role,
168
- content: m.content.map(contentBlockToInput),
169
- })),
170
- matchType("function_call", (f) => ({
171
- type: "function_call",
172
- call_id: f.call_id,
173
- name: f.name,
174
- arguments: f.arguments,
175
- })),
176
- matchType("function_call_output", (o) => ({
177
- type: "function_call_output",
178
- call_id: o.call_id,
179
- output: o.output,
180
- })),
181
- matchType("reasoning", (r) => ({
182
- type: "reasoning",
183
- ...(r.id !== undefined && { id: r.id }),
184
- ...(r.summary !== undefined && {
185
- summary: [{ type: "summary_text", text: r.summary }],
174
+ Match.discriminatorsExhaustive("type")({
175
+ message: (m) => ({
176
+ type: "message",
177
+ role: m.role,
178
+ content: m.content.map(contentBlockToInput),
179
+ }),
180
+ function_call: (f) => ({
181
+ type: "function_call",
182
+ call_id: f.call_id,
183
+ name: f.name,
184
+ arguments: f.arguments,
186
185
  }),
187
- ...(r.signature !== undefined && { encrypted_content: r.signature }),
188
- })),
189
- Match.exhaustive,
186
+ function_call_output: (o) => ({
187
+ type: "function_call_output",
188
+ call_id: o.call_id,
189
+ output: o.output,
190
+ }),
191
+ reasoning: (r) => ({
192
+ type: "reasoning",
193
+ ...(r.id !== undefined && { id: r.id }),
194
+ ...(r.summary !== undefined && {
195
+ summary: [{ type: "summary_text", text: r.summary }],
196
+ }),
197
+ ...(r.signature !== undefined && { encrypted_content: r.signature }),
198
+ }),
199
+ }),
190
200
  )
191
201
 
192
202
  /** Convert our `Item[]` history into the Responses API `input` array. */
@@ -198,43 +208,42 @@ export const itemsToInput = (items: ReadonlyArray<Item>): ReadonlyArray<Record<s
198
208
  // ---------------------------------------------------------------------------
199
209
 
200
210
  const wireMessageContentToBlock = Match.type<typeof WireMessageContent.Type>().pipe(
201
- matchType(
202
- "output_text",
203
- (c): ContentBlock => ({
211
+ Match.discriminatorsExhaustive("type")({
212
+ output_text: (c): ContentBlock => ({
204
213
  type: "output_text",
205
214
  text: c.text,
206
215
  ...(c.annotations !== undefined && c.annotations !== null && { annotations: c.annotations }),
207
216
  }),
208
- ),
209
- matchType("refusal", (c): ContentBlock => ({ type: "refusal", text: c.refusal })),
210
- Match.exhaustive,
217
+ refusal: (c): ContentBlock => ({ type: "refusal", text: c.refusal }),
218
+ }),
211
219
  )
212
220
 
213
221
  export const wireItemToItem = (wire: WireOutputItem): Item =>
214
222
  Match.value(wire).pipe(
215
- matchType("message", (m) => ({
216
- type: "message" as const,
217
- role: m.role,
218
- content: m.content.map(wireMessageContentToBlock),
219
- providerData: m,
220
- })),
221
- matchType("function_call", (f) => ({
222
- type: "function_call" as const,
223
- call_id: f.call_id,
224
- name: f.name,
225
- arguments: f.arguments,
226
- providerData: f,
227
- })),
228
- matchType("reasoning", (r) => ({
229
- type: "reasoning" as const,
230
- ...(r.id !== undefined && { id: r.id }),
231
- ...(r.summary !== undefined && {
232
- summary: r.summary.map((s) => s.text).join("\n"),
223
+ Match.discriminatorsExhaustive("type")({
224
+ message: (m) => ({
225
+ type: "message" as const,
226
+ role: m.role,
227
+ content: m.content.map(wireMessageContentToBlock),
228
+ providerData: m,
229
+ }),
230
+ function_call: (f) => ({
231
+ type: "function_call" as const,
232
+ call_id: f.call_id,
233
+ name: f.name,
234
+ arguments: f.arguments,
235
+ providerData: f,
233
236
  }),
234
- ...(r.encrypted_content !== undefined && { signature: r.encrypted_content }),
235
- providerData: r,
236
- })),
237
- Match.exhaustive,
237
+ reasoning: (r) => ({
238
+ type: "reasoning" as const,
239
+ ...(r.id !== undefined && { id: r.id }),
240
+ ...(r.summary !== undefined && {
241
+ summary: r.summary.map((s) => s.text).join("\n"),
242
+ }),
243
+ ...(r.encrypted_content !== undefined && { signature: r.encrypted_content }),
244
+ providerData: r,
245
+ }),
246
+ }),
238
247
  )
239
248
 
240
249
  // ---------------------------------------------------------------------------
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
- export * from "./Responses.js"
2
- export * from "./models.js"
1
+ export * as Responses from "./Responses.js"
2
+ export * as OpenAIEmbedding from "./OpenAIEmbedding.js"
3
3
  export * as codec from "./codec.js"
4
4
  export * as streamEvents from "./streamEvents.js"
5
+ export * from "./models.js"
package/src/models.ts CHANGED
@@ -22,3 +22,21 @@ export type OpenAIModel =
22
22
  | "gpt-4o-mini"
23
23
  // eslint-disable-next-line @typescript-eslint/ban-types
24
24
  | (string & {})
25
+
26
+ /**
27
+ * Known OpenAI embedding model identifiers. The `-3-` line is still the
28
+ * current general-purpose lineup; `dimensions` parameter supports
29
+ * Matryoshka truncation up to the model's native dimensionality.
30
+ *
31
+ * - `text-embedding-3-small`: 1..1536 dimensions, default 1536
32
+ * - `text-embedding-3-large`: 1..3072 dimensions, default 3072
33
+ * - `text-embedding-ada-002`: legacy, 1536 dim, no Matryoshka
34
+ *
35
+ * Reference: https://developers.openai.com/api/docs/guides/embeddings
36
+ */
37
+ export type OpenAIEmbeddingModel =
38
+ | "text-embedding-3-small"
39
+ | "text-embedding-3-large"
40
+ | "text-embedding-ada-002"
41
+ // eslint-disable-next-line @typescript-eslint/ban-types
42
+ | (string & {})
@@ -1,5 +1,4 @@
1
1
  import { Match, Schema } from "effect"
2
- import { matchType } from "@effect-uai/core/Match"
3
2
  import type { TurnEvent } from "@effect-uai/core/Turn"
4
3
  import { WireOutputItem, WireResponseCompleted, turnFromCompleted } from "./codec.js"
5
4
 
@@ -119,7 +118,7 @@ export type ProviderEvent = typeof ProviderEvent.Type
119
118
  // `call_id` lookup for `function_call_arguments.delta`. The SSE event
120
119
  // references the *item id*, not the call id; we keep a small map populated
121
120
  // from the `output_item.added` events.
122
- export interface CallIdLookup {
121
+ export type CallIdLookup = {
123
122
  readonly resolve: (itemId: string) => string | undefined
124
123
  readonly remember: (itemId: string, callId: string) => void
125
124
  }
@@ -145,55 +144,52 @@ export const eventToDeltas = (
145
144
  lookup: CallIdLookup,
146
145
  ): ReadonlyArray<TurnEvent> =>
147
146
  Match.value(event).pipe(
148
- matchType("response.output_item.added", ({ item }) => {
149
- if (item.type !== "function_call") return []
150
- if (item.id !== undefined) lookup.remember(item.id, item.call_id)
151
- return [
152
- {
153
- type: "tool_call_start" as const,
154
- call_id: item.call_id,
155
- name: item.name,
156
- },
157
- ]
147
+ Match.discriminatorsExhaustive("type")({
148
+ "response.output_item.added": ({ item }) => {
149
+ if (item.type !== "function_call") return []
150
+ if (item.id !== undefined) lookup.remember(item.id, item.call_id)
151
+ return [
152
+ {
153
+ type: "tool_call_start" as const,
154
+ call_id: item.call_id,
155
+ name: item.name,
156
+ },
157
+ ]
158
+ },
159
+ "response.output_text.delta": ({ delta }) => [{ type: "text_delta" as const, text: delta }],
160
+ "response.function_call_arguments.delta": ({ item_id, delta }) => {
161
+ const call_id = lookup.resolve(item_id)
162
+ return call_id === undefined
163
+ ? []
164
+ : [{ type: "tool_call_args_delta" as const, call_id, delta }]
165
+ },
166
+ "response.reasoning_text.delta": ({ delta }) => [
167
+ { type: "reasoning_delta" as const, text: delta, kind: "trace" as const },
168
+ ],
169
+ "response.reasoning_summary_text.delta": ({ delta }) => [
170
+ { type: "reasoning_delta" as const, text: delta, kind: "summary" as const },
171
+ ],
172
+ "response.refusal.delta": ({ delta }) => [{ type: "refusal_delta" as const, text: delta }],
173
+ // Terminal marker for the refusal stream; the deltas already covered
174
+ // the text, so no canonical event is emitted here.
175
+ "response.refusal.done": () => [],
176
+ "response.completed": ({ response }) => [
177
+ { type: "turn_complete" as const, turn: turnFromCompleted(response) },
178
+ ],
179
+ // Incomplete = the model stopped early but produced a usable partial
180
+ // turn (max_tokens, content_filter, max_tool_calls, refusal). Same
181
+ // payload shape as `response.completed`; the stop_reason carries the
182
+ // reason.
183
+ "response.incomplete": ({ response }) => [
184
+ { type: "turn_complete" as const, turn: turnFromCompleted(response) },
185
+ ],
186
+ // Failed and error are surfaced separately as `AiError` by the stream
187
+ // pipeline, not as canonical events.
188
+ "response.failed": () => [],
189
+ error: () => [],
190
+ // No silent drops: unknown wire events flow through `streamNative` but
191
+ // produce no canonical delta. Step 3 (canonical `other` event) replaces
192
+ // this with a forwarded `other` delta on `TurnEvent`.
193
+ _unknown: () => [],
158
194
  }),
159
- matchType("response.output_text.delta", ({ delta }) => [
160
- { type: "text_delta" as const, text: delta },
161
- ]),
162
- matchType("response.function_call_arguments.delta", ({ item_id, delta }) => {
163
- const call_id = lookup.resolve(item_id)
164
- return call_id === undefined
165
- ? []
166
- : [{ type: "tool_call_args_delta" as const, call_id, delta }]
167
- }),
168
- matchType("response.reasoning_text.delta", ({ delta }) => [
169
- { type: "reasoning_delta" as const, text: delta, kind: "trace" as const },
170
- ]),
171
- matchType("response.reasoning_summary_text.delta", ({ delta }) => [
172
- { type: "reasoning_delta" as const, text: delta, kind: "summary" as const },
173
- ]),
174
- matchType("response.refusal.delta", ({ delta }) => [
175
- { type: "refusal_delta" as const, text: delta },
176
- ]),
177
- // Terminal marker for the refusal stream; the deltas already covered
178
- // the text, so no canonical event is emitted here.
179
- matchType("response.refusal.done", () => []),
180
- matchType("response.completed", ({ response }) => [
181
- { type: "turn_complete" as const, turn: turnFromCompleted(response) },
182
- ]),
183
- // Incomplete = the model stopped early but produced a usable partial
184
- // turn (max_tokens, content_filter, max_tool_calls, refusal). Same
185
- // payload shape as `response.completed`; the stop_reason carries the
186
- // reason.
187
- matchType("response.incomplete", ({ response }) => [
188
- { type: "turn_complete" as const, turn: turnFromCompleted(response) },
189
- ]),
190
- // Failed and error are surfaced separately as `AiError` by the stream
191
- // pipeline, not as canonical events.
192
- matchType("response.failed", () => []),
193
- matchType("error", () => []),
194
- // No silent drops: unknown wire events flow through `streamNative` but
195
- // produce no canonical delta. Step 3 (canonical `other` event) replaces
196
- // this with a forwarded `other` delta on `TurnEvent`.
197
- matchType("_unknown", () => []),
198
- Match.exhaustive,
199
195
  )
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/models.ts","../src/streamEvents.ts","../src/Responses.ts","../src/codec.ts"],"mappings":";;;;;;;;;;;;;;;;KAQY,WAAA;AAAA;;;;;;;cC2EC,kBAAA,EAAkB,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmBlB,aAAA,EAAa,MAAA,CAAA,KAAA,WAAA,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAcd,aAAA,UAAuB,aAAA,CAAc,IAAA;AAAA,UAKhC,YAAA;EAAA,SACN,OAAA,GAAU,MAAA;EAAA,SACV,QAAA,GAAW,MAAA,UAAgB,MAAA;AAAA;AAAA,cAGzB,gBAAA,QAAuB,YAAA;;;;;;;cAgBvB,aAAA,GACX,KAAA,EAAO,aAAA,EACP,MAAA,EAAQ,YAAA,KACP,aAAA,CAAc,SAAA;;;UCxHA,gBAAA,SAAyB,IAAA,CAAK,aAAA;;AFjB/C;;;WEsBW,KAAA,EAAO,WAAA;EAAA,SACP,SAAA;IAAA,SAAuB,MAAA;EAAA;EAAA,SACvB,KAAA;EAAA,SACA,kBAAA;EAAA,SACA,YAAA;EAAA,SACA,iBAAA;EAAA,SACA,QAAA,GAAW,QAAA,CAAS,MAAA;EAAA,SACpB,IAAA;EAAA,SACA,gBAAA;EAAA,SACA,cAAA;EAAA,SACA,UAAA;EDuDT;;;;;EAAA,SCjDS,cAAA;IAAA,SAA4B,IAAA;EAAA;;;;;WAK5B,SAAA;AAAA;AAAA,UAGM,gBAAA;;;;;;WAMN,YAAA,GACP,OAAA,EAAS,gBAAA,KACN,MAAA,CAAO,MAAA,CAAO,aAAA,EAAe,OAAA,CAAQ,OAAA;;;;;WAKjC,UAAA,GAAa,OAAA,EAAS,gBAAA,KAAqB,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,OAAA,CAAQ,OAAA;;;;;;WAM5E,WAAA,SACP,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,aAAA,EAAe,CAAA,EAAG,CAAA,MAChC,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,CAAA,EAAG,CAAA;AAAA;AAAA,cAClC,cAAA;;;;;;;cAQY,SAAA,SAAkB,cAAA;AAAA,UAId,MAAA;EAAA,SACN,MAAA,EAAQ,QAAA,CAAS,QAAA;EAAA,SACjB,OAAA;AAAA;;;;;;cAgLE,WAAA,SACX,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,aAAA,EAAe,CAAA,EAAG,CAAA,MAClC,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,CAAA,EAAG,CAAA;;;;cAelB,IAAA,GAAQ,GAAA,EAAK,MAAA,KAAS,MAAA,CAAO,MAAA,CAAO,gBAAA,SAAyB,UAAA,CAAW,UAAA;;;;;;;;cAkBxE,KAAA,GACX,GAAA,EAAK,MAAA,KACJ,KAAA,CAAM,KAAA,CAAM,SAAA,GAAY,aAAA,SAAsB,UAAA,CAAW,UAAA;AAAA;;;cC1N/C,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;;cA+DpD,YAAA,GAAgB,KAAA,EAAO,aAAA,CAAc,IAAA,MAAQ,aAAA,CAAc,MAAA;AAAA,cAoB3D,cAAA,GAAkB,IAAA,EAAM,cAAA,KAAiB,IAAA;AAAA,cA6DzC,iBAAA,GAAqB,OAAA,EAAS,qBAAA,KAAwB,IAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/codec.ts","../src/streamEvents.ts","../src/Responses.ts"],"sourcesContent":["import { Match, Option, Schema } from \"effect\"\nimport type { ContentBlock, Item } from \"@effect-uai/core/Items\"\nimport { matchType } from \"@effect-uai/core/Match\"\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: Item): 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\nconst contentBlockToInput = Match.type<ContentBlock>().pipe(\n matchType(\"input_text\", (b) => ({ type: \"input_text\", text: b.text })),\n matchType(\"input_image\", (b) => ({\n type: \"input_image\",\n image_url:\n b.source._tag === \"url\"\n ? b.source.url\n : `data:${b.source.media_type};base64,${b.source.data}`,\n })),\n matchType(\"output_text\", (b) => ({ type: \"output_text\", text: b.text })),\n matchType(\"refusal\", (b) => ({ type: \"refusal\", refusal: b.text })),\n Match.exhaustive,\n)\n\nconst itemToInput = (item: Item): Record<string, unknown> =>\n passthrough(item) ??\n Match.value(item).pipe(\n matchType(\"message\", (m) => ({\n type: \"message\",\n role: m.role,\n content: m.content.map(contentBlockToInput),\n })),\n matchType(\"function_call\", (f) => ({\n type: \"function_call\",\n call_id: f.call_id,\n name: f.name,\n arguments: f.arguments,\n })),\n matchType(\"function_call_output\", (o) => ({\n type: \"function_call_output\",\n call_id: o.call_id,\n output: o.output,\n })),\n matchType(\"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 Match.exhaustive,\n )\n\n/** Convert our `Item[]` history into the Responses API `input` array. */\nexport const itemsToInput = (items: ReadonlyArray<Item>): ReadonlyArray<Record<string, unknown>> =>\n items.map(itemToInput)\n\n// ---------------------------------------------------------------------------\n// Wire output items → our Items\n// ---------------------------------------------------------------------------\n\nconst wireMessageContentToBlock = Match.type<typeof WireMessageContent.Type>().pipe(\n matchType(\n \"output_text\",\n (c): ContentBlock => ({\n type: \"output_text\",\n text: c.text,\n ...(c.annotations !== undefined && c.annotations !== null && { annotations: c.annotations }),\n }),\n ),\n matchType(\"refusal\", (c): ContentBlock => ({ type: \"refusal\", text: c.refusal })),\n Match.exhaustive,\n)\n\nexport const wireItemToItem = (wire: WireOutputItem): Item =>\n Match.value(wire).pipe(\n matchType(\"message\", (m) => ({\n type: \"message\" as const,\n role: m.role,\n content: m.content.map(wireMessageContentToBlock),\n providerData: m,\n })),\n matchType(\"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 matchType(\"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 Match.exhaustive,\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","import { Match, Schema } from \"effect\"\nimport { matchType } from \"@effect-uai/core/Match\"\nimport type { TurnEvent } from \"@effect-uai/core/Turn\"\nimport { WireOutputItem, WireResponseCompleted, turnFromCompleted } from \"./codec.js\"\n\n// ---------------------------------------------------------------------------\n// Schemas for the SSE event payloads we care about. The Responses API ships\n// many event types; we model only the ones that map to a `TurnEvent`. All\n// others are silently ignored at the dispatch site.\n// ---------------------------------------------------------------------------\n\nconst OutputItemAdded = Schema.Struct({\n type: Schema.Literal(\"response.output_item.added\"),\n item: WireOutputItem,\n})\n\nconst OutputTextDelta = Schema.Struct({\n type: Schema.Literal(\"response.output_text.delta\"),\n delta: Schema.String,\n})\n\nconst FunctionArgsDelta = Schema.Struct({\n type: Schema.Literal(\"response.function_call_arguments.delta\"),\n item_id: Schema.String,\n delta: Schema.String,\n})\n\nconst ReasoningTextDelta = Schema.Struct({\n type: Schema.Literal(\"response.reasoning_text.delta\"),\n delta: Schema.String,\n})\n\nconst ReasoningSummaryDelta = Schema.Struct({\n type: Schema.Literal(\"response.reasoning_summary_text.delta\"),\n delta: Schema.String,\n})\n\nconst RefusalDelta = Schema.Struct({\n type: Schema.Literal(\"response.refusal.delta\"),\n delta: Schema.String,\n})\n\nconst RefusalDone = Schema.Struct({\n type: Schema.Literal(\"response.refusal.done\"),\n refusal: Schema.optional(Schema.String),\n})\n\nconst Completed = Schema.Struct({\n type: Schema.Literal(\"response.completed\"),\n response: WireResponseCompleted,\n})\n\nconst Incomplete = Schema.Struct({\n type: Schema.Literal(\"response.incomplete\"),\n response: WireResponseCompleted,\n})\n\nconst Failed = Schema.Struct({\n type: Schema.Literal(\"response.failed\"),\n response: WireResponseCompleted,\n})\n\nconst ErrorEvent = Schema.Struct({\n type: Schema.Literal(\"error\"),\n message: Schema.optional(Schema.String),\n code: Schema.optional(Schema.String),\n})\n\n/**\n * Catch-all variant for wire events that fail to decode against any known\n * schema, plus events that fail to JSON-parse. The decoder never produces\n * this directly - it's synthesized by `sseEventToProviderEvent` when\n * `decodeKnown` fails.\n */\nconst Unknown = Schema.Struct({\n type: Schema.Literal(\"_unknown\"),\n raw: Schema.Unknown,\n})\n\n/**\n * Internal: union of variants we actually know how to decode from the wire.\n * Used as the decode target; failures are caught and re-emitted as `Unknown`.\n */\nexport const KnownProviderEvent = Schema.Union([\n OutputItemAdded,\n OutputTextDelta,\n FunctionArgsDelta,\n ReasoningTextDelta,\n ReasoningSummaryDelta,\n RefusalDelta,\n RefusalDone,\n Completed,\n Incomplete,\n Failed,\n ErrorEvent,\n])\n\n/**\n * Public: every event the native stream can emit. Discriminated on `type`.\n * The `_unknown` branch closes the cardinality so downstream `Match.exhaustive`\n * cannot silently miss a wire event we didn't model.\n */\nexport const ProviderEvent = Schema.Union([\n OutputItemAdded,\n OutputTextDelta,\n FunctionArgsDelta,\n ReasoningTextDelta,\n ReasoningSummaryDelta,\n RefusalDelta,\n RefusalDone,\n Completed,\n Incomplete,\n Failed,\n ErrorEvent,\n Unknown,\n])\nexport type ProviderEvent = typeof ProviderEvent.Type\n\n// `call_id` lookup for `function_call_arguments.delta`. The SSE event\n// references the *item id*, not the call id; we keep a small map populated\n// from the `output_item.added` events.\nexport interface CallIdLookup {\n readonly resolve: (itemId: string) => string | undefined\n readonly remember: (itemId: string, callId: string) => void\n}\n\nexport const makeCallIdLookup = (): CallIdLookup => {\n const map = new Map<string, string>()\n return {\n resolve: (id) => map.get(id),\n remember: (id, callId) => {\n map.set(id, callId)\n },\n }\n}\n\n/**\n * Translate a decoded provider event into zero-or-more `TurnEvent`s.\n * Mutates `lookup` to record `(item_id → call_id)` from `output_item.added`\n * so subsequent `function_call_arguments.delta` events can be tagged with\n * the right call id.\n */\nexport const eventToDeltas = (\n event: ProviderEvent,\n lookup: CallIdLookup,\n): ReadonlyArray<TurnEvent> =>\n Match.value(event).pipe(\n matchType(\"response.output_item.added\", ({ item }) => {\n if (item.type !== \"function_call\") return []\n if (item.id !== undefined) lookup.remember(item.id, item.call_id)\n return [\n {\n type: \"tool_call_start\" as const,\n call_id: item.call_id,\n name: item.name,\n },\n ]\n }),\n matchType(\"response.output_text.delta\", ({ delta }) => [\n { type: \"text_delta\" as const, text: delta },\n ]),\n matchType(\"response.function_call_arguments.delta\", ({ item_id, delta }) => {\n const call_id = lookup.resolve(item_id)\n return call_id === undefined\n ? []\n : [{ type: \"tool_call_args_delta\" as const, call_id, delta }]\n }),\n matchType(\"response.reasoning_text.delta\", ({ delta }) => [\n { type: \"reasoning_delta\" as const, text: delta, kind: \"trace\" as const },\n ]),\n matchType(\"response.reasoning_summary_text.delta\", ({ delta }) => [\n { type: \"reasoning_delta\" as const, text: delta, kind: \"summary\" as const },\n ]),\n matchType(\"response.refusal.delta\", ({ delta }) => [\n { type: \"refusal_delta\" as const, text: delta },\n ]),\n // Terminal marker for the refusal stream; the deltas already covered\n // the text, so no canonical event is emitted here.\n matchType(\"response.refusal.done\", () => []),\n matchType(\"response.completed\", ({ response }) => [\n { type: \"turn_complete\" as const, turn: turnFromCompleted(response) },\n ]),\n // Incomplete = the model stopped early but produced a usable partial\n // turn (max_tokens, content_filter, max_tool_calls, refusal). Same\n // payload shape as `response.completed`; the stop_reason carries the\n // reason.\n matchType(\"response.incomplete\", ({ response }) => [\n { type: \"turn_complete\" as const, turn: turnFromCompleted(response) },\n ]),\n // Failed and error are surfaced separately as `AiError` by the stream\n // pipeline, not as canonical events.\n matchType(\"response.failed\", () => []),\n matchType(\"error\", () => []),\n // No silent drops: unknown wire events flow through `streamNative` but\n // produce no canonical delta. Step 3 (canonical `other` event) replaces\n // this with a forwarded `other` delta on `TurnEvent`.\n matchType(\"_unknown\", () => []),\n Match.exhaustive,\n )\n","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 { matchType } from \"@effect-uai/core/Match\"\nimport * as StructuredFormat from \"@effect-uai/core/StructuredFormat\"\nimport {\n type CommonRequest,\n LanguageModel,\n type LanguageModelService,\n} from \"@effect-uai/core/LanguageModel\"\nimport * as SSE from \"@effect-uai/core/SSE\"\nimport type { TurnEvent } from \"@effect-uai/core/Turn\"\nimport { itemsToInput } from \"./codec.js\"\nimport type { OpenAIModel } from \"./models.js\"\nimport {\n KnownProviderEvent,\n ProviderEvent,\n eventToDeltas,\n makeCallIdLookup,\n} from \"./streamEvents.js\"\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ResponsesRequest extends 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 interface 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 * 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 interface Config {\n readonly apiKey: Redacted.Redacted\n readonly baseUrl?: string\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 return {\n model: request.model,\n input: itemsToInput(request.history),\n stream: true,\n ...(request.tools !== undefined &&\n request.tools.length > 0 && {\n tools: 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 }),\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 matchType(\n \"error\",\n (e): AiError.AiError => new AiError.Unavailable({ provider: \"responses\", raw: e }),\n ),\n matchType(\"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 Match.option,\n)\n\nconst sseEventToProviderEvent = (ev: SSE.Event): Effect.Effect<ProviderEvent> =>\n Effect.try({\n try: () => JSON.parse(ev.data) as unknown,\n catch: () => ev.data,\n }).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 = `${cfg.baseUrl ?? \"https://api.openai.com/v1\"}/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 return {\n streamNative,\n streamTurn: (request) => toCanonical(streamNative(request)),\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 }),\n ),\n )\n return Layer.merge(typed, generic)\n}\n"],"mappings":"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"}