@opencode-ai/ai 0.0.0-beta-17639 → 0.0.0-beta-17727

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +17 -6
  2. package/dist/cache-policy.js +3 -5
  3. package/dist/protocols/anthropic-messages.d.ts +26 -28
  4. package/dist/protocols/anthropic-messages.js +5 -5
  5. package/dist/protocols/gemini.d.ts +5 -9
  6. package/dist/protocols/gemini.js +5 -4
  7. package/dist/protocols/open-responses.d.ts +176 -38
  8. package/dist/protocols/open-responses.js +108 -33
  9. package/dist/protocols/openai-chat.d.ts +17 -15
  10. package/dist/protocols/openai-chat.js +8 -2
  11. package/dist/protocols/openai-compatible-chat.d.ts +3 -3
  12. package/dist/protocols/openai-compatible-responses.d.ts +27 -5
  13. package/dist/protocols/openai-responses.d.ts +151 -33
  14. package/dist/protocols/openai-responses.js +4 -2
  15. package/dist/protocols/shared.d.ts +8 -14
  16. package/dist/protocols/shared.js +8 -14
  17. package/dist/protocols/utils/bedrock-cache.js +3 -4
  18. package/dist/protocols/utils/cache.js +3 -6
  19. package/dist/protocols/utils/open-responses-options.d.ts +46 -15
  20. package/dist/protocols/utils/open-responses-options.js +38 -25
  21. package/dist/protocols/utils/openai-options.d.ts +7 -5
  22. package/dist/protocols/utils/openai-options.js +3 -3
  23. package/dist/provider-package.d.ts +0 -5
  24. package/dist/providers/amazon-bedrock-mantle.d.ts +43 -19
  25. package/dist/providers/amazon-bedrock-mantle.js +0 -1
  26. package/dist/providers/amazon-bedrock.d.ts +3 -9
  27. package/dist/providers/amazon-bedrock.js +0 -1
  28. package/dist/providers/anthropic-compatible.d.ts +11 -11
  29. package/dist/providers/anthropic-compatible.js +0 -1
  30. package/dist/providers/anthropic.d.ts +12 -12
  31. package/dist/providers/anthropic.js +0 -1
  32. package/dist/providers/azure.d.ts +40 -16
  33. package/dist/providers/azure.js +0 -1
  34. package/dist/providers/cloudflare.d.ts +11 -11
  35. package/dist/providers/google-vertex-chat.d.ts +5 -5
  36. package/dist/providers/google-vertex-chat.js +0 -1
  37. package/dist/providers/google-vertex-messages.d.ts +11 -11
  38. package/dist/providers/google-vertex-messages.js +0 -1
  39. package/dist/providers/google-vertex-responses.d.ts +29 -7
  40. package/dist/providers/google-vertex-responses.js +1 -2
  41. package/dist/providers/google-vertex.d.ts +5 -7
  42. package/dist/providers/google-vertex.js +1 -2
  43. package/dist/providers/google.d.ts +4 -4
  44. package/dist/providers/google.js +0 -1
  45. package/dist/providers/open-responses-options.d.ts +3 -14
  46. package/dist/providers/openai-compatible-responses.d.ts +29 -7
  47. package/dist/providers/openai-compatible-responses.js +0 -1
  48. package/dist/providers/openai-compatible.d.ts +13 -12
  49. package/dist/providers/openai-compatible.js +1 -1
  50. package/dist/providers/openai-options.d.ts +2 -4
  51. package/dist/providers/openai-options.js +3 -3
  52. package/dist/providers/openai.d.ts +44 -20
  53. package/dist/providers/openai.js +0 -1
  54. package/dist/providers/openrouter.d.ts +16 -17
  55. package/dist/providers/openrouter.js +1 -2
  56. package/dist/providers/xai.d.ts +46 -24
  57. package/dist/providers/xai.js +1 -2
  58. package/dist/route/client.d.ts +2 -6
  59. package/dist/route/client.js +1 -2
  60. package/dist/route/framing.d.ts +2 -2
  61. package/dist/route/protocol.d.ts +1 -2
  62. package/dist/route/protocol.js +1 -2
  63. package/dist/schema/errors.js +2 -1
  64. package/dist/schema/events.d.ts +5 -3
  65. package/dist/schema/events.js +5 -2
  66. package/dist/schema/ids.d.ts +0 -13
  67. package/dist/schema/ids.js +0 -9
  68. package/dist/schema/messages.d.ts +7 -7
  69. package/dist/schema/messages.js +5 -2
  70. package/dist/schema/options.d.ts +6 -22
  71. package/dist/schema/options.js +6 -30
  72. package/package.json +5 -5
