@yolk-sdk/agent 0.1.0-canary.89 → 0.1.0-canary.90

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/README.md CHANGED
@@ -255,8 +255,10 @@ as zero. Treat snapshots as best-effort; hosts own polling, stale-data policy, p
255
255
  The fetcher blocks redirects and sanitizes failures using the shared subscription-usage error types.
256
256
 
257
257
  Vercel AI Gateway uses its OpenAI-compatible Chat Completions endpoint, with a single JSON
258
- completion by default. Set factory option `streaming: true` for SSE deltas and independently set
259
- `reasoningContent: true` to preserve compatible models' `reasoning_content` output and assistant
258
+ completion by default. Native PDF `DocumentPart` inputs are lowered to Gateway file parts by
259
+ default; the selected Gateway model must advertise PDF input. Set factory option `streaming: true`
260
+ for SSE deltas and independently set `reasoningContent: true` to preserve compatible models'
261
+ `reasoning_content` output and assistant
260
262
  replay. Both default to false; replayed reasoning spends input tokens. Pass either an AI
261
263
  Gateway API key or Vercel OIDC token as `apiKey`; `maxCompletionTokens` is sent as Gateway
262
264
  `max_tokens`. The env-backed `VercelAiGatewayProviderLayer` tries `AI_GATEWAY_API_KEY` first, then
@@ -495,9 +497,17 @@ inside one source fail validation. Hosts own file discovery, storage, enablement
495
497
  - `AudioPart` with `InlineBase64`, `Url`, or host-owned `Ref` source
496
498
 
497
499
  Build sources with `inlineBase64AttachmentSource`, `urlAttachmentSource`, or
498
- `refAttachmentSource`. Providers can pass through supported media URLs: OpenAI Chat and Vercel AI
499
- Gateway support image URLs; OpenAI Codex supports image and document URLs; Anthropic supports image
500
- and PDF URLs. The Grok
500
+ `refAttachmentSource`. OpenAI-compatible Chat Completions providers support inline text documents;
501
+ native PDF `DocumentPart` lowering is opt-in through `supportsPdfAttachments`, while Vercel AI
502
+ Gateway enables it by default (set `supportsPdfAttachments: false` to disable it). For URL-backed
503
+ user-message PDFs, both opted-in generic OpenAI chat and Gateway use the host-provided `HttpClient`
504
+ to fetch and buffer the PDF before sending inline file data; the provider does not fetch the URL.
505
+ Hosts must authorize attachment URLs and enforce destination and redirect policy, streamed-byte
506
+ limits, timeouts, safe logging, and credential isolation so provider credentials are never attached
507
+ to attachment destinations. The SDK resolver does not establish those guarantees. Prefer validated
508
+ inline bytes when the host cannot provide a bounded attachment transport. OpenAI Chat and Vercel AI
509
+ Gateway support image URLs; OpenAI Codex supports image
510
+ and document URLs; Anthropic supports image and PDF URLs. The Grok
501
511
  Responses lowerer can encode image URLs/data URLs, but hosts should enable image capability only for
502
512
  subscription models they have verified accept image input. Use
503
513
  inline base64 for simple apps, durable URLs for app-owned uploads, or persist opaque `Ref` values and
@@ -30,7 +30,8 @@ type OpenAiProviderConfig = {
30
30
  * Request incremental server-sent deltas instead of one JSON body. Hosts
31
31
  * must only enable this against endpoints that serve chat SSE.
32
32
  */
33
- readonly streaming?: boolean; /** Customizes safe error metadata for a branded OpenAI-compatible endpoint. */
33
+ readonly streaming?: boolean; /** Enables native PDF file parts for compatible Chat Completions endpoints. */
34
+ readonly supportsPdfAttachments?: boolean; /** Customizes safe error metadata for a branded OpenAI-compatible endpoint. */
34
35
  readonly providerIdentity?: OpenAiProviderIdentity;
35
36
  readonly apiKey: Redacted.Redacted<string>;
36
37
  };
@@ -44,7 +45,14 @@ type OpenAiImageContentPart = {
44
45
  readonly url: string;
45
46
  };
46
47
  };
47
- type OpenAiUserContent = string | ReadonlyArray<OpenAiTextContentPart | OpenAiImageContentPart>;
48
+ type OpenAiFileContentPart = {
49
+ readonly type: 'file';
50
+ readonly file: {
51
+ readonly filename: string;
52
+ readonly file_data: string;
53
+ };
54
+ };
55
+ type OpenAiUserContent = string | ReadonlyArray<OpenAiTextContentPart | OpenAiImageContentPart | OpenAiFileContentPart>;
48
56
  type OpenAiToolCall = {
49
57
  readonly id: string;
50
58
  readonly type: 'function';
@@ -93,6 +101,7 @@ type OpenAiRequestBody = {
93
101
  readonly tools?: ReadonlyArray<OpenAiTool>;
94
102
  readonly parallel_tool_calls?: true;
95
103
  };
104
+ type ResolvePdfUrl = (url: string) => Effect.Effect<string, LLMError>;
96
105
  type OpenAiRequestBodyConfig = {
97
106
  readonly maxCompletionTokens: number;
98
107
  readonly completionTokenField?: 'max_completion_tokens' | 'max_tokens';
@@ -100,6 +109,8 @@ type OpenAiRequestBodyConfig = {
100
109
  readonly reasoningEffortFormat?: 'reasoning-object' | 'reasoning-effort';
101
110
  readonly reasoningContent?: boolean;
102
111
  readonly streaming?: boolean;
112
+ readonly supportsPdfAttachments?: boolean;
113
+ readonly resolvePdfUrl?: ResolvePdfUrl;
103
114
  readonly providerName?: string;
104
115
  };
105
116
  declare const toOpenAiRequestBody: (request: LLMRequest, config: OpenAiRequestBodyConfig) => Effect.Effect<OpenAiRequestBody, LLMError>;
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.mts","names":[],"sources":["../../../src/providers/openai/provider.ts"],"mappings":";;;;;;;KA6DK,sBAAA;EAAA,SACM,EAAA;EAAA,SACA,IAAI;AAAA;;KAIH,mBAAA;EAAA,UACA,GAAA,WAAc,QAAA,CAAO,IAAI;AAAA;AAAA,KAgJzB,oBAAA;EAAA,SACD,kBAAA;EAAA,SACA,mBAAA,UAlJC;EAAA,SAoJD,oBAAA;EAAA,SACA,YAAA,GAAe,QAAA,CAAS,MAAA;EArJE;AAAA;AAgJrC;;;EAhJqC,SA2J1B,SAAA,GAAY,mBAAA,EANG;EAAA,SAQf,qBAAA,4CASmB;EAAA,SAPnB,gBAAA;EAQyB;;;;EAAA,SAHzB,SAAA,YAfA;EAAA,SAiBA,gBAAA,GAAmB,sBAAA;EAAA,SACnB,MAAA,EAAQ,QAAA,CAAS,QAAA;AAAA;AAAA,KAGvB,qBAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAI;AAAA;AAAA,KAGV,sBAAA;EAAA,SACM,IAAA;EAAA,SACA,SAAA;IAAA,SACE,GAAA;EAAA;AAAA;AAAA,KAIR,iBAAA,YAA6B,aAAA,CAAc,qBAAA,GAAwB,sBAAA;AAAA,KAEnE,cAAA;EAAA,SACM,EAAA;EAAA,SACA,IAAA;EAAA,SACA,QAAA;IAAA,SACE,IAAA;IAAA,SACA,SAAA;EAAA;AAAA;AAAA,KAIR,aAAA;EAAA,SACU,IAAA;EAAA,SAAyB,OAAA;AAAA;EAAA,SACzB,IAAA;EAAA,SAAuB,OAAA,EAAS,iBAAA;AAAA;EAAA,SAEhC,IAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA,GAAa,aAAA,CAAc,cAAA;EAAA,SAC3B,iBAAA;AAAA;EAAA,SAEA,IAAA;EAAA,SAAuB,YAAA;EAAA,SAA+B,OAAA;AAAA;AAAA,KAEhE,UAAA;EAAA,SACM,IAAA;EAAA,SACA,QAAA;IAAA,SACE,IAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA,EAAY,QAAA,CAAO,IAAI;EAAA;AAAA;AAAA,KAI/B,iBAAA;EAAA,SACM,KAAA;EAAA,SACA,QAAA,EAAU,aAAA,CAAc,aAAA;EAAA,SACxB,qBAAA;EAAA,SACA,UAAA;EAAA,SACA,MAAA;EAAA,SACA,cAAA;IAAA,SACE,aAAA;EAAA;EAAA,SAEF,SAAA;IAAA,SACE,MAAA,EAAQ,oBAAA;EAAA;EAAA,SAEV,gBAAA,GAAmB,oBAAA;EAAA,SACnB,KAAA,GAAQ,aAAA,CAAc,UAAA;EAAA,SACtB,mBAAA;AAAA;AAAA,KAGN,uBAAA;EAAA,SACM,mBAAA;EAAA,SACA,oBAAA;EAAA,SACA,SAAA;EAAA,SACA,qBAAA;EAAA,SACA,gBAAA;EAAA,SACA,SAAA;EAAA,SACA,YAAA;AAAA;AAAA,cA+aE,mBAAA,GACX,OAAA,EAAS,UAAA,EACT,MAAA,EAAQ,uBAAA,KACP,MAAA,CAAO,MAAA,CAAO,iBAAA,EAAmB,QAAA;AAAA,cAuzBvB,uBAAA,GAA2B,MAAA,EAAQ,oBAAA,KAAoB,KAAA,CAAA,KAAA,CAAA,WAAA,SAAA,UAAA,CAAA,UAAA;AAAA,cAYvD,mBAAA,EAAmB,KAAA,CAAA,KAAA,CAAA,WAAA,EAAA,QAAA"}
1
+ {"version":3,"file":"provider.d.mts","names":[],"sources":["../../../src/providers/openai/provider.ts"],"mappings":";;;;;;;KA8DK,sBAAA;EAAA,SACM,EAAA;EAAA,SACA,IAAI;AAAA;;KAIH,mBAAA;EAAA,UACA,GAAA,WAAc,QAAA,CAAO,IAAI;AAAA;AAAA,KAgJzB,oBAAA;EAAA,SACD,kBAAA;EAAA,SACA,mBAAA,UAlJC;EAAA,SAoJD,oBAAA;EAAA,SACA,YAAA,GAAe,QAAA,CAAS,MAAA;EArJE;AAAA;AAgJrC;;;EAhJqC,SA2J1B,SAAA,GAAY,mBAAA,EANG;EAAA,SAQf,qBAAA,4CAWmB;EAAA,SATnB,gBAAA;EAUyB;;;;EAAA,SALzB,SAAA,YAfA;EAAA,SAiBA,sBAAA,YAjBwB;EAAA,SAmBxB,gBAAA,GAAmB,sBAAA;EAAA,SACnB,MAAA,EAAQ,QAAA,CAAS,QAAA;AAAA;AAAA,KAGvB,qBAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAI;AAAA;AAAA,KAGV,sBAAA;EAAA,SACM,IAAA;EAAA,SACA,SAAA;IAAA,SACE,GAAA;EAAA;AAAA;AAAA,KAIR,qBAAA;EAAA,SACM,IAAA;EAAA,SACA,IAAA;IAAA,SACE,QAAA;IAAA,SACA,SAAA;EAAA;AAAA;AAAA,KAIR,iBAAA,YAED,aAAA,CAAc,qBAAA,GAAwB,sBAAA,GAAyB,qBAAA;AAAA,KAE9D,cAAA;EAAA,SACM,EAAA;EAAA,SACA,IAAA;EAAA,SACA,QAAA;IAAA,SACE,IAAA;IAAA,SACA,SAAA;EAAA;AAAA;AAAA,KAIR,aAAA;EAAA,SACU,IAAA;EAAA,SAAyB,OAAA;AAAA;EAAA,SACzB,IAAA;EAAA,SAAuB,OAAA,EAAS,iBAAA;AAAA;EAAA,SAEhC,IAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA,GAAa,aAAA,CAAc,cAAA;EAAA,SAC3B,iBAAA;AAAA;EAAA,SAEA,IAAA;EAAA,SAAuB,YAAA;EAAA,SAA+B,OAAA;AAAA;AAAA,KAEhE,UAAA;EAAA,SACM,IAAA;EAAA,SACA,QAAA;IAAA,SACE,IAAA;IAAA,SACA,WAAA;IAAA,SACA,UAAA,EAAY,QAAA,CAAO,IAAI;EAAA;AAAA;AAAA,KAI/B,iBAAA;EAAA,SACM,KAAA;EAAA,SACA,QAAA,EAAU,aAAA,CAAc,aAAA;EAAA,SACxB,qBAAA;EAAA,SACA,UAAA;EAAA,SACA,MAAA;EAAA,SACA,cAAA;IAAA,SACE,aAAA;EAAA;EAAA,SAEF,SAAA;IAAA,SACE,MAAA,EAAQ,oBAAA;EAAA;EAAA,SAEV,gBAAA,GAAmB,oBAAA;EAAA,SACnB,KAAA,GAAQ,aAAA,CAAc,UAAA;EAAA,SACtB,mBAAA;AAAA;AAAA,KAGN,aAAA,IAAiB,GAAA,aAAgB,MAAA,CAAO,MAAM,SAAS,QAAA;AAAA,KAEvD,uBAAA;EAAA,SACM,mBAAA;EAAA,SACA,oBAAA;EAAA,SACA,SAAA;EAAA,SACA,qBAAA;EAAA,SACA,gBAAA;EAAA,SACA,SAAA;EAAA,SACA,sBAAA;EAAA,SACA,aAAA,GAAgB,aAAa;EAAA,SAC7B,YAAA;AAAA;AAAA,cA8dE,mBAAA,GACX,OAAA,EAAS,UAAA,EACT,MAAA,EAAQ,uBAAA,KACP,MAAA,CAAO,MAAA,CAAO,iBAAA,EAAmB,QAAA;AAAA,cAw3BvB,uBAAA,GAA2B,MAAA,EAAQ,oBAAA,KAAoB,KAAA,CAAA,KAAA,CAAA,WAAA,SAAA,UAAA,CAAA,UAAA;AAAA,cAYvD,mBAAA,EAAmB,KAAA,CAAA,KAAA,CAAA,WAAA,EAAA,QAAA"}
@@ -1,6 +1,6 @@
1
1
  import { classifyProviderFailure, providerErrorInfo, providerFailureCause, providerFailureRetryable } from "../provider-error.mjs";
2
2
  import { validateProviderTranscript } from "../transcript.mjs";
3
- import { Config, Context, Effect, Layer, Match, Option, Predicate, Redacted, Ref, Stream } from "effect";
3
+ import { Config, Context, Effect, Encoding, Layer, Match, Option, Predicate, Redacted, Ref, Stream } from "effect";
4
4
  import { AgentInputUsage, AgentOutputUsage, AgentUsage, ProviderStreamDiagnostics, ToolCall, assistantContent, assistantHostToolCalls, assistantReasoningText, attachmentSourceText, attachmentSourceUrl, isTextDocumentMimeType, messageContextText, prependMessageContextToContent, replaceLoneSurrogatesDeep } from "@yolk-sdk/agent/protocol";
5
5
  import * as Schema$1 from "effect/Schema";
6
6
  import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
@@ -217,7 +217,15 @@ const textDocumentToOpenAiPart = (part, providerName) => attachmentSourceText(pa
217
217
  return Effect.succeed(block);
218
218
  }
219
219
  })));
220
- const contentPartToUserPart = (part, providerName) => Match.value(part).pipe(Match.tag("Text", (current) => Effect.succeed({
220
+ const pdfDocumentToOpenAiPart = (part, providerName, resolvePdfUrl) => Match.value(part.source).pipe(Match.tag("InlineBase64", (source) => Effect.succeed(`data:${part.mimeType};base64,${source.data}`)), Match.tag("Url", (source) => resolvePdfUrl === void 0 ? Effect.fail(unsupportedContentError("Unresolved document source", providerName)) : resolvePdfUrl(source.url)), Match.tag("Ref", () => Effect.fail(unsupportedContentError("Unresolved document source", providerName))), Match.exhaustive, Effect.map((fileData) => ({
221
+ type: "file",
222
+ file: {
223
+ filename: part.filename,
224
+ file_data: fileData
225
+ }
226
+ })));
227
+ const normalizedMimeType = (mimeType) => mimeType.split(";", 1)[0]?.trim().toLowerCase() ?? "";
228
+ const contentPartToUserPart = (part, providerName, supportsPdfAttachments, resolvePdfUrl) => Match.value(part).pipe(Match.tag("Text", (current) => Effect.succeed({
221
229
  type: "text",
222
230
  text: current.text
223
231
  })), Match.tag("Image", (current) => Option.match(attachmentSourceUrl(current.source, current.mimeType), {
@@ -226,8 +234,8 @@ const contentPartToUserPart = (part, providerName) => Match.value(part).pipe(Mat
226
234
  type: "image_url",
227
235
  image_url: { url }
228
236
  })
229
- })), Match.tag("Document", (current) => isTextDocumentMimeType(current.mimeType) ? textDocumentToOpenAiPart(current, providerName) : Effect.fail(unsupportedContentError("Document", providerName))), Match.tag("Audio", () => Effect.fail(unsupportedContentError("Audio", providerName))), Match.exhaustive);
230
- const contentToUserContent = (content, providerName) => Predicate.isString(content) ? Effect.succeed(content) : Effect.forEach(content, (part) => contentPartToUserPart(part, providerName));
237
+ })), Match.tag("Document", (current) => isTextDocumentMimeType(current.mimeType) ? textDocumentToOpenAiPart(current, providerName) : supportsPdfAttachments && normalizedMimeType(current.mimeType) === "application/pdf" ? pdfDocumentToOpenAiPart(current, providerName, resolvePdfUrl) : Effect.fail(unsupportedContentError("Document", providerName))), Match.tag("Audio", () => Effect.fail(unsupportedContentError("Audio", providerName))), Match.exhaustive);
238
+ const contentToUserContent = (content, providerName, supportsPdfAttachments, resolvePdfUrl) => Predicate.isString(content) ? Effect.succeed(content) : Effect.forEach(content, (part) => contentPartToUserPart(part, providerName, supportsPdfAttachments, resolvePdfUrl));
231
239
  const contentPartToText = (part, owner, providerName) => Match.value(part).pipe(Match.tag("Text", (current) => Effect.succeed(current.text)), Match.tag("Image", () => Effect.fail(unsupportedContentError(`${owner} image`, providerName))), Match.tag("Document", () => Effect.fail(unsupportedContentError(`${owner} document`, providerName))), Match.tag("Audio", () => Effect.fail(unsupportedContentError(`${owner} audio`, providerName))), Match.exhaustive);
