@ai-sdk/open-responses 2.0.31 → 2.0.35

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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = true ? "2.0.31" : "0.0.0-test";
2
+ var VERSION = true ? "2.0.35" : "0.0.0-test";
3
3
 
4
4
  // src/open-responses-provider.ts
5
5
  import {
@@ -10,6 +10,184 @@ import {
10
10
  withUserAgentSuffix
11
11
  } from "@ai-sdk/provider-utils";
12
12
 
13
+ // src/open-responses-extension.ts
14
+ function createOpenResponsesExtensionRegistry(extensions) {
15
+ const registry = {
16
+ byEventType: /* @__PURE__ */ new Map(),
17
+ byExtensionId: /* @__PURE__ */ new Map(),
18
+ byItemType: /* @__PURE__ */ new Map(),
19
+ byProviderToolId: /* @__PURE__ */ new Map(),
20
+ byToolType: /* @__PURE__ */ new Map()
21
+ };
22
+ for (const extension of extensions != null ? extensions : []) {
23
+ const namespaceSeparatorIndex = extension.id.indexOf(".");
24
+ if (namespaceSeparatorIndex <= 0) {
25
+ throw new Error(
26
+ `Open Responses extension ID ${extension.id} must use <implementor>.<extension> format.`
27
+ );
28
+ }
29
+ const namespace = extension.id.slice(0, namespaceSeparatorIndex);
30
+ registerUnique({
31
+ map: registry.byExtensionId,
32
+ key: extension.id,
33
+ extension,
34
+ field: "id"
35
+ });
36
+ const hasToolType = extension.toolType != null;
37
+ const hasToolEncoder = extension.encodeTool != null;
38
+ if (hasToolType !== hasToolEncoder) {
39
+ throw new Error(
40
+ `Open Responses extension ${extension.id} must provide toolType and encodeTool together.`
41
+ );
42
+ }
43
+ if (extension.encodeToolChoice != null && !hasToolEncoder) {
44
+ throw new Error(
45
+ `Open Responses extension ${extension.id} cannot provide encodeToolChoice without toolType and encodeTool.`
46
+ );
47
+ }
48
+ if (hasToolType && hasToolEncoder) {
49
+ const toolExtension = extension;
50
+ assertNamespacedType({
51
+ extensionId: extension.id,
52
+ namespace,
53
+ type: toolExtension.toolType,
54
+ field: "toolType"
55
+ });
56
+ registerUnique({
57
+ map: registry.byProviderToolId,
58
+ key: extension.id,
59
+ extension: toolExtension,
60
+ field: "provider-tool id"
61
+ });
62
+ registerUnique({
63
+ map: registry.byToolType,
64
+ key: toolExtension.toolType,
65
+ extension: toolExtension,
66
+ field: "toolType"
67
+ });
68
+ }
69
+ const hasItemTypes = extension.itemTypes != null;
70
+ const hasItemDecoder = extension.decodeItem != null;
71
+ if (hasItemTypes !== hasItemDecoder) {
72
+ throw new Error(
73
+ `Open Responses extension ${extension.id} must provide itemTypes and decodeItem together.`
74
+ );
75
+ }
76
+ if (extension.encodeInputItem != null && !hasItemDecoder) {
77
+ throw new Error(
78
+ `Open Responses extension ${extension.id} cannot provide encodeInputItem without itemTypes and decodeItem.`
79
+ );
80
+ }
81
+ if (hasItemTypes && hasItemDecoder) {
82
+ const itemExtension = extension;
83
+ if (itemExtension.itemTypes.length === 0) {
84
+ throw new Error(
85
+ `Open Responses extension ${extension.id} must register at least one item type.`
86
+ );
87
+ }
88
+ for (const itemType of itemExtension.itemTypes) {
89
+ assertNamespacedType({
90
+ extensionId: extension.id,
91
+ namespace,
92
+ type: itemType,
93
+ field: "itemTypes"
94
+ });
95
+ registerUnique({
96
+ map: registry.byItemType,
97
+ key: itemType,
98
+ extension: itemExtension,
99
+ field: "item type"
100
+ });
101
+ }
102
+ }
103
+ const hasEventTypes = extension.eventTypes != null;
104
+ const hasEventDecoder = extension.decodeEvent != null;
105
+ if (hasEventTypes !== hasEventDecoder) {
106
+ throw new Error(
107
+ `Open Responses extension ${extension.id} must provide eventTypes and decodeEvent together.`
108
+ );
109
+ }
110
+ if (hasEventTypes && hasEventDecoder) {
111
+ const eventExtension = extension;
112
+ if (eventExtension.eventTypes.length === 0) {
113
+ throw new Error(
114
+ `Open Responses extension ${extension.id} must register at least one event type.`
115
+ );
116
+ }
117
+ for (const eventType of eventExtension.eventTypes) {
118
+ assertNamespacedType({
119
+ extensionId: extension.id,
120
+ namespace,
121
+ type: eventType,
122
+ field: "eventTypes"
123
+ });
124
+ registerUnique({
125
+ map: registry.byEventType,
126
+ key: eventType,
127
+ extension: eventExtension,
128
+ field: "event type"
129
+ });
130
+ }
131
+ }
132
+ if (!hasToolEncoder && !hasItemDecoder && !hasEventDecoder) {
133
+ throw new Error(
134
+ `Open Responses extension ${extension.id} must register a tool, item, or event capability.`
135
+ );
136
+ }
137
+ }
138
+ return registry;
139
+ }
140
+ function assertNamespacedType({
141
+ extensionId,
142
+ namespace,
143
+ type,
144
+ field
145
+ }) {
146
+ if (!type.includes(":") || type.slice(0, type.indexOf(":")) !== namespace) {
147
+ throw new Error(
148
+ `Open Responses extension ${extensionId} has invalid ${field} value ${type}. Extension wire types must use the ${namespace}: namespace.`
149
+ );
150
+ }
151
+ }
152
+ function registerUnique({
153
+ map,
154
+ key,
155
+ extension,
156
+ field
157
+ }) {
158
+ const existing = map.get(key);
159
+ if (existing != null) {
160
+ throw new Error(
161
+ `Open Responses extension ${extension.id} cannot register ${field} ${String(key)} because it is already registered by ${existing.id}.`
162
+ );
163
+ }
164
+ map.set(key, extension);
165
+ }
166
+ function isOpenResponsesNamespacedType(value) {
167
+ return typeof value === "string" && value.includes(":");
168
+ }
169
+ function isOpenResponsesExtensionRecord(value) {
170
+ return isOpenResponsesJSONObject(value) && isOpenResponsesNamespacedType(value.type);
171
+ }
172
+ function isOpenResponsesJSONObject(value) {
173
+ return value != null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype && Object.values(value).every(isOpenResponsesJSONValue);
174
+ }
175
+ function isOpenResponsesExtensionItem(value) {
176
+ return isOpenResponsesExtensionRecord(value) && typeof value.id === "string" && typeof value.status === "string";
177
+ }
178
+ function isOpenResponsesExtensionEvent(value) {
179
+ return isOpenResponsesExtensionRecord(value) && typeof value.sequence_number === "number";
180
+ }
181
+ function isOpenResponsesJSONValue(value) {
182
+ if (value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
183
+ return true;
184
+ }
185
+ if (Array.isArray(value)) {
186
+ return value.every(isOpenResponsesJSONValue);
187
+ }
188
+ return isOpenResponsesJSONObject(value);
189
+ }
190
+
13
191
  // src/responses/open-responses-language-model.ts
14
192
  import {
15
193
  APICallError
@@ -19,11 +197,13 @@ import {
19
197
  createEventSourceResponseHandler,
20
198
  createJsonErrorResponseHandler,
21
199
  createJsonResponseHandler,
200
+ createProviderStreamError,
22
201
  isCustomReasoning,
23
202
  jsonSchema,
24
203
  mapReasoningToProviderEffort,
25
204
  parseProviderOptions,
26
205
  postJsonToApi,
206
+ SerializationError,
27
207
  serializeModelOptions,
28
208
  WORKFLOW_SERIALIZE,
29
209
  WORKFLOW_DESERIALIZE
@@ -41,12 +221,15 @@ import {
41
221
  } from "@ai-sdk/provider-utils";
42
222
  async function convertToOpenResponsesInput({
43
223
  prompt,
44
- providerOptionsName = "open-responses"
224
+ providerOptionsName = "open-responses",
225
+ extensionRegistry,
226
+ providerToolsByName = /* @__PURE__ */ new Map()
45
227
  }) {
46
228
  var _a, _b, _c, _d;
47
229
  const input = [];
48
230
  const warnings = [];
49
231
  const systemMessages = [];
232
+ const replayedExtensionItems = /* @__PURE__ */ new Set();
50
233
  for (const { role, content } of prompt) {
51
234
  switch (role) {
52
235
  case "system": {
@@ -123,6 +306,44 @@ async function convertToOpenResponsesInput({
123
306
  assistantMessageId = void 0;
124
307
  };
125
308
  for (const part of content) {
309
+ const extensionReplay = getExtensionReplay({
310
+ part,
311
+ providerOptionsName,
312
+ extensionRegistry
313
+ });
314
+ if (extensionReplay != null) {
315
+ flushAssistantContent();
316
+ const replayItem = extensionReplay.item;
317
+ if (replayItem != null) {
318
+ const replayKey = `${replayItem.type}:${replayItem.id}`;
319
+ if (!replayedExtensionItems.has(replayKey)) {
320
+ input.push(replayItem);
321
+ replayedExtensionItems.add(replayKey);
322
+ }
323
+ }
324
+ continue;
325
+ }
326
+ if (part.type === "tool-call" || part.type === "tool-result") {
327
+ const providerTool = providerToolsByName.get(part.toolName);
328
+ const extension = providerTool == null ? void 0 : extensionRegistry == null ? void 0 : extensionRegistry.byProviderToolId.get(providerTool.id);
329
+ if (providerTool != null && extension != null) {
330
+ flushAssistantContent();
331
+ const encoded = await encodeExtensionInputPart({
332
+ extensionRegistry,
333
+ part,
334
+ providerTool
335
+ });
336
+ if (encoded == null) {
337
+ warnings.push({
338
+ type: "unsupported",
339
+ feature: `provider-defined tool ${providerTool.id} ${part.type} history`
340
+ });
341
+ } else {
342
+ input.push(...encoded);
343
+ }
344
+ continue;
345
+ }
346
+ }
126
347
  switch (part.type) {
127
348
  case "reasoning": {
128
349
  flushAssistantContent();
@@ -204,6 +425,40 @@ async function convertToOpenResponsesInput({
204
425
  case "tool": {
205
426
  for (const part of content) {
206
427
  if (part.type === "tool-result") {
428
+ const extensionReplay = getExtensionReplay({
429
+ part,
430
+ providerOptionsName,
431
+ extensionRegistry
432
+ });
433
+ if (extensionReplay != null) {
434
+ const replayItem = extensionReplay.item;
435
+ if (replayItem != null) {
436
+ const replayKey = `${replayItem.type}:${replayItem.id}`;
437
+ if (!replayedExtensionItems.has(replayKey)) {
438
+ input.push(replayItem);
439
+ replayedExtensionItems.add(replayKey);
440
+ }
441
+ }
442
+ continue;
443
+ }
444
+ const providerTool = providerToolsByName.get(part.toolName);
445
+ const extension = providerTool == null ? void 0 : extensionRegistry == null ? void 0 : extensionRegistry.byProviderToolId.get(providerTool.id);
446
+ if (providerTool != null && extension != null) {
447
+ const encoded = await encodeExtensionInputPart({
448
+ extensionRegistry,
449
+ part,
450
+ providerTool
451
+ });
452
+ if (encoded == null) {
453
+ warnings.push({
454
+ type: "unsupported",
455
+ feature: `provider-defined tool ${providerTool.id} tool-result history`
456
+ });
457
+ } else {
458
+ input.push(...encoded);
459
+ }
460
+ continue;
461
+ }
207
462
  const output = part.output;
208
463
  let contentValue;
209
464
  switch (output.type) {
@@ -297,6 +552,61 @@ async function convertToOpenResponsesInput({
297
552
  warnings
298
553
  };
299
554
  }
555
+ async function encodeExtensionInputPart({
556
+ extensionRegistry,
557
+ part,
558
+ providerTool
559
+ }) {
560
+ const extension = extensionRegistry == null ? void 0 : extensionRegistry.byProviderToolId.get(providerTool.id);
561
+ const encodeInputItem = extension == null ? void 0 : extension.encodeInputItem;
562
+ const itemTypes = extension == null ? void 0 : extension.itemTypes;
563
+ if (encodeInputItem == null || itemTypes == null) {
564
+ return void 0;
565
+ }
566
+ try {
567
+ const value = await encodeInputItem({
568
+ part,
569
+ tool: providerTool
570
+ });
571
+ const items = value == null ? void 0 : Array.isArray(value) ? value : [value];
572
+ if (items == null || items.length === 0 || !items.every(
573
+ (item) => isOpenResponsesExtensionItem(item) && itemTypes.includes(item.type)
574
+ )) {
575
+ return void 0;
576
+ }
577
+ return items;
578
+ } catch (e) {
579
+ return void 0;
580
+ }
581
+ }
582
+ function getExtensionReplay({
583
+ part,
584
+ providerOptionsName,
585
+ extensionRegistry
586
+ }) {
587
+ var _a, _b;
588
+ const extensionData = (_a = getProviderData(
589
+ part,
590
+ providerOptionsName
591
+ )) == null ? void 0 : _a.openResponsesExtension;
592
+ if (extensionData == null || typeof extensionData !== "object" || Array.isArray(extensionData)) {
593
+ return void 0;
594
+ }
595
+ const { id, item, itemId } = extensionData;
596
+ if (typeof id !== "string") {
597
+ return void 0;
598
+ }
599
+ const extension = extensionRegistry == null ? void 0 : extensionRegistry.byExtensionId.get(
600
+ id
601
+ );
602
+ if (extension == null) {
603
+ return void 0;
604
+ }
605
+ if (isOpenResponsesExtensionItem(item) && ((_b = extension.itemTypes) == null ? void 0 : _b.includes(item.type))) {
606
+ return { item };
607
+ }
608
+ return typeof itemId === "string" ? {} : void 0;
609
+ }
300
610
  function getProviderData(part, providerOptionsName) {
301
611
  var _a, _b, _c;
302
612
  const providerData = (_c = (_a = part.providerOptions) == null ? void 0 : _a[providerOptionsName]) != null ? _c : (_b = part.providerMetadata) == null ? void 0 : _b[providerOptionsName];
@@ -403,10 +713,17 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
403
713
  this.supportedUrls = {
404
714
  "image/*": [/^https?:\/\/.*$/]
405
715
  };
716
+ var _a;
406
717
  this.modelId = modelId;
407
718
  this.config = config;
719
+ this.extensionRegistry = (_a = config.extensionRegistry) != null ? _a : createOpenResponsesExtensionRegistry();
408
720
  }
409
721
  static [WORKFLOW_SERIALIZE](model) {
722
+ if (model.extensionRegistry.byExtensionId.size > 0) {
723
+ throw new SerializationError({
724
+ message: "Open Responses models with registered extensions cannot be serialized across workflow boundaries. Recreate the provider with its extension codecs inside the workflow step."
725
+ });
726
+ }
410
727
  return serializeModelOptions({
411
728
  modelId: model.modelId,
412
729
  config: model.config
@@ -445,24 +762,56 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
445
762
  if (seed != null) {
446
763
  warnings.push({ type: "unsupported", feature: "seed" });
447
764
  }
765
+ const providerToolsByName = new Map(
766
+ (tools != null ? tools : []).filter((tool) => tool.type === "provider").map((tool) => [tool.name, tool])
767
+ );
448
768
  const {
449
769
  input,
450
770
  instructions,
451
771
  warnings: inputWarnings
452
772
  } = await convertToOpenResponsesInput({
453
773
  prompt,
454
- providerOptionsName: this.config.providerOptionsName
774
+ providerOptionsName: this.config.providerOptionsName,
775
+ extensionRegistry: this.extensionRegistry,
776
+ providerToolsByName
455
777
  });
456
778
  warnings.push(...inputWarnings);
457
- const functionTools = [];
779
+ const convertedTools = [];
780
+ const encodedProviderToolsByName = /* @__PURE__ */ new Map();
458
781
  for (const tool of tools != null ? tools : []) {
459
782
  if (tool.type === "provider") {
460
- warnings.push({
461
- type: "unsupported",
462
- feature: `provider-defined tool ${tool.id}`
463
- });
783
+ const extension = this.extensionRegistry.byProviderToolId.get(tool.id);
784
+ let encoded;
785
+ if (extension != null) {
786
+ try {
787
+ const fields = await extension.encodeTool({
788
+ name: tool.name,
789
+ args: tool.args
790
+ });
791
+ if (isOpenResponsesJSONObject(fields)) {
792
+ encoded = {
793
+ ...fields,
794
+ type: extension.toolType
795
+ };
796
+ }
797
+ } catch (e) {
798
+ }
799
+ }
800
+ if (encoded == null) {
801
+ warnings.push({
802
+ type: "unsupported",
803
+ feature: `provider-defined tool ${tool.id}`
804
+ });
805
+ } else if (extension != null) {
806
+ convertedTools.push(encoded);
807
+ encodedProviderToolsByName.set(tool.name, {
808
+ toolType: extension.toolType,
809
+ encodeToolChoice: extension.encodeToolChoice,
810
+ tool
811
+ });
812
+ }
464
813
  } else {
465
- functionTools.push({
814
+ convertedTools.push({
466
815
  type: "function",
467
816
  name: tool.name,
468
817
  description: tool.description,
@@ -471,7 +820,44 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
471
820
  });
472
821
  }
473
822
  }
474
- const convertedToolChoice = toolChoice == null ? void 0 : toolChoice.type === "tool" ? { type: "function", name: toolChoice.toolName } : toolChoice.type;
823
+ let convertedToolChoice;
824
+ if ((toolChoice == null ? void 0 : toolChoice.type) === "tool") {
825
+ const registeredTool = encodedProviderToolsByName.get(
826
+ toolChoice.toolName
827
+ );
828
+ if (registeredTool == null) {
829
+ if (!providerToolsByName.has(toolChoice.toolName)) {
830
+ convertedToolChoice = {
831
+ type: "function",
832
+ name: toolChoice.toolName
833
+ };
834
+ }
835
+ } else {
836
+ const { encodeToolChoice, tool, toolType } = registeredTool;
837
+ let fields = {};
838
+ try {
839
+ fields = await (encodeToolChoice == null ? void 0 : encodeToolChoice({
840
+ name: tool.name,
841
+ args: tool.args
842
+ }));
843
+ } catch (e) {
844
+ fields = void 0;
845
+ }
846
+ if (encodeToolChoice != null && !isOpenResponsesJSONObject(fields)) {
847
+ warnings.push({
848
+ type: "unsupported",
849
+ feature: `tool choice for provider-defined tool ${tool.id}`
850
+ });
851
+ } else {
852
+ convertedToolChoice = {
853
+ ...isOpenResponsesJSONObject(fields) ? fields : {},
854
+ type: toolType
855
+ };
856
+ }
857
+ }
858
+ } else {
859
+ convertedToolChoice = toolChoice == null ? void 0 : toolChoice.type;
860
+ }
475
861
  const textFormat = (responseFormat == null ? void 0 : responseFormat.type) === "json" ? {
476
862
  type: "json_schema",
477
863
  ...responseFormat.schema != null ? {
@@ -515,7 +901,7 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
515
901
  summary: openResponsesOptions.reasoningSummary
516
902
  }
517
903
  } : void 0,
518
- tools: functionTools.length ? functionTools : void 0,
904
+ tools: convertedTools.length ? convertedTools : void 0,
519
905
  tool_choice: convertedToolChoice,
520
906
  ...textFormat != null && { text: { format: textFormat } }
521
907
  },
@@ -628,6 +1014,22 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
628
1014
  });
629
1015
  break;
630
1016
  }
1017
+ default: {
1018
+ if (!isOpenResponsesExtensionItem(part)) {
1019
+ break;
1020
+ }
1021
+ const decoded = await decodeExtensionItem({
1022
+ extensionRegistry: this.extensionRegistry,
1023
+ item: part,
1024
+ mode: "generate",
1025
+ providerOptionsName: this.config.providerOptionsName
1026
+ });
1027
+ if (decoded != null) {
1028
+ content.push(...decoded);
1029
+ hasToolCalls || (hasToolCalls = decoded.some((part2) => part2.type === "tool-call"));
1030
+ }
1031
+ break;
1032
+ }
631
1033
  }
632
1034
  }
633
1035
  const usage = response.usage;
@@ -731,13 +1133,15 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
731
1133
  };
732
1134
  const toolCallsByItemId = /* @__PURE__ */ new Map();
733
1135
  const providerOptionsName = this.config.providerOptionsName;
1136
+ const extensionRegistry = this.extensionRegistry;
1137
+ const extensionStreamState = /* @__PURE__ */ new Map();
734
1138
  return {
735
1139
  stream: response.pipeThrough(
736
1140
  new TransformStream({
737
1141
  start(controller) {
738
1142
  controller.enqueue({ type: "stream-start", warnings });
739
1143
  },
740
- transform(parseResult, controller) {
1144
+ async transform(parseResult, controller) {
741
1145
  var _a2, _b2, _c, _d, _e, _f, _g, _h;
742
1146
  if (options.includeRawChunks) {
743
1147
  controller.enqueue({
@@ -750,6 +1154,24 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
750
1154
  return;
751
1155
  }
752
1156
  const chunk = parseResult.value;
1157
+ if (isOpenResponsesExtensionEvent(chunk)) {
1158
+ const extension = extensionRegistry.byEventType.get(chunk.type);
1159
+ if ((extension == null ? void 0 : extension.decodeEvent) != null) {
1160
+ try {
1161
+ const decoded = await extension.decodeEvent({
1162
+ event: chunk,
1163
+ state: extensionStreamState
1164
+ });
1165
+ for (const part of decoded != null ? decoded : []) {
1166
+ controller.enqueue(part);
1167
+ hasToolCalls || (hasToolCalls = part.type === "tool-call" || part.type === "tool-input-start");
1168
+ }
1169
+ } catch (error) {
1170
+ controller.enqueue({ type: "error", error });
1171
+ }
1172
+ }
1173
+ return;
1174
+ }
753
1175
  if (chunk.type === "response.output_item.added" && chunk.item.type === "function_call") {
754
1176
  toolCallsByItemId.set(chunk.item.id, {
755
1177
  toolName: chunk.item.name,
@@ -794,13 +1216,28 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
794
1216
  });
795
1217
  hasToolCalls = true;
796
1218
  toolCallsByItemId.delete(chunk.item.id);
1219
+ } else if (chunk.type === "response.output_item.done" && isOpenResponsesExtensionItem(chunk.item)) {
1220
+ try {
1221
+ const decoded = await decodeExtensionItem({
1222
+ extensionRegistry,
1223
+ item: chunk.item,
1224
+ mode: "stream",
1225
+ providerOptionsName
1226
+ });
1227
+ for (const part of decoded != null ? decoded : []) {
1228
+ controller.enqueue(part);
1229
+ hasToolCalls || (hasToolCalls = part.type === "tool-call");
1230
+ }
1231
+ } catch (error) {
1232
+ controller.enqueue({ type: "error", error });
1233
+ }
797
1234
  } else if (chunk.type === "response.output_item.added" && chunk.item.type === "reasoning") {
798
1235
  controller.enqueue({
799
1236
  type: "reasoning-start",
800
1237
  id: chunk.item.id
801
1238
  });
802
1239
  activeReasoningId = chunk.item.id;
803
- } else if (chunk.type === "response.reasoning_text.delta") {
1240
+ } else if (chunk.type === "response.reasoning_summary_text.delta" || chunk.type === "response.reasoning_text.delta") {
804
1241
  const reasoningChunk = chunk;
805
1242
  controller.enqueue({
806
1243
  type: "reasoning-delta",
@@ -857,6 +1294,29 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
857
1294
  raw: (_h = (_g = chunk.response.error) == null ? void 0 : _g.code) != null ? _h : chunk.response.status
858
1295
  };
859
1296
  updateUsage(chunk.response.usage);
1297
+ if (chunk.response.error != null) {
1298
+ controller.enqueue({
1299
+ type: "error",
1300
+ error: createOpenResponsesStreamError({
1301
+ type: chunk.type,
1302
+ error: chunk.response.error,
1303
+ data: chunk
1304
+ })
1305
+ });
1306
+ }
1307
+ } else if (chunk.type === "error") {
1308
+ finishReason = {
1309
+ unified: "error",
1310
+ raw: chunk.error.code
1311
+ };
1312
+ controller.enqueue({
1313
+ type: "error",
1314
+ error: createOpenResponsesStreamError({
1315
+ type: chunk.type,
1316
+ error: chunk.error,
1317
+ data: chunk
1318
+ })
1319
+ });
860
1320
  }
861
1321
  },
862
1322
  flush(controller) {
@@ -880,6 +1340,18 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
880
1340
  };
881
1341
  }
882
1342
  };
1343
+ function createOpenResponsesStreamError({
1344
+ type,
1345
+ error,
1346
+ data
1347
+ }) {
1348
+ return createProviderStreamError({
1349
+ message: error.message,
1350
+ type,
1351
+ code: error.code,
1352
+ data
1353
+ });
1354
+ }
883
1355
  function createReasoningProviderMetadata({
884
1356
  part,
885
1357
  providerOptionsName,
@@ -902,6 +1374,76 @@ function createReasoningProviderMetadata({
902
1374
  }
903
1375
  };
904
1376
  }
1377
+ async function decodeExtensionItem({
1378
+ extensionRegistry,
1379
+ item,
1380
+ mode,
1381
+ providerOptionsName
1382
+ }) {
1383
+ const extension = extensionRegistry.byItemType.get(item.type);
1384
+ if (extension == null) {
1385
+ return void 0;
1386
+ }
1387
+ const decoded = await extension.decodeItem({ item, mode });
1388
+ if (decoded == null) {
1389
+ return void 0;
1390
+ }
1391
+ return [
1392
+ createExtensionReplayCarrier({
1393
+ extension,
1394
+ item,
1395
+ providerOptionsName
1396
+ }),
1397
+ ...decoded.map(
1398
+ (part) => addExtensionItemReferenceMetadata({
1399
+ extension,
1400
+ item,
1401
+ part,
1402
+ providerOptionsName
1403
+ })
1404
+ )
1405
+ ];
1406
+ }
1407
+ function createExtensionReplayCarrier({
1408
+ extension,
1409
+ item,
1410
+ providerOptionsName
1411
+ }) {
1412
+ return {
1413
+ type: "custom",
1414
+ kind: "open-responses.extension-replay",
1415
+ providerMetadata: {
1416
+ [providerOptionsName]: {
1417
+ openResponsesExtension: {
1418
+ id: extension.id,
1419
+ item
1420
+ }
1421
+ }
1422
+ }
1423
+ };
1424
+ }
1425
+ function addExtensionItemReferenceMetadata({
1426
+ extension,
1427
+ item,
1428
+ part,
1429
+ providerOptionsName
1430
+ }) {
1431
+ var _a;
1432
+ const providerMetadata = (_a = part.providerMetadata) != null ? _a : {};
1433
+ return {
1434
+ ...part,
1435
+ providerMetadata: {
1436
+ ...providerMetadata,
1437
+ [providerOptionsName]: {
1438
+ ...providerMetadata[providerOptionsName],
1439
+ openResponsesExtension: {
1440
+ id: extension.id,
1441
+ itemId: item.id
1442
+ }
1443
+ }
1444
+ }
1445
+ };
1446
+ }
905
1447
  function getOutputTextAnnotations(value) {
906
1448
  if (value == null || typeof value !== "object" || !("annotations" in value) || !Array.isArray(value.annotations) || !value.annotations.every(
907
1449
  (annotation) => annotation != null && typeof annotation === "object" && annotation.type === "url_citation" && typeof annotation.start_index === "number" && typeof annotation.end_index === "number" && typeof annotation.url === "string" && typeof annotation.title === "string"
@@ -920,6 +1462,9 @@ function getOutputTextAnnotations(value) {
920
1462
  // src/open-responses-provider.ts
921
1463
  function createOpenResponses(options) {
922
1464
  const providerName = options.name;
1465
+ const extensionRegistry = createOpenResponsesExtensionRegistry(
1466
+ options.experimental_extensions
1467
+ );
923
1468
  const getHeaders = () => withUserAgentSuffix(
924
1469
  {
925
1470
  ...options.apiKey ? {
@@ -936,7 +1481,8 @@ function createOpenResponses(options) {
936
1481
  headers: getHeaders,
937
1482
  url: options.url,
938
1483
  fetch: options.fetch,
939
- generateId: () => generateId()
1484
+ generateId: () => generateId(),
1485
+ extensionRegistry
940
1486
  });
941
1487
  };
942
1488
  const createLanguageModel = (modelId) => {