@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,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
|
}
|
|
@@ -502,7 +607,7 @@ function formatMessagesForXAI(messages) {
|
|
|
502
607
|
return {
|
|
503
608
|
role: "tool",
|
|
504
609
|
tool_call_id: msg.toolCallId,
|
|
505
|
-
content: msg.content
|
|
610
|
+
content: textToolOutput(msg.modelOutput, msg.content)
|
|
506
611
|
};
|
|
507
612
|
default:
|
|
508
613
|
return msg;
|
|
@@ -510,6 +615,64 @@ function formatMessagesForXAI(messages) {
|
|
|
510
615
|
});
|
|
511
616
|
}
|
|
512
617
|
|
|
618
|
+
// src/core/openai-responses.ts
|
|
619
|
+
function resolveOpenAITransport(defaults, overrides) {
|
|
620
|
+
return {
|
|
621
|
+
api: overrides?.api ?? defaults.api ?? "auto",
|
|
622
|
+
responses: defaults.responses !== void 0 || overrides?.responses !== void 0 ? { ...defaults.responses, ...overrides?.responses } : void 0
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function useOpenAIResponses(model, baseURL, parameters, transport, hasTools, hasReplay, nativeToolSearch = false) {
|
|
626
|
+
const api = transport.api ?? "auto";
|
|
627
|
+
if (!["auto", "chat", "responses"].includes(api)) {
|
|
628
|
+
throw new Error(`Unknown OpenAI API selection: ${api}`);
|
|
629
|
+
}
|
|
630
|
+
if (api === "chat") {
|
|
631
|
+
if (transport.responses !== void 0 || nativeToolSearch) {
|
|
632
|
+
throw new Error(
|
|
633
|
+
"Responses options and native tool search require the Responses API"
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
let officialEndpoint = !baseURL;
|
|
639
|
+
try {
|
|
640
|
+
officialEndpoint = !baseURL || new URL(baseURL).hostname === "api.openai.com";
|
|
641
|
+
} catch {
|
|
642
|
+
}
|
|
643
|
+
return api === "responses" || transport.responses !== void 0 || hasReplay && officialEndpoint || nativeToolSearch || hasTools && requiresOpenAIResponses(model, baseURL, parameters);
|
|
644
|
+
}
|
|
645
|
+
function responseMetadata(response) {
|
|
646
|
+
const output = Array.isArray(response?.output) ? response.output : [];
|
|
647
|
+
return {
|
|
648
|
+
openai: {
|
|
649
|
+
response: {
|
|
650
|
+
id: response?.id,
|
|
651
|
+
model: response?.model,
|
|
652
|
+
status: response?.status,
|
|
653
|
+
output,
|
|
654
|
+
usage: response?.usage,
|
|
655
|
+
store: response?.store,
|
|
656
|
+
refusals: output.flatMap(
|
|
657
|
+
(item) => item?.type === "message" && Array.isArray(item.content) ? item.content.filter(
|
|
658
|
+
(part) => part?.type === "refusal" && typeof part.refusal === "string"
|
|
659
|
+
).map((part) => part.refusal) : []
|
|
660
|
+
)
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function getResponseReplay(metadata) {
|
|
666
|
+
const response = metadata?.openai?.response;
|
|
667
|
+
if (response === void 0) return void 0;
|
|
668
|
+
if (!Array.isArray(response.output) || response.output.some((item) => !item || typeof item.type !== "string")) {
|
|
669
|
+
throw new Error(
|
|
670
|
+
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
return response.output;
|
|
674
|
+
}
|
|
675
|
+
|
|
513
676
|
// src/core/provider-error.ts
|
|
514
677
|
function providerErrorEvent(error, code) {
|
|
515
678
|
const details = error ?? {};
|
|
@@ -586,13 +749,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
586
749
|
}));
|
|
587
750
|
}
|
|
588
751
|
shouldUseResponsesApi(request) {
|
|
589
|
-
|
|
590
|
-
if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false)
|
|
591
|
-
return true;
|
|
592
|
-
return requiresOpenAIResponses(
|
|
752
|
+
return useOpenAIResponses(
|
|
593
753
|
request.config?.model || this.model,
|
|
594
754
|
this.config.baseUrl,
|
|
595
|
-
this.parameterOptions(request)
|
|
755
|
+
this.parameterOptions(request),
|
|
756
|
+
resolveOpenAITransport(this.config, request.config?.openai),
|
|
757
|
+
this.toolDefinitions(request).length > 0,
|
|
758
|
+
!!(request.rawMessages ?? request.messages)?.some(
|
|
759
|
+
(message) => message.providerMetadata?.openai?.response
|
|
760
|
+
),
|
|
761
|
+
request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false
|
|
596
762
|
);
|
|
597
763
|
}
|
|
598
764
|
/**
|
|
@@ -625,11 +791,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
625
791
|
});
|
|
626
792
|
}
|
|
627
793
|
buildResponsesInput(request) {
|
|
628
|
-
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages) : formatMessagesForOpenAI(request.messages, void 0);
|
|
794
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages, true) : formatMessagesForOpenAI(request.messages, void 0, true);
|
|
629
795
|
const input = [];
|
|
630
796
|
for (const message of sourceMessages) {
|
|
631
797
|
if (message.role === "system") {
|
|
632
|
-
if (
|
|
798
|
+
if (message.content && message.content !== request.systemPrompt) {
|
|
633
799
|
input.push({
|
|
634
800
|
type: "message",
|
|
635
801
|
role: "developer",
|
|
@@ -639,6 +805,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
639
805
|
continue;
|
|
640
806
|
}
|
|
641
807
|
if (message.role === "assistant") {
|
|
808
|
+
const replay = getResponseReplay(message.providerMetadata);
|
|
809
|
+
if (replay) {
|
|
810
|
+
input.push(...replay);
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
642
813
|
const content = this.toResponsesContent(message.content, "assistant");
|
|
643
814
|
if (typeof content === "string" ? content : Array.isArray(content) && content.length > 0) {
|
|
644
815
|
input.push({
|
|
@@ -662,7 +833,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
662
833
|
input.push({
|
|
663
834
|
type: "function_call_output",
|
|
664
835
|
call_id: message.tool_call_id,
|
|
665
|
-
output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
836
|
+
output: message.modelOutput ? toolOutputForProvider(message.modelOutput, "responses") : typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
666
837
|
});
|
|
667
838
|
continue;
|
|
668
839
|
}
|
|
@@ -676,10 +847,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
676
847
|
return input;
|
|
677
848
|
}
|
|
678
849
|
/** Preserve Copilot screenshot attachments on every OpenAI transport. */
|
|
679
|
-
formatRawMessages(messages) {
|
|
850
|
+
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
680
851
|
return messages.map((message) => {
|
|
681
|
-
const { attachments, ...rest } = message;
|
|
682
|
-
let content = message.content;
|
|
852
|
+
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
853
|
+
let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
|
|
854
|
+
if (preserveProviderMetadata && modelOutput)
|
|
855
|
+
rest.modelOutput = modelOutput;
|
|
683
856
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
684
857
|
content = null;
|
|
685
858
|
}
|
|
@@ -692,7 +865,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
692
865
|
content = [...parts, ...images];
|
|
693
866
|
}
|
|
694
867
|
}
|
|
695
|
-
return {
|
|
868
|
+
return {
|
|
869
|
+
...rest,
|
|
870
|
+
content,
|
|
871
|
+
...preserveProviderMetadata && providerMetadata ? { providerMetadata } : {}
|
|
872
|
+
};
|
|
696
873
|
});
|
|
697
874
|
}
|
|
698
875
|
/**
|
|
@@ -773,14 +950,25 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
773
950
|
).map((part) => part.text) : []
|
|
774
951
|
).join("") : "";
|
|
775
952
|
const content = textFromOutput || (typeof response?.output_text === "string" ? response.output_text : "");
|
|
776
|
-
const
|
|
777
|
-
|
|
778
|
-
name
|
|
779
|
-
|
|
780
|
-
|
|
953
|
+
const seenCallIds = /* @__PURE__ */ new Set();
|
|
954
|
+
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
955
|
+
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
956
|
+
throw new Error("Responses contains an incomplete function call");
|
|
957
|
+
}
|
|
958
|
+
if (seenCallIds.has(item.call_id))
|
|
959
|
+
throw new Error("Responses contains duplicate function call IDs");
|
|
960
|
+
seenCallIds.add(item.call_id);
|
|
961
|
+
const args = JSON.parse(item.arguments);
|
|
962
|
+
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
963
|
+
throw new Error(
|
|
964
|
+
"Responses function arguments must be a JSON object"
|
|
965
|
+
);
|
|
966
|
+
return { id: item.call_id, name: item.name, args };
|
|
967
|
+
}) : [];
|
|
781
968
|
return {
|
|
782
969
|
content,
|
|
783
970
|
toolCalls,
|
|
971
|
+
providerMetadata: responseMetadata(response),
|
|
784
972
|
usage: response?.usage ? {
|
|
785
973
|
promptTokens: response.usage.input_tokens ?? 0,
|
|
786
974
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
@@ -791,6 +979,17 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
791
979
|
}
|
|
792
980
|
buildResponsesPayload(request, stream) {
|
|
793
981
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
982
|
+
const options = resolveOpenAITransport(
|
|
983
|
+
this.config,
|
|
984
|
+
request.config?.openai
|
|
985
|
+
).responses;
|
|
986
|
+
const parameters = buildOpenAIParameters(
|
|
987
|
+
request.config?.model || this.model,
|
|
988
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
989
|
+
request.config?.temperature ?? this.config.temperature,
|
|
990
|
+
this.parameterOptions(request),
|
|
991
|
+
"responses"
|
|
992
|
+
);
|
|
794
993
|
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
795
994
|
request.config?.responseFormat
|
|
796
995
|
);
|
|
@@ -806,13 +1005,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
806
1005
|
),
|
|
807
1006
|
tool_choice: openaiToolOptions?.toolChoice,
|
|
808
1007
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
809
|
-
...
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
1008
|
+
...parameters,
|
|
1009
|
+
...options?.reasoningSummary ? {
|
|
1010
|
+
reasoning: {
|
|
1011
|
+
...parameters.reasoning,
|
|
1012
|
+
summary: options.reasoningSummary
|
|
1013
|
+
}
|
|
1014
|
+
} : {},
|
|
1015
|
+
...options?.store !== void 0 ? { store: options.store } : {},
|
|
1016
|
+
...options?.previousResponseId !== void 0 ? { previous_response_id: options.previousResponseId } : {},
|
|
1017
|
+
...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
|
|
1018
|
+
...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
|
|
1019
|
+
...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
|
|
1020
|
+
...options?.store === false || options?.include ? {
|
|
1021
|
+
include: [
|
|
1022
|
+
.../* @__PURE__ */ new Set([
|
|
1023
|
+
...options?.include ?? [],
|
|
1024
|
+
...options?.store === false ? ["reasoning.encrypted_content"] : []
|
|
1025
|
+
])
|
|
1026
|
+
]
|
|
1027
|
+
} : {},
|
|
816
1028
|
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
817
1029
|
stream
|
|
818
1030
|
};
|
|
@@ -871,6 +1083,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
871
1083
|
let usage;
|
|
872
1084
|
const citations = [];
|
|
873
1085
|
let completed = false;
|
|
1086
|
+
let terminalResponse;
|
|
1087
|
+
let responseIdentity = {};
|
|
1088
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
1089
|
+
let streamedText = "";
|
|
874
1090
|
function* flushToolCalls() {
|
|
875
1091
|
for (const call of toolCalls.values()) {
|
|
876
1092
|
if (!call.name)
|
|
@@ -887,17 +1103,36 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
887
1103
|
for await (const event of stream) {
|
|
888
1104
|
throwIfAborted(request.signal);
|
|
889
1105
|
logProviderPayload("openai", "stream chunk", event, request.debug);
|
|
1106
|
+
if (completed)
|
|
1107
|
+
throw new Error("Responses stream emitted an event after completion");
|
|
890
1108
|
const index = event?.output_index ?? 0;
|
|
891
1109
|
switch (event?.type) {
|
|
1110
|
+
case "response.created":
|
|
1111
|
+
responseIdentity = {
|
|
1112
|
+
id: event.response?.id,
|
|
1113
|
+
model: event.response?.model
|
|
1114
|
+
};
|
|
1115
|
+
break;
|
|
1116
|
+
case "response.output_item.done":
|
|
1117
|
+
if (event.item) outputItems.set(index, event.item);
|
|
1118
|
+
if (event.item?.type === "function_call") {
|
|
1119
|
+
toolCalls.set(index, {
|
|
1120
|
+
id: event.item.call_id,
|
|
1121
|
+
name: event.item.name,
|
|
1122
|
+
arguments: event.item.arguments
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
break;
|
|
892
1126
|
case "response.output_text.delta":
|
|
893
1127
|
if (event.delta) {
|
|
1128
|
+
streamedText += event.delta;
|
|
894
1129
|
yield { type: "message:delta", content: event.delta };
|
|
895
1130
|
}
|
|
896
1131
|
break;
|
|
897
1132
|
case "response.output_item.added":
|
|
898
1133
|
if (event.item?.type === "function_call") {
|
|
899
1134
|
toolCalls.set(index, {
|
|
900
|
-
id: event.item.call_id ??
|
|
1135
|
+
id: event.item.call_id ?? "",
|
|
901
1136
|
name: event.item.name ?? "",
|
|
902
1137
|
arguments: event.item.arguments ?? ""
|
|
903
1138
|
});
|
|
@@ -916,7 +1151,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
916
1151
|
break;
|
|
917
1152
|
}
|
|
918
1153
|
case "response.completed": {
|
|
1154
|
+
if (event.response?.status && event.response.status !== "completed")
|
|
1155
|
+
throw new Error(`Responses stream ${event.response.status}`);
|
|
919
1156
|
completed = true;
|
|
1157
|
+
terminalResponse = { ...responseIdentity, ...event.response };
|
|
920
1158
|
const found = this.collectResponsesCitations(
|
|
921
1159
|
event.response?.output,
|
|
922
1160
|
citations.length
|
|
@@ -953,12 +1191,64 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
953
1191
|
throwIfAborted(request.signal);
|
|
954
1192
|
if (!completed)
|
|
955
1193
|
throw new Error("Responses stream ended without a completed response");
|
|
1194
|
+
const output = terminalResponse.output?.length ? terminalResponse.output : [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
1195
|
+
if (output.some((item) => item.type === "function_call"))
|
|
1196
|
+
toolCalls.clear();
|
|
1197
|
+
for (const [index, item] of output.entries()) {
|
|
1198
|
+
if (item.type === "function_call") {
|
|
1199
|
+
toolCalls.set(index, {
|
|
1200
|
+
id: item.call_id,
|
|
1201
|
+
name: item.name,
|
|
1202
|
+
arguments: item.arguments
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1207
|
+
for (const call of toolCalls.values()) {
|
|
1208
|
+
if (!call.id || !call.name)
|
|
1209
|
+
throw new Error("Responses stream contains an incomplete tool call");
|
|
1210
|
+
uniqueCalls.set(call.id, call);
|
|
1211
|
+
}
|
|
1212
|
+
toolCalls.clear();
|
|
1213
|
+
[...uniqueCalls.values()].forEach(
|
|
1214
|
+
(call, index) => toolCalls.set(index, call)
|
|
1215
|
+
);
|
|
1216
|
+
if (!output.length && toolCalls.size) {
|
|
1217
|
+
for (const call of toolCalls.values())
|
|
1218
|
+
output.push({
|
|
1219
|
+
type: "function_call",
|
|
1220
|
+
call_id: call.id,
|
|
1221
|
+
name: call.name,
|
|
1222
|
+
arguments: call.arguments
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
if (!output.length && streamedText)
|
|
1226
|
+
output.push({
|
|
1227
|
+
type: "message",
|
|
1228
|
+
role: "assistant",
|
|
1229
|
+
content: [{ type: "output_text", text: streamedText, annotations: [] }]
|
|
1230
|
+
});
|
|
1231
|
+
terminalResponse.output = output;
|
|
1232
|
+
const finalText = this.parseResponsesResult(terminalResponse).content;
|
|
1233
|
+
if (finalText.startsWith(streamedText) && finalText.length > streamedText.length) {
|
|
1234
|
+
yield {
|
|
1235
|
+
type: "message:delta",
|
|
1236
|
+
content: finalText.slice(streamedText.length)
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
956
1239
|
yield* flushToolCalls();
|
|
957
1240
|
if (citations.length > 0) {
|
|
958
1241
|
yield { type: "citation", citations: deduplicateCitations(citations) };
|
|
959
1242
|
}
|
|
960
|
-
yield {
|
|
961
|
-
|
|
1243
|
+
yield {
|
|
1244
|
+
type: "message:end",
|
|
1245
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1246
|
+
};
|
|
1247
|
+
yield {
|
|
1248
|
+
type: "done",
|
|
1249
|
+
usage,
|
|
1250
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1251
|
+
};
|
|
962
1252
|
}
|
|
963
1253
|
async *stream(request) {
|
|
964
1254
|
throwIfAborted(request.signal);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { L as LLMAdapter } from './base-
|
|
1
|
+
import { ae as OpenAIParameterOptions, O as OpenAITransportOptions, e as ToolDefinition, a1 as UnifiedToolCall, a2 as UnifiedToolResult } from './types-Dg1Bcg1k.mjs';
|
|
2
|
+
import { L as LLMAdapter } from './base-BICaQaRS.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Provider formatter interface
|
|
@@ -251,7 +251,7 @@ interface BaseProviderConfig {
|
|
|
251
251
|
/**
|
|
252
252
|
* OpenAI provider configuration
|
|
253
253
|
*/
|
|
254
|
-
interface OpenAIProviderConfig extends BaseProviderConfig, OpenAIParameterOptions {
|
|
254
|
+
interface OpenAIProviderConfig extends BaseProviderConfig, OpenAIParameterOptions, OpenAITransportOptions {
|
|
255
255
|
/** OpenAI organization ID */
|
|
256
256
|
organization?: string;
|
|
257
257
|
/** OpenAI project ID */
|