@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
|
}
|
|
@@ -553,7 +658,7 @@ function formatMessagesForGoogle(messages) {
|
|
|
553
658
|
return {
|
|
554
659
|
role: "tool",
|
|
555
660
|
tool_call_id: msg.toolCallId,
|
|
556
|
-
content: msg.content
|
|
661
|
+
content: textToolOutput(msg.modelOutput, msg.content)
|
|
557
662
|
};
|
|
558
663
|
default:
|
|
559
664
|
return msg;
|
|
@@ -561,7 +666,120 @@ function formatMessagesForGoogle(messages) {
|
|
|
561
666
|
});
|
|
562
667
|
}
|
|
563
668
|
|
|
669
|
+
// src/core/openai-responses.ts
|
|
670
|
+
function resolveOpenAITransport(defaults, overrides) {
|
|
671
|
+
return {
|
|
672
|
+
api: overrides?.api ?? defaults.api ?? "auto",
|
|
673
|
+
responses: defaults.responses !== void 0 || overrides?.responses !== void 0 ? { ...defaults.responses, ...overrides?.responses } : void 0
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
function useOpenAIResponses(model, baseURL, parameters, transport, hasTools, hasReplay, nativeToolSearch = false) {
|
|
677
|
+
const api = transport.api ?? "auto";
|
|
678
|
+
if (!["auto", "chat", "responses"].includes(api)) {
|
|
679
|
+
throw new Error(`Unknown OpenAI API selection: ${api}`);
|
|
680
|
+
}
|
|
681
|
+
if (api === "chat") {
|
|
682
|
+
if (transport.responses !== void 0 || nativeToolSearch) {
|
|
683
|
+
throw new Error(
|
|
684
|
+
"Responses options and native tool search require the Responses API"
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
return false;
|
|
688
|
+
}
|
|
689
|
+
let officialEndpoint = !baseURL;
|
|
690
|
+
try {
|
|
691
|
+
officialEndpoint = !baseURL || new URL(baseURL).hostname === "api.openai.com";
|
|
692
|
+
} catch {
|
|
693
|
+
}
|
|
694
|
+
return api === "responses" || transport.responses !== void 0 || hasReplay && officialEndpoint || nativeToolSearch || hasTools && requiresOpenAIResponses(model, baseURL, parameters);
|
|
695
|
+
}
|
|
696
|
+
function responseMetadata(response) {
|
|
697
|
+
const output = Array.isArray(response?.output) ? response.output : [];
|
|
698
|
+
return {
|
|
699
|
+
openai: {
|
|
700
|
+
response: {
|
|
701
|
+
id: response?.id,
|
|
702
|
+
model: response?.model,
|
|
703
|
+
status: response?.status,
|
|
704
|
+
output,
|
|
705
|
+
usage: response?.usage,
|
|
706
|
+
store: response?.store,
|
|
707
|
+
refusals: output.flatMap(
|
|
708
|
+
(item) => item?.type === "message" && Array.isArray(item.content) ? item.content.filter(
|
|
709
|
+
(part) => part?.type === "refusal" && typeof part.refusal === "string"
|
|
710
|
+
).map((part) => part.refusal) : []
|
|
711
|
+
)
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
function responseReplayMetadata(metadata) {
|
|
717
|
+
const response = metadata?.openai?.response;
|
|
718
|
+
if (!response) return metadata;
|
|
719
|
+
const output = response.output.map((item) => {
|
|
720
|
+
const fields = ["type", "id", "status"];
|
|
721
|
+
switch (item.type) {
|
|
722
|
+
case "reasoning":
|
|
723
|
+
fields.push("encrypted_content");
|
|
724
|
+
break;
|
|
725
|
+
case "message":
|
|
726
|
+
fields.push("role", "phase");
|
|
727
|
+
break;
|
|
728
|
+
case "function_call":
|
|
729
|
+
fields.push("call_id", "name", "namespace", "arguments");
|
|
730
|
+
break;
|
|
731
|
+
case "tool_search_call":
|
|
732
|
+
fields.push("call_id", "execution", "arguments");
|
|
733
|
+
break;
|
|
734
|
+
case "tool_search_output":
|
|
735
|
+
fields.push("call_id", "tools");
|
|
736
|
+
break;
|
|
737
|
+
case "web_search_call":
|
|
738
|
+
fields.push("action");
|
|
739
|
+
break;
|
|
740
|
+
default:
|
|
741
|
+
return stripItemDiagnostics(item);
|
|
742
|
+
}
|
|
743
|
+
const replay = Object.fromEntries(
|
|
744
|
+
fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
|
|
745
|
+
);
|
|
746
|
+
if (item.type === "reasoning") replay.summary = [];
|
|
747
|
+
if (item.type === "message")
|
|
748
|
+
replay.content = Array.isArray(item.content) ? item.content.flatMap(
|
|
749
|
+
(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 }] : []
|
|
750
|
+
) : [];
|
|
751
|
+
return stripItemDiagnostics(replay);
|
|
752
|
+
});
|
|
753
|
+
return { openai: { response: { output, refusals: [] } } };
|
|
754
|
+
}
|
|
755
|
+
function stripItemDiagnostics(item) {
|
|
756
|
+
const {
|
|
757
|
+
usage: _usage,
|
|
758
|
+
logprobs: _logprobs,
|
|
759
|
+
metadata: _metadata,
|
|
760
|
+
...state
|
|
761
|
+
} = item;
|
|
762
|
+
return state;
|
|
763
|
+
}
|
|
764
|
+
function getResponseReplay(metadata) {
|
|
765
|
+
const response = metadata?.openai?.response;
|
|
766
|
+
if (response === void 0) return void 0;
|
|
767
|
+
if (!Array.isArray(response.output) || response.output.some((item) => !item || typeof item.type !== "string")) {
|
|
768
|
+
throw new Error(
|
|
769
|
+
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
return responseReplayMetadata(metadata)?.openai?.response?.output;
|
|
773
|
+
}
|
|
774
|
+
|
|
564
775
|
// src/core/provider-error.ts
|
|
776
|
+
function invalidProviderResponse(message) {
|
|
777
|
+
return Object.assign(new Error(message), {
|
|
778
|
+
name: "InvalidProviderResponseError",
|
|
779
|
+
status: 502,
|
|
780
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
781
|
+
});
|
|
782
|
+
}
|
|
565
783
|
function providerErrorEvent(error, code) {
|
|
566
784
|
const details = error ?? {};
|
|
567
785
|
const event = {
|
|
@@ -637,13 +855,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
637
855
|
}));
|
|
638
856
|
}
|
|
639
857
|
shouldUseResponsesApi(request) {
|
|
640
|
-
|
|
641
|
-
if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false)
|
|
642
|
-
return true;
|
|
643
|
-
return requiresOpenAIResponses(
|
|
858
|
+
return useOpenAIResponses(
|
|
644
859
|
request.config?.model || this.model,
|
|
645
860
|
this.config.baseUrl,
|
|
646
|
-
this.parameterOptions(request)
|
|
861
|
+
this.parameterOptions(request),
|
|
862
|
+
resolveOpenAITransport(this.config, request.config?.openai),
|
|
863
|
+
this.toolDefinitions(request).length > 0,
|
|
864
|
+
!!(request.rawMessages ?? request.messages)?.some(
|
|
865
|
+
(message) => message.providerMetadata?.openai?.response
|
|
866
|
+
),
|
|
867
|
+
request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false
|
|
647
868
|
);
|
|
648
869
|
}
|
|
649
870
|
/**
|
|
@@ -676,11 +897,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
676
897
|
});
|
|
677
898
|
}
|
|
678
899
|
buildResponsesInput(request) {
|
|
679
|
-
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages) : formatMessagesForOpenAI(request.messages, void 0);
|
|
900
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages, true) : formatMessagesForOpenAI(request.messages, void 0, true);
|
|
680
901
|
const input = [];
|
|
681
902
|
for (const message of sourceMessages) {
|
|
682
903
|
if (message.role === "system") {
|
|
683
|
-
if (
|
|
904
|
+
if (message.content && message.content !== request.systemPrompt) {
|
|
684
905
|
input.push({
|
|
685
906
|
type: "message",
|
|
686
907
|
role: "developer",
|
|
@@ -690,6 +911,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
690
911
|
continue;
|
|
691
912
|
}
|
|
692
913
|
if (message.role === "assistant") {
|
|
914
|
+
const replay = getResponseReplay(message.providerMetadata);
|
|
915
|
+
if (replay) {
|
|
916
|
+
input.push(...replay);
|
|
917
|
+
continue;
|
|
918
|
+
}
|
|
693
919
|
const content = this.toResponsesContent(message.content, "assistant");
|
|
694
920
|
if (typeof content === "string" ? content : Array.isArray(content) && content.length > 0) {
|
|
695
921
|
input.push({
|
|
@@ -713,7 +939,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
713
939
|
input.push({
|
|
714
940
|
type: "function_call_output",
|
|
715
941
|
call_id: message.tool_call_id,
|
|
716
|
-
output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
942
|
+
output: message.modelOutput ? toolOutputForProvider(message.modelOutput, "responses") : typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
717
943
|
});
|
|
718
944
|
continue;
|
|
719
945
|
}
|
|
@@ -727,10 +953,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
727
953
|
return input;
|
|
728
954
|
}
|
|
729
955
|
/** Preserve Copilot screenshot attachments on every OpenAI transport. */
|
|
730
|
-
formatRawMessages(messages) {
|
|
956
|
+
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
731
957
|
return messages.map((message) => {
|
|
732
|
-
const { attachments, ...rest } = message;
|
|
733
|
-
let content = message.content;
|
|
958
|
+
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
959
|
+
let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
|
|
960
|
+
if (preserveProviderMetadata && modelOutput)
|
|
961
|
+
rest.modelOutput = modelOutput;
|
|
734
962
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
735
963
|
content = null;
|
|
736
964
|
}
|
|
@@ -743,7 +971,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
743
971
|
content = [...parts, ...images];
|
|
744
972
|
}
|
|
745
973
|
}
|
|
746
|
-
return {
|
|
974
|
+
return {
|
|
975
|
+
...rest,
|
|
976
|
+
content,
|
|
977
|
+
...preserveProviderMetadata && providerMetadata ? { providerMetadata } : {}
|
|
978
|
+
};
|
|
747
979
|
});
|
|
748
980
|
}
|
|
749
981
|
/**
|
|
@@ -824,14 +1056,40 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
824
1056
|
).map((part) => part.text) : []
|
|
825
1057
|
).join("") : "";
|
|
826
1058
|
const content = textFromOutput || (typeof response?.output_text === "string" ? response.output_text : "");
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
name
|
|
830
|
-
|
|
831
|
-
|
|
1059
|
+
const seenCallIds = /* @__PURE__ */ new Set();
|
|
1060
|
+
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
1061
|
+
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
1062
|
+
throw invalidProviderResponse(
|
|
1063
|
+
"Responses contains an incomplete function call"
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
if (seenCallIds.has(item.call_id))
|
|
1067
|
+
throw invalidProviderResponse(
|
|
1068
|
+
"Responses contains duplicate function call IDs"
|
|
1069
|
+
);
|
|
1070
|
+
seenCallIds.add(item.call_id);
|
|
1071
|
+
let args;
|
|
1072
|
+
try {
|
|
1073
|
+
args = JSON.parse(item.arguments);
|
|
1074
|
+
} catch {
|
|
1075
|
+
throw invalidProviderResponse(
|
|
1076
|
+
"Responses function arguments must be valid JSON"
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
1080
|
+
throw invalidProviderResponse(
|
|
1081
|
+
"Responses function arguments must be a JSON object"
|
|
1082
|
+
);
|
|
1083
|
+
return {
|
|
1084
|
+
id: item.call_id,
|
|
1085
|
+
name: item.name,
|
|
1086
|
+
args
|
|
1087
|
+
};
|
|
1088
|
+
}) : [];
|
|
832
1089
|
return {
|
|
833
1090
|
content,
|
|
834
1091
|
toolCalls,
|
|
1092
|
+
providerMetadata: responseMetadata(response),
|
|
835
1093
|
usage: response?.usage ? {
|
|
836
1094
|
promptTokens: response.usage.input_tokens ?? 0,
|
|
837
1095
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
@@ -842,6 +1100,17 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
842
1100
|
}
|
|
843
1101
|
buildResponsesPayload(request, stream) {
|
|
844
1102
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
1103
|
+
const options = resolveOpenAITransport(
|
|
1104
|
+
this.config,
|
|
1105
|
+
request.config?.openai
|
|
1106
|
+
).responses;
|
|
1107
|
+
const parameters = buildOpenAIParameters(
|
|
1108
|
+
request.config?.model || this.model,
|
|
1109
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
1110
|
+
request.config?.temperature ?? this.config.temperature,
|
|
1111
|
+
this.parameterOptions(request),
|
|
1112
|
+
"responses"
|
|
1113
|
+
);
|
|
845
1114
|
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
846
1115
|
request.config?.responseFormat
|
|
847
1116
|
);
|
|
@@ -857,13 +1126,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
857
1126
|
),
|
|
858
1127
|
tool_choice: openaiToolOptions?.toolChoice,
|
|
859
1128
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
860
|
-
...
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1129
|
+
...parameters,
|
|
1130
|
+
...options?.reasoningSummary ? {
|
|
1131
|
+
reasoning: {
|
|
1132
|
+
...parameters.reasoning,
|
|
1133
|
+
summary: options.reasoningSummary
|
|
1134
|
+
}
|
|
1135
|
+
} : {},
|
|
1136
|
+
...options?.store !== void 0 ? { store: options.store } : {},
|
|
1137
|
+
...options?.previousResponseId !== void 0 ? { previous_response_id: options.previousResponseId } : {},
|
|
1138
|
+
...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
|
|
1139
|
+
...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
|
|
1140
|
+
...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
|
|
1141
|
+
...options?.store === false || options?.include ? {
|
|
1142
|
+
include: [
|
|
1143
|
+
.../* @__PURE__ */ new Set([
|
|
1144
|
+
...options?.include ?? [],
|
|
1145
|
+
...options?.store === false ? ["reasoning.encrypted_content"] : []
|
|
1146
|
+
])
|
|
1147
|
+
]
|
|
1148
|
+
} : {},
|
|
867
1149
|
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
868
1150
|
stream
|
|
869
1151
|
};
|
|
@@ -922,6 +1204,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
922
1204
|
let usage;
|
|
923
1205
|
const citations = [];
|
|
924
1206
|
let completed = false;
|
|
1207
|
+
let terminalResponse;
|
|
1208
|
+
let responseIdentity = {};
|
|
1209
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
1210
|
+
let streamedText = "";
|
|
925
1211
|
function* flushToolCalls() {
|
|
926
1212
|
for (const call of toolCalls.values()) {
|
|
927
1213
|
if (!call.name)
|
|
@@ -938,17 +1224,36 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
938
1224
|
for await (const event of stream) {
|
|
939
1225
|
throwIfAborted(request.signal);
|
|
940
1226
|
logProviderPayload("openai", "stream chunk", event, request.debug);
|
|
1227
|
+
if (completed)
|
|
1228
|
+
throw new Error("Responses stream emitted an event after completion");
|
|
941
1229
|
const index = event?.output_index ?? 0;
|
|
942
1230
|
switch (event?.type) {
|
|
1231
|
+
case "response.created":
|
|
1232
|
+
responseIdentity = {
|
|
1233
|
+
id: event.response?.id,
|
|
1234
|
+
model: event.response?.model
|
|
1235
|
+
};
|
|
1236
|
+
break;
|
|
1237
|
+
case "response.output_item.done":
|
|
1238
|
+
if (event.item) outputItems.set(index, event.item);
|
|
1239
|
+
if (event.item?.type === "function_call") {
|
|
1240
|
+
toolCalls.set(index, {
|
|
1241
|
+
id: event.item.call_id,
|
|
1242
|
+
name: event.item.name,
|
|
1243
|
+
arguments: event.item.arguments
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
break;
|
|
943
1247
|
case "response.output_text.delta":
|
|
944
1248
|
if (event.delta) {
|
|
1249
|
+
streamedText += event.delta;
|
|
945
1250
|
yield { type: "message:delta", content: event.delta };
|
|
946
1251
|
}
|
|
947
1252
|
break;
|
|
948
1253
|
case "response.output_item.added":
|
|
949
1254
|
if (event.item?.type === "function_call") {
|
|
950
1255
|
toolCalls.set(index, {
|
|
951
|
-
id: event.item.call_id ??
|
|
1256
|
+
id: event.item.call_id ?? "",
|
|
952
1257
|
name: event.item.name ?? "",
|
|
953
1258
|
arguments: event.item.arguments ?? ""
|
|
954
1259
|
});
|
|
@@ -967,7 +1272,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
967
1272
|
break;
|
|
968
1273
|
}
|
|
969
1274
|
case "response.completed": {
|
|
1275
|
+
if (event.response?.status && event.response.status !== "completed")
|
|
1276
|
+
throw new Error(`Responses stream ${event.response.status}`);
|
|
970
1277
|
completed = true;
|
|
1278
|
+
terminalResponse = { ...responseIdentity, ...event.response };
|
|
971
1279
|
const found = this.collectResponsesCitations(
|
|
972
1280
|
event.response?.output,
|
|
973
1281
|
citations.length
|
|
@@ -1004,12 +1312,66 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
1004
1312
|
throwIfAborted(request.signal);
|
|
1005
1313
|
if (!completed)
|
|
1006
1314
|
throw new Error("Responses stream ended without a completed response");
|
|
1315
|
+
const output = terminalResponse.output?.length ? terminalResponse.output : [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
1316
|
+
if (output.some((item) => item.type === "function_call"))
|
|
1317
|
+
toolCalls.clear();
|
|
1318
|
+
for (const [index, item] of output.entries()) {
|
|
1319
|
+
if (item.type === "function_call") {
|
|
1320
|
+
toolCalls.set(index, {
|
|
1321
|
+
id: item.call_id,
|
|
1322
|
+
name: item.name,
|
|
1323
|
+
arguments: item.arguments
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1328
|
+
for (const call of toolCalls.values()) {
|
|
1329
|
+
if (!call.id || !call.name)
|
|
1330
|
+
throw invalidProviderResponse(
|
|
1331
|
+
"Responses stream contains an incomplete tool call"
|
|
1332
|
+
);
|
|
1333
|
+
uniqueCalls.set(call.id, call);
|
|
1334
|
+
}
|
|
1335
|
+
toolCalls.clear();
|
|
1336
|
+
[...uniqueCalls.values()].forEach(
|
|
1337
|
+
(call, index) => toolCalls.set(index, call)
|
|
1338
|
+
);
|
|
1339
|
+
if (!output.length && toolCalls.size) {
|
|
1340
|
+
for (const call of toolCalls.values())
|
|
1341
|
+
output.push({
|
|
1342
|
+
type: "function_call",
|
|
1343
|
+
call_id: call.id,
|
|
1344
|
+
name: call.name,
|
|
1345
|
+
arguments: call.arguments
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
if (!output.length && streamedText)
|
|
1349
|
+
output.push({
|
|
1350
|
+
type: "message",
|
|
1351
|
+
role: "assistant",
|
|
1352
|
+
content: [{ type: "output_text", text: streamedText, annotations: [] }]
|
|
1353
|
+
});
|
|
1354
|
+
terminalResponse.output = output;
|
|
1355
|
+
const finalText = this.parseResponsesResult(terminalResponse).content;
|
|
1356
|
+
if (finalText.startsWith(streamedText) && finalText.length > streamedText.length) {
|
|
1357
|
+
yield {
|
|
1358
|
+
type: "message:delta",
|
|
1359
|
+
content: finalText.slice(streamedText.length)
|
|
1360
|
+
};
|
|
1361
|
+
}
|
|
1007
1362
|
yield* flushToolCalls();
|
|
1008
1363
|
if (citations.length > 0) {
|
|
1009
1364
|
yield { type: "citation", citations: deduplicateCitations(citations) };
|
|
1010
1365
|
}
|
|
1011
|
-
yield {
|
|
1012
|
-
|
|
1366
|
+
yield {
|
|
1367
|
+
type: "message:end",
|
|
1368
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1369
|
+
};
|
|
1370
|
+
yield {
|
|
1371
|
+
type: "done",
|
|
1372
|
+
usage,
|
|
1373
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1374
|
+
};
|
|
1013
1375
|
}
|
|
1014
1376
|
async *stream(request) {
|
|
1015
1377
|
throwIfAborted(request.signal);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as OllamaProviderConfig, A as AIProvider } from '../../types-
|
|
2
|
-
export { d as OllamaModelOptions } from '../../types-
|
|
3
|
-
import '../../types-
|
|
1
|
+
import { c as OllamaProviderConfig, A as AIProvider } from '../../types-DHQEMFHA.mjs';
|
|
2
|
+
export { d as OllamaModelOptions } from '../../types-DHQEMFHA.mjs';
|
|
3
|
+
import '../../types-Dg1Bcg1k.mjs';
|
|
4
4
|
import 'zod';
|
|
5
|
-
import '../../base-
|
|
5
|
+
import '../../base-BICaQaRS.mjs';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Ollama Provider
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as OllamaProviderConfig, A as AIProvider } from '../../types-
|
|
2
|
-
export { d as OllamaModelOptions } from '../../types-
|
|
3
|
-
import '../../types-
|
|
1
|
+
import { c as OllamaProviderConfig, A as AIProvider } from '../../types-Dikj3En4.js';
|
|
2
|
+
export { d as OllamaModelOptions } from '../../types-Dikj3En4.js';
|
|
3
|
+
import '../../types-Dg1Bcg1k.js';
|
|
4
4
|
import 'zod';
|
|
5
|
-
import '../../base-
|
|
5
|
+
import '../../base-CpRPB8u8.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Ollama Provider
|