@ai-sdk/open-responses 2.0.34 → 2.0.36
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 +16 -0
- package/dist/index.d.ts +96 -3
- package/dist/index.js +523 -13
- package/dist/index.js.map +1 -1
- package/docs/06-open-responses.mdx +116 -2
- package/package.json +3 -3
- package/src/index.ts +10 -0
- package/src/open-responses-extension.ts +387 -0
- package/src/open-responses-provider.ts +15 -0
- package/src/responses/convert-to-open-responses-input.ts +193 -0
- package/src/responses/open-responses-api.ts +14 -4
- package/src/responses/open-responses-config.ts +2 -0
- package/src/responses/open-responses-language-model.ts +270 -16
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = true ? "2.0.
|
|
2
|
+
var VERSION = true ? "2.0.36" : "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
|
|
@@ -25,6 +203,7 @@ import {
|
|
|
25
203
|
mapReasoningToProviderEffort,
|
|
26
204
|
parseProviderOptions,
|
|
27
205
|
postJsonToApi,
|
|
206
|
+
SerializationError,
|
|
28
207
|
serializeModelOptions,
|
|
29
208
|
WORKFLOW_SERIALIZE,
|
|
30
209
|
WORKFLOW_DESERIALIZE
|
|
@@ -42,12 +221,15 @@ import {
|
|
|
42
221
|
} from "@ai-sdk/provider-utils";
|
|
43
222
|
async function convertToOpenResponsesInput({
|
|
44
223
|
prompt,
|
|
45
|
-
providerOptionsName = "open-responses"
|
|
224
|
+
providerOptionsName = "open-responses",
|
|
225
|
+
extensionRegistry,
|
|
226
|
+
providerToolsByName = /* @__PURE__ */ new Map()
|
|
46
227
|
}) {
|
|
47
228
|
var _a, _b, _c, _d;
|
|
48
229
|
const input = [];
|
|
49
230
|
const warnings = [];
|
|
50
231
|
const systemMessages = [];
|
|
232
|
+
const replayedExtensionItems = /* @__PURE__ */ new Set();
|
|
51
233
|
for (const { role, content } of prompt) {
|
|
52
234
|
switch (role) {
|
|
53
235
|
case "system": {
|
|
@@ -124,6 +306,44 @@ async function convertToOpenResponsesInput({
|
|
|
124
306
|
assistantMessageId = void 0;
|
|
125
307
|
};
|
|
126
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
|
+
}
|
|
127
347
|
switch (part.type) {
|
|
128
348
|
case "reasoning": {
|
|
129
349
|
flushAssistantContent();
|
|
@@ -205,6 +425,40 @@ async function convertToOpenResponsesInput({
|
|
|
205
425
|
case "tool": {
|
|
206
426
|
for (const part of content) {
|
|
207
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
|
+
}
|
|
208
462
|
const output = part.output;
|
|
209
463
|
let contentValue;
|
|
210
464
|
switch (output.type) {
|
|
@@ -298,6 +552,61 @@ async function convertToOpenResponsesInput({
|
|
|
298
552
|
warnings
|
|
299
553
|
};
|
|
300
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
|
+
}
|
|
301
610
|
function getProviderData(part, providerOptionsName) {
|
|
302
611
|
var _a, _b, _c;
|
|
303
612
|
const providerData = (_c = (_a = part.providerOptions) == null ? void 0 : _a[providerOptionsName]) != null ? _c : (_b = part.providerMetadata) == null ? void 0 : _b[providerOptionsName];
|
|
@@ -404,10 +713,17 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
404
713
|
this.supportedUrls = {
|
|
405
714
|
"image/*": [/^https?:\/\/.*$/]
|
|
406
715
|
};
|
|
716
|
+
var _a;
|
|
407
717
|
this.modelId = modelId;
|
|
408
718
|
this.config = config;
|
|
719
|
+
this.extensionRegistry = (_a = config.extensionRegistry) != null ? _a : createOpenResponsesExtensionRegistry();
|
|
409
720
|
}
|
|
410
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
|
+
}
|
|
411
727
|
return serializeModelOptions({
|
|
412
728
|
modelId: model.modelId,
|
|
413
729
|
config: model.config
|
|
@@ -446,24 +762,56 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
446
762
|
if (seed != null) {
|
|
447
763
|
warnings.push({ type: "unsupported", feature: "seed" });
|
|
448
764
|
}
|
|
765
|
+
const providerToolsByName = new Map(
|
|
766
|
+
(tools != null ? tools : []).filter((tool) => tool.type === "provider").map((tool) => [tool.name, tool])
|
|
767
|
+
);
|
|
449
768
|
const {
|
|
450
769
|
input,
|
|
451
770
|
instructions,
|
|
452
771
|
warnings: inputWarnings
|
|
453
772
|
} = await convertToOpenResponsesInput({
|
|
454
773
|
prompt,
|
|
455
|
-
providerOptionsName: this.config.providerOptionsName
|
|
774
|
+
providerOptionsName: this.config.providerOptionsName,
|
|
775
|
+
extensionRegistry: this.extensionRegistry,
|
|
776
|
+
providerToolsByName
|
|
456
777
|
});
|
|
457
778
|
warnings.push(...inputWarnings);
|
|
458
|
-
const
|
|
779
|
+
const convertedTools = [];
|
|
780
|
+
const encodedProviderToolsByName = /* @__PURE__ */ new Map();
|
|
459
781
|
for (const tool of tools != null ? tools : []) {
|
|
460
782
|
if (tool.type === "provider") {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
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
|
+
}
|
|
465
813
|
} else {
|
|
466
|
-
|
|
814
|
+
convertedTools.push({
|
|
467
815
|
type: "function",
|
|
468
816
|
name: tool.name,
|
|
469
817
|
description: tool.description,
|
|
@@ -472,7 +820,44 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
472
820
|
});
|
|
473
821
|
}
|
|
474
822
|
}
|
|
475
|
-
|
|
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
|
+
}
|
|
476
861
|
const textFormat = (responseFormat == null ? void 0 : responseFormat.type) === "json" ? {
|
|
477
862
|
type: "json_schema",
|
|
478
863
|
...responseFormat.schema != null ? {
|
|
@@ -516,7 +901,7 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
516
901
|
summary: openResponsesOptions.reasoningSummary
|
|
517
902
|
}
|
|
518
903
|
} : void 0,
|
|
519
|
-
tools:
|
|
904
|
+
tools: convertedTools.length ? convertedTools : void 0,
|
|
520
905
|
tool_choice: convertedToolChoice,
|
|
521
906
|
...textFormat != null && { text: { format: textFormat } }
|
|
522
907
|
},
|
|
@@ -629,6 +1014,22 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
629
1014
|
});
|
|
630
1015
|
break;
|
|
631
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
|
+
}
|
|
632
1033
|
}
|
|
633
1034
|
}
|
|
634
1035
|
const usage = response.usage;
|
|
@@ -732,13 +1133,15 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
732
1133
|
};
|
|
733
1134
|
const toolCallsByItemId = /* @__PURE__ */ new Map();
|
|
734
1135
|
const providerOptionsName = this.config.providerOptionsName;
|
|
1136
|
+
const extensionRegistry = this.extensionRegistry;
|
|
1137
|
+
const extensionStreamState = /* @__PURE__ */ new Map();
|
|
735
1138
|
return {
|
|
736
1139
|
stream: response.pipeThrough(
|
|
737
1140
|
new TransformStream({
|
|
738
1141
|
start(controller) {
|
|
739
1142
|
controller.enqueue({ type: "stream-start", warnings });
|
|
740
1143
|
},
|
|
741
|
-
transform(parseResult, controller) {
|
|
1144
|
+
async transform(parseResult, controller) {
|
|
742
1145
|
var _a2, _b2, _c, _d, _e, _f, _g, _h;
|
|
743
1146
|
if (options.includeRawChunks) {
|
|
744
1147
|
controller.enqueue({
|
|
@@ -751,6 +1154,24 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
751
1154
|
return;
|
|
752
1155
|
}
|
|
753
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
|
+
}
|
|
754
1175
|
if (chunk.type === "response.output_item.added" && chunk.item.type === "function_call") {
|
|
755
1176
|
toolCallsByItemId.set(chunk.item.id, {
|
|
756
1177
|
toolName: chunk.item.name,
|
|
@@ -795,6 +1216,21 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
795
1216
|
});
|
|
796
1217
|
hasToolCalls = true;
|
|
797
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
|
+
}
|
|
798
1234
|
} else if (chunk.type === "response.output_item.added" && chunk.item.type === "reasoning") {
|
|
799
1235
|
controller.enqueue({
|
|
800
1236
|
type: "reasoning-start",
|
|
@@ -938,6 +1374,76 @@ function createReasoningProviderMetadata({
|
|
|
938
1374
|
}
|
|
939
1375
|
};
|
|
940
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
|
+
}
|
|
941
1447
|
function getOutputTextAnnotations(value) {
|
|
942
1448
|
if (value == null || typeof value !== "object" || !("annotations" in value) || !Array.isArray(value.annotations) || !value.annotations.every(
|
|
943
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"
|
|
@@ -956,6 +1462,9 @@ function getOutputTextAnnotations(value) {
|
|
|
956
1462
|
// src/open-responses-provider.ts
|
|
957
1463
|
function createOpenResponses(options) {
|
|
958
1464
|
const providerName = options.name;
|
|
1465
|
+
const extensionRegistry = createOpenResponsesExtensionRegistry(
|
|
1466
|
+
options.experimental_extensions
|
|
1467
|
+
);
|
|
959
1468
|
const getHeaders = () => withUserAgentSuffix(
|
|
960
1469
|
{
|
|
961
1470
|
...options.apiKey ? {
|
|
@@ -972,7 +1481,8 @@ function createOpenResponses(options) {
|
|
|
972
1481
|
headers: getHeaders,
|
|
973
1482
|
url: options.url,
|
|
974
1483
|
fetch: options.fetch,
|
|
975
|
-
generateId: () => generateId()
|
|
1484
|
+
generateId: () => generateId(),
|
|
1485
|
+
extensionRegistry
|
|
976
1486
|
});
|
|
977
1487
|
};
|
|
978
1488
|
const createLanguageModel = (modelId) => {
|