@yourgpt/llm-sdk 2.6.0-beta.2 → 2.6.0-beta.3
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/README.md +42 -8
- package/dist/adapters/index.js +86 -21
- package/dist/adapters/index.mjs +86 -21
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +108 -19
- package/dist/index.mjs +108 -19
- package/dist/providers/anthropic/index.js +6 -13
- package/dist/providers/anthropic/index.mjs +6 -13
- package/dist/providers/fireworks/index.js +80 -8
- package/dist/providers/fireworks/index.mjs +80 -8
- package/dist/providers/google/index.js +80 -8
- package/dist/providers/google/index.mjs +80 -8
- package/dist/providers/openai/index.js +80 -8
- package/dist/providers/openai/index.mjs +80 -8
- package/dist/providers/openrouter/index.js +80 -8
- package/dist/providers/openrouter/index.mjs +80 -8
- package/dist/providers/togetherai/index.js +80 -8
- package/dist/providers/togetherai/index.mjs +80 -8
- package/dist/providers/xai/index.js +80 -8
- package/dist/providers/xai/index.mjs +80 -8
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { cors } from 'hono/cors';
|
|
3
3
|
|
|
4
|
+
// src/core/openai-responses.ts
|
|
5
|
+
function responseReplayMetadata(metadata) {
|
|
6
|
+
const response = metadata?.openai?.response;
|
|
7
|
+
if (!response) return metadata;
|
|
8
|
+
const output = response.output.map((item) => {
|
|
9
|
+
const fields = ["type", "id", "status"];
|
|
10
|
+
switch (item.type) {
|
|
11
|
+
case "reasoning":
|
|
12
|
+
fields.push("encrypted_content");
|
|
13
|
+
break;
|
|
14
|
+
case "message":
|
|
15
|
+
fields.push("role", "phase");
|
|
16
|
+
break;
|
|
17
|
+
case "function_call":
|
|
18
|
+
fields.push("call_id", "name", "namespace", "arguments");
|
|
19
|
+
break;
|
|
20
|
+
case "tool_search_call":
|
|
21
|
+
fields.push("call_id", "execution", "arguments");
|
|
22
|
+
break;
|
|
23
|
+
case "tool_search_output":
|
|
24
|
+
fields.push("call_id", "tools");
|
|
25
|
+
break;
|
|
26
|
+
case "web_search_call":
|
|
27
|
+
fields.push("action");
|
|
28
|
+
break;
|
|
29
|
+
default:
|
|
30
|
+
return stripItemDiagnostics(item);
|
|
31
|
+
}
|
|
32
|
+
const replay = Object.fromEntries(
|
|
33
|
+
fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
|
|
34
|
+
);
|
|
35
|
+
if (item.type === "reasoning") replay.summary = [];
|
|
36
|
+
if (item.type === "message")
|
|
37
|
+
replay.content = Array.isArray(item.content) ? item.content.flatMap(
|
|
38
|
+
(part) => part?.type === "output_text" && typeof part.text === "string" ? [{ type: "output_text", text: part.text, annotations: [] }] : part?.type === "refusal" && typeof part.refusal === "string" ? [{ type: "refusal", refusal: part.refusal }] : []
|
|
39
|
+
) : [];
|
|
40
|
+
return stripItemDiagnostics(replay);
|
|
41
|
+
});
|
|
42
|
+
return { openai: { response: { output, refusals: [] } } };
|
|
43
|
+
}
|
|
44
|
+
function stripItemDiagnostics(item) {
|
|
45
|
+
const {
|
|
46
|
+
usage: _usage,
|
|
47
|
+
logprobs: _logprobs,
|
|
48
|
+
metadata: _metadata,
|
|
49
|
+
...state
|
|
50
|
+
} = item;
|
|
51
|
+
return state;
|
|
52
|
+
}
|
|
53
|
+
|
|
4
54
|
// src/core/tool-output.ts
|
|
5
55
|
var imageTypes = /* @__PURE__ */ new Set([
|
|
6
56
|
"image/png",
|
|
@@ -238,10 +288,11 @@ async function generateText(params) {
|
|
|
238
288
|
signal
|
|
239
289
|
});
|
|
240
290
|
throwIfAborted(signal);
|
|
291
|
+
const toolCalls = result.toolCalls ?? [];
|
|
241
292
|
const stepToolResults = [];
|
|
242
|
-
if (
|
|
243
|
-
allToolCalls.push(...
|
|
244
|
-
for (const call of
|
|
293
|
+
if (toolCalls.length > 0 && tools) {
|
|
294
|
+
allToolCalls.push(...toolCalls);
|
|
295
|
+
for (const call of toolCalls) {
|
|
245
296
|
throwIfAborted(signal);
|
|
246
297
|
const toolDef = tools[call.name];
|
|
247
298
|
if (!toolDef) {
|
|
@@ -286,7 +337,7 @@ async function generateText(params) {
|
|
|
286
337
|
}
|
|
287
338
|
steps.push({
|
|
288
339
|
text: result.text,
|
|
289
|
-
toolCalls
|
|
340
|
+
toolCalls,
|
|
290
341
|
toolResults: stepToolResults,
|
|
291
342
|
finishReason: result.finishReason,
|
|
292
343
|
usage: result.usage,
|
|
@@ -295,11 +346,11 @@ async function generateText(params) {
|
|
|
295
346
|
const assistantMessage = {
|
|
296
347
|
role: "assistant",
|
|
297
348
|
content: result.text || null,
|
|
298
|
-
...
|
|
299
|
-
...result.providerMetadata ? { providerMetadata: result.providerMetadata } : {}
|
|
349
|
+
...toolCalls.length ? { toolCalls } : {},
|
|
350
|
+
...result.providerMetadata ? { providerMetadata: responseReplayMetadata(result.providerMetadata) } : {}
|
|
300
351
|
};
|
|
301
352
|
messages = [...messages, assistantMessage];
|
|
302
|
-
if (
|
|
353
|
+
if (toolCalls.length === 0) break;
|
|
303
354
|
for (const tr of stepToolResults) {
|
|
304
355
|
const toolMessage = {
|
|
305
356
|
role: "tool",
|
|
@@ -450,7 +501,7 @@ async function streamText(params) {
|
|
|
450
501
|
role: "assistant",
|
|
451
502
|
content: stepText || null,
|
|
452
503
|
...toolCalls.length ? { toolCalls } : {},
|
|
453
|
-
...stepProviderMetadata ? { providerMetadata: stepProviderMetadata } : {}
|
|
504
|
+
...stepProviderMetadata ? { providerMetadata: responseReplayMetadata(stepProviderMetadata) } : {}
|
|
454
505
|
}
|
|
455
506
|
];
|
|
456
507
|
if (toolCalls.length === 0 || !tools) break;
|
|
@@ -782,17 +833,32 @@ function createTextStreamHeaders() {
|
|
|
782
833
|
};
|
|
783
834
|
}
|
|
784
835
|
function formatSSEData(event) {
|
|
785
|
-
|
|
836
|
+
const safeEvent = { ...event };
|
|
837
|
+
if ("providerMetadata" in safeEvent)
|
|
838
|
+
safeEvent.providerMetadata = responseReplayMetadata(
|
|
839
|
+
safeEvent.providerMetadata
|
|
840
|
+
);
|
|
841
|
+
if (safeEvent.type === "done" && safeEvent.messages)
|
|
842
|
+
safeEvent.messages = safeEvent.messages.map((message) => ({
|
|
843
|
+
...message,
|
|
844
|
+
...message.providerMetadata ? { providerMetadata: responseReplayMetadata(message.providerMetadata) } : {}
|
|
845
|
+
}));
|
|
846
|
+
return `data: ${JSON.stringify(safeEvent)}
|
|
786
847
|
|
|
787
848
|
`;
|
|
788
849
|
}
|
|
789
|
-
function createEventStream(generator) {
|
|
850
|
+
function createEventStream(generator, options) {
|
|
790
851
|
const encoder = new TextEncoder();
|
|
791
852
|
return new ReadableStream({
|
|
792
853
|
async start(controller) {
|
|
793
854
|
try {
|
|
794
855
|
for await (const event of generator) {
|
|
795
|
-
|
|
856
|
+
let clientEvent = event;
|
|
857
|
+
if (event.type === "done" && !options?.includeUsage) {
|
|
858
|
+
const { usage: _usage, ...withoutUsage } = event;
|
|
859
|
+
clientEvent = withoutUsage;
|
|
860
|
+
}
|
|
861
|
+
const data = formatSSEData(clientEvent);
|
|
796
862
|
controller.enqueue(encoder.encode(data));
|
|
797
863
|
}
|
|
798
864
|
} catch (error) {
|
|
@@ -933,7 +999,9 @@ var StreamResult = class {
|
|
|
933
999
|
...createSSEHeaders(),
|
|
934
1000
|
...options?.headers
|
|
935
1001
|
};
|
|
936
|
-
return new Response(createEventStream(this.generator), {
|
|
1002
|
+
return new Response(createEventStream(this.generator, options), {
|
|
1003
|
+
headers
|
|
1004
|
+
});
|
|
937
1005
|
}
|
|
938
1006
|
/**
|
|
939
1007
|
* Alias for toResponse() - returns SSE Response
|
|
@@ -2376,7 +2444,10 @@ var Runtime = class {
|
|
|
2376
2444
|
yield event;
|
|
2377
2445
|
break;
|
|
2378
2446
|
case "message:end":
|
|
2379
|
-
yield
|
|
2447
|
+
yield {
|
|
2448
|
+
...event,
|
|
2449
|
+
providerMetadata: responseReplayMetadata(event.providerMetadata)
|
|
2450
|
+
};
|
|
2380
2451
|
break;
|
|
2381
2452
|
case "message:delta":
|
|
2382
2453
|
accumulatedText += event.content;
|
|
@@ -2498,7 +2569,9 @@ var Runtime = class {
|
|
|
2498
2569
|
return;
|
|
2499
2570
|
// Exit on error
|
|
2500
2571
|
case "done":
|
|
2501
|
-
adapterProviderMetadata =
|
|
2572
|
+
adapterProviderMetadata = responseReplayMetadata(
|
|
2573
|
+
event.providerMetadata
|
|
2574
|
+
);
|
|
2502
2575
|
if (event.usage) {
|
|
2503
2576
|
adapterUsage = event.usage;
|
|
2504
2577
|
}
|
|
@@ -2769,7 +2842,7 @@ var Runtime = class {
|
|
|
2769
2842
|
}
|
|
2770
2843
|
yield {
|
|
2771
2844
|
type: "message:end",
|
|
2772
|
-
providerMetadata: result.providerMetadata
|
|
2845
|
+
providerMetadata: responseReplayMetadata(result.providerMetadata)
|
|
2773
2846
|
};
|
|
2774
2847
|
if (result.toolCalls.length > 0) {
|
|
2775
2848
|
const serverToolCalls = [];
|
|
@@ -2870,7 +2943,11 @@ var Runtime = class {
|
|
|
2870
2943
|
const assistantMessage = {
|
|
2871
2944
|
role: "assistant",
|
|
2872
2945
|
content: result.content || null,
|
|
2873
|
-
...result.providerMetadata ? {
|
|
2946
|
+
...result.providerMetadata ? {
|
|
2947
|
+
providerMetadata: responseReplayMetadata(
|
|
2948
|
+
result.providerMetadata
|
|
2949
|
+
)
|
|
2950
|
+
} : {},
|
|
2874
2951
|
tool_calls: result.toolCalls.map((tc) => ({
|
|
2875
2952
|
id: tc.id,
|
|
2876
2953
|
type: "function",
|
|
@@ -2900,7 +2977,11 @@ var Runtime = class {
|
|
|
2900
2977
|
const assistantWithToolCalls = {
|
|
2901
2978
|
role: "assistant",
|
|
2902
2979
|
content: result.content || null,
|
|
2903
|
-
...result.providerMetadata ? {
|
|
2980
|
+
...result.providerMetadata ? {
|
|
2981
|
+
providerMetadata: responseReplayMetadata(
|
|
2982
|
+
result.providerMetadata
|
|
2983
|
+
)
|
|
2984
|
+
} : {},
|
|
2904
2985
|
tool_calls: result.toolCalls.map((tc) => ({
|
|
2905
2986
|
id: tc.id,
|
|
2906
2987
|
type: "function",
|
|
@@ -2932,7 +3013,11 @@ var Runtime = class {
|
|
|
2932
3013
|
const assistantMessage = {
|
|
2933
3014
|
role: "assistant",
|
|
2934
3015
|
content: result.content || null,
|
|
2935
|
-
...result.providerMetadata ? {
|
|
3016
|
+
...result.providerMetadata ? {
|
|
3017
|
+
providerMetadata: responseReplayMetadata(
|
|
3018
|
+
result.providerMetadata
|
|
3019
|
+
)
|
|
3020
|
+
} : {},
|
|
2936
3021
|
tool_calls: clientToolCalls.map((tc) => ({
|
|
2937
3022
|
id: tc.id,
|
|
2938
3023
|
type: "function",
|
|
@@ -2962,7 +3047,11 @@ var Runtime = class {
|
|
|
2962
3047
|
newMessages.push({
|
|
2963
3048
|
role: "assistant",
|
|
2964
3049
|
content: result.content,
|
|
2965
|
-
...result.providerMetadata ? {
|
|
3050
|
+
...result.providerMetadata ? {
|
|
3051
|
+
providerMetadata: responseReplayMetadata(
|
|
3052
|
+
result.providerMetadata
|
|
3053
|
+
)
|
|
3054
|
+
} : {}
|
|
2966
3055
|
});
|
|
2967
3056
|
}
|
|
2968
3057
|
if (debug) {
|
|
@@ -294,21 +294,14 @@ function messageToAnthropicContent(message) {
|
|
|
294
294
|
return blocks;
|
|
295
295
|
}
|
|
296
296
|
function extractAnthropicSystemPrompt(messages, systemPrompt) {
|
|
297
|
-
const
|
|
297
|
+
const explicit = typeof systemPrompt === "string" ? systemPrompt : "";
|
|
298
|
+
const parts = explicit ? [explicit] : [];
|
|
298
299
|
for (const message of messages) {
|
|
299
300
|
if (message.role !== "system") continue;
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (block?.type !== "text" || typeof block.text !== "string") {
|
|
305
|
-
throw new TypeError("Anthropic system messages must contain text.");
|
|
306
|
-
}
|
|
307
|
-
if (block.text) parts.push(block.text);
|
|
308
|
-
}
|
|
309
|
-
} else {
|
|
310
|
-
throw new TypeError("Anthropic system messages must contain text.");
|
|
311
|
-
}
|
|
301
|
+
const text = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.filter(
|
|
302
|
+
(block) => block?.type === "text" && typeof block.text === "string"
|
|
303
|
+
).map((block) => block.text).filter(Boolean).join("\n") : "";
|
|
304
|
+
if (text && text !== explicit) parts.push(text);
|
|
312
305
|
}
|
|
313
306
|
return parts.join("\n");
|
|
314
307
|
}
|
|
@@ -292,21 +292,14 @@ function messageToAnthropicContent(message) {
|
|
|
292
292
|
return blocks;
|
|
293
293
|
}
|
|
294
294
|
function extractAnthropicSystemPrompt(messages, systemPrompt) {
|
|
295
|
-
const
|
|
295
|
+
const explicit = typeof systemPrompt === "string" ? systemPrompt : "";
|
|
296
|
+
const parts = explicit ? [explicit] : [];
|
|
296
297
|
for (const message of messages) {
|
|
297
298
|
if (message.role !== "system") continue;
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (block?.type !== "text" || typeof block.text !== "string") {
|
|
303
|
-
throw new TypeError("Anthropic system messages must contain text.");
|
|
304
|
-
}
|
|
305
|
-
if (block.text) parts.push(block.text);
|
|
306
|
-
}
|
|
307
|
-
} else {
|
|
308
|
-
throw new TypeError("Anthropic system messages must contain text.");
|
|
309
|
-
}
|
|
299
|
+
const text = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.filter(
|
|
300
|
+
(block) => block?.type === "text" && typeof block.text === "string"
|
|
301
|
+
).map((block) => block.text).filter(Boolean).join("\n") : "";
|
|
302
|
+
if (text && text !== explicit) parts.push(text);
|
|
310
303
|
}
|
|
311
304
|
return parts.join("\n");
|
|
312
305
|
}
|
|
@@ -635,6 +635,54 @@ function responseMetadata(response) {
|
|
|
635
635
|
}
|
|
636
636
|
};
|
|
637
637
|
}
|
|
638
|
+
function responseReplayMetadata(metadata) {
|
|
639
|
+
const response = metadata?.openai?.response;
|
|
640
|
+
if (!response) return metadata;
|
|
641
|
+
const output = response.output.map((item) => {
|
|
642
|
+
const fields = ["type", "id", "status"];
|
|
643
|
+
switch (item.type) {
|
|
644
|
+
case "reasoning":
|
|
645
|
+
fields.push("encrypted_content");
|
|
646
|
+
break;
|
|
647
|
+
case "message":
|
|
648
|
+
fields.push("role", "phase");
|
|
649
|
+
break;
|
|
650
|
+
case "function_call":
|
|
651
|
+
fields.push("call_id", "name", "namespace", "arguments");
|
|
652
|
+
break;
|
|
653
|
+
case "tool_search_call":
|
|
654
|
+
fields.push("call_id", "execution", "arguments");
|
|
655
|
+
break;
|
|
656
|
+
case "tool_search_output":
|
|
657
|
+
fields.push("call_id", "tools");
|
|
658
|
+
break;
|
|
659
|
+
case "web_search_call":
|
|
660
|
+
fields.push("action");
|
|
661
|
+
break;
|
|
662
|
+
default:
|
|
663
|
+
return stripItemDiagnostics(item);
|
|
664
|
+
}
|
|
665
|
+
const replay = Object.fromEntries(
|
|
666
|
+
fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
|
|
667
|
+
);
|
|
668
|
+
if (item.type === "reasoning") replay.summary = [];
|
|
669
|
+
if (item.type === "message")
|
|
670
|
+
replay.content = Array.isArray(item.content) ? item.content.flatMap(
|
|
671
|
+
(part) => part?.type === "output_text" && typeof part.text === "string" ? [{ type: "output_text", text: part.text, annotations: [] }] : part?.type === "refusal" && typeof part.refusal === "string" ? [{ type: "refusal", refusal: part.refusal }] : []
|
|
672
|
+
) : [];
|
|
673
|
+
return stripItemDiagnostics(replay);
|
|
674
|
+
});
|
|
675
|
+
return { openai: { response: { output, refusals: [] } } };
|
|
676
|
+
}
|
|
677
|
+
function stripItemDiagnostics(item) {
|
|
678
|
+
const {
|
|
679
|
+
usage: _usage,
|
|
680
|
+
logprobs: _logprobs,
|
|
681
|
+
metadata: _metadata,
|
|
682
|
+
...state
|
|
683
|
+
} = item;
|
|
684
|
+
return state;
|
|
685
|
+
}
|
|
638
686
|
function getResponseReplay(metadata) {
|
|
639
687
|
const response = metadata?.openai?.response;
|
|
640
688
|
if (response === void 0) return void 0;
|
|
@@ -643,10 +691,17 @@ function getResponseReplay(metadata) {
|
|
|
643
691
|
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
644
692
|
);
|
|
645
693
|
}
|
|
646
|
-
return response
|
|
694
|
+
return responseReplayMetadata(metadata)?.openai?.response?.output;
|
|
647
695
|
}
|
|
648
696
|
|
|
649
697
|
// src/core/provider-error.ts
|
|
698
|
+
function invalidProviderResponse(message) {
|
|
699
|
+
return Object.assign(new Error(message), {
|
|
700
|
+
name: "InvalidProviderResponseError",
|
|
701
|
+
status: 502,
|
|
702
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
703
|
+
});
|
|
704
|
+
}
|
|
650
705
|
function providerErrorEvent(error, code) {
|
|
651
706
|
const details = error ?? {};
|
|
652
707
|
const event = {
|
|
@@ -823,7 +878,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
823
878
|
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
824
879
|
return messages.map((message) => {
|
|
825
880
|
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
826
|
-
let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput,
|
|
881
|
+
let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
|
|
827
882
|
if (preserveProviderMetadata && modelOutput)
|
|
828
883
|
rest.modelOutput = modelOutput;
|
|
829
884
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
@@ -926,17 +981,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
926
981
|
const seenCallIds = /* @__PURE__ */ new Set();
|
|
927
982
|
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
928
983
|
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
929
|
-
throw
|
|
984
|
+
throw invalidProviderResponse(
|
|
985
|
+
"Responses contains an incomplete function call"
|
|
986
|
+
);
|
|
930
987
|
}
|
|
931
988
|
if (seenCallIds.has(item.call_id))
|
|
932
|
-
throw
|
|
989
|
+
throw invalidProviderResponse(
|
|
990
|
+
"Responses contains duplicate function call IDs"
|
|
991
|
+
);
|
|
933
992
|
seenCallIds.add(item.call_id);
|
|
934
|
-
|
|
993
|
+
let args;
|
|
994
|
+
try {
|
|
995
|
+
args = JSON.parse(item.arguments);
|
|
996
|
+
} catch {
|
|
997
|
+
throw invalidProviderResponse(
|
|
998
|
+
"Responses function arguments must be valid JSON"
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
935
1001
|
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
936
|
-
throw
|
|
1002
|
+
throw invalidProviderResponse(
|
|
937
1003
|
"Responses function arguments must be a JSON object"
|
|
938
1004
|
);
|
|
939
|
-
return {
|
|
1005
|
+
return {
|
|
1006
|
+
id: item.call_id,
|
|
1007
|
+
name: item.name,
|
|
1008
|
+
args
|
|
1009
|
+
};
|
|
940
1010
|
}) : [];
|
|
941
1011
|
return {
|
|
942
1012
|
content,
|
|
@@ -1179,7 +1249,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1179
1249
|
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1180
1250
|
for (const call of toolCalls.values()) {
|
|
1181
1251
|
if (!call.id || !call.name)
|
|
1182
|
-
throw
|
|
1252
|
+
throw invalidProviderResponse(
|
|
1253
|
+
"Responses stream contains an incomplete tool call"
|
|
1254
|
+
);
|
|
1183
1255
|
uniqueCalls.set(call.id, call);
|
|
1184
1256
|
}
|
|
1185
1257
|
toolCalls.clear();
|
|
@@ -633,6 +633,54 @@ function responseMetadata(response) {
|
|
|
633
633
|
}
|
|
634
634
|
};
|
|
635
635
|
}
|
|
636
|
+
function responseReplayMetadata(metadata) {
|
|
637
|
+
const response = metadata?.openai?.response;
|
|
638
|
+
if (!response) return metadata;
|
|
639
|
+
const output = response.output.map((item) => {
|
|
640
|
+
const fields = ["type", "id", "status"];
|
|
641
|
+
switch (item.type) {
|
|
642
|
+
case "reasoning":
|
|
643
|
+
fields.push("encrypted_content");
|
|
644
|
+
break;
|
|
645
|
+
case "message":
|
|
646
|
+
fields.push("role", "phase");
|
|
647
|
+
break;
|
|
648
|
+
case "function_call":
|
|
649
|
+
fields.push("call_id", "name", "namespace", "arguments");
|
|
650
|
+
break;
|
|
651
|
+
case "tool_search_call":
|
|
652
|
+
fields.push("call_id", "execution", "arguments");
|
|
653
|
+
break;
|
|
654
|
+
case "tool_search_output":
|
|
655
|
+
fields.push("call_id", "tools");
|
|
656
|
+
break;
|
|
657
|
+
case "web_search_call":
|
|
658
|
+
fields.push("action");
|
|
659
|
+
break;
|
|
660
|
+
default:
|
|
661
|
+
return stripItemDiagnostics(item);
|
|
662
|
+
}
|
|
663
|
+
const replay = Object.fromEntries(
|
|
664
|
+
fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
|
|
665
|
+
);
|
|
666
|
+
if (item.type === "reasoning") replay.summary = [];
|
|
667
|
+
if (item.type === "message")
|
|
668
|
+
replay.content = Array.isArray(item.content) ? item.content.flatMap(
|
|
669
|
+
(part) => part?.type === "output_text" && typeof part.text === "string" ? [{ type: "output_text", text: part.text, annotations: [] }] : part?.type === "refusal" && typeof part.refusal === "string" ? [{ type: "refusal", refusal: part.refusal }] : []
|
|
670
|
+
) : [];
|
|
671
|
+
return stripItemDiagnostics(replay);
|
|
672
|
+
});
|
|
673
|
+
return { openai: { response: { output, refusals: [] } } };
|
|
674
|
+
}
|
|
675
|
+
function stripItemDiagnostics(item) {
|
|
676
|
+
const {
|
|
677
|
+
usage: _usage,
|
|
678
|
+
logprobs: _logprobs,
|
|
679
|
+
metadata: _metadata,
|
|
680
|
+
...state
|
|
681
|
+
} = item;
|
|
682
|
+
return state;
|
|
683
|
+
}
|
|
636
684
|
function getResponseReplay(metadata) {
|
|
637
685
|
const response = metadata?.openai?.response;
|
|
638
686
|
if (response === void 0) return void 0;
|
|
@@ -641,10 +689,17 @@ function getResponseReplay(metadata) {
|
|
|
641
689
|
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
642
690
|
);
|
|
643
691
|
}
|
|
644
|
-
return response
|
|
692
|
+
return responseReplayMetadata(metadata)?.openai?.response?.output;
|
|
645
693
|
}
|
|
646
694
|
|
|
647
695
|
// src/core/provider-error.ts
|
|
696
|
+
function invalidProviderResponse(message) {
|
|
697
|
+
return Object.assign(new Error(message), {
|
|
698
|
+
name: "InvalidProviderResponseError",
|
|
699
|
+
status: 502,
|
|
700
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
701
|
+
});
|
|
702
|
+
}
|
|
648
703
|
function providerErrorEvent(error, code) {
|
|
649
704
|
const details = error ?? {};
|
|
650
705
|
const event = {
|
|
@@ -821,7 +876,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
821
876
|
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
822
877
|
return messages.map((message) => {
|
|
823
878
|
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
824
|
-
let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput,
|
|
879
|
+
let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
|
|
825
880
|
if (preserveProviderMetadata && modelOutput)
|
|
826
881
|
rest.modelOutput = modelOutput;
|
|
827
882
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
@@ -924,17 +979,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
924
979
|
const seenCallIds = /* @__PURE__ */ new Set();
|
|
925
980
|
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
926
981
|
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
927
|
-
throw
|
|
982
|
+
throw invalidProviderResponse(
|
|
983
|
+
"Responses contains an incomplete function call"
|
|
984
|
+
);
|
|
928
985
|
}
|
|
929
986
|
if (seenCallIds.has(item.call_id))
|
|
930
|
-
throw
|
|
987
|
+
throw invalidProviderResponse(
|
|
988
|
+
"Responses contains duplicate function call IDs"
|
|
989
|
+
);
|
|
931
990
|
seenCallIds.add(item.call_id);
|
|
932
|
-
|
|
991
|
+
let args;
|
|
992
|
+
try {
|
|
993
|
+
args = JSON.parse(item.arguments);
|
|
994
|
+
} catch {
|
|
995
|
+
throw invalidProviderResponse(
|
|
996
|
+
"Responses function arguments must be valid JSON"
|
|
997
|
+
);
|
|
998
|
+
}
|
|
933
999
|
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
934
|
-
throw
|
|
1000
|
+
throw invalidProviderResponse(
|
|
935
1001
|
"Responses function arguments must be a JSON object"
|
|
936
1002
|
);
|
|
937
|
-
return {
|
|
1003
|
+
return {
|
|
1004
|
+
id: item.call_id,
|
|
1005
|
+
name: item.name,
|
|
1006
|
+
args
|
|
1007
|
+
};
|
|
938
1008
|
}) : [];
|
|
939
1009
|
return {
|
|
940
1010
|
content,
|
|
@@ -1177,7 +1247,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1177
1247
|
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1178
1248
|
for (const call of toolCalls.values()) {
|
|
1179
1249
|
if (!call.id || !call.name)
|
|
1180
|
-
throw
|
|
1250
|
+
throw invalidProviderResponse(
|
|
1251
|
+
"Responses stream contains an incomplete tool call"
|
|
1252
|
+
);
|
|
1181
1253
|
uniqueCalls.set(call.id, call);
|
|
1182
1254
|
}
|
|
1183
1255
|
toolCalls.clear();
|
|
@@ -715,6 +715,54 @@ function responseMetadata(response) {
|
|
|
715
715
|
}
|
|
716
716
|
};
|
|
717
717
|
}
|
|
718
|
+
function responseReplayMetadata(metadata) {
|
|
719
|
+
const response = metadata?.openai?.response;
|
|
720
|
+
if (!response) return metadata;
|
|
721
|
+
const output = response.output.map((item) => {
|
|
722
|
+
const fields = ["type", "id", "status"];
|
|
723
|
+
switch (item.type) {
|
|
724
|
+
case "reasoning":
|
|
725
|
+
fields.push("encrypted_content");
|
|
726
|
+
break;
|
|
727
|
+
case "message":
|
|
728
|
+
fields.push("role", "phase");
|
|
729
|
+
break;
|
|
730
|
+
case "function_call":
|
|
731
|
+
fields.push("call_id", "name", "namespace", "arguments");
|
|
732
|
+
break;
|
|
733
|
+
case "tool_search_call":
|
|
734
|
+
fields.push("call_id", "execution", "arguments");
|
|
735
|
+
break;
|
|
736
|
+
case "tool_search_output":
|
|
737
|
+
fields.push("call_id", "tools");
|
|
738
|
+
break;
|
|
739
|
+
case "web_search_call":
|
|
740
|
+
fields.push("action");
|
|
741
|
+
break;
|
|
742
|
+
default:
|
|
743
|
+
return stripItemDiagnostics(item);
|
|
744
|
+
}
|
|
745
|
+
const replay = Object.fromEntries(
|
|
746
|
+
fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
|
|
747
|
+
);
|
|
748
|
+
if (item.type === "reasoning") replay.summary = [];
|
|
749
|
+
if (item.type === "message")
|
|
750
|
+
replay.content = Array.isArray(item.content) ? item.content.flatMap(
|
|
751
|
+
(part) => part?.type === "output_text" && typeof part.text === "string" ? [{ type: "output_text", text: part.text, annotations: [] }] : part?.type === "refusal" && typeof part.refusal === "string" ? [{ type: "refusal", refusal: part.refusal }] : []
|
|
752
|
+
) : [];
|
|
753
|
+
return stripItemDiagnostics(replay);
|
|
754
|
+
});
|
|
755
|
+
return { openai: { response: { output, refusals: [] } } };
|
|
756
|
+
}
|
|
757
|
+
function stripItemDiagnostics(item) {
|
|
758
|
+
const {
|
|
759
|
+
usage: _usage,
|
|
760
|
+
logprobs: _logprobs,
|
|
761
|
+
metadata: _metadata,
|
|
762
|
+
...state
|
|
763
|
+
} = item;
|
|
764
|
+
return state;
|
|
765
|
+
}
|
|
718
766
|
function getResponseReplay(metadata) {
|
|
719
767
|
const response = metadata?.openai?.response;
|
|
720
768
|
if (response === void 0) return void 0;
|
|
@@ -723,10 +771,17 @@ function getResponseReplay(metadata) {
|
|
|
723
771
|
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
724
772
|
);
|
|
725
773
|
}
|
|
726
|
-
return response
|
|
774
|
+
return responseReplayMetadata(metadata)?.openai?.response?.output;
|
|
727
775
|
}
|
|
728
776
|
|
|
729
777
|
// src/core/provider-error.ts
|
|
778
|
+
function invalidProviderResponse(message) {
|
|
779
|
+
return Object.assign(new Error(message), {
|
|
780
|
+
name: "InvalidProviderResponseError",
|
|
781
|
+
status: 502,
|
|
782
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
783
|
+
});
|
|
784
|
+
}
|
|
730
785
|
function providerErrorEvent(error, code) {
|
|
731
786
|
const details = error ?? {};
|
|
732
787
|
const event = {
|
|
@@ -903,7 +958,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
903
958
|
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
904
959
|
return messages.map((message) => {
|
|
905
960
|
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
906
|
-
let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput,
|
|
961
|
+
let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
|
|
907
962
|
if (preserveProviderMetadata && modelOutput)
|
|
908
963
|
rest.modelOutput = modelOutput;
|
|
909
964
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
@@ -1006,17 +1061,32 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1006
1061
|
const seenCallIds = /* @__PURE__ */ new Set();
|
|
1007
1062
|
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
1008
1063
|
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
1009
|
-
throw
|
|
1064
|
+
throw invalidProviderResponse(
|
|
1065
|
+
"Responses contains an incomplete function call"
|
|
1066
|
+
);
|
|
1010
1067
|
}
|
|
1011
1068
|
if (seenCallIds.has(item.call_id))
|
|
1012
|
-
throw
|
|
1069
|
+
throw invalidProviderResponse(
|
|
1070
|
+
"Responses contains duplicate function call IDs"
|
|
1071
|
+
);
|
|
1013
1072
|
seenCallIds.add(item.call_id);
|
|
1014
|
-
|
|
1073
|
+
let args;
|
|
1074
|
+
try {
|
|
1075
|
+
args = JSON.parse(item.arguments);
|
|
1076
|
+
} catch {
|
|
1077
|
+
throw invalidProviderResponse(
|
|
1078
|
+
"Responses function arguments must be valid JSON"
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1015
1081
|
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
1016
|
-
throw
|
|
1082
|
+
throw invalidProviderResponse(
|
|
1017
1083
|
"Responses function arguments must be a JSON object"
|
|
1018
1084
|
);
|
|
1019
|
-
return {
|
|
1085
|
+
return {
|
|
1086
|
+
id: item.call_id,
|
|
1087
|
+
name: item.name,
|
|
1088
|
+
args
|
|
1089
|
+
};
|
|
1020
1090
|
}) : [];
|
|
1021
1091
|
return {
|
|
1022
1092
|
content,
|
|
@@ -1259,7 +1329,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1259
1329
|
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1260
1330
|
for (const call of toolCalls.values()) {
|
|
1261
1331
|
if (!call.id || !call.name)
|
|
1262
|
-
throw
|
|
1332
|
+
throw invalidProviderResponse(
|
|
1333
|
+
"Responses stream contains an incomplete tool call"
|
|
1334
|
+
);
|
|
1263
1335
|
uniqueCalls.set(call.id, call);
|
|
1264
1336
|
}
|
|
1265
1337
|
toolCalls.clear();
|