@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/CHANGELOG.md +31 -0
- package/dist/index.d.ts +96 -3
- package/dist/index.js +560 -14
- package/dist/index.js.map +1 -1
- package/docs/06-open-responses.mdx +116 -2
- package/package.json +2 -2
- 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 +313 -17
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.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
|
|
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
|
-
|
|
461
|
-
|
|
462
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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) => {
|