@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
|
}
|
|
@@ -478,7 +583,7 @@ function formatMessages(messages) {
|
|
|
478
583
|
return {
|
|
479
584
|
role: "tool",
|
|
480
585
|
tool_call_id: msg.toolCallId,
|
|
481
|
-
content: msg.content
|
|
586
|
+
content: textToolOutput(msg.modelOutput, msg.content)
|
|
482
587
|
};
|
|
483
588
|
default:
|
|
484
589
|
return msg;
|
|
@@ -486,7 +591,120 @@ function formatMessages(messages) {
|
|
|
486
591
|
});
|
|
487
592
|
}
|
|
488
593
|
|
|
594
|
+
// src/core/openai-responses.ts
|
|
595
|
+
function resolveOpenAITransport(defaults, overrides) {
|
|
596
|
+
return {
|
|
597
|
+
api: overrides?.api ?? defaults.api ?? "auto",
|
|
598
|
+
responses: defaults.responses !== void 0 || overrides?.responses !== void 0 ? { ...defaults.responses, ...overrides?.responses } : void 0
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
function useOpenAIResponses(model, baseURL, parameters, transport, hasTools, hasReplay, nativeToolSearch = false) {
|
|
602
|
+
const api = transport.api ?? "auto";
|
|
603
|
+
if (!["auto", "chat", "responses"].includes(api)) {
|
|
604
|
+
throw new Error(`Unknown OpenAI API selection: ${api}`);
|
|
605
|
+
}
|
|
606
|
+
if (api === "chat") {
|
|
607
|
+
if (transport.responses !== void 0 || nativeToolSearch) {
|
|
608
|
+
throw new Error(
|
|
609
|
+
"Responses options and native tool search require the Responses API"
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
let officialEndpoint = !baseURL;
|
|
615
|
+
try {
|
|
616
|
+
officialEndpoint = !baseURL || new URL(baseURL).hostname === "api.openai.com";
|
|
617
|
+
} catch {
|
|
618
|
+
}
|
|
619
|
+
return api === "responses" || transport.responses !== void 0 || hasReplay && officialEndpoint || nativeToolSearch || hasTools && requiresOpenAIResponses(model, baseURL, parameters);
|
|
620
|
+
}
|
|
621
|
+
function responseMetadata(response) {
|
|
622
|
+
const output = Array.isArray(response?.output) ? response.output : [];
|
|
623
|
+
return {
|
|
624
|
+
openai: {
|
|
625
|
+
response: {
|
|
626
|
+
id: response?.id,
|
|
627
|
+
model: response?.model,
|
|
628
|
+
status: response?.status,
|
|
629
|
+
output,
|
|
630
|
+
usage: response?.usage,
|
|
631
|
+
store: response?.store,
|
|
632
|
+
refusals: output.flatMap(
|
|
633
|
+
(item) => item?.type === "message" && Array.isArray(item.content) ? item.content.filter(
|
|
634
|
+
(part) => part?.type === "refusal" && typeof part.refusal === "string"
|
|
635
|
+
).map((part) => part.refusal) : []
|
|
636
|
+
)
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
function responseReplayMetadata(metadata) {
|
|
642
|
+
const response = metadata?.openai?.response;
|
|
643
|
+
if (!response) return metadata;
|
|
644
|
+
const output = response.output.map((item) => {
|
|
645
|
+
const fields = ["type", "id", "status"];
|
|
646
|
+
switch (item.type) {
|
|
647
|
+
case "reasoning":
|
|
648
|
+
fields.push("encrypted_content");
|
|
649
|
+
break;
|
|
650
|
+
case "message":
|
|
651
|
+
fields.push("role", "phase");
|
|
652
|
+
break;
|
|
653
|
+
case "function_call":
|
|
654
|
+
fields.push("call_id", "name", "namespace", "arguments");
|
|
655
|
+
break;
|
|
656
|
+
case "tool_search_call":
|
|
657
|
+
fields.push("call_id", "execution", "arguments");
|
|
658
|
+
break;
|
|
659
|
+
case "tool_search_output":
|
|
660
|
+
fields.push("call_id", "tools");
|
|
661
|
+
break;
|
|
662
|
+
case "web_search_call":
|
|
663
|
+
fields.push("action");
|
|
664
|
+
break;
|
|
665
|
+
default:
|
|
666
|
+
return stripItemDiagnostics(item);
|
|
667
|
+
}
|
|
668
|
+
const replay = Object.fromEntries(
|
|
669
|
+
fields.filter((key) => item[key] !== void 0).map((key) => [key, item[key]])
|
|
670
|
+
);
|
|
671
|
+
if (item.type === "reasoning") replay.summary = [];
|
|
672
|
+
if (item.type === "message")
|
|
673
|
+
replay.content = Array.isArray(item.content) ? item.content.flatMap(
|
|
674
|
+
(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 }] : []
|
|
675
|
+
) : [];
|
|
676
|
+
return stripItemDiagnostics(replay);
|
|
677
|
+
});
|
|
678
|
+
return { openai: { response: { output, refusals: [] } } };
|
|
679
|
+
}
|
|
680
|
+
function stripItemDiagnostics(item) {
|
|
681
|
+
const {
|
|
682
|
+
usage: _usage,
|
|
683
|
+
logprobs: _logprobs,
|
|
684
|
+
metadata: _metadata,
|
|
685
|
+
...state
|
|
686
|
+
} = item;
|
|
687
|
+
return state;
|
|
688
|
+
}
|
|
689
|
+
function getResponseReplay(metadata) {
|
|
690
|
+
const response = metadata?.openai?.response;
|
|
691
|
+
if (response === void 0) return void 0;
|
|
692
|
+
if (!Array.isArray(response.output) || response.output.some((item) => !item || typeof item.type !== "string")) {
|
|
693
|
+
throw new Error(
|
|
694
|
+
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
return responseReplayMetadata(metadata)?.openai?.response?.output;
|
|
698
|
+
}
|
|
699
|
+
|
|
489
700
|
// src/core/provider-error.ts
|
|
701
|
+
function invalidProviderResponse(message) {
|
|
702
|
+
return Object.assign(new Error(message), {
|
|
703
|
+
name: "InvalidProviderResponseError",
|
|
704
|
+
status: 502,
|
|
705
|
+
code: "INVALID_PROVIDER_RESPONSE"
|
|
706
|
+
});
|
|
707
|
+
}
|
|
490
708
|
function providerErrorEvent(error, code) {
|
|
491
709
|
const details = error ?? {};
|
|
492
710
|
const event = {
|
|
@@ -562,13 +780,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
562
780
|
}));
|
|
563
781
|
}
|
|
564
782
|
shouldUseResponsesApi(request) {
|
|
565
|
-
|
|
566
|
-
if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false)
|
|
567
|
-
return true;
|
|
568
|
-
return requiresOpenAIResponses(
|
|
783
|
+
return useOpenAIResponses(
|
|
569
784
|
request.config?.model || this.model,
|
|
570
785
|
this.config.baseUrl,
|
|
571
|
-
this.parameterOptions(request)
|
|
786
|
+
this.parameterOptions(request),
|
|
787
|
+
resolveOpenAITransport(this.config, request.config?.openai),
|
|
788
|
+
this.toolDefinitions(request).length > 0,
|
|
789
|
+
!!(request.rawMessages ?? request.messages)?.some(
|
|
790
|
+
(message) => message.providerMetadata?.openai?.response
|
|
791
|
+
),
|
|
792
|
+
request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false
|
|
572
793
|
);
|
|
573
794
|
}
|
|
574
795
|
/**
|
|
@@ -601,11 +822,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
601
822
|
});
|
|
602
823
|
}
|
|
603
824
|
buildResponsesInput(request) {
|
|
604
|
-
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages) : formatMessagesForOpenAI(request.messages, void 0);
|
|
825
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages, true) : formatMessagesForOpenAI(request.messages, void 0, true);
|
|
605
826
|
const input = [];
|
|
606
827
|
for (const message of sourceMessages) {
|
|
607
828
|
if (message.role === "system") {
|
|
608
|
-
if (
|
|
829
|
+
if (message.content && message.content !== request.systemPrompt) {
|
|
609
830
|
input.push({
|
|
610
831
|
type: "message",
|
|
611
832
|
role: "developer",
|
|
@@ -615,6 +836,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
615
836
|
continue;
|
|
616
837
|
}
|
|
617
838
|
if (message.role === "assistant") {
|
|
839
|
+
const replay = getResponseReplay(message.providerMetadata);
|
|
840
|
+
if (replay) {
|
|
841
|
+
input.push(...replay);
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
618
844
|
const content = this.toResponsesContent(message.content, "assistant");
|
|
619
845
|
if (typeof content === "string" ? content : Array.isArray(content) && content.length > 0) {
|
|
620
846
|
input.push({
|
|
@@ -638,7 +864,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
638
864
|
input.push({
|
|
639
865
|
type: "function_call_output",
|
|
640
866
|
call_id: message.tool_call_id,
|
|
641
|
-
output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
867
|
+
output: message.modelOutput ? toolOutputForProvider(message.modelOutput, "responses") : typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
642
868
|
});
|
|
643
869
|
continue;
|
|
644
870
|
}
|
|
@@ -652,10 +878,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
652
878
|
return input;
|
|
653
879
|
}
|
|
654
880
|
/** Preserve Copilot screenshot attachments on every OpenAI transport. */
|
|
655
|
-
formatRawMessages(messages) {
|
|
881
|
+
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
656
882
|
return messages.map((message) => {
|
|
657
|
-
const { attachments, ...rest } = message;
|
|
658
|
-
let content = message.content;
|
|
883
|
+
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
884
|
+
let content = message.role === "tool" && !preserveProviderMetadata && modelOutput !== void 0 ? textToolOutput(modelOutput, "") : message.content;
|
|
885
|
+
if (preserveProviderMetadata && modelOutput)
|
|
886
|
+
rest.modelOutput = modelOutput;
|
|
659
887
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
660
888
|
content = null;
|
|
661
889
|
}
|
|
@@ -668,7 +896,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
668
896
|
content = [...parts, ...images];
|
|
669
897
|
}
|
|
670
898
|
}
|
|
671
|
-
return {
|
|
899
|
+
return {
|
|
900
|
+
...rest,
|
|
901
|
+
content,
|
|
902
|
+
...preserveProviderMetadata && providerMetadata ? { providerMetadata } : {}
|
|
903
|
+
};
|
|
672
904
|
});
|
|
673
905
|
}
|
|
674
906
|
/**
|
|
@@ -749,14 +981,40 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
749
981
|
).map((part) => part.text) : []
|
|
750
982
|
).join("") : "";
|
|
751
983
|
const content = textFromOutput || (typeof response?.output_text === "string" ? response.output_text : "");
|
|
752
|
-
const
|
|
753
|
-
|
|
754
|
-
name
|
|
755
|
-
|
|
756
|
-
|
|
984
|
+
const seenCallIds = /* @__PURE__ */ new Set();
|
|
985
|
+
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
986
|
+
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
987
|
+
throw invalidProviderResponse(
|
|
988
|
+
"Responses contains an incomplete function call"
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
if (seenCallIds.has(item.call_id))
|
|
992
|
+
throw invalidProviderResponse(
|
|
993
|
+
"Responses contains duplicate function call IDs"
|
|
994
|
+
);
|
|
995
|
+
seenCallIds.add(item.call_id);
|
|
996
|
+
let args;
|
|
997
|
+
try {
|
|
998
|
+
args = JSON.parse(item.arguments);
|
|
999
|
+
} catch {
|
|
1000
|
+
throw invalidProviderResponse(
|
|
1001
|
+
"Responses function arguments must be valid JSON"
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
1005
|
+
throw invalidProviderResponse(
|
|
1006
|
+
"Responses function arguments must be a JSON object"
|
|
1007
|
+
);
|
|
1008
|
+
return {
|
|
1009
|
+
id: item.call_id,
|
|
1010
|
+
name: item.name,
|
|
1011
|
+
args
|
|
1012
|
+
};
|
|
1013
|
+
}) : [];
|
|
757
1014
|
return {
|
|
758
1015
|
content,
|
|
759
1016
|
toolCalls,
|
|
1017
|
+
providerMetadata: responseMetadata(response),
|
|
760
1018
|
usage: response?.usage ? {
|
|
761
1019
|
promptTokens: response.usage.input_tokens ?? 0,
|
|
762
1020
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
@@ -767,6 +1025,17 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
767
1025
|
}
|
|
768
1026
|
buildResponsesPayload(request, stream) {
|
|
769
1027
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
1028
|
+
const options = resolveOpenAITransport(
|
|
1029
|
+
this.config,
|
|
1030
|
+
request.config?.openai
|
|
1031
|
+
).responses;
|
|
1032
|
+
const parameters = buildOpenAIParameters(
|
|
1033
|
+
request.config?.model || this.model,
|
|
1034
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
1035
|
+
request.config?.temperature ?? this.config.temperature,
|
|
1036
|
+
this.parameterOptions(request),
|
|
1037
|
+
"responses"
|
|
1038
|
+
);
|
|
770
1039
|
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
771
1040
|
request.config?.responseFormat
|
|
772
1041
|
);
|
|
@@ -782,13 +1051,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
782
1051
|
),
|
|
783
1052
|
tool_choice: openaiToolOptions?.toolChoice,
|
|
784
1053
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
785
|
-
...
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
1054
|
+
...parameters,
|
|
1055
|
+
...options?.reasoningSummary ? {
|
|
1056
|
+
reasoning: {
|
|
1057
|
+
...parameters.reasoning,
|
|
1058
|
+
summary: options.reasoningSummary
|
|
1059
|
+
}
|
|
1060
|
+
} : {},
|
|
1061
|
+
...options?.store !== void 0 ? { store: options.store } : {},
|
|
1062
|
+
...options?.previousResponseId !== void 0 ? { previous_response_id: options.previousResponseId } : {},
|
|
1063
|
+
...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
|
|
1064
|
+
...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
|
|
1065
|
+
...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
|
|
1066
|
+
...options?.store === false || options?.include ? {
|
|
1067
|
+
include: [
|
|
1068
|
+
.../* @__PURE__ */ new Set([
|
|
1069
|
+
...options?.include ?? [],
|
|
1070
|
+
...options?.store === false ? ["reasoning.encrypted_content"] : []
|
|
1071
|
+
])
|
|
1072
|
+
]
|
|
1073
|
+
} : {},
|
|
792
1074
|
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
793
1075
|
stream
|
|
794
1076
|
};
|
|
@@ -847,6 +1129,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
847
1129
|
let usage;
|
|
848
1130
|
const citations = [];
|
|
849
1131
|
let completed = false;
|
|
1132
|
+
let terminalResponse;
|
|
1133
|
+
let responseIdentity = {};
|
|
1134
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
1135
|
+
let streamedText = "";
|
|
850
1136
|
function* flushToolCalls() {
|
|
851
1137
|
for (const call of toolCalls.values()) {
|
|
852
1138
|
if (!call.name)
|
|
@@ -863,17 +1149,36 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
863
1149
|
for await (const event of stream) {
|
|
864
1150
|
throwIfAborted(request.signal);
|
|
865
1151
|
logProviderPayload("openai", "stream chunk", event, request.debug);
|
|
1152
|
+
if (completed)
|
|
1153
|
+
throw new Error("Responses stream emitted an event after completion");
|
|
866
1154
|
const index = event?.output_index ?? 0;
|
|
867
1155
|
switch (event?.type) {
|
|
1156
|
+
case "response.created":
|
|
1157
|
+
responseIdentity = {
|
|
1158
|
+
id: event.response?.id,
|
|
1159
|
+
model: event.response?.model
|
|
1160
|
+
};
|
|
1161
|
+
break;
|
|
1162
|
+
case "response.output_item.done":
|
|
1163
|
+
if (event.item) outputItems.set(index, event.item);
|
|
1164
|
+
if (event.item?.type === "function_call") {
|
|
1165
|
+
toolCalls.set(index, {
|
|
1166
|
+
id: event.item.call_id,
|
|
1167
|
+
name: event.item.name,
|
|
1168
|
+
arguments: event.item.arguments
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
break;
|
|
868
1172
|
case "response.output_text.delta":
|
|
869
1173
|
if (event.delta) {
|
|
1174
|
+
streamedText += event.delta;
|
|
870
1175
|
yield { type: "message:delta", content: event.delta };
|
|
871
1176
|
}
|
|
872
1177
|
break;
|
|
873
1178
|
case "response.output_item.added":
|
|
874
1179
|
if (event.item?.type === "function_call") {
|
|
875
1180
|
toolCalls.set(index, {
|
|
876
|
-
id: event.item.call_id ??
|
|
1181
|
+
id: event.item.call_id ?? "",
|
|
877
1182
|
name: event.item.name ?? "",
|
|
878
1183
|
arguments: event.item.arguments ?? ""
|
|
879
1184
|
});
|
|
@@ -892,7 +1197,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
892
1197
|
break;
|
|
893
1198
|
}
|
|
894
1199
|
case "response.completed": {
|
|
1200
|
+
if (event.response?.status && event.response.status !== "completed")
|
|
1201
|
+
throw new Error(`Responses stream ${event.response.status}`);
|
|
895
1202
|
completed = true;
|
|
1203
|
+
terminalResponse = { ...responseIdentity, ...event.response };
|
|
896
1204
|
const found = this.collectResponsesCitations(
|
|
897
1205
|
event.response?.output,
|
|
898
1206
|
citations.length
|
|
@@ -929,12 +1237,66 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
929
1237
|
throwIfAborted(request.signal);
|
|
930
1238
|
if (!completed)
|
|
931
1239
|
throw new Error("Responses stream ended without a completed response");
|
|
1240
|
+
const output = terminalResponse.output?.length ? terminalResponse.output : [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
1241
|
+
if (output.some((item) => item.type === "function_call"))
|
|
1242
|
+
toolCalls.clear();
|
|
1243
|
+
for (const [index, item] of output.entries()) {
|
|
1244
|
+
if (item.type === "function_call") {
|
|
1245
|
+
toolCalls.set(index, {
|
|
1246
|
+
id: item.call_id,
|
|
1247
|
+
name: item.name,
|
|
1248
|
+
arguments: item.arguments
|
|
1249
|
+
});
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1253
|
+
for (const call of toolCalls.values()) {
|
|
1254
|
+
if (!call.id || !call.name)
|
|
1255
|
+
throw invalidProviderResponse(
|
|
1256
|
+
"Responses stream contains an incomplete tool call"
|
|
1257
|
+
);
|
|
1258
|
+
uniqueCalls.set(call.id, call);
|
|
1259
|
+
}
|
|
1260
|
+
toolCalls.clear();
|
|
1261
|
+
[...uniqueCalls.values()].forEach(
|
|
1262
|
+
(call, index) => toolCalls.set(index, call)
|
|
1263
|
+
);
|
|
1264
|
+
if (!output.length && toolCalls.size) {
|
|
1265
|
+
for (const call of toolCalls.values())
|
|
1266
|
+
output.push({
|
|
1267
|
+
type: "function_call",
|
|
1268
|
+
call_id: call.id,
|
|
1269
|
+
name: call.name,
|
|
1270
|
+
arguments: call.arguments
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
if (!output.length && streamedText)
|
|
1274
|
+
output.push({
|
|
1275
|
+
type: "message",
|
|
1276
|
+
role: "assistant",
|
|
1277
|
+
content: [{ type: "output_text", text: streamedText, annotations: [] }]
|
|
1278
|
+
});
|
|
1279
|
+
terminalResponse.output = output;
|
|
1280
|
+
const finalText = this.parseResponsesResult(terminalResponse).content;
|
|
1281
|
+
if (finalText.startsWith(streamedText) && finalText.length > streamedText.length) {
|
|
1282
|
+
yield {
|
|
1283
|
+
type: "message:delta",
|
|
1284
|
+
content: finalText.slice(streamedText.length)
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
932
1287
|
yield* flushToolCalls();
|
|
933
1288
|
if (citations.length > 0) {
|
|
934
1289
|
yield { type: "citation", citations: deduplicateCitations(citations) };
|
|
935
1290
|
}
|
|
936
|
-
yield {
|
|
937
|
-
|
|
1291
|
+
yield {
|
|
1292
|
+
type: "message:end",
|
|
1293
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1294
|
+
};
|
|
1295
|
+
yield {
|
|
1296
|
+
type: "done",
|
|
1297
|
+
usage,
|
|
1298
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1299
|
+
};
|
|
938
1300
|
}
|
|
939
1301
|
async *stream(request) {
|
|
940
1302
|
throwIfAborted(request.signal);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { X as XAIProviderConfig, A as AIProvider } from '../../types-
|
|
1
|
+
import { L as LanguageModel } from '../../types-Dg1Bcg1k.mjs';
|
|
2
|
+
import { X as XAIProviderConfig, 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
|
* xAI Provider - Modern Pattern
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { X as XAIProviderConfig, A as AIProvider } from '../../types-
|
|
1
|
+
import { L as LanguageModel } from '../../types-Dg1Bcg1k.js';
|
|
2
|
+
import { X as XAIProviderConfig, 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
|
* xAI Provider - Modern Pattern
|