@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,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-
|
|
1
|
+
import { L as LanguageModel } from '../../types-Dg1Bcg1k.mjs';
|
|
2
|
+
import { a as AnthropicProviderConfig, 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
|
* Anthropic Provider - Modern Pattern
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LanguageModel } from '../../types-
|
|
2
|
-
import { a as AnthropicProviderConfig, A as AIProvider } from '../../types-
|
|
1
|
+
import { L as LanguageModel } from '../../types-Dg1Bcg1k.js';
|
|
2
|
+
import { a as AnthropicProviderConfig, 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
|
* Anthropic Provider - Modern Pattern
|
|
@@ -1,5 +1,92 @@
|
|
|
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: "text",
|
|
76
|
+
text: part.text
|
|
77
|
+
};
|
|
78
|
+
if ("fileId" in part) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
"OpenAI image file references cannot be sent to another provider"
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
type: "image",
|
|
85
|
+
source: "url" in part ? { type: "url", url: part.url } : { type: "base64", media_type: part.mediaType, data: part.data }
|
|
86
|
+
};
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
3
90
|
// src/adapters/base.ts
|
|
4
91
|
function stringifyForDebug(value) {
|
|
5
92
|
return JSON.stringify(
|
|
@@ -206,7 +293,20 @@ function messageToAnthropicContent(message) {
|
|
|
206
293
|
}
|
|
207
294
|
return blocks;
|
|
208
295
|
}
|
|
296
|
+
function extractAnthropicSystemPrompt(messages, systemPrompt) {
|
|
297
|
+
const explicit = typeof systemPrompt === "string" ? systemPrompt : "";
|
|
298
|
+
const parts = explicit ? [explicit] : [];
|
|
299
|
+
for (const message of messages) {
|
|
300
|
+
if (message.role !== "system") continue;
|
|
301
|
+
const text = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.filter(
|
|
302
|
+
(block) => block?.type === "text" && typeof block.text === "string"
|
|
303
|
+
).map((block) => block.text).filter(Boolean).join("\n") : "";
|
|
304
|
+
if (text && text !== explicit) parts.push(text);
|
|
305
|
+
}
|
|
306
|
+
return parts.join("\n");
|
|
307
|
+
}
|
|
209
308
|
function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
309
|
+
const system = extractAnthropicSystemPrompt(messages, systemPrompt);
|
|
210
310
|
const formatted = [];
|
|
211
311
|
for (let i = 0; i < messages.length; i++) {
|
|
212
312
|
const msg = messages[i];
|
|
@@ -235,7 +335,7 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
235
335
|
{
|
|
236
336
|
type: "tool_result",
|
|
237
337
|
tool_use_id: msg.tool_call_id,
|
|
238
|
-
content: msg.content ?? ""
|
|
338
|
+
content: msg.modelOutput ? toolOutputForProvider(msg.modelOutput) : msg.content ?? ""
|
|
239
339
|
}
|
|
240
340
|
];
|
|
241
341
|
while (i + 1 < messages.length && messages[i + 1].role === "tool") {
|
|
@@ -245,7 +345,7 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
245
345
|
toolResults.push({
|
|
246
346
|
type: "tool_result",
|
|
247
347
|
tool_use_id: nextTool.tool_call_id,
|
|
248
|
-
content: nextTool.content ?? ""
|
|
348
|
+
content: nextTool.modelOutput ? toolOutputForProvider(nextTool.modelOutput) : nextTool.content ?? ""
|
|
249
349
|
});
|
|
250
350
|
}
|
|
251
351
|
}
|
|
@@ -261,7 +361,7 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
261
361
|
}
|
|
262
362
|
}
|
|
263
363
|
return {
|
|
264
|
-
system
|
|
364
|
+
system,
|
|
265
365
|
messages: formatted
|
|
266
366
|
};
|
|
267
367
|
}
|
|
@@ -631,7 +731,7 @@ function formatMessagesForAnthropic2(messages) {
|
|
|
631
731
|
}
|
|
632
732
|
pendingToolResults.push({
|
|
633
733
|
toolCallId,
|
|
634
|
-
content: msg.content
|
|
734
|
+
content: msg.modelOutput ? toolOutputForProvider(msg.modelOutput) : msg.content
|
|
635
735
|
});
|
|
636
736
|
}
|
|
637
737
|
}
|
|
@@ -750,7 +850,7 @@ var AnthropicAdapter = class {
|
|
|
750
850
|
}
|
|
751
851
|
pendingToolResults.push({
|
|
752
852
|
tool_use_id: toolCallId,
|
|
753
|
-
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
|
|
853
|
+
content: msg.modelOutput ? toolOutputForProvider(msg.modelOutput) : typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
|
|
754
854
|
});
|
|
755
855
|
} else if (msg.role === "user") {
|
|
756
856
|
if (pendingToolResults.length > 0) {
|
|
@@ -871,14 +971,23 @@ var AnthropicAdapter = class {
|
|
|
871
971
|
buildRequestOptions(request) {
|
|
872
972
|
const responseFormat = request.config?.responseFormat;
|
|
873
973
|
const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text." : "";
|
|
874
|
-
|
|
974
|
+
let systemMessage;
|
|
875
975
|
let messages;
|
|
876
976
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
977
|
+
systemMessage = extractAnthropicSystemPrompt(
|
|
978
|
+
request.rawMessages,
|
|
979
|
+
request.systemPrompt
|
|
980
|
+
);
|
|
877
981
|
messages = this.convertToAnthropicMessages(request.rawMessages);
|
|
878
982
|
} else {
|
|
879
|
-
const formatted = formatMessagesForAnthropic(
|
|
983
|
+
const formatted = formatMessagesForAnthropic(
|
|
984
|
+
request.messages,
|
|
985
|
+
request.systemPrompt
|
|
986
|
+
);
|
|
987
|
+
systemMessage = formatted.system;
|
|
880
988
|
messages = formatted.messages;
|
|
881
989
|
}
|
|
990
|
+
systemMessage += jsonObjectSuffix;
|
|
882
991
|
const anthropicNativeSearch = request.providerToolOptions?.anthropic?.nativeToolSearch;
|
|
883
992
|
const tools = anthropicNativeSearch?.enabled ? this.buildNativeSearchTools(
|
|
884
993
|
request.toolDefinitions ?? [],
|
|
@@ -1,3 +1,90 @@
|
|
|
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: "text",
|
|
74
|
+
text: part.text
|
|
75
|
+
};
|
|
76
|
+
if ("fileId" in part) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
"OpenAI image file references cannot be sent to another provider"
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
type: "image",
|
|
83
|
+
source: "url" in part ? { type: "url", url: part.url } : { type: "base64", media_type: part.mediaType, data: part.data }
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
1
88
|
// src/adapters/base.ts
|
|
2
89
|
function stringifyForDebug(value) {
|
|
3
90
|
return JSON.stringify(
|
|
@@ -204,7 +291,20 @@ function messageToAnthropicContent(message) {
|
|
|
204
291
|
}
|
|
205
292
|
return blocks;
|
|
206
293
|
}
|
|
294
|
+
function extractAnthropicSystemPrompt(messages, systemPrompt) {
|
|
295
|
+
const explicit = typeof systemPrompt === "string" ? systemPrompt : "";
|
|
296
|
+
const parts = explicit ? [explicit] : [];
|
|
297
|
+
for (const message of messages) {
|
|
298
|
+
if (message.role !== "system") continue;
|
|
299
|
+
const text = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content.filter(
|
|
300
|
+
(block) => block?.type === "text" && typeof block.text === "string"
|
|
301
|
+
).map((block) => block.text).filter(Boolean).join("\n") : "";
|
|
302
|
+
if (text && text !== explicit) parts.push(text);
|
|
303
|
+
}
|
|
304
|
+
return parts.join("\n");
|
|
305
|
+
}
|
|
207
306
|
function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
307
|
+
const system = extractAnthropicSystemPrompt(messages, systemPrompt);
|
|
208
308
|
const formatted = [];
|
|
209
309
|
for (let i = 0; i < messages.length; i++) {
|
|
210
310
|
const msg = messages[i];
|
|
@@ -233,7 +333,7 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
233
333
|
{
|
|
234
334
|
type: "tool_result",
|
|
235
335
|
tool_use_id: msg.tool_call_id,
|
|
236
|
-
content: msg.content ?? ""
|
|
336
|
+
content: msg.modelOutput ? toolOutputForProvider(msg.modelOutput) : msg.content ?? ""
|
|
237
337
|
}
|
|
238
338
|
];
|
|
239
339
|
while (i + 1 < messages.length && messages[i + 1].role === "tool") {
|
|
@@ -243,7 +343,7 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
243
343
|
toolResults.push({
|
|
244
344
|
type: "tool_result",
|
|
245
345
|
tool_use_id: nextTool.tool_call_id,
|
|
246
|
-
content: nextTool.content ?? ""
|
|
346
|
+
content: nextTool.modelOutput ? toolOutputForProvider(nextTool.modelOutput) : nextTool.content ?? ""
|
|
247
347
|
});
|
|
248
348
|
}
|
|
249
349
|
}
|
|
@@ -259,7 +359,7 @@ function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
|
259
359
|
}
|
|
260
360
|
}
|
|
261
361
|
return {
|
|
262
|
-
system
|
|
362
|
+
system,
|
|
263
363
|
messages: formatted
|
|
264
364
|
};
|
|
265
365
|
}
|
|
@@ -629,7 +729,7 @@ function formatMessagesForAnthropic2(messages) {
|
|
|
629
729
|
}
|
|
630
730
|
pendingToolResults.push({
|
|
631
731
|
toolCallId,
|
|
632
|
-
content: msg.content
|
|
732
|
+
content: msg.modelOutput ? toolOutputForProvider(msg.modelOutput) : msg.content
|
|
633
733
|
});
|
|
634
734
|
}
|
|
635
735
|
}
|
|
@@ -748,7 +848,7 @@ var AnthropicAdapter = class {
|
|
|
748
848
|
}
|
|
749
849
|
pendingToolResults.push({
|
|
750
850
|
tool_use_id: toolCallId,
|
|
751
|
-
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
|
|
851
|
+
content: msg.modelOutput ? toolOutputForProvider(msg.modelOutput) : typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
|
|
752
852
|
});
|
|
753
853
|
} else if (msg.role === "user") {
|
|
754
854
|
if (pendingToolResults.length > 0) {
|
|
@@ -869,14 +969,23 @@ var AnthropicAdapter = class {
|
|
|
869
969
|
buildRequestOptions(request) {
|
|
870
970
|
const responseFormat = request.config?.responseFormat;
|
|
871
971
|
const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text." : "";
|
|
872
|
-
|
|
972
|
+
let systemMessage;
|
|
873
973
|
let messages;
|
|
874
974
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
975
|
+
systemMessage = extractAnthropicSystemPrompt(
|
|
976
|
+
request.rawMessages,
|
|
977
|
+
request.systemPrompt
|
|
978
|
+
);
|
|
875
979
|
messages = this.convertToAnthropicMessages(request.rawMessages);
|
|
876
980
|
} else {
|
|
877
|
-
const formatted = formatMessagesForAnthropic(
|
|
981
|
+
const formatted = formatMessagesForAnthropic(
|
|
982
|
+
request.messages,
|
|
983
|
+
request.systemPrompt
|
|
984
|
+
);
|
|
985
|
+
systemMessage = formatted.system;
|
|
878
986
|
messages = formatted.messages;
|
|
879
987
|
}
|
|
988
|
+
systemMessage += jsonObjectSuffix;
|
|
880
989
|
const anthropicNativeSearch = request.providerToolOptions?.anthropic?.nativeToolSearch;
|
|
881
990
|
const tools = anthropicNativeSearch?.enabled ? this.buildNativeSearchTools(
|
|
882
991
|
request.toolDefinitions ?? [],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { b as AzureProviderConfig, A as AIProvider } from '../../types-
|
|
2
|
-
import '../../types-
|
|
1
|
+
import { b as AzureProviderConfig, A as AIProvider } from '../../types-DHQEMFHA.mjs';
|
|
2
|
+
import '../../types-Dg1Bcg1k.mjs';
|
|
3
3
|
import 'zod';
|
|
4
|
-
import '../../base-
|
|
4
|
+
import '../../base-BICaQaRS.mjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Azure OpenAI Provider
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { b as AzureProviderConfig, A as AIProvider } from '../../types-
|
|
2
|
-
import '../../types-
|
|
1
|
+
import { b as AzureProviderConfig, A as AIProvider } from '../../types-Dikj3En4.js';
|
|
2
|
+
import '../../types-Dg1Bcg1k.js';
|
|
3
3
|
import 'zod';
|
|
4
|
-
import '../../base-
|
|
4
|
+
import '../../base-CpRPB8u8.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Azure OpenAI Provider
|
|
@@ -1,5 +1,90 @@
|
|
|
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: "text",
|
|
76
|
+
text: part.text
|
|
77
|
+
};
|
|
78
|
+
throw new Error(
|
|
79
|
+
"Image tool results require OpenAI Responses or Anthropic; this endpoint is not supported"
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function textToolOutput(value, fallback) {
|
|
84
|
+
if (value === void 0) return fallback;
|
|
85
|
+
return toolOutputForProvider(value).map((part) => part.text).join("\n");
|
|
86
|
+
}
|
|
87
|
+
|
|
3
88
|
// src/core/utils.ts
|
|
4
89
|
function generateId(prefix = "id") {
|
|
5
90
|
return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
@@ -189,7 +274,7 @@ function messageToOpenAIContent(message) {
|
|
|
189
274
|
}
|
|
190
275
|
return blocks;
|
|
191
276
|
}
|
|
192
|
-
function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
277
|
+
function formatMessagesForOpenAI(messages, systemPrompt, preserveProviderMetadata = false) {
|
|
193
278
|
const formatted = [];
|
|
194
279
|
if (systemPrompt) {
|
|
195
280
|
formatted.push({ role: "system", content: systemPrompt });
|
|
@@ -207,7 +292,8 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
207
292
|
const assistantMsg = {
|
|
208
293
|
role: "assistant",
|
|
209
294
|
// Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
|
|
210
|
-
content: hasToolCalls ? msg.content || null : msg.content
|
|
295
|
+
content: hasToolCalls ? msg.content || null : msg.content,
|
|
296
|
+
...preserveProviderMetadata && msg.providerMetadata ? { providerMetadata: msg.providerMetadata } : {}
|
|
211
297
|
};
|
|
212
298
|
if (hasToolCalls) {
|
|
213
299
|
assistantMsg.tool_calls = msg.tool_calls;
|
|
@@ -216,7 +302,8 @@ function formatMessagesForOpenAI(messages, systemPrompt) {
|
|
|
216
302
|
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
217
303
|
formatted.push({
|
|
218
304
|
role: "tool",
|
|
219
|
-
content: msg.content ?? "",
|
|
305
|
+
content: preserveProviderMetadata ? msg.content ?? "" : textToolOutput(msg.modelOutput, msg.content ?? ""),
|
|
306
|
+
...preserveProviderMetadata && msg.modelOutput ? { modelOutput: msg.modelOutput } : {},
|
|
220
307
|
tool_call_id: msg.tool_call_id
|
|
221
308
|
});
|
|
222
309
|
}
|
|
@@ -256,6 +343,13 @@ var AzureAdapter = class {
|
|
|
256
343
|
let messages;
|
|
257
344
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
258
345
|
const processedMessages = request.rawMessages.map((msg) => {
|
|
346
|
+
const { modelOutput, ...rest } = msg;
|
|
347
|
+
msg = {
|
|
348
|
+
...rest,
|
|
349
|
+
...msg.role === "tool" ? {
|
|
350
|
+
content: textToolOutput(modelOutput, String(msg.content ?? ""))
|
|
351
|
+
} : {}
|
|
352
|
+
};
|
|
259
353
|
const hasAttachments = msg.attachments && Array.isArray(msg.attachments) && msg.attachments.length > 0;
|
|
260
354
|
if (hasAttachments) {
|
|
261
355
|
const content = [];
|
|
@@ -386,7 +480,10 @@ var AzureAdapter = class {
|
|
|
386
480
|
const client = await this.getClient();
|
|
387
481
|
let messages;
|
|
388
482
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
389
|
-
messages = request.rawMessages
|
|
483
|
+
messages = request.rawMessages.map(({ modelOutput, ...msg }) => ({
|
|
484
|
+
...msg,
|
|
485
|
+
...msg.role === "tool" ? { content: textToolOutput(modelOutput, String(msg.content ?? "")) } : {}
|
|
486
|
+
}));
|
|
390
487
|
if (request.systemPrompt) {
|
|
391
488
|
const hasSystem = messages.some((m) => m.role === "system");
|
|
392
489
|
if (!hasSystem) {
|