@standardagents/anthropic 0.0.0-stub.ffffff → 0.17.0
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/LICENSE.txt +48 -0
- package/README.md +33 -1
- package/dist/index.d.ts +220 -0
- package/dist/index.js +1432 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -7
- package/index.js +0 -1
package/dist/index.js
ADDED
|
@@ -0,0 +1,1432 @@
|
|
|
1
|
+
// src/AnthropicProvider.ts
|
|
2
|
+
import { ProviderError, defineTool } from "@standardagents/spec";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
// src/transformers.ts
|
|
6
|
+
import { mapReasoningLevel } from "@standardagents/spec";
|
|
7
|
+
|
|
8
|
+
// src/pricing.ts
|
|
9
|
+
var TOKENS_PER_MILLION = 1e6;
|
|
10
|
+
var CACHE_WRITE_5M_MULTIPLIER = 1.25;
|
|
11
|
+
var CACHE_WRITE_1H_MULTIPLIER = 2;
|
|
12
|
+
var CACHE_READ_MULTIPLIER = 0.1;
|
|
13
|
+
var MODEL_PRICING = [
|
|
14
|
+
["claude-fable-5", { inputPerMillion: 10, outputPerMillion: 50 }],
|
|
15
|
+
["claude-mythos", { inputPerMillion: 10, outputPerMillion: 50 }],
|
|
16
|
+
["claude-opus-4-8", { inputPerMillion: 5, outputPerMillion: 25 }],
|
|
17
|
+
["claude-opus-4-7", { inputPerMillion: 5, outputPerMillion: 25 }],
|
|
18
|
+
["claude-opus-4-6", { inputPerMillion: 5, outputPerMillion: 25 }],
|
|
19
|
+
["claude-opus-4-5", { inputPerMillion: 5, outputPerMillion: 25 }],
|
|
20
|
+
["claude-opus-4-1", { inputPerMillion: 15, outputPerMillion: 75 }],
|
|
21
|
+
["claude-opus-4", { inputPerMillion: 15, outputPerMillion: 75 }],
|
|
22
|
+
["claude-sonnet-4-6", { inputPerMillion: 3, outputPerMillion: 15 }],
|
|
23
|
+
["claude-sonnet-4-5", { inputPerMillion: 3, outputPerMillion: 15 }],
|
|
24
|
+
["claude-sonnet-4", { inputPerMillion: 3, outputPerMillion: 15 }],
|
|
25
|
+
["claude-haiku-4-5", { inputPerMillion: 1, outputPerMillion: 5 }],
|
|
26
|
+
["claude-3-7-sonnet", { inputPerMillion: 3, outputPerMillion: 15 }],
|
|
27
|
+
["claude-3-5-sonnet", { inputPerMillion: 3, outputPerMillion: 15 }],
|
|
28
|
+
["claude-3-5-haiku", { inputPerMillion: 0.8, outputPerMillion: 4 }],
|
|
29
|
+
["claude-3-opus", { inputPerMillion: 15, outputPerMillion: 75 }],
|
|
30
|
+
["claude-3-haiku", { inputPerMillion: 0.25, outputPerMillion: 1.25 }]
|
|
31
|
+
];
|
|
32
|
+
function getAnthropicModelPricing(modelId) {
|
|
33
|
+
if (!modelId) return null;
|
|
34
|
+
const normalized = modelId.trim().toLowerCase();
|
|
35
|
+
let best = null;
|
|
36
|
+
for (const [prefix, pricing] of MODEL_PRICING) {
|
|
37
|
+
if (normalized.startsWith(prefix) && (!best || prefix.length > best.prefix.length)) {
|
|
38
|
+
best = { prefix, pricing };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return best ? { ...best.pricing } : null;
|
|
42
|
+
}
|
|
43
|
+
function extractUsageBuckets(usage) {
|
|
44
|
+
const totalCacheWrite = usage.cache_creation_input_tokens ?? 0;
|
|
45
|
+
const write1h = usage.cache_creation?.ephemeral_1h_input_tokens ?? 0;
|
|
46
|
+
const write5m = usage.cache_creation?.ephemeral_5m_input_tokens ?? Math.max(totalCacheWrite - write1h, 0);
|
|
47
|
+
return {
|
|
48
|
+
inputTokens: usage.input_tokens,
|
|
49
|
+
outputTokens: usage.output_tokens,
|
|
50
|
+
cacheReadTokens: usage.cache_read_input_tokens ?? 0,
|
|
51
|
+
cacheWrite5mTokens: write5m,
|
|
52
|
+
cacheWrite1hTokens: write1h
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function roundCost(value) {
|
|
56
|
+
return Number(value.toFixed(12));
|
|
57
|
+
}
|
|
58
|
+
function calculateAnthropicUsageCost(modelId, buckets) {
|
|
59
|
+
const pricing = getAnthropicModelPricing(modelId);
|
|
60
|
+
if (!pricing) return void 0;
|
|
61
|
+
const inputRate = pricing.inputPerMillion / TOKENS_PER_MILLION;
|
|
62
|
+
const outputRate = pricing.outputPerMillion / TOKENS_PER_MILLION;
|
|
63
|
+
const cost = buckets.inputTokens * inputRate + buckets.cacheWrite5mTokens * inputRate * CACHE_WRITE_5M_MULTIPLIER + buckets.cacheWrite1hTokens * inputRate * CACHE_WRITE_1H_MULTIPLIER + buckets.cacheReadTokens * inputRate * CACHE_READ_MULTIPLIER + buckets.outputTokens * outputRate;
|
|
64
|
+
return roundCost(cost);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/transformers.ts
|
|
68
|
+
var THINKING_FORMAT = "anthropic-thinking-v1";
|
|
69
|
+
var REDACTED_THINKING_FORMAT = "anthropic-redacted-thinking-v1";
|
|
70
|
+
var DEFAULT_REASONING_LEVELS = {
|
|
71
|
+
0: null,
|
|
72
|
+
33: "low",
|
|
73
|
+
66: "medium",
|
|
74
|
+
100: "high"
|
|
75
|
+
};
|
|
76
|
+
var ANTHROPIC_NATIVE_TOOLS = /* @__PURE__ */ new Set(["web_search"]);
|
|
77
|
+
var DEFAULT_MAX_OUTPUT_TOKENS = 8192;
|
|
78
|
+
var THINKING_MODE_PREFIXES = [
|
|
79
|
+
["claude-fable-5", "adaptive"],
|
|
80
|
+
["claude-mythos", "adaptive"],
|
|
81
|
+
["claude-opus-4-8", "adaptive"],
|
|
82
|
+
["claude-opus-4-7", "adaptive"],
|
|
83
|
+
["claude-opus-4-6", "adaptive"],
|
|
84
|
+
["claude-opus-4-5", "budget"],
|
|
85
|
+
["claude-opus-4-1", "budget"],
|
|
86
|
+
["claude-opus-4-0", "budget"],
|
|
87
|
+
["claude-opus-4-2", "budget"],
|
|
88
|
+
// dated full IDs like claude-opus-4-20250514
|
|
89
|
+
["claude-sonnet-4-6", "adaptive"],
|
|
90
|
+
["claude-sonnet-4-5", "budget"],
|
|
91
|
+
["claude-sonnet-4-0", "budget"],
|
|
92
|
+
["claude-sonnet-4-2", "budget"],
|
|
93
|
+
// dated full IDs like claude-sonnet-4-20250514
|
|
94
|
+
["claude-haiku-4-5", "budget"],
|
|
95
|
+
["claude-3-7-sonnet", "budget"],
|
|
96
|
+
["claude-3", "none"]
|
|
97
|
+
];
|
|
98
|
+
function getThinkingMode(modelId) {
|
|
99
|
+
for (const [prefix, mode] of THINKING_MODE_PREFIXES) {
|
|
100
|
+
if (modelId.startsWith(prefix)) {
|
|
101
|
+
return mode;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return "adaptive";
|
|
105
|
+
}
|
|
106
|
+
function parseDataUri(value) {
|
|
107
|
+
const match = /^data:([^;,]+)?(;base64)?,(.*)$/s.exec(value);
|
|
108
|
+
if (!match) return null;
|
|
109
|
+
return {
|
|
110
|
+
mediaType: match[1] || "application/octet-stream",
|
|
111
|
+
data: match[3]
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
var SUPPORTED_IMAGE_MEDIA_TYPES = /* @__PURE__ */ new Set([
|
|
115
|
+
"image/jpeg",
|
|
116
|
+
"image/png",
|
|
117
|
+
"image/gif",
|
|
118
|
+
"image/webp"
|
|
119
|
+
]);
|
|
120
|
+
function normalizeImageMediaType(mediaType) {
|
|
121
|
+
if (mediaType && SUPPORTED_IMAGE_MEDIA_TYPES.has(mediaType)) {
|
|
122
|
+
return mediaType;
|
|
123
|
+
}
|
|
124
|
+
return "image/png";
|
|
125
|
+
}
|
|
126
|
+
function imageBlock(data, mediaType) {
|
|
127
|
+
if (data.startsWith("http://") || data.startsWith("https://")) {
|
|
128
|
+
return { type: "image", source: { type: "url", url: data } };
|
|
129
|
+
}
|
|
130
|
+
const parsed = parseDataUri(data);
|
|
131
|
+
if (parsed) {
|
|
132
|
+
return {
|
|
133
|
+
type: "image",
|
|
134
|
+
source: {
|
|
135
|
+
type: "base64",
|
|
136
|
+
media_type: normalizeImageMediaType(parsed.mediaType),
|
|
137
|
+
data: parsed.data
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
type: "image",
|
|
143
|
+
source: {
|
|
144
|
+
type: "base64",
|
|
145
|
+
media_type: normalizeImageMediaType(mediaType),
|
|
146
|
+
data
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function decodeBase64Text(data) {
|
|
151
|
+
try {
|
|
152
|
+
const binary = atob(data);
|
|
153
|
+
const bytes = new Uint8Array(binary.length);
|
|
154
|
+
for (let i = 0; i < binary.length; i++) {
|
|
155
|
+
bytes[i] = binary.charCodeAt(i);
|
|
156
|
+
}
|
|
157
|
+
return new TextDecoder().decode(bytes);
|
|
158
|
+
} catch {
|
|
159
|
+
return data;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function fileBlock(data, mediaType, filename) {
|
|
163
|
+
const parsed = parseDataUri(data);
|
|
164
|
+
const base64 = parsed ? parsed.data : data;
|
|
165
|
+
const resolvedMediaType = parsed?.mediaType || mediaType;
|
|
166
|
+
if (data.startsWith("http://") || data.startsWith("https://")) {
|
|
167
|
+
return { type: "document", source: { type: "url", url: data } };
|
|
168
|
+
}
|
|
169
|
+
if (resolvedMediaType === "application/pdf") {
|
|
170
|
+
return {
|
|
171
|
+
type: "document",
|
|
172
|
+
source: { type: "base64", media_type: "application/pdf", data: base64 },
|
|
173
|
+
...filename ? { title: filename } : {}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (resolvedMediaType.startsWith("text/") || resolvedMediaType === "application/json") {
|
|
177
|
+
return {
|
|
178
|
+
type: "document",
|
|
179
|
+
source: { type: "text", media_type: "text/plain", data: decodeBase64Text(base64) },
|
|
180
|
+
...filename ? { title: filename } : {}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
type: "text",
|
|
185
|
+
text: `[Unsupported file attachment${filename ? `: ${filename}` : ""} (${resolvedMediaType})]`
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function transformContentPart(part) {
|
|
189
|
+
if (part.type === "text") {
|
|
190
|
+
return { type: "text", text: part.text };
|
|
191
|
+
}
|
|
192
|
+
if (part.type === "image") {
|
|
193
|
+
return imageBlock(part.data || "", part.mediaType);
|
|
194
|
+
}
|
|
195
|
+
if (part.type === "image_url") {
|
|
196
|
+
return imageBlock(part.image_url?.url || "");
|
|
197
|
+
}
|
|
198
|
+
return fileBlock(part.data || "", part.mediaType || "application/octet-stream", part.filename);
|
|
199
|
+
}
|
|
200
|
+
function transformMessageContent(content) {
|
|
201
|
+
if (typeof content === "string") {
|
|
202
|
+
return content;
|
|
203
|
+
}
|
|
204
|
+
return content.map(transformContentPart);
|
|
205
|
+
}
|
|
206
|
+
function transformAssistantMessage(msg) {
|
|
207
|
+
const content = [];
|
|
208
|
+
if (msg.reasoningDetails) {
|
|
209
|
+
for (const detail of msg.reasoningDetails) {
|
|
210
|
+
if (detail.format === THINKING_FORMAT && detail.text !== void 0) {
|
|
211
|
+
content.push({
|
|
212
|
+
type: "thinking",
|
|
213
|
+
thinking: detail.text,
|
|
214
|
+
signature: detail.data ?? ""
|
|
215
|
+
});
|
|
216
|
+
} else if (detail.format === REDACTED_THINKING_FORMAT && detail.data) {
|
|
217
|
+
content.push({ type: "redacted_thinking", data: detail.data });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (msg.content) {
|
|
222
|
+
content.push({ type: "text", text: msg.content });
|
|
223
|
+
}
|
|
224
|
+
if (msg.toolCalls) {
|
|
225
|
+
for (const tc of msg.toolCalls) {
|
|
226
|
+
if (ANTHROPIC_NATIVE_TOOLS.has(tc.name)) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
content.push({
|
|
230
|
+
type: "tool_use",
|
|
231
|
+
id: tc.id,
|
|
232
|
+
name: tc.name,
|
|
233
|
+
input: tc.arguments
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (content.length === 0) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
return { role: "assistant", content };
|
|
241
|
+
}
|
|
242
|
+
function transformToolMessage(msg) {
|
|
243
|
+
if (ANTHROPIC_NATIVE_TOOLS.has(msg.toolName)) {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
let text;
|
|
247
|
+
let isError = false;
|
|
248
|
+
if (typeof msg.content === "string") {
|
|
249
|
+
text = msg.content;
|
|
250
|
+
} else if ("type" in msg.content) {
|
|
251
|
+
if (msg.content.type === "text") {
|
|
252
|
+
text = msg.content.text;
|
|
253
|
+
} else if (msg.content.type === "error") {
|
|
254
|
+
text = msg.content.error;
|
|
255
|
+
isError = true;
|
|
256
|
+
} else {
|
|
257
|
+
text = JSON.stringify(msg.content);
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
text = JSON.stringify(msg.content);
|
|
261
|
+
}
|
|
262
|
+
const blocks = [];
|
|
263
|
+
if (text) {
|
|
264
|
+
blocks.push({ type: "text", text });
|
|
265
|
+
}
|
|
266
|
+
if (msg.attachments?.length) {
|
|
267
|
+
for (const attachment of msg.attachments) {
|
|
268
|
+
if (attachment.type === "image" && attachment.data) {
|
|
269
|
+
blocks.push(imageBlock(attachment.data, attachment.mediaType));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
type: "tool_result",
|
|
275
|
+
tool_use_id: msg.toolCallId,
|
|
276
|
+
...blocks.length > 0 ? { content: blocks } : {},
|
|
277
|
+
...isError ? { is_error: true } : {}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function transformMessages(messages) {
|
|
281
|
+
let system;
|
|
282
|
+
const anthropicMessages = [];
|
|
283
|
+
let pendingToolResults = [];
|
|
284
|
+
const flushToolResults = () => {
|
|
285
|
+
if (pendingToolResults.length > 0) {
|
|
286
|
+
anthropicMessages.push({ role: "user", content: pendingToolResults });
|
|
287
|
+
pendingToolResults = [];
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
for (const msg of messages) {
|
|
291
|
+
switch (msg.role) {
|
|
292
|
+
case "system":
|
|
293
|
+
system = system ? `${system}
|
|
294
|
+
|
|
295
|
+
${msg.content}` : msg.content;
|
|
296
|
+
break;
|
|
297
|
+
case "user":
|
|
298
|
+
flushToolResults();
|
|
299
|
+
anthropicMessages.push({
|
|
300
|
+
role: "user",
|
|
301
|
+
content: transformMessageContent(msg.content)
|
|
302
|
+
});
|
|
303
|
+
break;
|
|
304
|
+
case "assistant": {
|
|
305
|
+
flushToolResults();
|
|
306
|
+
const assistantMessage = transformAssistantMessage(msg);
|
|
307
|
+
if (assistantMessage) {
|
|
308
|
+
anthropicMessages.push(assistantMessage);
|
|
309
|
+
}
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
case "tool": {
|
|
313
|
+
const toolResult = transformToolMessage(msg);
|
|
314
|
+
if (toolResult) {
|
|
315
|
+
pendingToolResults.push(toolResult);
|
|
316
|
+
}
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
flushToolResults();
|
|
322
|
+
return { anthropicMessages, system };
|
|
323
|
+
}
|
|
324
|
+
function isRecord(value) {
|
|
325
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
326
|
+
}
|
|
327
|
+
function transformTool(tool) {
|
|
328
|
+
const parameters = isRecord(tool.function.parameters) ? tool.function.parameters : { type: "object", properties: {} };
|
|
329
|
+
return {
|
|
330
|
+
name: tool.function.name,
|
|
331
|
+
...tool.function.description ? { description: tool.function.description } : {},
|
|
332
|
+
input_schema: {
|
|
333
|
+
...parameters,
|
|
334
|
+
type: "object"
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
function transformTools(tools) {
|
|
339
|
+
const result = [];
|
|
340
|
+
for (const tool of tools) {
|
|
341
|
+
const toolName = tool.function.name;
|
|
342
|
+
if (tool.executionMode === "provider" && ANTHROPIC_NATIVE_TOOLS.has(toolName)) {
|
|
343
|
+
if (toolName === "web_search") {
|
|
344
|
+
result.push({ type: "web_search_20250305", name: "web_search" });
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
result.push(transformTool(tool));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return result;
|
|
351
|
+
}
|
|
352
|
+
function transformToolChoice(choice, parallelToolCalls) {
|
|
353
|
+
const disable = parallelToolCalls === false ? { disable_parallel_tool_use: true } : {};
|
|
354
|
+
if (choice === "none") {
|
|
355
|
+
return { type: "none" };
|
|
356
|
+
}
|
|
357
|
+
if (choice === "required") {
|
|
358
|
+
return { type: "any", ...disable };
|
|
359
|
+
}
|
|
360
|
+
if (typeof choice === "object" && choice !== null && "name" in choice) {
|
|
361
|
+
return { type: "tool", name: choice.name, ...disable };
|
|
362
|
+
}
|
|
363
|
+
if (choice === "auto" || parallelToolCalls === false) {
|
|
364
|
+
return { type: "auto", ...disable };
|
|
365
|
+
}
|
|
366
|
+
return void 0;
|
|
367
|
+
}
|
|
368
|
+
function mapFinishReason(stopReason) {
|
|
369
|
+
switch (stopReason) {
|
|
370
|
+
case "end_turn":
|
|
371
|
+
case "stop_sequence":
|
|
372
|
+
case "pause_turn":
|
|
373
|
+
return "stop";
|
|
374
|
+
case "max_tokens":
|
|
375
|
+
return "length";
|
|
376
|
+
case "tool_use":
|
|
377
|
+
return "tool_calls";
|
|
378
|
+
case "refusal":
|
|
379
|
+
return "content_filter";
|
|
380
|
+
default:
|
|
381
|
+
return "stop";
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function extractTextContent(content) {
|
|
385
|
+
const textParts = [];
|
|
386
|
+
for (const block of content) {
|
|
387
|
+
if (block.type === "text") {
|
|
388
|
+
textParts.push(block.text);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return textParts.length > 0 ? textParts.join("") : null;
|
|
392
|
+
}
|
|
393
|
+
function extractReasoningContent(content) {
|
|
394
|
+
let reasoning = null;
|
|
395
|
+
const reasoningDetails = [];
|
|
396
|
+
for (const block of content) {
|
|
397
|
+
if (block.type === "thinking") {
|
|
398
|
+
if (block.thinking) {
|
|
399
|
+
reasoning = reasoning ? `${reasoning}
|
|
400
|
+
${block.thinking}` : block.thinking;
|
|
401
|
+
}
|
|
402
|
+
reasoningDetails.push({
|
|
403
|
+
type: "text",
|
|
404
|
+
text: block.thinking,
|
|
405
|
+
data: block.signature,
|
|
406
|
+
format: THINKING_FORMAT
|
|
407
|
+
});
|
|
408
|
+
} else if (block.type === "redacted_thinking") {
|
|
409
|
+
reasoningDetails.push({
|
|
410
|
+
type: "encrypted",
|
|
411
|
+
data: block.data,
|
|
412
|
+
format: REDACTED_THINKING_FORMAT
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return {
|
|
417
|
+
reasoning,
|
|
418
|
+
reasoningDetails: reasoningDetails.length > 0 ? reasoningDetails : void 0
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function extractToolCalls(content) {
|
|
422
|
+
const toolCalls = [];
|
|
423
|
+
for (const block of content) {
|
|
424
|
+
if (block.type === "tool_use") {
|
|
425
|
+
toolCalls.push({
|
|
426
|
+
id: block.id,
|
|
427
|
+
name: block.name,
|
|
428
|
+
arguments: isRecord(block.input) ? block.input : {}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return toolCalls.length > 0 ? toolCalls : void 0;
|
|
433
|
+
}
|
|
434
|
+
function webSearchToolResult(id, input, resultContent) {
|
|
435
|
+
const query = isRecord(input) && typeof input.query === "string" ? input.query : void 0;
|
|
436
|
+
let status = "completed";
|
|
437
|
+
let sources;
|
|
438
|
+
if (Array.isArray(resultContent)) {
|
|
439
|
+
sources = resultContent.filter(isRecord).filter((item) => item.type === "web_search_result" && typeof item.url === "string").map((item) => ({
|
|
440
|
+
type: "url",
|
|
441
|
+
url: item.url,
|
|
442
|
+
...typeof item.title === "string" ? { title: item.title } : {}
|
|
443
|
+
}));
|
|
444
|
+
} else if (isRecord(resultContent) && resultContent.type === "web_search_tool_result_error") {
|
|
445
|
+
status = "failed";
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
name: "web_search",
|
|
449
|
+
type: "web_search",
|
|
450
|
+
provider: "anthropic",
|
|
451
|
+
id,
|
|
452
|
+
status,
|
|
453
|
+
result: {
|
|
454
|
+
actions: [{
|
|
455
|
+
type: "search",
|
|
456
|
+
...query ? { query } : {},
|
|
457
|
+
...sources && sources.length > 0 ? { sources } : {}
|
|
458
|
+
}]
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function extractProviderToolResults(content) {
|
|
463
|
+
const providerTools = [];
|
|
464
|
+
const serverToolUses = /* @__PURE__ */ new Map();
|
|
465
|
+
for (const block of content) {
|
|
466
|
+
if (block.type === "server_tool_use") {
|
|
467
|
+
serverToolUses.set(block.id, { name: block.name, input: block.input });
|
|
468
|
+
} else if (block.type === "web_search_tool_result") {
|
|
469
|
+
const use = serverToolUses.get(block.tool_use_id);
|
|
470
|
+
providerTools.push(
|
|
471
|
+
webSearchToolResult(block.tool_use_id, use?.input, block.content)
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return providerTools.length > 0 ? providerTools : void 0;
|
|
476
|
+
}
|
|
477
|
+
function transformUsage(usage, modelId) {
|
|
478
|
+
if (!usage) {
|
|
479
|
+
return { promptTokens: 0, completionTokens: 0, totalTokens: 0, provider: "anthropic" };
|
|
480
|
+
}
|
|
481
|
+
const cacheCreation = usage.cache_creation_input_tokens ?? 0;
|
|
482
|
+
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
483
|
+
const promptTokens = usage.input_tokens + cacheCreation + cacheRead;
|
|
484
|
+
const completionTokens = usage.output_tokens;
|
|
485
|
+
const reasoningTokens = usage.output_tokens_details?.thinking_tokens;
|
|
486
|
+
const cost = modelId ? calculateAnthropicUsageCost(modelId, extractUsageBuckets(usage)) : void 0;
|
|
487
|
+
return {
|
|
488
|
+
promptTokens,
|
|
489
|
+
completionTokens,
|
|
490
|
+
totalTokens: promptTokens + completionTokens,
|
|
491
|
+
...reasoningTokens !== void 0 ? { reasoningTokens } : {},
|
|
492
|
+
...cacheRead > 0 ? { cachedTokens: cacheRead } : {},
|
|
493
|
+
...cost !== void 0 ? { cost } : {},
|
|
494
|
+
provider: "anthropic"
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
function transformResponse(message) {
|
|
498
|
+
const content = extractTextContent(message.content);
|
|
499
|
+
const { reasoning, reasoningDetails } = extractReasoningContent(message.content);
|
|
500
|
+
const toolCalls = extractToolCalls(message.content);
|
|
501
|
+
const providerTools = extractProviderToolResults(message.content);
|
|
502
|
+
return {
|
|
503
|
+
content,
|
|
504
|
+
reasoning,
|
|
505
|
+
reasoningDetails,
|
|
506
|
+
toolCalls,
|
|
507
|
+
providerTools,
|
|
508
|
+
finishReason: mapFinishReason(message.stop_reason),
|
|
509
|
+
usage: transformUsage(message.usage, message.model),
|
|
510
|
+
metadata: {
|
|
511
|
+
model: message.model,
|
|
512
|
+
provider: "anthropic",
|
|
513
|
+
requestId: message.id,
|
|
514
|
+
...message.stop_sequence ? { stopSequence: message.stop_sequence } : {},
|
|
515
|
+
...message.usage?.cache_creation_input_tokens ? { cacheCreationInputTokens: message.usage.cache_creation_input_tokens } : {},
|
|
516
|
+
...message.usage?.cache_read_input_tokens ? { cacheReadInputTokens: message.usage.cache_read_input_tokens } : {},
|
|
517
|
+
...message.usage?.service_tier ? { serviceTier: message.usage.service_tier } : {},
|
|
518
|
+
...message.usage?.server_tool_use ? { serverToolUse: { ...message.usage.server_tool_use } } : {}
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function resolveThinkingOverride(value) {
|
|
523
|
+
if (!isRecord(value)) return void 0;
|
|
524
|
+
const display = value.display === "summarized" || value.display === "omitted" ? value.display : void 0;
|
|
525
|
+
if (value.type === "adaptive") {
|
|
526
|
+
return { type: "adaptive", ...display ? { display } : {} };
|
|
527
|
+
}
|
|
528
|
+
if (value.type === "enabled" && typeof value.budget_tokens === "number") {
|
|
529
|
+
return {
|
|
530
|
+
type: "enabled",
|
|
531
|
+
budget_tokens: value.budget_tokens,
|
|
532
|
+
...display ? { display } : {}
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
if (value.type === "disabled") {
|
|
536
|
+
return { type: "disabled" };
|
|
537
|
+
}
|
|
538
|
+
return void 0;
|
|
539
|
+
}
|
|
540
|
+
function resolveThinkingBudget(level, maxTokens, explicitBudget) {
|
|
541
|
+
if (maxTokens < 2048) {
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
const ceiling = maxTokens - 1024;
|
|
545
|
+
const scaled = explicitBudget ?? Math.floor(maxTokens * Math.min(level, 100) / 100 * 0.75);
|
|
546
|
+
return Math.max(1024, Math.min(scaled, ceiling));
|
|
547
|
+
}
|
|
548
|
+
function buildCreateParams(request, reasoningLevels = DEFAULT_REASONING_LEVELS, defaultMaxTokens = DEFAULT_MAX_OUTPUT_TOKENS) {
|
|
549
|
+
const { anthropicMessages, system } = transformMessages(request.messages);
|
|
550
|
+
const maxTokens = request.maxOutputTokens ?? defaultMaxTokens;
|
|
551
|
+
const params = {
|
|
552
|
+
model: request.model,
|
|
553
|
+
max_tokens: maxTokens,
|
|
554
|
+
messages: anthropicMessages
|
|
555
|
+
};
|
|
556
|
+
const providerOptions = isRecord(request.providerOptions) ? request.providerOptions : {};
|
|
557
|
+
const {
|
|
558
|
+
cacheSystemPrompt,
|
|
559
|
+
thinking: thinkingOverride,
|
|
560
|
+
...passthroughOptions
|
|
561
|
+
} = providerOptions;
|
|
562
|
+
let systemText = system;
|
|
563
|
+
if (request.responseFormat?.type === "json") {
|
|
564
|
+
if (request.responseFormat.schema) {
|
|
565
|
+
params.output_config = {
|
|
566
|
+
format: { type: "json_schema", schema: request.responseFormat.schema }
|
|
567
|
+
};
|
|
568
|
+
} else {
|
|
569
|
+
const jsonInstruction = "Respond with valid JSON only. Do not include any text outside the JSON.";
|
|
570
|
+
systemText = systemText ? `${systemText}
|
|
571
|
+
|
|
572
|
+
${jsonInstruction}` : jsonInstruction;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
if (systemText) {
|
|
576
|
+
params.system = cacheSystemPrompt === true ? [{ type: "text", text: systemText, cache_control: { type: "ephemeral" } }] : systemText;
|
|
577
|
+
}
|
|
578
|
+
if (request.tools && request.tools.length > 0) {
|
|
579
|
+
params.tools = transformTools(request.tools);
|
|
580
|
+
}
|
|
581
|
+
const toolChoice = transformToolChoice(request.toolChoice, request.parallelToolCalls);
|
|
582
|
+
if (toolChoice && params.tools && params.tools.length > 0) {
|
|
583
|
+
params.tool_choice = toolChoice;
|
|
584
|
+
}
|
|
585
|
+
const thinkingMode = getThinkingMode(request.model);
|
|
586
|
+
let thinkingEnabled = false;
|
|
587
|
+
const resolvedOverride = resolveThinkingOverride(thinkingOverride);
|
|
588
|
+
if (resolvedOverride) {
|
|
589
|
+
params.thinking = resolvedOverride;
|
|
590
|
+
thinkingEnabled = resolvedOverride.type !== "disabled";
|
|
591
|
+
} else if (request.reasoning?.level !== void 0 && request.reasoning.level > 0) {
|
|
592
|
+
if (thinkingMode === "adaptive") {
|
|
593
|
+
params.thinking = {
|
|
594
|
+
type: "adaptive",
|
|
595
|
+
...request.reasoning.exclude ? { display: "omitted" } : {}
|
|
596
|
+
};
|
|
597
|
+
const effort = mapReasoningLevel(request.reasoning.level, reasoningLevels);
|
|
598
|
+
if (effort) {
|
|
599
|
+
params.output_config = {
|
|
600
|
+
...params.output_config,
|
|
601
|
+
effort
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
thinkingEnabled = true;
|
|
605
|
+
} else if (thinkingMode === "budget") {
|
|
606
|
+
const budget = resolveThinkingBudget(
|
|
607
|
+
request.reasoning.level,
|
|
608
|
+
maxTokens,
|
|
609
|
+
request.reasoning.maxTokens
|
|
610
|
+
);
|
|
611
|
+
if (budget !== null) {
|
|
612
|
+
params.thinking = {
|
|
613
|
+
type: "enabled",
|
|
614
|
+
budget_tokens: budget,
|
|
615
|
+
...request.reasoning.exclude ? { display: "omitted" } : {}
|
|
616
|
+
};
|
|
617
|
+
thinkingEnabled = true;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
if (!thinkingEnabled) {
|
|
622
|
+
if (request.temperature !== void 0) {
|
|
623
|
+
params.temperature = request.temperature;
|
|
624
|
+
}
|
|
625
|
+
if (request.topP !== void 0) {
|
|
626
|
+
params.top_p = request.topP;
|
|
627
|
+
}
|
|
628
|
+
if (request.topK !== void 0) {
|
|
629
|
+
params.top_k = request.topK;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (request.stopSequences && request.stopSequences.length > 0) {
|
|
633
|
+
params.stop_sequences = request.stopSequences;
|
|
634
|
+
}
|
|
635
|
+
Object.assign(params, passthroughOptions);
|
|
636
|
+
return params;
|
|
637
|
+
}
|
|
638
|
+
function createStreamState() {
|
|
639
|
+
return {
|
|
640
|
+
toolCallsByIndex: /* @__PURE__ */ new Map(),
|
|
641
|
+
thinkingByIndex: /* @__PURE__ */ new Map(),
|
|
642
|
+
serverToolsByIndex: /* @__PURE__ */ new Map(),
|
|
643
|
+
pendingServerTools: /* @__PURE__ */ new Map(),
|
|
644
|
+
reasoningDetails: [],
|
|
645
|
+
hasContent: false,
|
|
646
|
+
hasReasoning: false,
|
|
647
|
+
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0, provider: "anthropic" },
|
|
648
|
+
buckets: {
|
|
649
|
+
inputTokens: 0,
|
|
650
|
+
outputTokens: 0,
|
|
651
|
+
cacheReadTokens: 0,
|
|
652
|
+
cacheWrite5mTokens: 0,
|
|
653
|
+
cacheWrite1hTokens: 0
|
|
654
|
+
},
|
|
655
|
+
finishReason: "stop",
|
|
656
|
+
model: null,
|
|
657
|
+
messageId: null,
|
|
658
|
+
serverToolUse: null
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
function parseToolCallArguments(argumentsJson) {
|
|
662
|
+
try {
|
|
663
|
+
const parsed = argumentsJson ? JSON.parse(argumentsJson) : {};
|
|
664
|
+
return isRecord(parsed) ? parsed : {};
|
|
665
|
+
} catch {
|
|
666
|
+
return {};
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
function applyDeltaUsage(state, usage) {
|
|
670
|
+
const cacheCreation = usage.cache_creation_input_tokens ?? 0;
|
|
671
|
+
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
672
|
+
if (usage.input_tokens !== null && usage.input_tokens !== void 0) {
|
|
673
|
+
state.usage.promptTokens = usage.input_tokens + cacheCreation + cacheRead;
|
|
674
|
+
if (cacheRead > 0) {
|
|
675
|
+
state.usage.cachedTokens = cacheRead;
|
|
676
|
+
}
|
|
677
|
+
state.buckets.inputTokens = usage.input_tokens;
|
|
678
|
+
state.buckets.cacheReadTokens = cacheRead;
|
|
679
|
+
state.buckets.cacheWrite5mTokens = Math.max(
|
|
680
|
+
cacheCreation - state.buckets.cacheWrite1hTokens,
|
|
681
|
+
0
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
state.buckets.outputTokens = usage.output_tokens;
|
|
685
|
+
state.usage.completionTokens = usage.output_tokens;
|
|
686
|
+
const thinkingTokens = usage.output_tokens_details?.thinking_tokens;
|
|
687
|
+
if (thinkingTokens !== void 0) {
|
|
688
|
+
state.usage.reasoningTokens = thinkingTokens;
|
|
689
|
+
}
|
|
690
|
+
state.usage.totalTokens = state.usage.promptTokens + state.usage.completionTokens;
|
|
691
|
+
if (usage.server_tool_use) {
|
|
692
|
+
state.serverToolUse = { ...usage.server_tool_use };
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
function processStreamEvent(event, state) {
|
|
696
|
+
const chunks = [];
|
|
697
|
+
switch (event.type) {
|
|
698
|
+
case "message_start": {
|
|
699
|
+
const usage = event.message.usage;
|
|
700
|
+
const cacheCreation = usage.cache_creation_input_tokens ?? 0;
|
|
701
|
+
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
702
|
+
state.usage.promptTokens = usage.input_tokens + cacheCreation + cacheRead;
|
|
703
|
+
if (cacheRead > 0) {
|
|
704
|
+
state.usage.cachedTokens = cacheRead;
|
|
705
|
+
}
|
|
706
|
+
state.usage.completionTokens = usage.output_tokens;
|
|
707
|
+
state.usage.totalTokens = state.usage.promptTokens + state.usage.completionTokens;
|
|
708
|
+
state.buckets = extractUsageBuckets(usage);
|
|
709
|
+
state.model = event.message.model;
|
|
710
|
+
state.messageId = event.message.id;
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
case "content_block_start": {
|
|
714
|
+
const block = event.content_block;
|
|
715
|
+
if (block.type === "tool_use") {
|
|
716
|
+
state.toolCallsByIndex.set(event.index, {
|
|
717
|
+
id: block.id,
|
|
718
|
+
name: block.name,
|
|
719
|
+
argumentsJson: ""
|
|
720
|
+
});
|
|
721
|
+
chunks.push({ type: "tool-call-start", id: block.id, name: block.name });
|
|
722
|
+
} else if (block.type === "thinking") {
|
|
723
|
+
state.thinkingByIndex.set(event.index, {
|
|
724
|
+
thinking: block.thinking || "",
|
|
725
|
+
signature: block.signature || ""
|
|
726
|
+
});
|
|
727
|
+
} else if (block.type === "redacted_thinking") {
|
|
728
|
+
state.reasoningDetails.push({
|
|
729
|
+
type: "encrypted",
|
|
730
|
+
data: block.data,
|
|
731
|
+
format: REDACTED_THINKING_FORMAT
|
|
732
|
+
});
|
|
733
|
+
} else if (block.type === "server_tool_use") {
|
|
734
|
+
state.serverToolsByIndex.set(event.index, {
|
|
735
|
+
id: block.id,
|
|
736
|
+
name: block.name,
|
|
737
|
+
inputJson: ""
|
|
738
|
+
});
|
|
739
|
+
} else if (block.type === "web_search_tool_result") {
|
|
740
|
+
const use = state.pendingServerTools.get(block.tool_use_id);
|
|
741
|
+
chunks.push({
|
|
742
|
+
type: "provider-tool-done",
|
|
743
|
+
tool: webSearchToolResult(block.tool_use_id, use?.input, block.content)
|
|
744
|
+
});
|
|
745
|
+
state.pendingServerTools.delete(block.tool_use_id);
|
|
746
|
+
}
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
case "content_block_delta": {
|
|
750
|
+
const delta = event.delta;
|
|
751
|
+
if (delta.type === "text_delta") {
|
|
752
|
+
state.hasContent = true;
|
|
753
|
+
chunks.push({ type: "content-delta", delta: delta.text });
|
|
754
|
+
} else if (delta.type === "thinking_delta") {
|
|
755
|
+
state.hasReasoning = true;
|
|
756
|
+
const thinkingBlock = state.thinkingByIndex.get(event.index);
|
|
757
|
+
if (thinkingBlock) {
|
|
758
|
+
thinkingBlock.thinking += delta.thinking;
|
|
759
|
+
}
|
|
760
|
+
chunks.push({ type: "reasoning-delta", delta: delta.thinking });
|
|
761
|
+
} else if (delta.type === "signature_delta") {
|
|
762
|
+
const thinkingBlock = state.thinkingByIndex.get(event.index);
|
|
763
|
+
if (thinkingBlock) {
|
|
764
|
+
thinkingBlock.signature += delta.signature;
|
|
765
|
+
}
|
|
766
|
+
} else if (delta.type === "input_json_delta") {
|
|
767
|
+
const toolCall = state.toolCallsByIndex.get(event.index);
|
|
768
|
+
if (toolCall) {
|
|
769
|
+
toolCall.argumentsJson += delta.partial_json;
|
|
770
|
+
chunks.push({
|
|
771
|
+
type: "tool-call-delta",
|
|
772
|
+
id: toolCall.id,
|
|
773
|
+
argumentsDelta: delta.partial_json
|
|
774
|
+
});
|
|
775
|
+
} else {
|
|
776
|
+
const serverTool = state.serverToolsByIndex.get(event.index);
|
|
777
|
+
if (serverTool) {
|
|
778
|
+
serverTool.inputJson += delta.partial_json;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
case "content_block_stop": {
|
|
785
|
+
const toolCall = state.toolCallsByIndex.get(event.index);
|
|
786
|
+
if (toolCall) {
|
|
787
|
+
chunks.push({
|
|
788
|
+
type: "tool-call-done",
|
|
789
|
+
id: toolCall.id,
|
|
790
|
+
arguments: parseToolCallArguments(toolCall.argumentsJson)
|
|
791
|
+
});
|
|
792
|
+
state.toolCallsByIndex.delete(event.index);
|
|
793
|
+
break;
|
|
794
|
+
}
|
|
795
|
+
const thinkingBlock = state.thinkingByIndex.get(event.index);
|
|
796
|
+
if (thinkingBlock) {
|
|
797
|
+
state.reasoningDetails.push({
|
|
798
|
+
type: "text",
|
|
799
|
+
text: thinkingBlock.thinking,
|
|
800
|
+
data: thinkingBlock.signature,
|
|
801
|
+
format: THINKING_FORMAT
|
|
802
|
+
});
|
|
803
|
+
state.thinkingByIndex.delete(event.index);
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
const serverTool = state.serverToolsByIndex.get(event.index);
|
|
807
|
+
if (serverTool) {
|
|
808
|
+
state.pendingServerTools.set(serverTool.id, {
|
|
809
|
+
name: serverTool.name,
|
|
810
|
+
input: parseToolCallArguments(serverTool.inputJson)
|
|
811
|
+
});
|
|
812
|
+
state.serverToolsByIndex.delete(event.index);
|
|
813
|
+
}
|
|
814
|
+
break;
|
|
815
|
+
}
|
|
816
|
+
case "message_delta": {
|
|
817
|
+
if (event.delta.stop_reason) {
|
|
818
|
+
state.finishReason = mapFinishReason(event.delta.stop_reason);
|
|
819
|
+
}
|
|
820
|
+
applyDeltaUsage(state, event.usage);
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
case "message_stop": {
|
|
824
|
+
if (state.hasContent) {
|
|
825
|
+
chunks.push({ type: "content-done" });
|
|
826
|
+
}
|
|
827
|
+
if (state.hasReasoning) {
|
|
828
|
+
chunks.push({ type: "reasoning-done" });
|
|
829
|
+
}
|
|
830
|
+
const cost = calculateAnthropicUsageCost(state.model, state.buckets);
|
|
831
|
+
chunks.push({
|
|
832
|
+
type: "finish",
|
|
833
|
+
finishReason: state.finishReason,
|
|
834
|
+
usage: { ...state.usage, ...cost !== void 0 ? { cost } : {} },
|
|
835
|
+
...state.reasoningDetails.length > 0 ? { reasoningDetails: [...state.reasoningDetails] } : {}
|
|
836
|
+
});
|
|
837
|
+
break;
|
|
838
|
+
}
|
|
839
|
+
default:
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
return chunks;
|
|
843
|
+
}
|
|
844
|
+
function createErrorChunk(error, code) {
|
|
845
|
+
return { type: "error", error, code };
|
|
846
|
+
}
|
|
847
|
+
function isBase64Like(str) {
|
|
848
|
+
if (str.startsWith("data:")) return true;
|
|
849
|
+
if (str.length > 200) {
|
|
850
|
+
const base64Pattern = /^[A-Za-z0-9+/]+=*$/;
|
|
851
|
+
return base64Pattern.test(str.substring(0, 200));
|
|
852
|
+
}
|
|
853
|
+
return false;
|
|
854
|
+
}
|
|
855
|
+
function truncateBase64String(str, maxLength = 50) {
|
|
856
|
+
if (str.length <= maxLength) return str;
|
|
857
|
+
const preview = str.substring(0, maxLength);
|
|
858
|
+
return `${preview}...[truncated, ${str.length.toLocaleString()} chars]`;
|
|
859
|
+
}
|
|
860
|
+
function truncateBase64(obj, maxLength = 50) {
|
|
861
|
+
if (obj === null || obj === void 0) {
|
|
862
|
+
return obj;
|
|
863
|
+
}
|
|
864
|
+
if (typeof obj === "string") {
|
|
865
|
+
if (isBase64Like(obj)) {
|
|
866
|
+
return truncateBase64String(obj, maxLength);
|
|
867
|
+
}
|
|
868
|
+
return obj;
|
|
869
|
+
}
|
|
870
|
+
if (Array.isArray(obj)) {
|
|
871
|
+
return obj.map((item) => truncateBase64(item, maxLength));
|
|
872
|
+
}
|
|
873
|
+
if (typeof obj === "object") {
|
|
874
|
+
const result = {};
|
|
875
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
876
|
+
result[key] = truncateBase64(value, maxLength);
|
|
877
|
+
}
|
|
878
|
+
return result;
|
|
879
|
+
}
|
|
880
|
+
return obj;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// src/icons.ts
|
|
884
|
+
var ANTHROPIC_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48" fill="none">
|
|
885
|
+
<rect width="48" height="48" fill="#F0EFEA"/>
|
|
886
|
+
<path d="M32.84 10H26.72L37.88 38H44L32.84 10Z" fill="black"/>
|
|
887
|
+
<path d="M15.16 10L4 38H10.24L12.5224 32.12H24.1976L26.48 38H32.72L21.56 10H15.16ZM14.5408 26.92L18.36 17.08L22.1793 26.92H14.5408Z" fill="black"/>
|
|
888
|
+
</svg>`;
|
|
889
|
+
function svgToDataUri(svg) {
|
|
890
|
+
const encoded = encodeURIComponent(svg).replace(/'/g, "%27").replace(/"/g, "%22");
|
|
891
|
+
return `data:image/svg+xml,${encoded}`;
|
|
892
|
+
}
|
|
893
|
+
function normalizeIcon(icon) {
|
|
894
|
+
if (icon.startsWith("data:") || icon.endsWith(".svg") || icon.includes(".svg?")) {
|
|
895
|
+
return icon;
|
|
896
|
+
}
|
|
897
|
+
return svgToDataUri(icon);
|
|
898
|
+
}
|
|
899
|
+
function getAnthropicIconDataUri() {
|
|
900
|
+
return normalizeIcon(ANTHROPIC_ICON);
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// src/AnthropicProvider.ts
|
|
904
|
+
function isObjectLike(value) {
|
|
905
|
+
return typeof value === "object" && value !== null;
|
|
906
|
+
}
|
|
907
|
+
function parseRetryAfter(headers) {
|
|
908
|
+
let raw;
|
|
909
|
+
if (isObjectLike(headers)) {
|
|
910
|
+
const get = headers.get;
|
|
911
|
+
if (typeof get === "function") {
|
|
912
|
+
raw = get.call(headers, "retry-after");
|
|
913
|
+
} else {
|
|
914
|
+
raw = headers["retry-after"];
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
if (typeof raw === "number") {
|
|
918
|
+
return raw;
|
|
919
|
+
}
|
|
920
|
+
if (typeof raw === "string") {
|
|
921
|
+
const parsed = parseInt(raw, 10);
|
|
922
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
923
|
+
}
|
|
924
|
+
return void 0;
|
|
925
|
+
}
|
|
926
|
+
var ADAPTIVE_REASONING_LEVELS = DEFAULT_REASONING_LEVELS;
|
|
927
|
+
var BUDGET_REASONING_LEVELS = { 0: null, 100: "enabled" };
|
|
928
|
+
var NO_REASONING_LEVELS = { 0: null };
|
|
929
|
+
var AnthropicProvider = class _AnthropicProvider {
|
|
930
|
+
name = "anthropic";
|
|
931
|
+
specificationVersion = "1";
|
|
932
|
+
client = null;
|
|
933
|
+
config;
|
|
934
|
+
/** Cache for models list to avoid repeated API calls */
|
|
935
|
+
static modelsCache = null;
|
|
936
|
+
static modelsCacheTime = 0;
|
|
937
|
+
static CACHE_TTL = 5 * 60 * 1e3;
|
|
938
|
+
// 5 minutes
|
|
939
|
+
constructor(config) {
|
|
940
|
+
this.config = config;
|
|
941
|
+
}
|
|
942
|
+
async getClient() {
|
|
943
|
+
if (!this.client) {
|
|
944
|
+
const { default: Anthropic } = await import("@anthropic-ai/sdk");
|
|
945
|
+
this.client = new Anthropic({
|
|
946
|
+
apiKey: this.config.apiKey,
|
|
947
|
+
baseURL: this.config.baseUrl,
|
|
948
|
+
timeout: this.config.timeout
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
return this.client;
|
|
952
|
+
}
|
|
953
|
+
supportsModel(modelId) {
|
|
954
|
+
return modelId.startsWith("claude-");
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Get the icon for this provider as a data URI.
|
|
958
|
+
* Always returns the Anthropic icon since all models are from Anthropic.
|
|
959
|
+
*/
|
|
960
|
+
getIcon(_modelId) {
|
|
961
|
+
return getAnthropicIconDataUri();
|
|
962
|
+
}
|
|
963
|
+
// ============================================================================
|
|
964
|
+
// Model Capabilities
|
|
965
|
+
// ============================================================================
|
|
966
|
+
/**
|
|
967
|
+
* Capability mappings for Anthropic models, keyed by model ID prefix.
|
|
968
|
+
* Used as a fallback when the live Models API is unavailable; the API's
|
|
969
|
+
* capability listing takes precedence when reachable.
|
|
970
|
+
*/
|
|
971
|
+
static MODEL_CAPABILITIES = {
|
|
972
|
+
"claude-fable-5": {
|
|
973
|
+
supportsImages: true,
|
|
974
|
+
supportsToolCalls: true,
|
|
975
|
+
supportsStreaming: true,
|
|
976
|
+
supportsJsonMode: true,
|
|
977
|
+
maxContextTokens: 1e6,
|
|
978
|
+
maxOutputTokens: 128e3,
|
|
979
|
+
reasoningLevels: ADAPTIVE_REASONING_LEVELS
|
|
980
|
+
},
|
|
981
|
+
"claude-mythos": {
|
|
982
|
+
supportsImages: true,
|
|
983
|
+
supportsToolCalls: true,
|
|
984
|
+
supportsStreaming: true,
|
|
985
|
+
supportsJsonMode: true,
|
|
986
|
+
maxContextTokens: 1e6,
|
|
987
|
+
maxOutputTokens: 128e3,
|
|
988
|
+
reasoningLevels: ADAPTIVE_REASONING_LEVELS
|
|
989
|
+
},
|
|
990
|
+
"claude-opus-4-8": {
|
|
991
|
+
supportsImages: true,
|
|
992
|
+
supportsToolCalls: true,
|
|
993
|
+
supportsStreaming: true,
|
|
994
|
+
supportsJsonMode: true,
|
|
995
|
+
maxContextTokens: 1e6,
|
|
996
|
+
maxOutputTokens: 128e3,
|
|
997
|
+
reasoningLevels: ADAPTIVE_REASONING_LEVELS
|
|
998
|
+
},
|
|
999
|
+
"claude-opus-4-7": {
|
|
1000
|
+
supportsImages: true,
|
|
1001
|
+
supportsToolCalls: true,
|
|
1002
|
+
supportsStreaming: true,
|
|
1003
|
+
supportsJsonMode: true,
|
|
1004
|
+
maxContextTokens: 1e6,
|
|
1005
|
+
maxOutputTokens: 128e3,
|
|
1006
|
+
reasoningLevels: ADAPTIVE_REASONING_LEVELS
|
|
1007
|
+
},
|
|
1008
|
+
"claude-opus-4-6": {
|
|
1009
|
+
supportsImages: true,
|
|
1010
|
+
supportsToolCalls: true,
|
|
1011
|
+
supportsStreaming: true,
|
|
1012
|
+
supportsJsonMode: true,
|
|
1013
|
+
maxContextTokens: 1e6,
|
|
1014
|
+
maxOutputTokens: 128e3,
|
|
1015
|
+
reasoningLevels: ADAPTIVE_REASONING_LEVELS
|
|
1016
|
+
},
|
|
1017
|
+
"claude-opus-4-5": {
|
|
1018
|
+
supportsImages: true,
|
|
1019
|
+
supportsToolCalls: true,
|
|
1020
|
+
supportsStreaming: true,
|
|
1021
|
+
supportsJsonMode: true,
|
|
1022
|
+
maxContextTokens: 2e5,
|
|
1023
|
+
maxOutputTokens: 64e3,
|
|
1024
|
+
reasoningLevels: BUDGET_REASONING_LEVELS
|
|
1025
|
+
},
|
|
1026
|
+
"claude-opus-4-1": {
|
|
1027
|
+
supportsImages: true,
|
|
1028
|
+
supportsToolCalls: true,
|
|
1029
|
+
supportsStreaming: true,
|
|
1030
|
+
supportsJsonMode: false,
|
|
1031
|
+
maxContextTokens: 2e5,
|
|
1032
|
+
maxOutputTokens: 32e3,
|
|
1033
|
+
reasoningLevels: BUDGET_REASONING_LEVELS
|
|
1034
|
+
},
|
|
1035
|
+
"claude-opus-4": {
|
|
1036
|
+
supportsImages: true,
|
|
1037
|
+
supportsToolCalls: true,
|
|
1038
|
+
supportsStreaming: true,
|
|
1039
|
+
supportsJsonMode: false,
|
|
1040
|
+
maxContextTokens: 2e5,
|
|
1041
|
+
maxOutputTokens: 32e3,
|
|
1042
|
+
reasoningLevels: BUDGET_REASONING_LEVELS
|
|
1043
|
+
},
|
|
1044
|
+
"claude-sonnet-4-6": {
|
|
1045
|
+
supportsImages: true,
|
|
1046
|
+
supportsToolCalls: true,
|
|
1047
|
+
supportsStreaming: true,
|
|
1048
|
+
supportsJsonMode: true,
|
|
1049
|
+
maxContextTokens: 1e6,
|
|
1050
|
+
maxOutputTokens: 64e3,
|
|
1051
|
+
reasoningLevels: ADAPTIVE_REASONING_LEVELS
|
|
1052
|
+
},
|
|
1053
|
+
"claude-sonnet-4-5": {
|
|
1054
|
+
supportsImages: true,
|
|
1055
|
+
supportsToolCalls: true,
|
|
1056
|
+
supportsStreaming: true,
|
|
1057
|
+
supportsJsonMode: true,
|
|
1058
|
+
maxContextTokens: 2e5,
|
|
1059
|
+
maxOutputTokens: 64e3,
|
|
1060
|
+
reasoningLevels: BUDGET_REASONING_LEVELS
|
|
1061
|
+
},
|
|
1062
|
+
"claude-sonnet-4": {
|
|
1063
|
+
supportsImages: true,
|
|
1064
|
+
supportsToolCalls: true,
|
|
1065
|
+
supportsStreaming: true,
|
|
1066
|
+
supportsJsonMode: false,
|
|
1067
|
+
maxContextTokens: 2e5,
|
|
1068
|
+
maxOutputTokens: 64e3,
|
|
1069
|
+
reasoningLevels: BUDGET_REASONING_LEVELS
|
|
1070
|
+
},
|
|
1071
|
+
"claude-haiku-4-5": {
|
|
1072
|
+
supportsImages: true,
|
|
1073
|
+
supportsToolCalls: true,
|
|
1074
|
+
supportsStreaming: true,
|
|
1075
|
+
supportsJsonMode: true,
|
|
1076
|
+
maxContextTokens: 2e5,
|
|
1077
|
+
maxOutputTokens: 64e3,
|
|
1078
|
+
reasoningLevels: BUDGET_REASONING_LEVELS
|
|
1079
|
+
},
|
|
1080
|
+
"claude-3-7-sonnet": {
|
|
1081
|
+
supportsImages: true,
|
|
1082
|
+
supportsToolCalls: true,
|
|
1083
|
+
supportsStreaming: true,
|
|
1084
|
+
supportsJsonMode: false,
|
|
1085
|
+
maxContextTokens: 2e5,
|
|
1086
|
+
maxOutputTokens: 64e3,
|
|
1087
|
+
reasoningLevels: BUDGET_REASONING_LEVELS
|
|
1088
|
+
},
|
|
1089
|
+
"claude-3-5-sonnet": {
|
|
1090
|
+
supportsImages: true,
|
|
1091
|
+
supportsToolCalls: true,
|
|
1092
|
+
supportsStreaming: true,
|
|
1093
|
+
supportsJsonMode: false,
|
|
1094
|
+
maxContextTokens: 2e5,
|
|
1095
|
+
maxOutputTokens: 8192,
|
|
1096
|
+
reasoningLevels: NO_REASONING_LEVELS
|
|
1097
|
+
},
|
|
1098
|
+
"claude-3-5-haiku": {
|
|
1099
|
+
supportsImages: true,
|
|
1100
|
+
supportsToolCalls: true,
|
|
1101
|
+
supportsStreaming: true,
|
|
1102
|
+
supportsJsonMode: false,
|
|
1103
|
+
maxContextTokens: 2e5,
|
|
1104
|
+
maxOutputTokens: 8192,
|
|
1105
|
+
reasoningLevels: NO_REASONING_LEVELS
|
|
1106
|
+
},
|
|
1107
|
+
"claude-3-opus": {
|
|
1108
|
+
supportsImages: true,
|
|
1109
|
+
supportsToolCalls: true,
|
|
1110
|
+
supportsStreaming: true,
|
|
1111
|
+
supportsJsonMode: false,
|
|
1112
|
+
maxContextTokens: 2e5,
|
|
1113
|
+
maxOutputTokens: 4096,
|
|
1114
|
+
reasoningLevels: NO_REASONING_LEVELS
|
|
1115
|
+
},
|
|
1116
|
+
"claude-3-haiku": {
|
|
1117
|
+
supportsImages: true,
|
|
1118
|
+
supportsToolCalls: true,
|
|
1119
|
+
supportsStreaming: true,
|
|
1120
|
+
supportsJsonMode: false,
|
|
1121
|
+
maxContextTokens: 2e5,
|
|
1122
|
+
maxOutputTokens: 4096,
|
|
1123
|
+
reasoningLevels: NO_REASONING_LEVELS
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
/**
|
|
1127
|
+
* Look up static capabilities for a model by exact then prefix match.
|
|
1128
|
+
*/
|
|
1129
|
+
static lookupStaticCapabilities(modelId) {
|
|
1130
|
+
if (_AnthropicProvider.MODEL_CAPABILITIES[modelId]) {
|
|
1131
|
+
return { ..._AnthropicProvider.MODEL_CAPABILITIES[modelId] };
|
|
1132
|
+
}
|
|
1133
|
+
let best = null;
|
|
1134
|
+
for (const [prefix, caps] of Object.entries(_AnthropicProvider.MODEL_CAPABILITIES)) {
|
|
1135
|
+
if (modelId.startsWith(prefix) && (!best || prefix.length > best.prefix.length)) {
|
|
1136
|
+
best = { prefix, caps };
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
return best ? { ...best.caps } : null;
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Map a live Models API capability listing to Standard Agents capabilities.
|
|
1143
|
+
*/
|
|
1144
|
+
static mapLiveCapabilities(model) {
|
|
1145
|
+
const caps = model.capabilities;
|
|
1146
|
+
if (!caps) return null;
|
|
1147
|
+
let reasoningLevels;
|
|
1148
|
+
if (caps.thinking.types.adaptive.supported && caps.effort.supported) {
|
|
1149
|
+
reasoningLevels = ADAPTIVE_REASONING_LEVELS;
|
|
1150
|
+
} else if (caps.thinking.supported) {
|
|
1151
|
+
reasoningLevels = BUDGET_REASONING_LEVELS;
|
|
1152
|
+
} else {
|
|
1153
|
+
reasoningLevels = NO_REASONING_LEVELS;
|
|
1154
|
+
}
|
|
1155
|
+
return {
|
|
1156
|
+
supportsImages: caps.image_input.supported,
|
|
1157
|
+
supportsToolCalls: true,
|
|
1158
|
+
supportsStreaming: true,
|
|
1159
|
+
supportsJsonMode: caps.structured_outputs.supported,
|
|
1160
|
+
...model.max_input_tokens ? { maxContextTokens: model.max_input_tokens } : {},
|
|
1161
|
+
...model.max_tokens ? { maxOutputTokens: model.max_tokens } : {},
|
|
1162
|
+
reasoningLevels
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Get capabilities for a specific model.
|
|
1167
|
+
* Prefers the live Models API (which reports per-model capability flags)
|
|
1168
|
+
* and falls back to the static prefix table when the API is unreachable.
|
|
1169
|
+
*/
|
|
1170
|
+
async getModelCapabilities(modelId) {
|
|
1171
|
+
try {
|
|
1172
|
+
const models = await this.fetchModelsWithCache();
|
|
1173
|
+
const model = models.find((m) => m.id === modelId);
|
|
1174
|
+
if (model) {
|
|
1175
|
+
const live = _AnthropicProvider.mapLiveCapabilities(model);
|
|
1176
|
+
if (live) {
|
|
1177
|
+
return live;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
} catch {
|
|
1181
|
+
}
|
|
1182
|
+
const staticCaps = _AnthropicProvider.lookupStaticCapabilities(modelId);
|
|
1183
|
+
if (staticCaps) {
|
|
1184
|
+
return staticCaps;
|
|
1185
|
+
}
|
|
1186
|
+
return {
|
|
1187
|
+
supportsImages: true,
|
|
1188
|
+
supportsToolCalls: true,
|
|
1189
|
+
supportsStreaming: true,
|
|
1190
|
+
supportsJsonMode: true,
|
|
1191
|
+
maxContextTokens: 2e5,
|
|
1192
|
+
maxOutputTokens: 8192,
|
|
1193
|
+
reasoningLevels: ADAPTIVE_REASONING_LEVELS
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
// ============================================================================
|
|
1197
|
+
// Provider-Embedded Tools
|
|
1198
|
+
// ============================================================================
|
|
1199
|
+
/**
|
|
1200
|
+
* Provider-embedded tools using defineTool().
|
|
1201
|
+
* These are Anthropic's server-side tools that execute on Anthropic's
|
|
1202
|
+
* servers. The execute function is a no-op since execution is handled by
|
|
1203
|
+
* the provider; results surface as providerTools entries on the response.
|
|
1204
|
+
*/
|
|
1205
|
+
static TOOLS = {
|
|
1206
|
+
web_search: defineTool({
|
|
1207
|
+
description: "Search the web for up-to-date information with citations",
|
|
1208
|
+
args: z.object({
|
|
1209
|
+
query: z.string().describe("Search query")
|
|
1210
|
+
}),
|
|
1211
|
+
execute: async (_state, _args) => {
|
|
1212
|
+
return { status: "success", result: "Handled by Anthropic" };
|
|
1213
|
+
},
|
|
1214
|
+
executionMode: "provider",
|
|
1215
|
+
executionProvider: "anthropic"
|
|
1216
|
+
})
|
|
1217
|
+
};
|
|
1218
|
+
/**
|
|
1219
|
+
* Get tools embedded in this provider.
|
|
1220
|
+
* Anthropic's web_search server tool is available on all current models.
|
|
1221
|
+
*
|
|
1222
|
+
* @param modelId - Optional filter to get tools available for a specific model
|
|
1223
|
+
* @returns Record of tool name to tool definition
|
|
1224
|
+
*/
|
|
1225
|
+
getTools(_modelId) {
|
|
1226
|
+
return { ..._AnthropicProvider.TOOLS };
|
|
1227
|
+
}
|
|
1228
|
+
// ============================================================================
|
|
1229
|
+
// Model Listing
|
|
1230
|
+
// ============================================================================
|
|
1231
|
+
/**
|
|
1232
|
+
* Fetch models from the Anthropic Models API with caching.
|
|
1233
|
+
*/
|
|
1234
|
+
async fetchModelsWithCache() {
|
|
1235
|
+
const now = Date.now();
|
|
1236
|
+
if (_AnthropicProvider.modelsCache && now - _AnthropicProvider.modelsCacheTime < _AnthropicProvider.CACHE_TTL) {
|
|
1237
|
+
return _AnthropicProvider.modelsCache;
|
|
1238
|
+
}
|
|
1239
|
+
const client = await this.getClient();
|
|
1240
|
+
const models = [];
|
|
1241
|
+
for await (const model of client.models.list({ limit: 100 })) {
|
|
1242
|
+
models.push(model);
|
|
1243
|
+
}
|
|
1244
|
+
_AnthropicProvider.modelsCache = models;
|
|
1245
|
+
_AnthropicProvider.modelsCacheTime = now;
|
|
1246
|
+
return models;
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Map Anthropic model info to ProviderModelInfo.
|
|
1250
|
+
*/
|
|
1251
|
+
mapToProviderModelInfo(model) {
|
|
1252
|
+
const capabilities = _AnthropicProvider.mapLiveCapabilities(model) ?? _AnthropicProvider.lookupStaticCapabilities(model.id) ?? void 0;
|
|
1253
|
+
return {
|
|
1254
|
+
id: model.id,
|
|
1255
|
+
name: model.display_name,
|
|
1256
|
+
contextLength: model.max_input_tokens ?? capabilities?.maxContextTokens,
|
|
1257
|
+
iconId: this.getIcon(model.id),
|
|
1258
|
+
...capabilities ? { capabilities } : {}
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* Get list of available models from Anthropic.
|
|
1263
|
+
* Fetches from the Models API with caching.
|
|
1264
|
+
*
|
|
1265
|
+
* @param filter - Optional search string to filter models by name/id
|
|
1266
|
+
*/
|
|
1267
|
+
async getModels(filter) {
|
|
1268
|
+
try {
|
|
1269
|
+
const rawModels = await this.fetchModelsWithCache();
|
|
1270
|
+
let models = rawModels.map((m) => this.mapToProviderModelInfo(m));
|
|
1271
|
+
if (filter) {
|
|
1272
|
+
const lowerFilter = filter.toLowerCase();
|
|
1273
|
+
models = models.filter(
|
|
1274
|
+
(m) => m.id.toLowerCase().includes(lowerFilter) || m.name.toLowerCase().includes(lowerFilter)
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1277
|
+
return models;
|
|
1278
|
+
} catch (error) {
|
|
1279
|
+
console.error("Failed to fetch models from Anthropic:", error);
|
|
1280
|
+
return [];
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
// ============================================================================
|
|
1284
|
+
// Generation Methods
|
|
1285
|
+
// ============================================================================
|
|
1286
|
+
/**
|
|
1287
|
+
* Resolve the default max_tokens for a model from the static capability
|
|
1288
|
+
* table, clamped so non-streaming requests stay under HTTP timeouts.
|
|
1289
|
+
*/
|
|
1290
|
+
defaultMaxTokensFor(modelId) {
|
|
1291
|
+
const caps = _AnthropicProvider.lookupStaticCapabilities(modelId);
|
|
1292
|
+
return Math.min(caps?.maxOutputTokens ?? 8192, 8192);
|
|
1293
|
+
}
|
|
1294
|
+
async generate(request) {
|
|
1295
|
+
const client = await this.getClient();
|
|
1296
|
+
try {
|
|
1297
|
+
const params = buildCreateParams(
|
|
1298
|
+
request,
|
|
1299
|
+
DEFAULT_REASONING_LEVELS,
|
|
1300
|
+
this.defaultMaxTokensFor(request.model)
|
|
1301
|
+
);
|
|
1302
|
+
const response = await client.messages.create(
|
|
1303
|
+
{ ...params, stream: false },
|
|
1304
|
+
{ signal: request.signal }
|
|
1305
|
+
);
|
|
1306
|
+
return transformResponse(response);
|
|
1307
|
+
} catch (error) {
|
|
1308
|
+
throw this.toProviderError(error);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
async stream(request) {
|
|
1312
|
+
const client = await this.getClient();
|
|
1313
|
+
const self = this;
|
|
1314
|
+
try {
|
|
1315
|
+
const params = buildCreateParams(
|
|
1316
|
+
request,
|
|
1317
|
+
DEFAULT_REASONING_LEVELS,
|
|
1318
|
+
this.defaultMaxTokensFor(request.model)
|
|
1319
|
+
);
|
|
1320
|
+
const stream = await client.messages.create(
|
|
1321
|
+
{ ...params, stream: true },
|
|
1322
|
+
{ signal: request.signal }
|
|
1323
|
+
);
|
|
1324
|
+
return {
|
|
1325
|
+
async *[Symbol.asyncIterator]() {
|
|
1326
|
+
const state = createStreamState();
|
|
1327
|
+
try {
|
|
1328
|
+
for await (const event of stream) {
|
|
1329
|
+
const chunks = processStreamEvent(event, state);
|
|
1330
|
+
for (const chunk of chunks) {
|
|
1331
|
+
yield chunk;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
} catch (error) {
|
|
1335
|
+
const providerError = self.toProviderError(error);
|
|
1336
|
+
yield createErrorChunk(providerError.message, providerError.code);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
};
|
|
1340
|
+
} catch (error) {
|
|
1341
|
+
throw this.toProviderError(error);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
// ============================================================================
|
|
1345
|
+
// Error Handling
|
|
1346
|
+
// ============================================================================
|
|
1347
|
+
toProviderError(error) {
|
|
1348
|
+
if (error instanceof ProviderError) {
|
|
1349
|
+
return error;
|
|
1350
|
+
}
|
|
1351
|
+
const record = isObjectLike(error) ? error : null;
|
|
1352
|
+
const status = typeof record?.status === "number" ? record.status : typeof record?.statusCode === "number" ? record.statusCode : void 0;
|
|
1353
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1354
|
+
if (status === 429) {
|
|
1355
|
+
return new ProviderError(message, "rate_limit", status, parseRetryAfter(record?.headers));
|
|
1356
|
+
}
|
|
1357
|
+
if (status === 401 || status === 403) {
|
|
1358
|
+
return new ProviderError(message, "auth_error", status);
|
|
1359
|
+
}
|
|
1360
|
+
if (status === 400 || status === 404 || status === 413) {
|
|
1361
|
+
return new ProviderError(message, "invalid_request", status);
|
|
1362
|
+
}
|
|
1363
|
+
if (status !== void 0 && status >= 500) {
|
|
1364
|
+
return new ProviderError(message, "server_error", status);
|
|
1365
|
+
}
|
|
1366
|
+
if (error instanceof Error && error.name === "AbortError" || record?.code === "ETIMEDOUT") {
|
|
1367
|
+
return new ProviderError(message, "timeout");
|
|
1368
|
+
}
|
|
1369
|
+
return new ProviderError(message, "unknown", status);
|
|
1370
|
+
}
|
|
1371
|
+
// ============================================================================
|
|
1372
|
+
// Inspection
|
|
1373
|
+
// ============================================================================
|
|
1374
|
+
/**
|
|
1375
|
+
* Transform a ProviderRequest to Anthropic Messages API format for inspection.
|
|
1376
|
+
* Returns the exact request body that would be sent, with base64 data truncated.
|
|
1377
|
+
*/
|
|
1378
|
+
async inspectRequest(request) {
|
|
1379
|
+
const params = buildCreateParams(
|
|
1380
|
+
request,
|
|
1381
|
+
DEFAULT_REASONING_LEVELS,
|
|
1382
|
+
this.defaultMaxTokensFor(request.model)
|
|
1383
|
+
);
|
|
1384
|
+
const body = JSON.parse(JSON.stringify(params));
|
|
1385
|
+
return {
|
|
1386
|
+
body: truncateBase64(body),
|
|
1387
|
+
messagesPath: "messages",
|
|
1388
|
+
metadata: {
|
|
1389
|
+
endpoint: "messages.create"
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
|
|
1395
|
+
// src/providerOptions.ts
|
|
1396
|
+
import { z as z2 } from "zod";
|
|
1397
|
+
var anthropicProviderOptions = z2.object({
|
|
1398
|
+
/** Request priority tier: 'auto' uses priority capacity when available, 'standard_only' opts out */
|
|
1399
|
+
service_tier: z2.enum(["auto", "standard_only"]).optional(),
|
|
1400
|
+
/** Request metadata. user_id is an opaque identifier for abuse monitoring */
|
|
1401
|
+
metadata: z2.object({
|
|
1402
|
+
user_id: z2.string().optional()
|
|
1403
|
+
}).optional(),
|
|
1404
|
+
/**
|
|
1405
|
+
* Cache the system prompt with a prompt-caching breakpoint.
|
|
1406
|
+
* Adds `cache_control: { type: 'ephemeral' }` to the system prompt so
|
|
1407
|
+
* repeated requests with the same prefix bill cached-input rates.
|
|
1408
|
+
*/
|
|
1409
|
+
cacheSystemPrompt: z2.boolean().optional(),
|
|
1410
|
+
/**
|
|
1411
|
+
* Explicit thinking configuration override. When set, this takes precedence
|
|
1412
|
+
* over the thinking config derived from the request's reasoning level.
|
|
1413
|
+
* Accepts the Anthropic API shape, e.g. `{ type: 'adaptive' }` or
|
|
1414
|
+
* `{ type: 'enabled', budget_tokens: 8192 }`.
|
|
1415
|
+
*/
|
|
1416
|
+
thinking: z2.record(z2.string(), z2.unknown()).optional()
|
|
1417
|
+
}).passthrough();
|
|
1418
|
+
|
|
1419
|
+
// src/index.ts
|
|
1420
|
+
var anthropic = Object.assign(
|
|
1421
|
+
(config) => new AnthropicProvider(config),
|
|
1422
|
+
{ providerOptions: anthropicProviderOptions }
|
|
1423
|
+
);
|
|
1424
|
+
export {
|
|
1425
|
+
AnthropicProvider,
|
|
1426
|
+
anthropic,
|
|
1427
|
+
anthropicProviderOptions,
|
|
1428
|
+
calculateAnthropicUsageCost,
|
|
1429
|
+
extractUsageBuckets,
|
|
1430
|
+
getAnthropicModelPricing
|
|
1431
|
+
};
|
|
1432
|
+
//# sourceMappingURL=index.js.map
|