@yourgpt/llm-sdk 2.6.0-beta.1 → 2.6.0-beta.2
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 +112 -0
- package/dist/adapters/index.d.mts +5 -5
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/index.js +372 -39
- package/dist/adapters/index.mjs +372 -39
- package/dist/audio-BBSwnjo8.d.mts +92 -0
- package/dist/audio-BBSwnjo8.d.ts +92 -0
- package/dist/{base-CkeT7u-O.d.mts → base-BICaQaRS.d.mts} +7 -3
- package/dist/{base-BdTpUAWI.d.ts → base-CpRPB8u8.d.ts} +7 -3
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/index.d.mts +17 -35
- package/dist/index.d.ts +17 -35
- package/dist/index.js +229 -60
- package/dist/index.mjs +227 -61
- package/dist/providers/anthropic/index.d.mts +3 -3
- package/dist/providers/anthropic/index.d.ts +3 -3
- package/dist/providers/anthropic/index.js +123 -7
- package/dist/providers/anthropic/index.mjs +123 -7
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/azure/index.js +101 -4
- package/dist/providers/azure/index.mjs +101 -4
- package/dist/providers/fireworks/index.d.mts +3 -3
- package/dist/providers/fireworks/index.d.ts +3 -3
- package/dist/providers/fireworks/index.js +321 -31
- package/dist/providers/fireworks/index.mjs +321 -31
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +321 -31
- package/dist/providers/google/index.mjs +321 -31
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/ollama/index.js +87 -2
- package/dist/providers/ollama/index.mjs +87 -2
- package/dist/providers/openai/index.d.mts +25 -6
- package/dist/providers/openai/index.d.ts +25 -6
- package/dist/providers/openai/index.js +750 -40
- package/dist/providers/openai/index.mjs +749 -41
- package/dist/providers/openrouter/index.d.mts +3 -3
- package/dist/providers/openrouter/index.d.ts +3 -3
- package/dist/providers/openrouter/index.js +321 -31
- package/dist/providers/openrouter/index.mjs +321 -31
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +321 -31
- package/dist/providers/togetherai/index.mjs +321 -31
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +321 -31
- package/dist/providers/xai/index.mjs +321 -31
- package/dist/{types-BWRYIvl_.d.mts → types-C3RgRbEC.d.mts} +1 -1
- package/dist/{types-CpXcT-tY.d.ts → types-DCFqkJAy.d.ts} +1 -1
- package/dist/{types-NOswlhm9.d.mts → types-DHQEMFHA.d.mts} +3 -3
- package/dist/{types-BW3csYo5.d.mts → types-Dg1Bcg1k.d.mts} +106 -3
- package/dist/{types-BW3csYo5.d.ts → types-Dg1Bcg1k.d.ts} +106 -3
- package/dist/{types-DA54bSmX.d.ts → types-Dikj3En4.d.ts} +3 -3
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/docs/multimodal-and-audio.md +170 -0
- package/package.json +3 -2
|
@@ -1,5 +1,108 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/core/tool-output.ts
|
|
4
|
+
var imageTypes = /* @__PURE__ */ new Set([
|
|
5
|
+
"image/png",
|
|
6
|
+
"image/jpeg",
|
|
7
|
+
"image/webp",
|
|
8
|
+
"image/gif"
|
|
9
|
+
]);
|
|
10
|
+
function normalizeToolOutput(value) {
|
|
11
|
+
const output = value;
|
|
12
|
+
if (output?.type !== "content" || !Array.isArray(output.content) || !output.content.length) {
|
|
13
|
+
throw new Error("Tool model output must contain a nonempty content array");
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
type: "content",
|
|
17
|
+
content: output.content.map((part) => {
|
|
18
|
+
if (part?.type === "text" && typeof part.text === "string")
|
|
19
|
+
return { type: "text", text: part.text };
|
|
20
|
+
if (part?.type !== "image")
|
|
21
|
+
throw new Error("Unsupported tool output content type");
|
|
22
|
+
const sources = ["data", "url", "fileId"].filter((key) => key in part);
|
|
23
|
+
if (sources.length !== 1)
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Tool image requires exactly one of data, url, or fileId"
|
|
26
|
+
);
|
|
27
|
+
if ("fileId" in part) {
|
|
28
|
+
if (part.provider !== "openai" || typeof part.fileId !== "string" || !part.fileId.trim())
|
|
29
|
+
throw new Error(
|
|
30
|
+
"Tool image file references must name the openai provider and fileId"
|
|
31
|
+
);
|
|
32
|
+
return { type: "image", fileId: part.fileId, provider: "openai" };
|
|
33
|
+
}
|
|
34
|
+
if ("url" in part) {
|
|
35
|
+
let url;
|
|
36
|
+
try {
|
|
37
|
+
url = new URL(part.url);
|
|
38
|
+
} catch {
|
|
39
|
+
throw new Error("Invalid tool image URL");
|
|
40
|
+
}
|
|
41
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password)
|
|
42
|
+
throw new Error(
|
|
43
|
+
"Tool image URL must use HTTP(S) without credentials"
|
|
44
|
+
);
|
|
45
|
+
return { type: "image", url: url.href };
|
|
46
|
+
}
|
|
47
|
+
if (!("data" in part) || !imageTypes.has(part.mediaType))
|
|
48
|
+
throw new Error("Unsupported tool image media type");
|
|
49
|
+
let data = part.data instanceof Uint8Array ? Buffer.from(part.data).toString("base64") : part.data;
|
|
50
|
+
if (typeof data !== "string")
|
|
51
|
+
throw new Error("Tool image data must be base64 or bytes");
|
|
52
|
+
if (data.startsWith("data:")) {
|
|
53
|
+
const match = /^data:([^;,]+);base64,(.+)$/.exec(data);
|
|
54
|
+
if (!match || match[1] !== part.mediaType)
|
|
55
|
+
throw new Error(
|
|
56
|
+
"Tool image data URL media type does not match mediaType"
|
|
57
|
+
);
|
|
58
|
+
data = match[2];
|
|
59
|
+
}
|
|
60
|
+
if (!data.length || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data))
|
|
61
|
+
throw new Error("Invalid tool image base64 data");
|
|
62
|
+
if (Buffer.byteLength(data, "base64") > 20 * 1024 * 1024)
|
|
63
|
+
throw new Error("Tool image exceeds 20 MiB");
|
|
64
|
+
if (Buffer.from(data, "base64").toString("base64") !== data)
|
|
65
|
+
throw new Error("Invalid tool image base64 data");
|
|
66
|
+
return { type: "image", data, mediaType: part.mediaType };
|
|
67
|
+
})
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function toolOutputForProvider(value, provider) {
|
|
71
|
+
const output = normalizeToolOutput(value);
|
|
72
|
+
return output.content.map((part) => {
|
|
73
|
+
if (part.type === "text")
|
|
74
|
+
return {
|
|
75
|
+
type: provider === "responses" ? "input_text" : "text",
|
|
76
|
+
text: part.text
|
|
77
|
+
};
|
|
78
|
+
if (provider === "unsupported")
|
|
79
|
+
throw new Error(
|
|
80
|
+
"Image tool results require OpenAI Responses or Anthropic; this endpoint is not supported"
|
|
81
|
+
);
|
|
82
|
+
if ("fileId" in part) {
|
|
83
|
+
if (provider !== "responses")
|
|
84
|
+
throw new Error(
|
|
85
|
+
"OpenAI image file references cannot be sent to another provider"
|
|
86
|
+
);
|
|
87
|
+
return { type: "input_image", file_id: part.fileId, detail: "auto" };
|
|
88
|
+
}
|
|
89
|
+
if (provider === "responses")
|
|
90
|
+
return {
|
|
91
|
+
type: "input_image",
|
|
92
|
+
image_url: "url" in part ? part.url : `data:${part.mediaType};base64,${part.data}`,
|
|
93
|
+
detail: "auto"
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
type: "image",
|
|
97
|
+
source: "url" in part ? { type: "url", url: part.url } : { type: "base64", media_type: part.mediaType, data: part.data }
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function textToolOutput(value, fallback) {
|
|
102
|
+
if (value === void 0) return fallback;
|
|
103
|
+
return toolOutputForProvider(value, "unsupported").map((part) => part.text).join("\n");
|
|
104
|
+
}
|
|
105
|
+
|
|
3
106
|
// src/core/openai-parameters.ts
|
|
4
107
|
function capabilities(model) {
|
|
5
108
|
const gpt = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/i.exec(model);
|
|
@@ -241,7 +344,7 @@ function messageToOpenAIContent(message) {
|
|
|
241
344
|
}
|
|
242
345
|
return blocks;
|
|
243
346
|
}
|
|
244
|
-
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
347
|
+
function formatMessagesForOpenAI(messages, systemPrompt, preserveProviderMetadata = false) {
|
|
245
348
|
const formatted = [];
|
|
246
349
|
if (systemPrompt) {
|
|
247
350
|
formatted.push({ role: "system", content: systemPrompt });
|
|
@@ -259,7 +362,8 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
259
362
|
const assistantMsg = {
|
|
260
363
|
role: "assistant",
|
|
261
364
|
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
262
|
-
content: hasToolCalls ? msg.content || null : msg.content
|
|
365
|
+
content: hasToolCalls ? msg.content || null : msg.content,
|
|
366
|
+
...preserveProviderMetadata && msg.providerMetadata ? { providerMetadata: msg.providerMetadata } : {}
|
|
263
367
|
};
|
|
264
368
|
if (hasToolCalls) {
|
|
265
369
|
assistantMsg.tool_calls = msg.tool_calls;
|
|
@@ -268,7 +372,8 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
268
372
|
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
269
373
|
formatted.push({
|
|
270
374
|
role: "tool",
|
|
271
|
-
content: msg.content ?? "",
|
|
375
|
+
content: preserveProviderMetadata ? msg.content ?? "" : textToolOutput(msg.modelOutput, msg.content ?? ""),
|
|
376
|
+
...preserveProviderMetadata && msg.modelOutput ? { modelOutput: msg.modelOutput } : {},
|
|
272
377
|
tool_call_id: msg.tool_call_id
|
|
273
378
|
});
|
|
274
379
|
}
|
|
@@ -504,7 +609,7 @@ function formatMessagesForXAI(messages) {
|
|
|
504
609
|
return {
|
|
505
610
|
role: "tool",
|
|
506
611
|
tool_call_id: msg.toolCallId,
|
|
507
|
-
content: msg.content
|
|
612
|
+
content: textToolOutput(msg.modelOutput, msg.content)
|
|
508
613
|
};
|
|
509
614
|
default:
|
|
510
615
|
return msg;
|
|
@@ -512,6 +617,64 @@ function formatMessagesForXAI(messages) {
|
|
|
512
617
|
});
|
|
513
618
|
}
|
|
514
619
|
|
|
620
|
+
// src/core/openai-responses.ts
|
|
621
|
+
function resolveOpenAITransport(defaults, overrides) {
|
|
622
|
+
return {
|
|
623
|
+
api: overrides?.api ?? defaults.api ?? "auto",
|
|
624
|
+
responses: defaults.responses !== void 0 || overrides?.responses !== void 0 ? { ...defaults.responses, ...overrides?.responses } : void 0
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
function useOpenAIResponses(model, baseURL, parameters, transport, hasTools, hasReplay, nativeToolSearch = false) {
|
|
628
|
+
const api = transport.api ?? "auto";
|
|
629
|
+
if (!["auto", "chat", "responses"].includes(api)) {
|
|
630
|
+
throw new Error(`Unknown OpenAI API selection: ${api}`);
|
|
631
|
+
}
|
|
632
|
+
if (api === "chat") {
|
|
633
|
+
if (transport.responses !== void 0 || nativeToolSearch) {
|
|
634
|
+
throw new Error(
|
|
635
|
+
"Responses options and native tool search require the Responses API"
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
let officialEndpoint = !baseURL;
|
|
641
|
+
try {
|
|
642
|
+
officialEndpoint = !baseURL || new URL(baseURL).hostname === "api.openai.com";
|
|
643
|
+
} catch {
|
|
644
|
+
}
|
|
645
|
+
return api === "responses" || transport.responses !== void 0 || hasReplay && officialEndpoint || nativeToolSearch || hasTools && requiresOpenAIResponses(model, baseURL, parameters);
|
|
646
|
+
}
|
|
647
|
+
function responseMetadata(response) {
|
|
648
|
+
const output = Array.isArray(response?.output) ? response.output : [];
|
|
649
|
+
return {
|
|
650
|
+
openai: {
|
|
651
|
+
response: {
|
|
652
|
+
id: response?.id,
|
|
653
|
+
model: response?.model,
|
|
654
|
+
status: response?.status,
|
|
655
|
+
output,
|
|
656
|
+
usage: response?.usage,
|
|
657
|
+
store: response?.store,
|
|
658
|
+
refusals: output.flatMap(
|
|
659
|
+
(item) => item?.type === "message" && Array.isArray(item.content) ? item.content.filter(
|
|
660
|
+
(part) => part?.type === "refusal" && typeof part.refusal === "string"
|
|
661
|
+
).map((part) => part.refusal) : []
|
|
662
|
+
)
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
function getResponseReplay(metadata) {
|
|
668
|
+
const response = metadata?.openai?.response;
|
|
669
|
+
if (response === void 0) return void 0;
|
|
670
|
+
if (!Array.isArray(response.output) || response.output.some((item) => !item || typeof item.type !== "string")) {
|
|
671
|
+
throw new Error(
|
|
672
|
+
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
return response.output;
|
|
676
|
+
}
|
|
677
|
+
|
|
515
678
|
// src/core/provider-error.ts
|
|
516
679
|
function providerErrorEvent(error, code) {
|
|
517
680
|
const details = error ?? {};
|
|
@@ -588,13 +751,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
588
751
|
}));
|
|
589
752
|
}
|
|
590
753
|
shouldUseResponsesApi(request) {
|
|
591
|
-
|
|
592
|
-
if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false)
|
|
593
|
-
return true;
|
|
594
|
-
return requiresOpenAIResponses(
|
|
754
|
+
return useOpenAIResponses(
|
|
595
755
|
request.config?.model || this.model,
|
|
596
756
|
this.config.baseUrl,
|
|
597
|
-
this.parameterOptions(request)
|
|
757
|
+
this.parameterOptions(request),
|
|
758
|
+
resolveOpenAITransport(this.config, request.config?.openai),
|
|
759
|
+
this.toolDefinitions(request).length > 0,
|
|
760
|
+
!!(request.rawMessages ?? request.messages)?.some(
|
|
761
|
+
(message) => message.providerMetadata?.openai?.response
|
|
762
|
+
),
|
|
763
|
+
request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false
|
|
598
764
|
);
|
|
599
765
|
}
|
|
600
766
|
/**
|
|
@@ -627,11 +793,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
627
793
|
});
|
|
628
794
|
}
|
|
629
795
|
buildResponsesInput(request) {
|
|
630
|
-
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages) : formatMessagesForOpenAI(request.messages, void 0);
|
|
796
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages, true) : formatMessagesForOpenAI(request.messages, void 0, true);
|
|
631
797
|
const input = [];
|
|
632
798
|
for (const message of sourceMessages) {
|
|
633
799
|
if (message.role === "system") {
|
|
634
|
-
if (
|
|
800
|
+
if (message.content && message.content !== request.systemPrompt) {
|
|
635
801
|
input.push({
|
|
636
802
|
type: "message",
|
|
637
803
|
role: "developer",
|
|
@@ -641,6 +807,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
641
807
|
continue;
|
|
642
808
|
}
|
|
643
809
|
if (message.role === "assistant") {
|
|
810
|
+
const replay = getResponseReplay(message.providerMetadata);
|
|
811
|
+
if (replay) {
|
|
812
|
+
input.push(...replay);
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
644
815
|
const content = this.toResponsesContent(message.content, "assistant");
|
|
645
816
|
if (typeof content === "string" ? content : Array.isArray(content) && content.length > 0) {
|
|
646
817
|
input.push({
|
|
@@ -664,7 +835,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
664
835
|
input.push({
|
|
665
836
|
type: "function_call_output",
|
|
666
837
|
call_id: message.tool_call_id,
|
|
667
|
-
output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
838
|
+
output: message.modelOutput ? toolOutputForProvider(message.modelOutput, "responses") : typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
668
839
|
});
|
|
669
840
|
continue;
|
|
670
841
|
}
|
|
@@ -678,10 +849,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
678
849
|
return input;
|
|
679
850
|
}
|
|
680
851
|
/** Preserve Copilot screenshot attachments on every OpenAI transport. */
|
|
681
|
-
formatRawMessages(messages) {
|
|
852
|
+
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
682
853
|
return messages.map((message) => {
|
|
683
|
-
const { attachments, ...rest } = message;
|
|
684
|
-
let content = message.content;
|
|
854
|
+
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
855
|
+
let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
|
|
856
|
+
if (preserveProviderMetadata && modelOutput)
|
|
857
|
+
rest.modelOutput = modelOutput;
|
|
685
858
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
686
859
|
content = null;
|
|
687
860
|
}
|
|
@@ -694,7 +867,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
694
867
|
content = [...parts, ...images];
|
|
695
868
|
}
|
|
696
869
|
}
|
|
697
|
-
return {
|
|
870
|
+
return {
|
|
871
|
+
...rest,
|
|
872
|
+
content,
|
|
873
|
+
...preserveProviderMetadata && providerMetadata ? { providerMetadata } : {}
|
|
874
|
+
};
|
|
698
875
|
});
|
|
699
876
|
}
|
|
700
877
|
/**
|
|
@@ -775,14 +952,25 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
775
952
|
).map((part) => part.text) : []
|
|
776
953
|
).join("") : "";
|
|
777
954
|
const content = textFromOutput || (typeof response?.output_text === "string" ? response.output_text : "");
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
name
|
|
781
|
-
|
|
782
|
-
|
|
955
|
+
const seenCallIds = /* @__PURE__ */ new Set();
|
|
956
|
+
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
957
|
+
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
958
|
+
throw new Error("Responses contains an incomplete function call");
|
|
959
|
+
}
|
|
960
|
+
if (seenCallIds.has(item.call_id))
|
|
961
|
+
throw new Error("Responses contains duplicate function call IDs");
|
|
962
|
+
seenCallIds.add(item.call_id);
|
|
963
|
+
const args = JSON.parse(item.arguments);
|
|
964
|
+
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
965
|
+
throw new Error(
|
|
966
|
+
"Responses function arguments must be a JSON object"
|
|
967
|
+
);
|
|
968
|
+
return { id: item.call_id, name: item.name, args };
|
|
969
|
+
}) : [];
|
|
783
970
|
return {
|
|
784
971
|
content,
|
|
785
972
|
toolCalls,
|
|
973
|
+
providerMetadata: responseMetadata(response),
|
|
786
974
|
usage: response?.usage ? {
|
|
787
975
|
promptTokens: response.usage.input_tokens ?? 0,
|
|
788
976
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
@@ -793,6 +981,17 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
793
981
|
}
|
|
794
982
|
buildResponsesPayload(request, stream) {
|
|
795
983
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
984
|
+
const options = resolveOpenAITransport(
|
|
985
|
+
this.config,
|
|
986
|
+
request.config?.openai
|
|
987
|
+
).responses;
|
|
988
|
+
const parameters = buildOpenAIParameters(
|
|
989
|
+
request.config?.model || this.model,
|
|
990
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
991
|
+
request.config?.temperature ?? this.config.temperature,
|
|
992
|
+
this.parameterOptions(request),
|
|
993
|
+
"responses"
|
|
994
|
+
);
|
|
796
995
|
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
797
996
|
request.config?.responseFormat
|
|
798
997
|
);
|
|
@@ -808,13 +1007,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
808
1007
|
),
|
|
809
1008
|
tool_choice: openaiToolOptions?.toolChoice,
|
|
810
1009
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
811
|
-
...
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
1010
|
+
...parameters,
|
|
1011
|
+
...options?.reasoningSummary ? {
|
|
1012
|
+
reasoning: {
|
|
1013
|
+
...parameters.reasoning,
|
|
1014
|
+
summary: options.reasoningSummary
|
|
1015
|
+
}
|
|
1016
|
+
} : {},
|
|
1017
|
+
...options?.store !== void 0 ? { store: options.store } : {},
|
|
1018
|
+
...options?.previousResponseId !== void 0 ? { previous_response_id: options.previousResponseId } : {},
|
|
1019
|
+
...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
|
|
1020
|
+
...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
|
|
1021
|
+
...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
|
|
1022
|
+
...options?.store === false || options?.include ? {
|
|
1023
|
+
include: [
|
|
1024
|
+
.../* @__PURE__ */ new Set([
|
|
1025
|
+
...options?.include ?? [],
|
|
1026
|
+
...options?.store === false ? ["reasoning.encrypted_content"] : []
|
|
1027
|
+
])
|
|
1028
|
+
]
|
|
1029
|
+
} : {},
|
|
818
1030
|
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
819
1031
|
stream
|
|
820
1032
|
};
|
|
@@ -873,6 +1085,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
873
1085
|
let usage;
|
|
874
1086
|
const citations = [];
|
|
875
1087
|
let completed = false;
|
|
1088
|
+
let terminalResponse;
|
|
1089
|
+
let responseIdentity = {};
|
|
1090
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
1091
|
+
let streamedText = "";
|
|
876
1092
|
function* flushToolCalls() {
|
|
877
1093
|
for (const call of toolCalls.values()) {
|
|
878
1094
|
if (!call.name)
|
|
@@ -889,17 +1105,36 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
889
1105
|
for await (const event of stream) {
|
|
890
1106
|
throwIfAborted(request.signal);
|
|
891
1107
|
logProviderPayload("openai", "stream chunk", event, request.debug);
|
|
1108
|
+
if (completed)
|
|
1109
|
+
throw new Error("Responses stream emitted an event after completion");
|
|
892
1110
|
const index = event?.output_index ?? 0;
|
|
893
1111
|
switch (event?.type) {
|
|
1112
|
+
case "response.created":
|
|
1113
|
+
responseIdentity = {
|
|
1114
|
+
id: event.response?.id,
|
|
1115
|
+
model: event.response?.model
|
|
1116
|
+
};
|
|
1117
|
+
break;
|
|
1118
|
+
case "response.output_item.done":
|
|
1119
|
+
if (event.item) outputItems.set(index, event.item);
|
|
1120
|
+
if (event.item?.type === "function_call") {
|
|
1121
|
+
toolCalls.set(index, {
|
|
1122
|
+
id: event.item.call_id,
|
|
1123
|
+
name: event.item.name,
|
|
1124
|
+
arguments: event.item.arguments
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
break;
|
|
894
1128
|
case "response.output_text.delta":
|
|
895
1129
|
if (event.delta) {
|
|
1130
|
+
streamedText += event.delta;
|
|
896
1131
|
yield { type: "message:delta", content: event.delta };
|
|
897
1132
|
}
|
|
898
1133
|
break;
|
|
899
1134
|
case "response.output_item.added":
|
|
900
1135
|
if (event.item?.type === "function_call") {
|
|
901
1136
|
toolCalls.set(index, {
|
|
902
|
-
id: event.item.call_id ??
|
|
1137
|
+
id: event.item.call_id ?? "",
|
|
903
1138
|
name: event.item.name ?? "",
|
|
904
1139
|
arguments: event.item.arguments ?? ""
|
|
905
1140
|
});
|
|
@@ -918,7 +1153,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
918
1153
|
break;
|
|
919
1154
|
}
|
|
920
1155
|
case "response.completed": {
|
|
1156
|
+
if (event.response?.status && event.response.status !== "completed")
|
|
1157
|
+
throw new Error(`Responses stream ${event.response.status}`);
|
|
921
1158
|
completed = true;
|
|
1159
|
+
terminalResponse = { ...responseIdentity, ...event.response };
|
|
922
1160
|
const found = this.collectResponsesCitations(
|
|
923
1161
|
event.response?.output,
|
|
924
1162
|
citations.length
|
|
@@ -955,12 +1193,64 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
955
1193
|
throwIfAborted(request.signal);
|
|
956
1194
|
if (!completed)
|
|
957
1195
|
throw new Error("Responses stream ended without a completed response");
|
|
1196
|
+
const output = terminalResponse.output?.length ? terminalResponse.output : [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
1197
|
+
if (output.some((item) => item.type === "function_call"))
|
|
1198
|
+
toolCalls.clear();
|
|
1199
|
+
for (const [index, item] of output.entries()) {
|
|
1200
|
+
if (item.type === "function_call") {
|
|
1201
|
+
toolCalls.set(index, {
|
|
1202
|
+
id: item.call_id,
|
|
1203
|
+
name: item.name,
|
|
1204
|
+
arguments: item.arguments
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1209
|
+
for (const call of toolCalls.values()) {
|
|
1210
|
+
if (!call.id || !call.name)
|
|
1211
|
+
throw new Error("Responses stream contains an incomplete tool call");
|
|
1212
|
+
uniqueCalls.set(call.id, call);
|
|
1213
|
+
}
|
|
1214
|
+
toolCalls.clear();
|
|
1215
|
+
[...uniqueCalls.values()].forEach(
|
|
1216
|
+
(call, index) => toolCalls.set(index, call)
|
|
1217
|
+
);
|
|
1218
|
+
if (!output.length && toolCalls.size) {
|
|
1219
|
+
for (const call of toolCalls.values())
|
|
1220
|
+
output.push({
|
|
1221
|
+
type: "function_call",
|
|
1222
|
+
call_id: call.id,
|
|
1223
|
+
name: call.name,
|
|
1224
|
+
arguments: call.arguments
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
if (!output.length && streamedText)
|
|
1228
|
+
output.push({
|
|
1229
|
+
type: "message",
|
|
1230
|
+
role: "assistant",
|
|
1231
|
+
content: [{ type: "output_text", text: streamedText, annotations: [] }]
|
|
1232
|
+
});
|
|
1233
|
+
terminalResponse.output = output;
|
|
1234
|
+
const finalText = this.parseResponsesResult(terminalResponse).content;
|
|
1235
|
+
if (finalText.startsWith(streamedText) && finalText.length > streamedText.length) {
|
|
1236
|
+
yield {
|
|
1237
|
+
type: "message:delta",
|
|
1238
|
+
content: finalText.slice(streamedText.length)
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
958
1241
|
yield* flushToolCalls();
|
|
959
1242
|
if (citations.length > 0) {
|
|
960
1243
|
yield { type: "citation", citations: deduplicateCitations(citations) };
|
|
961
1244
|
}
|
|
962
|
-
yield {
|
|
963
|
-
|
|
1245
|
+
yield {
|
|
1246
|
+
type: "message:end",
|
|
1247
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1248
|
+
};
|
|
1249
|
+
yield {
|
|
1250
|
+
type: "done",
|
|
1251
|
+
usage,
|
|
1252
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1253
|
+
};
|
|
964
1254
|
}
|
|
965
1255
|
async *stream(request) {
|
|
966
1256
|
throwIfAborted(request.signal);
|