@effect/ai-anthropic 0.23.0 → 4.0.0-beta.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.
Files changed (104) hide show
  1. package/dist/AnthropicClient.d.ts +196 -0
  2. package/dist/AnthropicClient.d.ts.map +1 -0
  3. package/dist/AnthropicClient.js +142 -0
  4. package/dist/AnthropicClient.js.map +1 -0
  5. package/dist/{dts/AnthropicConfig.d.ts → AnthropicConfig.d.ts} +9 -9
  6. package/dist/AnthropicConfig.d.ts.map +1 -0
  7. package/dist/{esm/AnthropicConfig.js → AnthropicConfig.js} +8 -5
  8. package/dist/AnthropicConfig.js.map +1 -0
  9. package/dist/AnthropicError.d.ts +102 -0
  10. package/dist/AnthropicError.d.ts.map +1 -0
  11. package/dist/AnthropicError.js +10 -0
  12. package/dist/AnthropicError.js.map +1 -0
  13. package/dist/AnthropicLanguageModel.d.ts +522 -0
  14. package/dist/AnthropicLanguageModel.d.ts.map +1 -0
  15. package/dist/AnthropicLanguageModel.js +2107 -0
  16. package/dist/AnthropicLanguageModel.js.map +1 -0
  17. package/dist/AnthropicTelemetry.d.ts +101 -0
  18. package/dist/AnthropicTelemetry.d.ts.map +1 -0
  19. package/dist/AnthropicTelemetry.js +35 -0
  20. package/dist/AnthropicTelemetry.js.map +1 -0
  21. package/dist/AnthropicTool.d.ts +2153 -0
  22. package/dist/AnthropicTool.d.ts.map +1 -0
  23. package/dist/AnthropicTool.js +1168 -0
  24. package/dist/AnthropicTool.js.map +1 -0
  25. package/dist/Generated.d.ts +25233 -0
  26. package/dist/Generated.d.ts.map +1 -0
  27. package/dist/Generated.js +7649 -0
  28. package/dist/Generated.js.map +1 -0
  29. package/dist/index.d.ts +53 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +54 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/internal/errors.d.ts +2 -0
  34. package/dist/internal/errors.d.ts.map +1 -0
  35. package/dist/internal/errors.js +344 -0
  36. package/dist/internal/errors.js.map +1 -0
  37. package/dist/{dts/internal → internal}/utilities.d.ts.map +1 -1
  38. package/dist/internal/utilities.js.map +1 -0
  39. package/package.json +45 -81
  40. package/src/AnthropicClient.ts +327 -683
  41. package/src/AnthropicConfig.ts +20 -34
  42. package/src/AnthropicError.ts +111 -0
  43. package/src/AnthropicLanguageModel.ts +2039 -993
  44. package/src/AnthropicTelemetry.ts +138 -0
  45. package/src/AnthropicTool.ts +1500 -475
  46. package/src/Generated.ts +9798 -6359
  47. package/src/index.ts +38 -6
  48. package/src/internal/errors.ts +368 -0
  49. package/src/internal/utilities.ts +1 -1
  50. package/AnthropicClient/package.json +0 -6
  51. package/AnthropicConfig/package.json +0 -6
  52. package/AnthropicLanguageModel/package.json +0 -6
  53. package/AnthropicTokenizer/package.json +0 -6
  54. package/AnthropicTool/package.json +0 -6
  55. package/Generated/package.json +0 -6
  56. package/README.md +0 -5
  57. package/dist/cjs/AnthropicClient.js +0 -344
  58. package/dist/cjs/AnthropicClient.js.map +0 -1
  59. package/dist/cjs/AnthropicConfig.js +0 -30
  60. package/dist/cjs/AnthropicConfig.js.map +0 -1
  61. package/dist/cjs/AnthropicLanguageModel.js +0 -1322
  62. package/dist/cjs/AnthropicLanguageModel.js.map +0 -1
  63. package/dist/cjs/AnthropicTokenizer.js +0 -52
  64. package/dist/cjs/AnthropicTokenizer.js.map +0 -1
  65. package/dist/cjs/AnthropicTool.js +0 -461
  66. package/dist/cjs/AnthropicTool.js.map +0 -1
  67. package/dist/cjs/Generated.js +0 -6578
  68. package/dist/cjs/Generated.js.map +0 -1
  69. package/dist/cjs/index.js +0 -20
  70. package/dist/cjs/index.js.map +0 -1
  71. package/dist/cjs/internal/utilities.js +0 -29
  72. package/dist/cjs/internal/utilities.js.map +0 -1
  73. package/dist/dts/AnthropicClient.d.ts +0 -730
  74. package/dist/dts/AnthropicClient.d.ts.map +0 -1
  75. package/dist/dts/AnthropicConfig.d.ts.map +0 -1
  76. package/dist/dts/AnthropicLanguageModel.d.ts +0 -304
  77. package/dist/dts/AnthropicLanguageModel.d.ts.map +0 -1
  78. package/dist/dts/AnthropicTokenizer.d.ts +0 -13
  79. package/dist/dts/AnthropicTokenizer.d.ts.map +0 -1
  80. package/dist/dts/AnthropicTool.d.ts +0 -548
  81. package/dist/dts/AnthropicTool.d.ts.map +0 -1
  82. package/dist/dts/Generated.d.ts +0 -12504
  83. package/dist/dts/Generated.d.ts.map +0 -1
  84. package/dist/dts/index.d.ts +0 -25
  85. package/dist/dts/index.d.ts.map +0 -1
  86. package/dist/esm/AnthropicClient.js +0 -317
  87. package/dist/esm/AnthropicClient.js.map +0 -1
  88. package/dist/esm/AnthropicConfig.js.map +0 -1
  89. package/dist/esm/AnthropicLanguageModel.js +0 -1309
  90. package/dist/esm/AnthropicLanguageModel.js.map +0 -1
  91. package/dist/esm/AnthropicTokenizer.js +0 -44
  92. package/dist/esm/AnthropicTokenizer.js.map +0 -1
  93. package/dist/esm/AnthropicTool.js +0 -452
  94. package/dist/esm/AnthropicTool.js.map +0 -1
  95. package/dist/esm/Generated.js +0 -6247
  96. package/dist/esm/Generated.js.map +0 -1
  97. package/dist/esm/index.js +0 -25
  98. package/dist/esm/index.js.map +0 -1
  99. package/dist/esm/internal/utilities.js.map +0 -1
  100. package/dist/esm/package.json +0 -4
  101. package/index/package.json +0 -6
  102. package/src/AnthropicTokenizer.ts +0 -59
  103. /package/dist/{dts/internal → internal}/utilities.d.ts +0 -0
  104. /package/dist/{esm/internal → internal}/utilities.js +0 -0
