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