@yourgpt/llm-sdk 2.5.0 → 2.5.1-beta.1
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 +19 -1
- package/dist/adapters/index.d.mts +4 -4
- package/dist/adapters/index.d.ts +4 -4
- package/dist/adapters/index.js +293 -23
- package/dist/adapters/index.mjs +293 -23
- package/dist/base-BYQKp9TW.d.mts +263 -0
- package/dist/base-Cxq3ni0t.d.ts +263 -0
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/index.d.mts +61 -8
- package/dist/index.d.ts +61 -8
- package/dist/index.js +71 -0
- package/dist/index.mjs +71 -0
- package/dist/providers/anthropic/index.d.mts +3 -3
- package/dist/providers/anthropic/index.d.ts +3 -3
- package/dist/providers/anthropic/index.js +360 -203
- package/dist/providers/anthropic/index.mjs +360 -203
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/azure/index.js +49 -1
- package/dist/providers/azure/index.mjs +49 -1
- package/dist/providers/fireworks/index.d.mts +1 -1
- package/dist/providers/fireworks/index.d.ts +1 -1
- package/dist/providers/fireworks/index.js +56 -0
- package/dist/providers/fireworks/index.mjs +56 -0
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +303 -207
- package/dist/providers/google/index.mjs +303 -207
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/ollama/index.js +10 -2
- package/dist/providers/ollama/index.mjs +10 -2
- package/dist/providers/openai/index.d.mts +3 -3
- package/dist/providers/openai/index.d.ts +3 -3
- package/dist/providers/openai/index.js +318 -216
- package/dist/providers/openai/index.mjs +318 -216
- package/dist/providers/openrouter/index.d.mts +3 -3
- package/dist/providers/openrouter/index.d.ts +3 -3
- package/dist/providers/openrouter/index.js +308 -206
- package/dist/providers/openrouter/index.mjs +308 -206
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +308 -206
- package/dist/providers/togetherai/index.mjs +308 -206
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +307 -210
- package/dist/providers/xai/index.mjs +307 -210
- package/dist/{types-BctsnC3g.d.ts → types-BvkiJ1dd.d.mts} +2 -1
- package/dist/{types-38yolWJn.d.ts → types-ChORafYS.d.ts} +1 -1
- package/dist/types-D774b0dg.d.mts +1018 -0
- package/dist/types-D774b0dg.d.ts +1018 -0
- package/dist/{types-DRqxMIjF.d.mts → types-TMilS-Dz.d.ts} +2 -1
- package/dist/{types-D4YfrQJR.d.mts → types-mwMhCwOq.d.mts} +1 -1
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/base-D-U61JaB.d.mts +0 -788
- package/dist/base-iGi9Va6Z.d.ts +0 -788
- package/dist/types-CR8mi9I0.d.mts +0 -417
- package/dist/types-CR8mi9I0.d.ts +0 -417
|
@@ -1,3 +1,298 @@
|
|
|
1
|
+
// src/adapters/base.ts
|
|
2
|
+
function stringifyForDebug(value) {
|
|
3
|
+
return JSON.stringify(
|
|
4
|
+
value,
|
|
5
|
+
(_key, currentValue) => {
|
|
6
|
+
if (typeof currentValue === "bigint") {
|
|
7
|
+
return currentValue.toString();
|
|
8
|
+
}
|
|
9
|
+
if (currentValue instanceof Error) {
|
|
10
|
+
return {
|
|
11
|
+
name: currentValue.name,
|
|
12
|
+
message: currentValue.message,
|
|
13
|
+
stack: currentValue.stack
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return currentValue;
|
|
17
|
+
},
|
|
18
|
+
2
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
function logProviderPayload(provider, label, payload, enabled) {
|
|
22
|
+
if (!enabled) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (label.toLowerCase().includes("stream ")) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
console.log(
|
|
30
|
+
`[llm-sdk:${provider}] ${label}
|
|
31
|
+
${stringifyForDebug(payload)}`
|
|
32
|
+
);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.log(
|
|
35
|
+
`[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
|
|
36
|
+
error
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function stripSchemaKeys(schema, keysToDrop, options = {}) {
|
|
41
|
+
if (Array.isArray(schema)) {
|
|
42
|
+
return schema.map((item) => stripSchemaKeys(item, keysToDrop, options));
|
|
43
|
+
}
|
|
44
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
45
|
+
const out = {};
|
|
46
|
+
for (const [key, value] of Object.entries(
|
|
47
|
+
schema
|
|
48
|
+
)) {
|
|
49
|
+
if (keysToDrop.has(key)) continue;
|
|
50
|
+
const renamed = options.renameKeys?.[key] ?? key;
|
|
51
|
+
out[renamed] = stripSchemaKeys(value, keysToDrop, options);
|
|
52
|
+
}
|
|
53
|
+
if (options.forceAdditionalPropertiesFalse && out.type === "object") {
|
|
54
|
+
out.additionalProperties = false;
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
var ANTHROPIC_UNSUPPORTED_KEYS = /* @__PURE__ */ new Set([
|
|
59
|
+
"minimum",
|
|
60
|
+
"maximum",
|
|
61
|
+
"exclusiveMinimum",
|
|
62
|
+
"exclusiveMaximum",
|
|
63
|
+
"multipleOf",
|
|
64
|
+
"minLength",
|
|
65
|
+
"maxLength",
|
|
66
|
+
"minItems",
|
|
67
|
+
"maxItems",
|
|
68
|
+
"minProperties",
|
|
69
|
+
"maxProperties",
|
|
70
|
+
"pattern",
|
|
71
|
+
"$schema"
|
|
72
|
+
]);
|
|
73
|
+
function toAnthropicOutputConfig(rf) {
|
|
74
|
+
if (!rf || rf.type !== "json_schema") return void 0;
|
|
75
|
+
const schema = stripSchemaKeys(
|
|
76
|
+
rf.json_schema.schema,
|
|
77
|
+
ANTHROPIC_UNSUPPORTED_KEYS,
|
|
78
|
+
{
|
|
79
|
+
forceAdditionalPropertiesFalse: true,
|
|
80
|
+
renameKeys: { oneOf: "anyOf" }
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
return {
|
|
84
|
+
format: {
|
|
85
|
+
type: "json_schema",
|
|
86
|
+
schema
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function toAnthropicMcp(mcpServers) {
|
|
91
|
+
if (!mcpServers || mcpServers.length === 0) {
|
|
92
|
+
return { mcpServers: [], tools: [], betas: [] };
|
|
93
|
+
}
|
|
94
|
+
const serverEntries = [];
|
|
95
|
+
const toolEntries = [];
|
|
96
|
+
for (const mcp of mcpServers) {
|
|
97
|
+
const authHeader = mcp.headers?.Authorization ?? mcp.headers?.authorization;
|
|
98
|
+
const token = authHeader?.replace(/^Bearer\s+/i, "");
|
|
99
|
+
serverEntries.push({
|
|
100
|
+
type: "url",
|
|
101
|
+
url: mcp.url,
|
|
102
|
+
name: mcp.label,
|
|
103
|
+
...token ? { authorization_token: token } : {}
|
|
104
|
+
});
|
|
105
|
+
if (mcp.allowedTools && mcp.allowedTools.length > 0) {
|
|
106
|
+
toolEntries.push({
|
|
107
|
+
type: "mcp_toolset",
|
|
108
|
+
mcp_server_name: mcp.label,
|
|
109
|
+
configs: Object.fromEntries(
|
|
110
|
+
mcp.allowedTools.map((toolName) => [toolName, {}])
|
|
111
|
+
)
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
mcpServers: serverEntries,
|
|
117
|
+
tools: toolEntries,
|
|
118
|
+
betas: ["mcp-client-2025-11-20"]
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function isStringEffort(effort) {
|
|
122
|
+
return typeof effort === "string" && (effort === "minimal" || effort === "low" || effort === "medium" || effort === "high");
|
|
123
|
+
}
|
|
124
|
+
var ANTHROPIC_ADAPTIVE_MODELS = /(claude-opus-4-7|claude-opus-4-6|claude-sonnet-4-6)/i;
|
|
125
|
+
function toAnthropicThinking(effort, modelId) {
|
|
126
|
+
if (!effort) return {};
|
|
127
|
+
if (typeof effort === "object" && "raw" in effort) {
|
|
128
|
+
return { thinking: effort.raw };
|
|
129
|
+
}
|
|
130
|
+
const isAdaptive = !!modelId && ANTHROPIC_ADAPTIVE_MODELS.test(modelId);
|
|
131
|
+
if (typeof effort === "object" && "budgetTokens" in effort) {
|
|
132
|
+
return {
|
|
133
|
+
thinking: { type: "enabled", budget_tokens: effort.budgetTokens }
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (!isStringEffort(effort)) return {};
|
|
137
|
+
if (isAdaptive) {
|
|
138
|
+
const mapped = effort === "minimal" ? "low" : effort;
|
|
139
|
+
return {
|
|
140
|
+
thinking: { type: "adaptive" },
|
|
141
|
+
outputConfigEffort: mapped
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const budget = effort === "high" ? 16e3 : effort === "medium" ? 8e3 : effort === "low" ? 4e3 : 2048;
|
|
145
|
+
return { thinking: { type: "enabled", budget_tokens: budget } };
|
|
146
|
+
}
|
|
147
|
+
function hasMediaAttachments(message) {
|
|
148
|
+
const attachments = message.metadata?.attachments;
|
|
149
|
+
return attachments?.some(
|
|
150
|
+
(a) => a.type === "image" || a.type === "file" && a.mimeType === "application/pdf"
|
|
151
|
+
) ?? false;
|
|
152
|
+
}
|
|
153
|
+
function attachmentToAnthropicImage(attachment) {
|
|
154
|
+
if (attachment.type !== "image") return null;
|
|
155
|
+
if (attachment.url) {
|
|
156
|
+
return {
|
|
157
|
+
type: "image",
|
|
158
|
+
source: {
|
|
159
|
+
type: "url",
|
|
160
|
+
url: attachment.url
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (!attachment.data) return null;
|
|
165
|
+
let base64Data = attachment.data;
|
|
166
|
+
if (base64Data.startsWith("data:")) {
|
|
167
|
+
const commaIndex = base64Data.indexOf(",");
|
|
168
|
+
if (commaIndex !== -1) {
|
|
169
|
+
base64Data = base64Data.slice(commaIndex + 1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
type: "image",
|
|
174
|
+
source: {
|
|
175
|
+
type: "base64",
|
|
176
|
+
media_type: attachment.mimeType || "image/png",
|
|
177
|
+
data: base64Data
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function attachmentToAnthropicDocument(attachment) {
|
|
182
|
+
if (attachment.type !== "file" || attachment.mimeType !== "application/pdf") {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
if (attachment.url) {
|
|
186
|
+
return {
|
|
187
|
+
type: "document",
|
|
188
|
+
source: {
|
|
189
|
+
type: "url",
|
|
190
|
+
url: attachment.url
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
if (!attachment.data) return null;
|
|
195
|
+
let base64Data = attachment.data;
|
|
196
|
+
if (base64Data.startsWith("data:")) {
|
|
197
|
+
const commaIndex = base64Data.indexOf(",");
|
|
198
|
+
if (commaIndex !== -1) {
|
|
199
|
+
base64Data = base64Data.slice(commaIndex + 1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
type: "document",
|
|
204
|
+
source: {
|
|
205
|
+
type: "base64",
|
|
206
|
+
media_type: "application/pdf",
|
|
207
|
+
data: base64Data
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function messageToAnthropicContent(message) {
|
|
212
|
+
const attachments = message.metadata?.attachments;
|
|
213
|
+
const content = message.content ?? "";
|
|
214
|
+
if (!hasMediaAttachments(message)) {
|
|
215
|
+
return content;
|
|
216
|
+
}
|
|
217
|
+
const blocks = [];
|
|
218
|
+
if (attachments) {
|
|
219
|
+
for (const attachment of attachments) {
|
|
220
|
+
const imageBlock = attachmentToAnthropicImage(attachment);
|
|
221
|
+
if (imageBlock) {
|
|
222
|
+
blocks.push(imageBlock);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const docBlock = attachmentToAnthropicDocument(attachment);
|
|
226
|
+
if (docBlock) {
|
|
227
|
+
blocks.push(docBlock);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (content) {
|
|
232
|
+
blocks.push({ type: "text", text: content });
|
|
233
|
+
}
|
|
234
|
+
return blocks;
|
|
235
|
+
}
|
|
236
|
+
function formatMessagesForAnthropic(messages, systemPrompt) {
|
|
237
|
+
const formatted = [];
|
|
238
|
+
for (let i = 0; i < messages.length; i++) {
|
|
239
|
+
const msg = messages[i];
|
|
240
|
+
if (msg.role === "system") continue;
|
|
241
|
+
if (msg.role === "assistant") {
|
|
242
|
+
const content = [];
|
|
243
|
+
if (msg.content) {
|
|
244
|
+
content.push({ type: "text", text: msg.content });
|
|
245
|
+
}
|
|
246
|
+
if (msg.tool_calls && msg.tool_calls.length > 0) {
|
|
247
|
+
for (const tc of msg.tool_calls) {
|
|
248
|
+
content.push({
|
|
249
|
+
type: "tool_use",
|
|
250
|
+
id: tc.id,
|
|
251
|
+
name: tc.function.name,
|
|
252
|
+
input: JSON.parse(tc.function.arguments)
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
formatted.push({
|
|
257
|
+
role: "assistant",
|
|
258
|
+
content: content.length === 1 && content[0].type === "text" ? content[0].text : content
|
|
259
|
+
});
|
|
260
|
+
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
261
|
+
const toolResults = [
|
|
262
|
+
{
|
|
263
|
+
type: "tool_result",
|
|
264
|
+
tool_use_id: msg.tool_call_id,
|
|
265
|
+
content: msg.content ?? ""
|
|
266
|
+
}
|
|
267
|
+
];
|
|
268
|
+
while (i + 1 < messages.length && messages[i + 1].role === "tool") {
|
|
269
|
+
i++;
|
|
270
|
+
const nextTool = messages[i];
|
|
271
|
+
if (nextTool.tool_call_id) {
|
|
272
|
+
toolResults.push({
|
|
273
|
+
type: "tool_result",
|
|
274
|
+
tool_use_id: nextTool.tool_call_id,
|
|
275
|
+
content: nextTool.content ?? ""
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
formatted.push({
|
|
280
|
+
role: "user",
|
|
281
|
+
content: toolResults
|
|
282
|
+
});
|
|
283
|
+
} else if (msg.role === "user") {
|
|
284
|
+
formatted.push({
|
|
285
|
+
role: "user",
|
|
286
|
+
content: messageToAnthropicContent(msg)
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
system: "",
|
|
292
|
+
messages: formatted
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
1
296
|
// src/providers/anthropic/provider.ts
|
|
2
297
|
var ANTHROPIC_MODELS = {
|
|
3
298
|
// Claude 4 series
|
|
@@ -6,6 +301,7 @@ var ANTHROPIC_MODELS = {
|
|
|
6
301
|
tools: true,
|
|
7
302
|
thinking: true,
|
|
8
303
|
pdf: true,
|
|
304
|
+
jsonMode: true,
|
|
9
305
|
maxTokens: 2e5
|
|
10
306
|
},
|
|
11
307
|
"claude-opus-4-20250514": {
|
|
@@ -13,6 +309,7 @@ var ANTHROPIC_MODELS = {
|
|
|
13
309
|
tools: true,
|
|
14
310
|
thinking: true,
|
|
15
311
|
pdf: true,
|
|
312
|
+
jsonMode: true,
|
|
16
313
|
maxTokens: 2e5
|
|
17
314
|
},
|
|
18
315
|
// Claude 3.7 series
|
|
@@ -21,6 +318,7 @@ var ANTHROPIC_MODELS = {
|
|
|
21
318
|
tools: true,
|
|
22
319
|
thinking: true,
|
|
23
320
|
pdf: true,
|
|
321
|
+
jsonMode: true,
|
|
24
322
|
maxTokens: 2e5
|
|
25
323
|
},
|
|
26
324
|
"claude-3-7-sonnet-latest": {
|
|
@@ -28,6 +326,7 @@ var ANTHROPIC_MODELS = {
|
|
|
28
326
|
tools: true,
|
|
29
327
|
thinking: true,
|
|
30
328
|
pdf: true,
|
|
329
|
+
jsonMode: true,
|
|
31
330
|
maxTokens: 2e5
|
|
32
331
|
},
|
|
33
332
|
// Claude 3.5 series
|
|
@@ -36,6 +335,7 @@ var ANTHROPIC_MODELS = {
|
|
|
36
335
|
tools: true,
|
|
37
336
|
thinking: false,
|
|
38
337
|
pdf: true,
|
|
338
|
+
jsonMode: true,
|
|
39
339
|
maxTokens: 2e5
|
|
40
340
|
},
|
|
41
341
|
"claude-3-5-sonnet-latest": {
|
|
@@ -43,6 +343,7 @@ var ANTHROPIC_MODELS = {
|
|
|
43
343
|
tools: true,
|
|
44
344
|
thinking: false,
|
|
45
345
|
pdf: true,
|
|
346
|
+
jsonMode: true,
|
|
46
347
|
maxTokens: 2e5
|
|
47
348
|
},
|
|
48
349
|
"claude-3-5-haiku-20241022": {
|
|
@@ -50,6 +351,7 @@ var ANTHROPIC_MODELS = {
|
|
|
50
351
|
tools: true,
|
|
51
352
|
thinking: false,
|
|
52
353
|
pdf: false,
|
|
354
|
+
jsonMode: true,
|
|
53
355
|
maxTokens: 2e5
|
|
54
356
|
},
|
|
55
357
|
"claude-3-5-haiku-latest": {
|
|
@@ -57,6 +359,7 @@ var ANTHROPIC_MODELS = {
|
|
|
57
359
|
tools: true,
|
|
58
360
|
thinking: false,
|
|
59
361
|
pdf: false,
|
|
362
|
+
jsonMode: true,
|
|
60
363
|
maxTokens: 2e5
|
|
61
364
|
},
|
|
62
365
|
// Claude 3 series
|
|
@@ -65,6 +368,7 @@ var ANTHROPIC_MODELS = {
|
|
|
65
368
|
tools: true,
|
|
66
369
|
thinking: false,
|
|
67
370
|
pdf: false,
|
|
371
|
+
jsonMode: false,
|
|
68
372
|
maxTokens: 2e5
|
|
69
373
|
},
|
|
70
374
|
"claude-3-sonnet-20240229": {
|
|
@@ -72,6 +376,7 @@ var ANTHROPIC_MODELS = {
|
|
|
72
376
|
tools: true,
|
|
73
377
|
thinking: false,
|
|
74
378
|
pdf: false,
|
|
379
|
+
jsonMode: false,
|
|
75
380
|
maxTokens: 2e5
|
|
76
381
|
},
|
|
77
382
|
"claude-3-haiku-20240307": {
|
|
@@ -79,6 +384,7 @@ var ANTHROPIC_MODELS = {
|
|
|
79
384
|
tools: true,
|
|
80
385
|
thinking: false,
|
|
81
386
|
pdf: false,
|
|
387
|
+
jsonMode: false,
|
|
82
388
|
maxTokens: 2e5
|
|
83
389
|
}
|
|
84
390
|
};
|
|
@@ -103,7 +409,7 @@ function anthropic(modelId, options = {}) {
|
|
|
103
409
|
supportsVision: modelConfig.vision,
|
|
104
410
|
supportsTools: modelConfig.tools,
|
|
105
411
|
supportsStreaming: true,
|
|
106
|
-
supportsJsonMode:
|
|
412
|
+
supportsJsonMode: modelConfig.jsonMode,
|
|
107
413
|
supportsThinking: modelConfig.thinking,
|
|
108
414
|
supportsPDF: modelConfig.pdf,
|
|
109
415
|
maxTokens: modelConfig.maxTokens,
|
|
@@ -111,7 +417,7 @@ function anthropic(modelId, options = {}) {
|
|
|
111
417
|
},
|
|
112
418
|
async doGenerate(params) {
|
|
113
419
|
const client2 = await getClient();
|
|
114
|
-
const { system, messages } =
|
|
420
|
+
const { system, messages } = formatMessagesForAnthropic2(params.messages);
|
|
115
421
|
const requestOptions = {
|
|
116
422
|
model: modelId,
|
|
117
423
|
max_tokens: params.maxTokens ?? 4096,
|
|
@@ -128,6 +434,10 @@ function anthropic(modelId, options = {}) {
|
|
|
128
434
|
budget_tokens: options.thinking.budgetTokens ?? 1e4
|
|
129
435
|
};
|
|
130
436
|
}
|
|
437
|
+
const outputConfig = toAnthropicOutputConfig(params.responseFormat);
|
|
438
|
+
if (outputConfig) {
|
|
439
|
+
requestOptions.output_config = outputConfig;
|
|
440
|
+
}
|
|
131
441
|
const response = await client2.messages.create(requestOptions);
|
|
132
442
|
let text = "";
|
|
133
443
|
const toolCalls = [];
|
|
@@ -156,7 +466,7 @@ function anthropic(modelId, options = {}) {
|
|
|
156
466
|
},
|
|
157
467
|
async *doStream(params) {
|
|
158
468
|
const client2 = await getClient();
|
|
159
|
-
const { system, messages } =
|
|
469
|
+
const { system, messages } = formatMessagesForAnthropic2(params.messages);
|
|
160
470
|
const requestOptions = {
|
|
161
471
|
model: modelId,
|
|
162
472
|
max_tokens: params.maxTokens ?? 4096,
|
|
@@ -173,6 +483,10 @@ function anthropic(modelId, options = {}) {
|
|
|
173
483
|
budget_tokens: options.thinking.budgetTokens ?? 1e4
|
|
174
484
|
};
|
|
175
485
|
}
|
|
486
|
+
const outputConfig = toAnthropicOutputConfig(params.responseFormat);
|
|
487
|
+
if (outputConfig) {
|
|
488
|
+
requestOptions.output_config = outputConfig;
|
|
489
|
+
}
|
|
176
490
|
const stream = await client2.messages.stream(requestOptions);
|
|
177
491
|
let currentToolUse = null;
|
|
178
492
|
let inputTokens = 0;
|
|
@@ -251,7 +565,7 @@ function mapFinishReason(reason) {
|
|
|
251
565
|
return "unknown";
|
|
252
566
|
}
|
|
253
567
|
}
|
|
254
|
-
function
|
|
568
|
+
function formatMessagesForAnthropic2(messages) {
|
|
255
569
|
let system = "";
|
|
256
570
|
const formatted = [];
|
|
257
571
|
const pendingToolResults = [];
|
|
@@ -360,194 +674,6 @@ function generateMessageId() {
|
|
|
360
674
|
return generateId("msg");
|
|
361
675
|
}
|
|
362
676
|
|
|
363
|
-
// src/adapters/base.ts
|
|
364
|
-
function stringifyForDebug(value) {
|
|
365
|
-
return JSON.stringify(
|
|
366
|
-
value,
|
|
367
|
-
(_key, currentValue) => {
|
|
368
|
-
if (typeof currentValue === "bigint") {
|
|
369
|
-
return currentValue.toString();
|
|
370
|
-
}
|
|
371
|
-
if (currentValue instanceof Error) {
|
|
372
|
-
return {
|
|
373
|
-
name: currentValue.name,
|
|
374
|
-
message: currentValue.message,
|
|
375
|
-
stack: currentValue.stack
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
return currentValue;
|
|
379
|
-
},
|
|
380
|
-
2
|
|
381
|
-
);
|
|
382
|
-
}
|
|
383
|
-
function logProviderPayload(provider, label, payload, enabled) {
|
|
384
|
-
if (!enabled) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
if (label.toLowerCase().includes("stream ")) {
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
try {
|
|
391
|
-
console.log(
|
|
392
|
-
`[llm-sdk:${provider}] ${label}
|
|
393
|
-
${stringifyForDebug(payload)}`
|
|
394
|
-
);
|
|
395
|
-
} catch (error) {
|
|
396
|
-
console.log(
|
|
397
|
-
`[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
|
|
398
|
-
error
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
function hasMediaAttachments(message) {
|
|
403
|
-
const attachments = message.metadata?.attachments;
|
|
404
|
-
return attachments?.some(
|
|
405
|
-
(a) => a.type === "image" || a.type === "file" && a.mimeType === "application/pdf"
|
|
406
|
-
) ?? false;
|
|
407
|
-
}
|
|
408
|
-
function attachmentToAnthropicImage(attachment) {
|
|
409
|
-
if (attachment.type !== "image") return null;
|
|
410
|
-
if (attachment.url) {
|
|
411
|
-
return {
|
|
412
|
-
type: "image",
|
|
413
|
-
source: {
|
|
414
|
-
type: "url",
|
|
415
|
-
url: attachment.url
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
if (!attachment.data) return null;
|
|
420
|
-
let base64Data = attachment.data;
|
|
421
|
-
if (base64Data.startsWith("data:")) {
|
|
422
|
-
const commaIndex = base64Data.indexOf(",");
|
|
423
|
-
if (commaIndex !== -1) {
|
|
424
|
-
base64Data = base64Data.slice(commaIndex + 1);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
return {
|
|
428
|
-
type: "image",
|
|
429
|
-
source: {
|
|
430
|
-
type: "base64",
|
|
431
|
-
media_type: attachment.mimeType || "image/png",
|
|
432
|
-
data: base64Data
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
function attachmentToAnthropicDocument(attachment) {
|
|
437
|
-
if (attachment.type !== "file" || attachment.mimeType !== "application/pdf") {
|
|
438
|
-
return null;
|
|
439
|
-
}
|
|
440
|
-
if (attachment.url) {
|
|
441
|
-
return {
|
|
442
|
-
type: "document",
|
|
443
|
-
source: {
|
|
444
|
-
type: "url",
|
|
445
|
-
url: attachment.url
|
|
446
|
-
}
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
|
-
if (!attachment.data) return null;
|
|
450
|
-
let base64Data = attachment.data;
|
|
451
|
-
if (base64Data.startsWith("data:")) {
|
|
452
|
-
const commaIndex = base64Data.indexOf(",");
|
|
453
|
-
if (commaIndex !== -1) {
|
|
454
|
-
base64Data = base64Data.slice(commaIndex + 1);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
return {
|
|
458
|
-
type: "document",
|
|
459
|
-
source: {
|
|
460
|
-
type: "base64",
|
|
461
|
-
media_type: "application/pdf",
|
|
462
|
-
data: base64Data
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
function messageToAnthropicContent(message) {
|
|
467
|
-
const attachments = message.metadata?.attachments;
|
|
468
|
-
const content = message.content ?? "";
|
|
469
|
-
if (!hasMediaAttachments(message)) {
|
|
470
|
-
return content;
|
|
471
|
-
}
|
|
472
|
-
const blocks = [];
|
|
473
|
-
if (attachments) {
|
|
474
|
-
for (const attachment of attachments) {
|
|
475
|
-
const imageBlock = attachmentToAnthropicImage(attachment);
|
|
476
|
-
if (imageBlock) {
|
|
477
|
-
blocks.push(imageBlock);
|
|
478
|
-
continue;
|
|
479
|
-
}
|
|
480
|
-
const docBlock = attachmentToAnthropicDocument(attachment);
|
|
481
|
-
if (docBlock) {
|
|
482
|
-
blocks.push(docBlock);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
if (content) {
|
|
487
|
-
blocks.push({ type: "text", text: content });
|
|
488
|
-
}
|
|
489
|
-
return blocks;
|
|
490
|
-
}
|
|
491
|
-
function formatMessagesForAnthropic2(messages, systemPrompt) {
|
|
492
|
-
const formatted = [];
|
|
493
|
-
for (let i = 0; i < messages.length; i++) {
|
|
494
|
-
const msg = messages[i];
|
|
495
|
-
if (msg.role === "system") continue;
|
|
496
|
-
if (msg.role === "assistant") {
|
|
497
|
-
const content = [];
|
|
498
|
-
if (msg.content) {
|
|
499
|
-
content.push({ type: "text", text: msg.content });
|
|
500
|
-
}
|
|
501
|
-
if (msg.tool_calls && msg.tool_calls.length > 0) {
|
|
502
|
-
for (const tc of msg.tool_calls) {
|
|
503
|
-
content.push({
|
|
504
|
-
type: "tool_use",
|
|
505
|
-
id: tc.id,
|
|
506
|
-
name: tc.function.name,
|
|
507
|
-
input: JSON.parse(tc.function.arguments)
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
formatted.push({
|
|
512
|
-
role: "assistant",
|
|
513
|
-
content: content.length === 1 && content[0].type === "text" ? content[0].text : content
|
|
514
|
-
});
|
|
515
|
-
} else if (msg.role === "tool" && msg.tool_call_id) {
|
|
516
|
-
const toolResults = [
|
|
517
|
-
{
|
|
518
|
-
type: "tool_result",
|
|
519
|
-
tool_use_id: msg.tool_call_id,
|
|
520
|
-
content: msg.content ?? ""
|
|
521
|
-
}
|
|
522
|
-
];
|
|
523
|
-
while (i + 1 < messages.length && messages[i + 1].role === "tool") {
|
|
524
|
-
i++;
|
|
525
|
-
const nextTool = messages[i];
|
|
526
|
-
if (nextTool.tool_call_id) {
|
|
527
|
-
toolResults.push({
|
|
528
|
-
type: "tool_result",
|
|
529
|
-
tool_use_id: nextTool.tool_call_id,
|
|
530
|
-
content: nextTool.content ?? ""
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
formatted.push({
|
|
535
|
-
role: "user",
|
|
536
|
-
content: toolResults
|
|
537
|
-
});
|
|
538
|
-
} else if (msg.role === "user") {
|
|
539
|
-
formatted.push({
|
|
540
|
-
role: "user",
|
|
541
|
-
content: messageToAnthropicContent(msg)
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
return {
|
|
546
|
-
system: "",
|
|
547
|
-
messages: formatted
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
|
|
551
677
|
// src/adapters/anthropic.ts
|
|
552
678
|
var AnthropicAdapter = class {
|
|
553
679
|
constructor(config) {
|
|
@@ -770,12 +896,14 @@ var AnthropicAdapter = class {
|
|
|
770
896
|
* Build common request options for both streaming and non-streaming
|
|
771
897
|
*/
|
|
772
898
|
buildRequestOptions(request) {
|
|
773
|
-
const
|
|
899
|
+
const responseFormat = request.config?.responseFormat;
|
|
900
|
+
const jsonObjectSuffix = responseFormat?.type === "json_object" ? "\n\nRespond with a single JSON object and no other text." : "";
|
|
901
|
+
const systemMessage = (request.systemPrompt || "") + jsonObjectSuffix;
|
|
774
902
|
let messages;
|
|
775
903
|
if (request.rawMessages && request.rawMessages.length > 0) {
|
|
776
904
|
messages = this.convertToAnthropicMessages(request.rawMessages);
|
|
777
905
|
} else {
|
|
778
|
-
const formatted =
|
|
906
|
+
const formatted = formatMessagesForAnthropic(request.messages);
|
|
779
907
|
messages = formatted.messages;
|
|
780
908
|
}
|
|
781
909
|
const anthropicNativeSearch = request.providerToolOptions?.anthropic?.nativeToolSearch;
|
|
@@ -851,32 +979,58 @@ var AnthropicAdapter = class {
|
|
|
851
979
|
if (serverToolConfiguration) {
|
|
852
980
|
options.server_tool_configuration = serverToolConfiguration;
|
|
853
981
|
}
|
|
854
|
-
|
|
982
|
+
const modelForThinking = request.config?.model || this.model;
|
|
983
|
+
const thinkingTranslation = toAnthropicThinking(
|
|
984
|
+
request.config?.reasoningEffort,
|
|
985
|
+
modelForThinking
|
|
986
|
+
);
|
|
987
|
+
const outputConfig = toAnthropicOutputConfig(responseFormat);
|
|
988
|
+
if (outputConfig || thinkingTranslation.outputConfigEffort) {
|
|
989
|
+
options.output_config = {
|
|
990
|
+
...outputConfig ?? {},
|
|
991
|
+
...thinkingTranslation.outputConfigEffort ? { effort: thinkingTranslation.outputConfigEffort } : {}
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
if (thinkingTranslation.thinking) {
|
|
995
|
+
options.thinking = thinkingTranslation.thinking;
|
|
996
|
+
} else if (this.config.thinking?.type === "enabled") {
|
|
855
997
|
options.thinking = {
|
|
856
998
|
type: "enabled",
|
|
857
999
|
budget_tokens: this.config.thinking.budgetTokens || 1e4
|
|
858
1000
|
};
|
|
859
1001
|
}
|
|
860
|
-
|
|
1002
|
+
const mcp = toAnthropicMcp(request.config?.mcpServers);
|
|
1003
|
+
const betas = [];
|
|
1004
|
+
if (mcp.mcpServers.length > 0) {
|
|
1005
|
+
options.mcp_servers = mcp.mcpServers;
|
|
1006
|
+
betas.push(...mcp.betas);
|
|
1007
|
+
if (mcp.tools.length > 0) {
|
|
1008
|
+
const existingTools = Array.isArray(options.tools) ? options.tools : [];
|
|
1009
|
+
options.tools = [...existingTools, ...mcp.tools];
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
return { options, messages, betas };
|
|
861
1013
|
}
|
|
862
1014
|
/**
|
|
863
1015
|
* Non-streaming completion (for debugging/comparison with original studio-ai)
|
|
864
1016
|
*/
|
|
865
1017
|
async complete(request) {
|
|
866
1018
|
const client = await this.getClient();
|
|
867
|
-
const { options } = this.buildRequestOptions(request);
|
|
1019
|
+
const { options, betas } = this.buildRequestOptions(request);
|
|
868
1020
|
const nonStreamingOptions = {
|
|
869
1021
|
...options,
|
|
870
1022
|
stream: false
|
|
871
1023
|
};
|
|
872
1024
|
try {
|
|
1025
|
+
const finalOptions = betas.length > 0 ? { ...nonStreamingOptions, betas } : nonStreamingOptions;
|
|
1026
|
+
const messagesApi = betas.length > 0 ? client.beta.messages : client.messages;
|
|
873
1027
|
logProviderPayload(
|
|
874
1028
|
"anthropic",
|
|
875
1029
|
"request payload",
|
|
876
|
-
|
|
1030
|
+
finalOptions,
|
|
877
1031
|
request.debug
|
|
878
1032
|
);
|
|
879
|
-
const response = await
|
|
1033
|
+
const response = await messagesApi.create(finalOptions);
|
|
880
1034
|
logProviderPayload(
|
|
881
1035
|
"anthropic",
|
|
882
1036
|
"response payload",
|
|
@@ -911,17 +1065,19 @@ var AnthropicAdapter = class {
|
|
|
911
1065
|
}
|
|
912
1066
|
async *stream(request) {
|
|
913
1067
|
const client = await this.getClient();
|
|
914
|
-
const { options } = this.buildRequestOptions(request);
|
|
1068
|
+
const { options, betas } = this.buildRequestOptions(request);
|
|
915
1069
|
const messageId = generateMessageId();
|
|
916
1070
|
yield { type: "message:start", id: messageId };
|
|
917
1071
|
try {
|
|
1072
|
+
const finalOptions = betas.length > 0 ? { ...options, betas } : options;
|
|
1073
|
+
const streamApi = betas.length > 0 ? client.beta.messages : client.messages;
|
|
918
1074
|
logProviderPayload(
|
|
919
1075
|
"anthropic",
|
|
920
1076
|
"request payload",
|
|
921
|
-
|
|
1077
|
+
finalOptions,
|
|
922
1078
|
request.debug
|
|
923
1079
|
);
|
|
924
|
-
const stream = await
|
|
1080
|
+
const stream = await streamApi.stream(finalOptions);
|
|
925
1081
|
let currentToolUse = null;
|
|
926
1082
|
let isInThinkingBlock = false;
|
|
927
1083
|
const collectedCitations = [];
|
|
@@ -1179,7 +1335,8 @@ function createAnthropic(config = {}) {
|
|
|
1179
1335
|
"image/gif",
|
|
1180
1336
|
"image/webp"
|
|
1181
1337
|
],
|
|
1182
|
-
|
|
1338
|
+
// Native `output_config.format` — GA on Claude 3.5 and newer.
|
|
1339
|
+
supportsJsonMode: true,
|
|
1183
1340
|
supportsSystemMessages: true
|
|
1184
1341
|
};
|
|
1185
1342
|
};
|