232
240
  const contentToText = (content, owner, providerName) => Predicate.isString(content) ? Effect.succeed(content) : Effect.forEach(content, (part) => contentPartToText(part, owner, providerName)).pipe(Effect.map((textParts) => textParts.join("\n")));
233
241
  const serializeToolArguments = (call, providerName) => Schema$1.decodeUnknownEffect(Schema$1.Json)(call.params).pipe(Effect.mapError(schemaErrorToLlmError("provider_error", `Could not serialize ${providerName} tool arguments`)), Effect.flatMap((json) => encodeJsonString(json, `Could not serialize ${providerName} tool arguments`)));
@@ -241,7 +249,7 @@ const toolCallToOpenAiToolCall = (call, providerName) => Effect.gen(function* ()
241
249
  }
242
250
  };
243
251
  });
244
- const toOpenAiMessage = (message, providerName, reasoningContent) => Match.value(message).pipe(Match.withReturnType(), Match.tag("User", (current) => contentToUserContent(prependMessageContextToContent(current.content, messageContextText(current)), providerName).pipe(Effect.map((content) => ({
252
+ const toOpenAiMessage = (message, providerName, reasoningContent, supportsPdfAttachments, resolvePdfUrl) => Match.value(message).pipe(Match.withReturnType(), Match.tag("User", (current) => contentToUserContent(prependMessageContextToContent(current.content, messageContextText(current)), providerName, supportsPdfAttachments, resolvePdfUrl).pipe(Effect.map((content) => ({
245
253
  role: "user",
246
254
  content
247
255
  })))), Match.tag("Assistant", (current) => {
@@ -282,7 +290,7 @@ const toOpenAiRequestBody = (request, config) => Effect.gen(function* () {
282
290
  const messages = [{
283
291
  role: "system",
284
292
  content: request.systemPrompt
285
- }, ...yield* Effect.forEach(request.messages, (message) => toOpenAiMessage(message, providerName, config.reasoningContent ?? false))];
293
+ }, ...yield* Effect.forEach(request.messages, (message) => toOpenAiMessage(message, providerName, config.reasoningContent ?? false, config.supportsPdfAttachments ?? false, config.resolvePdfUrl))];
286
294
  const completionTokenLimit = config.completionTokenField === "max_tokens" ? { max_tokens: config.maxCompletionTokens } : { max_completion_tokens: config.maxCompletionTokens };
287
295
  const reasoning = request.reasoningEffort === void 0 ? {} : config.reasoningEffortFormat === "reasoning-object" ? { reasoning: { effort: request.reasoningEffort } } : config.reasoningEffortFormat === "reasoning-effort" ? { reasoning_effort: request.reasoningEffort } : {};
288
296
  const extraBody = config.extraBody === void 0 ? {} : yield* snapshotOpenAiRequestExtras(config.extraBody, config, providerName);
@@ -598,7 +606,7 @@ const parseOpenAiResponseJson = (response, providerName) => Effect.gen(function*
598
606
  })));
599
607
  return yield* Schema$1.decodeUnknownEffect(Schema$1.Json)(raw).pipe(Effect.mapError(schemaErrorToLlmError("invalid_response", `Could not parse ${providerName} response JSON`)));
600
608
  });
601
- const openAiRequestBodyFields = (config, providerIdentity) => {
609
+ const openAiRequestBodyFields = (config, providerIdentity, resolvePdfUrl) => {
602
610
  const fields = {
603
611
  maxCompletionTokens: config.maxCompletionTokens,
604
612
  providerName: providerIdentity.name
@@ -608,6 +616,8 @@ const openAiRequestBodyFields = (config, providerIdentity) => {
608
616
  if (config.reasoningEffortFormat !== void 0) fields.reasoningEffortFormat = config.reasoningEffortFormat;
609
617
  if (config.reasoningContent !== void 0) fields.reasoningContent = config.reasoningContent;
610
618
  if (config.streaming !== void 0) fields.streaming = config.streaming;
619
+ if (config.supportsPdfAttachments !== void 0) fields.supportsPdfAttachments = config.supportsPdfAttachments;
620
+ if (resolvePdfUrl !== void 0) fields.resolvePdfUrl = resolvePdfUrl;
611
621
  return fields;
612
622
  };
613
623
  const serializeOpenAiRequestBody = (body, providerName) => Schema$1.decodeUnknownEffect(Schema$1.Json)(replaceLoneSurrogatesDeep(body)).pipe(Effect.mapError(schemaErrorToLlmError("provider_error", `Could not serialize ${providerName} request`)), Effect.flatMap((json) => encodeJsonString(json, `Could not serialize ${providerName} request`)));
@@ -642,12 +652,29 @@ const postOpenAiRequest = (config, providerIdentity, serializedBody, client) =>
642
652
  }
643
653
  return response;
644
654
  });
645
- const sendOpenAiRequestBody = (config, request, providerIdentity) => Effect.gen(function* () {
646
- return yield* serializeOpenAiRequestBody(yield* toOpenAiRequestBody(request, openAiRequestBodyFields(config, providerIdentity)), providerIdentity.name);
655
+ const pdfDataUrlFromResponse = (response, providerName) => {
656
+ if (response.status < 200 || response.status >= 300) return Effect.fail(new LLMError({
657
+ cause: "provider_error",
658
+ message: `Could not fetch PDF attachment for ${providerName}: returned ${response.status}`,
659
+ retryable: false
660
+ }));
661
+ return response.arrayBuffer.pipe(Effect.mapError((error) => new LLMError({
662
+ cause: "provider_error",
663
+ message: `Could not read PDF attachment for ${providerName}: ${error.message}`,
664
+ retryable: false
665
+ })), Effect.map((bytes) => `data:application/pdf;base64,${Encoding.encodeBase64(new Uint8Array(bytes))}`));
666
+ };
667
+ const pdfUrlResolver = (client, providerName) => (url) => client.get(url).pipe(Effect.mapError((error) => new LLMError({
668
+ cause: "provider_error",
669
+ message: `Could not fetch PDF attachment for ${providerName}: ${error.message}`,
670
+ retryable: false
671
+ })), Effect.flatMap((response) => pdfDataUrlFromResponse(response, providerName)));
672
+ const sendOpenAiRequestBody = (config, request, providerIdentity, client) => Effect.gen(function* () {
673
+ return yield* serializeOpenAiRequestBody(yield* toOpenAiRequestBody(request, openAiRequestBodyFields(config, providerIdentity, config.supportsPdfAttachments === true ? pdfUrlResolver(client, providerIdentity.name) : void 0)), providerIdentity.name);
647
674
  });
648
675
  const sendOpenAiRequest = (config, request, client) => Effect.gen(function* () {
649
676
  const providerIdentity = config.providerIdentity ?? defaultOpenAiProviderIdentity;
650
- const json = yield* parseOpenAiResponseJson(yield* postOpenAiRequest(config, providerIdentity, yield* sendOpenAiRequestBody(config, request, providerIdentity), client), providerIdentity.name);
677
+ const json = yield* parseOpenAiResponseJson(yield* postOpenAiRequest(config, providerIdentity, yield* sendOpenAiRequestBody(config, request, providerIdentity, client), client), providerIdentity.name);
651
678
  const parsed = yield* Schema$1.decodeUnknownEffect(OpenAiChatCompletionResponse)(json).pipe(Effect.mapError(schemaErrorToLlmError("invalid_response", `Invalid ${providerIdentity.name} response`)));
652
679
  const choice = parsed.choices[0];
653
680
  if (choice === void 0) return yield* Effect.fail(new LLMError({
@@ -661,7 +688,7 @@ const sendOpenAiRequest = (config, request, client) => Effect.gen(function* () {
661
688
  }).pipe(Effect.withSpan(`${config.providerIdentity?.id ?? defaultOpenAiProviderIdentity.id}.stream`));
662
689
  const streamOpenAiRequest = (config, request, client) => Stream.unwrap(Effect.gen(function* () {
663
690
  const providerIdentity = config.providerIdentity ?? defaultOpenAiProviderIdentity;
664
- const response = yield* postOpenAiRequest(config, providerIdentity, yield* sendOpenAiRequestBody(config, request, providerIdentity), client);
691
+ const response = yield* postOpenAiRequest(config, providerIdentity, yield* sendOpenAiRequestBody(config, request, providerIdentity, client), client);
665
692
  const responseFormat = yield* expectChatSseResponse(providerIdentity, response);
666
693
  return streamOpenAiChatResponse(providerIdentity, config.reasoningContent ?? false, responseFormat, response);
667
694
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"provider.mjs","names":["Schema","LLMReasoningDelta","LLMTextDelta"],"sources":["../../../src/providers/openai/provider.ts"],"sourcesContent":["import {\n Config,\n Context,\n Effect,\n Layer,\n Match,\n Option,\n Predicate,\n Redacted,\n Ref,\n Stream\n} from 'effect'\nimport {\n FetchHttpClient,\n HttpClient,\n HttpClientRequest,\n type HttpClientError,\n type HttpClientResponse\n} from 'effect/unstable/http'\nimport * as Schema from 'effect/Schema'\nimport {\n ToolCall,\n AgentInputUsage,\n AgentOutputUsage,\n AgentUsage,\n ProviderStreamDiagnostics,\n attachmentSourceText,\n attachmentSourceUrl,\n assistantContent,\n assistantHostToolCalls,\n assistantReasoningText,\n isTextDocumentMimeType,\n messageContextText,\n replaceLoneSurrogatesDeep,\n prependMessageContextToContent,\n type AgentMessage,\n type AgentReasoningEffort,\n type Content,\n type ContentPart,\n type ProviderStreamResponseFormat,\n type ToolDef\n} from '@yolk-sdk/agent/protocol'\nimport {\n LLMError,\n LLMDone,\n LLMProvider,\n LLMReasoningDelta,\n LLMTextDelta,\n LLMToolCall,\n LLMUsage,\n type LLMEvent,\n type LLMRequest\n} from '@yolk-sdk/agent/loop'\nimport {\n classifyProviderFailure,\n providerErrorInfo,\n providerFailureCause,\n providerFailureRetryable\n} from '../provider-error.ts'\nimport { validateProviderTranscript } from '../transcript.ts'\n\ntype OpenAiProviderIdentity = {\n readonly id: string\n readonly name: string\n}\n\n/** Chat Completions extras input; lowering admits a portable JSON-object snapshot. */\nexport type OpenAiRequestExtras = {\n readonly [key: string]: Schema.Json\n}\n\nconst isPlainObject = (value: object) => {\n const proto = Object.getPrototypeOf(value)\n\n return proto === Object.prototype || proto === null\n}\n\nconst isDataPropertyDescriptor = (descriptor: PropertyDescriptor) =>\n descriptor.enumerable === true && Object.hasOwn(descriptor, 'value')\n\nconst snapshotFailed = Option.none<Schema.Json>()\n\nconst snapshotPortableJson = (\n value: unknown,\n stack: Set<object>,\n memo: Map<object, Schema.Json>\n): Option.Option<Schema.Json> => {\n if (value === null || Predicate.isString(value) || Predicate.isBoolean(value)) {\n return Option.some(value)\n }\n\n if (Predicate.isNumber(value)) {\n return Number.isFinite(value) ? Option.some(value) : snapshotFailed\n }\n\n if (!Predicate.isObjectOrArray(value)) {\n return snapshotFailed\n }\n\n if (stack.has(value)) {\n return snapshotFailed\n }\n\n const memoized = memo.get(value)\n\n if (memoized !== undefined) {\n return Option.some(memoized)\n }\n\n stack.add(value)\n\n if (Array.isArray(value)) {\n if (\n Object.getPrototypeOf(value) !== Array.prototype ||\n Object.getOwnPropertySymbols(value).length !== 0 ||\n Object.getOwnPropertyNames(value).length !== value.length + 1\n ) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const items: Array<Schema.Json> = []\n\n for (let index = 0; index < value.length; index++) {\n const descriptor = Object.getOwnPropertyDescriptor(value, index)\n\n if (descriptor === undefined || !isDataPropertyDescriptor(descriptor)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const item = snapshotPortableJson(descriptor.value, stack, memo)\n\n if (Option.isNone(item)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n items.push(item.value)\n }\n\n stack.delete(value)\n memo.set(value, items)\n\n return Option.some(items)\n }\n\n if (!isPlainObject(value)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const keys = Object.keys(value)\n\n if (\n Object.getOwnPropertySymbols(value).length !== 0 ||\n Object.getOwnPropertyNames(value).length !== keys.length\n ) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const snapshot: { [key: string]: Schema.Json } = {}\n\n Object.setPrototypeOf(snapshot, null)\n\n for (const key of keys) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key)\n\n if (descriptor === undefined || !isDataPropertyDescriptor(descriptor)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const field = snapshotPortableJson(descriptor.value, stack, memo)\n\n if (Option.isNone(field)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n Object.defineProperty(snapshot, key, {\n value: field.value,\n enumerable: true,\n writable: true,\n configurable: true\n })\n }\n\n stack.delete(value)\n memo.set(value, snapshot)\n\n return Option.some(snapshot)\n}\n\nconst openAiCanonicalRequestKeys = new Set([\n 'model',\n 'messages',\n 'stream',\n 'tools',\n 'parallel_tool_calls',\n 'max_completion_tokens',\n 'max_tokens'\n])\n\nexport type OpenAiProviderConfig = {\n readonly chatCompletionsUrl?: string\n readonly maxCompletionTokens: number\n /** Selects the compatible endpoint's output-limit parameter. Defaults to `max_completion_tokens`. */\n readonly completionTokenField?: 'max_completion_tokens' | 'max_tokens'\n readonly extraHeaders?: Readonly<Record<string, string>>\n /**\n * Admitted portable JSON-object extras. Runtime still snapshots and validates\n * untyped input. Canonical model/messages/limit/stream/tools keys are omitted\n * without reading values.\n */\n readonly extraBody?: OpenAiRequestExtras\n /** Opts into a compatible endpoint's reasoning object or reasoning_effort request field. */\n readonly reasoningEffortFormat?: 'reasoning-object' | 'reasoning-effort'\n /** Preserve compatible models' reasoning_content output and assistant replay. */\n readonly reasoningContent?: boolean\n /**\n * Request incremental server-sent deltas instead of one JSON body. Hosts\n * must only enable this against endpoints that serve chat SSE.\n */\n readonly streaming?: boolean\n /** Customizes safe error metadata for a branded OpenAI-compatible endpoint. */\n readonly providerIdentity?: OpenAiProviderIdentity\n readonly apiKey: Redacted.Redacted<string>\n}\n\ntype OpenAiTextContentPart = {\n readonly type: 'text'\n readonly text: string\n}\n\ntype OpenAiImageContentPart = {\n readonly type: 'image_url'\n readonly image_url: {\n readonly url: string\n }\n}\n\ntype OpenAiUserContent = string | ReadonlyArray<OpenAiTextContentPart | OpenAiImageContentPart>\n\ntype OpenAiToolCall = {\n readonly id: string\n readonly type: 'function'\n readonly function: {\n readonly name: string\n readonly arguments: string\n }\n}\n\ntype OpenAiMessage =\n | { readonly role: 'system'; readonly content: string }\n | { readonly role: 'user'; readonly content: OpenAiUserContent }\n | {\n readonly role: 'assistant'\n readonly content: string | null\n readonly tool_calls?: ReadonlyArray<OpenAiToolCall>\n readonly reasoning_content?: string\n }\n | { readonly role: 'tool'; readonly tool_call_id: string; readonly content: string }\n\ntype OpenAiTool = {\n readonly type: 'function'\n readonly function: {\n readonly name: string\n readonly description: string\n readonly parameters: Schema.Json\n }\n}\n\ntype OpenAiRequestBody = {\n readonly model: string\n readonly messages: ReadonlyArray<OpenAiMessage>\n readonly max_completion_tokens?: number\n readonly max_tokens?: number\n readonly stream: boolean\n readonly stream_options?: {\n readonly include_usage: boolean\n }\n readonly reasoning?: {\n readonly effort: AgentReasoningEffort\n }\n readonly reasoning_effort?: AgentReasoningEffort\n readonly tools?: ReadonlyArray<OpenAiTool>\n readonly parallel_tool_calls?: true\n}\n\ntype OpenAiRequestBodyConfig = {\n readonly maxCompletionTokens: number\n readonly completionTokenField?: 'max_completion_tokens' | 'max_tokens'\n readonly extraBody?: unknown\n readonly reasoningEffortFormat?: 'reasoning-object' | 'reasoning-effort'\n readonly reasoningContent?: boolean\n readonly streaming?: boolean\n readonly providerName?: string\n}\n\ntype OpenAiRequestBodyConfigFields = {\n maxCompletionTokens: number\n providerName: string\n completionTokenField?: OpenAiRequestBodyConfig['completionTokenField']\n extraBody?: OpenAiRequestBodyConfig['extraBody']\n reasoningEffortFormat?: OpenAiRequestBodyConfig['reasoningEffortFormat']\n reasoningContent?: boolean\n streaming?: boolean\n}\n\nconst defaultOpenAiProviderIdentity: OpenAiProviderIdentity = {\n id: 'openai',\n name: 'OpenAI'\n}\n\nclass OpenAiFunctionResponse extends Schema.Class<OpenAiFunctionResponse>('OpenAiFunctionResponse')(\n {\n name: Schema.String,\n arguments: Schema.String\n }\n) {}\n\nclass OpenAiToolCallResponse extends Schema.Class<OpenAiToolCallResponse>('OpenAiToolCallResponse')(\n {\n id: Schema.String,\n type: Schema.Literals(['function']),\n function: OpenAiFunctionResponse\n }\n) {}\n\nclass OpenAiMessageResponse extends Schema.Class<OpenAiMessageResponse>('OpenAiMessageResponse')({\n content: Schema.NullOr(Schema.String),\n reasoning_content: Schema.optional(Schema.Unknown),\n // See OpenAiChatDelta: normalized `reasoning` alias for thinking output.\n reasoning: Schema.optional(Schema.Unknown),\n tool_calls: Schema.optional(Schema.Array(OpenAiToolCallResponse))\n}) {}\n\nclass OpenAiChoiceResponse extends Schema.Class<OpenAiChoiceResponse>('OpenAiChoiceResponse')({\n message: OpenAiMessageResponse,\n finish_reason: Schema.optional(Schema.NullOr(Schema.String))\n}) {}\n\nclass OpenAiPromptTokensDetails extends Schema.Class<OpenAiPromptTokensDetails>(\n 'OpenAiPromptTokensDetails'\n)({\n cached_tokens: Schema.optional(Schema.Number)\n}) {}\n\nclass OpenAiCompletionTokensDetails extends Schema.Class<OpenAiCompletionTokensDetails>(\n 'OpenAiCompletionTokensDetails'\n)({\n reasoning_tokens: Schema.optional(Schema.Number)\n}) {}\n\nclass OpenAiUsageResponse extends Schema.Class<OpenAiUsageResponse>('OpenAiUsageResponse')({\n prompt_tokens: Schema.Number,\n completion_tokens: Schema.Number,\n prompt_tokens_details: Schema.optional(OpenAiPromptTokensDetails),\n completion_tokens_details: Schema.optional(OpenAiCompletionTokensDetails)\n}) {}\n\nclass OpenAiChatCompletionResponse extends Schema.Class<OpenAiChatCompletionResponse>(\n 'OpenAiChatCompletionResponse'\n)({\n choices: Schema.Array(OpenAiChoiceResponse),\n usage: Schema.optional(OpenAiUsageResponse)\n}) {}\n\nclass OpenAiChatDeltaFunction extends Schema.Class<OpenAiChatDeltaFunction>(\n 'OpenAiChatDeltaFunction'\n)({\n name: Schema.optional(Schema.String),\n arguments: Schema.optional(Schema.String)\n}) {}\n\nclass OpenAiChatDeltaToolCall extends Schema.Class<OpenAiChatDeltaToolCall>(\n 'OpenAiChatDeltaToolCall'\n)({\n index: Schema.optional(Schema.Number),\n id: Schema.optional(Schema.String),\n function: Schema.optional(OpenAiChatDeltaFunction)\n}) {}\n\nclass OpenAiChatDelta extends Schema.Class<OpenAiChatDelta>('OpenAiChatDelta')({\n content: Schema.optional(Schema.NullOr(Schema.String)),\n reasoning_content: Schema.optional(Schema.Unknown),\n // Some OpenAI-compatible hosts (e.g. Vercel AI Gateway normalizing\n // DeepSeek output) stream thinking under `reasoning` instead.\n reasoning: Schema.optional(Schema.Unknown),\n tool_calls: Schema.optional(Schema.Array(OpenAiChatDeltaToolCall))\n}) {}\n\nclass OpenAiChatStreamChoice extends Schema.Class<OpenAiChatStreamChoice>('OpenAiChatStreamChoice')(\n {\n delta: Schema.optional(OpenAiChatDelta),\n finish_reason: Schema.optional(Schema.NullOr(Schema.String)),\n usage: Schema.optional(Schema.Unknown)\n }\n) {}\n\nclass OpenAiChatStreamChunk extends Schema.Class<OpenAiChatStreamChunk>('OpenAiChatStreamChunk')({\n choices: Schema.optional(Schema.Array(OpenAiChatStreamChoice)),\n usage: Schema.optional(Schema.Unknown)\n}) {}\n\nclass OpenAiConfig extends Context.Service<OpenAiConfig, OpenAiProviderConfig>()(\n '@app/OpenAiConfig'\n) {}\n\nconst OpenAiConfigLayer = Layer.effect(\n OpenAiConfig,\n Effect.gen(function* () {\n const apiKey = yield* Config.Redacted('OPENAI_API_KEY')\n const maxCompletionTokens = yield* Config.Int('OPENAI_MAX_COMPLETION_TOKENS')\n\n return { apiKey, maxCompletionTokens }\n }).pipe(\n Effect.mapError(\n () =>\n new LLMError({\n cause: 'provider_error',\n message: 'OpenAI provider environment configuration missing',\n retryable: false\n })\n )\n )\n)\n\nconst JsonFromJsonString = Schema.fromJsonString(Schema.Json)\n\nconst isJsonRecord = (value: Schema.Json | undefined): value is Schema.JsonObject =>\n value !== undefined && Predicate.isObjectOrArray(value) && !Array.isArray(value)\n\nconst jsonRecordField = (value: Schema.JsonObject, key: string): Schema.Json | undefined =>\n Object.hasOwn(value, key) ? value[key] : undefined\n\nconst jsonField = (value: Schema.Json | undefined, key: string): Schema.Json | undefined =>\n isJsonRecord(value) ? jsonRecordField(value, key) : undefined\n\nconst stringField = (value: Schema.Json | undefined, key: string) => {\n const raw = jsonField(value, key)\n\n return Predicate.isString(raw) ? raw : undefined\n}\n\n// Machine error codes are safe to surface in provider metadata. Free-text\n// upstream messages stay out of LLMError per provider sanitization policy.\nconst decodeOpenAiHttpErrorCode = (raw: string): Effect.Effect<string | undefined> =>\n Schema.decodeUnknownEffect(JsonFromJsonString)(raw).pipe(\n Effect.map(parsed => {\n const error = jsonField(parsed, 'error')\n\n return stringField(error, 'code') ?? stringField(error, 'type')\n }),\n Effect.catch(() => Effect.succeed(undefined))\n )\n\nconst schemaErrorMessage = (error: Schema.SchemaError) => error.message\n\nconst schemaErrorToLlmError =\n (cause: LLMError['cause'], message: string) => (error: Schema.SchemaError) =>\n new LLMError({\n cause,\n message: `${message}: ${schemaErrorMessage(error)}`,\n retryable: false\n })\n\nconst encodeJsonString = (value: Schema.Json, message: string) =>\n Schema.encodeEffect(JsonFromJsonString)(value).pipe(\n Effect.mapError(schemaErrorToLlmError('provider_error', message))\n )\n\nconst invalidExtraBodyError = (providerName: string) =>\n new LLMError({\n cause: 'provider_error',\n message: `Invalid ${providerName} extraBody JSON: expected a JSON object`,\n retryable: false\n })\n\nconst isOpenAiCanonicalRequestKey = (key: string, config: OpenAiRequestBodyConfig) =>\n openAiCanonicalRequestKeys.has(key) ||\n (config.reasoningEffortFormat === 'reasoning-object' && key === 'reasoning') ||\n (config.reasoningEffortFormat === 'reasoning-effort' && key === 'reasoning_effort')\n\nconst snapshotOpenAiRequestExtras = (\n extraBody: unknown,\n config: OpenAiRequestBodyConfig,\n providerName: string\n): Effect.Effect<OpenAiRequestExtras, LLMError> => {\n if (\n !Predicate.isObjectOrArray(extraBody) ||\n Array.isArray(extraBody) ||\n !isPlainObject(extraBody)\n ) {\n return Effect.fail(invalidExtraBodyError(providerName))\n }\n\n const surviving: { [key: string]: Schema.Json } = {}\n\n Object.setPrototypeOf(surviving, null)\n\n const stack = new Set<object>()\n const memo = new Map<object, Schema.Json>()\n\n for (const key of Object.keys(extraBody)) {\n if (isOpenAiCanonicalRequestKey(key, config)) continue\n\n const descriptor = Object.getOwnPropertyDescriptor(extraBody, key)\n\n if (descriptor === undefined || !isDataPropertyDescriptor(descriptor)) {\n return Effect.fail(invalidExtraBodyError(providerName))\n }\n\n const field = snapshotPortableJson(descriptor.value, stack, memo)\n\n if (Option.isNone(field)) {\n return Effect.fail(invalidExtraBodyError(providerName))\n }\n\n Object.defineProperty(surviving, key, {\n value: field.value,\n enumerable: true,\n writable: true,\n configurable: true\n })\n }\n\n return Effect.succeed(surviving)\n}\n\nconst decodeJsonString = (raw: string, message: string) =>\n Schema.decodeUnknownEffect(JsonFromJsonString)(raw).pipe(\n Effect.mapError(schemaErrorToLlmError('invalid_response', message))\n )\n\nconst unsupportedContentError = (contentType: string, providerName: string) =>\n new LLMError({\n cause: 'provider_error',\n message: `${contentType} content is not supported by the ${providerName} provider yet`,\n retryable: false\n })\n\nconst textDocumentToOpenAiPart = (\n part: Extract<ContentPart, { readonly _tag: 'Document' }>,\n providerName: string\n) =>\n attachmentSourceText(part.source).pipe(\n Effect.mapError(() => unsupportedContentError('Invalid document text', providerName)),\n Effect.flatMap(\n Option.match({\n onNone: () =>\n Effect.fail(unsupportedContentError('Unresolved document source', providerName)),\n onSome: text => {\n const block: OpenAiTextContentPart = {\n type: 'text',\n text: `Document: ${part.title ?? part.filename}\\n\\n${text}`\n }\n\n return Effect.succeed(block)\n }\n })\n )\n )\n\nconst contentPartToUserPart = (\n part: ContentPart,\n providerName: string\n): Effect.Effect<OpenAiTextContentPart | OpenAiImageContentPart, LLMError> =>\n Match.value(part).pipe(\n Match.tag(\n 'Text',\n (current): Effect.Effect<OpenAiTextContentPart | OpenAiImageContentPart, LLMError> =>\n Effect.succeed({ type: 'text', text: current.text })\n ),\n Match.tag(\n 'Image',\n (current): Effect.Effect<OpenAiTextContentPart | OpenAiImageContentPart, LLMError> =>\n Option.match(attachmentSourceUrl(current.source, current.mimeType), {\n onNone: () =>\n Effect.fail(unsupportedContentError('Unresolved image source', providerName)),\n onSome: url => Effect.succeed({ type: 'image_url', image_url: { url } })\n })\n ),\n Match.tag('Document', current =>\n isTextDocumentMimeType(current.mimeType)\n ? textDocumentToOpenAiPart(current, providerName)\n : Effect.fail(unsupportedContentError('Document', providerName))\n ),\n Match.tag('Audio', () => Effect.fail(unsupportedContentError('Audio', providerName))),\n Match.exhaustive\n )\n\nconst contentToUserContent = (\n content: Content,\n providerName: string\n): Effect.Effect<OpenAiUserContent, LLMError> =>\n Predicate.isString(content)\n ? Effect.succeed(content)\n : Effect.forEach(content, part => contentPartToUserPart(part, providerName))\n\nconst contentPartToText = (\n part: ContentPart,\n owner: string,\n providerName: string\n): Effect.Effect<string, LLMError> =>\n Match.value(part).pipe(\n Match.tag('Text', current => Effect.succeed(current.text)),\n Match.tag('Image', () => Effect.fail(unsupportedContentError(`${owner} image`, providerName))),\n Match.tag('Document', () =>\n Effect.fail(unsupportedContentError(`${owner} document`, providerName))\n ),\n Match.tag('Audio', () => Effect.fail(unsupportedContentError(`${owner} audio`, providerName))),\n Match.exhaustive\n )\n\nconst contentToText = (\n content: Content,\n owner: string,\n providerName: string\n): Effect.Effect<string, LLMError> =>\n Predicate.isString(content)\n ? Effect.succeed(content)\n : Effect.forEach(content, part => contentPartToText(part, owner, providerName)).pipe(\n Effect.map(textParts => textParts.join('\\n'))\n )\n\nconst serializeToolArguments = (call: ToolCall, providerName: string) =>\n Schema.decodeUnknownEffect(Schema.Json)(call.params).pipe(\n Effect.mapError(\n schemaErrorToLlmError('provider_error', `Could not serialize ${providerName} tool arguments`)\n ),\n Effect.flatMap(json =>\n encodeJsonString(json, `Could not serialize ${providerName} tool arguments`)\n )\n )\n\nconst toolCallToOpenAiToolCall = (\n call: ToolCall,\n providerName: string\n): Effect.Effect<OpenAiToolCall, LLMError> =>\n Effect.gen(function* () {\n return {\n id: call.id,\n type: 'function',\n function: {\n name: call.name,\n arguments: yield* serializeToolArguments(call, providerName)\n }\n }\n })\n\nconst toOpenAiMessage = (\n message: AgentMessage,\n providerName: string,\n reasoningContent: boolean\n): Effect.Effect<OpenAiMessage, LLMError> =>\n Match.value(message).pipe(\n Match.withReturnType<Effect.Effect<OpenAiMessage, LLMError>>(),\n Match.tag('User', current =>\n contentToUserContent(\n prependMessageContextToContent(current.content, messageContextText(current)),\n providerName\n ).pipe(Effect.map(content => ({ role: 'user' as const, content })))\n ),\n Match.tag('Assistant', current => {\n const content = prependMessageContextToContent(\n assistantContent(current),\n messageContextText(current)\n )\n\n const reasoning = reasoningContent ? assistantReasoningText(current) : ''\n const reasoningFields = reasoning.length > 0 ? { reasoning_content: reasoning } : {}\n\n return Effect.forEach(assistantHostToolCalls(current), call =>\n toolCallToOpenAiToolCall(call, providerName)\n ).pipe(\n Effect.flatMap(toolCalls =>\n contentToText(content, 'Assistant', providerName).pipe(\n Effect.map(text =>\n toolCalls.length > 0\n ? {\n role: 'assistant' as const,\n content: text,\n tool_calls: toolCalls,\n ...reasoningFields\n }\n : {\n role: 'assistant' as const,\n content: text,\n ...reasoningFields\n }\n )\n )\n )\n )\n }),\n Match.tag('ToolResult', current =>\n contentToText(\n prependMessageContextToContent(current.content, messageContextText(current)),\n 'Tool result',\n providerName\n ).pipe(\n Effect.map(content => ({\n role: 'tool' as const,\n tool_call_id: current.toolCallId,\n content\n }))\n )\n ),\n Match.exhaustive\n )\n\nconst toOpenAiTool = (tool: ToolDef, providerName: string): Effect.Effect<OpenAiTool, LLMError> =>\n Schema.decodeUnknownEffect(Schema.Json)(tool.parameters).pipe(\n Effect.mapError(\n schemaErrorToLlmError('provider_error', `Invalid ${providerName} tool parameters JSON`)\n ),\n Effect.map((parameters): OpenAiTool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters\n }\n }))\n )\n\nexport const toOpenAiRequestBody = (\n request: LLMRequest,\n config: OpenAiRequestBodyConfig\n): Effect.Effect<OpenAiRequestBody, LLMError> =>\n Effect.gen(function* () {\n const providerName = config.providerName ?? defaultOpenAiProviderIdentity.name\n\n if (!Number.isSafeInteger(config.maxCompletionTokens) || config.maxCompletionTokens <= 0) {\n return yield* Effect.fail(\n new LLMError({\n cause: 'validation_error',\n message: `${providerName} maxCompletionTokens must be a positive safe integer`,\n retryable: false\n })\n )\n }\n\n yield* validateProviderTranscript(request.messages)\n const systemMessage: OpenAiMessage = { role: 'system', content: request.systemPrompt }\n\n const requestMessages = yield* Effect.forEach(request.messages, message =>\n toOpenAiMessage(message, providerName, config.reasoningContent ?? false)\n )\n\n const messages = [systemMessage, ...requestMessages]\n\n const completionTokenLimit =\n config.completionTokenField === 'max_tokens'\n ? { max_tokens: config.maxCompletionTokens }\n : { max_completion_tokens: config.maxCompletionTokens }\n\n const reasoning =\n request.reasoningEffort === undefined\n ? {}\n : config.reasoningEffortFormat === 'reasoning-object'\n ? { reasoning: { effort: request.reasoningEffort } }\n : config.reasoningEffortFormat === 'reasoning-effort'\n ? { reasoning_effort: request.reasoningEffort }\n : {}\n\n const extraBody =\n config.extraBody === undefined\n ? {}\n : yield* snapshotOpenAiRequestExtras(config.extraBody, config, providerName)\n\n const streaming = config.streaming === true\n\n // Usage only arrives on the stream when the endpoint is asked for it.\n const bodyWithoutTools: OpenAiRequestBody = streaming\n ? {\n ...extraBody,\n ...reasoning,\n model: request.model,\n messages,\n ...completionTokenLimit,\n stream: true,\n stream_options: { include_usage: true }\n }\n : {\n ...extraBody,\n ...reasoning,\n model: request.model,\n messages,\n ...completionTokenLimit,\n stream: false\n }\n\n const body: OpenAiRequestBody =\n request.tools.length === 0\n ? bodyWithoutTools\n : {\n ...bodyWithoutTools,\n tools: yield* Effect.forEach(request.tools, tool => toOpenAiTool(tool, providerName)),\n parallel_tool_calls: true\n }\n\n return body\n })\n\nconst parseToolArguments = (raw: string, providerName: string) =>\n decodeJsonString(raw, `Invalid ${providerName} tool arguments JSON`)\n\nconst toLlmEvents = (\n choice: OpenAiChoiceResponse,\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean\n): Effect.Effect<ReadonlyArray<LLMEvent>, LLMError> =>\n Effect.gen(function* () {\n if (choice.finish_reason === 'length' || choice.finish_reason === 'content_filter') {\n return yield* Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} response stopped with ${choice.finish_reason}`,\n retryable: false,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: 'invalid_response',\n providerCode: choice.finish_reason\n })\n })\n )\n }\n\n const content = choice.message.content ?? ''\n\n const reasoning = reasoningContent\n ? ((yield* Schema.decodeUnknownEffect(Schema.NullOr(Schema.String))(\n choice.message.reasoning_content ?? choice.message.reasoning ?? null\n ).pipe(\n Effect.mapError(\n schemaErrorToLlmError(\n 'invalid_response',\n `Invalid ${providerIdentity.name} reasoning content`\n )\n )\n )) ?? '')\n : ''\n\n const textEvents: Array<LLMEvent> = []\n\n if (reasoning.length > 0) textEvents.push(LLMReasoningDelta.make({ text: reasoning }))\n\n if (content.length > 0) textEvents.push(LLMTextDelta.make({ text: content }))\n\n const toolCallEvents = yield* Effect.forEach(choice.message.tool_calls ?? [], call =>\n parseToolArguments(call.function.arguments, providerIdentity.name).pipe(\n Effect.map(params =>\n LLMToolCall.make({\n call: ToolCall.make({\n id: call.id,\n name: call.function.name,\n params\n })\n })\n )\n )\n )\n\n if (toolCallEvents.length > 0) {\n return [...textEvents, ...toolCallEvents, LLMDone.make({ stopReason: 'tool_use' })]\n }\n\n return [...textEvents, LLMDone.make({ stopReason: 'stop' })]\n })\n\nconst toAgentUsage = (usage: OpenAiUsageResponse) =>\n AgentUsage.make({\n input: AgentInputUsage.make({\n total: usage.prompt_tokens,\n uncached: usage.prompt_tokens - (usage.prompt_tokens_details?.cached_tokens ?? 0),\n cacheRead: usage.prompt_tokens_details?.cached_tokens\n }),\n output: AgentOutputUsage.make({\n total: usage.completion_tokens,\n reasoning: usage.completion_tokens_details?.reasoning_tokens,\n text: usage.completion_tokens - (usage.completion_tokens_details?.reasoning_tokens ?? 0)\n })\n })\n\ntype OpenAiChatStreamToolCall = {\n readonly index: number\n readonly id: string | undefined\n readonly name: string | undefined\n readonly arguments: string\n}\n\ntype OpenAiChatStreamState = {\n readonly buffer: string\n readonly toolCalls: ReadonlyArray<OpenAiChatStreamToolCall>\n readonly finishReason: string | undefined\n readonly hasTerminal: boolean\n // Only [DONE] closes the stream: usage commonly arrives after the finish\n // chunk, so a bare finish reason must not discard later payloads.\n readonly streamClosed: boolean\n readonly usage: unknown\n readonly receivedBytes: number\n readonly outputStarted: boolean\n}\n\nconst initialOpenAiChatStreamState: OpenAiChatStreamState = {\n buffer: '',\n toolCalls: [],\n finishReason: undefined,\n hasTerminal: false,\n streamClosed: false,\n usage: undefined,\n receivedBytes: 0,\n outputStarted: false\n}\n\n// Split on blank lines in any newline style. Only CRLF pairs normalize, so a\n// chunk-ending lone CR stays pending and a split CRLF (or CR + multiline\n// continuation) cannot form a false event boundary. A \\r\\n surviving\n// normalization always spans two original breaks (a lone CR plus a collapsed\n// pair or lone LF), so recognizing it cannot re-split an atomic CRLF.\nconst splitCompleteChatSseBlocks = (buffer: string) => {\n const blocks = buffer.replace(/\\r\\n/g, '\\n').split(/\\n\\n|\\n\\r|\\r\\r|\\r\\n/)\n const tail = blocks.at(-1) ?? ''\n\n return { completeBlocks: blocks.slice(0, -1), tail }\n}\n\nconst chatSseBlockData = (block: string) => {\n const lines = block\n .split(/\\r\\n|\\n|\\r/)\n .filter(line => line.startsWith('data:'))\n .map(line => line.slice(5).trimStart())\n\n const done = lines.some(line => line === '[DONE]')\n\n const data = lines\n .filter(line => line.length > 0 && line !== '[DONE]')\n .join('\\n')\n .trim()\n\n return { done, payload: data.length > 0 ? data : undefined }\n}\n\n// Stream construction failures use fixed messages: schema diagnostics and\n// upstream values stay out of LLMError per provider sanitization policy.\nconst invalidChatStreamEvent = (providerIdentity: OpenAiProviderIdentity) =>\n new LLMError({\n cause: 'invalid_response',\n message: `Invalid ${providerIdentity.name} stream event`,\n retryable: false\n })\n\nconst chatStreamError = (\n providerIdentity: OpenAiProviderIdentity,\n raw: string\n): Effect.Effect<never, LLMError> =>\n Effect.gen(function* () {\n const errorCode = yield* decodeOpenAiHttpErrorCode(raw)\n\n const provider = classifyProviderFailure({\n provider: providerIdentity.id,\n body: raw,\n providerCode: errorCode\n })\n\n return yield* Effect.fail(\n new LLMError({\n cause: providerFailureCause(provider.kind),\n message: `${providerIdentity.name} stream reported an error`,\n retryable: providerFailureRetryable(provider.kind),\n provider\n })\n )\n })\n\nconst mergeChatToolCallDelta = (\n toolCalls: ReadonlyArray<OpenAiChatStreamToolCall>,\n delta: typeof OpenAiChatDeltaToolCall.Type\n): ReadonlyArray<OpenAiChatStreamToolCall> => {\n const index = delta.index ?? 0\n const current = toolCalls.find(call => call.index === index)\n\n const merged = {\n index,\n id: delta.id ?? current?.id,\n name: delta.function?.name ?? current?.name,\n arguments: `${current?.arguments ?? ''}${delta.function?.arguments ?? ''}`\n }\n\n return [...toolCalls.filter(call => call.index !== index), merged]\n}\n\nconst decodeChatDeltaReasoning = (\n providerIdentity: OpenAiProviderIdentity,\n reasoning: unknown\n): Effect.Effect<string, LLMError> =>\n Schema.decodeUnknownEffect(Schema.NullOr(Schema.String))(reasoning).pipe(\n Effect.map(value => value ?? ''),\n Effect.mapError(() => invalidChatStreamEvent(providerIdentity))\n )\n\ntype OpenAiChatStreamStep = {\n readonly state: OpenAiChatStreamState\n readonly events: ReadonlyArray<LLMEvent>\n}\n\nconst processChatStreamPayload = (\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean,\n state: OpenAiChatStreamState,\n payload: string\n): Effect.Effect<OpenAiChatStreamStep, LLMError> =>\n Effect.gen(function* () {\n const parsed = yield* Schema.decodeUnknownEffect(JsonFromJsonString)(payload).pipe(\n Effect.mapError(() => invalidChatStreamEvent(providerIdentity))\n )\n\n const envelope = isJsonRecord(parsed) ? jsonRecordField(parsed, 'error') : undefined\n\n if (envelope !== undefined && isJsonRecord(envelope)) {\n return yield* chatStreamError(providerIdentity, payload)\n }\n\n const chunk = yield* Schema.decodeUnknownEffect(OpenAiChatStreamChunk)(parsed).pipe(\n Effect.mapError(() => invalidChatStreamEvent(providerIdentity))\n )\n\n const events: Array<LLMEvent> = []\n let toolCalls = state.toolCalls\n let finishReason = state.finishReason\n let usage = state.usage\n\n for (const choice of chunk.choices ?? []) {\n if (choice.delta?.content) {\n events.push(LLMTextDelta.make({ text: choice.delta.content }))\n }\n\n if (\n reasoningContent &&\n (choice.delta?.reasoning_content != null || choice.delta?.reasoning != null)\n ) {\n const reasoning = yield* decodeChatDeltaReasoning(\n providerIdentity,\n choice.delta.reasoning_content ?? choice.delta.reasoning ?? null\n )\n\n if (reasoning.length > 0) events.push(LLMReasoningDelta.make({ text: reasoning }))\n }\n\n for (const call of choice.delta?.tool_calls ?? []) {\n toolCalls = mergeChatToolCallDelta(toolCalls, call)\n }\n\n if (\n choice.finish_reason !== undefined &&\n choice.finish_reason !== null &&\n finishReason === undefined\n ) {\n finishReason = choice.finish_reason\n }\n\n if (choice.usage !== undefined) usage = choice.usage\n }\n\n if (chunk.usage !== undefined) usage = chunk.usage\n\n return {\n state: {\n ...state,\n toolCalls,\n finishReason,\n hasTerminal: state.hasTerminal || finishReason !== undefined,\n usage,\n outputStarted: state.outputStarted || events.length > 0\n },\n events\n }\n })\n\nconst processChatStreamBlock = (\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean,\n state: OpenAiChatStreamState,\n block: string\n): Effect.Effect<OpenAiChatStreamStep, LLMError> =>\n Effect.gen(function* () {\n // Frames after [DONE] are transport noise: ignore them so a malformed\n // trailer cannot fail an otherwise completed turn.\n if (state.streamClosed) return { state, events: [] }\n\n const { done, payload } = chatSseBlockData(block)\n\n const current: OpenAiChatStreamState = done\n ? { ...state, hasTerminal: true, streamClosed: true }\n : state\n\n if (payload === undefined) return { state: current, events: [] }\n\n return yield* processChatStreamPayload(providerIdentity, reasoningContent, current, payload)\n })\n\nconst chatStreamDiagnostics = (\n responseFormat: ProviderStreamResponseFormat,\n state: OpenAiChatStreamState\n) =>\n ProviderStreamDiagnostics.make({\n protocol: 'chat-completions',\n responseFormat,\n receivedBytes: state.receivedBytes,\n bufferedChars: state.buffer.length,\n outputStarted: state.outputStarted,\n terminalSeen: state.hasTerminal\n })\n\nconst processChatStreamText = (\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean,\n state: OpenAiChatStreamState,\n text: string\n): Effect.Effect<OpenAiChatStreamStep, LLMError> =>\n Effect.gen(function* () {\n const split = splitCompleteChatSseBlocks(`${state.buffer}${text}`)\n let current: OpenAiChatStreamState = { ...state, buffer: split.tail }\n const events: Array<LLMEvent> = []\n\n for (const block of split.completeBlocks) {\n const step = yield* processChatStreamBlock(providerIdentity, reasoningContent, current, block)\n current = step.state\n events.push(...step.events)\n }\n\n return { state: current, events }\n })\n\nconst finalizeChatStreamState = (\n providerIdentity: OpenAiProviderIdentity,\n responseFormat: ProviderStreamResponseFormat,\n state: OpenAiChatStreamState\n): Effect.Effect<ReadonlyArray<LLMEvent>, LLMError> =>\n Effect.gen(function* () {\n if (!state.hasTerminal) {\n return yield* Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} stream ended before a terminal chunk`,\n retryable: false,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: 'invalid_response',\n providerCode: 'incomplete_stream',\n stream: chatStreamDiagnostics(responseFormat, state)\n })\n })\n )\n }\n\n if (state.finishReason === 'length' || state.finishReason === 'content_filter') {\n return yield* Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} response stopped with ${state.finishReason}`,\n retryable: false,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: 'invalid_response',\n providerCode: state.finishReason\n })\n })\n )\n }\n\n if (\n state.finishReason !== undefined &&\n state.finishReason !== 'stop' &&\n state.finishReason !== 'tool_calls'\n ) {\n const provider = classifyProviderFailure({\n provider: providerIdentity.id,\n body: state.finishReason,\n providerCode: state.finishReason\n })\n\n return yield* Effect.fail(\n new LLMError({\n cause: 'provider_error',\n message: `${providerIdentity.name} stream stopped with unrecognized finish reason`,\n retryable: false,\n provider\n })\n )\n }\n\n const orderedCalls = [...state.toolCalls].sort((left, right) => left.index - right.index)\n\n const toolCallEvents = yield* Effect.forEach(orderedCalls, call => {\n const id = call.id\n const name = call.name\n\n if (id === undefined || name === undefined) {\n return Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `Invalid ${providerIdentity.name} streamed tool call`,\n retryable: false\n })\n )\n }\n\n return parseToolArguments(call.arguments, providerIdentity.name).pipe(\n Effect.map(params => LLMToolCall.make({ call: ToolCall.make({ id, name, params }) }))\n )\n })\n\n const events: Array<LLMEvent> = [...toolCallEvents]\n\n events.push(LLMDone.make({ stopReason: toolCallEvents.length > 0 ? 'tool_use' : 'stop' }))\n\n if (state.usage !== undefined) {\n const usage = yield* Schema.decodeUnknownEffect(OpenAiUsageResponse)(state.usage).pipe(\n Effect.mapError(() => invalidChatStreamEvent(providerIdentity))\n )\n\n events.push(LLMUsage.make({ usage: toAgentUsage(usage) }))\n }\n\n return events\n })\n\nconst chatStreamResponseFormat = (\n contentType: string | undefined\n): ProviderStreamResponseFormat => {\n if (contentType === undefined) return 'unknown'\n\n const mediaType = contentType.split(';', 1)[0].trim().toLowerCase()\n\n if (mediaType === 'text/event-stream') return 'sse'\n\n if (mediaType === 'application/json' || mediaType.endsWith('+json')) return 'json'\n\n return 'other'\n}\n\nconst expectChatSseResponse = (\n providerIdentity: OpenAiProviderIdentity,\n response: HttpClientResponse.HttpClientResponse\n): Effect.Effect<ProviderStreamResponseFormat, LLMError> => {\n const responseFormat = chatStreamResponseFormat(response.headers['content-type'])\n\n // Accept missing Content-Type for compatibility with existing SSE endpoints.\n if (responseFormat === 'sse' || responseFormat === 'unknown') {\n return Effect.succeed(responseFormat)\n }\n\n return Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} streaming response was not an SSE stream`,\n retryable: false,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: 'invalid_response',\n status: response.status,\n providerCode: 'unexpected_content_type',\n stream: ProviderStreamDiagnostics.make({\n protocol: 'chat-completions',\n responseFormat,\n receivedBytes: 0,\n bufferedChars: 0,\n outputStarted: false,\n terminalSeen: false\n })\n })\n })\n )\n}\n\nconst streamOpenAiChatResponse = (\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean,\n responseFormat: ProviderStreamResponseFormat,\n response: HttpClientResponse.HttpClientResponse\n): Stream.Stream<LLMEvent, LLMError> =>\n Stream.unwrap(\n Ref.make(initialOpenAiChatStreamState).pipe(\n Effect.map(stateRef => {\n const chunks = response.stream.pipe(\n Stream.mapError(toHttpClientLlmError(providerIdentity, true)),\n Stream.tap(chunk =>\n Ref.update(stateRef, state => ({\n ...state,\n receivedBytes: state.receivedBytes + chunk.byteLength\n }))\n ),\n Stream.decodeText,\n Stream.mapEffect(chunk =>\n Effect.gen(function* () {\n const state = yield* Ref.get(stateRef)\n\n const step = yield* processChatStreamText(\n providerIdentity,\n reasoningContent,\n state,\n chunk\n )\n\n yield* Ref.set(stateRef, step.state)\n\n return step.events\n })\n ),\n Stream.flatMap(events => Stream.fromIterable(events))\n )\n\n const finalEvents = Stream.fromEffect(\n Ref.get(stateRef).pipe(\n Effect.flatMap(state =>\n finalizeChatStreamState(providerIdentity, responseFormat, state)\n )\n )\n ).pipe(Stream.flatMap(events => Stream.fromIterable(events)))\n\n return chunks.pipe(Stream.concat(finalEvents))\n })\n )\n )\n\nconst toHttpClientLlmError =\n (providerIdentity: OpenAiProviderIdentity, retryable: boolean) =>\n (error: HttpClientError.HttpClientError) =>\n new LLMError({\n cause: 'provider_error',\n message: `${providerIdentity.name} request failed: ${error.message}`,\n retryable,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: retryable ? 'network' : 'unknown'\n })\n })\n\nconst parseOpenAiResponseJson = (\n response: HttpClientResponse.HttpClientResponse,\n providerName: string\n): Effect.Effect<Schema.Json, LLMError> =>\n Effect.gen(function* () {\n const raw = yield* response.json.pipe(\n Effect.mapError(\n error =>\n new LLMError({\n cause: 'invalid_response',\n message: `Could not parse ${providerName} response JSON: ${error.message}`,\n retryable: false\n })\n )\n )\n\n return yield* Schema.decodeUnknownEffect(Schema.Json)(raw).pipe(\n Effect.mapError(\n schemaErrorToLlmError('invalid_response', `Could not parse ${providerName} response JSON`)\n )\n )\n })\n\nconst openAiRequestBodyFields = (\n config: OpenAiProviderConfig,\n providerIdentity: OpenAiProviderIdentity\n): OpenAiRequestBodyConfigFields => {\n const fields: OpenAiRequestBodyConfigFields = {\n maxCompletionTokens: config.maxCompletionTokens,\n providerName: providerIdentity.name\n }\n\n if (config.completionTokenField !== undefined) {\n fields.completionTokenField = config.completionTokenField\n }\n\n if (config.extraBody !== undefined) {\n fields.extraBody = config.extraBody\n }\n\n if (config.reasoningEffortFormat !== undefined) {\n fields.reasoningEffortFormat = config.reasoningEffortFormat\n }\n\n if (config.reasoningContent !== undefined) {\n fields.reasoningContent = config.reasoningContent\n }\n\n if (config.streaming !== undefined) {\n fields.streaming = config.streaming\n }\n\n return fields\n}\n\nconst serializeOpenAiRequestBody = (\n body: OpenAiRequestBody,\n providerName: string\n): Effect.Effect<string, LLMError> =>\n // Replayed transcripts can carry lone surrogates; harden the lowered\n // body so one bad historical string cannot poison every model call.\n Schema.decodeUnknownEffect(Schema.Json)(replaceLoneSurrogatesDeep(body)).pipe(\n Effect.mapError(\n schemaErrorToLlmError('provider_error', `Could not serialize ${providerName} request`)\n ),\n Effect.flatMap(json => encodeJsonString(json, `Could not serialize ${providerName} request`))\n )\n\nconst postOpenAiRequest = (\n config: OpenAiProviderConfig,\n providerIdentity: OpenAiProviderIdentity,\n serializedBody: string,\n client: HttpClient.HttpClient\n): Effect.Effect<HttpClientResponse.HttpClientResponse, LLMError> =>\n Effect.gen(function* () {\n const httpRequest = HttpClientRequest.post(\n config.chatCompletionsUrl ?? 'https://api.openai.com/v1/chat/completions'\n ).pipe(\n HttpClientRequest.setHeaders({\n ...config.extraHeaders,\n accept: config.streaming === true ? 'text/event-stream' : 'application/json',\n authorization: `Bearer ${Redacted.value(config.apiKey)}`,\n 'content-type': 'application/json'\n }),\n HttpClientRequest.bodyText(serializedBody, 'application/json')\n )\n\n const response = yield* client\n .execute(httpRequest)\n .pipe(Effect.mapError(toHttpClientLlmError(providerIdentity, true)))\n\n if (response.status < 200 || response.status >= 300) {\n const errorText = yield* response.text.pipe(\n Effect.mapError(\n error =>\n new LLMError({\n cause: 'provider_error',\n message: `Could not read ${providerIdentity.name} error body: ${error.message}`,\n retryable: false\n })\n )\n )\n\n const errorCode = yield* decodeOpenAiHttpErrorCode(errorText)\n\n const provider = classifyProviderFailure({\n provider: providerIdentity.id,\n status: response.status,\n headers: response.headers,\n body: errorText,\n providerCode: errorCode\n })\n\n return yield* Effect.fail(\n new LLMError({\n cause: providerFailureCause(provider.kind),\n message: `${providerIdentity.name} returned ${response.status}`,\n retryable: providerFailureRetryable(provider.kind),\n provider\n })\n )\n }\n\n return response\n })\n\nconst sendOpenAiRequestBody = (\n config: OpenAiProviderConfig,\n request: LLMRequest,\n providerIdentity: OpenAiProviderIdentity\n): Effect.Effect<string, LLMError> =>\n Effect.gen(function* () {\n const body = yield* toOpenAiRequestBody(\n request,\n openAiRequestBodyFields(config, providerIdentity)\n )\n\n return yield* serializeOpenAiRequestBody(body, providerIdentity.name)\n })\n\nconst sendOpenAiRequest = (\n config: OpenAiProviderConfig,\n request: LLMRequest,\n client: HttpClient.HttpClient\n): Effect.Effect<ReadonlyArray<LLMEvent>, LLMError> =>\n Effect.gen(function* () {\n const providerIdentity = config.providerIdentity ?? defaultOpenAiProviderIdentity\n const serializedBody = yield* sendOpenAiRequestBody(config, request, providerIdentity)\n const response = yield* postOpenAiRequest(config, providerIdentity, serializedBody, client)\n const json = yield* parseOpenAiResponseJson(response, providerIdentity.name)\n\n const parsed = yield* Schema.decodeUnknownEffect(OpenAiChatCompletionResponse)(json).pipe(\n Effect.mapError(\n schemaErrorToLlmError('invalid_response', `Invalid ${providerIdentity.name} response`)\n )\n )\n\n const choice = parsed.choices[0]\n\n if (choice === undefined) {\n return yield* Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} response contained no choices`,\n retryable: false\n })\n )\n }\n\n const events = yield* toLlmEvents(choice, providerIdentity, config.reasoningContent ?? false)\n\n if (parsed.usage === undefined) {\n return events\n }\n\n return [...events, LLMUsage.make({ usage: toAgentUsage(parsed.usage) })]\n }).pipe(\n Effect.withSpan(`${config.providerIdentity?.id ?? defaultOpenAiProviderIdentity.id}.stream`)\n )\n\nconst streamOpenAiRequest = (\n config: OpenAiProviderConfig,\n request: LLMRequest,\n client: HttpClient.HttpClient\n): Stream.Stream<LLMEvent, LLMError> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const providerIdentity = config.providerIdentity ?? defaultOpenAiProviderIdentity\n const serializedBody = yield* sendOpenAiRequestBody(config, request, providerIdentity)\n const response = yield* postOpenAiRequest(config, providerIdentity, serializedBody, client)\n const responseFormat = yield* expectChatSseResponse(providerIdentity, response)\n\n return streamOpenAiChatResponse(\n providerIdentity,\n config.reasoningContent ?? false,\n responseFormat,\n response\n )\n })\n )\n\nconst openAiProviderStream = (\n config: OpenAiProviderConfig,\n request: LLMRequest,\n client: HttpClient.HttpClient\n): Stream.Stream<LLMEvent, LLMError> =>\n config.streaming === true\n ? streamOpenAiRequest(config, request, client)\n : Stream.fromEffect(sendOpenAiRequest(config, request, client)).pipe(\n Stream.flatMap(events => Stream.fromIterable(events))\n )\n\nexport const makeOpenAiProviderLayer = (config: OpenAiProviderConfig) =>\n Layer.effect(\n LLMProvider,\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n\n return LLMProvider.of({\n stream: request => openAiProviderStream(config, request, client)\n })\n })\n )\n\nexport const OpenAiProviderLayer = Layer.effect(\n LLMProvider,\n Effect.gen(function* () {\n const config = yield* OpenAiConfig\n const client = yield* HttpClient.HttpClient\n\n return LLMProvider.of({\n stream: request => openAiProviderStream(config, request, client)\n })\n })\n).pipe(Layer.provide(Layer.mergeAll(OpenAiConfigLayer, FetchHttpClient.layer)))\n"],"mappings":"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"}
1
+ {"version":3,"file":"provider.mjs","names":["Schema","LLMReasoningDelta","LLMTextDelta"],"sources":["../../../src/providers/openai/provider.ts"],"sourcesContent":["import {\n Config,\n Context,\n Effect,\n Encoding,\n Layer,\n Match,\n Option,\n Predicate,\n Redacted,\n Ref,\n Stream\n} from 'effect'\nimport {\n FetchHttpClient,\n HttpClient,\n HttpClientRequest,\n type HttpClientError,\n type HttpClientResponse\n} from 'effect/unstable/http'\nimport * as Schema from 'effect/Schema'\nimport {\n ToolCall,\n AgentInputUsage,\n AgentOutputUsage,\n AgentUsage,\n ProviderStreamDiagnostics,\n attachmentSourceText,\n attachmentSourceUrl,\n assistantContent,\n assistantHostToolCalls,\n assistantReasoningText,\n isTextDocumentMimeType,\n messageContextText,\n replaceLoneSurrogatesDeep,\n prependMessageContextToContent,\n type AgentMessage,\n type AgentReasoningEffort,\n type Content,\n type ContentPart,\n type ProviderStreamResponseFormat,\n type ToolDef\n} from '@yolk-sdk/agent/protocol'\nimport {\n LLMError,\n LLMDone,\n LLMProvider,\n LLMReasoningDelta,\n LLMTextDelta,\n LLMToolCall,\n LLMUsage,\n type LLMEvent,\n type LLMRequest\n} from '@yolk-sdk/agent/loop'\nimport {\n classifyProviderFailure,\n providerErrorInfo,\n providerFailureCause,\n providerFailureRetryable\n} from '../provider-error.ts'\nimport { validateProviderTranscript } from '../transcript.ts'\n\ntype OpenAiProviderIdentity = {\n readonly id: string\n readonly name: string\n}\n\n/** Chat Completions extras input; lowering admits a portable JSON-object snapshot. */\nexport type OpenAiRequestExtras = {\n readonly [key: string]: Schema.Json\n}\n\nconst isPlainObject = (value: object) => {\n const proto = Object.getPrototypeOf(value)\n\n return proto === Object.prototype || proto === null\n}\n\nconst isDataPropertyDescriptor = (descriptor: PropertyDescriptor) =>\n descriptor.enumerable === true && Object.hasOwn(descriptor, 'value')\n\nconst snapshotFailed = Option.none<Schema.Json>()\n\nconst snapshotPortableJson = (\n value: unknown,\n stack: Set<object>,\n memo: Map<object, Schema.Json>\n): Option.Option<Schema.Json> => {\n if (value === null || Predicate.isString(value) || Predicate.isBoolean(value)) {\n return Option.some(value)\n }\n\n if (Predicate.isNumber(value)) {\n return Number.isFinite(value) ? Option.some(value) : snapshotFailed\n }\n\n if (!Predicate.isObjectOrArray(value)) {\n return snapshotFailed\n }\n\n if (stack.has(value)) {\n return snapshotFailed\n }\n\n const memoized = memo.get(value)\n\n if (memoized !== undefined) {\n return Option.some(memoized)\n }\n\n stack.add(value)\n\n if (Array.isArray(value)) {\n if (\n Object.getPrototypeOf(value) !== Array.prototype ||\n Object.getOwnPropertySymbols(value).length !== 0 ||\n Object.getOwnPropertyNames(value).length !== value.length + 1\n ) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const items: Array<Schema.Json> = []\n\n for (let index = 0; index < value.length; index++) {\n const descriptor = Object.getOwnPropertyDescriptor(value, index)\n\n if (descriptor === undefined || !isDataPropertyDescriptor(descriptor)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const item = snapshotPortableJson(descriptor.value, stack, memo)\n\n if (Option.isNone(item)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n items.push(item.value)\n }\n\n stack.delete(value)\n memo.set(value, items)\n\n return Option.some(items)\n }\n\n if (!isPlainObject(value)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const keys = Object.keys(value)\n\n if (\n Object.getOwnPropertySymbols(value).length !== 0 ||\n Object.getOwnPropertyNames(value).length !== keys.length\n ) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const snapshot: { [key: string]: Schema.Json } = {}\n\n Object.setPrototypeOf(snapshot, null)\n\n for (const key of keys) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key)\n\n if (descriptor === undefined || !isDataPropertyDescriptor(descriptor)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n const field = snapshotPortableJson(descriptor.value, stack, memo)\n\n if (Option.isNone(field)) {\n stack.delete(value)\n\n return snapshotFailed\n }\n\n Object.defineProperty(snapshot, key, {\n value: field.value,\n enumerable: true,\n writable: true,\n configurable: true\n })\n }\n\n stack.delete(value)\n memo.set(value, snapshot)\n\n return Option.some(snapshot)\n}\n\nconst openAiCanonicalRequestKeys = new Set([\n 'model',\n 'messages',\n 'stream',\n 'tools',\n 'parallel_tool_calls',\n 'max_completion_tokens',\n 'max_tokens'\n])\n\nexport type OpenAiProviderConfig = {\n readonly chatCompletionsUrl?: string\n readonly maxCompletionTokens: number\n /** Selects the compatible endpoint's output-limit parameter. Defaults to `max_completion_tokens`. */\n readonly completionTokenField?: 'max_completion_tokens' | 'max_tokens'\n readonly extraHeaders?: Readonly<Record<string, string>>\n /**\n * Admitted portable JSON-object extras. Runtime still snapshots and validates\n * untyped input. Canonical model/messages/limit/stream/tools keys are omitted\n * without reading values.\n */\n readonly extraBody?: OpenAiRequestExtras\n /** Opts into a compatible endpoint's reasoning object or reasoning_effort request field. */\n readonly reasoningEffortFormat?: 'reasoning-object' | 'reasoning-effort'\n /** Preserve compatible models' reasoning_content output and assistant replay. */\n readonly reasoningContent?: boolean\n /**\n * Request incremental server-sent deltas instead of one JSON body. Hosts\n * must only enable this against endpoints that serve chat SSE.\n */\n readonly streaming?: boolean\n /** Enables native PDF file parts for compatible Chat Completions endpoints. */\n readonly supportsPdfAttachments?: boolean\n /** Customizes safe error metadata for a branded OpenAI-compatible endpoint. */\n readonly providerIdentity?: OpenAiProviderIdentity\n readonly apiKey: Redacted.Redacted<string>\n}\n\ntype OpenAiTextContentPart = {\n readonly type: 'text'\n readonly text: string\n}\n\ntype OpenAiImageContentPart = {\n readonly type: 'image_url'\n readonly image_url: {\n readonly url: string\n }\n}\n\ntype OpenAiFileContentPart = {\n readonly type: 'file'\n readonly file: {\n readonly filename: string\n readonly file_data: string\n }\n}\n\ntype OpenAiUserContent =\n | string\n | ReadonlyArray<OpenAiTextContentPart | OpenAiImageContentPart | OpenAiFileContentPart>\n\ntype OpenAiToolCall = {\n readonly id: string\n readonly type: 'function'\n readonly function: {\n readonly name: string\n readonly arguments: string\n }\n}\n\ntype OpenAiMessage =\n | { readonly role: 'system'; readonly content: string }\n | { readonly role: 'user'; readonly content: OpenAiUserContent }\n | {\n readonly role: 'assistant'\n readonly content: string | null\n readonly tool_calls?: ReadonlyArray<OpenAiToolCall>\n readonly reasoning_content?: string\n }\n | { readonly role: 'tool'; readonly tool_call_id: string; readonly content: string }\n\ntype OpenAiTool = {\n readonly type: 'function'\n readonly function: {\n readonly name: string\n readonly description: string\n readonly parameters: Schema.Json\n }\n}\n\ntype OpenAiRequestBody = {\n readonly model: string\n readonly messages: ReadonlyArray<OpenAiMessage>\n readonly max_completion_tokens?: number\n readonly max_tokens?: number\n readonly stream: boolean\n readonly stream_options?: {\n readonly include_usage: boolean\n }\n readonly reasoning?: {\n readonly effort: AgentReasoningEffort\n }\n readonly reasoning_effort?: AgentReasoningEffort\n readonly tools?: ReadonlyArray<OpenAiTool>\n readonly parallel_tool_calls?: true\n}\n\ntype ResolvePdfUrl = (url: string) => Effect.Effect<string, LLMError>\n\ntype OpenAiRequestBodyConfig = {\n readonly maxCompletionTokens: number\n readonly completionTokenField?: 'max_completion_tokens' | 'max_tokens'\n readonly extraBody?: unknown\n readonly reasoningEffortFormat?: 'reasoning-object' | 'reasoning-effort'\n readonly reasoningContent?: boolean\n readonly streaming?: boolean\n readonly supportsPdfAttachments?: boolean\n readonly resolvePdfUrl?: ResolvePdfUrl\n readonly providerName?: string\n}\n\ntype OpenAiRequestBodyConfigFields = {\n maxCompletionTokens: number\n providerName: string\n completionTokenField?: OpenAiRequestBodyConfig['completionTokenField']\n extraBody?: OpenAiRequestBodyConfig['extraBody']\n reasoningEffortFormat?: OpenAiRequestBodyConfig['reasoningEffortFormat']\n reasoningContent?: boolean\n streaming?: boolean\n supportsPdfAttachments?: boolean\n resolvePdfUrl?: ResolvePdfUrl\n}\n\nconst defaultOpenAiProviderIdentity: OpenAiProviderIdentity = {\n id: 'openai',\n name: 'OpenAI'\n}\n\nclass OpenAiFunctionResponse extends Schema.Class<OpenAiFunctionResponse>('OpenAiFunctionResponse')(\n {\n name: Schema.String,\n arguments: Schema.String\n }\n) {}\n\nclass OpenAiToolCallResponse extends Schema.Class<OpenAiToolCallResponse>('OpenAiToolCallResponse')(\n {\n id: Schema.String,\n type: Schema.Literals(['function']),\n function: OpenAiFunctionResponse\n }\n) {}\n\nclass OpenAiMessageResponse extends Schema.Class<OpenAiMessageResponse>('OpenAiMessageResponse')({\n content: Schema.NullOr(Schema.String),\n reasoning_content: Schema.optional(Schema.Unknown),\n // See OpenAiChatDelta: normalized `reasoning` alias for thinking output.\n reasoning: Schema.optional(Schema.Unknown),\n tool_calls: Schema.optional(Schema.Array(OpenAiToolCallResponse))\n}) {}\n\nclass OpenAiChoiceResponse extends Schema.Class<OpenAiChoiceResponse>('OpenAiChoiceResponse')({\n message: OpenAiMessageResponse,\n finish_reason: Schema.optional(Schema.NullOr(Schema.String))\n}) {}\n\nclass OpenAiPromptTokensDetails extends Schema.Class<OpenAiPromptTokensDetails>(\n 'OpenAiPromptTokensDetails'\n)({\n cached_tokens: Schema.optional(Schema.Number)\n}) {}\n\nclass OpenAiCompletionTokensDetails extends Schema.Class<OpenAiCompletionTokensDetails>(\n 'OpenAiCompletionTokensDetails'\n)({\n reasoning_tokens: Schema.optional(Schema.Number)\n}) {}\n\nclass OpenAiUsageResponse extends Schema.Class<OpenAiUsageResponse>('OpenAiUsageResponse')({\n prompt_tokens: Schema.Number,\n completion_tokens: Schema.Number,\n prompt_tokens_details: Schema.optional(OpenAiPromptTokensDetails),\n completion_tokens_details: Schema.optional(OpenAiCompletionTokensDetails)\n}) {}\n\nclass OpenAiChatCompletionResponse extends Schema.Class<OpenAiChatCompletionResponse>(\n 'OpenAiChatCompletionResponse'\n)({\n choices: Schema.Array(OpenAiChoiceResponse),\n usage: Schema.optional(OpenAiUsageResponse)\n}) {}\n\nclass OpenAiChatDeltaFunction extends Schema.Class<OpenAiChatDeltaFunction>(\n 'OpenAiChatDeltaFunction'\n)({\n name: Schema.optional(Schema.String),\n arguments: Schema.optional(Schema.String)\n}) {}\n\nclass OpenAiChatDeltaToolCall extends Schema.Class<OpenAiChatDeltaToolCall>(\n 'OpenAiChatDeltaToolCall'\n)({\n index: Schema.optional(Schema.Number),\n id: Schema.optional(Schema.String),\n function: Schema.optional(OpenAiChatDeltaFunction)\n}) {}\n\nclass OpenAiChatDelta extends Schema.Class<OpenAiChatDelta>('OpenAiChatDelta')({\n content: Schema.optional(Schema.NullOr(Schema.String)),\n reasoning_content: Schema.optional(Schema.Unknown),\n // Some OpenAI-compatible hosts (e.g. Vercel AI Gateway normalizing\n // DeepSeek output) stream thinking under `reasoning` instead.\n reasoning: Schema.optional(Schema.Unknown),\n tool_calls: Schema.optional(Schema.Array(OpenAiChatDeltaToolCall))\n}) {}\n\nclass OpenAiChatStreamChoice extends Schema.Class<OpenAiChatStreamChoice>('OpenAiChatStreamChoice')(\n {\n delta: Schema.optional(OpenAiChatDelta),\n finish_reason: Schema.optional(Schema.NullOr(Schema.String)),\n usage: Schema.optional(Schema.Unknown)\n }\n) {}\n\nclass OpenAiChatStreamChunk extends Schema.Class<OpenAiChatStreamChunk>('OpenAiChatStreamChunk')({\n choices: Schema.optional(Schema.Array(OpenAiChatStreamChoice)),\n usage: Schema.optional(Schema.Unknown)\n}) {}\n\nclass OpenAiConfig extends Context.Service<OpenAiConfig, OpenAiProviderConfig>()(\n '@app/OpenAiConfig'\n) {}\n\nconst OpenAiConfigLayer = Layer.effect(\n OpenAiConfig,\n Effect.gen(function* () {\n const apiKey = yield* Config.Redacted('OPENAI_API_KEY')\n const maxCompletionTokens = yield* Config.Int('OPENAI_MAX_COMPLETION_TOKENS')\n\n return { apiKey, maxCompletionTokens }\n }).pipe(\n Effect.mapError(\n () =>\n new LLMError({\n cause: 'provider_error',\n message: 'OpenAI provider environment configuration missing',\n retryable: false\n })\n )\n )\n)\n\nconst JsonFromJsonString = Schema.fromJsonString(Schema.Json)\n\nconst isJsonRecord = (value: Schema.Json | undefined): value is Schema.JsonObject =>\n value !== undefined && Predicate.isObjectOrArray(value) && !Array.isArray(value)\n\nconst jsonRecordField = (value: Schema.JsonObject, key: string): Schema.Json | undefined =>\n Object.hasOwn(value, key) ? value[key] : undefined\n\nconst jsonField = (value: Schema.Json | undefined, key: string): Schema.Json | undefined =>\n isJsonRecord(value) ? jsonRecordField(value, key) : undefined\n\nconst stringField = (value: Schema.Json | undefined, key: string) => {\n const raw = jsonField(value, key)\n\n return Predicate.isString(raw) ? raw : undefined\n}\n\n// Machine error codes are safe to surface in provider metadata. Free-text\n// upstream messages stay out of LLMError per provider sanitization policy.\nconst decodeOpenAiHttpErrorCode = (raw: string): Effect.Effect<string | undefined> =>\n Schema.decodeUnknownEffect(JsonFromJsonString)(raw).pipe(\n Effect.map(parsed => {\n const error = jsonField(parsed, 'error')\n\n return stringField(error, 'code') ?? stringField(error, 'type')\n }),\n Effect.catch(() => Effect.succeed(undefined))\n )\n\nconst schemaErrorMessage = (error: Schema.SchemaError) => error.message\n\nconst schemaErrorToLlmError =\n (cause: LLMError['cause'], message: string) => (error: Schema.SchemaError) =>\n new LLMError({\n cause,\n message: `${message}: ${schemaErrorMessage(error)}`,\n retryable: false\n })\n\nconst encodeJsonString = (value: Schema.Json, message: string) =>\n Schema.encodeEffect(JsonFromJsonString)(value).pipe(\n Effect.mapError(schemaErrorToLlmError('provider_error', message))\n )\n\nconst invalidExtraBodyError = (providerName: string) =>\n new LLMError({\n cause: 'provider_error',\n message: `Invalid ${providerName} extraBody JSON: expected a JSON object`,\n retryable: false\n })\n\nconst isOpenAiCanonicalRequestKey = (key: string, config: OpenAiRequestBodyConfig) =>\n openAiCanonicalRequestKeys.has(key) ||\n (config.reasoningEffortFormat === 'reasoning-object' && key === 'reasoning') ||\n (config.reasoningEffortFormat === 'reasoning-effort' && key === 'reasoning_effort')\n\nconst snapshotOpenAiRequestExtras = (\n extraBody: unknown,\n config: OpenAiRequestBodyConfig,\n providerName: string\n): Effect.Effect<OpenAiRequestExtras, LLMError> => {\n if (\n !Predicate.isObjectOrArray(extraBody) ||\n Array.isArray(extraBody) ||\n !isPlainObject(extraBody)\n ) {\n return Effect.fail(invalidExtraBodyError(providerName))\n }\n\n const surviving: { [key: string]: Schema.Json } = {}\n\n Object.setPrototypeOf(surviving, null)\n\n const stack = new Set<object>()\n const memo = new Map<object, Schema.Json>()\n\n for (const key of Object.keys(extraBody)) {\n if (isOpenAiCanonicalRequestKey(key, config)) continue\n\n const descriptor = Object.getOwnPropertyDescriptor(extraBody, key)\n\n if (descriptor === undefined || !isDataPropertyDescriptor(descriptor)) {\n return Effect.fail(invalidExtraBodyError(providerName))\n }\n\n const field = snapshotPortableJson(descriptor.value, stack, memo)\n\n if (Option.isNone(field)) {\n return Effect.fail(invalidExtraBodyError(providerName))\n }\n\n Object.defineProperty(surviving, key, {\n value: field.value,\n enumerable: true,\n writable: true,\n configurable: true\n })\n }\n\n return Effect.succeed(surviving)\n}\n\nconst decodeJsonString = (raw: string, message: string) =>\n Schema.decodeUnknownEffect(JsonFromJsonString)(raw).pipe(\n Effect.mapError(schemaErrorToLlmError('invalid_response', message))\n )\n\nconst unsupportedContentError = (contentType: string, providerName: string) =>\n new LLMError({\n cause: 'provider_error',\n message: `${contentType} content is not supported by the ${providerName} provider yet`,\n retryable: false\n })\n\nconst textDocumentToOpenAiPart = (\n part: Extract<ContentPart, { readonly _tag: 'Document' }>,\n providerName: string\n) =>\n attachmentSourceText(part.source).pipe(\n Effect.mapError(() => unsupportedContentError('Invalid document text', providerName)),\n Effect.flatMap(\n Option.match({\n onNone: () =>\n Effect.fail(unsupportedContentError('Unresolved document source', providerName)),\n onSome: text => {\n const block: OpenAiTextContentPart = {\n type: 'text',\n text: `Document: ${part.title ?? part.filename}\\n\\n${text}`\n }\n\n return Effect.succeed(block)\n }\n })\n )\n )\n\nconst pdfDocumentToOpenAiPart = (\n part: Extract<ContentPart, { readonly _tag: 'Document' }>,\n providerName: string,\n resolvePdfUrl: ResolvePdfUrl | undefined\n): Effect.Effect<OpenAiFileContentPart, LLMError> =>\n Match.value(part.source).pipe(\n Match.tag('InlineBase64', source =>\n Effect.succeed(`data:${part.mimeType};base64,${source.data}`)\n ),\n Match.tag('Url', source =>\n resolvePdfUrl === undefined\n ? Effect.fail(unsupportedContentError('Unresolved document source', providerName))\n : resolvePdfUrl(source.url)\n ),\n Match.tag('Ref', () =>\n Effect.fail(unsupportedContentError('Unresolved document source', providerName))\n ),\n Match.exhaustive,\n Effect.map(fileData => ({\n type: 'file' as const,\n file: {\n filename: part.filename,\n file_data: fileData\n }\n }))\n )\n\nconst normalizedMimeType = (mimeType: string) =>\n mimeType.split(';', 1)[0]?.trim().toLowerCase() ?? ''\n\nconst contentPartToUserPart = (\n part: ContentPart,\n providerName: string,\n supportsPdfAttachments: boolean,\n resolvePdfUrl: ResolvePdfUrl | undefined\n): Effect.Effect<\n OpenAiTextContentPart | OpenAiImageContentPart | OpenAiFileContentPart,\n LLMError\n> =>\n Match.value(part).pipe(\n Match.tag(\n 'Text',\n (current): Effect.Effect<OpenAiTextContentPart | OpenAiImageContentPart, LLMError> =>\n Effect.succeed({ type: 'text', text: current.text })\n ),\n Match.tag(\n 'Image',\n (current): Effect.Effect<OpenAiTextContentPart | OpenAiImageContentPart, LLMError> =>\n Option.match(attachmentSourceUrl(current.source, current.mimeType), {\n onNone: () =>\n Effect.fail(unsupportedContentError('Unresolved image source', providerName)),\n onSome: url => Effect.succeed({ type: 'image_url', image_url: { url } })\n })\n ),\n Match.tag('Document', current =>\n isTextDocumentMimeType(current.mimeType)\n ? textDocumentToOpenAiPart(current, providerName)\n : supportsPdfAttachments && normalizedMimeType(current.mimeType) === 'application/pdf'\n ? pdfDocumentToOpenAiPart(current, providerName, resolvePdfUrl)\n : Effect.fail(unsupportedContentError('Document', providerName))\n ),\n Match.tag('Audio', () => Effect.fail(unsupportedContentError('Audio', providerName))),\n Match.exhaustive\n )\n\nconst contentToUserContent = (\n content: Content,\n providerName: string,\n supportsPdfAttachments: boolean,\n resolvePdfUrl: ResolvePdfUrl | undefined\n): Effect.Effect<OpenAiUserContent, LLMError> =>\n Predicate.isString(content)\n ? Effect.succeed(content)\n : Effect.forEach(content, part =>\n contentPartToUserPart(part, providerName, supportsPdfAttachments, resolvePdfUrl)\n )\n\nconst contentPartToText = (\n part: ContentPart,\n owner: string,\n providerName: string\n): Effect.Effect<string, LLMError> =>\n Match.value(part).pipe(\n Match.tag('Text', current => Effect.succeed(current.text)),\n Match.tag('Image', () => Effect.fail(unsupportedContentError(`${owner} image`, providerName))),\n Match.tag('Document', () =>\n Effect.fail(unsupportedContentError(`${owner} document`, providerName))\n ),\n Match.tag('Audio', () => Effect.fail(unsupportedContentError(`${owner} audio`, providerName))),\n Match.exhaustive\n )\n\nconst contentToText = (\n content: Content,\n owner: string,\n providerName: string\n): Effect.Effect<string, LLMError> =>\n Predicate.isString(content)\n ? Effect.succeed(content)\n : Effect.forEach(content, part => contentPartToText(part, owner, providerName)).pipe(\n Effect.map(textParts => textParts.join('\\n'))\n )\n\nconst serializeToolArguments = (call: ToolCall, providerName: string) =>\n Schema.decodeUnknownEffect(Schema.Json)(call.params).pipe(\n Effect.mapError(\n schemaErrorToLlmError('provider_error', `Could not serialize ${providerName} tool arguments`)\n ),\n Effect.flatMap(json =>\n encodeJsonString(json, `Could not serialize ${providerName} tool arguments`)\n )\n )\n\nconst toolCallToOpenAiToolCall = (\n call: ToolCall,\n providerName: string\n): Effect.Effect<OpenAiToolCall, LLMError> =>\n Effect.gen(function* () {\n return {\n id: call.id,\n type: 'function',\n function: {\n name: call.name,\n arguments: yield* serializeToolArguments(call, providerName)\n }\n }\n })\n\nconst toOpenAiMessage = (\n message: AgentMessage,\n providerName: string,\n reasoningContent: boolean,\n supportsPdfAttachments: boolean,\n resolvePdfUrl: ResolvePdfUrl | undefined\n): Effect.Effect<OpenAiMessage, LLMError> =>\n Match.value(message).pipe(\n Match.withReturnType<Effect.Effect<OpenAiMessage, LLMError>>(),\n Match.tag('User', current =>\n contentToUserContent(\n prependMessageContextToContent(current.content, messageContextText(current)),\n providerName,\n supportsPdfAttachments,\n resolvePdfUrl\n ).pipe(Effect.map(content => ({ role: 'user' as const, content })))\n ),\n Match.tag('Assistant', current => {\n const content = prependMessageContextToContent(\n assistantContent(current),\n messageContextText(current)\n )\n\n const reasoning = reasoningContent ? assistantReasoningText(current) : ''\n const reasoningFields = reasoning.length > 0 ? { reasoning_content: reasoning } : {}\n\n return Effect.forEach(assistantHostToolCalls(current), call =>\n toolCallToOpenAiToolCall(call, providerName)\n ).pipe(\n Effect.flatMap(toolCalls =>\n contentToText(content, 'Assistant', providerName).pipe(\n Effect.map(text =>\n toolCalls.length > 0\n ? {\n role: 'assistant' as const,\n content: text,\n tool_calls: toolCalls,\n ...reasoningFields\n }\n : {\n role: 'assistant' as const,\n content: text,\n ...reasoningFields\n }\n )\n )\n )\n )\n }),\n Match.tag('ToolResult', current =>\n contentToText(\n prependMessageContextToContent(current.content, messageContextText(current)),\n 'Tool result',\n providerName\n ).pipe(\n Effect.map(content => ({\n role: 'tool' as const,\n tool_call_id: current.toolCallId,\n content\n }))\n )\n ),\n Match.exhaustive\n )\n\nconst toOpenAiTool = (tool: ToolDef, providerName: string): Effect.Effect<OpenAiTool, LLMError> =>\n Schema.decodeUnknownEffect(Schema.Json)(tool.parameters).pipe(\n Effect.mapError(\n schemaErrorToLlmError('provider_error', `Invalid ${providerName} tool parameters JSON`)\n ),\n Effect.map((parameters): OpenAiTool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters\n }\n }))\n )\n\nexport const toOpenAiRequestBody = (\n request: LLMRequest,\n config: OpenAiRequestBodyConfig\n): Effect.Effect<OpenAiRequestBody, LLMError> =>\n Effect.gen(function* () {\n const providerName = config.providerName ?? defaultOpenAiProviderIdentity.name\n\n if (!Number.isSafeInteger(config.maxCompletionTokens) || config.maxCompletionTokens <= 0) {\n return yield* Effect.fail(\n new LLMError({\n cause: 'validation_error',\n message: `${providerName} maxCompletionTokens must be a positive safe integer`,\n retryable: false\n })\n )\n }\n\n yield* validateProviderTranscript(request.messages)\n const systemMessage: OpenAiMessage = { role: 'system', content: request.systemPrompt }\n\n const requestMessages = yield* Effect.forEach(request.messages, message =>\n toOpenAiMessage(\n message,\n providerName,\n config.reasoningContent ?? false,\n config.supportsPdfAttachments ?? false,\n config.resolvePdfUrl\n )\n )\n\n const messages = [systemMessage, ...requestMessages]\n\n const completionTokenLimit =\n config.completionTokenField === 'max_tokens'\n ? { max_tokens: config.maxCompletionTokens }\n : { max_completion_tokens: config.maxCompletionTokens }\n\n const reasoning =\n request.reasoningEffort === undefined\n ? {}\n : config.reasoningEffortFormat === 'reasoning-object'\n ? { reasoning: { effort: request.reasoningEffort } }\n : config.reasoningEffortFormat === 'reasoning-effort'\n ? { reasoning_effort: request.reasoningEffort }\n : {}\n\n const extraBody =\n config.extraBody === undefined\n ? {}\n : yield* snapshotOpenAiRequestExtras(config.extraBody, config, providerName)\n\n const streaming = config.streaming === true\n\n // Usage only arrives on the stream when the endpoint is asked for it.\n const bodyWithoutTools: OpenAiRequestBody = streaming\n ? {\n ...extraBody,\n ...reasoning,\n model: request.model,\n messages,\n ...completionTokenLimit,\n stream: true,\n stream_options: { include_usage: true }\n }\n : {\n ...extraBody,\n ...reasoning,\n model: request.model,\n messages,\n ...completionTokenLimit,\n stream: false\n }\n\n const body: OpenAiRequestBody =\n request.tools.length === 0\n ? bodyWithoutTools\n : {\n ...bodyWithoutTools,\n tools: yield* Effect.forEach(request.tools, tool => toOpenAiTool(tool, providerName)),\n parallel_tool_calls: true\n }\n\n return body\n })\n\nconst parseToolArguments = (raw: string, providerName: string) =>\n decodeJsonString(raw, `Invalid ${providerName} tool arguments JSON`)\n\nconst toLlmEvents = (\n choice: OpenAiChoiceResponse,\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean\n): Effect.Effect<ReadonlyArray<LLMEvent>, LLMError> =>\n Effect.gen(function* () {\n if (choice.finish_reason === 'length' || choice.finish_reason === 'content_filter') {\n return yield* Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} response stopped with ${choice.finish_reason}`,\n retryable: false,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: 'invalid_response',\n providerCode: choice.finish_reason\n })\n })\n )\n }\n\n const content = choice.message.content ?? ''\n\n const reasoning = reasoningContent\n ? ((yield* Schema.decodeUnknownEffect(Schema.NullOr(Schema.String))(\n choice.message.reasoning_content ?? choice.message.reasoning ?? null\n ).pipe(\n Effect.mapError(\n schemaErrorToLlmError(\n 'invalid_response',\n `Invalid ${providerIdentity.name} reasoning content`\n )\n )\n )) ?? '')\n : ''\n\n const textEvents: Array<LLMEvent> = []\n\n if (reasoning.length > 0) textEvents.push(LLMReasoningDelta.make({ text: reasoning }))\n\n if (content.length > 0) textEvents.push(LLMTextDelta.make({ text: content }))\n\n const toolCallEvents = yield* Effect.forEach(choice.message.tool_calls ?? [], call =>\n parseToolArguments(call.function.arguments, providerIdentity.name).pipe(\n Effect.map(params =>\n LLMToolCall.make({\n call: ToolCall.make({\n id: call.id,\n name: call.function.name,\n params\n })\n })\n )\n )\n )\n\n if (toolCallEvents.length > 0) {\n return [...textEvents, ...toolCallEvents, LLMDone.make({ stopReason: 'tool_use' })]\n }\n\n return [...textEvents, LLMDone.make({ stopReason: 'stop' })]\n })\n\nconst toAgentUsage = (usage: OpenAiUsageResponse) =>\n AgentUsage.make({\n input: AgentInputUsage.make({\n total: usage.prompt_tokens,\n uncached: usage.prompt_tokens - (usage.prompt_tokens_details?.cached_tokens ?? 0),\n cacheRead: usage.prompt_tokens_details?.cached_tokens\n }),\n output: AgentOutputUsage.make({\n total: usage.completion_tokens,\n reasoning: usage.completion_tokens_details?.reasoning_tokens,\n text: usage.completion_tokens - (usage.completion_tokens_details?.reasoning_tokens ?? 0)\n })\n })\n\ntype OpenAiChatStreamToolCall = {\n readonly index: number\n readonly id: string | undefined\n readonly name: string | undefined\n readonly arguments: string\n}\n\ntype OpenAiChatStreamState = {\n readonly buffer: string\n readonly toolCalls: ReadonlyArray<OpenAiChatStreamToolCall>\n readonly finishReason: string | undefined\n readonly hasTerminal: boolean\n // Only [DONE] closes the stream: usage commonly arrives after the finish\n // chunk, so a bare finish reason must not discard later payloads.\n readonly streamClosed: boolean\n readonly usage: unknown\n readonly receivedBytes: number\n readonly outputStarted: boolean\n}\n\nconst initialOpenAiChatStreamState: OpenAiChatStreamState = {\n buffer: '',\n toolCalls: [],\n finishReason: undefined,\n hasTerminal: false,\n streamClosed: false,\n usage: undefined,\n receivedBytes: 0,\n outputStarted: false\n}\n\n// Split on blank lines in any newline style. Only CRLF pairs normalize, so a\n// chunk-ending lone CR stays pending and a split CRLF (or CR + multiline\n// continuation) cannot form a false event boundary. A \\r\\n surviving\n// normalization always spans two original breaks (a lone CR plus a collapsed\n// pair or lone LF), so recognizing it cannot re-split an atomic CRLF.\nconst splitCompleteChatSseBlocks = (buffer: string) => {\n const blocks = buffer.replace(/\\r\\n/g, '\\n').split(/\\n\\n|\\n\\r|\\r\\r|\\r\\n/)\n const tail = blocks.at(-1) ?? ''\n\n return { completeBlocks: blocks.slice(0, -1), tail }\n}\n\nconst chatSseBlockData = (block: string) => {\n const lines = block\n .split(/\\r\\n|\\n|\\r/)\n .filter(line => line.startsWith('data:'))\n .map(line => line.slice(5).trimStart())\n\n const done = lines.some(line => line === '[DONE]')\n\n const data = lines\n .filter(line => line.length > 0 && line !== '[DONE]')\n .join('\\n')\n .trim()\n\n return { done, payload: data.length > 0 ? data : undefined }\n}\n\n// Stream construction failures use fixed messages: schema diagnostics and\n// upstream values stay out of LLMError per provider sanitization policy.\nconst invalidChatStreamEvent = (providerIdentity: OpenAiProviderIdentity) =>\n new LLMError({\n cause: 'invalid_response',\n message: `Invalid ${providerIdentity.name} stream event`,\n retryable: false\n })\n\nconst chatStreamError = (\n providerIdentity: OpenAiProviderIdentity,\n raw: string\n): Effect.Effect<never, LLMError> =>\n Effect.gen(function* () {\n const errorCode = yield* decodeOpenAiHttpErrorCode(raw)\n\n const provider = classifyProviderFailure({\n provider: providerIdentity.id,\n body: raw,\n providerCode: errorCode\n })\n\n return yield* Effect.fail(\n new LLMError({\n cause: providerFailureCause(provider.kind),\n message: `${providerIdentity.name} stream reported an error`,\n retryable: providerFailureRetryable(provider.kind),\n provider\n })\n )\n })\n\nconst mergeChatToolCallDelta = (\n toolCalls: ReadonlyArray<OpenAiChatStreamToolCall>,\n delta: typeof OpenAiChatDeltaToolCall.Type\n): ReadonlyArray<OpenAiChatStreamToolCall> => {\n const index = delta.index ?? 0\n const current = toolCalls.find(call => call.index === index)\n\n const merged = {\n index,\n id: delta.id ?? current?.id,\n name: delta.function?.name ?? current?.name,\n arguments: `${current?.arguments ?? ''}${delta.function?.arguments ?? ''}`\n }\n\n return [...toolCalls.filter(call => call.index !== index), merged]\n}\n\nconst decodeChatDeltaReasoning = (\n providerIdentity: OpenAiProviderIdentity,\n reasoning: unknown\n): Effect.Effect<string, LLMError> =>\n Schema.decodeUnknownEffect(Schema.NullOr(Schema.String))(reasoning).pipe(\n Effect.map(value => value ?? ''),\n Effect.mapError(() => invalidChatStreamEvent(providerIdentity))\n )\n\ntype OpenAiChatStreamStep = {\n readonly state: OpenAiChatStreamState\n readonly events: ReadonlyArray<LLMEvent>\n}\n\nconst processChatStreamPayload = (\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean,\n state: OpenAiChatStreamState,\n payload: string\n): Effect.Effect<OpenAiChatStreamStep, LLMError> =>\n Effect.gen(function* () {\n const parsed = yield* Schema.decodeUnknownEffect(JsonFromJsonString)(payload).pipe(\n Effect.mapError(() => invalidChatStreamEvent(providerIdentity))\n )\n\n const envelope = isJsonRecord(parsed) ? jsonRecordField(parsed, 'error') : undefined\n\n if (envelope !== undefined && isJsonRecord(envelope)) {\n return yield* chatStreamError(providerIdentity, payload)\n }\n\n const chunk = yield* Schema.decodeUnknownEffect(OpenAiChatStreamChunk)(parsed).pipe(\n Effect.mapError(() => invalidChatStreamEvent(providerIdentity))\n )\n\n const events: Array<LLMEvent> = []\n let toolCalls = state.toolCalls\n let finishReason = state.finishReason\n let usage = state.usage\n\n for (const choice of chunk.choices ?? []) {\n if (choice.delta?.content) {\n events.push(LLMTextDelta.make({ text: choice.delta.content }))\n }\n\n if (\n reasoningContent &&\n (choice.delta?.reasoning_content != null || choice.delta?.reasoning != null)\n ) {\n const reasoning = yield* decodeChatDeltaReasoning(\n providerIdentity,\n choice.delta.reasoning_content ?? choice.delta.reasoning ?? null\n )\n\n if (reasoning.length > 0) events.push(LLMReasoningDelta.make({ text: reasoning }))\n }\n\n for (const call of choice.delta?.tool_calls ?? []) {\n toolCalls = mergeChatToolCallDelta(toolCalls, call)\n }\n\n if (\n choice.finish_reason !== undefined &&\n choice.finish_reason !== null &&\n finishReason === undefined\n ) {\n finishReason = choice.finish_reason\n }\n\n if (choice.usage !== undefined) usage = choice.usage\n }\n\n if (chunk.usage !== undefined) usage = chunk.usage\n\n return {\n state: {\n ...state,\n toolCalls,\n finishReason,\n hasTerminal: state.hasTerminal || finishReason !== undefined,\n usage,\n outputStarted: state.outputStarted || events.length > 0\n },\n events\n }\n })\n\nconst processChatStreamBlock = (\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean,\n state: OpenAiChatStreamState,\n block: string\n): Effect.Effect<OpenAiChatStreamStep, LLMError> =>\n Effect.gen(function* () {\n // Frames after [DONE] are transport noise: ignore them so a malformed\n // trailer cannot fail an otherwise completed turn.\n if (state.streamClosed) return { state, events: [] }\n\n const { done, payload } = chatSseBlockData(block)\n\n const current: OpenAiChatStreamState = done\n ? { ...state, hasTerminal: true, streamClosed: true }\n : state\n\n if (payload === undefined) return { state: current, events: [] }\n\n return yield* processChatStreamPayload(providerIdentity, reasoningContent, current, payload)\n })\n\nconst chatStreamDiagnostics = (\n responseFormat: ProviderStreamResponseFormat,\n state: OpenAiChatStreamState\n) =>\n ProviderStreamDiagnostics.make({\n protocol: 'chat-completions',\n responseFormat,\n receivedBytes: state.receivedBytes,\n bufferedChars: state.buffer.length,\n outputStarted: state.outputStarted,\n terminalSeen: state.hasTerminal\n })\n\nconst processChatStreamText = (\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean,\n state: OpenAiChatStreamState,\n text: string\n): Effect.Effect<OpenAiChatStreamStep, LLMError> =>\n Effect.gen(function* () {\n const split = splitCompleteChatSseBlocks(`${state.buffer}${text}`)\n let current: OpenAiChatStreamState = { ...state, buffer: split.tail }\n const events: Array<LLMEvent> = []\n\n for (const block of split.completeBlocks) {\n const step = yield* processChatStreamBlock(providerIdentity, reasoningContent, current, block)\n current = step.state\n events.push(...step.events)\n }\n\n return { state: current, events }\n })\n\nconst finalizeChatStreamState = (\n providerIdentity: OpenAiProviderIdentity,\n responseFormat: ProviderStreamResponseFormat,\n state: OpenAiChatStreamState\n): Effect.Effect<ReadonlyArray<LLMEvent>, LLMError> =>\n Effect.gen(function* () {\n if (!state.hasTerminal) {\n return yield* Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} stream ended before a terminal chunk`,\n retryable: false,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: 'invalid_response',\n providerCode: 'incomplete_stream',\n stream: chatStreamDiagnostics(responseFormat, state)\n })\n })\n )\n }\n\n if (state.finishReason === 'length' || state.finishReason === 'content_filter') {\n return yield* Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} response stopped with ${state.finishReason}`,\n retryable: false,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: 'invalid_response',\n providerCode: state.finishReason\n })\n })\n )\n }\n\n if (\n state.finishReason !== undefined &&\n state.finishReason !== 'stop' &&\n state.finishReason !== 'tool_calls'\n ) {\n const provider = classifyProviderFailure({\n provider: providerIdentity.id,\n body: state.finishReason,\n providerCode: state.finishReason\n })\n\n return yield* Effect.fail(\n new LLMError({\n cause: 'provider_error',\n message: `${providerIdentity.name} stream stopped with unrecognized finish reason`,\n retryable: false,\n provider\n })\n )\n }\n\n const orderedCalls = [...state.toolCalls].sort((left, right) => left.index - right.index)\n\n const toolCallEvents = yield* Effect.forEach(orderedCalls, call => {\n const id = call.id\n const name = call.name\n\n if (id === undefined || name === undefined) {\n return Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `Invalid ${providerIdentity.name} streamed tool call`,\n retryable: false\n })\n )\n }\n\n return parseToolArguments(call.arguments, providerIdentity.name).pipe(\n Effect.map(params => LLMToolCall.make({ call: ToolCall.make({ id, name, params }) }))\n )\n })\n\n const events: Array<LLMEvent> = [...toolCallEvents]\n\n events.push(LLMDone.make({ stopReason: toolCallEvents.length > 0 ? 'tool_use' : 'stop' }))\n\n if (state.usage !== undefined) {\n const usage = yield* Schema.decodeUnknownEffect(OpenAiUsageResponse)(state.usage).pipe(\n Effect.mapError(() => invalidChatStreamEvent(providerIdentity))\n )\n\n events.push(LLMUsage.make({ usage: toAgentUsage(usage) }))\n }\n\n return events\n })\n\nconst chatStreamResponseFormat = (\n contentType: string | undefined\n): ProviderStreamResponseFormat => {\n if (contentType === undefined) return 'unknown'\n\n const mediaType = contentType.split(';', 1)[0].trim().toLowerCase()\n\n if (mediaType === 'text/event-stream') return 'sse'\n\n if (mediaType === 'application/json' || mediaType.endsWith('+json')) return 'json'\n\n return 'other'\n}\n\nconst expectChatSseResponse = (\n providerIdentity: OpenAiProviderIdentity,\n response: HttpClientResponse.HttpClientResponse\n): Effect.Effect<ProviderStreamResponseFormat, LLMError> => {\n const responseFormat = chatStreamResponseFormat(response.headers['content-type'])\n\n // Accept missing Content-Type for compatibility with existing SSE endpoints.\n if (responseFormat === 'sse' || responseFormat === 'unknown') {\n return Effect.succeed(responseFormat)\n }\n\n return Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} streaming response was not an SSE stream`,\n retryable: false,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: 'invalid_response',\n status: response.status,\n providerCode: 'unexpected_content_type',\n stream: ProviderStreamDiagnostics.make({\n protocol: 'chat-completions',\n responseFormat,\n receivedBytes: 0,\n bufferedChars: 0,\n outputStarted: false,\n terminalSeen: false\n })\n })\n })\n )\n}\n\nconst streamOpenAiChatResponse = (\n providerIdentity: OpenAiProviderIdentity,\n reasoningContent: boolean,\n responseFormat: ProviderStreamResponseFormat,\n response: HttpClientResponse.HttpClientResponse\n): Stream.Stream<LLMEvent, LLMError> =>\n Stream.unwrap(\n Ref.make(initialOpenAiChatStreamState).pipe(\n Effect.map(stateRef => {\n const chunks = response.stream.pipe(\n Stream.mapError(toHttpClientLlmError(providerIdentity, true)),\n Stream.tap(chunk =>\n Ref.update(stateRef, state => ({\n ...state,\n receivedBytes: state.receivedBytes + chunk.byteLength\n }))\n ),\n Stream.decodeText,\n Stream.mapEffect(chunk =>\n Effect.gen(function* () {\n const state = yield* Ref.get(stateRef)\n\n const step = yield* processChatStreamText(\n providerIdentity,\n reasoningContent,\n state,\n chunk\n )\n\n yield* Ref.set(stateRef, step.state)\n\n return step.events\n })\n ),\n Stream.flatMap(events => Stream.fromIterable(events))\n )\n\n const finalEvents = Stream.fromEffect(\n Ref.get(stateRef).pipe(\n Effect.flatMap(state =>\n finalizeChatStreamState(providerIdentity, responseFormat, state)\n )\n )\n ).pipe(Stream.flatMap(events => Stream.fromIterable(events)))\n\n return chunks.pipe(Stream.concat(finalEvents))\n })\n )\n )\n\nconst toHttpClientLlmError =\n (providerIdentity: OpenAiProviderIdentity, retryable: boolean) =>\n (error: HttpClientError.HttpClientError) =>\n new LLMError({\n cause: 'provider_error',\n message: `${providerIdentity.name} request failed: ${error.message}`,\n retryable,\n provider: providerErrorInfo({\n provider: providerIdentity.id,\n kind: retryable ? 'network' : 'unknown'\n })\n })\n\nconst parseOpenAiResponseJson = (\n response: HttpClientResponse.HttpClientResponse,\n providerName: string\n): Effect.Effect<Schema.Json, LLMError> =>\n Effect.gen(function* () {\n const raw = yield* response.json.pipe(\n Effect.mapError(\n error =>\n new LLMError({\n cause: 'invalid_response',\n message: `Could not parse ${providerName} response JSON: ${error.message}`,\n retryable: false\n })\n )\n )\n\n return yield* Schema.decodeUnknownEffect(Schema.Json)(raw).pipe(\n Effect.mapError(\n schemaErrorToLlmError('invalid_response', `Could not parse ${providerName} response JSON`)\n )\n )\n })\n\nconst openAiRequestBodyFields = (\n config: OpenAiProviderConfig,\n providerIdentity: OpenAiProviderIdentity,\n resolvePdfUrl?: ResolvePdfUrl\n): OpenAiRequestBodyConfigFields => {\n const fields: OpenAiRequestBodyConfigFields = {\n maxCompletionTokens: config.maxCompletionTokens,\n providerName: providerIdentity.name\n }\n\n if (config.completionTokenField !== undefined) {\n fields.completionTokenField = config.completionTokenField\n }\n\n if (config.extraBody !== undefined) {\n fields.extraBody = config.extraBody\n }\n\n if (config.reasoningEffortFormat !== undefined) {\n fields.reasoningEffortFormat = config.reasoningEffortFormat\n }\n\n if (config.reasoningContent !== undefined) {\n fields.reasoningContent = config.reasoningContent\n }\n\n if (config.streaming !== undefined) {\n fields.streaming = config.streaming\n }\n\n if (config.supportsPdfAttachments !== undefined) {\n fields.supportsPdfAttachments = config.supportsPdfAttachments\n }\n\n if (resolvePdfUrl !== undefined) {\n fields.resolvePdfUrl = resolvePdfUrl\n }\n\n return fields\n}\n\nconst serializeOpenAiRequestBody = (\n body: OpenAiRequestBody,\n providerName: string\n): Effect.Effect<string, LLMError> =>\n // Replayed transcripts can carry lone surrogates; harden the lowered\n // body so one bad historical string cannot poison every model call.\n Schema.decodeUnknownEffect(Schema.Json)(replaceLoneSurrogatesDeep(body)).pipe(\n Effect.mapError(\n schemaErrorToLlmError('provider_error', `Could not serialize ${providerName} request`)\n ),\n Effect.flatMap(json => encodeJsonString(json, `Could not serialize ${providerName} request`))\n )\n\nconst postOpenAiRequest = (\n config: OpenAiProviderConfig,\n providerIdentity: OpenAiProviderIdentity,\n serializedBody: string,\n client: HttpClient.HttpClient\n): Effect.Effect<HttpClientResponse.HttpClientResponse, LLMError> =>\n Effect.gen(function* () {\n const httpRequest = HttpClientRequest.post(\n config.chatCompletionsUrl ?? 'https://api.openai.com/v1/chat/completions'\n ).pipe(\n HttpClientRequest.setHeaders({\n ...config.extraHeaders,\n accept: config.streaming === true ? 'text/event-stream' : 'application/json',\n authorization: `Bearer ${Redacted.value(config.apiKey)}`,\n 'content-type': 'application/json'\n }),\n HttpClientRequest.bodyText(serializedBody, 'application/json')\n )\n\n const response = yield* client\n .execute(httpRequest)\n .pipe(Effect.mapError(toHttpClientLlmError(providerIdentity, true)))\n\n if (response.status < 200 || response.status >= 300) {\n const errorText = yield* response.text.pipe(\n Effect.mapError(\n error =>\n new LLMError({\n cause: 'provider_error',\n message: `Could not read ${providerIdentity.name} error body: ${error.message}`,\n retryable: false\n })\n )\n )\n\n const errorCode = yield* decodeOpenAiHttpErrorCode(errorText)\n\n const provider = classifyProviderFailure({\n provider: providerIdentity.id,\n status: response.status,\n headers: response.headers,\n body: errorText,\n providerCode: errorCode\n })\n\n return yield* Effect.fail(\n new LLMError({\n cause: providerFailureCause(provider.kind),\n message: `${providerIdentity.name} returned ${response.status}`,\n retryable: providerFailureRetryable(provider.kind),\n provider\n })\n )\n }\n\n return response\n })\n\nconst pdfDataUrlFromResponse = (\n response: HttpClientResponse.HttpClientResponse,\n providerName: string\n) => {\n if (response.status < 200 || response.status >= 300) {\n return Effect.fail(\n new LLMError({\n cause: 'provider_error',\n message: `Could not fetch PDF attachment for ${providerName}: returned ${response.status}`,\n retryable: false\n })\n )\n }\n\n return response.arrayBuffer.pipe(\n Effect.mapError(\n error =>\n new LLMError({\n cause: 'provider_error',\n message: `Could not read PDF attachment for ${providerName}: ${error.message}`,\n retryable: false\n })\n ),\n Effect.map(\n bytes => `data:application/pdf;base64,${Encoding.encodeBase64(new Uint8Array(bytes))}`\n )\n )\n}\n\nconst pdfUrlResolver =\n (client: HttpClient.HttpClient, providerName: string): ResolvePdfUrl =>\n url =>\n client.get(url).pipe(\n Effect.mapError(\n error =>\n new LLMError({\n cause: 'provider_error',\n message: `Could not fetch PDF attachment for ${providerName}: ${error.message}`,\n retryable: false\n })\n ),\n Effect.flatMap(response => pdfDataUrlFromResponse(response, providerName))\n )\n\nconst sendOpenAiRequestBody = (\n config: OpenAiProviderConfig,\n request: LLMRequest,\n providerIdentity: OpenAiProviderIdentity,\n client: HttpClient.HttpClient\n): Effect.Effect<string, LLMError> =>\n Effect.gen(function* () {\n const resolvePdfUrl =\n config.supportsPdfAttachments === true\n ? pdfUrlResolver(client, providerIdentity.name)\n : undefined\n\n const body = yield* toOpenAiRequestBody(\n request,\n openAiRequestBodyFields(config, providerIdentity, resolvePdfUrl)\n )\n\n return yield* serializeOpenAiRequestBody(body, providerIdentity.name)\n })\n\nconst sendOpenAiRequest = (\n config: OpenAiProviderConfig,\n request: LLMRequest,\n client: HttpClient.HttpClient\n): Effect.Effect<ReadonlyArray<LLMEvent>, LLMError> =>\n Effect.gen(function* () {\n const providerIdentity = config.providerIdentity ?? defaultOpenAiProviderIdentity\n const serializedBody = yield* sendOpenAiRequestBody(config, request, providerIdentity, client)\n const response = yield* postOpenAiRequest(config, providerIdentity, serializedBody, client)\n const json = yield* parseOpenAiResponseJson(response, providerIdentity.name)\n\n const parsed = yield* Schema.decodeUnknownEffect(OpenAiChatCompletionResponse)(json).pipe(\n Effect.mapError(\n schemaErrorToLlmError('invalid_response', `Invalid ${providerIdentity.name} response`)\n )\n )\n\n const choice = parsed.choices[0]\n\n if (choice === undefined) {\n return yield* Effect.fail(\n new LLMError({\n cause: 'invalid_response',\n message: `${providerIdentity.name} response contained no choices`,\n retryable: false\n })\n )\n }\n\n const events = yield* toLlmEvents(choice, providerIdentity, config.reasoningContent ?? false)\n\n if (parsed.usage === undefined) {\n return events\n }\n\n return [...events, LLMUsage.make({ usage: toAgentUsage(parsed.usage) })]\n }).pipe(\n Effect.withSpan(`${config.providerIdentity?.id ?? defaultOpenAiProviderIdentity.id}.stream`)\n )\n\nconst streamOpenAiRequest = (\n config: OpenAiProviderConfig,\n request: LLMRequest,\n client: HttpClient.HttpClient\n): Stream.Stream<LLMEvent, LLMError> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const providerIdentity = config.providerIdentity ?? defaultOpenAiProviderIdentity\n const serializedBody = yield* sendOpenAiRequestBody(config, request, providerIdentity, client)\n const response = yield* postOpenAiRequest(config, providerIdentity, serializedBody, client)\n const responseFormat = yield* expectChatSseResponse(providerIdentity, response)\n\n return streamOpenAiChatResponse(\n providerIdentity,\n config.reasoningContent ?? false,\n responseFormat,\n response\n )\n })\n )\n\nconst openAiProviderStream = (\n config: OpenAiProviderConfig,\n request: LLMRequest,\n client: HttpClient.HttpClient\n): Stream.Stream<LLMEvent, LLMError> =>\n config.streaming === true\n ? streamOpenAiRequest(config, request, client)\n : Stream.fromEffect(sendOpenAiRequest(config, request, client)).pipe(\n Stream.flatMap(events => Stream.fromIterable(events))\n )\n\nexport const makeOpenAiProviderLayer = (config: OpenAiProviderConfig) =>\n Layer.effect(\n LLMProvider,\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n\n return LLMProvider.of({\n stream: request => openAiProviderStream(config, request, client)\n })\n })\n )\n\nexport const OpenAiProviderLayer = Layer.effect(\n LLMProvider,\n Effect.gen(function* () {\n const config = yield* OpenAiConfig\n const client = yield* HttpClient.HttpClient\n\n return LLMProvider.of({\n stream: request => openAiProviderStream(config, request, client)\n })\n })\n).pipe(Layer.provide(Layer.mergeAll(OpenAiConfigLayer, FetchHttpClient.layer)))\n"],"mappings":"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"}
@@ -29,7 +29,8 @@ type VercelAiGatewayProviderConfig = {
29
29
  * events (and replay into later requests, which spends input tokens).
30
30
  * Defaults to false; reasoning output is otherwise dropped.
31
31
  */
32
- readonly reasoningContent?: boolean;
32
+ readonly reasoningContent?: boolean; /** Enables native PDF file parts for the Gateway Chat Completions endpoint. */
33
+ readonly supportsPdfAttachments?: boolean;
33
34
  /**
34
35
  * Override the reasoning-effort wire format. Defaults to the Anthropic
35
36
  * `reasoning` object; DeepSeek-style hosts expect the literal
@@ -1 +1 @@
1
- {"version":3,"file":"ai-gateway-provider.d.mts","names":[],"sources":["../../../src/providers/vercel/ai-gateway-provider.ts"],"mappings":";;;;cAMa,yBAAA;AAAA,cAEA,iCAAA;AAAA,KAED,2BAAA;AAAA,KAEA,6BAAA;EAAA,SACD,KAAA,GAAQ,aAAA;EAAA,SACR,IAAA,GAAO,aAAA;EAAA,SACP,IAAA,GAAO,2BAAA;AAAA;AAAA,KAGN,6BAAA;8EAED,MAAA,EAAQ,QAAA,CAAS,QAAA;EAAA,SACjB,mBAAA;EAAA,SACA,cAAA,GAAiB,aAAA;EAAA,SACjB,OAAA,GAAU,6BAAA;EAAA,SACV,YAAA,GAAe,QAAA,CAAS,MAAA,mBAdI;EAAA,SAgB5B,kBAAA;EAdC;;;;;EAAA,SAoBD,SAAA;EAjBkC;;;;;;EAAA,SAwBlC,gBAAA;EAxBO;;AAA2B;AAG7C;;EAHkB,SA8BP,qBAAA;EAzBQ;;;;EAAA,SA8BR,QAAA;IAAA,SAAsB,IAAA;EAAA;AAAA;AAAA,cAqDpB,gCAAA,GAAoC,MAAA,EAAQ,6BAAA,KAA6B,KAAA,CAAA,KAAA,gCAAA,WAAA,mDAAA,UAAA;AAAA,cAgDzE,4BAAA,EAA4B,KAAA,CAAA,KAAA,gCAAA,WAAA,EAAA,QAAA"}
1
+ {"version":3,"file":"ai-gateway-provider.d.mts","names":[],"sources":["../../../src/providers/vercel/ai-gateway-provider.ts"],"mappings":";;;;cAMa,yBAAA;AAAA,cAEA,iCAAA;AAAA,KAED,2BAAA;AAAA,KAEA,6BAAA;EAAA,SACD,KAAA,GAAQ,aAAA;EAAA,SACR,IAAA,GAAO,aAAA;EAAA,SACP,IAAA,GAAO,2BAAA;AAAA;AAAA,KAGN,6BAAA;8EAED,MAAA,EAAQ,QAAA,CAAS,QAAA;EAAA,SACjB,mBAAA;EAAA,SACA,cAAA,GAAiB,aAAA;EAAA,SACjB,OAAA,GAAU,6BAAA;EAAA,SACV,YAAA,GAAe,QAAA,CAAS,MAAA,mBAdI;EAAA,SAgB5B,kBAAA;EAdC;;;;;EAAA,SAoBD,SAAA;EAjBkC;;;;;;EAAA,SAwBlC,gBAAA,YAxBO;EAAA,SA0BP,sBAAA;EA1BkC;AAG7C;;;;EAH6C,SAgClC,qBAAA;EAxBU;;;;EAAA,SA6BV,QAAA;IAAA,SAAsB,IAAA;EAAA;AAAA;AAAA,cAsDpB,gCAAA,GAAoC,MAAA,EAAQ,6BAAA,KAA6B,KAAA,CAAA,KAAA,gCAAA,WAAA,mDAAA,UAAA;AAAA,cAiDzE,4BAAA,EAA4B,KAAA,CAAA,KAAA,gCAAA,WAAA,EAAA,QAAA"}
@@ -30,7 +30,8 @@ const makeVercelAiGatewayProviderLayer = (config) => makeOpenAiProviderLayer((()
30
30
  reasoningEffortFormat: config.reasoningEffortFormat ?? "reasoning-object",
31
31
  chatCompletionsUrl: config.chatCompletionsUrl ?? "https://ai-gateway.vercel.sh/v1/chat/completions",
32
32
  providerIdentity: vercelAiGatewayProviderIdentity,
33
- extraBody: gatewayExtraBody(config)
33
+ extraBody: gatewayExtraBody(config),
34
+ supportsPdfAttachments: config.supportsPdfAttachments ?? true
34
35
  };
35
36
  if (config.extraHeaders !== void 0) fields.extraHeaders = config.extraHeaders;
36
37
  if (config.streaming !== void 0) fields.streaming = config.streaming;