@yourgpt/llm-sdk 2.6.0-beta.1 → 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 +146 -0
- package/dist/adapters/index.d.mts +5 -5
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/index.js +437 -39
- package/dist/adapters/index.mjs +437 -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 +20 -36
- package/dist/index.d.ts +20 -36
- package/dist/index.js +327 -69
- package/dist/index.mjs +325 -70
- package/dist/providers/anthropic/index.d.mts +3 -3
- package/dist/providers/anthropic/index.d.ts +3 -3
- package/dist/providers/anthropic/index.js +116 -7
- package/dist/providers/anthropic/index.mjs +116 -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 +393 -31
- package/dist/providers/fireworks/index.mjs +393 -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 +393 -31
- package/dist/providers/google/index.mjs +393 -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 +822 -40
- package/dist/providers/openai/index.mjs +821 -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 +393 -31
- package/dist/providers/openrouter/index.mjs +393 -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 +393 -31
- package/dist/providers/togetherai/index.mjs +393 -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 +393 -31
- package/dist/providers/xai/index.mjs +393 -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,3 +1,106 @@
|
|
|
1
|
+
// src/core/tool-output.ts
|
|
2
|
+
var imageTypes = /* @__PURE__ */ new Set([
|
|
3
|
+
"image/png",
|
|
4
|
+
"image/jpeg",
|
|
5
|
+
"image/webp",
|
|
6
|
+
"image/gif"
|
|
7
|
+
]);
|
|
8
|
+
function normalizeToolOutput(value) {
|
|
9
|
+
const output = value;
|
|
10
|
+
if (output?.type !== "content" || !Array.isArray(output.content) || !output.content.length) {
|
|
11
|
+
throw new Error("Tool model output must contain a nonempty content array");
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
type: "content",
|
|
15
|
+
content: output.content.map((part) => {
|
|
16
|
+
if (part?.type === "text" && typeof part.text === "string")
|
|
17
|
+
return { type: "text", text: part.text };
|
|
18
|
+
if (part?.type !== "image")
|
|
19
|
+
throw new Error("Unsupported tool output content type");
|
|
20
|
+
const sources = ["data", "url", "fileId"].filter((key) => key in part);
|
|
21
|
+
if (sources.length !== 1)
|
|
22
|
+
throw new Error(
|
|
23
|
+
"Tool image requires exactly one of data, url, or fileId"
|
|
24
|
+
);
|
|
25
|
+
if ("fileId" in part) {
|
|
26
|
+
if (part.provider !== "openai" || typeof part.fileId !== "string" || !part.fileId.trim())
|
|
27
|
+
throw new Error(
|
|
28
|
+
"Tool image file references must name the openai provider and fileId"
|
|
29
|
+
);
|
|
30
|
+
return { type: "image", fileId: part.fileId, provider: "openai" };
|
|
31
|
+
}
|
|
32
|
+
if ("url" in part) {
|
|
33
|
+
let url;
|
|
34
|
+
try {
|
|
35
|
+
url = new URL(part.url);
|
|
36
|
+
} catch {
|
|
37
|
+
throw new Error("Invalid tool image URL");
|
|
38
|
+
}
|
|
39
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password)
|
|
40
|
+
throw new Error(
|
|
41
|
+
"Tool image URL must use HTTP(S) without credentials"
|
|
42
|
+
);
|
|
43
|
+
return { type: "image", url: url.href };
|
|
44
|
+
}
|
|
45
|
+
if (!("data" in part) || !imageTypes.has(part.mediaType))
|
|
46
|
+
throw new Error("Unsupported tool image media type");
|
|
47
|
+
let data = part.data instanceof Uint8Array ? Buffer.from(part.data).toString("base64") : part.data;
|
|
48
|
+
if (typeof data !== "string")
|
|
49
|
+
throw new Error("Tool image data must be base64 or bytes");
|
|
50
|
+
if (data.startsWith("data:")) {
|
|
51
|
+
const match = /^data:([^;,]+);base64,(.+)$/.exec(data);
|
|
52
|
+
if (!match || match[1] !== part.mediaType)
|
|
53
|
+
throw new Error(
|
|
54
|
+
"Tool image data URL media type does not match mediaType"
|
|
55
|
+
);
|
|
56
|
+
data = match[2];
|
|
57
|
+
}
|
|
58
|
+
if (!data.length || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data))
|
|
59
|
+
throw new Error("Invalid tool image base64 data");
|
|
60
|
+
if (Buffer.byteLength(data, "base64") > 20 * 1024 * 1024)
|
|
61
|
+
throw new Error("Tool image exceeds 20 MiB");
|
|
62
|
+
if (Buffer.from(data, "base64").toString("base64") !== data)
|
|
63
|
+
throw new Error("Invalid tool image base64 data");
|
|
64
|
+
return { type: "image", data, mediaType: part.mediaType };
|
|
65
|
+
})
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function toolOutputForProvider(value, provider) {
|
|
69
|
+
const output = normalizeToolOutput(value);
|
|
70
|
+
return output.content.map((part) => {
|
|
71
|
+
if (part.type === "text")
|
|
72
|
+
return {
|
|
73
|
+
type: provider === "responses" ? "input_text" : "text",
|
|
74
|
+
text: part.text
|
|
75
|
+
};
|
|
76
|
+
if (provider === "unsupported")
|
|
77
|
+
throw new Error(
|
|
78
|
+
"Image tool results require OpenAI Responses or Anthropic; this endpoint is not supported"
|
|
79
|
+
);
|
|
80
|
+
if ("fileId" in part) {
|
|
81
|
+
if (provider !== "responses")
|
|
82
|
+
throw new Error(
|
|
83
|
+
"OpenAI image file references cannot be sent to another provider"
|
|
84
|
+
);
|
|
85
|
+
return { type: "input_image", file_id: part.fileId, detail: "auto" };
|
|
86
|
+
}
|
|
87
|
+
if (provider === "responses")
|
|
88
|
+
return {
|
|
89
|
+
type: "input_image",
|
|
90
|
+
image_url: "url" in part ? part.url : `data:${part.mediaType};base64,${part.data}`,
|
|
91
|
+
detail: "auto"
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
type: "image",
|
|
95
|
+
source: "url" in part ? { type: "url", url: part.url } : { type: "base64", media_type: part.mediaType, data: part.data }
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function textToolOutput(value, fallback) {
|
|
100
|
+
if (value === void 0) return fallback;
|
|
101
|
+
return toolOutputForProvider(value, "unsupported").map((part) => part.text).join("\n");
|
|
102
|
+
}
|
|
103
|
+
|
|
1
104
|
// src/core/openai-parameters.ts
|
|
2
105
|
function capabilities(model) {
|
|
3
106
|
const gpt = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/i.exec(model);
|
|
@@ -239,7 +342,7 @@ function messageToOpenAIContent(message) {
|
|
|
239
342
|
}
|
|
240
343
|
return blocks;
|
|
241
344
|
}
|
|
242
|
-
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
345
|
+
function formatMessagesForOpenAI(messages, systemPrompt, preserveProviderMetadata = false) {
|
|
243
346
|
const formatted = [];
|
|
244
347
|
if (systemPrompt) {
|
|
245
348
|
formatted.push({ role: "system", content: systemPrompt });
|
|
@@ -257,7 +360,8 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
257
360
|
const assistantMsg = {
|
|
258
361
|
role: "assistant",
|
|
259
362
|
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
260
|
-
content: hasToolCalls ? msg.content || null : msg.content
|
|
363
|
+
content: hasToolCalls ? msg.content || null : msg.content,
|
|
364
|
+
...preserveProviderMetadata && msg.providerMetadata ? { providerMetadata: msg.providerMetadata } : {}
|
|
261
365
|
};
|
|
262
366
|
if (hasToolCalls) {
|
|
263
367
|
assistantMsg.tool_calls = msg.tool_calls;
|
|
@@ -266,7 +370,8 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
266
370
|
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
267
371
|
formatted.push({
|
|
268
372
|
role: "tool",
|
|
269
|
-
content: msg.content ?? "",
|
|
373
|
+
content: preserveProviderMetadata ? msg.content ?? "" : textToolOutput(msg.modelOutput, msg.content ?? ""),
|
|
374
|
+
...preserveProviderMetadata && msg.modelOutput ? { modelOutput: msg.modelOutput } : {},
|
|
270
375
|
tool_call_id: msg.tool_call_id
|
|
271
376
|
});
|
|
272
377
|
}
|
|
@@ -503,7 +608,7 @@ function formatMessagesForOpenRouter(messages) {
|
|
|
503
608
|
return {
|
|
504
609
|
role: "tool",
|
|
505
610
|
tool_call_id: msg.toolCallId,
|
|
506
|
-
content: msg.content
|
|
611
|
+
content: textToolOutput(msg.modelOutput, msg.content)
|
|
507
612
|
};
|
|
508
613
|
default:
|
|
509
614
|
return msg;
|
|
@@ -534,7 +639,120 @@ async function searchOpenRouterModels(query, apiKey) {
|
|
|
534
639
|
);
|
|
535
640
|
}
|
|
536
641
|
|
|
642
|
+
// src/core/openai-responses.ts
|
|
643
|
+
function resolveOpenAITransport(defaults, overrides) {
|
|
644
|
+
return {
|
|
645
|
+
api: overrides?.api ?? defaults.api ?? "auto",
|
|
646
|
+
responses: defaults.responses !== void 0 || overrides?.responses !== void 0 ? { ...defaults.responses, ...overrides?.responses } : void 0
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
function useOpenAIResponses(model, baseURL, parameters, transport, hasTools, hasReplay, nativeToolSearch = false) {
|
|
650
|
+
const api = transport.api ?? "auto";
|
|
651
|
+
if (!["auto", "chat", "responses"].includes(api)) {
|
|
652
|
+
throw new Error(`Unknown OpenAI API selection: ${api}`);
|
|
653
|
+
}
|
|
654
|
+
if (api === "chat") {
|
|
655
|
+
if (transport.responses !== void 0 || nativeToolSearch) {
|
|
656
|
+
throw new Error(
|
|
657
|
+
"Responses options and native tool search require the Responses API"
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
let officialEndpoint = !baseURL;
|
|
663
|
+
try {
|
|
664
|
+
officialEndpoint = !baseURL || new URL(baseURL).hostname === "api.openai.com";
|
|
665
|
+
} catch {
|
|
666
|
+
}
|
|
667
|
+
return api === "responses" || transport.responses !== void 0 || hasReplay && officialEndpoint || nativeToolSearch || hasTools && requiresOpenAIResponses(model, baseURL, parameters);
|
|
668
|
+
}
|
|
669
|
+
function responseMetadata(response) {
|
|
670
|
+
const output = Array.isArray(response?.output) ? response.output : [];
|
|
671
|
+
return {
|
|
672
|
+
openai: {
|
|
673
|
+
response: {
|
|
674
|
+
id: response?.id,
|
|
675
|
+
model: response?.model,
|
|
676
|
+
status: response?.status,
|
|
677
|
+
output,
|
|
678
|
+
usage: response?.usage,
|
|
679
|
+
store: response?.store,
|
|
680
|
+
refusals: output.flatMap(
|
|
681
|
+
(item) => item?.type === "message" && Array.isArray(item.content) ? item.content.filter(
|
|
682
|
+
(part) => part?.type === "refusal" && typeof part.refusal === "string"
|
|
683
|
+
).map((part) => part.refusal) : []
|
|
684
|
+
)
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
function responseReplayMetadata(metadata) {
|
|
690
|
+
const response = metadata?.openai?.response;
|
|
691
|
+
if (!response) return metadata;
|
|
692
|
+
const output = response.output.map((item) => {
|
|
693
|
+
const fields = ["type", "id", "status"];
|
|
694
|
+
switch (item.type) {
|
|
695
|
+
case "reasoning":
|
|
696
|
+
fields.push("encrypted_content");
|
|
697
|
+
break;
|
|
698
|
+
case "message":
|
|
699
|
+
fields.push("role", "phase");
|
|
700
|
+
break;
|
|
701
|
+
case "function_call":
|
|
702
|
+
fields.push("call_id", "name", "namespace", "arguments");
|
|
703
|
+
break;
|
|
704
|
+
case "tool_search_call":
|
|
705
|
+
fields.push("call_id", "execution", "arguments");
|
|
706
|
+
break;
|
|
707
|
+
case "tool_search_output":
|
|
708
|
+
fields.push("call_id", "tools");
|
|
709
|
+
break;
|
|
710
|
+
case "web_search_call":
|
|
711
|
+
fields.push("action");
|
|
712
|
+
break;
|
|
713
|
+
default:
|
|
714
|
+
return stripItemDiagnostics(item);
|
|
715
|
+
}
|
|
716
|
+
const replay = Object.fromEntries(
|
|
717
|
+
fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
|
|
718
|
+
);
|
|
719
|
+
if (item.type === "reasoning") replay.summary = [];
|
|
720
|
+
if (item.type === "message")
|
|
721
|
+
replay.content = Array.isArray(item.content) ? item.content.flatMap(
|
|
722
|
+
(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 }] : []
|
|
723
|
+
) : [];
|
|
724
|
+
return stripItemDiagnostics(replay);
|
|
725
|
+
});
|
|
726
|
+
return { openai: { response: { output, refusals: [] } } };
|
|
727
|
+
}
|
|
728
|
+
function stripItemDiagnostics(item) {
|
|
729
|
+
const {
|
|
730
|
+
usage: _usage,
|
|
731
|
+
logprobs: _logprobs,
|
|
732
|
+
metadata: _metadata,
|
|
733
|
+
...state
|
|
734
|
+
} = item;
|
|
735
|
+
return state;
|
|
736
|
+
}
|
|
737
|
+
function getResponseReplay(metadata) {
|
|
738
|
+
const response = metadata?.openai?.response;
|
|
739
|
+
if (response === void 0) return void 0;
|
|
740
|
+
if (!Array.isArray(response.output) || response.output.some((item) => !item || typeof item.type !== "string")) {
|
|
741
|
+
throw new Error(
|
|
742
|
+
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
return responseReplayMetadata(metadata)?.openai?.response?.output;
|
|
746
|
+
}
|
|
747
|
+
|
|
537
748
|
// src/core/provider-error.ts
|
|
749
|
+
function invalidProviderResponse(message) {
|
|
750
|
+
return Object.assign(new Error(message), {
|
|
751
|
+
name: "InvalidProviderResponseError",
|
|
752
|
+
status: 502,
|
|
753
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
754
|
+
});
|
|
755
|
+
}
|
|
538
756
|
function providerErrorEvent(error, code) {
|
|
539
757
|
const details = error ?? {};
|
|
540
758
|
const event = {
|
|
@@ -610,13 +828,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
610
828
|
}));
|
|
611
829
|
}
|
|
612
830
|
shouldUseResponsesApi(request) {
|
|
613
|
-
|
|
614
|
-
if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false)
|
|
615
|
-
return true;
|
|
616
|
-
return requiresOpenAIResponses(
|
|
831
|
+
return useOpenAIResponses(
|
|
617
832
|
request.config?.model || this.model,
|
|
618
833
|
this.config.baseUrl,
|
|
619
|
-
this.parameterOptions(request)
|
|
834
|
+
this.parameterOptions(request),
|
|
835
|
+
resolveOpenAITransport(this.config, request.config?.openai),
|
|
836
|
+
this.toolDefinitions(request).length > 0,
|
|
837
|
+
!!(request.rawMessages ?? request.messages)?.some(
|
|
838
|
+
(message) => message.providerMetadata?.openai?.response
|
|
839
|
+
),
|
|
840
|
+
request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false
|
|
620
841
|
);
|
|
621
842
|
}
|
|
622
843
|
/**
|
|
@@ -649,11 +870,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
649
870
|
});
|
|
650
871
|
}
|
|
651
872
|
buildResponsesInput(request) {
|
|
652
|
-
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages) : formatMessagesForOpenAI(request.messages, void 0);
|
|
873
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages, true) : formatMessagesForOpenAI(request.messages, void 0, true);
|
|
653
874
|
const input = [];
|
|
654
875
|
for (const message of sourceMessages) {
|
|
655
876
|
if (message.role === "system") {
|
|
656
|
-
if (
|
|
877
|
+
if (message.content && message.content !== request.systemPrompt) {
|
|
657
878
|
input.push({
|
|
658
879
|
type: "message",
|
|
659
880
|
role: "developer",
|
|
@@ -663,6 +884,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
663
884
|
continue;
|
|
664
885
|
}
|
|
665
886
|
if (message.role === "assistant") {
|
|
887
|
+
const replay = getResponseReplay(message.providerMetadata);
|
|
888
|
+
if (replay) {
|
|
889
|
+
input.push(...replay);
|
|
890
|
+
continue;
|
|
891
|
+
}
|
|
666
892
|
const content = this.toResponsesContent(message.content, "assistant");
|
|
667
893
|
if (typeof content === "string" ? content : Array.isArray(content) && content.length > 0) {
|
|
668
894
|
input.push({
|
|
@@ -686,7 +912,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
686
912
|
input.push({
|
|
687
913
|
type: "function_call_output",
|
|
688
914
|
call_id: message.tool_call_id,
|
|
689
|
-
output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
915
|
+
output: message.modelOutput ? toolOutputForProvider(message.modelOutput, "responses") : typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
690
916
|
});
|
|
691
917
|
continue;
|
|
692
918
|
}
|
|
@@ -700,10 +926,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
700
926
|
return input;
|
|
701
927
|
}
|
|
702
928
|
/** Preserve Copilot screenshot attachments on every OpenAI transport. */
|
|
703
|
-
formatRawMessages(messages) {
|
|
929
|
+
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
704
930
|
return messages.map((message) => {
|
|
705
|
-
const { attachments, ...rest } = message;
|
|
706
|
-
let content = message.content;
|
|
931
|
+
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
932
|
+
let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
|
|
933
|
+
if (preserveProviderMetadata && modelOutput)
|
|
934
|
+
rest.modelOutput = modelOutput;
|
|
707
935
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
708
936
|
content = null;
|
|
709
937
|
}
|
|
@@ -716,7 +944,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
716
944
|
content = [...parts, ...images];
|
|
717
945
|
}
|
|
718
946
|
}
|
|
719
|
-
return {
|
|
947
|
+
return {
|
|
948
|
+
...rest,
|
|
949
|
+
content,
|
|
950
|
+
...preserveProviderMetadata && providerMetadata ? { providerMetadata } : {}
|
|
951
|
+
};
|
|
720
952
|
});
|
|
721
953
|
}
|
|
722
954
|
/**
|
|
@@ -797,14 +1029,40 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
797
1029
|
).map((part) => part.text) : []
|
|
798
1030
|
).join("") : "";
|
|
799
1031
|
const content = textFromOutput || (typeof response?.output_text === "string" ? response.output_text : "");
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
name
|
|
803
|
-
|
|
804
|
-
|
|
1032
|
+
const seenCallIds = /* @__PURE__ */ new Set();
|
|
1033
|
+
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
1034
|
+
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
1035
|
+
throw invalidProviderResponse(
|
|
1036
|
+
"Responses contains an incomplete function call"
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
if (seenCallIds.has(item.call_id))
|
|
1040
|
+
throw invalidProviderResponse(
|
|
1041
|
+
"Responses contains duplicate function call IDs"
|
|
1042
|
+
);
|
|
1043
|
+
seenCallIds.add(item.call_id);
|
|
1044
|
+
let args;
|
|
1045
|
+
try {
|
|
1046
|
+
args = JSON.parse(item.arguments);
|
|
1047
|
+
} catch {
|
|
1048
|
+
throw invalidProviderResponse(
|
|
1049
|
+
"Responses function arguments must be valid JSON"
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
1053
|
+
throw invalidProviderResponse(
|
|
1054
|
+
"Responses function arguments must be a JSON object"
|
|
1055
|
+
);
|
|
1056
|
+
return {
|
|
1057
|
+
id: item.call_id,
|
|
1058
|
+
name: item.name,
|
|
1059
|
+
args
|
|
1060
|
+
};
|
|
1061
|
+
}) : [];
|
|
805
1062
|
return {
|
|
806
1063
|
content,
|
|
807
1064
|
toolCalls,
|
|
1065
|
+
providerMetadata: responseMetadata(response),
|
|
808
1066
|
usage: response?.usage ? {
|
|
809
1067
|
promptTokens: response.usage.input_tokens ?? 0,
|
|
810
1068
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
@@ -815,6 +1073,17 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
815
1073
|
}
|
|
816
1074
|
buildResponsesPayload(request, stream) {
|
|
817
1075
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
1076
|
+
const options = resolveOpenAITransport(
|
|
1077
|
+
this.config,
|
|
1078
|
+
request.config?.openai
|
|
1079
|
+
).responses;
|
|
1080
|
+
const parameters = buildOpenAIParameters(
|
|
1081
|
+
request.config?.model || this.model,
|
|
1082
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
1083
|
+
request.config?.temperature ?? this.config.temperature,
|
|
1084
|
+
this.parameterOptions(request),
|
|
1085
|
+
"responses"
|
|
1086
|
+
);
|
|
818
1087
|
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
819
1088
|
request.config?.responseFormat
|
|
820
1089
|
);
|
|
@@ -830,13 +1099,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
830
1099
|
),
|
|
831
1100
|
tool_choice: openaiToolOptions?.toolChoice,
|
|
832
1101
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
833
|
-
...
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1102
|
+
...parameters,
|
|
1103
|
+
...options?.reasoningSummary ? {
|
|
1104
|
+
reasoning: {
|
|
1105
|
+
...parameters.reasoning,
|
|
1106
|
+
summary: options.reasoningSummary
|
|
1107
|
+
}
|
|
1108
|
+
} : {},
|
|
1109
|
+
...options?.store !== void 0 ? { store: options.store } : {},
|
|
1110
|
+
...options?.previousResponseId !== void 0 ? { previous_response_id: options.previousResponseId } : {},
|
|
1111
|
+
...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
|
|
1112
|
+
...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
|
|
1113
|
+
...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
|
|
1114
|
+
...options?.store === false || options?.include ? {
|
|
1115
|
+
include: [
|
|
1116
|
+
.../* @__PURE__ */ new Set([
|
|
1117
|
+
...options?.include ?? [],
|
|
1118
|
+
...options?.store === false ? ["reasoning.encrypted_content"] : []
|
|
1119
|
+
])
|
|
1120
|
+
]
|
|
1121
|
+
} : {},
|
|
840
1122
|
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
841
1123
|
stream
|
|
842
1124
|
};
|
|
@@ -895,6 +1177,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
895
1177
|
let usage;
|
|
896
1178
|
const citations = [];
|
|
897
1179
|
let completed = false;
|
|
1180
|
+
let terminalResponse;
|
|
1181
|
+
let responseIdentity = {};
|
|
1182
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
1183
|
+
let streamedText = "";
|
|
898
1184
|
function* flushToolCalls() {
|
|
899
1185
|
for (const call of toolCalls.values()) {
|
|
900
1186
|
if (!call.name)
|
|
@@ -911,17 +1197,36 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
911
1197
|
for await (const event of stream) {
|
|
912
1198
|
throwIfAborted(request.signal);
|
|
913
1199
|
logProviderPayload("openai", "stream chunk", event, request.debug);
|
|
1200
|
+
if (completed)
|
|
1201
|
+
throw new Error("Responses stream emitted an event after completion");
|
|
914
1202
|
const index = event?.output_index ?? 0;
|
|
915
1203
|
switch (event?.type) {
|
|
1204
|
+
case "response.created":
|
|
1205
|
+
responseIdentity = {
|
|
1206
|
+
id: event.response?.id,
|
|
1207
|
+
model: event.response?.model
|
|
1208
|
+
};
|
|
1209
|
+
break;
|
|
1210
|
+
case "response.output_item.done":
|
|
1211
|
+
if (event.item) outputItems.set(index, event.item);
|
|
1212
|
+
if (event.item?.type === "function_call") {
|
|
1213
|
+
toolCalls.set(index, {
|
|
1214
|
+
id: event.item.call_id,
|
|
1215
|
+
name: event.item.name,
|
|
1216
|
+
arguments: event.item.arguments
|
|
1217
|
+
});
|
|
1218
|
+
}
|
|
1219
|
+
break;
|
|
916
1220
|
case "response.output_text.delta":
|
|
917
1221
|
if (event.delta) {
|
|
1222
|
+
streamedText += event.delta;
|
|
918
1223
|
yield { type: "message:delta", content: event.delta };
|
|
919
1224
|
}
|
|
920
1225
|
break;
|
|
921
1226
|
case "response.output_item.added":
|
|
922
1227
|
if (event.item?.type === "function_call") {
|
|
923
1228
|
toolCalls.set(index, {
|
|
924
|
-
id: event.item.call_id ??
|
|
1229
|
+
id: event.item.call_id ?? "",
|
|
925
1230
|
name: event.item.name ?? "",
|
|
926
1231
|
arguments: event.item.arguments ?? ""
|
|
927
1232
|
});
|
|
@@ -940,7 +1245,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
940
1245
|
break;
|
|
941
1246
|
}
|
|
942
1247
|
case "response.completed": {
|
|
1248
|
+
if (event.response?.status && event.response.status !== "completed")
|
|
1249
|
+
throw new Error(`Responses stream ${event.response.status}`);
|
|
943
1250
|
completed = true;
|
|
1251
|
+
terminalResponse = { ...responseIdentity, ...event.response };
|
|
944
1252
|
const found = this.collectResponsesCitations(
|
|
945
1253
|
event.response?.output,
|
|
946
1254
|
citations.length
|
|
@@ -977,12 +1285,66 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
977
1285
|
throwIfAborted(request.signal);
|
|
978
1286
|
if (!completed)
|
|
979
1287
|
throw new Error("Responses stream ended without a completed response");
|
|
1288
|
+
const output = terminalResponse.output?.length ? terminalResponse.output : [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
1289
|
+
if (output.some((item) => item.type === "function_call"))
|
|
1290
|
+
toolCalls.clear();
|
|
1291
|
+
for (const [index, item] of output.entries()) {
|
|
1292
|
+
if (item.type === "function_call") {
|
|
1293
|
+
toolCalls.set(index, {
|
|
1294
|
+
id: item.call_id,
|
|
1295
|
+
name: item.name,
|
|
1296
|
+
arguments: item.arguments
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1301
|
+
for (const call of toolCalls.values()) {
|
|
1302
|
+
if (!call.id || !call.name)
|
|
1303
|
+
throw invalidProviderResponse(
|
|
1304
|
+
"Responses stream contains an incomplete tool call"
|
|
1305
|
+
);
|
|
1306
|
+
uniqueCalls.set(call.id, call);
|
|
1307
|
+
}
|
|
1308
|
+
toolCalls.clear();
|
|
1309
|
+
[...uniqueCalls.values()].forEach(
|
|
1310
|
+
(call, index) => toolCalls.set(index, call)
|
|
1311
|
+
);
|
|
1312
|
+
if (!output.length && toolCalls.size) {
|
|
1313
|
+
for (const call of toolCalls.values())
|
|
1314
|
+
output.push({
|
|
1315
|
+
type: "function_call",
|
|
1316
|
+
call_id: call.id,
|
|
1317
|
+
name: call.name,
|
|
1318
|
+
arguments: call.arguments
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
if (!output.length && streamedText)
|
|
1322
|
+
output.push({
|
|
1323
|
+
type: "message",
|
|
1324
|
+
role: "assistant",
|
|
1325
|
+
content: [{ type: "output_text", text: streamedText, annotations: [] }]
|
|
1326
|
+
});
|
|
1327
|
+
terminalResponse.output = output;
|
|
1328
|
+
const finalText = this.parseResponsesResult(terminalResponse).content;
|
|
1329
|
+
if (finalText.startsWith(streamedText) && finalText.length > streamedText.length) {
|
|
1330
|
+
yield {
|
|
1331
|
+
type: "message:delta",
|
|
1332
|
+
content: finalText.slice(streamedText.length)
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
980
1335
|
yield* flushToolCalls();
|
|
981
1336
|
if (citations.length > 0) {
|
|
982
1337
|
yield { type: "citation", citations: deduplicateCitations(citations) };
|
|
983
1338
|
}
|
|
984
|
-
yield {
|
|
985
|
-
|
|
1339
|
+
yield {
|
|
1340
|
+
type: "message:end",
|
|
1341
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1342
|
+
};
|
|
1343
|
+
yield {
|
|
1344
|
+
type: "done",
|
|
1345
|
+
usage,
|
|
1346
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1347
|
+
};
|
|
986
1348
|
}
|
|
987
1349
|
async *stream(request) {
|
|
988
1350
|
throwIfAborted(request.signal);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { A as AIProvider } from '../../types-
|
|
1
|
+
import { L as LanguageModel } from '../../types-Dg1Bcg1k.mjs';
|
|
2
|
+
import { A as AIProvider } from '../../types-DHQEMFHA.mjs';
|
|
3
3
|
import 'zod';
|
|
4
|
-
import '../../base-
|
|
4
|
+
import '../../base-BICaQaRS.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Together AI Provider
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { A as AIProvider } from '../../types-
|
|
1
|
+
import { L as LanguageModel } from '../../types-Dg1Bcg1k.js';
|
|
2
|
+
import { A as AIProvider } from '../../types-Dikj3En4.js';
|
|
3
3
|
import 'zod';
|
|
4
|
-
import '../../base-
|
|
4
|
+
import '../../base-CpRPB8u8.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Together AI Provider
|