@@ -66,6 +66,8 @@ export const InputItem = Schema.Union([
66
66
  Schema.Struct({ role: Schema.tag("developer"), content: Schema.String }),
67
67
  Schema.Struct({ role: Schema.tag("user"), content: Schema.Array(OpenResponsesInputContent) }),
68
68
  Schema.Struct({
69
+ type: Schema.tag("message"),
70
+ id: Schema.optionalKey(Schema.String),
69
71
  role: Schema.tag("assistant"),
70
72
  content: Schema.Array(OpenResponsesOutputText),
71
73
  phase: Schema.optionalKey(MessagePhase),
@@ -74,6 +76,7 @@ export const InputItem = Schema.Union([
74
76
  OpenResponsesItemReference,
75
77
  Schema.Struct({
76
78
  type: Schema.tag("function_call"),
79
+ id: Schema.optionalKey(Schema.String),
77
80
  call_id: Schema.String,
78
81
  name: Schema.String,
79
82
  arguments: Schema.String,
@@ -94,6 +97,11 @@ export const Tool = Schema.Struct({
94
97
  export const ToolChoice = Schema.Union([
95
98
  Schema.Literals(["auto", "none", "required"]),
96
99
  Schema.Struct({ type: Schema.tag("function"), name: Schema.String }),
100
+ Schema.Struct({
101
+ type: Schema.tag("allowed_tools"),
102
+ mode: Schema.Literals(["auto", "none", "required"]),
103
+ tools: Schema.Array(Schema.Struct({ type: Schema.tag("function"), name: Schema.String })),
104
+ }),
97
105
  ]);
98
106
  // Fields shared between the HTTP body and the WebSocket `response.create`
99
107
  // message. The HTTP body adds `stream: true`; the WebSocket message adds
@@ -106,6 +114,12 @@ export const coreFields = {
106
114
  tools: optionalArray(Tool),
107
115
  tool_choice: Schema.optional(ToolChoice),
108
116
  store: Schema.optional(Schema.Boolean),
117
+ metadata: Schema.optional(Schema.Record(Schema.String, Schema.String)),
118
+ safety_identifier: Schema.optional(Schema.String),
119
+ stream_options: Schema.optional(Schema.Struct({
120
+ include_obfuscation: Schema.optional(Schema.Boolean),
121
+ })),
122
+ top_logprobs: Schema.optional(Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 20 }))),
109
123
  truncation: Schema.optional(OpenResponsesOptions.TruncationSchema),
110
124
  service_tier: Schema.optional(OpenResponsesOptions.ServiceTierSchema),
111
125
  prompt_cache_key: Schema.optional(Schema.String),
@@ -118,8 +132,12 @@ export const coreFields = {
118
132
  verbosity: Schema.optional(OpenResponsesOptions.TextVerbositySchema),
119
133
  })),
120
134
  max_output_tokens: Schema.optional(Schema.Number),
135
+ max_tool_calls: Schema.optional(Schema.Int),
136
+ parallel_tool_calls: Schema.optional(Schema.Boolean),
121
137
  temperature: Schema.optional(Schema.Number),
122
138
  top_p: Schema.optional(Schema.Number),
139
+ presence_penalty: Schema.optional(Schema.Number),
140
+ frequency_penalty: Schema.optional(Schema.Number),
123
141
  };
124
142
  const OpenResponsesBody = Schema.Struct({
125
143
  ...coreFields,
@@ -195,6 +213,19 @@ export const Event = Schema.StructWithRest(Schema.Struct({
195
213
  status_code: Schema.optional(Schema.Unknown),
196
214
  headers: Schema.optional(Schema.Unknown),
197
215
  }), [Schema.Record(Schema.String, Schema.Unknown)]);
216
+ const RefusalEvent = Schema.Union([
217
+ Schema.Struct({
218
+ type: Schema.tag("response.refusal.delta"),
219
+ item_id: Schema.String,
220
+ delta: Schema.String,
221
+ }),
222
+ Schema.Struct({
223
+ type: Schema.tag("response.refusal.done"),
224
+ item_id: Schema.String,
225
+ refusal: Schema.String,
226
+ }),
227
+ ]);
228
+ const isRefusalEvent = Schema.is(RefusalEvent);
198
229
  const BASE = { id: ADAPTER, name: NAME };
199
230
  // =============================================================================
200
231
  // Request Lowering
@@ -207,7 +238,7 @@ export const lowerTool = Effect.fn("OpenResponses.lowerTool")(function* (protoco
207
238
  name: tool.name,
208
239
  description: tool.description,
209
240
  parameters: ToolSchemaProjection.responses(inputSchema),
210
- // TODO: Read this from Responses tool options so direct LLM callers can opt into strict schemas.
241
+ // The common tool definition does not currently express Responses strict-schema policy.
211
242
  strict: false,
212
243
  };
213
244
  });
@@ -217,31 +248,39 @@ export const lowerToolChoice = (protocolName, toolChoice) => ProviderShared.matc
217
248
  required: () => "required",
218
249
  tool: (toolName) => ({ type: "function", name: toolName }),
219
250
  });
220
- const lowerToolCall = (part) => ({
221
- type: "function_call",
222
- call_id: part.id,
223
- name: part.name,
224
- arguments: ProviderShared.encodeJson(part.input),
225
- });
251
+ const itemID = (providerMetadata, providerMetadataKey) => {
252
+ const metadata = providerMetadata?.[providerMetadataKey];
253
+ return ProviderShared.isRecord(metadata) && typeof metadata.itemId === "string" && metadata.itemId.length > 0
254
+ ? metadata.itemId
255
+ : undefined;
256
+ };
257
+ const lowerToolCall = (part, providerMetadataKey) => {
258
+ const id = itemID(part.providerMetadata, providerMetadataKey);
259
+ return {
260
+ type: "function_call",
261
+ ...(id ? { id } : {}),
262
+ call_id: part.id,
263
+ name: part.name,
264
+ arguments: ProviderShared.encodeJson(part.input),
265
+ };
266
+ };
226
267
  const lowerReasoning = (part, providerMetadataKey) => {
227
268
  const metadata = part.providerMetadata?.[providerMetadataKey];
228
- if (!ProviderShared.isRecord(metadata) || typeof metadata.itemId !== "string" || metadata.itemId.length === 0)
269
+ const id = itemID(part.providerMetadata, providerMetadataKey);
270
+ if (!ProviderShared.isRecord(metadata) || !id)
229
271
  return undefined;
230
272
  const encryptedContent = typeof metadata.reasoningEncryptedContent === "string" || metadata.reasoningEncryptedContent === null
231
273
  ? metadata.reasoningEncryptedContent
232
274
  : undefined;
233
275
  return {
234
276
  type: "reasoning",
235
- id: metadata.itemId,
277
+ id,
236
278
  summary: part.text.length > 0 ? [{ type: "summary_text", text: part.text }] : [],
237
279
  encrypted_content: encryptedContent,
238
280
  };
239
281
  };
240
282
  const hostedToolItemID = (part, providerMetadataKey) => {
241
- const metadata = part.providerMetadata?.[providerMetadataKey];
242
- return ProviderShared.isRecord(metadata) && typeof metadata.itemId === "string" && metadata.itemId.length > 0
243
- ? metadata.itemId
244
- : undefined;
283
+ return itemID(part.providerMetadata, providerMetadataKey);
245
284
  };
246
285
  const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (part, request, extension) {
247
286
  const media = ProviderShared.normalizeMedia(part);
@@ -310,15 +349,18 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
310
349
  return;
311
350
  const groups = content.reduce((groups, part) => {
312
351
  const metadata = part.providerMetadata?.[providerMetadataKey];
352
+ const id = itemID(part.providerMetadata, providerMetadataKey);
313
353
  const phase = ProviderShared.isRecord(metadata) ? messagePhase(metadata.phase, extension) : undefined;
314
354
  const group = groups.at(-1);
315
- if (group && group.phase === phase)
355
+ if (group && group.id === id && group.phase === phase)
316
356
  group.parts.push(part);
317
357
  else
318
- groups.push({ phase, parts: [part] });
358
+ groups.push({ id, phase, parts: [part] });
319
359
  return groups;
320
360
  }, []);
321
361
  input.push(...groups.map((group) => ({
362
+ type: "message",
363
+ ...(group.id === undefined ? {} : { id: group.id }),
322
364
  role: "assistant",
323
365
  content: group.parts.map((part) => ({ type: "output_text", text: part.text })),
324
366
  ...(group.phase === undefined ? {} : { phase: group.phase }),
@@ -348,20 +390,15 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
348
390
  existing.encrypted_content = reasoning.encrypted_content;
349
391
  continue;
350
392
  }
351
- const replay = {
352
- type: reasoning.type,
353
- summary: reasoning.summary,
354
- encrypted_content: reasoning.encrypted_content,
355
- };
356
- reasoningItems[reasoning.id] = replay;
357
- input.push(replay);
393
+ reasoningItems[reasoning.id] = reasoning;
394
+ input.push(reasoning);
358
395
  continue;
359
396
  }
360
397
  if (part.type === "tool-call") {
361
398
  flushText();
362
399
  if (part.providerExecuted === true)
363
400
  continue;
364
- input.push(lowerToolCall(part));
401
+ input.push(lowerToolCall(part, providerMetadataKey));
365
402
  continue;
366
403
  }
367
404
  if (part.type === "tool-result" && part.providerExecuted === true) {
@@ -412,6 +449,12 @@ const lowerOptions = (request) => {
412
449
  return {
413
450
  ...(options.instructions ? { instructions: options.instructions } : {}),
414
451
  ...(options.store !== undefined ? { store: options.store } : {}),
452
+ ...(options.metadata ? { metadata: options.metadata } : {}),
453
+ ...(options.safetyIdentifier ? { safety_identifier: options.safetyIdentifier } : {}),
454
+ ...(options.streamOptions?.includeObfuscation !== undefined
455
+ ? { stream_options: { include_obfuscation: options.streamOptions.includeObfuscation } }
456
+ : {}),
457
+ ...(options.topLogprobs !== undefined ? { top_logprobs: options.topLogprobs } : {}),
415
458
  ...(request.promptCacheKey ? { prompt_cache_key: request.promptCacheKey } : {}),
416
459
  ...(options.include ? { include: options.include } : {}),
417
460
  ...(options.reasoningEffort || options.reasoningSummary
@@ -419,9 +462,21 @@ const lowerOptions = (request) => {
419
462
  : {}),
420
463
  ...(options.textVerbosity ? { text: { verbosity: options.textVerbosity } } : {}),
421
464
  ...(options.serviceTier ? { service_tier: options.serviceTier } : {}),
465
+ ...(options.maxToolCalls !== undefined ? { max_tool_calls: options.maxToolCalls } : {}),
466
+ ...(options.parallelToolCalls !== undefined ? { parallel_tool_calls: options.parallelToolCalls } : {}),
422
467
  ...(options.truncation ? { truncation: options.truncation } : {}),
423
468
  };
424
469
  };
470
+ const allowedToolChoice = (request) => {
471
+ const allowed = OpenResponsesOptions.resolve(request).allowedTools;
472
+ if (!allowed)
473
+ return undefined;
474
+ return {
475
+ type: "allowed_tools",
476
+ mode: allowed.mode,
477
+ tools: allowed.toolNames.map((name) => ({ type: "function", name })),
478
+ };
479
+ };
425
480
  export const fromRequestWithExtension = Effect.fn("OpenResponses.fromRequestWithExtension")(function* (request, extension) {
426
481
  const generation = request.generation;
427
482
  const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
@@ -431,11 +486,14 @@ export const fromRequestWithExtension = Effect.fn("OpenResponses.fromRequestWith
431
486
  tools: request.tools.length === 0
432
487
  ? undefined
433
488
  : yield* Effect.forEach(request.tools, (tool) => lowerTool(extension.name, tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility))),
434
- tool_choice: request.toolChoice ? yield* lowerToolChoice(extension.name, request.toolChoice) : undefined,
489
+ tool_choice: allowedToolChoice(request) ??
490
+ (request.toolChoice ? yield* lowerToolChoice(extension.name, request.toolChoice) : undefined),
435
491
  stream: true,
436
492
  max_output_tokens: generation?.maxTokens,
437
493
  temperature: generation?.temperature,
438
494
  top_p: generation?.topP,
495
+ presence_penalty: generation?.presencePenalty,
496
+ frequency_penalty: generation?.frequencyPenalty,
439
497
  ...lowerOptions(request),
440
498
  };
441
499
  });
@@ -498,7 +556,7 @@ const onOutputTextDelta = (state, event, id) => {
498
556
  return [state, NO_EVENTS];
499
557
  const events = [];
500
558
  const phase = state.messagePhases[id];
501
- const metadata = phase === undefined ? undefined : providerMetadata(state, { phase });
559
+ const metadata = providerMetadata(state, { itemId: id, ...(phase === undefined ? {} : { phase }) });
502
560
  const lifecycle = Lifecycle.textStart(state.lifecycle, events, id, metadata);
503
561
  return [{ ...state, lifecycle: Lifecycle.textDelta(lifecycle, events, id, event.delta) }, events];
504
562
  };
@@ -682,7 +740,7 @@ const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
682
740
  return [
683
741
  {
684
742
  ...state,
685
- lifecycle: Lifecycle.textEnd(state.lifecycle, events, item.id, phase === undefined ? undefined : providerMetadata(state, { phase })),
743
+ lifecycle: Lifecycle.textEnd(state.lifecycle, events, item.id, providerMetadata(state, { itemId: item.id, ...(phase === undefined ? {} : { phase }) })),
686
744
  messageItems,
687
745
  messagePhases,
688
746
  },
@@ -694,7 +752,11 @@ const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
694
752
  return [state, NO_EVENTS];
695
753
  const tools = state.tools[item.id]
696
754
  ? state.tools
697
- : ToolStream.start(state.tools, item.id, { id: item.call_id, name: item.name });
755
+ : ToolStream.start(state.tools, item.id, {
756
+ id: item.call_id,
757
+ name: item.name,
758
+ providerMetadata: providerMetadata(state, { itemId: item.id }),
759
+ });
698
760
  const result = item.arguments === undefined
699
761
  ? yield* ToolStream.finish(state.id, tools, item.id)
700
762
  : yield* ToolStream.finishWithInput(state.id, tools, item.id, item.arguments);
@@ -737,11 +799,17 @@ const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
737
799
  }
738
800
  return [state, NO_EVENTS];
739
801
  });
740
- const onResponseFinish = (state, event) => {
741
- const events = [];
802
+ const onResponseFinish = Effect.fn("OpenResponses.onResponseFinish")(function* (state, event) {
803
+ // Some compatible providers omit output_item.done even after completing the response.
804
+ const pending = event.type === "response.completed"
805
+ ? yield* ToolStream.finishAll(state.id, state.tools)
806
+ : { tools: state.tools, events: NO_EVENTS };
807
+ const events = [...pending.events];
808
+ const hasFunctionCall = pending.events.some((event) => LLMEvent.is.toolCall(event) || LLMEvent.is.toolInputError(event)) ||
809
+ state.hasFunctionCall;
742
810
  const lifecycle = Lifecycle.finish(state.lifecycle, events, {
743
811
  reason: {
744
- normalized: mapFinishReason(event, state.hasFunctionCall),
812
+ normalized: mapFinishReason(event, hasFunctionCall),
745
813
  raw: event.response?.incomplete_details?.reason,
746
814
  },
747
815
  usage: mapUsage(event.response?.usage, state.providerMetadataKey),
@@ -752,8 +820,8 @@ const onResponseFinish = (state, event) => {
752
820
  })
753
821
  : undefined,
754
822
  });
755
- return [{ ...state, lifecycle }, events];
756
- };
823
+ return [{ ...state, lifecycle, hasFunctionCall, tools: pending.tools }, events];
824
+ });
757
825
  // Build a single human-readable message from whatever the provider supplied.
758
826
  // When both code and message are present, prefix the code so consumers see
759
827
  // the failure mode (e.g. `rate_limit_exceeded: Slow down`) instead of just
@@ -790,6 +858,13 @@ export const step = (state, event) => {
790
858
  ? onOutputTextDelta(state, event, event.item_id)
791
859
  : onOutputTextDone(state, event, event.item_id));
792
860
  }
861
+ if (event.type === "response.refusal.delta" || event.type === "response.refusal.done") {
862
+ if (!isRefusalEvent(event))
863
+ return ProviderShared.eventError(state.id, `${event.type} is malformed`);
864
+ return Effect.succeed(event.type === "response.refusal.delta"
865
+ ? onOutputTextDelta(state, event, event.item_id)
866
+ : onOutputTextDone(state, { ...event, text: event.refusal }, event.item_id));
867
+ }
793
868
  if (event.type === "response.reasoning.delta" || event.type === "response.reasoning_summary_text.delta") {
794
869
  if (!event.item_id)
795
870
  return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
@@ -821,7 +896,7 @@ export const step = (state, event) => {
821
896
  return onOutputItemDone(state, event);
822
897
  }
823
898
  if (event.type === "response.completed" || event.type === "response.incomplete")
824
- return Effect.succeed(onResponseFinish(state, event));
899
+ return onResponseFinish(state, event);
825
900
  if (event.type === "response.failed")
826
901
  return providerError(state, event, `${state.name} response failed`);
827
902
  if (event.type === "error")
@@ -95,7 +95,7 @@ export declare const bodyFields: {
95
95
  }>>;
96
96
  store: Schema.optional<Schema.Boolean>;
97
97
  prompt_cache_key: Schema.optional<Schema.String>;
98
- reasoning_effort: Schema.optional<Schema.String>;
98
+ reasoning_effort: Schema.optional<Schema.declare<import("./utils/open-responses-options.js").ReasoningEffort, import("./utils/open-responses-options.js").ReasoningEffort>>;
99
99
  max_completion_tokens: Schema.optional<Schema.Number>;
100
100
  max_tokens: Schema.optional<Schema.Number>;
101
101
  temperature: Schema.optional<Schema.Number>;
@@ -189,7 +189,7 @@ declare const OpenAIChatBody: Schema.Struct<{
189
189
  }>>;
190
190
  store: Schema.optional<Schema.Boolean>;
191
191
  prompt_cache_key: Schema.optional<Schema.String>;
192
- reasoning_effort: Schema.optional<Schema.String>;
192
+ reasoning_effort: Schema.optional<Schema.declare<import("./utils/open-responses-options.js").ReasoningEffort, import("./utils/open-responses-options.js").ReasoningEffort>>;
193
193
  max_completion_tokens: Schema.optional<Schema.Number>;
194
194
  max_tokens: Schema.optional<Schema.Number>;
195
195
  temperature: Schema.optional<Schema.Number>;
@@ -204,6 +204,7 @@ export declare const OpenAIChatEvent: Schema.Struct<{
204
204
  readonly choices: Schema.optional<Schema.NullOr<Schema.$Array<Schema.Struct<{
205
205
  readonly delta: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
206
206
  readonly content: Schema.optional<Schema.NullOr<Schema.String>>;
207
+ readonly refusal: Schema.optional<Schema.NullOr<Schema.String>>;
207
208
  readonly reasoning_content: Schema.optional<Schema.NullOr<Schema.String>>;
208
209
  readonly reasoning: Schema.optional<Schema.NullOr<Schema.String>>;
209
210
  readonly reasoning_text: Schema.optional<Schema.NullOr<Schema.String>>;
@@ -263,7 +264,7 @@ interface LoweringOptions {
263
264
  readonly cacheControl?: (cache: CacheHint | undefined) => Schema.Schema.Type<typeof OpenAIChatCacheControl> | undefined;
264
265
  }
265
266
  export declare const fromRequest: (request: LLMRequest, options?: LoweringOptions | undefined) => Effect.Effect<{
266
- reasoning_effort?: string | undefined;
267
+ reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
267
268
  prompt_cache_key?: string | undefined;
268
269
  store?: boolean | undefined;
269
270
  temperature: number | undefined;
@@ -347,7 +348,7 @@ export declare const fromRequest: (request: LLMRequest, options?: LoweringOption
347
348
  readonly ttl?: string | undefined;
348
349
  } | undefined;
349
350
  }[] | undefined;
350
- tool_choice: "required" | "none" | "auto" | {
351
+ tool_choice: "required" | "auto" | "none" | {
351
352
  type: "function";
352
353
  function: {
353
354
  name: string;
@@ -358,7 +359,7 @@ export declare const fromRequest: (request: LLMRequest, options?: LoweringOption
358
359
  include_usage: boolean;
359
360
  };
360
361
  } | {
361
- reasoning_effort?: string | undefined;
362
+ reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
362
363
  prompt_cache_key?: string | undefined;
363
364
  store?: boolean | undefined;
364
365
  temperature: number | undefined;
@@ -442,7 +443,7 @@ export declare const fromRequest: (request: LLMRequest, options?: LoweringOption
442
443
  readonly ttl?: string | undefined;
443
444
  } | undefined;
444
445
  }[] | undefined;
445
- tool_choice: "required" | "none" | "auto" | {
446
+ tool_choice: "required" | "auto" | "none" | {
446
447
  type: "function";
447
448
  function: {
448
449
  name: string;
@@ -521,7 +522,6 @@ export declare const protocol: Protocol<{
521
522
  } | undefined;
522
523
  })[];
523
524
  readonly stream: true;
524
- readonly stop?: readonly string[] | undefined;
525
525
  readonly max_completion_tokens?: number | undefined;
526
526
  readonly max_tokens?: number | undefined;
527
527
  readonly tools?: readonly {
@@ -538,9 +538,10 @@ export declare const protocol: Protocol<{
538
538
  readonly ttl?: string | undefined;
539
539
  } | undefined;
540
540
  }[] | undefined;
541
+ readonly stop?: readonly string[] | undefined;
541
542
  readonly temperature?: number | undefined;
542
543
  readonly seed?: number | undefined;
543
- readonly tool_choice?: "required" | "none" | "auto" | {
544
+ readonly tool_choice?: "required" | "auto" | "none" | {
544
545
  readonly type: "function";
545
546
  readonly function: {
546
547
  readonly name: string;
@@ -552,7 +553,7 @@ export declare const protocol: Protocol<{
552
553
  readonly include_usage: boolean;
553
554
  } | undefined;
554
555
  readonly prompt_cache_key?: string | undefined;
555
- readonly reasoning_effort?: string | undefined;
556
+ readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
556
557
  readonly frequency_penalty?: number | undefined;
557
558
  readonly presence_penalty?: number | undefined;
558
559
  }, string, {
@@ -584,6 +585,7 @@ export declare const protocol: Protocol<{
584
585
  readonly reasoning_content?: string | null | undefined;
585
586
  readonly reasoning_text?: string | null | undefined;
586
587
  readonly content?: string | null | undefined;
588
+ readonly refusal?: string | null | undefined;
587
589
  readonly tool_calls?: readonly {
588
590
  readonly function?: {
589
591
  readonly name?: string | null | undefined;
@@ -660,7 +662,6 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
660
662
  } | undefined;
661
663
  })[];
662
664
  readonly stream: true;
663
- readonly stop?: readonly string[] | undefined;
664
665
  readonly max_completion_tokens?: number | undefined;
665
666
  readonly max_tokens?: number | undefined;
666
667
  readonly tools?: readonly {
@@ -677,9 +678,10 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
677
678
  readonly ttl?: string | undefined;
678
679
  } | undefined;
679
680
  }[] | undefined;
681
+ readonly stop?: readonly string[] | undefined;
680
682
  readonly temperature?: number | undefined;
681
683
  readonly seed?: number | undefined;
682
- readonly tool_choice?: "required" | "none" | "auto" | {
684
+ readonly tool_choice?: "required" | "auto" | "none" | {
683
685
  readonly type: "function";
684
686
  readonly function: {
685
687
  readonly name: string;
@@ -691,7 +693,7 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
691
693
  readonly include_usage: boolean;
692
694
  } | undefined;
693
695
  readonly prompt_cache_key?: string | undefined;
694
- readonly reasoning_effort?: string | undefined;
696
+ readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
695
697
  readonly frequency_penalty?: number | undefined;
696
698
  readonly presence_penalty?: number | undefined;
697
699
  }, string>;
@@ -757,7 +759,6 @@ export declare const route: Route<{
757
759
  } | undefined;
758
760
  })[];
759
761
  readonly stream: true;
760
- readonly stop?: readonly string[] | undefined;
761
762
  readonly max_completion_tokens?: number | undefined;
762
763
  readonly max_tokens?: number | undefined;
763
764
  readonly tools?: readonly {
@@ -774,9 +775,10 @@ export declare const route: Route<{
774
775
  readonly ttl?: string | undefined;
775
776
  } | undefined;
776
777
  }[] | undefined;
778
+ readonly stop?: readonly string[] | undefined;
777
779
  readonly temperature?: number | undefined;
778
780
  readonly seed?: number | undefined;
779
- readonly tool_choice?: "required" | "none" | "auto" | {
781
+ readonly tool_choice?: "required" | "auto" | "none" | {
780
782
  readonly type: "function";
781
783
  readonly function: {
782
784
  readonly name: string;
@@ -788,7 +790,7 @@ export declare const route: Route<{
788
790
  readonly include_usage: boolean;
789
791
  } | undefined;
790
792
  readonly prompt_cache_key?: string | undefined;
791
- readonly reasoning_effort?: string | undefined;
793
+ readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
792
794
  readonly frequency_penalty?: number | undefined;
793
795
  readonly presence_penalty?: number | undefined;
794
796
  }, HttpTransport.HttpPrepared<string>>;
@@ -13,7 +13,7 @@ import { Lifecycle } from "./utils/lifecycle.js";
13
13
  import { ToolSchemaProjection } from "./utils/tool-schema.js";
14
14
  import { ToolStream } from "./utils/tool-stream.js";
15
15
  const ADAPTER = "openai-chat";
16
- const RESERVED_REASONING_FIELDS = new Set(["role", "content", "tool_calls"]);
16
+ const RESERVED_REASONING_FIELDS = new Set(["role", "content", "refusal", "tool_calls"]);
17
17
  export const DEFAULT_BASE_URL = "https://api.openai.com/v1";
18
18
  export const PATH = "/chat/completions";
19
19
  // =============================================================================
@@ -144,6 +144,7 @@ const OpenAIChatToolCallDelta = Schema.Struct({
144
144
  });
145
145
  const OpenAIChatDelta = Schema.StructWithRest(Schema.Struct({
146
146
  content: optionalNull(Schema.String),
147
+ refusal: optionalNull(Schema.String),
147
148
  reasoning_content: optionalNull(Schema.String),
148
149
  reasoning: optionalNull(Schema.String),
149
150
  reasoning_text: optionalNull(Schema.String),
@@ -568,6 +569,7 @@ const step = (state, event) => Effect.gen(function* () {
568
569
  let lifecycle = state.lifecycle;
569
570
  const reasoning = reasoningDelta(delta, state.reasoningField);
570
571
  const hasLateContent = Boolean(delta?.content) ||
572
+ Boolean(delta?.refusal) ||
571
573
  reasoning !== undefined ||
572
574
  (Array.isArray(delta?.reasoning_details) && delta.reasoning_details.length > 0) ||
573
575
  toolDeltas.some((tool) => Boolean(tool.id) || Boolean(tool.function?.name) || Boolean(tool.function?.arguments));
@@ -587,13 +589,17 @@ const step = (state, event) => Effect.gen(function* () {
587
589
  lifecycle = Lifecycle.reasoningDelta(lifecycle, events, "reasoning-0", text, deltaMetadata);
588
590
  else if (reasoningDetailsObserved &&
589
591
  !lifecycle.reasoning.has("reasoning-0") &&
590
- (Boolean(delta?.content) || toolDeltas.length > 0))
592
+ (Boolean(delta?.content) || Boolean(delta?.refusal) || toolDeltas.length > 0))
591
593
  lifecycle = Lifecycle.reasoningStart(lifecycle, events, "reasoning-0", deltaMetadata);
592
594
  const reasoningEmitted = state.reasoningEmitted || lifecycle.reasoning.has("reasoning-0");
593
595
  if (delta?.content) {
594
596
  lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningMetadata(reasoningField, reasoningDetailsObserved ? state.reasoningDetails : undefined));
595
597
  lifecycle = Lifecycle.textDelta(lifecycle, events, "text-0", delta.content);
596
598
  }
599
+ if (delta?.refusal) {
600
+ lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningMetadata(reasoningField, reasoningDetailsObserved ? state.reasoningDetails : undefined));
601
+ lifecycle = Lifecycle.textDelta(lifecycle, events, "text-0", delta.refusal);
602
+ }
597
603
  // Compatible providers may omit indexes. Prefer durable identity, then use
598
604
  // batch position for parallel deltas or the latest call for sparse chunks.
599
605
  for (const [position, tool] of toolDeltas.entries()) {
@@ -69,7 +69,6 @@ export declare const route: Route<{
69
69
  } | undefined;
70
70
  })[];
71
71
  readonly stream: true;
72
- readonly stop?: readonly string[] | undefined;
73
72
  readonly max_completion_tokens?: number | undefined;
74
73
  readonly max_tokens?: number | undefined;
75
74
  readonly tools?: readonly {
@@ -86,9 +85,10 @@ export declare const route: Route<{
86
85
  readonly ttl?: string | undefined;
87
86
  } | undefined;
88
87
  }[] | undefined;
88
+ readonly stop?: readonly string[] | undefined;
89
89
  readonly temperature?: number | undefined;
90
90
  readonly seed?: number | undefined;
91
- readonly tool_choice?: "required" | "none" | "auto" | {
91
+ readonly tool_choice?: "required" | "auto" | "none" | {
92
92
  readonly type: "function";
93
93
  readonly function: {
94
94
  readonly name: string;
@@ -100,7 +100,7 @@ export declare const route: Route<{
100
100
  readonly include_usage: boolean;
101
101
  } | undefined;
102
102
  readonly prompt_cache_key?: string | undefined;
103
- readonly reasoning_effort?: string | undefined;
103
+ readonly reasoning_effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
104
104
  readonly frequency_penalty?: number | undefined;
105
105
  readonly presence_penalty?: number | undefined;
106
106
  }, import("../route/transport/http.js").HttpPrepared<string>>;
@@ -38,17 +38,20 @@ export declare const route: Route<{
38
38
  readonly text: string;
39
39
  })[];
40
40
  } | {
41
+ readonly type: "message";
41
42
  readonly content: readonly {
42
43
  readonly type: "output_text";
43
44
  readonly text: string;
44
45
  }[];
45
46
  readonly role: "assistant";
47
+ readonly id?: string | undefined;
46
48
  readonly phase?: "commentary" | "final_answer" | undefined;
47
49
  } | {
48
50
  readonly type: "function_call";
49
- readonly call_id: string;
50
51
  readonly name: string;
51
52
  readonly arguments: string;
53
+ readonly call_id: string;
54
+ readonly id?: string | undefined;
52
55
  } | {
53
56
  readonly type: "function_call_output";
54
57
  readonly call_id: string;
@@ -67,10 +70,13 @@ export declare const route: Route<{
67
70
  })[];
68
71
  readonly model: string;
69
72
  readonly stream: true;
73
+ readonly metadata?: {
74
+ readonly [x: string]: string;
75
+ } | undefined;
70
76
  readonly instructions?: string | undefined;
71
77
  readonly reasoning?: {
72
78
  readonly summary?: "auto" | "concise" | "detailed" | undefined;
73
- readonly effort?: string | undefined;
79
+ readonly effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
74
80
  } | undefined;
75
81
  readonly tools?: readonly {
76
82
  readonly type: "function";
@@ -82,19 +88,35 @@ export declare const route: Route<{
82
88
  readonly strict?: boolean | undefined;
83
89
  }[] | undefined;
84
90
  readonly text?: {
85
- readonly verbosity?: "low" | "medium" | "high" | undefined;
91
+ readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
86
92
  } | undefined;
87
93
  readonly temperature?: number | undefined;
88
- readonly tool_choice?: "required" | "none" | "auto" | {
94
+ readonly tool_choice?: "required" | "auto" | "none" | {
89
95
  readonly type: "function";
90
96
  readonly name: string;
97
+ } | {
98
+ readonly type: "allowed_tools";
99
+ readonly mode: "required" | "auto" | "none";
100
+ readonly tools: readonly {
101
+ readonly type: "function";
102
+ readonly name: string;
103
+ }[];
91
104
  } | undefined;
92
105
  readonly top_p?: number | undefined;
93
- readonly include?: readonly ("file_search_call.results" | "web_search_call.results" | "web_search_call.action.sources" | "message.input_image.image_url" | "computer_call_output.output.image_url" | "code_interpreter_call.outputs" | "reasoning.encrypted_content" | "message.output_text.logprobs")[] | undefined;
94
106
  readonly store?: boolean | undefined;
107
+ readonly include?: readonly import("./utils/open-responses-options.js").ResponseIncludable[] | undefined;
95
108
  readonly truncation?: "auto" | "disabled" | undefined;
109
+ readonly stream_options?: {
110
+ readonly include_obfuscation?: boolean | undefined;
111
+ } | undefined;
96
112
  readonly prompt_cache_key?: string | undefined;
113
+ readonly frequency_penalty?: number | undefined;
114
+ readonly presence_penalty?: number | undefined;
115
+ readonly safety_identifier?: string | undefined;
116
+ readonly top_logprobs?: number | undefined;
97
117
  readonly service_tier?: "default" | "auto" | "flex" | "priority" | undefined;
98
118
  readonly max_output_tokens?: number | undefined;
119
+ readonly max_tool_calls?: number | undefined;
120
+ readonly parallel_tool_calls?: boolean | undefined;
99
121
  }, import("../route/transport/http.js").HttpPrepared<string>>;
100
122
  export * as OpenAICompatibleResponses from "./openai-compatible-responses.js";