@better-agent/providers 0.1.0-canary.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.
@@ -0,0 +1,1909 @@
1
+ import { n as extractPassthroughOptions, r as omitNullish, t as baFetch } from "../fetch-CW0dWlVC.mjs";
2
+ import { Events } from "@better-agent/core/events";
3
+ import { BetterAgentError } from "@better-agent/shared/errors";
4
+ import { err, ok } from "@better-agent/shared/neverthrow";
5
+ import { z } from "zod";
6
+ import { safeJsonParse } from "@better-agent/shared/utils";
7
+ import { TOOL_JSON_SCHEMA, isCallableToolDefinition } from "@better-agent/core";
8
+
9
+ //#region src/anthropic/client/auth.ts
10
+ const buildAnthropicHeaders = (config, options = {}) => {
11
+ const headers = {
12
+ "anthropic-version": config.anthropicVersion ?? "2023-06-01",
13
+ ...config.headers ?? {},
14
+ ...options.headers ?? {}
15
+ };
16
+ if (config.authToken) headers.Authorization = `Bearer ${config.authToken}`;
17
+ else if (config.apiKey) headers["x-api-key"] = config.apiKey;
18
+ if (options.beta?.length) headers["anthropic-beta"] = options.beta.join(",");
19
+ return headers;
20
+ };
21
+
22
+ //#endregion
23
+ //#region src/anthropic/client/errors.ts
24
+ const mapAnthropicHttpError = (httpError, ctx) => {
25
+ if (!httpError) return BetterAgentError.fromCode("UPSTREAM_FAILED", "Anthropic request failed", { context: { provider: "anthropic" } }).at({
26
+ at: ctx.at,
27
+ data: { path: ctx.path }
28
+ });
29
+ const { status, statusText, error } = httpError;
30
+ const message = error?.message ?? statusText ?? "Anthropic request failed";
31
+ const code = String(error?.type ?? status);
32
+ return BetterAgentError.fromCode("UPSTREAM_FAILED", message, {
33
+ status,
34
+ context: {
35
+ provider: "anthropic",
36
+ upstreamCode: code,
37
+ raw: error
38
+ }
39
+ }).at({
40
+ at: ctx.at,
41
+ data: {
42
+ path: ctx.path,
43
+ status
44
+ }
45
+ });
46
+ };
47
+
48
+ //#endregion
49
+ //#region src/anthropic/responses/schemas.ts
50
+ const ANTHROPIC_KNOWN_RESPONSE_MODELS = [
51
+ "claude-3-haiku-20240307",
52
+ "claude-haiku-4-5-20251001",
53
+ "claude-haiku-4-5",
54
+ "claude-opus-4-0",
55
+ "claude-opus-4-20250514",
56
+ "claude-opus-4-1-20250805",
57
+ "claude-opus-4-1",
58
+ "claude-opus-4-5",
59
+ "claude-opus-4-5-20251101",
60
+ "claude-sonnet-4-0",
61
+ "claude-sonnet-4-20250514",
62
+ "claude-sonnet-4-5-20250929",
63
+ "claude-sonnet-4-5",
64
+ "claude-sonnet-4-6",
65
+ "claude-opus-4-6"
66
+ ];
67
+ const AnthropicKnownResponseModelsSchema = z.enum(ANTHROPIC_KNOWN_RESPONSE_MODELS);
68
+ const AnthropicResponseModelIdSchema = z.string();
69
+ const AnthropicCacheControlSchema = z.object({
70
+ type: z.literal("ephemeral"),
71
+ ttl: z.enum(["5m", "1h"]).optional()
72
+ });
73
+ const AnthropicTextContentSchema = z.object({
74
+ type: z.literal("text"),
75
+ text: z.string(),
76
+ citations: z.array(z.unknown()).optional(),
77
+ cache_control: AnthropicCacheControlSchema.optional()
78
+ });
79
+ const AnthropicThinkingContentSchema = z.object({
80
+ type: z.literal("thinking"),
81
+ thinking: z.string(),
82
+ signature: z.string()
83
+ });
84
+ const AnthropicRedactedThinkingContentSchema = z.object({
85
+ type: z.literal("redacted_thinking"),
86
+ data: z.string()
87
+ });
88
+ const AnthropicContentSourceSchema = z.discriminatedUnion("type", [
89
+ z.object({
90
+ type: z.literal("base64"),
91
+ media_type: z.string(),
92
+ data: z.string()
93
+ }),
94
+ z.object({
95
+ type: z.literal("url"),
96
+ url: z.string()
97
+ }),
98
+ z.object({
99
+ type: z.literal("text"),
100
+ media_type: z.literal("text/plain"),
101
+ data: z.string()
102
+ })
103
+ ]);
104
+ const AnthropicImageContentSchema = z.object({
105
+ type: z.literal("image"),
106
+ source: AnthropicContentSourceSchema,
107
+ cache_control: AnthropicCacheControlSchema.optional()
108
+ });
109
+ const AnthropicDocumentContentSchema = z.object({
110
+ type: z.literal("document"),
111
+ source: AnthropicContentSourceSchema,
112
+ title: z.string().optional(),
113
+ context: z.string().optional(),
114
+ citations: z.object({ enabled: z.boolean() }).optional(),
115
+ cache_control: AnthropicCacheControlSchema.optional()
116
+ });
117
+ const AnthropicToolResultContentSchema = z.object({
118
+ type: z.literal("tool_result"),
119
+ tool_use_id: z.string(),
120
+ content: z.union([z.string(), z.array(z.unknown())]),
121
+ is_error: z.boolean().optional(),
122
+ cache_control: AnthropicCacheControlSchema.optional()
123
+ });
124
+ const AnthropicToolCallContentSchema = z.object({
125
+ type: z.literal("tool_use"),
126
+ id: z.string(),
127
+ name: z.string(),
128
+ input: z.unknown(),
129
+ cache_control: AnthropicCacheControlSchema.optional()
130
+ });
131
+ const AnthropicServerToolUseContentSchema = z.object({
132
+ type: z.literal("server_tool_use"),
133
+ id: z.string(),
134
+ name: z.enum([
135
+ "web_fetch",
136
+ "web_search",
137
+ "code_execution",
138
+ "bash_code_execution",
139
+ "text_editor_code_execution",
140
+ "tool_search_tool_regex",
141
+ "tool_search_tool_bm25"
142
+ ]),
143
+ input: z.unknown(),
144
+ cache_control: AnthropicCacheControlSchema.optional()
145
+ });
146
+ const AnthropicProviderToolResultSchema = z.object({
147
+ tool_use_id: z.string(),
148
+ cache_control: AnthropicCacheControlSchema.optional()
149
+ }).passthrough();
150
+ const AnthropicWebSearchToolResultContentSchema = AnthropicProviderToolResultSchema.extend({
151
+ type: z.literal("web_search_tool_result"),
152
+ content: z.array(z.object({
153
+ url: z.string(),
154
+ title: z.string().nullable(),
155
+ page_age: z.string().nullable(),
156
+ encrypted_content: z.string(),
157
+ type: z.string()
158
+ }))
159
+ });
160
+ const AnthropicWebFetchToolResultContentSchema = AnthropicProviderToolResultSchema.extend({
161
+ type: z.literal("web_fetch_tool_result"),
162
+ content: z.unknown()
163
+ });
164
+ const AnthropicToolSearchToolResultContentSchema = AnthropicProviderToolResultSchema.extend({
165
+ type: z.literal("tool_search_tool_result"),
166
+ content: z.unknown()
167
+ });
168
+ const AnthropicCodeExecutionToolResultContentSchema = AnthropicProviderToolResultSchema.extend({
169
+ type: z.literal("code_execution_tool_result"),
170
+ content: z.unknown()
171
+ });
172
+ const AnthropicBashCodeExecutionToolResultContentSchema = AnthropicProviderToolResultSchema.extend({
173
+ type: z.literal("bash_code_execution_tool_result"),
174
+ content: z.unknown()
175
+ });
176
+ const AnthropicTextEditorCodeExecutionToolResultContentSchema = AnthropicProviderToolResultSchema.extend({
177
+ type: z.literal("text_editor_code_execution_tool_result"),
178
+ content: z.unknown()
179
+ });
180
+ const AnthropicMcpToolUseContentSchema = z.object({
181
+ type: z.literal("mcp_tool_use"),
182
+ id: z.string(),
183
+ name: z.string(),
184
+ server_name: z.string().optional(),
185
+ input: z.unknown(),
186
+ cache_control: AnthropicCacheControlSchema.optional()
187
+ }).passthrough();
188
+ const AnthropicMcpToolResultContentSchema = z.object({
189
+ type: z.literal("mcp_tool_result"),
190
+ tool_use_id: z.string(),
191
+ content: z.unknown(),
192
+ is_error: z.boolean().optional(),
193
+ cache_control: AnthropicCacheControlSchema.optional()
194
+ }).passthrough();
195
+ const AnthropicCompactionContentSchema = z.object({
196
+ type: z.literal("compaction"),
197
+ content: z.string(),
198
+ cache_control: AnthropicCacheControlSchema.optional()
199
+ });
200
+ const AnthropicResponseContentBlockSchema = z.discriminatedUnion("type", [
201
+ AnthropicTextContentSchema,
202
+ AnthropicThinkingContentSchema,
203
+ AnthropicRedactedThinkingContentSchema,
204
+ AnthropicImageContentSchema,
205
+ AnthropicDocumentContentSchema,
206
+ AnthropicToolResultContentSchema,
207
+ AnthropicToolCallContentSchema,
208
+ AnthropicServerToolUseContentSchema,
209
+ AnthropicWebSearchToolResultContentSchema,
210
+ AnthropicWebFetchToolResultContentSchema,
211
+ AnthropicToolSearchToolResultContentSchema,
212
+ AnthropicCodeExecutionToolResultContentSchema,
213
+ AnthropicBashCodeExecutionToolResultContentSchema,
214
+ AnthropicTextEditorCodeExecutionToolResultContentSchema,
215
+ AnthropicMcpToolUseContentSchema,
216
+ AnthropicMcpToolResultContentSchema,
217
+ AnthropicCompactionContentSchema
218
+ ]);
219
+ const AnthropicMessageSchema = z.object({
220
+ role: z.enum(["user", "assistant"]),
221
+ content: z.array(z.union([
222
+ AnthropicTextContentSchema,
223
+ AnthropicImageContentSchema,
224
+ AnthropicDocumentContentSchema,
225
+ AnthropicToolResultContentSchema,
226
+ AnthropicThinkingContentSchema,
227
+ AnthropicRedactedThinkingContentSchema,
228
+ AnthropicToolCallContentSchema,
229
+ AnthropicServerToolUseContentSchema,
230
+ AnthropicWebSearchToolResultContentSchema,
231
+ AnthropicWebFetchToolResultContentSchema,
232
+ AnthropicToolSearchToolResultContentSchema,
233
+ AnthropicCodeExecutionToolResultContentSchema,
234
+ AnthropicBashCodeExecutionToolResultContentSchema,
235
+ AnthropicTextEditorCodeExecutionToolResultContentSchema,
236
+ AnthropicMcpToolUseContentSchema,
237
+ AnthropicMcpToolResultContentSchema,
238
+ AnthropicCompactionContentSchema
239
+ ]))
240
+ });
241
+ const AnthropicMetadataSchema = z.object({ user_id: z.string().optional() });
242
+ const AnthropicThinkingConfigSchema = z.discriminatedUnion("type", [
243
+ z.object({ type: z.literal("adaptive") }),
244
+ z.object({
245
+ type: z.literal("enabled"),
246
+ budget_tokens: z.number().optional()
247
+ }),
248
+ z.object({ type: z.literal("disabled") })
249
+ ]);
250
+ const AnthropicToolChoiceSchema = z.discriminatedUnion("type", [
251
+ z.object({
252
+ type: z.literal("auto"),
253
+ disable_parallel_tool_use: z.boolean().optional()
254
+ }),
255
+ z.object({
256
+ type: z.literal("any"),
257
+ disable_parallel_tool_use: z.boolean().optional()
258
+ }),
259
+ z.object({
260
+ type: z.literal("tool"),
261
+ name: z.string(),
262
+ disable_parallel_tool_use: z.boolean().optional()
263
+ })
264
+ ]);
265
+ const AnthropicFunctionToolSchema = z.object({
266
+ name: z.string(),
267
+ description: z.string().optional(),
268
+ input_schema: z.record(z.string(), z.unknown()),
269
+ cache_control: AnthropicCacheControlSchema.optional(),
270
+ strict: z.boolean().optional(),
271
+ eager_input_streaming: z.boolean().optional(),
272
+ defer_loading: z.boolean().optional(),
273
+ allowed_callers: z.array(z.enum([
274
+ "direct",
275
+ "code_execution_20250825",
276
+ "code_execution_20260120"
277
+ ])).optional(),
278
+ input_examples: z.array(z.unknown()).optional()
279
+ });
280
+ const AnthropicCodeExecution20250522ToolSchema = z.object({
281
+ type: z.literal("code_execution_20250522"),
282
+ name: z.literal("code_execution"),
283
+ cache_control: AnthropicCacheControlSchema.optional()
284
+ });
285
+ const AnthropicCodeExecution20250825ToolSchema = z.object({
286
+ type: z.literal("code_execution_20250825"),
287
+ name: z.literal("code_execution")
288
+ });
289
+ const AnthropicCodeExecution20260120ToolSchema = z.object({
290
+ type: z.literal("code_execution_20260120"),
291
+ name: z.literal("code_execution")
292
+ });
293
+ const AnthropicComputerBaseToolSchema = z.object({
294
+ display_width_px: z.number().int(),
295
+ display_height_px: z.number().int(),
296
+ display_number: z.number().int().optional(),
297
+ cache_control: AnthropicCacheControlSchema.optional()
298
+ });
299
+ const AnthropicComputer20241022ToolSchema = AnthropicComputerBaseToolSchema.extend({
300
+ type: z.literal("computer_20241022"),
301
+ name: z.literal("computer")
302
+ });
303
+ const AnthropicComputer20250124ToolSchema = AnthropicComputerBaseToolSchema.extend({
304
+ type: z.literal("computer_20250124"),
305
+ name: z.literal("computer")
306
+ });
307
+ const AnthropicComputer20251124ToolSchema = AnthropicComputerBaseToolSchema.extend({
308
+ type: z.literal("computer_20251124"),
309
+ name: z.literal("computer"),
310
+ enable_zoom: z.boolean().optional()
311
+ });
312
+ const AnthropicTextEditor20241022ToolSchema = z.object({
313
+ type: z.literal("text_editor_20241022"),
314
+ name: z.literal("str_replace_editor"),
315
+ cache_control: AnthropicCacheControlSchema.optional()
316
+ });
317
+ const AnthropicTextEditor20250124ToolSchema = z.object({
318
+ type: z.literal("text_editor_20250124"),
319
+ name: z.literal("str_replace_editor"),
320
+ cache_control: AnthropicCacheControlSchema.optional()
321
+ });
322
+ const AnthropicTextEditor20250429ToolSchema = z.object({
323
+ type: z.literal("text_editor_20250429"),
324
+ name: z.literal("str_replace_based_edit_tool"),
325
+ cache_control: AnthropicCacheControlSchema.optional()
326
+ });
327
+ const AnthropicTextEditor20250728ToolSchema = z.object({
328
+ type: z.literal("text_editor_20250728"),
329
+ name: z.literal("str_replace_based_edit_tool"),
330
+ max_characters: z.number().optional(),
331
+ cache_control: AnthropicCacheControlSchema.optional()
332
+ });
333
+ const AnthropicBash20241022ToolSchema = z.object({
334
+ type: z.literal("bash_20241022"),
335
+ name: z.literal("bash"),
336
+ cache_control: AnthropicCacheControlSchema.optional()
337
+ });
338
+ const AnthropicBash20250124ToolSchema = z.object({
339
+ type: z.literal("bash_20250124"),
340
+ name: z.literal("bash"),
341
+ cache_control: AnthropicCacheControlSchema.optional()
342
+ });
343
+ const AnthropicMemory20250818ToolSchema = z.object({
344
+ type: z.literal("memory_20250818"),
345
+ name: z.literal("memory")
346
+ });
347
+ const AnthropicWebSearchUserLocationSchema = z.object({
348
+ type: z.literal("approximate"),
349
+ city: z.string().optional(),
350
+ region: z.string().optional(),
351
+ country: z.string().optional(),
352
+ timezone: z.string().optional()
353
+ });
354
+ const AnthropicWebSearch20250305ToolSchema = z.object({
355
+ type: z.literal("web_search_20250305"),
356
+ name: z.literal("web_search"),
357
+ max_uses: z.number().optional(),
358
+ allowed_domains: z.array(z.string()).optional(),
359
+ blocked_domains: z.array(z.string()).optional(),
360
+ user_location: AnthropicWebSearchUserLocationSchema.optional(),
361
+ cache_control: AnthropicCacheControlSchema.optional()
362
+ });
363
+ const AnthropicWebSearch20260209ToolSchema = z.object({
364
+ type: z.literal("web_search_20260209"),
365
+ name: z.literal("web_search"),
366
+ max_uses: z.number().optional(),
367
+ allowed_domains: z.array(z.string()).optional(),
368
+ blocked_domains: z.array(z.string()).optional(),
369
+ user_location: AnthropicWebSearchUserLocationSchema.optional(),
370
+ cache_control: AnthropicCacheControlSchema.optional()
371
+ });
372
+ const AnthropicWebFetchBaseToolSchema = z.object({
373
+ max_uses: z.number().optional(),
374
+ allowed_domains: z.array(z.string()).optional(),
375
+ blocked_domains: z.array(z.string()).optional(),
376
+ citations: z.object({ enabled: z.boolean() }).optional(),
377
+ max_content_tokens: z.number().optional(),
378
+ cache_control: AnthropicCacheControlSchema.optional()
379
+ });
380
+ const AnthropicWebFetch20250910ToolSchema = AnthropicWebFetchBaseToolSchema.extend({
381
+ type: z.literal("web_fetch_20250910"),
382
+ name: z.literal("web_fetch")
383
+ });
384
+ const AnthropicWebFetch20260209ToolSchema = AnthropicWebFetchBaseToolSchema.extend({
385
+ type: z.literal("web_fetch_20260209"),
386
+ name: z.literal("web_fetch")
387
+ });
388
+ const AnthropicToolSearchRegex20251119ToolSchema = z.object({
389
+ type: z.literal("tool_search_tool_regex_20251119"),
390
+ name: z.literal("tool_search_tool_regex")
391
+ });
392
+ const AnthropicToolSearchBm2520251119ToolSchema = z.object({
393
+ type: z.literal("tool_search_tool_bm25_20251119"),
394
+ name: z.literal("tool_search_tool_bm25")
395
+ });
396
+ const AnthropicHostedToolRequestSchema = z.union([
397
+ AnthropicCodeExecution20250522ToolSchema,
398
+ AnthropicCodeExecution20250825ToolSchema,
399
+ AnthropicCodeExecution20260120ToolSchema,
400
+ AnthropicComputer20241022ToolSchema,
401
+ AnthropicComputer20250124ToolSchema,
402
+ AnthropicComputer20251124ToolSchema,
403
+ AnthropicTextEditor20241022ToolSchema,
404
+ AnthropicTextEditor20250124ToolSchema,
405
+ AnthropicTextEditor20250429ToolSchema,
406
+ AnthropicTextEditor20250728ToolSchema,
407
+ AnthropicBash20241022ToolSchema,
408
+ AnthropicBash20250124ToolSchema,
409
+ AnthropicMemory20250818ToolSchema,
410
+ AnthropicWebSearch20250305ToolSchema,
411
+ AnthropicWebSearch20260209ToolSchema,
412
+ AnthropicWebFetch20250910ToolSchema,
413
+ AnthropicWebFetch20260209ToolSchema,
414
+ AnthropicToolSearchRegex20251119ToolSchema,
415
+ AnthropicToolSearchBm2520251119ToolSchema
416
+ ]);
417
+ const AnthropicMessagesToolSchema = z.union([AnthropicFunctionToolSchema, AnthropicHostedToolRequestSchema]);
418
+ const AnthropicMessagesRequestSchema = z.object({
419
+ model: AnthropicResponseModelIdSchema,
420
+ max_tokens: z.number().int().positive(),
421
+ messages: z.array(AnthropicMessageSchema),
422
+ system: z.union([z.string(), z.array(AnthropicTextContentSchema)]).optional(),
423
+ cache_control: AnthropicCacheControlSchema.optional(),
424
+ metadata: AnthropicMetadataSchema.optional(),
425
+ output_config: z.object({
426
+ effort: z.enum([
427
+ "low",
428
+ "medium",
429
+ "high",
430
+ "max"
431
+ ]).optional(),
432
+ format: z.object({
433
+ type: z.literal("json_schema"),
434
+ schema: z.record(z.string(), z.unknown())
435
+ }).optional()
436
+ }).optional(),
437
+ stop_sequences: z.array(z.string()).optional(),
438
+ stream: z.boolean().optional(),
439
+ speed: z.enum(["fast", "standard"]).optional(),
440
+ temperature: z.number().optional(),
441
+ thinking: AnthropicThinkingConfigSchema.optional(),
442
+ tool_choice: AnthropicToolChoiceSchema.optional(),
443
+ tools: z.array(AnthropicMessagesToolSchema).optional(),
444
+ top_k: z.number().optional(),
445
+ top_p: z.number().optional(),
446
+ mcp_servers: z.array(z.object({
447
+ type: z.literal("url"),
448
+ name: z.string(),
449
+ url: z.string(),
450
+ authorization_token: z.string().nullish(),
451
+ tool_configuration: z.object({
452
+ enabled: z.boolean().nullish(),
453
+ allowed_tools: z.array(z.string()).nullish()
454
+ }).nullish()
455
+ })).optional(),
456
+ container: z.object({
457
+ id: z.string().optional(),
458
+ skills: z.array(z.object({
459
+ type: z.enum(["anthropic", "custom"]),
460
+ skill_id: z.string(),
461
+ version: z.string().optional()
462
+ })).optional()
463
+ }).optional(),
464
+ context_management: z.object({ edits: z.array(z.unknown()) }).optional()
465
+ }).passthrough();
466
+ const AnthropicUsageSchema = z.object({
467
+ input_tokens: z.number().int().optional(),
468
+ output_tokens: z.number().int().optional(),
469
+ cache_creation_input_tokens: z.number().int().optional(),
470
+ cache_read_input_tokens: z.number().int().optional(),
471
+ iterations: z.array(z.object({
472
+ type: z.enum(["compaction", "message"]),
473
+ input_tokens: z.number().int(),
474
+ output_tokens: z.number().int()
475
+ })).optional()
476
+ });
477
+ const AnthropicMessagesResponseSchema = z.object({
478
+ id: z.string(),
479
+ type: z.literal("message"),
480
+ role: z.literal("assistant"),
481
+ model: AnthropicResponseModelIdSchema,
482
+ content: z.array(AnthropicResponseContentBlockSchema),
483
+ stop_reason: z.string().nullable().optional(),
484
+ stop_sequence: z.string().nullable().optional(),
485
+ usage: AnthropicUsageSchema.default({})
486
+ }).passthrough();
487
+ const AnthropicContentBlockDeltaSchema = z.discriminatedUnion("type", [
488
+ z.object({
489
+ type: z.literal("text_delta"),
490
+ text: z.string()
491
+ }),
492
+ z.object({
493
+ type: z.literal("thinking_delta"),
494
+ thinking: z.string()
495
+ }),
496
+ z.object({
497
+ type: z.literal("input_json_delta"),
498
+ partial_json: z.string()
499
+ }),
500
+ z.object({
501
+ type: z.literal("signature_delta"),
502
+ signature: z.string()
503
+ }),
504
+ z.object({
505
+ type: z.literal("citations_delta"),
506
+ citation: z.unknown()
507
+ }),
508
+ z.object({
509
+ type: z.literal("compaction_delta"),
510
+ content: z.string().optional()
511
+ })
512
+ ]);
513
+ const AnthropicResponseStreamEventSchema = z.discriminatedUnion("type", [
514
+ z.object({ type: z.literal("ping") }),
515
+ z.object({
516
+ type: z.literal("message_start"),
517
+ message: AnthropicMessagesResponseSchema
518
+ }),
519
+ z.object({
520
+ type: z.literal("message_delta"),
521
+ delta: z.object({
522
+ stop_reason: z.string().nullable().optional(),
523
+ stop_sequence: z.string().nullable().optional()
524
+ }).passthrough(),
525
+ usage: z.object({
526
+ input_tokens: z.number().int().optional(),
527
+ output_tokens: z.number().int().optional(),
528
+ cache_creation_input_tokens: z.number().int().optional(),
529
+ cache_read_input_tokens: z.number().int().optional(),
530
+ iterations: z.array(z.object({
531
+ type: z.enum(["compaction", "message"]),
532
+ input_tokens: z.number().int(),
533
+ output_tokens: z.number().int()
534
+ })).optional()
535
+ }).passthrough().optional()
536
+ }),
537
+ z.object({ type: z.literal("message_stop") }),
538
+ z.object({
539
+ type: z.literal("content_block_start"),
540
+ index: z.number().int(),
541
+ content_block: AnthropicResponseContentBlockSchema
542
+ }),
543
+ z.object({
544
+ type: z.literal("content_block_delta"),
545
+ index: z.number().int(),
546
+ delta: AnthropicContentBlockDeltaSchema
547
+ }),
548
+ z.object({
549
+ type: z.literal("content_block_stop"),
550
+ index: z.number().int()
551
+ }),
552
+ z.object({
553
+ type: z.literal("error"),
554
+ error: z.object({
555
+ type: z.string().optional(),
556
+ message: z.string().optional()
557
+ }).passthrough()
558
+ })
559
+ ]);
560
+
561
+ //#endregion
562
+ //#region src/anthropic/client/stream.ts
563
+ const parseSSERecord = (record) => {
564
+ const lines = record.split(/\r?\n/).map((line) => line.trimEnd()).filter(Boolean);
565
+ if (!lines.length) return ok(null);
566
+ const data = lines.filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trimStart()).join("\n");
567
+ if (!data) return ok(null);
568
+ if (data === "[DONE]") return ok(null);
569
+ const parsed = safeJsonParse(data);
570
+ if (parsed.isErr()) return err(BetterAgentError.wrap({
571
+ err: parsed.error,
572
+ message: "Anthropic stream returned invalid JSON",
573
+ opts: {
574
+ code: "UPSTREAM_FAILED",
575
+ context: {
576
+ provider: "anthropic",
577
+ raw: data
578
+ }
579
+ }
580
+ }).at({ at: "anthropic.stream.parse" }));
581
+ const event = AnthropicResponseStreamEventSchema.safeParse(parsed.value);
582
+ if (!event.success) return err(BetterAgentError.fromCode("UPSTREAM_FAILED", "Anthropic stream returned an unknown event payload", { context: {
583
+ provider: "anthropic",
584
+ issues: event.error.issues
585
+ } }).at({ at: "anthropic.stream.validate" }));
586
+ return ok(event.data);
587
+ };
588
+ async function* parseAnthropicSSEStream(stream) {
589
+ const reader = stream.getReader();
590
+ const decoder = new TextDecoder();
591
+ let buffer = "";
592
+ try {
593
+ while (true) {
594
+ const { done, value } = await reader.read();
595
+ if (done) break;
596
+ buffer += decoder.decode(value, { stream: true });
597
+ while (true) {
598
+ const recordBoundary = buffer.indexOf("\n\n");
599
+ if (recordBoundary === -1) break;
600
+ const record = buffer.slice(0, recordBoundary);
601
+ buffer = buffer.slice(recordBoundary + 2);
602
+ const parsed = parseSSERecord(record);
603
+ if (parsed.isErr()) {
604
+ yield err(parsed.error);
605
+ return;
606
+ }
607
+ if (parsed.value) yield ok(parsed.value);
608
+ }
609
+ }
610
+ buffer += decoder.decode();
611
+ const remaining = buffer.trim();
612
+ if (!remaining) return;
613
+ const parsed = parseSSERecord(remaining);
614
+ if (parsed.isErr()) {
615
+ yield err(parsed.error);
616
+ return;
617
+ }
618
+ if (parsed.value) yield ok(parsed.value);
619
+ } finally {
620
+ reader.releaseLock();
621
+ }
622
+ }
623
+
624
+ //#endregion
625
+ //#region src/anthropic/client/create-client.ts
626
+ const createAnthropicClient = (config = {}) => {
627
+ const baseUrl = (config.baseURL ?? "https://api.anthropic.com/v1").replace(/\/+$/, "");
628
+ const post = async (path, body, at, options) => {
629
+ try {
630
+ const result = await baFetch(`${baseUrl}${path}`, {
631
+ method: "POST",
632
+ body: JSON.stringify(body),
633
+ headers: {
634
+ ...buildAnthropicHeaders(config, options),
635
+ "Content-Type": "application/json"
636
+ },
637
+ signal: options?.signal ?? null,
638
+ throw: false
639
+ });
640
+ if (result.error) return err(mapAnthropicHttpError(result.error, {
641
+ at,
642
+ path
643
+ }));
644
+ if (!result.data) return err(BetterAgentError.fromCode("UPSTREAM_FAILED", "Anthropic returned no data", { context: { provider: "anthropic" } }).at({
645
+ at,
646
+ data: { path }
647
+ }));
648
+ return ok(result.data);
649
+ } catch (e) {
650
+ return err(BetterAgentError.wrap({
651
+ err: e,
652
+ message: "Anthropic request failed",
653
+ opts: {
654
+ code: "UPSTREAM_FAILED",
655
+ context: { provider: "anthropic" }
656
+ }
657
+ }).at({
658
+ at,
659
+ data: { path }
660
+ }));
661
+ }
662
+ };
663
+ const stream = async (path, body, at, options) => {
664
+ try {
665
+ const response = await fetch(`${baseUrl}${path}`, {
666
+ method: "POST",
667
+ body: JSON.stringify(body),
668
+ headers: {
669
+ ...buildAnthropicHeaders(config, options),
670
+ Accept: "text/event-stream",
671
+ "Content-Type": "application/json"
672
+ },
673
+ signal: options?.signal ?? null
674
+ });
675
+ if (!response.ok) {
676
+ const parsed = safeJsonParse(await response.text());
677
+ const error = parsed.isOk() && parsed.value && typeof parsed.value === "object" ? parsed.value.error ? parsed.value : { error: parsed.value } : void 0;
678
+ return err(mapAnthropicHttpError({
679
+ status: response.status,
680
+ statusText: response.statusText,
681
+ error: error?.error
682
+ }, {
683
+ at,
684
+ path
685
+ }));
686
+ }
687
+ if (!response.body) return err(BetterAgentError.fromCode("UPSTREAM_FAILED", "Anthropic stream response did not include a body", { context: { provider: "anthropic" } }).at({
688
+ at,
689
+ data: { path }
690
+ }));
691
+ return ok(parseAnthropicSSEStream(response.body));
692
+ } catch (e) {
693
+ return err(BetterAgentError.wrap({
694
+ err: e,
695
+ message: "Anthropic streaming request failed",
696
+ opts: {
697
+ code: "UPSTREAM_FAILED",
698
+ context: { provider: "anthropic" }
699
+ }
700
+ }).at({
701
+ at,
702
+ data: { path }
703
+ }));
704
+ }
705
+ };
706
+ return { messages: {
707
+ create: (body, options) => post("/messages", body, "anthropic.messages.create", options),
708
+ stream: (body, options) => stream("/messages", body, "anthropic.messages.stream", options)
709
+ } };
710
+ };
711
+
712
+ //#endregion
713
+ //#region src/anthropic/tools/index.ts
714
+ function createAnthropicNativeToolBuilders() {
715
+ return {
716
+ codeExecution_20250522: (config = {}) => createNativeTool("code_execution_20250522", config),
717
+ codeExecution_20250825: (config = {}) => createNativeTool("code_execution_20250825", config),
718
+ codeExecution_20260120: (config = {}) => createNativeTool("code_execution_20260120", config),
719
+ computer_20241022: (config) => createNativeTool("computer_20241022", config),
720
+ computer_20250124: (config) => createNativeTool("computer_20250124", config),
721
+ computer_20251124: (config) => createNativeTool("computer_20251124", config),
722
+ textEditor_20241022: (config = {}) => createNativeTool("text_editor_20241022", config),
723
+ textEditor_20250124: (config = {}) => createNativeTool("text_editor_20250124", config),
724
+ textEditor_20250429: (config = {}) => createNativeTool("text_editor_20250429", config),
725
+ textEditor_20250728: (config = {}) => createNativeTool("text_editor_20250728", config),
726
+ bash_20241022: (config = {}) => createNativeTool("bash_20241022", config),
727
+ bash_20250124: (config = {}) => createNativeTool("bash_20250124", config),
728
+ memory_20250818: (config = {}) => createNativeTool("memory_20250818", config),
729
+ webSearch_20250305: (config = {}) => createNativeTool("web_search_20250305", config),
730
+ webSearch_20260209: (config = {}) => createNativeTool("web_search_20260209", config),
731
+ webFetch_20250910: (config = {}) => createNativeTool("web_fetch_20250910", config),
732
+ webFetch_20260209: (config = {}) => createNativeTool("web_fetch_20260209", config),
733
+ toolSearchRegex_20251119: (config = {}) => createNativeTool("tool_search_tool_regex_20251119", config),
734
+ toolSearchBm25_20251119: (config = {}) => createNativeTool("tool_search_tool_bm25_20251119", config)
735
+ };
736
+ }
737
+ function createNativeTool(type, config) {
738
+ return {
739
+ kind: "hosted",
740
+ provider: "anthropic",
741
+ type,
742
+ config
743
+ };
744
+ }
745
+ function isAnthropicNativeToolDefinition(tool) {
746
+ if (!tool || typeof tool !== "object") return false;
747
+ const t = tool;
748
+ return t.kind === "hosted" && t.provider === "anthropic" && typeof t.type === "string";
749
+ }
750
+ function mapAnthropicNativeToolToRequest(tool) {
751
+ switch (tool.type) {
752
+ case "code_execution_20250522": return {
753
+ type: "code_execution_20250522",
754
+ name: "code_execution",
755
+ ...tool.config
756
+ };
757
+ case "code_execution_20250825": return {
758
+ type: "code_execution_20250825",
759
+ name: "code_execution",
760
+ ...tool.config
761
+ };
762
+ case "code_execution_20260120": return {
763
+ type: "code_execution_20260120",
764
+ name: "code_execution",
765
+ ...tool.config
766
+ };
767
+ case "computer_20241022": return {
768
+ type: "computer_20241022",
769
+ name: "computer",
770
+ ...tool.config
771
+ };
772
+ case "computer_20250124": return {
773
+ type: "computer_20250124",
774
+ name: "computer",
775
+ ...tool.config
776
+ };
777
+ case "computer_20251124": return {
778
+ type: "computer_20251124",
779
+ name: "computer",
780
+ ...tool.config
781
+ };
782
+ case "text_editor_20241022": return {
783
+ type: "text_editor_20241022",
784
+ name: "str_replace_editor",
785
+ ...tool.config
786
+ };
787
+ case "text_editor_20250124": return {
788
+ type: "text_editor_20250124",
789
+ name: "str_replace_editor",
790
+ ...tool.config
791
+ };
792
+ case "text_editor_20250429": return {
793
+ type: "text_editor_20250429",
794
+ name: "str_replace_based_edit_tool",
795
+ ...tool.config
796
+ };
797
+ case "text_editor_20250728": return {
798
+ type: "text_editor_20250728",
799
+ name: "str_replace_based_edit_tool",
800
+ ...tool.config
801
+ };
802
+ case "bash_20241022": return {
803
+ type: "bash_20241022",
804
+ name: "bash",
805
+ ...tool.config
806
+ };
807
+ case "bash_20250124": return {
808
+ type: "bash_20250124",
809
+ name: "bash",
810
+ ...tool.config
811
+ };
812
+ case "memory_20250818": return {
813
+ type: "memory_20250818",
814
+ name: "memory",
815
+ ...tool.config
816
+ };
817
+ case "web_search_20250305": return {
818
+ type: "web_search_20250305",
819
+ name: "web_search",
820
+ ...tool.config
821
+ };
822
+ case "web_search_20260209": return {
823
+ type: "web_search_20260209",
824
+ name: "web_search",
825
+ ...tool.config
826
+ };
827
+ case "web_fetch_20250910": return {
828
+ type: "web_fetch_20250910",
829
+ name: "web_fetch",
830
+ ...tool.config
831
+ };
832
+ case "web_fetch_20260209": return {
833
+ type: "web_fetch_20260209",
834
+ name: "web_fetch",
835
+ ...tool.config
836
+ };
837
+ case "tool_search_tool_regex_20251119": return {
838
+ type: "tool_search_tool_regex_20251119",
839
+ name: "tool_search_tool_regex",
840
+ ...tool.config
841
+ };
842
+ case "tool_search_tool_bm25_20251119": return {
843
+ type: "tool_search_tool_bm25_20251119",
844
+ name: "tool_search_tool_bm25",
845
+ ...tool.config
846
+ };
847
+ }
848
+ }
849
+
850
+ //#endregion
851
+ //#region src/anthropic/responses/mappers.ts
852
+ /**
853
+ * Keys explicitly handled by the Anthropic responses mapper.
854
+ */
855
+ const ANTHROPIC_RESPONSE_KNOWN_KEYS = new Set([
856
+ "input",
857
+ "tools",
858
+ "toolChoice",
859
+ "modalities",
860
+ "structured_output",
861
+ "anthropicBeta",
862
+ "cacheControl",
863
+ "container",
864
+ "contextManagement",
865
+ "disableParallelToolUse",
866
+ "effort",
867
+ "max_tokens",
868
+ "mcpServers",
869
+ "metadata",
870
+ "speed",
871
+ "stop_sequences",
872
+ "structuredOutputMode",
873
+ "temperature",
874
+ "thinking",
875
+ "toolStreaming",
876
+ "top_k",
877
+ "top_p"
878
+ ]);
879
+ const DEFAULT_MAX_TOKENS = 4096;
880
+ const PDF_INPUT_BETA = "pdfs-2024-09-25";
881
+ const FINE_GRAINED_TOOL_STREAMING_BETA = "fine-grained-tool-streaming-2025-05-14";
882
+ const normalizeProviderToolName = (name) => {
883
+ if (name === "bash_code_execution" || name === "text_editor_code_execution") return "code_execution";
884
+ return name;
885
+ };
886
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
887
+ const decodeBase64Text = (data) => Buffer.from(data, "base64").toString("utf8");
888
+ const isUrlSource = (source) => isRecord(source) && source.kind === "url" && typeof source.url === "string";
889
+ const isBase64Source = (source) => isRecord(source) && source.kind === "base64" && typeof source.data === "string" && typeof source.mimeType === "string";
890
+ const buildBinarySource = (source) => {
891
+ if (isUrlSource(source)) return {
892
+ type: "url",
893
+ url: source.url
894
+ };
895
+ if (isBase64Source(source)) return {
896
+ type: "base64",
897
+ media_type: source.mimeType,
898
+ data: source.data
899
+ };
900
+ return null;
901
+ };
902
+ const serializeToolResultContent = (result) => typeof result === "string" ? result : JSON.stringify(result);
903
+ const parseMaybeJson = (value) => {
904
+ if (!value.trim()) return {};
905
+ const parsed = safeJsonParse(value);
906
+ return parsed.isOk() ? parsed.value : value;
907
+ };
908
+ const getAnthropicModelCapabilities = (modelId) => {
909
+ if (modelId.includes("claude-sonnet-4-6") || modelId.includes("claude-opus-4-6")) return { supportsStructuredOutput: true };
910
+ if (modelId.includes("claude-sonnet-4-5") || modelId.includes("claude-opus-4-5") || modelId.includes("claude-haiku-4-5")) return { supportsStructuredOutput: true };
911
+ if (modelId.includes("claude-opus-4-1")) return { supportsStructuredOutput: true };
912
+ return { supportsStructuredOutput: false };
913
+ };
914
+ const getAnthropicPartProviderMetadata = (part) => {
915
+ const providerMetadata = part.providerMetadata;
916
+ if (!isRecord(providerMetadata)) return void 0;
917
+ const anthropic = providerMetadata.anthropic;
918
+ if (!isRecord(anthropic)) return void 0;
919
+ return {
920
+ cacheControl: isRecord(anthropic.cacheControl) && anthropic.cacheControl.type === "ephemeral" && (anthropic.cacheControl.ttl == null || anthropic.cacheControl.ttl === "5m" || anthropic.cacheControl.ttl === "1h") ? {
921
+ type: "ephemeral",
922
+ ...anthropic.cacheControl.ttl != null ? { ttl: anthropic.cacheControl.ttl } : {}
923
+ } : void 0,
924
+ citations: isRecord(anthropic.citations) && typeof anthropic.citations.enabled === "boolean" ? { enabled: anthropic.citations.enabled } : void 0,
925
+ context: typeof anthropic.context === "string" ? anthropic.context : void 0,
926
+ title: typeof anthropic.title === "string" ? anthropic.title : void 0
927
+ };
928
+ };
929
+ const getAnthropicTextProviderMetadata = (citations) => citations?.length ? { anthropic: { citations } } : void 0;
930
+ const mapAnthropicStopReason = (stopReason, isJsonResponseFromTool) => {
931
+ switch (stopReason) {
932
+ case "pause_turn":
933
+ case "end_turn":
934
+ case "stop_sequence": return "stop";
935
+ case "refusal": return "content-filter";
936
+ case "tool_use": return isJsonResponseFromTool ? "stop" : "tool-calls";
937
+ case "max_tokens":
938
+ case "model_context_window_exceeded": return "length";
939
+ case "compaction": return "other";
940
+ default: return "other";
941
+ }
942
+ };
943
+ const mapAnthropicUsage = (usage) => {
944
+ const cacheCreation = usage?.cache_creation_input_tokens ?? 0;
945
+ const cacheRead = usage?.cache_read_input_tokens ?? 0;
946
+ const iteratedInput = usage?.iterations?.reduce((sum, item) => sum + item.input_tokens, 0) ?? usage?.input_tokens;
947
+ const iteratedOutput = usage?.iterations?.reduce((sum, item) => sum + item.output_tokens, 0) ?? usage?.output_tokens;
948
+ const inputTokens = typeof iteratedInput === "number" ? iteratedInput + cacheCreation + cacheRead : void 0;
949
+ const outputTokens = typeof iteratedOutput === "number" ? iteratedOutput : void 0;
950
+ return omitNullish({
951
+ inputTokens,
952
+ outputTokens,
953
+ totalTokens: typeof inputTokens === "number" && typeof outputTokens === "number" ? inputTokens + outputTokens : void 0,
954
+ cachedInputTokens: cacheRead || void 0
955
+ });
956
+ };
957
+ const mapContextManagementEdit = (edit) => {
958
+ if (!isRecord(edit) || typeof edit.type !== "string") return edit;
959
+ switch (edit.type) {
960
+ case "clear_tool_uses_20250919": return omitNullish({
961
+ type: edit.type,
962
+ trigger: edit.trigger,
963
+ keep: edit.keep,
964
+ clear_at_least: edit.clearAtLeast,
965
+ clear_tool_inputs: edit.clearToolInputs,
966
+ exclude_tools: edit.excludeTools
967
+ });
968
+ case "clear_thinking_20251015": return omitNullish({
969
+ type: edit.type,
970
+ keep: edit.keep
971
+ });
972
+ case "compact_20260112": return omitNullish({
973
+ type: edit.type,
974
+ trigger: edit.trigger,
975
+ pause_after_compaction: edit.pauseAfterCompaction,
976
+ instructions: edit.instructions
977
+ });
978
+ default: return edit;
979
+ }
980
+ };
981
+ const mapHostedToolBeta = (type) => {
982
+ switch (type) {
983
+ case "code_execution_20250522": return "code-execution-2025-05-22";
984
+ case "code_execution_20250825": return "code-execution-2025-08-25";
985
+ case "computer_20241022":
986
+ case "text_editor_20241022":
987
+ case "bash_20241022": return "computer-use-2024-10-22";
988
+ case "computer_20250124":
989
+ case "text_editor_20250124":
990
+ case "text_editor_20250429":
991
+ case "bash_20250124": return "computer-use-2025-01-24";
992
+ case "computer_20251124": return "computer-use-2025-11-24";
993
+ case "memory_20250818": return "context-management-2025-06-27";
994
+ case "web_fetch_20250910": return "web-fetch-2025-09-10";
995
+ case "web_fetch_20260209":
996
+ case "web_search_20260209": return "code-execution-web-tools-2026-02-09";
997
+ default: return null;
998
+ }
999
+ };
1000
+ const mapMessagePartsToAnthropicContent = (content, role, modelId, betas) => {
1001
+ const toValidationError = (message, at, context) => BetterAgentError.fromCode("VALIDATION_FAILED", message, { context: {
1002
+ provider: "anthropic",
1003
+ model: modelId,
1004
+ role,
1005
+ ...context ?? {}
1006
+ } }).at({ at });
1007
+ const parts = typeof content === "string" ? [{
1008
+ type: "text",
1009
+ text: content
1010
+ }] : content;
1011
+ if (!Array.isArray(parts)) return err(toValidationError("Message content must be a string or array.", "anthropic.map.input.content"));
1012
+ const anthropicContent = [];
1013
+ for (const part of parts) {
1014
+ if (!isRecord(part) || typeof part.type !== "string") return err(toValidationError("Message part must be an object with a type.", "anthropic.map.input.part"));
1015
+ if (part.type === "text") {
1016
+ if (typeof part.text !== "string") return err(toValidationError("Text message parts require a text string.", "anthropic.map.input.text"));
1017
+ const anthropicProviderOptions = getAnthropicPartProviderMetadata(part);
1018
+ anthropicContent.push({
1019
+ type: "text",
1020
+ text: part.text,
1021
+ ...anthropicProviderOptions?.cacheControl != null ? { cache_control: anthropicProviderOptions.cacheControl } : {}
1022
+ });
1023
+ continue;
1024
+ }
1025
+ if (role === "assistant" || role === "system" || role === "developer") return err(toValidationError(`Role '${role}' only supports text content for Anthropic.`, "anthropic.map.input.roleContent", { partType: part.type }));
1026
+ if (part.type === "image") {
1027
+ if (!isRecord(part.source) || typeof part.source.kind !== "string") return err(toValidationError("Image parts require a valid source.", "anthropic.map.input.imageSource"));
1028
+ if (part.source.kind === "provider-file") return err(toValidationError("Anthropic Messages API does not support provider-file image inputs in this adapter.", "anthropic.map.input.imageProviderFile"));
1029
+ const anthropicProviderOptions = getAnthropicPartProviderMetadata(part);
1030
+ const imageSource = isUrlSource(part.source) || isBase64Source(part.source) ? buildBinarySource(part.source) : null;
1031
+ if (imageSource == null) return err(toValidationError("Image parts require a URL or base64 source.", "anthropic.map.input.imageSourceKind"));
1032
+ anthropicContent.push({
1033
+ type: "image",
1034
+ source: imageSource,
1035
+ ...anthropicProviderOptions?.cacheControl != null ? { cache_control: anthropicProviderOptions.cacheControl } : {}
1036
+ });
1037
+ continue;
1038
+ }
1039
+ if (part.type === "file") {
1040
+ if (!isRecord(part.source) || typeof part.source.kind !== "string") return err(toValidationError("File parts require a valid source.", "anthropic.map.input.fileSource"));
1041
+ if (part.source.kind === "provider-file") return err(toValidationError("Anthropic Messages API does not support provider-file document inputs in this adapter.", "anthropic.map.input.fileProviderFile"));
1042
+ const mimeType = typeof part.source.mimeType === "string" ? part.source.mimeType : void 0;
1043
+ const filename = typeof part.source.filename === "string" ? part.source.filename : void 0;
1044
+ const anthropicProviderOptions = getAnthropicPartProviderMetadata(part);
1045
+ const citationsEnabled = anthropicProviderOptions?.citations?.enabled;
1046
+ const documentContext = anthropicProviderOptions?.context;
1047
+ const documentTitle = anthropicProviderOptions?.title ?? filename;
1048
+ const cacheControl = anthropicProviderOptions?.cacheControl;
1049
+ if (typeof mimeType === "string" && mimeType.startsWith("image/")) {
1050
+ const imageSource = buildBinarySource(part.source);
1051
+ if (imageSource == null) return err(toValidationError("Image file inputs require a URL or base64 source.", "anthropic.map.input.fileImageSource"));
1052
+ anthropicContent.push({
1053
+ type: "image",
1054
+ source: imageSource,
1055
+ ...cacheControl != null ? { cache_control: cacheControl } : {}
1056
+ });
1057
+ continue;
1058
+ }
1059
+ if (mimeType === "application/pdf") {
1060
+ betas.add(PDF_INPUT_BETA);
1061
+ const documentSource = buildBinarySource(part.source);
1062
+ if (documentSource == null) return err(toValidationError("PDF inputs require a URL or base64 source.", "anthropic.map.input.filePdfSource"));
1063
+ anthropicContent.push({
1064
+ type: "document",
1065
+ source: documentSource,
1066
+ ...documentTitle != null ? { title: documentTitle } : {},
1067
+ ...documentContext != null ? { context: documentContext } : {},
1068
+ ...citationsEnabled != null ? { citations: { enabled: citationsEnabled } } : {},
1069
+ ...cacheControl != null ? { cache_control: cacheControl } : {}
1070
+ });
1071
+ continue;
1072
+ }
1073
+ if (mimeType === "text/plain") {
1074
+ const documentSource = isUrlSource(part.source) ? {
1075
+ type: "url",
1076
+ url: part.source.url
1077
+ } : isBase64Source(part.source) ? {
1078
+ type: "text",
1079
+ media_type: "text/plain",
1080
+ data: decodeBase64Text(part.source.data)
1081
+ } : null;
1082
+ if (documentSource == null) return err(toValidationError("Text document inputs require a URL or base64 source.", "anthropic.map.input.fileTextSource"));
1083
+ anthropicContent.push({
1084
+ type: "document",
1085
+ source: documentSource,
1086
+ ...documentTitle != null ? { title: documentTitle } : {},
1087
+ ...documentContext != null ? { context: documentContext } : {},
1088
+ ...citationsEnabled != null ? { citations: { enabled: citationsEnabled } } : {},
1089
+ ...cacheControl != null ? { cache_control: cacheControl } : {}
1090
+ });
1091
+ continue;
1092
+ }
1093
+ return err(toValidationError("Anthropic file inputs currently support image/*, application/pdf, and text/plain only.", "anthropic.map.input.fileUnsupported", { mimeType }));
1094
+ }
1095
+ return err(toValidationError(`Unsupported Anthropic input part type '${part.type}'.`, "anthropic.map.input.unsupportedPart"));
1096
+ }
1097
+ return ok(anthropicContent);
1098
+ };
1099
+ function mapToAnthropicMessagesRequest(args) {
1100
+ try {
1101
+ const { modelId } = args;
1102
+ const o = args.options;
1103
+ const stream = args.stream === true;
1104
+ const betas = new Set(o.anthropicBeta ?? []);
1105
+ const systemParts = [];
1106
+ const messages = [];
1107
+ const inputItems = typeof o.input === "string" ? [{
1108
+ type: "message",
1109
+ role: "user",
1110
+ content: o.input
1111
+ }] : o.input;
1112
+ if (Array.isArray(inputItems)) for (const item of inputItems) {
1113
+ if (typeof item === "string") {
1114
+ messages.push({
1115
+ role: "user",
1116
+ content: [{
1117
+ type: "text",
1118
+ text: item
1119
+ }]
1120
+ });
1121
+ continue;
1122
+ }
1123
+ if (!isRecord(item) || typeof item.type !== "string") return err(BetterAgentError.fromCode("VALIDATION_FAILED", "Anthropic input items must be messages or tool-call results.", { context: {
1124
+ provider: "anthropic",
1125
+ model: modelId
1126
+ } }).at({ at: "anthropic.map.input.item" }));
1127
+ if (item.type === "message") {
1128
+ const role = typeof item.role === "string" ? item.role : "user";
1129
+ const content = mapMessagePartsToAnthropicContent(item.content, role, String(modelId), betas);
1130
+ if (content.isErr()) return err(content.error);
1131
+ if (role === "system" || role === "developer") {
1132
+ for (const part of content.value) if (part.type === "text") systemParts.push({
1133
+ type: "text",
1134
+ text: part.text
1135
+ });
1136
+ } else if (role === "assistant" || role === "user") messages.push({
1137
+ role,
1138
+ content: content.value
1139
+ });
1140
+ else return err(BetterAgentError.fromCode("VALIDATION_FAILED", `Anthropic does not support role '${role}'.`, { context: {
1141
+ provider: "anthropic",
1142
+ model: modelId,
1143
+ role
1144
+ } }).at({ at: "anthropic.map.input.role" }));
1145
+ continue;
1146
+ }
1147
+ if (item.type === "tool-call" && "result" in item) {
1148
+ const toolResult = item;
1149
+ messages.push({
1150
+ role: "assistant",
1151
+ content: [{
1152
+ type: "tool_use",
1153
+ id: toolResult.callId,
1154
+ name: toolResult.name,
1155
+ input: parseMaybeJson(toolResult.arguments ?? "{}")
1156
+ }]
1157
+ });
1158
+ messages.push({
1159
+ role: "user",
1160
+ content: [{
1161
+ type: "tool_result",
1162
+ tool_use_id: toolResult.callId,
1163
+ content: serializeToolResultContent(toolResult.result),
1164
+ is_error: toolResult.isError
1165
+ }]
1166
+ });
1167
+ continue;
1168
+ }
1169
+ return err(BetterAgentError.fromCode("VALIDATION_FAILED", "Anthropic input items must be messages or completed tool-call results.", { context: {
1170
+ provider: "anthropic",
1171
+ model: modelId
1172
+ } }).at({ at: "anthropic.map.input.unsupportedItem" }));
1173
+ }
1174
+ const anthropicTools = [];
1175
+ const tools = ("tools" in o ? o.tools : []) ?? [];
1176
+ const modelSupportsStructuredOutput = getAnthropicModelCapabilities(String(modelId)).supportsStructuredOutput;
1177
+ for (const tool of tools) {
1178
+ if (isAnthropicNativeToolDefinition(tool)) {
1179
+ anthropicTools.push(mapAnthropicNativeToolToRequest(tool));
1180
+ const beta = mapHostedToolBeta(tool.type);
1181
+ if (beta) betas.add(beta);
1182
+ continue;
1183
+ }
1184
+ const callableTool = tool;
1185
+ if (!callableTool || !isCallableToolDefinition(callableTool)) continue;
1186
+ const inputSchema = callableTool[TOOL_JSON_SCHEMA];
1187
+ if (!isRecord(inputSchema) || inputSchema.type !== "object") return err(BetterAgentError.fromCode("VALIDATION_FAILED", "Anthropic custom tools require an object JSON schema.", { context: {
1188
+ provider: "anthropic",
1189
+ model: modelId,
1190
+ toolName: callableTool.name
1191
+ } }).at({ at: "anthropic.map.tools.schema" }));
1192
+ anthropicTools.push(omitNullish({
1193
+ name: String(callableTool.name ?? ""),
1194
+ description: typeof callableTool.description === "string" ? callableTool.description : void 0,
1195
+ input_schema: inputSchema,
1196
+ strict: modelSupportsStructuredOutput && typeof callableTool.strict === "boolean" ? callableTool.strict : void 0
1197
+ }));
1198
+ if (modelSupportsStructuredOutput) betas.add("structured-outputs-2025-11-13");
1199
+ }
1200
+ const structuredOutput = "structured_output" in o ? o.structured_output : void 0;
1201
+ const structuredOutputMode = o.structuredOutputMode ?? "auto";
1202
+ const useStructuredOutput = structuredOutputMode === "outputFormat" || structuredOutputMode === "auto" && modelSupportsStructuredOutput;
1203
+ let usesJsonResponseTool = false;
1204
+ let outputConfig = o.effort != null ? { effort: o.effort } : void 0;
1205
+ if (structuredOutput) {
1206
+ if (!isRecord(structuredOutput.schema) || structuredOutput.schema.type !== "object") return err(BetterAgentError.fromCode("VALIDATION_FAILED", "Anthropic structured output schema must be a JSON object schema.", { context: {
1207
+ provider: "anthropic",
1208
+ model: modelId
1209
+ } }).at({ at: "anthropic.map.structuredOutput.schema" }));
1210
+ if (!useStructuredOutput) {
1211
+ usesJsonResponseTool = true;
1212
+ anthropicTools.push({
1213
+ name: "json",
1214
+ description: "Respond with a JSON object.",
1215
+ input_schema: structuredOutput.schema
1216
+ });
1217
+ } else outputConfig = {
1218
+ ...outputConfig ?? {},
1219
+ format: {
1220
+ type: "json_schema",
1221
+ schema: structuredOutput.schema
1222
+ }
1223
+ };
1224
+ }
1225
+ let toolChoice;
1226
+ if (usesJsonResponseTool) toolChoice = {
1227
+ type: "tool",
1228
+ name: "json",
1229
+ disable_parallel_tool_use: true
1230
+ };
1231
+ else if ("toolChoice" in o && o.toolChoice) switch (o.toolChoice.type) {
1232
+ case "auto":
1233
+ toolChoice = o.disableParallelToolUse ? {
1234
+ type: "auto",
1235
+ disable_parallel_tool_use: true
1236
+ } : { type: "auto" };
1237
+ break;
1238
+ case "required":
1239
+ toolChoice = {
1240
+ type: "any",
1241
+ ...o.disableParallelToolUse ? { disable_parallel_tool_use: true } : {}
1242
+ };
1243
+ break;
1244
+ case "tool":
1245
+ toolChoice = {
1246
+ type: "tool",
1247
+ name: o.toolChoice.name,
1248
+ ...o.disableParallelToolUse ? { disable_parallel_tool_use: true } : {}
1249
+ };
1250
+ break;
1251
+ case "none": break;
1252
+ }
1253
+ else if (o.disableParallelToolUse) toolChoice = {
1254
+ type: "auto",
1255
+ disable_parallel_tool_use: true
1256
+ };
1257
+ if (o.mcpServers?.length) betas.add("mcp-client-2025-04-04");
1258
+ if (o.contextManagement) {
1259
+ betas.add("context-management-2025-06-27");
1260
+ if (o.contextManagement.edits.some((edit) => isRecord(edit) && edit.type === "compact_20260112")) betas.add("compact-2026-01-12");
1261
+ }
1262
+ if (o.container?.skills?.length) {
1263
+ betas.add("code-execution-2025-08-25");
1264
+ betas.add("skills-2025-10-02");
1265
+ betas.add("files-api-2025-04-14");
1266
+ }
1267
+ if (o.effort) betas.add("effort-2025-11-24");
1268
+ if (o.speed === "fast") betas.add("fast-mode-2026-02-01");
1269
+ if (stream && (o.toolStreaming ?? true)) betas.add(FINE_GRAINED_TOOL_STREAMING_BETA);
1270
+ return ok({
1271
+ request: {
1272
+ ...extractPassthroughOptions(o, ANTHROPIC_RESPONSE_KNOWN_KEYS),
1273
+ model: modelId,
1274
+ max_tokens: o.max_tokens ?? DEFAULT_MAX_TOKENS,
1275
+ messages,
1276
+ ...omitNullish({
1277
+ system: systemParts.length ? systemParts : void 0,
1278
+ cache_control: o.cacheControl,
1279
+ metadata: o.metadata?.userId ? { user_id: o.metadata.userId } : void 0,
1280
+ output_config: outputConfig,
1281
+ stop_sequences: o.stop_sequences,
1282
+ temperature: o.temperature,
1283
+ stream: false,
1284
+ speed: o.speed,
1285
+ thinking: o.thinking == null ? void 0 : o.thinking.type === "enabled" ? {
1286
+ type: "enabled",
1287
+ budget_tokens: o.thinking.budgetTokens
1288
+ } : o.thinking,
1289
+ tool_choice: o.toolChoice?.type === "none" && !usesJsonResponseTool ? void 0 : toolChoice,
1290
+ tools: o.toolChoice?.type === "none" && !usesJsonResponseTool ? void 0 : anthropicTools.length ? anthropicTools : void 0,
1291
+ top_k: o.top_k,
1292
+ top_p: o.top_p,
1293
+ mcp_servers: o.mcpServers?.map((server) => ({
1294
+ type: server.type,
1295
+ name: server.name,
1296
+ url: server.url,
1297
+ authorization_token: server.authorizationToken,
1298
+ tool_configuration: server.toolConfiguration ? {
1299
+ enabled: server.toolConfiguration.enabled,
1300
+ allowed_tools: server.toolConfiguration.allowedTools
1301
+ } : void 0
1302
+ })),
1303
+ container: o.container ? {
1304
+ ...o.container.id != null ? { id: o.container.id } : {},
1305
+ ...o.container.skills?.length ? { skills: o.container.skills.map((skill) => ({
1306
+ type: skill.type,
1307
+ skill_id: skill.skillId,
1308
+ ...skill.version != null ? { version: skill.version } : {}
1309
+ })) } : {}
1310
+ } : void 0,
1311
+ context_management: o.contextManagement ? { edits: o.contextManagement.edits.map(mapContextManagementEdit) } : void 0
1312
+ })
1313
+ },
1314
+ betas: [...betas],
1315
+ usesJsonResponseTool
1316
+ });
1317
+ } catch (e) {
1318
+ return err(BetterAgentError.wrap({
1319
+ err: e,
1320
+ message: "Failed to map Anthropic Messages request",
1321
+ opts: {
1322
+ code: "INTERNAL",
1323
+ context: {
1324
+ provider: "anthropic",
1325
+ model: args.modelId
1326
+ }
1327
+ }
1328
+ }).at({ at: "anthropic.messages.mapToRequest" }));
1329
+ }
1330
+ }
1331
+ const mapProviderToolResultName = (part, serverToolCalls, mcpToolCalls) => {
1332
+ if (part.type === "server_tool_use" && typeof part.name === "string") return normalizeProviderToolName(part.name);
1333
+ if (part.type === "mcp_tool_use") return typeof part.name === "string" ? part.name : "mcp";
1334
+ if (part.type === "mcp_tool_result") return mcpToolCalls[part.tool_use_id ?? ""] ?? "mcp";
1335
+ const resolvedServerName = serverToolCalls[part.tool_use_id ?? ""];
1336
+ if (resolvedServerName) return normalizeProviderToolName(resolvedServerName);
1337
+ switch (part.type) {
1338
+ case "web_fetch_tool_result": return "web_fetch";
1339
+ case "web_search_tool_result": return "web_search";
1340
+ case "code_execution_tool_result":
1341
+ case "bash_code_execution_tool_result":
1342
+ case "text_editor_code_execution_tool_result": return "code_execution";
1343
+ case "tool_search_tool_result": return "tool_search_tool_regex";
1344
+ default: return part.type;
1345
+ }
1346
+ };
1347
+ function mapFromAnthropicMessagesResponse(args) {
1348
+ const assistantParts = [];
1349
+ const outputItems = [];
1350
+ const serverToolCalls = {};
1351
+ const mcpToolCalls = {};
1352
+ let isJsonResponseFromTool = false;
1353
+ for (const part of args.response.content) switch (part.type) {
1354
+ case "text":
1355
+ assistantParts.push({
1356
+ type: "text",
1357
+ text: part.text,
1358
+ ...part.citations?.length ? { providerMetadata: getAnthropicTextProviderMetadata(part.citations) } : {}
1359
+ });
1360
+ break;
1361
+ case "compaction":
1362
+ assistantParts.push({
1363
+ type: "text",
1364
+ text: part.content
1365
+ });
1366
+ break;
1367
+ case "tool_use":
1368
+ if (args.usesJsonResponseTool && part.name === "json") {
1369
+ isJsonResponseFromTool = true;
1370
+ assistantParts.push({
1371
+ type: "text",
1372
+ text: JSON.stringify(part.input)
1373
+ });
1374
+ } else outputItems.push({
1375
+ type: "tool-call",
1376
+ name: part.name,
1377
+ arguments: JSON.stringify(part.input ?? {}),
1378
+ callId: part.id
1379
+ });
1380
+ break;
1381
+ case "server_tool_use":
1382
+ serverToolCalls[part.id] = part.name;
1383
+ outputItems.push({
1384
+ type: "provider-tool-result",
1385
+ name: normalizeProviderToolName(part.name),
1386
+ callId: part.id,
1387
+ result: part
1388
+ });
1389
+ break;
1390
+ case "mcp_tool_use":
1391
+ mcpToolCalls[part.id] = part.name;
1392
+ outputItems.push({
1393
+ type: "provider-tool-result",
1394
+ name: part.name,
1395
+ callId: part.id,
1396
+ result: part
1397
+ });
1398
+ break;
1399
+ case "mcp_tool_result":
1400
+ case "web_fetch_tool_result":
1401
+ case "web_search_tool_result":
1402
+ case "code_execution_tool_result":
1403
+ case "bash_code_execution_tool_result":
1404
+ case "text_editor_code_execution_tool_result":
1405
+ case "tool_search_tool_result":
1406
+ outputItems.push({
1407
+ type: "provider-tool-result",
1408
+ name: mapProviderToolResultName(part, serverToolCalls, mcpToolCalls),
1409
+ callId: part.tool_use_id,
1410
+ result: part,
1411
+ isError: "is_error" in part && typeof part.is_error === "boolean" ? part.is_error : void 0
1412
+ });
1413
+ break;
1414
+ case "thinking":
1415
+ case "redacted_thinking": break;
1416
+ }
1417
+ if (assistantParts.length) outputItems.unshift({
1418
+ type: "message",
1419
+ role: "assistant",
1420
+ content: assistantParts
1421
+ });
1422
+ return {
1423
+ output: outputItems,
1424
+ finishReason: mapAnthropicStopReason(args.response.stop_reason, isJsonResponseFromTool),
1425
+ usage: mapAnthropicUsage(args.response.usage),
1426
+ response: { body: args.response }
1427
+ };
1428
+ }
1429
+ const createAnthropicStreamState = (messageId, usesJsonResponseTool = false) => ({
1430
+ messageId,
1431
+ outputItems: [],
1432
+ assistantParts: [],
1433
+ blocks: {},
1434
+ serverToolCalls: {},
1435
+ mcpToolCalls: {},
1436
+ finishReasonRaw: void 0,
1437
+ usage: {},
1438
+ usesJsonResponseTool
1439
+ });
1440
+ const createToolStartEvent = (parentMessageId, toolCallId, toolCallName) => ({
1441
+ type: Events.TOOL_CALL_START,
1442
+ parentMessageId,
1443
+ toolCallId,
1444
+ toolCallName,
1445
+ timestamp: Date.now()
1446
+ });
1447
+ const createToolArgsEvent = (parentMessageId, toolCallId, toolCallName, delta) => ({
1448
+ type: Events.TOOL_CALL_ARGS,
1449
+ parentMessageId,
1450
+ toolCallId,
1451
+ toolCallName,
1452
+ delta,
1453
+ timestamp: Date.now()
1454
+ });
1455
+ const createToolEndEvent = (parentMessageId, toolCallId, toolCallName) => ({
1456
+ type: Events.TOOL_CALL_END,
1457
+ parentMessageId,
1458
+ toolCallId,
1459
+ toolCallName,
1460
+ timestamp: Date.now()
1461
+ });
1462
+ const createToolResultEvent = (parentMessageId, toolCallId, toolCallName, result, isError) => ({
1463
+ type: Events.TOOL_CALL_RESULT,
1464
+ parentMessageId,
1465
+ toolCallId,
1466
+ toolCallName,
1467
+ result,
1468
+ isError,
1469
+ timestamp: Date.now()
1470
+ });
1471
+ const finalizeStreamResponse = (state) => {
1472
+ const output = [...state.outputItems];
1473
+ if (state.assistantParts.length) output.unshift({
1474
+ type: "message",
1475
+ role: "assistant",
1476
+ content: state.assistantParts
1477
+ });
1478
+ const hasToolCalls = output.some((item) => item.type === "tool-call" && "arguments" in item);
1479
+ return {
1480
+ output,
1481
+ finishReason: state.finishReasonRaw == null && hasToolCalls ? "tool-calls" : mapAnthropicStopReason(state.finishReasonRaw, state.usesJsonResponseTool),
1482
+ usage: mapAnthropicUsage(state.usage)
1483
+ };
1484
+ };
1485
+ function mapFromAnthropicStreamEvent(event, state) {
1486
+ switch (event.type) {
1487
+ case "ping": return ok(null);
1488
+ case "message_start":
1489
+ state.usage = {
1490
+ ...state.usage,
1491
+ ...event.message.usage
1492
+ };
1493
+ state.finishReasonRaw = event.message.stop_reason;
1494
+ return ok(null);
1495
+ case "message_delta":
1496
+ if (event.delta.stop_reason != null) state.finishReasonRaw = event.delta.stop_reason;
1497
+ state.usage = {
1498
+ ...state.usage,
1499
+ ...event.usage ?? {}
1500
+ };
1501
+ return ok(null);
1502
+ case "content_block_start": {
1503
+ const { index, content_block: part } = event;
1504
+ switch (part.type) {
1505
+ case "text":
1506
+ case "compaction": {
1507
+ const textMessageId = `${state.messageId}:text:${index}`;
1508
+ state.blocks[index] = {
1509
+ kind: "text",
1510
+ messageId: textMessageId,
1511
+ text: part.type === "compaction" ? part.content : "",
1512
+ ...part.type === "text" && part.citations?.length ? { citations: [...part.citations] } : {}
1513
+ };
1514
+ return ok({
1515
+ kind: "event",
1516
+ event: {
1517
+ type: Events.TEXT_MESSAGE_START,
1518
+ messageId: textMessageId,
1519
+ role: "assistant",
1520
+ timestamp: Date.now()
1521
+ }
1522
+ });
1523
+ }
1524
+ case "thinking":
1525
+ case "redacted_thinking": {
1526
+ const reasoningMessageId = `${state.messageId}:reasoning:${index}`;
1527
+ state.blocks[index] = {
1528
+ kind: "reasoning",
1529
+ messageId: reasoningMessageId
1530
+ };
1531
+ return ok({
1532
+ kind: "event",
1533
+ event: {
1534
+ type: Events.REASONING_MESSAGE_START,
1535
+ messageId: reasoningMessageId,
1536
+ role: "assistant",
1537
+ visibility: "full",
1538
+ timestamp: Date.now()
1539
+ }
1540
+ });
1541
+ }
1542
+ case "tool_use": {
1543
+ const outputAsText = state.usesJsonResponseTool && part.name === "json";
1544
+ const initialInput = JSON.stringify(part.input ?? {});
1545
+ state.blocks[index] = {
1546
+ kind: "tool",
1547
+ callId: part.id,
1548
+ toolName: part.name,
1549
+ rawToolName: part.name,
1550
+ rawType: "tool_use",
1551
+ input: initialInput === "{}" ? "" : initialInput,
1552
+ outputAsText,
1553
+ providerExecuted: false
1554
+ };
1555
+ if (outputAsText) {
1556
+ const textMessageId = `${state.messageId}:text:${index}`;
1557
+ state.blocks[index] = {
1558
+ ...state.blocks[index],
1559
+ kind: "tool"
1560
+ };
1561
+ return ok({
1562
+ kind: "event",
1563
+ event: {
1564
+ type: Events.TEXT_MESSAGE_START,
1565
+ messageId: textMessageId,
1566
+ role: "assistant",
1567
+ timestamp: Date.now()
1568
+ }
1569
+ });
1570
+ }
1571
+ return ok({
1572
+ kind: "event",
1573
+ event: createToolStartEvent(state.messageId, part.id, part.name)
1574
+ });
1575
+ }
1576
+ case "server_tool_use":
1577
+ state.serverToolCalls[part.id] = part.name;
1578
+ state.blocks[index] = {
1579
+ kind: "tool",
1580
+ callId: part.id,
1581
+ toolName: normalizeProviderToolName(part.name),
1582
+ rawToolName: part.name,
1583
+ rawType: "server_tool_use",
1584
+ input: JSON.stringify(part.input ?? {}) === "{}" ? "" : JSON.stringify(part.input ?? {}),
1585
+ outputAsText: false,
1586
+ providerExecuted: true
1587
+ };
1588
+ return ok({
1589
+ kind: "event",
1590
+ event: createToolStartEvent(state.messageId, part.id, normalizeProviderToolName(part.name))
1591
+ });
1592
+ case "mcp_tool_use":
1593
+ state.mcpToolCalls[part.id] = part.name;
1594
+ state.blocks[index] = {
1595
+ kind: "tool",
1596
+ callId: part.id,
1597
+ toolName: part.name,
1598
+ rawToolName: part.name,
1599
+ rawType: "mcp_tool_use",
1600
+ input: JSON.stringify(part.input ?? {}) === "{}" ? "" : JSON.stringify(part.input ?? {}),
1601
+ outputAsText: false,
1602
+ providerExecuted: true,
1603
+ extra: part.server_name != null ? { server_name: part.server_name } : void 0
1604
+ };
1605
+ return ok({
1606
+ kind: "event",
1607
+ event: createToolStartEvent(state.messageId, part.id, part.name)
1608
+ });
1609
+ case "mcp_tool_result":
1610
+ case "web_fetch_tool_result":
1611
+ case "web_search_tool_result":
1612
+ case "code_execution_tool_result":
1613
+ case "bash_code_execution_tool_result":
1614
+ case "text_editor_code_execution_tool_result":
1615
+ case "tool_search_tool_result": {
1616
+ const toolName = mapProviderToolResultName(part, state.serverToolCalls, state.mcpToolCalls);
1617
+ state.outputItems.push({
1618
+ type: "provider-tool-result",
1619
+ name: toolName,
1620
+ callId: part.tool_use_id,
1621
+ result: part,
1622
+ isError: "is_error" in part && typeof part.is_error === "boolean" ? part.is_error : void 0
1623
+ });
1624
+ return ok({
1625
+ kind: "event",
1626
+ event: createToolResultEvent(state.messageId, part.tool_use_id, toolName, part, "is_error" in part && typeof part.is_error === "boolean" ? part.is_error : void 0)
1627
+ });
1628
+ }
1629
+ }
1630
+ return ok(null);
1631
+ }
1632
+ case "content_block_delta": {
1633
+ const block = state.blocks[event.index];
1634
+ if (!block) return ok(null);
1635
+ switch (event.delta.type) {
1636
+ case "text_delta":
1637
+ if (block.kind !== "text") return ok(null);
1638
+ block.text += event.delta.text;
1639
+ return ok({
1640
+ kind: "event",
1641
+ event: {
1642
+ type: Events.TEXT_MESSAGE_CONTENT,
1643
+ messageId: block.messageId,
1644
+ delta: event.delta.text,
1645
+ timestamp: Date.now()
1646
+ }
1647
+ });
1648
+ case "compaction_delta":
1649
+ if (block.kind !== "text") return ok(null);
1650
+ if (event.delta.content) {
1651
+ block.text += event.delta.content;
1652
+ return ok({
1653
+ kind: "event",
1654
+ event: {
1655
+ type: Events.TEXT_MESSAGE_CONTENT,
1656
+ messageId: block.messageId,
1657
+ delta: event.delta.content,
1658
+ timestamp: Date.now()
1659
+ }
1660
+ });
1661
+ }
1662
+ return ok(null);
1663
+ case "thinking_delta":
1664
+ if (block.kind !== "reasoning") return ok(null);
1665
+ return ok({
1666
+ kind: "event",
1667
+ event: {
1668
+ type: Events.REASONING_MESSAGE_CONTENT,
1669
+ messageId: block.messageId,
1670
+ visibility: "full",
1671
+ delta: event.delta.thinking,
1672
+ timestamp: Date.now()
1673
+ }
1674
+ });
1675
+ case "signature_delta": return ok(null);
1676
+ case "input_json_delta":
1677
+ if (block.kind !== "tool") return ok(null);
1678
+ block.input += event.delta.partial_json;
1679
+ if (block.outputAsText) return ok({
1680
+ kind: "event",
1681
+ event: {
1682
+ type: Events.TEXT_MESSAGE_CONTENT,
1683
+ messageId: `${state.messageId}:text:${event.index}`,
1684
+ delta: event.delta.partial_json,
1685
+ timestamp: Date.now()
1686
+ }
1687
+ });
1688
+ return ok({
1689
+ kind: "event",
1690
+ event: createToolArgsEvent(state.messageId, block.callId, block.toolName, event.delta.partial_json)
1691
+ });
1692
+ case "citations_delta":
1693
+ if (block.kind !== "text") return ok(null);
1694
+ block.citations = [...block.citations ?? [], event.delta.citation];
1695
+ return ok(null);
1696
+ }
1697
+ return ok(null);
1698
+ }
1699
+ case "content_block_stop": {
1700
+ const block = state.blocks[event.index];
1701
+ if (!block) return ok(null);
1702
+ delete state.blocks[event.index];
1703
+ if (block.kind === "text") {
1704
+ if (block.text.length > 0) state.assistantParts.push({
1705
+ type: "text",
1706
+ text: block.text,
1707
+ ...block.citations?.length ? { providerMetadata: getAnthropicTextProviderMetadata(block.citations) } : {}
1708
+ });
1709
+ return ok({
1710
+ kind: "event",
1711
+ event: {
1712
+ type: Events.TEXT_MESSAGE_END,
1713
+ messageId: block.messageId,
1714
+ timestamp: Date.now()
1715
+ }
1716
+ });
1717
+ }
1718
+ if (block.kind === "reasoning") return ok({
1719
+ kind: "event",
1720
+ event: {
1721
+ type: Events.REASONING_MESSAGE_END,
1722
+ messageId: block.messageId,
1723
+ visibility: "full",
1724
+ timestamp: Date.now()
1725
+ }
1726
+ });
1727
+ if (block.outputAsText) {
1728
+ const finalText = block.input.trim() ? block.input : "{}";
1729
+ state.assistantParts.push({
1730
+ type: "text",
1731
+ text: finalText
1732
+ });
1733
+ state.usesJsonResponseTool = true;
1734
+ return ok({
1735
+ kind: "event",
1736
+ event: {
1737
+ type: Events.TEXT_MESSAGE_END,
1738
+ messageId: `${state.messageId}:text:${event.index}`,
1739
+ timestamp: Date.now()
1740
+ }
1741
+ });
1742
+ }
1743
+ if (block.rawType === "tool_use") state.outputItems.push({
1744
+ type: "tool-call",
1745
+ name: block.toolName,
1746
+ arguments: block.input.trim() ? block.input : "{}",
1747
+ callId: block.callId
1748
+ });
1749
+ else state.outputItems.push({
1750
+ type: "provider-tool-result",
1751
+ name: block.toolName,
1752
+ callId: block.callId,
1753
+ result: omitNullish({
1754
+ type: block.rawType,
1755
+ id: block.callId,
1756
+ name: block.rawToolName,
1757
+ input: parseMaybeJson(block.input),
1758
+ ...block.extra ?? {}
1759
+ })
1760
+ });
1761
+ return ok({
1762
+ kind: "event",
1763
+ event: createToolEndEvent(state.messageId, block.callId, block.toolName)
1764
+ });
1765
+ }
1766
+ case "message_stop": return ok({
1767
+ kind: "final",
1768
+ response: finalizeStreamResponse(state)
1769
+ });
1770
+ case "error": return err(BetterAgentError.fromCode("UPSTREAM_FAILED", event.error.message ?? "Anthropic streaming error", { context: {
1771
+ provider: "anthropic",
1772
+ upstreamCode: event.error.type ?? "STREAM_ERROR",
1773
+ raw: event
1774
+ } }).at({ at: "anthropic.messages.stream.event" }));
1775
+ }
1776
+ }
1777
+
1778
+ //#endregion
1779
+ //#region src/anthropic/responses/model.ts
1780
+ const ANTHROPIC_RESPONSE_CAPS = {
1781
+ inputModalities: {
1782
+ text: true,
1783
+ image: true,
1784
+ file: true
1785
+ },
1786
+ inputShape: "chat",
1787
+ replayMode: "multi_turn",
1788
+ supportsInstruction: true,
1789
+ outputModalities: { text: { options: {} } },
1790
+ tools: true,
1791
+ structured_output: true,
1792
+ additionalSupportedRoles: ["developer"]
1793
+ };
1794
+ const createDeferred = () => {
1795
+ let resolve;
1796
+ let reject;
1797
+ return {
1798
+ promise: new Promise((res, rej) => {
1799
+ resolve = res;
1800
+ reject = rej;
1801
+ }),
1802
+ resolve,
1803
+ reject
1804
+ };
1805
+ };
1806
+ const createAnthropicResponsesModel = (modelId, client) => {
1807
+ const doGenerate = async (options, ctx) => {
1808
+ const mappedRequest = mapToAnthropicMessagesRequest({
1809
+ modelId,
1810
+ options,
1811
+ stream: false
1812
+ });
1813
+ if (mappedRequest.isErr()) return err(mappedRequest.error.at({ at: "anthropic.generate.mapRequest" }));
1814
+ const raw = await client.messages.create(mappedRequest.value.request, {
1815
+ signal: ctx.signal ?? null,
1816
+ beta: mappedRequest.value.betas
1817
+ });
1818
+ if (raw.isErr()) return err(raw.error.at({ at: "anthropic.generate.http" }));
1819
+ return ok({ response: {
1820
+ ...mapFromAnthropicMessagesResponse({
1821
+ response: raw.value,
1822
+ usesJsonResponseTool: mappedRequest.value.usesJsonResponseTool
1823
+ }),
1824
+ request: { body: mappedRequest.value.request }
1825
+ } });
1826
+ };
1827
+ const doGenerateStream = async (options, ctx) => {
1828
+ const mappedRequest = mapToAnthropicMessagesRequest({
1829
+ modelId,
1830
+ options,
1831
+ stream: true
1832
+ });
1833
+ if (mappedRequest.isErr()) return err(mappedRequest.error.at({ at: "anthropic.generateStream.mapRequest" }));
1834
+ const streamResult = await client.messages.stream({
1835
+ ...mappedRequest.value.request,
1836
+ stream: true
1837
+ }, {
1838
+ signal: ctx.signal ?? null,
1839
+ beta: mappedRequest.value.betas
1840
+ });
1841
+ if (streamResult.isErr()) return err(streamResult.error.at({ at: "anthropic.generateStream.http" }));
1842
+ const { promise: final, resolve: resolveFinal, reject: rejectFinal } = createDeferred();
1843
+ return ok({
1844
+ events: (async function* () {
1845
+ const state = createAnthropicStreamState(ctx.generateMessageId(), mappedRequest.value.usesJsonResponseTool);
1846
+ let sawFinal = false;
1847
+ try {
1848
+ for await (const raw of streamResult.value) {
1849
+ if (raw.isErr()) {
1850
+ rejectFinal(raw.error);
1851
+ yield err(raw.error);
1852
+ return;
1853
+ }
1854
+ const mapped = mapFromAnthropicStreamEvent(raw.value, state);
1855
+ if (mapped.isErr()) {
1856
+ const error = mapped.error.at({ at: "anthropic.generateStream.mapEvent" });
1857
+ rejectFinal(error);
1858
+ yield err(error);
1859
+ return;
1860
+ }
1861
+ if (!mapped.value) continue;
1862
+ if (mapped.value.kind === "final") {
1863
+ sawFinal = true;
1864
+ resolveFinal({
1865
+ ...mapped.value.response,
1866
+ request: { body: mappedRequest.value.request }
1867
+ });
1868
+ continue;
1869
+ }
1870
+ yield ok(mapped.value.event);
1871
+ }
1872
+ } finally {
1873
+ if (!sawFinal) rejectFinal(BetterAgentError.fromCode("UPSTREAM_FAILED", "Anthropic stream ended without a final response event.", { context: {
1874
+ provider: "anthropic",
1875
+ model: String(modelId)
1876
+ } }).at({ at: "anthropic.generateStream.final" }));
1877
+ }
1878
+ })(),
1879
+ final
1880
+ });
1881
+ };
1882
+ return {
1883
+ providerId: "anthropic",
1884
+ modelId,
1885
+ caps: ANTHROPIC_RESPONSE_CAPS,
1886
+ doGenerate,
1887
+ doGenerateStream
1888
+ };
1889
+ };
1890
+
1891
+ //#endregion
1892
+ //#region src/anthropic/provider.ts
1893
+ const createAnthropic = (config) => {
1894
+ const httpClient = createAnthropicClient(config);
1895
+ return {
1896
+ id: "anthropic",
1897
+ tools: createAnthropicNativeToolBuilders(),
1898
+ model(modelId) {
1899
+ return createAnthropicResponsesModel(modelId, httpClient);
1900
+ },
1901
+ text(modelId) {
1902
+ return createAnthropicResponsesModel(modelId, httpClient);
1903
+ }
1904
+ };
1905
+ };
1906
+
1907
+ //#endregion
1908
+ export { createAnthropic };
1909
+ //# sourceMappingURL=index.mjs.map