@@ -0,0 +1,2107 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ /** @effect-diagnostics preferSchemaOverJson:skip-file */
5
+ import * as Arr from "effect/Array";
6
+ import * as DateTime from "effect/DateTime";
7
+ import * as Effect from "effect/Effect";
8
+ import * as Base64 from "effect/encoding/Base64";
9
+ import { dual } from "effect/Function";
10
+ import * as Layer from "effect/Layer";
11
+ import * as Predicate from "effect/Predicate";
12
+ import * as Redactable from "effect/Redactable";
13
+ import * as Schema from "effect/Schema";
14
+ import * as SchemaAST from "effect/SchemaAST";
15
+ import * as ServiceMap from "effect/ServiceMap";
16
+ import * as Stream from "effect/Stream";
17
+ import * as AiError from "effect/unstable/ai/AiError";
18
+ import { toCodecAnthropic } from "effect/unstable/ai/AnthropicStructuredOutput";
19
+ import * as IdGenerator from "effect/unstable/ai/IdGenerator";
20
+ import * as LanguageModel from "effect/unstable/ai/LanguageModel";
21
+ import * as AiModel from "effect/unstable/ai/Model";
22
+ import * as Tool from "effect/unstable/ai/Tool";
23
+ import { AnthropicClient } from "./AnthropicClient.js";
24
+ import { addGenAIAnnotations } from "./AnthropicTelemetry.js";
25
+ import * as InternalUtilities from "./internal/utilities.js";
26
+ // =============================================================================
27
+ // Configuration
28
+ // =============================================================================
29
+ /**
30
+ * Configuration options for the Anthropic language model.
31
+ *
32
+ * This service can be used to provide default configuration values or to
33
+ * override configuration on a per-request basis.
34
+ *
35
+ * @since 1.0.0
36
+ * @category configuration
37
+ */
38
+ export class Config extends /*#__PURE__*/ServiceMap.Service()("@effect/ai-anthropic/AnthropicLanguageModel/Config") {}
39
+ // =============================================================================
40
+ // Language Model
41
+ // =============================================================================
42
+ /**
43
+ * Creates an Anthropic language model that can be used with `AiModel.provide`.
44
+ *
45
+ * @since 1.0.0
46
+ * @category constructors
47
+ */
48
+ export const model = (model, config) => AiModel.make("anthropic", layer({
49
+ model,
50
+ config
51
+ }));
52
+ /**
53
+ * Creates an Anthropic language model service.
54
+ *
55
+ * @since 1.0.0
56
+ * @category constructors
57
+ */
58
+ export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
59
+ model,
60
+ config: providerConfig
61
+ }) {
62
+ const client = yield* AnthropicClient;
63
+ const makeConfig = Effect.gen(function* () {
64
+ const services = yield* Effect.services();
65
+ return {
66
+ model,
67
+ ...providerConfig,
68
+ ...services.mapUnsafe.get(Config.key)
69
+ };
70
+ });
71
+ const makeRequest = Effect.fnUntraced(function* ({
72
+ config,
73
+ options,
74
+ toolNameMapper
75
+ }) {
76
+ const betas = new Set();
77
+ const capabilities = getModelCapabilities(config.model);
78
+ const {
79
+ messages,
80
+ system
81
+ } = yield* prepareMessages({
82
+ betas,
83
+ options,
84
+ toolNameMapper
85
+ });
86
+ const outputFormat = yield* getOutputFormat({
87
+ capabilities,
88
+ options
89
+ });
90
+ const {
91
+ tools,
92
+ toolChoice
93
+ } = yield* prepareTools({
94
+ betas,
95
+ capabilities,
96
+ config,
97
+ options
98
+ });
99
+ const params = {};
100
+ if (betas.size > 0) {
101
+ params["anthropic-beta"] = Array.from(betas).join(",");
102
+ }
103
+ const {
104
+ disableParallelToolCalls: _,
105
+ output_config,
106
+ ...requestConfig
107
+ } = config;
108
+ const payload = {
109
+ ...requestConfig,
110
+ max_tokens: requestConfig.max_tokens ?? capabilities.maxOutputTokens,
111
+ messages,
112
+ ...(Predicate.isNotUndefined(system) ? {
113
+ system
114
+ } : undefined),
115
+ ...(Predicate.isNotUndefined(tools) ? {
116
+ tools
117
+ } : undefined),
118
+ ...(Predicate.isNotUndefined(toolChoice) ? {
119
+ tool_choice: toolChoice
120
+ } : undefined)
121
+ };
122
+ const outputConfig = {};
123
+ if (Predicate.isNotUndefined(outputFormat)) {
124
+ outputConfig.format = outputFormat;
125
+ }
126
+ if (Predicate.isNotUndefined(output_config?.effort)) {
127
+ outputConfig.effort = output_config.effort;
128
+ }
129
+ if (Object.keys(outputConfig).length > 0) {
130
+ payload.output_config = outputConfig;
131
+ }
132
+ return {
133
+ params,
134
+ payload
135
+ };
136
+ });
137
+ return yield* LanguageModel.make({
138
+ generateText: Effect.fnUntraced(function* (options) {
139
+ const config = yield* makeConfig;
140
+ const toolNameMapper = new Tool.NameMapper(options.tools);
141
+ const request = yield* makeRequest({
142
+ config,
143
+ options,
144
+ toolNameMapper
145
+ });
146
+ annotateRequest(options.span, request.payload);
147
+ const [rawResponse, response] = yield* client.createMessage(request);
148
+ annotateResponse(options.span, rawResponse);
149
+ return yield* makeResponse({
150
+ options,
151
+ rawResponse,
152
+ response,
153
+ toolNameMapper
154
+ });
155
+ }),
156
+ streamText: Effect.fnUntraced(function* (options) {
157
+ const config = yield* makeConfig;
158
+ const toolNameMapper = new Tool.NameMapper(options.tools);
159
+ const request = yield* makeRequest({
160
+ config,
161
+ options,
162
+ toolNameMapper
163
+ });
164
+ annotateRequest(options.span, request.payload);
165
+ const [response, stream] = yield* client.createMessageStream(request);
166
+ return yield* makeStreamResponse({
167
+ stream,
168
+ response,
169
+ options,
170
+ toolNameMapper
171
+ });
172
+ }, (effect, options) => effect.pipe(Stream.unwrap, Stream.map(response => {
173
+ annotateStreamResponse(options.span, response);
174
+ return response;
175
+ })))
176
+ }).pipe(Effect.provideService(LanguageModel.CurrentCodecTransformer, toCodecAnthropic));
177
+ });
178
+ /**
179
+ * Creates a layer for the Anthropic language model.
180
+ *
181
+ * @since 1.0.0
182
+ * @category layers
183
+ */
184
+ export const layer = options => Layer.effect(LanguageModel.LanguageModel, make(options));
185
+ /**
186
+ * Provides config overrides for Anthropic language model operations.
187
+ *
188
+ * @since 1.0.0
189
+ * @category configuration
190
+ */
191
+ export const withConfigOverride = /*#__PURE__*/dual(2, (self, overrides) => Effect.flatMap(Effect.serviceOption(Config), config => Effect.provideService(self, Config, {
192
+ ...(config._tag === "Some" ? config.value : {}),
193
+ ...overrides
194
+ })));
195
+ // =============================================================================
196
+ // Prompt Conversion
197
+ // =============================================================================
198
+ const prepareMessages = /*#__PURE__*/Effect.fnUntraced(function* ({
199
+ betas,
200
+ options,
201
+ toolNameMapper
202
+ }) {
203
+ const groups = groupMessages(options.prompt);
204
+ let system = undefined;
205
+ const messages = [];
206
+ for (let i = 0; i < groups.length; i++) {
207
+ const group = groups[i];
208
+ const isLastGroup = i === groups.length - 1;
209
+ switch (group.type) {
210
+ case "system":
211
+ {
212
+ system = group.messages.map(message => ({
213
+ type: "text",
214
+ text: message.content,
215
+ cache_control: getCacheControl(message)
216
+ }));
217
+ break;
218
+ }
219
+ case "user":
220
+ {
221
+ const content = [];
222
+ for (const message of group.messages) {
223
+ switch (message.role) {
224
+ case "user":
225
+ {
226
+ for (let j = 0; j < message.content.length; j++) {
227
+ const part = message.content[j];
228
+ const isLastPart = j === message.content.length - 1;
229
+ // Attempt to get the cache control from the part first. If
230
+ // the part does not have cache control defined and we are
231
+ // evaluating the last part for this message, also check the
232
+ // message for cache control.
233
+ const cacheControl = getCacheControl(part) ?? (isLastPart ? getCacheControl(message) : null);
234
+ switch (part.type) {
235
+ case "text":
236
+ {
237
+ content.push({
238
+ type: "text",
239
+ text: part.text,
240
+ cache_control: cacheControl
241
+ });
242
+ break;
243
+ }
244
+ case "file":
245
+ {
246
+ if (part.mediaType.startsWith("image/")) {
247
+ const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType;
248
+ const source = isUrlData(part.data) ? {
249
+ type: "url",
250
+ url: getUrlString(part.data)
251
+ } : {
252
+ type: "base64",
253
+ media_type: mediaType,
254
+ data: Base64.encode(part.data)
255
+ };
256
+ content.push({
257
+ type: "image",
258
+ source,
259
+ cache_control: cacheControl
260
+ });
261
+ } else if (part.mediaType === "application/pdf" || part.mediaType === "text/plain") {
262
+ betas.add("pdfs-2024-09-25");
263
+ const enableCitations = areCitationsEnabled(part);
264
+ const documentOptions = getDocumentMetadata(part);
265
+ const source = isUrlData(part.data) ? {
266
+ type: "url",
267
+ url: getUrlString(part.data)
268
+ } : part.mediaType === "application/pdf" ? {
269
+ type: "base64",
270
+ media_type: "application/pdf",
271
+ data: typeof part.data === "string" ? part.data : Base64.encode(part.data)
272
+ } : {
273
+ type: "text",
274
+ media_type: "text/plain",
275
+ data: typeof part.data === "string" ? part.data : Base64.encode(part.data)
276
+ };
277
+ content.push({
278
+ type: "document",
279
+ source,
280
+ title: documentOptions?.title ?? part.fileName ?? null,
281
+ cache_control: cacheControl,
282
+ ...(documentOptions?.context ? {
283
+ context: documentOptions.context
284
+ } : undefined),
285
+ ...(enableCitations ? {
286
+ citations: {
287
+ enabled: true
288
+ }
289
+ } : undefined)
290
+ });
291
+ } else {
292
+ return yield* new AiError.AiError({
293
+ module: "AnthropicLanguageModel",
294
+ method: "prepareMessages",
295
+ reason: new AiError.InvalidUserInputError({
296
+ description: `Detected unsupported media type for file: '${part.mediaType}'`
297
+ })
298
+ });
299
+ }
300
+ break;
301
+ }
302
+ }
303
+ }
304
+ break;
305
+ }
306
+ case "tool":
307
+ {
308
+ for (let j = 0; j < message.content.length; j++) {
309
+ const part = message.content[j];
310
+ // Skip evaluation of tool approval parts
311
+ if (part.type === "tool-approval-response") {
312
+ continue;
313
+ }
314
+ const isLastPart = j === message.content.length - 1;
315
+ // Attempt to get the cache control from the part first. If
316
+ // the part does not have cache control defined and we are
317
+ // evaluating the last part for this message, also check the
318
+ // message for cache control.
319
+ const cacheControl = getCacheControl(part) ?? (isLastPart ? getCacheControl(message) : null);
320
+ content.push({
321
+ type: "tool_result",
322
+ tool_use_id: part.id,
323
+ content: JSON.stringify(part.result),
324
+ is_error: part.isFailure,
325
+ cache_control: cacheControl
326
+ });
327
+ }
328
+ }
329
+ }
330
+ }
331
+ messages.push({
332
+ role: "user",
333
+ content
334
+ });
335
+ break;
336
+ }
337
+ case "assistant":
338
+ {
339
+ const content = [];
340
+ const mcpToolIds = new Set();
341
+ for (let j = 0; j < group.messages.length; j++) {
342
+ const message = group.messages[j];
343
+ const isLastMessage = j === group.messages.length - 1;
344
+ for (let k = 0; k < message.content.length; k++) {
345
+ const part = message.content[k];
346
+ if (part.type === "file" || part.type === "tool-approval-request") {
347
+ continue;
348
+ }
349
+ const isLastPart = k === message.content.length - 1;
350
+ // Attempt to get the cache control from the part first. If
351
+ // the part does not have cache control defined and we are
352
+ // evaluating the last part for this message, also check the
353
+ // message for cache control.
354
+ const cacheControl = getCacheControl(part) ?? (isLastPart ? getCacheControl(message) : undefined);
355
+ // TODO: use cache_control in content blocks
356
+ void cacheControl;
357
+ switch (part.type) {
358
+ case "text":
359
+ {
360
+ content.push({
361
+ type: "text",
362
+ // Anthropic does not allow trailing whitespace in assistant
363
+ // content blocks
364
+ text: isLastGroup && isLastMessage && isLastPart ? part.text.trim() : part.text
365
+ });
366
+ break;
367
+ }
368
+ case "reasoning":
369
+ {
370
+ // TODO: make sending reasoning configurable
371
+ const info = part.options.anthropic?.info;
372
+ if (Predicate.isNotNullish(info)) {
373
+ if (info.type === "thinking") {
374
+ content.push({
375
+ type: "thinking",
376
+ thinking: part.text,
377
+ signature: info.signature
378
+ });
379
+ } else {
380
+ content.push({
381
+ type: "redacted_thinking",
382
+ data: info.redactedData
383
+ });
384
+ }
385
+ }
386
+ break;
387
+ }
388
+ case "tool-call":
389
+ {
390
+ if (part.providerExecuted) {
391
+ const toolName = toolNameMapper.getProviderName(part.name);
392
+ const isMcpTool = Predicate.isNotNullish(part.options.anthropic?.mcp_tool);
393
+ if (isMcpTool) {
394
+ const {
395
+ server
396
+ } = part.options.anthropic.mcp_tool;
397
+ mcpToolIds.add(part.id);
398
+ content.push({
399
+ type: "mcp_tool_use",
400
+ id: part.id,
401
+ name: part.name,
402
+ input: part.params,
403
+ server_name: server
404
+ });
405
+ } else if (toolName === "code_execution" && Predicate.hasProperty(part.params, "type") && (part.params.type === "bash_code_execution" || part.params.type === "text_editor_code_execution")) {
406
+ content.push({
407
+ type: "server_tool_use",
408
+ id: part.id,
409
+ name: part.params.type,
410
+ input: part.params
411
+ });
412
+ } else if (
413
+ // code execution 20250825 programmatic tool calling:
414
+ // Strip the fake 'programmatic-tool-call' type before sending to Anthropic
415
+ toolName === "code_execution" && Predicate.hasProperty(part.params, "type") && part.params.type === "programmatic-tool-call") {
416
+ const {
417
+ type,
418
+ ...params
419
+ } = part.params;
420
+ content.push({
421
+ type: "server_tool_use",
422
+ id: part.id,
423
+ name: toolName,
424
+ input: params
425
+ });
426
+ } else {
427
+ if (
428
+ // code execution 20250522
429
+ toolName === "code_execution" || toolName === "tool_search_tool_regex" || toolName === "tool_search_tool_bm25" || toolName === "web_fetch" || toolName === "web_search") {
430
+ content.push({
431
+ type: "server_tool_use",
432
+ id: part.id,
433
+ name: toolName,
434
+ input: part.params
435
+ });
436
+ }
437
+ }
438
+ } else {
439
+ // Extract caller info from provider options for programmatic tool calling
440
+ const options = part.options.anthropic;
441
+ const caller = Predicate.isNotNullish(options?.caller) ? options.caller.type === "code_execution_20250825" && Predicate.isNotNullish(options.caller.toolId) ? {
442
+ type: "code_execution_20250825",
443
+ tool_id: options.caller.toolId
444
+ } : options.caller.type === "direct" ? {
445
+ type: "direct"
446
+ } : undefined : undefined;
447
+ content.push({
448
+ type: "tool_use",
449
+ id: part.id,
450
+ name: part.name,
451
+ input: part.params,
452
+ ...(Predicate.isNotUndefined(caller) ? {
453
+ caller
454
+ } : undefined)
455
+ });
456
+ }
457
+ break;
458
+ }
459
+ case "tool-result":
460
+ {
461
+ const toolName = toolNameMapper.getProviderName(part.name);
462
+ if (mcpToolIds.has(part.id)) {
463
+ content.push({
464
+ type: "mcp_tool_result",
465
+ tool_use_id: part.id,
466
+ is_error: part.isFailure,
467
+ content: part.result
468
+ });
469
+ break;
470
+ }
471
+ if (toolName === "code_execution" && Predicate.hasProperty(part.result, "type")) {
472
+ if (part.result.type === "code_execution_result") {
473
+ content.push({
474
+ type: "code_execution_tool_result",
475
+ tool_use_id: part.id,
476
+ content: part.result
477
+ });
478
+ } else if (part.result.type === "bash_code_execution_result" || part.result.type === "bash_code_execution_tool_result_error") {
479
+ content.push({
480
+ type: "bash_code_execution_tool_result",
481
+ tool_use_id: part.id,
482
+ content: part.result
483
+ });
484
+ } else if (part.result.type === "text_editor_code_execution_tool_result" || part.result.type === "text_editor_code_execution_tool_result_error") {
485
+ content.push({
486
+ type: "text_editor_code_execution_tool_result",
487
+ tool_use_id: part.id,
488
+ content: part.result
489
+ });
490
+ }
491
+ break;
492
+ }
493
+ if (toolName === "web_fetch") {
494
+ content.push({
495
+ type: "web_fetch_tool_result",
496
+ tool_use_id: part.id,
497
+ content: part.result
498
+ });
499
+ break;
500
+ }
501
+ if (toolName === "web_search") {
502
+ content.push({
503
+ type: "web_search_tool_result",
504
+ tool_use_id: part.id,
505
+ content: part.result
506
+ });
507
+ break;
508
+ }
509
+ if (toolName === "tool_search_tool_regex" || toolName === "tool_search_tool_bm25") {
510
+ content.push({
511
+ type: "tool_search_tool_result",
512
+ tool_use_id: part.id,
513
+ content: part.result
514
+ });
515
+ break;
516
+ }
517
+ break;
518
+ }
519
+ }
520
+ }
521
+ }
522
+ messages.push({
523
+ role: "assistant",
524
+ content
525
+ });
526
+ break;
527
+ }
528
+ }
529
+ }
530
+ return {
531
+ system,
532
+ messages
533
+ };
534
+ });
535
+ const prepareTools = /*#__PURE__*/Effect.fnUntraced(function* ({
536
+ betas,
537
+ capabilities,
538
+ config,
539
+ options
540
+ }) {
541
+ if (options.tools.length === 0 || options.toolChoice === "none") {
542
+ return {
543
+ tools: undefined,
544
+ toolChoice: undefined
545
+ };
546
+ }
547
+ // Return a JSON response tool when using non-native structured outputs
548
+ if (options.responseFormat.type === "json" && !capabilities.supportsStructuredOutput) {
549
+ const input_schema = yield* tryJsonSchema(options.responseFormat.schema, "prepareTools");
550
+ const userDescription = SchemaAST.resolveDescription(options.responseFormat.schema.ast);
551
+ const description = Predicate.isNotUndefined(userDescription) ? `${userDescription} - ` : "";
552
+ return {
553
+ tools: [{
554
+ name: options.responseFormat.objectName,
555
+ description: `${description}You MUST respond with a JSON object.`,
556
+ input_schema: input_schema
557
+ }],
558
+ toolChoice: {
559
+ type: "tool",
560
+ name: options.responseFormat.objectName,
561
+ disable_parallel_tool_use: true
562
+ }
563
+ };
564
+ }
565
+ const userTools = [];
566
+ const providerTools = [];
567
+ for (const tool of options.tools) {
568
+ if (Tool.isUserDefined(tool)) {
569
+ const description = Tool.getDescription(tool);
570
+ const input_schema = yield* tryJsonSchema(tool.parametersSchema, "prepareTools");
571
+ const toolStrict = Tool.getStrictMode(tool);
572
+ const strict = capabilities.supportsStructuredOutput ? toolStrict ?? config.strictJsonSchema ?? true : undefined;
573
+ userTools.push({
574
+ name: tool.name,
575
+ input_schema: input_schema,
576
+ ...(Predicate.isNotUndefined(description) ? {
577
+ description
578
+ } : undefined),
579
+ ...(Predicate.isNotUndefined(strict) ? {
580
+ strict
581
+ } : undefined)
582
+ });
583
+ if (capabilities.supportsStructuredOutput === true) {
584
+ betas.add("structured-outputs-2025-11-13");
585
+ }
586
+ }
587
+ if (Tool.isProviderDefined(tool)) {
588
+ const providerTool = tool;
589
+ switch (providerTool.id) {
590
+ case "anthropic.bash_20241022":
591
+ {
592
+ betas.add("computer-use-2024-10-22");
593
+ providerTools.push({
594
+ name: "bash",
595
+ type: "bash_20241022"
596
+ });
597
+ break;
598
+ }
599
+ case "anthropic.bash_20250124":
600
+ {
601
+ betas.add("computer-use-2025-01-24");
602
+ providerTools.push({
603
+ name: "bash",
604
+ type: "bash_20250124"
605
+ });
606
+ break;
607
+ }
608
+ case "anthropic.code_execution_20250522":
609
+ {
610
+ betas.add("code-execution-2025-05-22");
611
+ providerTools.push({
612
+ name: "code_execution",
613
+ type: "code_execution_20250522"
614
+ });
615
+ break;
616
+ }
617
+ case "anthropic.code_execution_20250825":
618
+ {
619
+ betas.add("code-execution-2025-08-25");
620
+ providerTools.push({
621
+ name: "code_execution",
622
+ type: "code_execution_20250825"
623
+ });
624
+ break;
625
+ }
626
+ case "anthropic.computer_use_20241022":
627
+ {
628
+ betas.add("computer-use-2024-10-22");
629
+ providerTools.push({
630
+ name: "computer",
631
+ type: "computer_20241022",
632
+ display_height_px: providerTool.args.displayHeightPx,
633
+ display_width_px: providerTool.args.displayWidthPx,
634
+ display_number: providerTool.args.displayNumber ?? null
635
+ });
636
+ break;
637
+ }
638
+ case "anthropic.computer_20250124":
639
+ {
640
+ betas.add("computer-use-2025-01-24");
641
+ providerTools.push({
642
+ name: "computer",
643
+ type: "computer_20250124",
644
+ display_height_px: providerTool.args.displayHeightPx,
645
+ display_width_px: providerTool.args.displayWidthPx,
646
+ display_number: providerTool.args.displayNumber ?? null
647
+ });
648
+ break;
649
+ }
650
+ case "anthropic.computer_20251124":
651
+ {
652
+ betas.add("computer-use-2025-11-24");
653
+ providerTools.push({
654
+ name: "computer",
655
+ type: "computer_20251124",
656
+ display_height_px: providerTool.args.displayHeightPx,
657
+ display_width_px: providerTool.args.displayWidthPx,
658
+ display_number: providerTool.args.displayNumber ?? null,
659
+ enable_zoom: providerTool.args.enableZoom ?? false
660
+ });
661
+ break;
662
+ }
663
+ case "anthropic.memory_20250818":
664
+ {
665
+ betas.add("context-management-2025-06-27");
666
+ providerTools.push({
667
+ name: "memory",
668
+ type: "memory_20250818"
669
+ });
670
+ break;
671
+ }
672
+ case "anthropic.text_editor_20241022":
673
+ {
674
+ betas.add("computer-use-2024-10-22");
675
+ providerTools.push({
676
+ name: "str_replace_editor",
677
+ type: "text_editor_20241022"
678
+ });
679
+ break;
680
+ }
681
+ case "anthropic.text_editor_20250124":
682
+ {
683
+ betas.add("computer-use-2025-01-24");
684
+ providerTools.push({
685
+ name: "str_replace_editor",
686
+ type: "text_editor_20250124"
687
+ });
688
+ break;
689
+ }
690
+ case "anthropic.text_editor_20250429":
691
+ {
692
+ betas.add("computer-use-2025-01-24");
693
+ providerTools.push({
694
+ name: "str_replace_based_edit_tool",
695
+ type: "text_editor_20250429"
696
+ });
697
+ break;
698
+ }
699
+ case "anthropic.text_editor_20250728":
700
+ {
701
+ providerTools.push({
702
+ name: "str_replace_based_edit_tool",
703
+ type: "text_editor_20250728",
704
+ max_characters: providerTool.args.max_characters ?? null
705
+ });
706
+ break;
707
+ }
708
+ case "anthropic.tool_search_tool_bm25_20251119":
709
+ {
710
+ betas.add("advanced-tool-use-2025-11-20");
711
+ providerTools.push({
712
+ name: "tool_search_tool_bm25",
713
+ type: "tool_search_tool_bm25_20251119"
714
+ });
715
+ break;
716
+ }
717
+ case "anthropic.tool_search_tool_regex_20251119":
718
+ {
719
+ providerTools.push({
720
+ name: "tool_search_tool_regex",
721
+ type: "tool_search_tool_regex_20251119"
722
+ });
723
+ break;
724
+ }
725
+ case "anthropic.web_search_20250305":
726
+ {
727
+ providerTools.push({
728
+ name: "web_search",
729
+ type: "web_search_20250305",
730
+ max_uses: providerTool.args.maxUses ?? null,
731
+ allowed_domains: providerTool.args.allowedDomains ?? null,
732
+ blocked_domains: providerTool.args.blockedDomains ?? null,
733
+ user_location: Predicate.isNotUndefined(providerTool.args.userLocation) ? {
734
+ type: providerTool.args.userLocation.type,
735
+ region: providerTool.args.userLocation.region ?? null,
736
+ city: providerTool.args.userLocation.city ?? null,
737
+ country: providerTool.args.userLocation.country ?? null,
738
+ timezone: providerTool.args.userLocation.timezone ?? null
739
+ } : null
740
+ });
741
+ break;
742
+ }
743
+ case "anthropic.web_fetch_20250910":
744
+ {
745
+ betas.add("web-fetch-2025-09-10");
746
+ providerTools.push({
747
+ name: "web_fetch",
748
+ type: "web_fetch_20250910",
749
+ max_uses: providerTool.args.maxUses ?? null,
750
+ allowed_domains: providerTool.args.allowedDomains ?? null,
751
+ blocked_domains: providerTool.args.blockedDomains ?? null,
752
+ citations: providerTool.args.citations ?? null,
753
+ max_content_tokens: providerTool.args.maxContentTokens ?? null
754
+ });
755
+ break;
756
+ }
757
+ default:
758
+ {
759
+ return yield* AiError.make({
760
+ module: "AnthropicLanguageModel",
761
+ method: "prepareTools",
762
+ reason: new AiError.InvalidUserInputError({
763
+ description: `Received request to call unknown provider-defined tool '${tool.name}'`
764
+ })
765
+ });
766
+ }
767
+ }
768
+ }
769
+ }
770
+ let tools = [...userTools, ...providerTools];
771
+ let toolChoice = undefined;
772
+ if (options.toolChoice === "auto") {
773
+ toolChoice = {
774
+ type: "auto"
775
+ };
776
+ } else if (options.toolChoice === "required") {
777
+ toolChoice = {
778
+ type: "any"
779
+ };
780
+ } else if ("tool" in options.toolChoice) {
781
+ toolChoice = {
782
+ type: "tool",
783
+ name: options.toolChoice.tool
784
+ };
785
+ } else {
786
+ const allowedTools = new Set(options.toolChoice.oneOf);
787
+ tools = tools.filter(tool => allowedTools.has(tool.name));
788
+ toolChoice = {
789
+ type: options.toolChoice.mode === "required" ? "any" : "auto"
790
+ };
791
+ }
792
+ if (Predicate.isNotUndefined(config.disableParallelToolCalls) && Predicate.isNotUndefined(toolChoice) && toolChoice.type !== "none") {
793
+ toolChoice.disable_parallel_tool_use = config.disableParallelToolCalls;
794
+ }
795
+ return {
796
+ tools,
797
+ toolChoice
798
+ };
799
+ });
800
+ // =============================================================================
801
+ // HTTP Details
802
+ // =============================================================================
803
+ const buildHttpRequestDetails = request => ({
804
+ method: request.method,
805
+ url: request.url,
806
+ urlParams: Array.from(request.urlParams),
807
+ hash: request.hash,
808
+ headers: Redactable.redact(request.headers)
809
+ });
810
+ const buildHttpResponseDetails = response => ({
811
+ status: response.status,
812
+ headers: Redactable.redact(response.headers)
813
+ });
814
+ // =============================================================================
815
+ // Response Conversion
816
+ // =============================================================================
817
+ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
818
+ options,
819
+ rawResponse,
820
+ response,
821
+ toolNameMapper
822
+ }) {
823
+ const parts = [];
824
+ const mcpToolCalls = new Map();
825
+ const serverToolCalls = new Map();
826
+ const citableDocuments = extractCitableDocuments(options.prompt);
827
+ parts.push({
828
+ type: "response-metadata",
829
+ id: rawResponse.id,
830
+ modelId: rawResponse.model,
831
+ timestamp: DateTime.formatIso(yield* DateTime.now),
832
+ request: buildHttpRequestDetails(response.request)
833
+ });
834
+ for (const part of rawResponse.content) {
835
+ switch (part.type) {
836
+ case "text":
837
+ {
838
+ // Text parts are added for both text and json response formats.
839
+ // For native structured output (json_schema), the JSON comes directly
840
+ // in a text content block. For tool-based structured output, text may
841
+ // also be present alongside the tool_use.
842
+ parts.push({
843
+ type: "text",
844
+ text: part.text
845
+ });
846
+ if (Predicate.isNotNullish(part.citations)) {
847
+ for (const citation of part.citations) {
848
+ const source = yield* processCitation(citation, citableDocuments);
849
+ if (Predicate.isNotUndefined(source)) {
850
+ parts.push(source);
851
+ }
852
+ }
853
+ }
854
+ break;
855
+ }
856
+ case "thinking":
857
+ {
858
+ const metadata = {
859
+ info: {
860
+ type: "thinking",
861
+ signature: part.signature
862
+ }
863
+ };
864
+ parts.push({
865
+ type: "reasoning",
866
+ text: part.thinking,
867
+ metadata: {
868
+ anthropic: metadata
869
+ }
870
+ });
871
+ break;
872
+ }
873
+ case "redacted_thinking":
874
+ {
875
+ const metadata = {
876
+ info: {
877
+ type: "redacted_thinking",
878
+ redactedData: part.data
879
+ }
880
+ };
881
+ parts.push({
882
+ type: "reasoning",
883
+ text: "",
884
+ metadata: {
885
+ anthropic: metadata
886
+ }
887
+ });
888
+ break;
889
+ }
890
+ case "tool_use":
891
+ {
892
+ // When the `"json"` response format is requested, the JSON we need
893
+ // is returned by a tool call injected into the request
894
+ if (options.responseFormat.type === "json") {
895
+ parts.push({
896
+ type: "text",
897
+ text: JSON.stringify(part.input)
898
+ });
899
+ } else {
900
+ // Extract caller info if present
901
+ const caller = part.caller;
902
+ const callerInfo = Predicate.isNotNullish(caller) ? {
903
+ type: caller.type,
904
+ toolId: "tool_id" in caller ? caller.tool_id : undefined
905
+ } : undefined;
906
+ const params = yield* transformToolCallParams(options.tools, part.name, part.input);
907
+ parts.push({
908
+ type: "tool-call",
909
+ id: part.id,
910
+ name: part.name,
911
+ params,
912
+ ...(Predicate.isNotUndefined(callerInfo) ? {
913
+ metadata: {
914
+ anthropic: {
915
+ caller: callerInfo
916
+ }
917
+ }
918
+ } : undefined)
919
+ });
920
+ }
921
+ break;
922
+ }
923
+ case "server_tool_use":
924
+ {
925
+ const toolName = toolNameMapper.getCustomName(part.name);
926
+ if (part.name === "bash_code_execution" || part.name === "text_editor_code_execution") {
927
+ parts.push({
928
+ type: "tool-call",
929
+ id: part.id,
930
+ name: toolName,
931
+ params: {
932
+ type: part.name,
933
+ ...part.input
934
+ },
935
+ providerExecuted: true
936
+ });
937
+ } else if (part.name === "code_execution" || part.name === "web_fetch" || part.name === "web_search") {
938
+ const toolParams = {
939
+ ...part.input
940
+ };
941
+ // Inject `type: "programmatic-tool-call"` when the input parameters
942
+ // has the format `{ code: ... }`
943
+ if (part.name === "code_execution" && Predicate.hasProperty(part.input, "code") && !Predicate.hasProperty(part.input, "type")) {
944
+ toolParams.type = "programmatic-tool-call";
945
+ }
946
+ parts.push({
947
+ type: "tool-call",
948
+ id: part.id,
949
+ name: toolName,
950
+ params: toolParams,
951
+ providerExecuted: true
952
+ });
953
+ } else if (part.name === "tool_search_tool_bm25" || part.name === "tool_search_tool_regex") {
954
+ serverToolCalls.set(part.id, part.name);
955
+ parts.push({
956
+ type: "tool-call",
957
+ id: part.id,
958
+ name: toolName,
959
+ params: part.input,
960
+ providerExecuted: true
961
+ });
962
+ }
963
+ break;
964
+ }
965
+ case "mcp_tool_use":
966
+ {
967
+ const toolCall = {
968
+ type: "tool-call",
969
+ id: part.id,
970
+ name: part.name,
971
+ params: part.input,
972
+ providerExecuted: true,
973
+ metadata: {
974
+ anthropic: {
975
+ mcp_tool: {
976
+ server: part.server_name
977
+ }
978
+ }
979
+ }
980
+ };
981
+ mcpToolCalls.set(part.id, toolCall);
982
+ parts.push(toolCall);
983
+ break;
984
+ }
985
+ case "mcp_tool_result":
986
+ {
987
+ const toolCall = mcpToolCalls.get(part.tool_use_id);
988
+ const mcpMetadata = toolCall?.metadata?.anthropic?.mcp_tool;
989
+ if (Predicate.isNotUndefined(toolCall)) {
990
+ parts.push({
991
+ type: "tool-result",
992
+ id: part.tool_use_id,
993
+ name: toolCall.name,
994
+ isFailure: part.is_error,
995
+ result: part.content,
996
+ metadata: {
997
+ anthropic: {
998
+ ...(Predicate.isNotNullish(mcpMetadata) ? {
999
+ mcp_tool: mcpMetadata
1000
+ } : undefined)
1001
+ }
1002
+ }
1003
+ });
1004
+ }
1005
+ break;
1006
+ }
1007
+ // Code Execution 20250522
1008
+ case "code_execution_tool_result":
1009
+ {
1010
+ const toolName = toolNameMapper.getCustomName("code_execution");
1011
+ if (part.content.type === "code_execution_result") {
1012
+ parts.push({
1013
+ type: "tool-result",
1014
+ id: part.tool_use_id,
1015
+ name: toolName,
1016
+ isFailure: false,
1017
+ result: part.content
1018
+ });
1019
+ } else {
1020
+ parts.push({
1021
+ type: "tool-result",
1022
+ id: part.tool_use_id,
1023
+ name: toolName,
1024
+ isFailure: true,
1025
+ result: part.content
1026
+ });
1027
+ }
1028
+ break;
1029
+ }
1030
+ // Code Execution 20250825
1031
+ case "bash_code_execution_tool_result":
1032
+ case "text_editor_code_execution_tool_result":
1033
+ {
1034
+ const toolName = toolNameMapper.getCustomName("code_execution");
1035
+ if (part.content.type === "bash_code_execution_tool_result_error" || part.content.type === "text_editor_code_execution_tool_result_error") {
1036
+ parts.push({
1037
+ type: "tool-result",
1038
+ id: part.tool_use_id,
1039
+ name: toolName,
1040
+ isFailure: true,
1041
+ result: part.content
1042
+ });
1043
+ } else {
1044
+ parts.push({
1045
+ type: "tool-result",
1046
+ id: part.tool_use_id,
1047
+ name: toolName,
1048
+ isFailure: false,
1049
+ result: part.content
1050
+ });
1051
+ }
1052
+ break;
1053
+ }
1054
+ case "tool_search_tool_result":
1055
+ {
1056
+ let providerName = serverToolCalls.get(part.tool_use_id);
1057
+ if (Predicate.isUndefined(providerName)) {
1058
+ const bm25Name = toolNameMapper.getCustomName("tool_search_tool_bm25");
1059
+ const regexName = toolNameMapper.getCustomName("tool_search_tool_regex");
1060
+ if (bm25Name !== "tool_search_tool_bm25") {
1061
+ providerName = "tool_search_tool_bm25";
1062
+ } else if (regexName !== "tool_search_tool_regex") {
1063
+ providerName = "tool_search_tool_regex";
1064
+ }
1065
+ }
1066
+ const toolName = toolNameMapper.getCustomName(providerName);
1067
+ if (part.content.type === "tool_search_tool_search_result") {
1068
+ parts.push({
1069
+ type: "tool-result",
1070
+ id: part.tool_use_id,
1071
+ name: toolName,
1072
+ isFailure: false,
1073
+ result: part.content.tool_references
1074
+ });
1075
+ } else {
1076
+ parts.push({
1077
+ type: "tool-result",
1078
+ id: part.tool_use_id,
1079
+ name: toolName,
1080
+ isFailure: true,
1081
+ result: part.content
1082
+ });
1083
+ }
1084
+ break;
1085
+ }
1086
+ case "web_fetch_tool_result":
1087
+ {
1088
+ const toolName = toolNameMapper.getCustomName("web_fetch");
1089
+ if (part.content.type === "web_fetch_result") {
1090
+ citableDocuments.push({
1091
+ title: part.content.content.title ?? part.content.url,
1092
+ mediaType: part.content.content.source.media_type
1093
+ });
1094
+ parts.push({
1095
+ type: "tool-result",
1096
+ id: part.tool_use_id,
1097
+ name: toolName,
1098
+ isFailure: false,
1099
+ result: part.content
1100
+ });
1101
+ } else {
1102
+ parts.push({
1103
+ type: "tool-result",
1104
+ id: part.tool_use_id,
1105
+ name: toolName,
1106
+ isFailure: true,
1107
+ result: part.content
1108
+ });
1109
+ }
1110
+ break;
1111
+ }
1112
+ case "web_search_tool_result":
1113
+ {
1114
+ const toolName = toolNameMapper.getCustomName("web_search");
1115
+ if (Predicate.hasProperty(part.content, "type")) {
1116
+ parts.push({
1117
+ type: "tool-result",
1118
+ id: part.tool_use_id,
1119
+ name: toolName,
1120
+ isFailure: true,
1121
+ result: part.content
1122
+ });
1123
+ } else {
1124
+ const idGenerator = yield* IdGenerator.IdGenerator;
1125
+ parts.push({
1126
+ type: "tool-result",
1127
+ id: part.tool_use_id,
1128
+ name: toolName,
1129
+ isFailure: false,
1130
+ result: part.content
1131
+ });
1132
+ const content = part.content;
1133
+ for (const result of content) {
1134
+ const id = yield* idGenerator.generateId();
1135
+ parts.push({
1136
+ type: "source",
1137
+ sourceType: "url",
1138
+ id,
1139
+ url: result.url,
1140
+ title: result.title,
1141
+ metadata: {
1142
+ anthropic: {
1143
+ source: "web",
1144
+ pageAge: result.page_age
1145
+ }
1146
+ }
1147
+ });
1148
+ }
1149
+ }
1150
+ break;
1151
+ }
1152
+ }
1153
+ }
1154
+ // Anthropic always returns a non-null `stop_reason` for non-streaming responses
1155
+ const finishReason = InternalUtilities.resolveFinishReason(rawResponse.stop_reason, options.responseFormat.type === "json");
1156
+ const inputTokens = rawResponse.usage.input_tokens;
1157
+ const outputTokens = rawResponse.usage.output_tokens;
1158
+ const cacheWriteTokens = rawResponse.usage.cache_creation_input_tokens ?? 0;
1159
+ const cacheReadTokens = rawResponse.usage.cache_read_input_tokens ?? 0;
1160
+ parts.push({
1161
+ type: "finish",
1162
+ reason: finishReason,
1163
+ usage: {
1164
+ inputTokens: {
1165
+ uncached: inputTokens,
1166
+ total: inputTokens + cacheWriteTokens + cacheReadTokens,
1167
+ cacheRead: cacheReadTokens,
1168
+ cacheWrite: cacheWriteTokens
1169
+ },
1170
+ outputTokens: {
1171
+ total: outputTokens,
1172
+ text: undefined,
1173
+ reasoning: undefined
1174
+ }
1175
+ },
1176
+ response: buildHttpResponseDetails(response),
1177
+ metadata: {
1178
+ anthropic: {
1179
+ container: rawResponse.container ?? null,
1180
+ contextManagement: rawResponse.context_management ?? null,
1181
+ usage: rawResponse.usage,
1182
+ stopSequence: rawResponse.stop_sequence
1183
+ }
1184
+ }
1185
+ });
1186
+ return parts;
1187
+ });
1188
+ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1189
+ stream,
1190
+ response,
1191
+ options,
1192
+ toolNameMapper
1193
+ }) {
1194
+ const citableDocuments = extractCitableDocuments(options.prompt);
1195
+ let container = null;
1196
+ let contextManagement = null;
1197
+ let finishReason = "unknown";
1198
+ let stopSequence = null;
1199
+ let rawUsage = null;
1200
+ const mcpToolCalls = new Map();
1201
+ const serverToolCalls = new Map();
1202
+ const contentBlocks = new Map();
1203
+ const usage = {
1204
+ inputTokens: 0,
1205
+ outputTokens: 0,
1206
+ cacheReadInputTokens: 0,
1207
+ cacheWriteInputTokens: 0
1208
+ };
1209
+ let blockType = undefined;
1210
+ return stream.pipe(Stream.mapEffect(Effect.fnUntraced(function* (event) {
1211
+ const parts = [];
1212
+ switch (event.type) {
1213
+ case "message_start":
1214
+ {
1215
+ rawUsage = {
1216
+ ...event.message.usage
1217
+ };
1218
+ usage.inputTokens = event.message.usage.input_tokens;
1219
+ usage.cacheReadInputTokens = event.message.usage.cache_read_input_tokens ?? 0;
1220
+ usage.cacheWriteInputTokens = event.message.usage.cache_creation_input_tokens ?? 0;
1221
+ if (Predicate.isNotNullish(event.message.container)) {
1222
+ container = event.message.container;
1223
+ }
1224
+ if (Predicate.isNotNull(event.message.stop_sequence)) {
1225
+ stopSequence = event.message.stop_sequence;
1226
+ }
1227
+ if (Predicate.isNotNull(event.message.stop_reason)) {
1228
+ finishReason = InternalUtilities.resolveFinishReason(event.message.stop_reason);
1229
+ }
1230
+ parts.push({
1231
+ type: "response-metadata",
1232
+ id: event.message.id,
1233
+ modelId: event.message.model,
1234
+ timestamp: DateTime.formatIso(yield* DateTime.now),
1235
+ request: buildHttpRequestDetails(response.request)
1236
+ });
1237
+ // Process pre-populated content blocks
1238
+ if (Predicate.isNotNullish(event.message.content) && event.message.content.length > 0) {
1239
+ for (let i = 0; i < event.message.content.length; i++) {
1240
+ const part = event.message.content[i];
1241
+ if (part.type === "tool_use") {
1242
+ const callerInfo = Predicate.isNotUndefined(part.caller) ? {
1243
+ type: part.caller.type,
1244
+ toolId: "tool_id" in part.caller ? part.caller.tool_id : null
1245
+ } : undefined;
1246
+ parts.push({
1247
+ type: "tool-params-start",
1248
+ id: part.id,
1249
+ name: part.name
1250
+ });
1251
+ parts.push({
1252
+ type: "tool-params-delta",
1253
+ id: part.id,
1254
+ delta: JSON.stringify(part.input ?? {})
1255
+ });
1256
+ parts.push({
1257
+ type: "tool-params-end",
1258
+ id: part.id
1259
+ });
1260
+ const params = yield* transformToolCallParams(options.tools, part.name, part.input);
1261
+ parts.push({
1262
+ type: "tool-call",
1263
+ id: part.id,
1264
+ name: part.name,
1265
+ params,
1266
+ ...(Predicate.isNotUndefined(callerInfo) ? {
1267
+ metadata: {
1268
+ anthropic: {
1269
+ caller: callerInfo
1270
+ }
1271
+ }
1272
+ } : undefined)
1273
+ });
1274
+ }
1275
+ }
1276
+ }
1277
+ break;
1278
+ }
1279
+ case "message_delta":
1280
+ {
1281
+ rawUsage = {
1282
+ ...rawUsage,
1283
+ ...event.usage
1284
+ };
1285
+ if (Predicate.isNotNull(event.usage.input_tokens) && usage.inputTokens !== event.usage.input_tokens) {
1286
+ usage.inputTokens = event.usage.input_tokens;
1287
+ }
1288
+ usage.outputTokens = event.usage.output_tokens;
1289
+ if (Predicate.isNotNull(event.usage.cache_read_input_tokens) && usage.cacheReadInputTokens !== event.usage.cache_read_input_tokens) {
1290
+ usage.cacheReadInputTokens = event.usage.cache_read_input_tokens;
1291
+ }
1292
+ if (Predicate.isNotNull(event.usage.cache_creation_input_tokens) && usage.cacheWriteInputTokens !== event.usage.cache_creation_input_tokens) {
1293
+ usage.cacheWriteInputTokens = event.usage.cache_creation_input_tokens;
1294
+ }
1295
+ if (Predicate.isNotNullish(event.delta.container)) {
1296
+ container = event.delta.container;
1297
+ }
1298
+ if (Predicate.isNotNullish(event.context_management)) {
1299
+ contextManagement = event.context_management;
1300
+ }
1301
+ if (Predicate.isNotNull(event.delta.stop_reason)) {
1302
+ finishReason = InternalUtilities.resolveFinishReason(event.delta.stop_reason);
1303
+ }
1304
+ if (Predicate.isNotNull(event.delta.stop_sequence)) {
1305
+ stopSequence = event.delta.stop_sequence;
1306
+ }
1307
+ break;
1308
+ }
1309
+ case "message_stop":
1310
+ {
1311
+ const metadata = {
1312
+ anthropic: {
1313
+ container,
1314
+ contextManagement,
1315
+ stopSequence,
1316
+ usage: rawUsage
1317
+ }
1318
+ };
1319
+ parts.push({
1320
+ type: "finish",
1321
+ reason: finishReason,
1322
+ usage: {
1323
+ inputTokens: {
1324
+ uncached: usage.inputTokens,
1325
+ total: usage.inputTokens + usage.cacheWriteInputTokens + usage.cacheReadInputTokens,
1326
+ cacheRead: usage.cacheReadInputTokens,
1327
+ cacheWrite: usage.cacheWriteInputTokens
1328
+ },
1329
+ outputTokens: {
1330
+ total: usage.outputTokens,
1331
+ text: undefined,
1332
+ reasoning: undefined
1333
+ }
1334
+ },
1335
+ response: buildHttpResponseDetails(response),
1336
+ metadata
1337
+ });
1338
+ break;
1339
+ }
1340
+ case "content_block_start":
1341
+ {
1342
+ blockType = event.content_block.type;
1343
+ switch (event.content_block.type) {
1344
+ case "text":
1345
+ {
1346
+ contentBlocks.set(event.index, {
1347
+ type: "text"
1348
+ });
1349
+ parts.push({
1350
+ type: "text-start",
1351
+ id: event.index.toString()
1352
+ });
1353
+ break;
1354
+ }
1355
+ case "thinking":
1356
+ {
1357
+ contentBlocks.set(event.index, {
1358
+ type: "reasoning"
1359
+ });
1360
+ parts.push({
1361
+ type: "reasoning-start",
1362
+ id: event.index.toString()
1363
+ });
1364
+ break;
1365
+ }
1366
+ case "redacted_thinking":
1367
+ {
1368
+ contentBlocks.set(event.index, {
1369
+ type: "reasoning"
1370
+ });
1371
+ const metadata = {
1372
+ anthropic: {
1373
+ info: {
1374
+ type: "redacted_thinking",
1375
+ redactedData: event.content_block.data
1376
+ }
1377
+ }
1378
+ };
1379
+ parts.push({
1380
+ type: "reasoning-start",
1381
+ id: event.index.toString(),
1382
+ metadata
1383
+ });
1384
+ break;
1385
+ }
1386
+ case "tool_use":
1387
+ {
1388
+ const part = event.content_block;
1389
+ const caller = Predicate.isNotUndefined(part.caller) ? {
1390
+ type: part.caller.type,
1391
+ toolId: "tool_id" in part.caller ? part.caller.tool_id : null
1392
+ } : undefined;
1393
+ const hasParams = Object.keys(part.input).length > 0;
1394
+ const initialParams = hasParams ? JSON.stringify(part.input) : "";
1395
+ contentBlocks.set(event.index, {
1396
+ type: "tool-call",
1397
+ id: part.id,
1398
+ name: part.name,
1399
+ params: initialParams,
1400
+ firstDelta: initialParams.length > 0,
1401
+ ...(Predicate.isNotUndefined(caller) ? {
1402
+ caller
1403
+ } : undefined)
1404
+ });
1405
+ parts.push({
1406
+ type: "tool-params-start",
1407
+ id: part.id,
1408
+ name: part.name
1409
+ });
1410
+ break;
1411
+ }
1412
+ case "server_tool_use":
1413
+ {
1414
+ const part = event.content_block;
1415
+ if (part.name === "code_execution" || part.name === "bash_code_execution" || part.name === "text_editor_code_execution" || part.name === "web_fetch" || part.name === "web_search") {
1416
+ const toolName = toolNameMapper.getCustomName(part.name === "bash_code_execution" || part.name === "text_editor_code_execution" ? "code_execution" : part.name);
1417
+ contentBlocks.set(event.index, {
1418
+ type: "tool-call",
1419
+ id: part.id,
1420
+ name: toolName,
1421
+ params: "",
1422
+ firstDelta: true,
1423
+ providerName: part.name,
1424
+ providerExecuted: true
1425
+ });
1426
+ parts.push({
1427
+ type: "tool-params-start",
1428
+ id: part.id,
1429
+ name: toolName,
1430
+ providerExecuted: true
1431
+ });
1432
+ } else if (part.name === "tool_search_tool_bm25" || part.name === "tool_search_tool_regex") {
1433
+ serverToolCalls.set(part.id, part.name);
1434
+ const toolName = toolNameMapper.getCustomName(part.name);
1435
+ contentBlocks.set(event.index, {
1436
+ type: "tool-call",
1437
+ id: part.id,
1438
+ name: toolName,
1439
+ params: "",
1440
+ firstDelta: true,
1441
+ providerName: part.name,
1442
+ providerExecuted: true
1443
+ });
1444
+ parts.push({
1445
+ type: "tool-params-start",
1446
+ id: part.id,
1447
+ name: toolName,
1448
+ providerExecuted: true
1449
+ });
1450
+ }
1451
+ break;
1452
+ }
1453
+ case "web_fetch_tool_result":
1454
+ {
1455
+ const part = event.content_block;
1456
+ const toolName = toolNameMapper.getCustomName("web_fetch");
1457
+ if (part.content.type === "web_fetch_result") {
1458
+ citableDocuments.push({
1459
+ title: part.content.content.title ?? part.content.url,
1460
+ mediaType: part.content.content.source.media_type
1461
+ });
1462
+ parts.push({
1463
+ type: "tool-result",
1464
+ id: part.tool_use_id,
1465
+ name: toolName,
1466
+ isFailure: false,
1467
+ result: part.content
1468
+ });
1469
+ } else {
1470
+ parts.push({
1471
+ type: "tool-result",
1472
+ id: part.tool_use_id,
1473
+ name: toolName,
1474
+ isFailure: true,
1475
+ result: part.content
1476
+ });
1477
+ }
1478
+ break;
1479
+ }
1480
+ case "web_search_tool_result":
1481
+ {
1482
+ const part = event.content_block;
1483
+ const toolName = toolNameMapper.getCustomName("web_search");
1484
+ if (Predicate.hasProperty(part.content, "type")) {
1485
+ parts.push({
1486
+ type: "tool-result",
1487
+ id: part.tool_use_id,
1488
+ name: toolName,
1489
+ isFailure: true,
1490
+ result: part.content
1491
+ });
1492
+ } else {
1493
+ const idGenerator = yield* IdGenerator.IdGenerator;
1494
+ parts.push({
1495
+ type: "tool-result",
1496
+ id: part.tool_use_id,
1497
+ name: toolName,
1498
+ isFailure: false,
1499
+ result: part.content
1500
+ });
1501
+ const content = part.content;
1502
+ for (const result of content) {
1503
+ const id = yield* idGenerator.generateId();
1504
+ parts.push({
1505
+ type: "source",
1506
+ sourceType: "url",
1507
+ id,
1508
+ url: result.url,
1509
+ title: result.title,
1510
+ metadata: {
1511
+ anthropic: {
1512
+ source: "web",
1513
+ pageAge: result.page_age
1514
+ }
1515
+ }
1516
+ });
1517
+ }
1518
+ }
1519
+ break;
1520
+ }
1521
+ case "code_execution_tool_result":
1522
+ {
1523
+ const part = event.content_block;
1524
+ const toolName = toolNameMapper.getCustomName("code_execution");
1525
+ if (part.content.type === "code_execution_result") {
1526
+ parts.push({
1527
+ type: "tool-result",
1528
+ id: part.tool_use_id,
1529
+ name: toolName,
1530
+ isFailure: false,
1531
+ result: part.content
1532
+ });
1533
+ } else {
1534
+ parts.push({
1535
+ type: "tool-result",
1536
+ id: part.tool_use_id,
1537
+ name: toolName,
1538
+ isFailure: true,
1539
+ result: part.content
1540
+ });
1541
+ }
1542
+ break;
1543
+ }
1544
+ case "bash_code_execution_tool_result":
1545
+ case "text_editor_code_execution_tool_result":
1546
+ {
1547
+ const part = event.content_block;
1548
+ const toolName = toolNameMapper.getCustomName("code_execution");
1549
+ if (part.content.type === "bash_code_execution_tool_result_error" || part.content.type === "text_editor_code_execution_tool_result_error") {
1550
+ parts.push({
1551
+ type: "tool-result",
1552
+ id: part.tool_use_id,
1553
+ name: toolName,
1554
+ isFailure: true,
1555
+ result: part.content
1556
+ });
1557
+ } else {
1558
+ parts.push({
1559
+ type: "tool-result",
1560
+ id: part.tool_use_id,
1561
+ name: toolName,
1562
+ isFailure: false,
1563
+ result: part.content
1564
+ });
1565
+ }
1566
+ break;
1567
+ }
1568
+ case "tool_search_tool_result":
1569
+ {
1570
+ const part = event.content_block;
1571
+ let providerName = serverToolCalls.get(part.tool_use_id);
1572
+ if (Predicate.isUndefined(providerName)) {
1573
+ const bm25Name = toolNameMapper.getCustomName("tool_search_tool_bm25");
1574
+ const regexName = toolNameMapper.getCustomName("tool_search_tool_regex");
1575
+ if (bm25Name !== "tool_search_tool_bm25") {
1576
+ providerName = "tool_search_tool_bm25";
1577
+ } else if (regexName !== "tool_search_tool_regex") {
1578
+ providerName = "tool_search_tool_regex";
1579
+ }
1580
+ }
1581
+ const toolName = toolNameMapper.getCustomName(providerName);
1582
+ if (part.content.type === "tool_search_tool_search_result") {
1583
+ parts.push({
1584
+ type: "tool-result",
1585
+ id: part.tool_use_id,
1586
+ name: toolName,
1587
+ isFailure: false,
1588
+ result: part.content.tool_references
1589
+ });
1590
+ } else {
1591
+ parts.push({
1592
+ type: "tool-result",
1593
+ id: part.tool_use_id,
1594
+ name: toolName,
1595
+ isFailure: true,
1596
+ result: part.content
1597
+ });
1598
+ }
1599
+ break;
1600
+ }
1601
+ case "mcp_tool_use":
1602
+ {
1603
+ const part = event.content_block;
1604
+ const toolCall = {
1605
+ type: "tool-call",
1606
+ id: part.id,
1607
+ name: part.name,
1608
+ params: part.input,
1609
+ providerExecuted: true,
1610
+ metadata: {
1611
+ anthropic: {
1612
+ mcp_tool: {
1613
+ server: part.server_name
1614
+ }
1615
+ }
1616
+ }
1617
+ };
1618
+ mcpToolCalls.set(part.id, toolCall);
1619
+ parts.push(toolCall);
1620
+ break;
1621
+ }
1622
+ case "mcp_tool_result":
1623
+ {
1624
+ const part = event.content_block;
1625
+ const toolCall = mcpToolCalls.get(part.tool_use_id);
1626
+ const mcpMetadata = toolCall?.metadata?.anthropic?.mcp_tool;
1627
+ if (Predicate.isNotUndefined(toolCall)) {
1628
+ parts.push({
1629
+ type: "tool-result",
1630
+ id: part.tool_use_id,
1631
+ name: toolCall.name,
1632
+ isFailure: part.is_error,
1633
+ result: part.content,
1634
+ metadata: {
1635
+ anthropic: {
1636
+ ...(Predicate.isNotNullish(mcpMetadata) ? {
1637
+ mcp_tool: mcpMetadata
1638
+ } : undefined)
1639
+ }
1640
+ }
1641
+ });
1642
+ }
1643
+ break;
1644
+ }
1645
+ }
1646
+ break;
1647
+ }
1648
+ case "content_block_delta":
1649
+ {
1650
+ const part = event.delta;
1651
+ switch (part.type) {
1652
+ case "text_delta":
1653
+ {
1654
+ parts.push({
1655
+ type: "text-delta",
1656
+ id: event.index.toString(),
1657
+ delta: part.text
1658
+ });
1659
+ break;
1660
+ }
1661
+ case "thinking_delta":
1662
+ {
1663
+ parts.push({
1664
+ type: "reasoning-delta",
1665
+ id: event.index.toString(),
1666
+ delta: part.thinking
1667
+ });
1668
+ break;
1669
+ }
1670
+ case "signature_delta":
1671
+ {
1672
+ if (blockType === "thinking") {
1673
+ parts.push({
1674
+ type: "reasoning-delta",
1675
+ id: event.index.toString(),
1676
+ delta: "",
1677
+ metadata: {
1678
+ anthropic: {
1679
+ info: {
1680
+ type: "thinking",
1681
+ signature: part.signature
1682
+ }
1683
+ }
1684
+ }
1685
+ });
1686
+ }
1687
+ break;
1688
+ }
1689
+ case "input_json_delta":
1690
+ {
1691
+ let delta = part.partial_json;
1692
+ // Skip empty deltas
1693
+ if (delta.length === 0) {
1694
+ break;
1695
+ }
1696
+ const contentBlock = contentBlocks.get(event.index);
1697
+ // Skip invalid deltas
1698
+ if (Predicate.isUndefined(contentBlock)) {
1699
+ break;
1700
+ }
1701
+ // Skip non-tool-call deltas
1702
+ if (contentBlock.type !== "tool-call") {
1703
+ break;
1704
+ }
1705
+ if (contentBlock.firstDelta && (contentBlock.providerName === "bash_code_execution" || contentBlock.providerName === "text_editor_code_execution")) {
1706
+ delta = `{"type":${contentBlock.providerName},${delta.substring(1)}}`;
1707
+ }
1708
+ parts.push({
1709
+ type: "tool-params-delta",
1710
+ id: contentBlock.id,
1711
+ delta
1712
+ });
1713
+ contentBlock.params += delta;
1714
+ contentBlock.firstDelta = false;
1715
+ break;
1716
+ }
1717
+ case "citations_delta":
1718
+ {
1719
+ const source = yield* processCitation(part.citation, citableDocuments);
1720
+ if (Predicate.isNotUndefined(source)) {
1721
+ parts.push(source);
1722
+ }
1723
+ break;
1724
+ }
1725
+ }
1726
+ break;
1727
+ }
1728
+ case "content_block_stop":
1729
+ {
1730
+ const contentBlock = contentBlocks.get(event.index);
1731
+ if (Predicate.isNotUndefined(contentBlock)) {
1732
+ switch (contentBlock.type) {
1733
+ case "text":
1734
+ {
1735
+ parts.push({
1736
+ type: "text-end",
1737
+ id: event.index.toString()
1738
+ });
1739
+ break;
1740
+ }
1741
+ case "reasoning":
1742
+ {
1743
+ parts.push({
1744
+ type: "reasoning-end",
1745
+ id: event.index.toString()
1746
+ });
1747
+ break;
1748
+ }
1749
+ case "tool-call":
1750
+ {
1751
+ parts.push({
1752
+ type: "tool-params-end",
1753
+ id: contentBlock.id
1754
+ });
1755
+ // For code execution, inject the `programmatic-tool-call` type
1756
+ // when the input format is `{ code }`
1757
+ let finalParams = contentBlock.params.length === 0 ? "{}" : contentBlock.params;
1758
+ if (contentBlock.providerName === "code_execution") {
1759
+ // @effect-diagnostics-next-line tryCatchInEffectGen:off
1760
+ try {
1761
+ const params = Tool.unsafeSecureJsonParse(finalParams);
1762
+ if (Predicate.hasProperty(params, "code") && !Predicate.hasProperty(params, "type")) {
1763
+ finalParams = JSON.stringify({
1764
+ type: "programmatic-tool-call",
1765
+ ...params
1766
+ });
1767
+ }
1768
+ } catch {
1769
+ // Ignore errors and use original tool call parameters
1770
+ }
1771
+ }
1772
+ const params = contentBlock.providerExecuted === true ? finalParams : transformToolCallParams(options.tools, contentBlock.name, finalParams);
1773
+ parts.push({
1774
+ type: "tool-call",
1775
+ id: contentBlock.id,
1776
+ name: contentBlock.name,
1777
+ params,
1778
+ providerExecuted: contentBlock.providerExecuted,
1779
+ ...(Predicate.isNotUndefined(contentBlock.caller) ? {
1780
+ metadata: {
1781
+ anthropic: {
1782
+ caller: contentBlock.caller
1783
+ }
1784
+ }
1785
+ } : undefined)
1786
+ });
1787
+ }
1788
+ }
1789
+ contentBlocks.delete(event.index);
1790
+ }
1791
+ blockType = undefined;
1792
+ break;
1793
+ }
1794
+ case "error":
1795
+ {
1796
+ parts.push({
1797
+ type: "error",
1798
+ error: event.error,
1799
+ metadata: {
1800
+ anthropic: {
1801
+ requestId: event.request_id
1802
+ }
1803
+ }
1804
+ });
1805
+ break;
1806
+ }
1807
+ }
1808
+ return parts;
1809
+ })), Stream.flattenIterable);
1810
+ });
1811
+ // =============================================================================
1812
+ // Telemetry
1813
+ // =============================================================================
1814
+ const annotateRequest = (span, request) => {
1815
+ addGenAIAnnotations(span, {
1816
+ system: "anthropic",
1817
+ operation: {
1818
+ name: "chat"
1819
+ },
1820
+ request: {
1821
+ model: request.model,
1822
+ temperature: request.temperature,
1823
+ topK: request.top_k,
1824
+ topP: request.top_p,
1825
+ maxTokens: request.max_tokens,
1826
+ stopSequences: Arr.ensure(request.stop_sequences).filter(Predicate.isNotNullish)
1827
+ }
1828
+ });
1829
+ };
1830
+ const annotateResponse = (span, response) => {
1831
+ addGenAIAnnotations(span, {
1832
+ response: {
1833
+ id: response.id,
1834
+ model: response.model,
1835
+ finishReasons: response.stop_reason ? [response.stop_reason] : undefined
1836
+ },
1837
+ usage: {
1838
+ inputTokens: response.usage.input_tokens,
1839
+ outputTokens: response.usage.output_tokens
1840
+ }
1841
+ });
1842
+ };
1843
+ const annotateStreamResponse = (span, part) => {
1844
+ if (part.type === "response-metadata") {
1845
+ addGenAIAnnotations(span, {
1846
+ response: {
1847
+ id: part.id,
1848
+ model: part.modelId
1849
+ }
1850
+ });
1851
+ }
1852
+ if (part.type === "finish") {
1853
+ addGenAIAnnotations(span, {
1854
+ response: {
1855
+ finishReasons: [part.reason]
1856
+ },
1857
+ usage: {
1858
+ inputTokens: part.usage.inputTokens.uncached,
1859
+ outputTokens: part.usage.outputTokens.total
1860
+ }
1861
+ });
1862
+ }
1863
+ };
1864
+ const groupMessages = prompt => {
1865
+ const messages = [];
1866
+ let current = undefined;
1867
+ for (const message of prompt.content) {
1868
+ switch (message.role) {
1869
+ case "system":
1870
+ {
1871
+ if (current?.type !== "system") {
1872
+ current = {
1873
+ type: "system",
1874
+ messages: []
1875
+ };
1876
+ messages.push(current);
1877
+ }
1878
+ current.messages.push(message);
1879
+ break;
1880
+ }
1881
+ case "assistant":
1882
+ {
1883
+ if (current?.type !== "assistant") {
1884
+ current = {
1885
+ type: "assistant",
1886
+ messages: []
1887
+ };
1888
+ messages.push(current);
1889
+ }
1890
+ current.messages.push(message);
1891
+ break;
1892
+ }
1893
+ case "tool":
1894
+ case "user":
1895
+ {
1896
+ if (current?.type !== "user") {
1897
+ current = {
1898
+ type: "user",
1899
+ messages: []
1900
+ };
1901
+ messages.push(current);
1902
+ }
1903
+ current.messages.push(message);
1904
+ break;
1905
+ }
1906
+ }
1907
+ }
1908
+ return messages;
1909
+ };
1910
+ /**
1911
+ * Checks if data is a URL (either a URL object or a URL string).
1912
+ */
1913
+ const isUrlData = data => data instanceof URL || isUrlString(data);
1914
+ const isUrlString = data => typeof data === "string" && /^https?:\/\//i.test(data);
1915
+ const getUrlString = data => data instanceof URL ? data.toString() : data;
1916
+ const getCacheControl = part => part.options.anthropic?.cacheControl ?? null;
1917
+ const getDocumentMetadata = part => {
1918
+ const options = part.options.anthropic;
1919
+ if (Predicate.isNotUndefined(options)) {
1920
+ return {
1921
+ title: options?.documentTitle ?? null,
1922
+ context: options?.documentContext ?? null
1923
+ };
1924
+ }
1925
+ return null;
1926
+ };
1927
+ const areCitationsEnabled = part => part.options.anthropic?.citations?.enabled ?? false;
1928
+ const isCitationPart = part => part.type === "file" && (part.mediaType === "application/pdf" || part.mediaType === "text/plain") ? areCitationsEnabled(part) : false;
1929
+ const extractCitableDocuments = prompt => {
1930
+ const citableDocuments = [];
1931
+ for (const message of prompt.content) {
1932
+ if (message.role === "user") {
1933
+ for (const part of message.content) {
1934
+ if (isCitationPart(part)) {
1935
+ citableDocuments.push({
1936
+ title: part.fileName ?? "Untitled Document",
1937
+ fileName: part.fileName,
1938
+ mediaType: part.mediaType
1939
+ });
1940
+ }
1941
+ }
1942
+ }
1943
+ }
1944
+ return citableDocuments;
1945
+ };
1946
+ const processCitation = /*#__PURE__*/Effect.fnUntraced(function* (citation, citableDocuments) {
1947
+ const idGenerator = yield* IdGenerator.IdGenerator;
1948
+ if (citation.type === "page_location" || citation.type === "char_location") {
1949
+ const citedDocument = citableDocuments[citation.document_index];
1950
+ if (Predicate.isNotUndefined(citedDocument)) {
1951
+ const id = yield* idGenerator.generateId();
1952
+ const metadata = citation.type === "char_location" ? {
1953
+ source: "document",
1954
+ type: citation.type,
1955
+ citedText: citation.cited_text,
1956
+ startCharIndex: citation.start_char_index,
1957
+ endCharIndex: citation.end_char_index
1958
+ } : {
1959
+ source: "document",
1960
+ type: citation.type,
1961
+ citedText: citation.cited_text,
1962
+ startPageNumber: citation.start_page_number,
1963
+ endPageNumber: citation.end_page_number
1964
+ };
1965
+ return {
1966
+ type: "source",
1967
+ sourceType: "document",
1968
+ id,
1969
+ mediaType: citedDocument.mediaType,
1970
+ title: citation.document_title ?? citedDocument.title,
1971
+ ...(Predicate.isNotUndefined(citedDocument.fileName) ? {
1972
+ fileName: citedDocument.fileName
1973
+ } : undefined),
1974
+ metadata: {
1975
+ anthropic: metadata
1976
+ }
1977
+ };
1978
+ }
1979
+ }
1980
+ if (citation.type === "web_search_result_location") {
1981
+ const id = yield* idGenerator.generateId();
1982
+ const metadata = {
1983
+ source: "url",
1984
+ citedText: citation.cited_text,
1985
+ encryptedIndex: citation.encrypted_index
1986
+ };
1987
+ return {
1988
+ type: "source",
1989
+ sourceType: "url",
1990
+ id,
1991
+ url: citation.url,
1992
+ title: citation.title ?? "Untitled",
1993
+ metadata: {
1994
+ anthropic: metadata
1995
+ }
1996
+ };
1997
+ }
1998
+ return undefined;
1999
+ });
2000
+ /**
2001
+ * Returns the capabilities of a Claude model that are used for defaults and feature selection.
2002
+ *
2003
+ * @see https://docs.claude.com/en/docs/about-claude/models/overview#model-comparison-table
2004
+ * @see https://platform.claude.com/docs/en/build-with-claude/structured-outputs
2005
+ */
2006
+ const getModelCapabilities = modelId => {
2007
+ if (modelId.includes("claude-sonnet-4-5") || modelId.includes("claude-opus-4-5") || modelId.includes("claude-haiku-4-5")) {
2008
+ return {
2009
+ maxOutputTokens: 64000,
2010
+ supportsStructuredOutput: true,
2011
+ isKnownModel: true
2012
+ };
2013
+ } else if (modelId.includes("claude-opus-4-1")) {
2014
+ return {
2015
+ maxOutputTokens: 32000,
2016
+ supportsStructuredOutput: true,
2017
+ isKnownModel: true
2018
+ };
2019
+ } else if (modelId.includes("claude-sonnet-4-") || modelId.includes("claude-3-7-sonnet")) {
2020
+ return {
2021
+ maxOutputTokens: 64000,
2022
+ supportsStructuredOutput: false,
2023
+ isKnownModel: true
2024
+ };
2025
+ } else if (modelId.includes("claude-opus-4-")) {
2026
+ return {
2027
+ maxOutputTokens: 32000,
2028
+ supportsStructuredOutput: false,
2029
+ isKnownModel: true
2030
+ };
2031
+ } else if (modelId.includes("claude-3-5-haiku")) {
2032
+ return {
2033
+ maxOutputTokens: 8192,
2034
+ supportsStructuredOutput: false,
2035
+ isKnownModel: true
2036
+ };
2037
+ } else if (modelId.includes("claude-3-haiku")) {
2038
+ return {
2039
+ maxOutputTokens: 4096,
2040
+ supportsStructuredOutput: false,
2041
+ isKnownModel: true
2042
+ };
2043
+ } else {
2044
+ return {
2045
+ maxOutputTokens: 4096,
2046
+ supportsStructuredOutput: false,
2047
+ isKnownModel: false
2048
+ };
2049
+ }
2050
+ };
2051
+ const unsupportedSchemaError = (error, method) => AiError.make({
2052
+ module: "AnthropicLanguageModel",
2053
+ method,
2054
+ reason: new AiError.UnsupportedSchemaError({
2055
+ description: error instanceof Error ? error.message : String(error)
2056
+ })
2057
+ });
2058
+ const tryCodecTransform = (schema, method) => Effect.try({
2059
+ try: () => toCodecAnthropic(schema),
2060
+ catch: error => unsupportedSchemaError(error, method)
2061
+ });
2062
+ const tryJsonSchema = (schema, method) => Effect.try({
2063
+ try: () => Tool.getJsonSchemaFromSchema(schema, {
2064
+ transformer: toCodecAnthropic
2065
+ }),
2066
+ catch: error => unsupportedSchemaError(error, method)
2067
+ });
2068
+ const getOutputFormat = /*#__PURE__*/Effect.fnUntraced(function* ({
2069
+ capabilities,
2070
+ options
2071
+ }) {
2072
+ if (options.responseFormat.type === "json" && capabilities.supportsStructuredOutput) {
2073
+ const jsonSchema = yield* tryJsonSchema(options.responseFormat.schema, "getOutputFormat");
2074
+ return {
2075
+ type: "json_schema",
2076
+ schema: jsonSchema
2077
+ };
2078
+ }
2079
+ return undefined;
2080
+ });
2081
+ const transformToolCallParams = /*#__PURE__*/Effect.fnUntraced(function* (tools, toolName, toolParams) {
2082
+ const tool = tools.find(tool => tool.name === toolName);
2083
+ if (Predicate.isUndefined(tool)) {
2084
+ return yield* AiError.make({
2085
+ module: "AnthropicLanguageModel",
2086
+ method: "makeResponse",
2087
+ reason: new AiError.ToolNotFoundError({
2088
+ toolName,
2089
+ availableTools: tools.map(tool => tool.name)
2090
+ })
2091
+ });
2092
+ }
2093
+ const {
2094
+ codec
2095
+ } = yield* tryCodecTransform(tool.parametersSchema, "makeResponse");
2096
+ const transform = Schema.decodeEffect(codec);
2097
+ return yield* transform(toolParams).pipe(Effect.mapError(error => AiError.make({
2098
+ module: "AnthropicLanguageModel",
2099
+ method: "makeResponse",
2100
+ reason: new AiError.ToolParameterValidationError({
2101
+ toolName,
2102
+ toolParams,
2103
+ description: error.issue.toString()
2104
+ })
2105
+ })));
2106
+ });
2107
+ //# sourceMappingURL=AnthropicLanguageModel.js.map