@ai-sdk/open-responses 2.0.54 → 2.0.55

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @ai-sdk/open-responses
2
2
 
3
+ ## 2.0.55
4
+
5
+ ### Patch Changes
6
+
7
+ - 8cf3f5b: Allow extension codecs to explicitly opt in to exact bare tool, item, and event discriminator registration.
8
+ - Updated dependencies [e3605f6]
9
+ - Updated dependencies [525efc5]
10
+ - @ai-sdk/provider-utils@5.0.50
11
+ - @ai-sdk/provider@4.0.19
12
+
3
13
  ## 2.0.54
4
14
 
5
15
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -5,14 +5,14 @@ import { MaybePromiseLike, FetchFunction, ResponseHandler, InferSchema } from '@
5
5
  declare const VERSION: string;
6
6
 
7
7
  type OpenResponsesNamespacedType = `${string}:${string}`;
8
- type OpenResponsesExtensionRecord = JSONObject & {
9
- type: OpenResponsesNamespacedType;
8
+ type OpenResponsesExtensionRecord<Type extends string = OpenResponsesNamespacedType> = JSONObject & {
9
+ type: Type;
10
10
  };
11
- type OpenResponsesExtensionItem = OpenResponsesExtensionRecord & {
11
+ type OpenResponsesExtensionItem<Type extends string = OpenResponsesNamespacedType> = OpenResponsesExtensionRecord<Type> & {
12
12
  id: string;
13
13
  status: string;
14
14
  };
15
- type OpenResponsesExtensionEvent = OpenResponsesExtensionRecord & {
15
+ type OpenResponsesExtensionEvent<Type extends string = OpenResponsesNamespacedType> = OpenResponsesExtensionRecord<Type> & {
16
16
  sequence_number: number;
17
17
  };
18
18
  type OpenResponsesExtensionInputPart = LanguageModelV4ToolCallPart | LanguageModelV4ToolResultPart;
@@ -25,7 +25,7 @@ type OpenResponsesExtensionStreamPart = Exclude<LanguageModelV4StreamPart, {
25
25
  *
26
26
  * Tool, item, and event codecs can be registered independently.
27
27
  */
28
- interface OpenResponsesExtension {
28
+ interface OpenResponsesExtensionBase {
29
29
  /**
30
30
  * Extension ID in `<implementor>.<extension>` format. For extensions that
31
31
  * encode a provider tool, this is also the AI SDK provider-tool ID.
@@ -36,78 +36,135 @@ interface OpenResponsesExtension {
36
36
  * Must be provided together with `encodeTool`.
37
37
  */
38
38
  toolType?: OpenResponsesNamespacedType;
39
- /**
40
- * Namespaced item types decoded by this extension. Must be provided together
41
- * with `decodeItem`.
42
- */
43
- itemTypes?: readonly OpenResponsesNamespacedType[];
44
- /**
45
- * Namespaced streaming event types decoded by this extension. Must be
46
- * provided together with `decodeEvent`.
47
- */
48
- eventTypes?: readonly OpenResponsesNamespacedType[];
49
39
  /**
50
40
  * Encodes an AI SDK provider tool. Return `undefined` when its arguments
51
- * cannot be encoded. The adapter adds `toolType` and omits a specific tool
52
- * choice that selects the omitted tool.
41
+ * cannot be encoded. The adapter adds the registered tool type and omits a
42
+ * specific tool choice that selects the omitted tool.
53
43
  */
54
44
  encodeTool?(options: {
55
45
  name: string;
56
46
  args: Record<string, unknown>;
57
47
  }): MaybePromiseLike<JSONObject | undefined>;
58
48
  /**
59
- * Encodes a specific `toolChoice`. The adapter adds `toolType`. The default
60
- * is an object containing only `toolType`.
49
+ * Encodes a specific `toolChoice`. The adapter adds the registered tool type.
50
+ * The default is an object containing only that type.
61
51
  */
62
52
  encodeToolChoice?(options: {
63
53
  name: string;
64
54
  args: Record<string, unknown>;
65
55
  }): MaybePromiseLike<JSONObject | undefined>;
56
+ }
57
+ type OpenResponsesExtensionItemCodec<Type extends string> = {
66
58
  /**
67
- * Decodes a completed namespaced item into AI SDK content parts. The adapter
59
+ * Namespaced item types decoded by this extension. Must be provided together
60
+ * with `decodeItem`.
61
+ */
62
+ itemTypes?: readonly OpenResponsesNamespacedType[];
63
+ /**
64
+ * Decodes a completed registered item into AI SDK content parts. The adapter
68
65
  * adds a custom replay part containing the original item and reference
69
66
  * metadata to the returned parts.
70
67
  */
71
68
  decodeItem?(options: {
72
- item: OpenResponsesExtensionItem;
69
+ item: OpenResponsesExtensionItem<Type>;
73
70
  mode: 'generate' | 'stream';
74
71
  }): MaybePromiseLike<OpenResponsesExtensionContentPart[] | undefined>;
75
72
  /**
76
73
  * Encodes an AI SDK history part when no original wire item is available.
77
- * Every returned item must use one of `itemTypes`.
74
+ * Every returned item must use one of the registered item types.
78
75
  */
79
76
  encodeInputItem?(options: {
80
77
  part: OpenResponsesExtensionInputPart;
81
78
  tool: LanguageModelV4ProviderTool;
82
- }): MaybePromiseLike<OpenResponsesExtensionItem | OpenResponsesExtensionItem[] | undefined>;
79
+ }): MaybePromiseLike<OpenResponsesExtensionItem<Type> | OpenResponsesExtensionItem<Type>[] | undefined>;
80
+ };
81
+ type OpenResponsesExtensionEventCodec<Type extends string> = {
82
+ /**
83
+ * Namespaced streaming event types decoded by this extension. Must be
84
+ * provided together with `decodeEvent`.
85
+ */
86
+ eventTypes?: readonly OpenResponsesNamespacedType[];
83
87
  /**
84
- * Decodes a namespaced streaming event.
88
+ * Decodes a registered streaming event.
85
89
  *
86
90
  * `state` persists for the lifetime of one response stream.
87
91
  */
88
92
  decodeEvent?(options: {
89
- event: OpenResponsesExtensionEvent;
93
+ event: OpenResponsesExtensionEvent<Type>;
90
94
  state: Map<string, unknown>;
91
95
  }): MaybePromiseLike<OpenResponsesExtensionStreamPart[] | undefined>;
96
+ };
97
+ /**
98
+ * Defines a portable Open Responses extension using namespaced wire types.
99
+ *
100
+ * This remains an interface so existing consumers can extend it from their own
101
+ * interfaces and implement it in classes.
102
+ */
103
+ interface OpenResponsesExtension extends OpenResponsesExtensionBase, OpenResponsesExtensionItemCodec<OpenResponsesNamespacedType>, OpenResponsesExtensionEventCodec<OpenResponsesNamespacedType> {
104
+ allowBareTypes?: false;
105
+ bareToolType?: undefined;
106
+ bareItemTypes?: undefined;
107
+ bareEventTypes?: undefined;
92
108
  }
109
+ /**
110
+ * Defines a non-portable Open Responses extension that explicitly registers
111
+ * exact bare wire types.
112
+ */
113
+ type OpenResponsesBareExtension = OpenResponsesExtensionBase & OpenResponsesExtensionItemCodec<string> & OpenResponsesExtensionEventCodec<string> & {
114
+ /**
115
+ * Explicitly enables non-portable bare discriminator registration for this
116
+ * extension.
117
+ */
118
+ allowBareTypes: true;
119
+ /**
120
+ * Exact non-namespaced tool type used by a documented implementation
121
+ * extension. Must be provided together with `encodeTool` and cannot be used
122
+ * together with `toolType`.
123
+ */
124
+ bareToolType?: string;
125
+ /**
126
+ * Exact non-namespaced item types decoded by a documented implementation
127
+ * extension. Must be provided together with `decodeItem`.
128
+ */
129
+ bareItemTypes?: readonly string[];
130
+ /**
131
+ * Exact non-namespaced streaming event types decoded by this extension.
132
+ * Must be provided together with `decodeEvent`.
133
+ */
134
+ bareEventTypes?: readonly string[];
135
+ } & ({
136
+ bareToolType: string;
137
+ } | {
138
+ bareItemTypes: readonly string[];
139
+ } | {
140
+ bareEventTypes: readonly string[];
141
+ });
142
+ type OpenResponsesExtensionRegistration = OpenResponsesExtension | OpenResponsesBareExtension;
93
143
  type OpenResponsesExtensionRegistry = {
94
- byEventType: Map<OpenResponsesNamespacedType, OpenResponsesEventExtension>;
95
- byExtensionId: Map<LanguageModelV4ProviderTool['id'], OpenResponsesExtension>;
96
- byItemType: Map<OpenResponsesNamespacedType, OpenResponsesItemExtension>;
144
+ byEventType: Map<string, OpenResponsesEventExtension>;
145
+ byExtensionId: Map<LanguageModelV4ProviderTool['id'], OpenResponsesExtensionRegistration>;
146
+ byItemType: Map<string, OpenResponsesItemExtension>;
97
147
  byProviderToolId: Map<LanguageModelV4ProviderTool['id'], OpenResponsesToolExtension>;
98
- byToolType: Map<OpenResponsesNamespacedType, OpenResponsesToolExtension>;
148
+ byToolType: Map<string, OpenResponsesToolExtension>;
99
149
  };
100
- type OpenResponsesToolExtension = OpenResponsesExtension & {
101
- toolType: OpenResponsesNamespacedType;
102
- encodeTool: NonNullable<OpenResponsesExtension['encodeTool']>;
150
+ type OpenResponsesToolExtension = OpenResponsesExtensionRegistration & {
151
+ encodeTool: NonNullable<OpenResponsesExtensionRegistration['encodeTool']>;
152
+ encodeInputItem?: (options: {
153
+ part: OpenResponsesExtensionInputPart;
154
+ tool: LanguageModelV4ProviderTool;
155
+ }) => MaybePromiseLike<OpenResponsesExtensionItem<string> | OpenResponsesExtensionItem<string>[] | undefined>;
103
156
  };
104
- type OpenResponsesItemExtension = OpenResponsesExtension & {
105
- itemTypes: readonly OpenResponsesNamespacedType[];
106
- decodeItem: NonNullable<OpenResponsesExtension['decodeItem']>;
157
+ type OpenResponsesItemExtension = OpenResponsesExtensionRegistration & {
158
+ decodeItem(options: {
159
+ item: OpenResponsesExtensionItem<string>;
160
+ mode: 'generate' | 'stream';
161
+ }): MaybePromiseLike<OpenResponsesExtensionContentPart[] | undefined>;
107
162
  };
108
- type OpenResponsesEventExtension = OpenResponsesExtension & {
109
- eventTypes: readonly OpenResponsesNamespacedType[];
110
- decodeEvent: NonNullable<OpenResponsesExtension['decodeEvent']>;
163
+ type OpenResponsesEventExtension = OpenResponsesExtensionRegistration & {
164
+ decodeEvent(options: {
165
+ event: OpenResponsesExtensionEvent<string>;
166
+ state: Map<string, unknown>;
167
+ }): MaybePromiseLike<OpenResponsesExtensionStreamPart[] | undefined>;
111
168
  };
112
169
 
113
170
  type OpenResponsesCustomToolOptions = {
@@ -230,7 +287,7 @@ interface OpenResponsesProviderSettings {
230
287
  *
231
288
  * @experimental This API may change in a future release.
232
289
  */
233
- experimental_extensions?: readonly OpenResponsesExtension[];
290
+ experimental_extensions?: readonly OpenResponsesExtensionRegistration[];
234
291
  }
235
292
  declare function createOpenResponses(options: OpenResponsesProviderSettings): OpenResponsesProvider;
236
293
 
@@ -240,4 +297,4 @@ declare const openResponsesLanguageModelOptions: _ai_sdk_provider_utils.LazySche
240
297
  }>;
241
298
  type OpenResponsesLanguageModelOptions = InferSchema<typeof openResponsesLanguageModelOptions>;
242
299
 
243
- export { type OpenResponsesExtension as Experimental_OpenResponsesExtension, type OpenResponsesExtensionContentPart as Experimental_OpenResponsesExtensionContentPart, type OpenResponsesExtensionEvent as Experimental_OpenResponsesExtensionEvent, type OpenResponsesExtensionInputPart as Experimental_OpenResponsesExtensionInputPart, type OpenResponsesExtensionItem as Experimental_OpenResponsesExtensionItem, type OpenResponsesExtensionRecord as Experimental_OpenResponsesExtensionRecord, type OpenResponsesExtensionStreamPart as Experimental_OpenResponsesExtensionStreamPart, type OpenResponsesNamespacedType as Experimental_OpenResponsesNamespacedType, type OpenResponsesCustomToolOptions, type OpenResponsesLanguageModelOptions, type OpenResponsesLanguageModelOptions as OpenResponsesOptions, type OpenResponsesProvider, type OpenResponsesProviderSettings, VERSION, createOpenResponses };
300
+ export { type OpenResponsesBareExtension as Experimental_OpenResponsesBareExtension, type OpenResponsesExtension as Experimental_OpenResponsesExtension, type OpenResponsesExtensionContentPart as Experimental_OpenResponsesExtensionContentPart, type OpenResponsesExtensionEvent as Experimental_OpenResponsesExtensionEvent, type OpenResponsesExtensionInputPart as Experimental_OpenResponsesExtensionInputPart, type OpenResponsesExtensionItem as Experimental_OpenResponsesExtensionItem, type OpenResponsesExtensionRecord as Experimental_OpenResponsesExtensionRecord, type OpenResponsesExtensionStreamPart as Experimental_OpenResponsesExtensionStreamPart, type OpenResponsesNamespacedType as Experimental_OpenResponsesNamespacedType, type OpenResponsesCustomToolOptions, type OpenResponsesLanguageModelOptions, type OpenResponsesLanguageModelOptions as OpenResponsesOptions, type OpenResponsesProvider, type OpenResponsesProviderSettings, VERSION, createOpenResponses };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = true ? "2.0.54" : "0.0.0-test";
2
+ var VERSION = true ? "2.0.55" : "0.0.0-test";
3
3
 
4
4
  // src/open-responses-provider.ts
5
5
  import {
@@ -11,6 +11,37 @@ import {
11
11
  } from "@ai-sdk/provider-utils";
12
12
 
13
13
  // src/open-responses-extension.ts
14
+ var coreToolTypes = /* @__PURE__ */ new Set(["allowed_tools", "function"]);
15
+ var coreItemTypes = /* @__PURE__ */ new Set([
16
+ "function_call",
17
+ "function_call_output",
18
+ "item_reference",
19
+ "message",
20
+ "reasoning"
21
+ ]);
22
+ var coreEventTypes = /* @__PURE__ */ new Set([
23
+ "error",
24
+ "response.completed",
25
+ "response.content_part.added",
26
+ "response.content_part.done",
27
+ "response.created",
28
+ "response.failed",
29
+ "response.function_call_arguments.delta",
30
+ "response.function_call_arguments.done",
31
+ "response.in_progress",
32
+ "response.incomplete",
33
+ "response.output_item.added",
34
+ "response.output_item.done",
35
+ "response.output_text.delta",
36
+ "response.output_text.done",
37
+ "response.reasoning_summary_part.added",
38
+ "response.reasoning_summary_part.done",
39
+ "response.reasoning_summary_text.delta",
40
+ "response.reasoning_summary_text.done",
41
+ "response.reasoning_text.delta",
42
+ "response.refusal.delta",
43
+ "response.refusal.done"
44
+ ]);
14
45
  function createOpenResponsesExtensionRegistry(extensions) {
15
46
  const registry = {
16
47
  byEventType: /* @__PURE__ */ new Map(),
@@ -33,26 +64,48 @@ function createOpenResponsesExtensionRegistry(extensions) {
33
64
  extension,
34
65
  field: "id"
35
66
  });
36
- const hasToolType = extension.toolType != null;
67
+ const hasBareTypes = extension.bareToolType != null || extension.bareItemTypes != null || extension.bareEventTypes != null;
68
+ if (hasBareTypes !== (extension.allowBareTypes === true)) {
69
+ throw new Error(
70
+ `Open Responses extension ${extension.id} must set allowBareTypes to true exactly when registering bare types.`
71
+ );
72
+ }
73
+ if (extension.toolType != null && extension.bareToolType != null) {
74
+ throw new Error(
75
+ `Open Responses extension ${extension.id} cannot provide toolType and bareToolType together.`
76
+ );
77
+ }
78
+ const toolType = extension.toolType ?? extension.bareToolType;
79
+ const hasToolType = toolType != null;
37
80
  const hasToolEncoder = extension.encodeTool != null;
38
81
  if (hasToolType !== hasToolEncoder) {
82
+ const typeField = extension.bareToolType != null ? "bareToolType" : "toolType";
39
83
  throw new Error(
40
- `Open Responses extension ${extension.id} must provide toolType and encodeTool together.`
84
+ `Open Responses extension ${extension.id} must provide ${typeField} and encodeTool together.`
41
85
  );
42
86
  }
43
87
  if (extension.encodeToolChoice != null && !hasToolEncoder) {
44
88
  throw new Error(
45
- `Open Responses extension ${extension.id} cannot provide encodeToolChoice without toolType and encodeTool.`
89
+ `Open Responses extension ${extension.id} cannot provide encodeToolChoice without a tool type and encodeTool.`
46
90
  );
47
91
  }
48
92
  if (hasToolType && hasToolEncoder) {
49
93
  const toolExtension = extension;
50
- assertNamespacedType({
51
- extensionId: extension.id,
52
- namespace,
53
- type: toolExtension.toolType,
54
- field: "toolType"
55
- });
94
+ if (extension.toolType != null) {
95
+ assertNamespacedType({
96
+ extensionId: extension.id,
97
+ namespace,
98
+ type: extension.toolType,
99
+ field: "toolType"
100
+ });
101
+ } else {
102
+ assertBareType({
103
+ coreTypes: coreToolTypes,
104
+ extensionId: extension.id,
105
+ type: extension.bareToolType,
106
+ field: "bareToolType"
107
+ });
108
+ }
56
109
  registerUnique({
57
110
  map: registry.byProviderToolId,
58
111
  key: extension.id,
@@ -61,31 +114,35 @@ function createOpenResponsesExtensionRegistry(extensions) {
61
114
  });
62
115
  registerUnique({
63
116
  map: registry.byToolType,
64
- key: toolExtension.toolType,
117
+ key: toolType,
65
118
  extension: toolExtension,
66
- field: "toolType"
119
+ field: "tool type"
67
120
  });
68
121
  }
69
- const hasItemTypes = extension.itemTypes != null;
122
+ const itemTypes = [
123
+ ...extension.itemTypes ?? [],
124
+ ...extension.bareItemTypes ?? []
125
+ ];
126
+ const hasItemTypes = extension.itemTypes != null || extension.bareItemTypes != null;
70
127
  const hasItemDecoder = extension.decodeItem != null;
71
128
  if (hasItemTypes !== hasItemDecoder) {
72
129
  throw new Error(
73
- `Open Responses extension ${extension.id} must provide itemTypes and decodeItem together.`
130
+ `Open Responses extension ${extension.id} must provide itemTypes or bareItemTypes together with decodeItem.`
74
131
  );
75
132
  }
76
133
  if (extension.encodeInputItem != null && !hasItemDecoder) {
77
134
  throw new Error(
78
- `Open Responses extension ${extension.id} cannot provide encodeInputItem without itemTypes and decodeItem.`
135
+ `Open Responses extension ${extension.id} cannot provide encodeInputItem without itemTypes or bareItemTypes and decodeItem.`
79
136
  );
80
137
  }
81
138
  if (hasItemTypes && hasItemDecoder) {
82
139
  const itemExtension = extension;
83
- if (itemExtension.itemTypes.length === 0) {
140
+ if (itemTypes.length === 0) {
84
141
  throw new Error(
85
142
  `Open Responses extension ${extension.id} must register at least one item type.`
86
143
  );
87
144
  }
88
- for (const itemType of itemExtension.itemTypes) {
145
+ for (const itemType of extension.itemTypes ?? []) {
89
146
  assertNamespacedType({
90
147
  extensionId: extension.id,
91
148
  namespace,
@@ -99,22 +156,40 @@ function createOpenResponsesExtensionRegistry(extensions) {
99
156
  field: "item type"
100
157
  });
101
158
  }
159
+ for (const itemType of extension.bareItemTypes ?? []) {
160
+ assertBareType({
161
+ coreTypes: coreItemTypes,
162
+ extensionId: extension.id,
163
+ type: itemType,
164
+ field: "bareItemTypes"
165
+ });
166
+ registerUnique({
167
+ map: registry.byItemType,
168
+ key: itemType,
169
+ extension: itemExtension,
170
+ field: "item type"
171
+ });
172
+ }
102
173
  }
103
- const hasEventTypes = extension.eventTypes != null;
174
+ const eventTypes = [
175
+ ...extension.eventTypes ?? [],
176
+ ...extension.bareEventTypes ?? []
177
+ ];
178
+ const hasEventTypes = extension.eventTypes != null || extension.bareEventTypes != null;
104
179
  const hasEventDecoder = extension.decodeEvent != null;
105
180
  if (hasEventTypes !== hasEventDecoder) {
106
181
  throw new Error(
107
- `Open Responses extension ${extension.id} must provide eventTypes and decodeEvent together.`
182
+ `Open Responses extension ${extension.id} must provide eventTypes or bareEventTypes together with decodeEvent.`
108
183
  );
109
184
  }
110
185
  if (hasEventTypes && hasEventDecoder) {
111
186
  const eventExtension = extension;
112
- if (eventExtension.eventTypes.length === 0) {
187
+ if (eventTypes.length === 0) {
113
188
  throw new Error(
114
189
  `Open Responses extension ${extension.id} must register at least one event type.`
115
190
  );
116
191
  }
117
- for (const eventType of eventExtension.eventTypes) {
192
+ for (const eventType of extension.eventTypes ?? []) {
118
193
  assertNamespacedType({
119
194
  extensionId: extension.id,
120
195
  namespace,
@@ -128,6 +203,20 @@ function createOpenResponsesExtensionRegistry(extensions) {
128
203
  field: "event type"
129
204
  });
130
205
  }
206
+ for (const eventType of extension.bareEventTypes ?? []) {
207
+ assertBareType({
208
+ coreTypes: coreEventTypes,
209
+ extensionId: extension.id,
210
+ type: eventType,
211
+ field: "bareEventTypes"
212
+ });
213
+ registerUnique({
214
+ map: registry.byEventType,
215
+ key: eventType,
216
+ extension: eventExtension,
217
+ field: "event type"
218
+ });
219
+ }
131
220
  }
132
221
  if (!hasToolEncoder && !hasItemDecoder && !hasEventDecoder) {
133
222
  throw new Error(
@@ -143,12 +232,39 @@ function assertNamespacedType({
143
232
  type,
144
233
  field
145
234
  }) {
146
- if (!type.includes(":") || type.slice(0, type.indexOf(":")) !== namespace) {
235
+ const separatorIndex = type.indexOf(":");
236
+ if (separatorIndex <= 0 || type.slice(0, separatorIndex) !== namespace) {
147
237
  throw new Error(
148
238
  `Open Responses extension ${extensionId} has invalid ${field} value ${type}. Extension wire types must use the ${namespace}: namespace.`
149
239
  );
150
240
  }
151
241
  }
242
+ function assertBareType({
243
+ coreTypes,
244
+ extensionId,
245
+ type,
246
+ field
247
+ }) {
248
+ if (type.length === 0 || type.includes(":")) {
249
+ throw new Error(
250
+ `Open Responses extension ${extensionId} has invalid ${field} value ${type}. Bare extension wire types must be non-empty and must not contain a colon.`
251
+ );
252
+ }
253
+ if (coreTypes.has(type)) {
254
+ throw new Error(
255
+ `Open Responses extension ${extensionId} cannot register core ${field} value ${type}.`
256
+ );
257
+ }
258
+ }
259
+ function getOpenResponsesExtensionItemTypes(extension) {
260
+ return [...extension.itemTypes ?? [], ...extension.bareItemTypes ?? []];
261
+ }
262
+ function getOpenResponsesExtensionToolType(extension) {
263
+ return extension.toolType ?? extension.bareToolType;
264
+ }
265
+ function asOpenResponsesExtensionRecord(value) {
266
+ return value;
267
+ }
152
268
  function registerUnique({
153
269
  map,
154
270
  key,
@@ -163,11 +279,8 @@ function registerUnique({
163
279
  }
164
280
  map.set(key, extension);
165
281
  }
166
- function isOpenResponsesNamespacedType(value) {
167
- return typeof value === "string" && value.includes(":");
168
- }
169
282
  function isOpenResponsesExtensionRecord(value) {
170
- return isOpenResponsesJSONObject(value) && isOpenResponsesNamespacedType(value.type);
283
+ return isOpenResponsesJSONObject(value) && typeof value.type === "string";
171
284
  }
172
285
  function isOpenResponsesJSONObject(value) {
173
286
  return value != null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype && Object.values(value).every(isOpenResponsesJSONValue);
@@ -367,7 +480,7 @@ async function convertToOpenResponsesInput({
367
480
  if (replayItem != null) {
368
481
  const replayKey = `${replayItem.type}:${replayItem.id}`;
369
482
  if (!replayedExtensionItems.has(replayKey)) {
370
- input.push(replayItem);
483
+ input.push(asOpenResponsesExtensionRecord(replayItem));
371
484
  replayedExtensionItems.add(replayKey);
372
485
  }
373
486
  }
@@ -389,7 +502,7 @@ async function convertToOpenResponsesInput({
389
502
  feature: `provider-defined tool ${providerTool.id} ${part.type} history`
390
503
  });
391
504
  } else {
392
- input.push(...encoded);
505
+ input.push(...encoded.map(asOpenResponsesExtensionRecord));
393
506
  }
394
507
  continue;
395
508
  }
@@ -496,7 +609,7 @@ async function convertToOpenResponsesInput({
496
609
  if (replayItem != null) {
497
610
  const replayKey = `${replayItem.type}:${replayItem.id}`;
498
611
  if (!replayedExtensionItems.has(replayKey)) {
499
- input.push(replayItem);
612
+ input.push(asOpenResponsesExtensionRecord(replayItem));
500
613
  replayedExtensionItems.add(replayKey);
501
614
  }
502
615
  }
@@ -516,7 +629,7 @@ async function convertToOpenResponsesInput({
516
629
  feature: `provider-defined tool ${providerTool.id} tool-result history`
517
630
  });
518
631
  } else {
519
- input.push(...encoded);
632
+ input.push(...encoded.map(asOpenResponsesExtensionRecord));
520
633
  }
521
634
  continue;
522
635
  }
@@ -622,8 +735,8 @@ async function encodeExtensionInputPart({
622
735
  }) {
623
736
  const extension = extensionRegistry?.byProviderToolId.get(providerTool.id);
624
737
  const encodeInputItem = extension?.encodeInputItem;
625
- const itemTypes = extension?.itemTypes;
626
- if (encodeInputItem == null || itemTypes == null) {
738
+ const itemTypes = extension == null ? [] : getOpenResponsesExtensionItemTypes(extension);
739
+ if (encodeInputItem == null || itemTypes.length === 0) {
627
740
  return void 0;
628
741
  }
629
742
  try {
@@ -664,7 +777,7 @@ function getExtensionReplay({
664
777
  if (extension == null) {
665
778
  return void 0;
666
779
  }
667
- if (isOpenResponsesExtensionItem(item) && extension.itemTypes?.includes(item.type)) {
780
+ if (isOpenResponsesExtensionItem(item) && getOpenResponsesExtensionItemTypes(extension).includes(item.type)) {
668
781
  return { item };
669
782
  }
670
783
  return typeof itemId === "string" ? {} : void 0;
@@ -866,6 +979,7 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
866
979
  const extension = this.extensionRegistry.byProviderToolId.get(tool.id);
867
980
  let encoded;
868
981
  if (extension != null) {
982
+ const toolType = getOpenResponsesExtensionToolType(extension);
869
983
  try {
870
984
  const fields = await extension.encodeTool({
871
985
  name: tool.name,
@@ -874,7 +988,7 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
874
988
  if (isOpenResponsesJSONObject(fields)) {
875
989
  encoded = {
876
990
  ...fields,
877
- type: extension.toolType
991
+ type: toolType
878
992
  };
879
993
  }
880
994
  } catch {
@@ -886,9 +1000,9 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
886
1000
  feature: `provider-defined tool ${tool.id}`
887
1001
  });
888
1002
  } else if (extension != null) {
889
- convertedTools.push(encoded);
1003
+ convertedTools.push(asOpenResponsesExtensionRecord(encoded));
890
1004
  encodedProviderToolsByName.set(tool.name, {
891
- toolType: extension.toolType,
1005
+ toolType: getOpenResponsesExtensionToolType(extension),
892
1006
  encodeToolChoice: extension.encodeToolChoice,
893
1007
  tool
894
1008
  });
@@ -937,10 +1051,10 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
937
1051
  feature: `tool choice for provider-defined tool ${tool.id}`
938
1052
  });
939
1053
  } else {
940
- convertedToolChoice = {
1054
+ convertedToolChoice = asOpenResponsesExtensionRecord({
941
1055
  ...isOpenResponsesJSONObject(fields) ? fields : {},
942
1056
  type: toolType
943
- };
1057
+ });
944
1058
  }
945
1059
  }
946
1060
  } else {
@@ -1269,8 +1383,8 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
1269
1383
  } catch (error) {
1270
1384
  controller.enqueue({ type: "error", error });
1271
1385
  }
1386
+ return;
1272
1387
  }
1273
- return;
1274
1388
  }
1275
1389
  if (chunk.type === "response.output_item.added" && chunk.item.type === "function_call") {
1276
1390
  toolCallsByItemId.set(chunk.item.id, {
@@ -1366,7 +1480,7 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
1366
1480
  });
1367
1481
  hasToolCalls = true;
1368
1482
  customToolCallsByItemId.delete(chunk.item.id);
1369
- } else if (chunk.type === "response.output_item.done" && isOpenResponsesExtensionItem(chunk.item)) {
1483
+ } else if (chunk.type === "response.output_item.done" && isOpenResponsesExtensionItem(chunk.item) && extensionRegistry.byItemType.has(chunk.item.type)) {
1370
1484
  try {
1371
1485
  const decoded = await decodeExtensionItem({
1372
1486
  extensionRegistry,