@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,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
|
* Fireworks 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
|
* Fireworks Provider
|
|
@@ -1,5 +1,108 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/core/tool-output.ts
|
|
4
|
+
var imageTypes = /* @__PURE__ */ new Set([
|
|
5
|
+
"image/png",
|
|
6
|
+
"image/jpeg",
|
|
7
|
+
"image/webp",
|
|
8
|
+
"image/gif"
|
|
9
|
+
]);
|
|
10
|
+
function normalizeToolOutput(value) {
|
|
11
|
+
const output = value;
|
|
12
|
+
if (output?.type !== "content" || !Array.isArray(output.content) || !output.content.length) {
|
|
13
|
+
throw new Error("Tool model output must contain a nonempty content array");
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
type: "content",
|
|
17
|
+
content: output.content.map((part) => {
|
|
18
|
+
if (part?.type === "text" && typeof part.text === "string")
|
|
19
|
+
return { type: "text", text: part.text };
|
|
20
|
+
if (part?.type !== "image")
|
|
21
|
+
throw new Error("Unsupported tool output content type");
|
|
22
|
+
const sources = ["data", "url", "fileId"].filter((key) => key in part);
|
|
23
|
+
if (sources.length !== 1)
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Tool image requires exactly one of data, url, or fileId"
|
|
26
|
+
);
|
|
27
|
+
if ("fileId" in part) {
|
|
28
|
+
if (part.provider !== "openai" || typeof part.fileId !== "string" || !part.fileId.trim())
|
|
29
|
+
throw new Error(
|
|
30
|
+
"Tool image file references must name the openai provider and fileId"
|
|
31
|
+
);
|
|
32
|
+
return { type: "image", fileId: part.fileId, provider: "openai" };
|
|
33
|
+
}
|
|
34
|
+
if ("url" in part) {
|
|
35
|
+
let url;
|
|
36
|
+
try {
|
|
37
|
+
url = new URL(part.url);
|
|
38
|
+
} catch {
|
|
39
|
+
throw new Error("Invalid tool image URL");
|
|
40
|
+
}
|
|
41
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password)
|
|
42
|
+
throw new Error(
|
|
43
|
+
"Tool image URL must use HTTP(S) without credentials"
|
|
44
|
+
);
|
|
45
|
+
return { type: "image", url: url.href };
|
|
46
|
+
}
|
|
47
|
+
if (!("data" in part) || !imageTypes.has(part.mediaType))
|
|
48
|
+
throw new Error("Unsupported tool image media type");
|
|
49
|
+
let data = part.data instanceof Uint8Array ? Buffer.from(part.data).toString("base64") : part.data;
|
|
50
|
+
if (typeof data !== "string")
|
|
51
|
+
throw new Error("Tool image data must be base64 or bytes");
|
|
52
|
+
if (data.startsWith("data:")) {
|
|
53
|
+
const match = /^data:([^;,]+);base64,(.+)$/.exec(data);
|
|
54
|
+
if (!match || match[1] !== part.mediaType)
|
|
55
|
+
throw new Error(
|
|
56
|
+
"Tool image data URL media type does not match mediaType"
|
|
57
|
+
);
|
|
58
|
+
data = match[2];
|
|
59
|
+
}
|
|
60
|
+
if (!data.length || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data))
|
|
61
|
+
throw new Error("Invalid tool image base64 data");
|
|
62
|
+
if (Buffer.byteLength(data, "base64") > 20 * 1024 * 1024)
|
|
63
|
+
throw new Error("Tool image exceeds 20 MiB");
|
|
64
|
+
if (Buffer.from(data, "base64").toString("base64") !== data)
|
|
65
|
+
throw new Error("Invalid tool image base64 data");
|
|
66
|
+
return { type: "image", data, mediaType: part.mediaType };
|
|
67
|
+
})
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function toolOutputForProvider(value, provider) {
|
|
71
|
+
const output = normalizeToolOutput(value);
|
|
72
|
+
return output.content.map((part) => {
|
|
73
|
+
if (part.type === "text")
|
|
74
|
+
return {
|
|
75
|
+
type: provider === "responses" ? "input_text" : "text",
|
|
76
|
+
text: part.text
|
|
77
|
+
};
|
|
78
|
+
if (provider === "unsupported")
|
|
79
|
+
throw new Error(
|
|
80
|
+
"Image tool results require OpenAI Responses or Anthropic; this endpoint is not supported"
|
|
81
|
+
);
|
|
82
|
+
if ("fileId" in part) {
|
|
83
|
+
if (provider !== "responses")
|
|
84
|
+
throw new Error(
|
|
85
|
+
"OpenAI image file references cannot be sent to another provider"
|
|
86
|
+
);
|
|
87
|
+
return { type: "input_image", file_id: part.fileId, detail: "auto" };
|
|
88
|
+
}
|
|
89
|
+
if (provider === "responses")
|
|
90
|
+
return {
|
|
91
|
+
type: "input_image",
|
|
92
|
+
image_url: "url" in part ? part.url : `data:${part.mediaType};base64,${part.data}`,
|
|
93
|
+
detail: "auto"
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
type: "image",
|
|
97
|
+
source: "url" in part ? { type: "url", url: part.url } : { type: "base64", media_type: part.mediaType, data: part.data }
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function textToolOutput(value, fallback) {
|
|
102
|
+
if (value === void 0) return fallback;
|
|
103
|
+
return toolOutputForProvider(value, "unsupported").map((part) => part.text).join("\n");
|
|
104
|
+
}
|
|
105
|
+
|
|
3
106
|
// src/core/openai-parameters.ts
|
|
4
107
|
function capabilities(model) {
|
|
5
108
|
const gpt = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/i.exec(model);
|
|
@@ -241,7 +344,7 @@ function messageToOpenAIContent(message) {
|
|
|
241
344
|
}
|
|
242
345
|
return blocks;
|
|
243
346
|
}
|
|
244
|
-
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
347
|
+
function formatMessagesForOpenAI(messages, systemPrompt, preserveProviderMetadata = false) {
|
|
245
348
|
const formatted = [];
|
|
246
349
|
if (systemPrompt) {
|
|
247
350
|
formatted.push({ role: "system", content: systemPrompt });
|
|
@@ -259,7 +362,8 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
259
362
|
const assistantMsg = {
|
|
260
363
|
role: "assistant",
|
|
261
364
|
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
262
|
-
content: hasToolCalls ? msg.content || null : msg.content
|
|
365
|
+
content: hasToolCalls ? msg.content || null : msg.content,
|
|
366
|
+
...preserveProviderMetadata && msg.providerMetadata ? { providerMetadata: msg.providerMetadata } : {}
|
|
263
367
|
};
|
|
264
368
|
if (hasToolCalls) {
|
|
265
369
|
assistantMsg.tool_calls = msg.tool_calls;
|
|
@@ -268,7 +372,8 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
268
372
|
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
269
373
|
formatted.push({
|
|
270
374
|
role: "tool",
|
|
271
|
-
content: msg.content ?? "",
|
|
375
|
+
content: preserveProviderMetadata ? msg.content ?? "" : textToolOutput(msg.modelOutput, msg.content ?? ""),
|
|
376
|
+
...preserveProviderMetadata && msg.modelOutput ? { modelOutput: msg.modelOutput } : {},
|
|
272
377
|
tool_call_id: msg.tool_call_id
|
|
273
378
|
});
|
|
274
379
|
}
|
|
@@ -475,7 +580,7 @@ function formatMessages(messages) {
|
|
|
475
580
|
return {
|
|
476
581
|
role: "tool",
|
|
477
582
|
tool_call_id: msg.toolCallId,
|
|
478
|
-
content: msg.content
|
|
583
|
+
content: textToolOutput(msg.modelOutput, msg.content)
|
|
479
584
|
};
|
|
480
585
|
default:
|
|
481
586
|
return msg;
|
|
@@ -483,6 +588,64 @@ function formatMessages(messages) {
|
|
|
483
588
|
});
|
|
484
589
|
}
|
|
485
590
|
|
|
591
|
+
// src/core/openai-responses.ts
|
|
592
|
+
function resolveOpenAITransport(defaults, overrides) {
|
|
593
|
+
return {
|
|
594
|
+
api: overrides?.api ?? defaults.api ?? "auto",
|
|
595
|
+
responses: defaults.responses !== void 0 || overrides?.responses !== void 0 ? { ...defaults.responses, ...overrides?.responses } : void 0
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function useOpenAIResponses(model, baseURL, parameters, transport, hasTools, hasReplay, nativeToolSearch = false) {
|
|
599
|
+
const api = transport.api ?? "auto";
|
|
600
|
+
if (!["auto", "chat", "responses"].includes(api)) {
|
|
601
|
+
throw new Error(`Unknown OpenAI API selection: ${api}`);
|
|
602
|
+
}
|
|
603
|
+
if (api === "chat") {
|
|
604
|
+
if (transport.responses !== void 0 || nativeToolSearch) {
|
|
605
|
+
throw new Error(
|
|
606
|
+
"Responses options and native tool search require the Responses API"
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
let officialEndpoint = !baseURL;
|
|
612
|
+
try {
|
|
613
|
+
officialEndpoint = !baseURL || new URL(baseURL).hostname === "api.openai.com";
|
|
614
|
+
} catch {
|
|
615
|
+
}
|
|
616
|
+
return api === "responses" || transport.responses !== void 0 || hasReplay && officialEndpoint || nativeToolSearch || hasTools && requiresOpenAIResponses(model, baseURL, parameters);
|
|
617
|
+
}
|
|
618
|
+
function responseMetadata(response) {
|
|
619
|
+
const output = Array.isArray(response?.output) ? response.output : [];
|
|
620
|
+
return {
|
|
621
|
+
openai: {
|
|
622
|
+
response: {
|
|
623
|
+
id: response?.id,
|
|
624
|
+
model: response?.model,
|
|
625
|
+
status: response?.status,
|
|
626
|
+
output,
|
|
627
|
+
usage: response?.usage,
|
|
628
|
+
store: response?.store,
|
|
629
|
+
refusals: output.flatMap(
|
|
630
|
+
(item) => item?.type === "message" && Array.isArray(item.content) ? item.content.filter(
|
|
631
|
+
(part) => part?.type === "refusal" && typeof part.refusal === "string"
|
|
632
|
+
).map((part) => part.refusal) : []
|
|
633
|
+
)
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function getResponseReplay(metadata) {
|
|
639
|
+
const response = metadata?.openai?.response;
|
|
640
|
+
if (response === void 0) return void 0;
|
|
641
|
+
if (!Array.isArray(response.output) || response.output.some((item) => !item || typeof item.type !== "string")) {
|
|
642
|
+
throw new Error(
|
|
643
|
+
"Invalid OpenAI Responses replay metadata: output must contain typed items"
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
return response.output;
|
|
647
|
+
}
|
|
648
|
+
|
|
486
649
|
// src/core/provider-error.ts
|
|
487
650
|
function providerErrorEvent(error, code) {
|
|
488
651
|
const details = error ?? {};
|
|
@@ -559,13 +722,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
559
722
|
}));
|
|
560
723
|
}
|
|
561
724
|
shouldUseResponsesApi(request) {
|
|
562
|
-
|
|
563
|
-
if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false)
|
|
564
|
-
return true;
|
|
565
|
-
return requiresOpenAIResponses(
|
|
725
|
+
return useOpenAIResponses(
|
|
566
726
|
request.config?.model || this.model,
|
|
567
727
|
this.config.baseUrl,
|
|
568
|
-
this.parameterOptions(request)
|
|
728
|
+
this.parameterOptions(request),
|
|
729
|
+
resolveOpenAITransport(this.config, request.config?.openai),
|
|
730
|
+
this.toolDefinitions(request).length > 0,
|
|
731
|
+
!!(request.rawMessages ?? request.messages)?.some(
|
|
732
|
+
(message) => message.providerMetadata?.openai?.response
|
|
733
|
+
),
|
|
734
|
+
request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false
|
|
569
735
|
);
|
|
570
736
|
}
|
|
571
737
|
/**
|
|
@@ -598,11 +764,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
598
764
|
});
|
|
599
765
|
}
|
|
600
766
|
buildResponsesInput(request) {
|
|
601
|
-
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages) : formatMessagesForOpenAI(request.messages, void 0);
|
|
767
|
+
const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages, true) : formatMessagesForOpenAI(request.messages, void 0, true);
|
|
602
768
|
const input = [];
|
|
603
769
|
for (const message of sourceMessages) {
|
|
604
770
|
if (message.role === "system") {
|
|
605
|
-
if (
|
|
771
|
+
if (message.content && message.content !== request.systemPrompt) {
|
|
606
772
|
input.push({
|
|
607
773
|
type: "message",
|
|
608
774
|
role: "developer",
|
|
@@ -612,6 +778,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
612
778
|
continue;
|
|
613
779
|
}
|
|
614
780
|
if (message.role === "assistant") {
|
|
781
|
+
const replay = getResponseReplay(message.providerMetadata);
|
|
782
|
+
if (replay) {
|
|
783
|
+
input.push(...replay);
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
615
786
|
const content = this.toResponsesContent(message.content, "assistant");
|
|
616
787
|
if (typeof content === "string" ? content : Array.isArray(content) && content.length > 0) {
|
|
617
788
|
input.push({
|
|
@@ -635,7 +806,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
635
806
|
input.push({
|
|
636
807
|
type: "function_call_output",
|
|
637
808
|
call_id: message.tool_call_id,
|
|
638
|
-
output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
809
|
+
output: message.modelOutput ? toolOutputForProvider(message.modelOutput, "responses") : typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
|
|
639
810
|
});
|
|
640
811
|
continue;
|
|
641
812
|
}
|
|
@@ -649,10 +820,12 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
649
820
|
return input;
|
|
650
821
|
}
|
|
651
822
|
/** Preserve Copilot screenshot attachments on every OpenAI transport. */
|
|
652
|
-
formatRawMessages(messages) {
|
|
823
|
+
formatRawMessages(messages, preserveProviderMetadata = false) {
|
|
653
824
|
return messages.map((message) => {
|
|
654
|
-
const { attachments, ...rest } = message;
|
|
655
|
-
let content = message.content;
|
|
825
|
+
const { attachments, providerMetadata, modelOutput, ...rest } = message;
|
|
826
|
+
let content = message.role === "tool" && !preserveProviderMetadata ? textToolOutput(modelOutput, String(message.content ?? "")) : message.content;
|
|
827
|
+
if (preserveProviderMetadata && modelOutput)
|
|
828
|
+
rest.modelOutput = modelOutput;
|
|
656
829
|
if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
|
|
657
830
|
content = null;
|
|
658
831
|
}
|
|
@@ -665,7 +838,11 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
665
838
|
content = [...parts, ...images];
|
|
666
839
|
}
|
|
667
840
|
}
|
|
668
|
-
return {
|
|
841
|
+
return {
|
|
842
|
+
...rest,
|
|
843
|
+
content,
|
|
844
|
+
...preserveProviderMetadata && providerMetadata ? { providerMetadata } : {}
|
|
845
|
+
};
|
|
669
846
|
});
|
|
670
847
|
}
|
|
671
848
|
/**
|
|
@@ -746,14 +923,25 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
746
923
|
).map((part) => part.text) : []
|
|
747
924
|
).join("") : "";
|
|
748
925
|
const content = textFromOutput || (typeof response?.output_text === "string" ? response.output_text : "");
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
name
|
|
752
|
-
|
|
753
|
-
|
|
926
|
+
const seenCallIds = /* @__PURE__ */ new Set();
|
|
927
|
+
const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => {
|
|
928
|
+
if (typeof item.call_id !== "string" || !item.call_id || typeof item.name !== "string" || !item.name || typeof item.arguments !== "string" || item.status && item.status !== "completed") {
|
|
929
|
+
throw new Error("Responses contains an incomplete function call");
|
|
930
|
+
}
|
|
931
|
+
if (seenCallIds.has(item.call_id))
|
|
932
|
+
throw new Error("Responses contains duplicate function call IDs");
|
|
933
|
+
seenCallIds.add(item.call_id);
|
|
934
|
+
const args = JSON.parse(item.arguments);
|
|
935
|
+
if (!args || typeof args !== "object" || Array.isArray(args))
|
|
936
|
+
throw new Error(
|
|
937
|
+
"Responses function arguments must be a JSON object"
|
|
938
|
+
);
|
|
939
|
+
return { id: item.call_id, name: item.name, args };
|
|
940
|
+
}) : [];
|
|
754
941
|
return {
|
|
755
942
|
content,
|
|
756
943
|
toolCalls,
|
|
944
|
+
providerMetadata: responseMetadata(response),
|
|
757
945
|
usage: response?.usage ? {
|
|
758
946
|
promptTokens: response.usage.input_tokens ?? 0,
|
|
759
947
|
completionTokens: response.usage.output_tokens ?? 0,
|
|
@@ -764,6 +952,17 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
764
952
|
}
|
|
765
953
|
buildResponsesPayload(request, stream) {
|
|
766
954
|
const openaiToolOptions = request.providerToolOptions?.openai;
|
|
955
|
+
const options = resolveOpenAITransport(
|
|
956
|
+
this.config,
|
|
957
|
+
request.config?.openai
|
|
958
|
+
).responses;
|
|
959
|
+
const parameters = buildOpenAIParameters(
|
|
960
|
+
request.config?.model || this.model,
|
|
961
|
+
request.config?.maxTokens ?? this.config.maxTokens,
|
|
962
|
+
request.config?.temperature ?? this.config.temperature,
|
|
963
|
+
this.parameterOptions(request),
|
|
964
|
+
"responses"
|
|
965
|
+
);
|
|
767
966
|
const responsesTextFormat = toOpenAIResponsesTextFormat(
|
|
768
967
|
request.config?.responseFormat
|
|
769
968
|
);
|
|
@@ -779,13 +978,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
779
978
|
),
|
|
780
979
|
tool_choice: openaiToolOptions?.toolChoice,
|
|
781
980
|
parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
|
|
782
|
-
...
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
981
|
+
...parameters,
|
|
982
|
+
...options?.reasoningSummary ? {
|
|
983
|
+
reasoning: {
|
|
984
|
+
...parameters.reasoning,
|
|
985
|
+
summary: options.reasoningSummary
|
|
986
|
+
}
|
|
987
|
+
} : {},
|
|
988
|
+
...options?.store !== void 0 ? { store: options.store } : {},
|
|
989
|
+
...options?.previousResponseId !== void 0 ? { previous_response_id: options.previousResponseId } : {},
|
|
990
|
+
...options?.promptCacheKey !== void 0 ? { prompt_cache_key: options.promptCacheKey } : {},
|
|
991
|
+
...options?.promptCacheOptions !== void 0 ? { prompt_cache_options: options.promptCacheOptions } : {},
|
|
992
|
+
...options?.promptCacheRetention !== void 0 ? { prompt_cache_retention: options.promptCacheRetention } : {},
|
|
993
|
+
...options?.store === false || options?.include ? {
|
|
994
|
+
include: [
|
|
995
|
+
.../* @__PURE__ */ new Set([
|
|
996
|
+
...options?.include ?? [],
|
|
997
|
+
...options?.store === false ? ["reasoning.encrypted_content"] : []
|
|
998
|
+
])
|
|
999
|
+
]
|
|
1000
|
+
} : {},
|
|
789
1001
|
...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
|
|
790
1002
|
stream
|
|
791
1003
|
};
|
|
@@ -844,6 +1056,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
844
1056
|
let usage;
|
|
845
1057
|
const citations = [];
|
|
846
1058
|
let completed = false;
|
|
1059
|
+
let terminalResponse;
|
|
1060
|
+
let responseIdentity = {};
|
|
1061
|
+
const outputItems = /* @__PURE__ */ new Map();
|
|
1062
|
+
let streamedText = "";
|
|
847
1063
|
function* flushToolCalls() {
|
|
848
1064
|
for (const call of toolCalls.values()) {
|
|
849
1065
|
if (!call.name)
|
|
@@ -860,17 +1076,36 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
860
1076
|
for await (const event of stream) {
|
|
861
1077
|
throwIfAborted(request.signal);
|
|
862
1078
|
logProviderPayload("openai", "stream chunk", event, request.debug);
|
|
1079
|
+
if (completed)
|
|
1080
|
+
throw new Error("Responses stream emitted an event after completion");
|
|
863
1081
|
const index = event?.output_index ?? 0;
|
|
864
1082
|
switch (event?.type) {
|
|
1083
|
+
case "response.created":
|
|
1084
|
+
responseIdentity = {
|
|
1085
|
+
id: event.response?.id,
|
|
1086
|
+
model: event.response?.model
|
|
1087
|
+
};
|
|
1088
|
+
break;
|
|
1089
|
+
case "response.output_item.done":
|
|
1090
|
+
if (event.item) outputItems.set(index, event.item);
|
|
1091
|
+
if (event.item?.type === "function_call") {
|
|
1092
|
+
toolCalls.set(index, {
|
|
1093
|
+
id: event.item.call_id,
|
|
1094
|
+
name: event.item.name,
|
|
1095
|
+
arguments: event.item.arguments
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
break;
|
|
865
1099
|
case "response.output_text.delta":
|
|
866
1100
|
if (event.delta) {
|
|
1101
|
+
streamedText += event.delta;
|
|
867
1102
|
yield { type: "message:delta", content: event.delta };
|
|
868
1103
|
}
|
|
869
1104
|
break;
|
|
870
1105
|
case "response.output_item.added":
|
|
871
1106
|
if (event.item?.type === "function_call") {
|
|
872
1107
|
toolCalls.set(index, {
|
|
873
|
-
id: event.item.call_id ??
|
|
1108
|
+
id: event.item.call_id ?? "",
|
|
874
1109
|
name: event.item.name ?? "",
|
|
875
1110
|
arguments: event.item.arguments ?? ""
|
|
876
1111
|
});
|
|
@@ -889,7 +1124,10 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
889
1124
|
break;
|
|
890
1125
|
}
|
|
891
1126
|
case "response.completed": {
|
|
1127
|
+
if (event.response?.status && event.response.status !== "completed")
|
|
1128
|
+
throw new Error(`Responses stream ${event.response.status}`);
|
|
892
1129
|
completed = true;
|
|
1130
|
+
terminalResponse = { ...responseIdentity, ...event.response };
|
|
893
1131
|
const found = this.collectResponsesCitations(
|
|
894
1132
|
event.response?.output,
|
|
895
1133
|
citations.length
|
|
@@ -926,12 +1164,64 @@ var OpenAIAdapter = class _OpenAIAdapter {
|
|
|
926
1164
|
throwIfAborted(request.signal);
|
|
927
1165
|
if (!completed)
|
|
928
1166
|
throw new Error("Responses stream ended without a completed response");
|
|
1167
|
+
const output = terminalResponse.output?.length ? terminalResponse.output : [...outputItems.entries()].sort(([a], [b]) => a - b).map(([, item]) => item);
|
|
1168
|
+
if (output.some((item) => item.type === "function_call"))
|
|
1169
|
+
toolCalls.clear();
|
|
1170
|
+
for (const [index, item] of output.entries()) {
|
|
1171
|
+
if (item.type === "function_call") {
|
|
1172
|
+
toolCalls.set(index, {
|
|
1173
|
+
id: item.call_id,
|
|
1174
|
+
name: item.name,
|
|
1175
|
+
arguments: item.arguments
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
const uniqueCalls = /* @__PURE__ */ new Map();
|
|
1180
|
+
for (const call of toolCalls.values()) {
|
|
1181
|
+
if (!call.id || !call.name)
|
|
1182
|
+
throw new Error("Responses stream contains an incomplete tool call");
|
|
1183
|
+
uniqueCalls.set(call.id, call);
|
|
1184
|
+
}
|
|
1185
|
+
toolCalls.clear();
|
|
1186
|
+
[...uniqueCalls.values()].forEach(
|
|
1187
|
+
(call, index) => toolCalls.set(index, call)
|
|
1188
|
+
);
|
|
1189
|
+
if (!output.length && toolCalls.size) {
|
|
1190
|
+
for (const call of toolCalls.values())
|
|
1191
|
+
output.push({
|
|
1192
|
+
type: "function_call",
|
|
1193
|
+
call_id: call.id,
|
|
1194
|
+
name: call.name,
|
|
1195
|
+
arguments: call.arguments
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
if (!output.length && streamedText)
|
|
1199
|
+
output.push({
|
|
1200
|
+
type: "message",
|
|
1201
|
+
role: "assistant",
|
|
1202
|
+
content: [{ type: "output_text", text: streamedText, annotations: [] }]
|
|
1203
|
+
});
|
|
1204
|
+
terminalResponse.output = output;
|
|
1205
|
+
const finalText = this.parseResponsesResult(terminalResponse).content;
|
|
1206
|
+
if (finalText.startsWith(streamedText) && finalText.length > streamedText.length) {
|
|
1207
|
+
yield {
|
|
1208
|
+
type: "message:delta",
|
|
1209
|
+
content: finalText.slice(streamedText.length)
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
929
1212
|
yield* flushToolCalls();
|
|
930
1213
|
if (citations.length > 0) {
|
|
931
1214
|
yield { type: "citation", citations: deduplicateCitations(citations) };
|
|
932
1215
|
}
|
|
933
|
-
yield {
|
|
934
|
-
|
|
1216
|
+
yield {
|
|
1217
|
+
type: "message:end",
|
|
1218
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1219
|
+
};
|
|
1220
|
+
yield {
|
|
1221
|
+
type: "done",
|
|
1222
|
+
usage,
|
|
1223
|
+
providerMetadata: responseMetadata(terminalResponse)
|
|
1224
|
+
};
|
|
935
1225
|
}
|
|
936
1226
|
async *stream(request) {
|
|
937
1227
|
throwIfAborted(request.signal);
|