@tanstack/ai-anthropic 0.15.8 → 0.15.9

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 (54) hide show
  1. package/package.json +3 -3
  2. package/dist/esm/adapters/summarize.d.ts +0 -41
  3. package/dist/esm/adapters/summarize.js +0 -18
  4. package/dist/esm/adapters/summarize.js.map +0 -1
  5. package/dist/esm/adapters/text.d.ts +0 -92
  6. package/dist/esm/adapters/text.js +0 -851
  7. package/dist/esm/adapters/text.js.map +0 -1
  8. package/dist/esm/index.d.ts +0 -9
  9. package/dist/esm/index.js +0 -15
  10. package/dist/esm/index.js.map +0 -1
  11. package/dist/esm/message-types.d.ts +0 -84
  12. package/dist/esm/model-meta.d.ts +0 -410
  13. package/dist/esm/model-meta.js +0 -81
  14. package/dist/esm/model-meta.js.map +0 -1
  15. package/dist/esm/text/text-provider-options.d.ts +0 -258
  16. package/dist/esm/text/text-provider-options.js +0 -30
  17. package/dist/esm/text/text-provider-options.js.map +0 -1
  18. package/dist/esm/tools/bash-tool.d.ts +0 -8
  19. package/dist/esm/tools/bash-tool.js +0 -17
  20. package/dist/esm/tools/bash-tool.js.map +0 -1
  21. package/dist/esm/tools/code-execution-tool.d.ts +0 -34
  22. package/dist/esm/tools/code-execution-tool.js +0 -39
  23. package/dist/esm/tools/code-execution-tool.js.map +0 -1
  24. package/dist/esm/tools/computer-use-tool.d.ts +0 -8
  25. package/dist/esm/tools/computer-use-tool.js +0 -17
  26. package/dist/esm/tools/computer-use-tool.js.map +0 -1
  27. package/dist/esm/tools/custom-tool.d.ts +0 -26
  28. package/dist/esm/tools/custom-tool.js +0 -34
  29. package/dist/esm/tools/custom-tool.js.map +0 -1
  30. package/dist/esm/tools/index.d.ts +0 -17
  31. package/dist/esm/tools/index.js +0 -22
  32. package/dist/esm/tools/index.js.map +0 -1
  33. package/dist/esm/tools/memory-tool.d.ts +0 -8
  34. package/dist/esm/tools/memory-tool.js +0 -20
  35. package/dist/esm/tools/memory-tool.js.map +0 -1
  36. package/dist/esm/tools/text-editor-tool.d.ts +0 -8
  37. package/dist/esm/tools/text-editor-tool.js +0 -19
  38. package/dist/esm/tools/text-editor-tool.js.map +0 -1
  39. package/dist/esm/tools/tool-converter.d.ts +0 -27
  40. package/dist/esm/tools/tool-converter.js +0 -35
  41. package/dist/esm/tools/tool-converter.js.map +0 -1
  42. package/dist/esm/tools/web-fetch-tool.d.ts +0 -8
  43. package/dist/esm/tools/web-fetch-tool.js +0 -21
  44. package/dist/esm/tools/web-fetch-tool.js.map +0 -1
  45. package/dist/esm/tools/web-search-tool.d.ts +0 -8
  46. package/dist/esm/tools/web-search-tool.js +0 -63
  47. package/dist/esm/tools/web-search-tool.js.map +0 -1
  48. package/dist/esm/usage.d.ts +0 -25
  49. package/dist/esm/usage.js +0 -35
  50. package/dist/esm/usage.js.map +0 -1
  51. package/dist/esm/utils/client.d.ts +0 -17
  52. package/dist/esm/utils/client.js +0 -20
  53. package/dist/esm/utils/client.js.map +0 -1
  54. package/dist/esm/utils/index.d.ts +0 -1
@@ -1,851 +0,0 @@
1
- import { EventType, normalizeSystemPrompts } from "@tanstack/ai";
2
- import { toRunErrorRawEvent } from "@tanstack/ai/adapter-internals";
3
- import { BaseTextAdapter } from "@tanstack/ai/adapters";
4
- import { convertToolsToProviderFormat } from "../tools/tool-converter.js";
5
- import { readCodeExecutionSkills, readCodeExecutionConfig } from "../tools/code-execution-tool.js";
6
- import { validateTextProviderOptions } from "../text/text-provider-options.js";
7
- import { buildAnthropicUsage } from "../usage.js";
8
- import { createAnthropicClient, generateId, getAnthropicApiKeyFromEnv } from "../utils/client.js";
9
- import { ANTHROPIC_COMBINED_TOOLS_AND_SCHEMA_MODELS } from "../model-meta.js";
10
- function computeAnthropicBetas(tools, modelOptions) {
11
- const betas = /* @__PURE__ */ new Set();
12
- const useInterleavedThinking = modelOptions?.thinking?.type === "enabled" && typeof modelOptions.thinking.budget_tokens === "number" && modelOptions.thinking.budget_tokens > 0;
13
- if (useInterleavedThinking) betas.add("interleaved-thinking-2025-05-14");
14
- const codeExecTool = tools?.find((t) => t.name === "code_execution");
15
- if (codeExecTool) {
16
- const cfgType = readCodeExecutionConfig(codeExecTool)?.type;
17
- betas.add(
18
- cfgType === "code_execution_20250522" ? "code-execution-2025-05-22" : "code-execution-2025-08-25"
19
- );
20
- }
21
- const hasSkills = tools?.some(
22
- (t) => t.name === "code_execution" && (readCodeExecutionSkills(t)?.length ?? 0) > 0
23
- );
24
- if (hasSkills) betas.add("skills-2025-10-02");
25
- return betas.size > 0 ? Array.from(betas) : void 0;
26
- }
27
- class AnthropicTextAdapter extends BaseTextAdapter {
28
- kind = "text";
29
- name = "anthropic";
30
- client;
31
- constructor(config, model) {
32
- super({}, model);
33
- this.client = createAnthropicClient(config);
34
- }
35
- async *chatStream(options) {
36
- const { logger } = options;
37
- try {
38
- const requestParams = this.mapCommonOptionsToAnthropic(options);
39
- logger.request(
40
- `activity=chat provider=anthropic model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,
41
- { provider: "anthropic", model: this.model }
42
- );
43
- const betas = computeAnthropicBetas(options.tools, options.modelOptions);
44
- const stream = await this.client.beta.messages.create(
45
- {
46
- ...requestParams,
47
- stream: true,
48
- ...betas && { betas }
49
- },
50
- {
51
- signal: options.request?.signal,
52
- headers: options.request?.headers
53
- }
54
- );
55
- yield* this.processAnthropicStream(
56
- stream,
57
- options,
58
- () => generateId(this.name),
59
- logger
60
- );
61
- } catch (error) {
62
- const err = error;
63
- const rawEvent = toRunErrorRawEvent(error);
64
- logger.errors("anthropic.chatStream fatal", {
65
- error,
66
- source: "anthropic.chatStream"
67
- });
68
- yield {
69
- type: EventType.RUN_ERROR,
70
- model: options.model,
71
- timestamp: Date.now(),
72
- message: err.message || "Unknown error occurred",
73
- code: err.code || String(err.status),
74
- // Forward the Anthropic SDK error's `.error` response body (e.g.
75
- // `{ type, message }`) when present; never the raw exception object.
76
- ...rawEvent !== void 0 && { rawEvent },
77
- error: {
78
- message: err.message || "Unknown error occurred",
79
- code: err.code || String(err.status)
80
- }
81
- };
82
- }
83
- }
84
- /**
85
- * Generate structured output using Anthropic's tool-based approach.
86
- * Anthropic doesn't have native structured output, so we use a tool with the schema
87
- * and force the model to call it.
88
- * The outputSchema is already JSON Schema (converted in the ai layer).
89
- */
90
- async structuredOutput(options) {
91
- const { chatOptions, outputSchema } = options;
92
- const { logger } = chatOptions;
93
- const requestParams = this.mapCommonOptionsToAnthropic(chatOptions);
94
- const structuredOutputTool = {
95
- name: "structured_output",
96
- description: "Use this tool to provide your response in the required structured format.",
97
- input_schema: {
98
- type: "object",
99
- properties: outputSchema.properties ?? {},
100
- required: outputSchema.required ?? []
101
- }
102
- };
103
- try {
104
- logger.request(
105
- `activity=chat provider=anthropic model=${this.model} messages=${chatOptions.messages.length} tools=${chatOptions.tools?.length ?? 0} stream=false`,
106
- { provider: "anthropic", model: this.model }
107
- );
108
- const betas = computeAnthropicBetas(
109
- chatOptions.tools,
110
- chatOptions.modelOptions
111
- );
112
- const response = await this.client.beta.messages.create(
113
- {
114
- ...requestParams,
115
- stream: false,
116
- tools: [structuredOutputTool],
117
- tool_choice: { type: "tool", name: "structured_output" },
118
- ...betas && { betas }
119
- },
120
- {
121
- signal: chatOptions.request?.signal,
122
- headers: chatOptions.request?.headers
123
- }
124
- );
125
- let parsed = null;
126
- let rawText = "";
127
- for (const block of response.content) {
128
- if (block.type === "tool_use" && block.name === "structured_output") {
129
- parsed = block.input;
130
- rawText = JSON.stringify(block.input);
131
- break;
132
- }
133
- }
134
- if (parsed === null) {
135
- rawText = response.content.map((b) => {
136
- if (b.type === "text") {
137
- return b.text;
138
- }
139
- return "";
140
- }).join("");
141
- try {
142
- parsed = JSON.parse(rawText);
143
- } catch {
144
- throw new Error(
145
- `Failed to extract structured output from response. Content: ${rawText.slice(0, 200)}${rawText.length > 200 ? "..." : ""}`
146
- );
147
- }
148
- }
149
- return {
150
- data: parsed,
151
- rawText,
152
- usage: buildAnthropicUsage(response.usage)
153
- };
154
- } catch (error) {
155
- const err = error;
156
- logger.errors("anthropic.structuredOutput fatal", {
157
- error,
158
- source: "anthropic.structuredOutput"
159
- });
160
- throw new Error(
161
- `Structured output generation failed: ${err.message || "Unknown error occurred"}`
162
- );
163
- }
164
- }
165
- mapCommonOptionsToAnthropic(options) {
166
- const modelOptions = options.modelOptions;
167
- const formattedMessages = this.formatMessages(options.messages);
168
- const tools = options.tools ? convertToolsToProviderFormat(options.tools) : void 0;
169
- const validProviderOptions = {};
170
- if (modelOptions) {
171
- const validKeys = [
172
- "container",
173
- "context_management",
174
- "effort",
175
- "mcp_servers",
176
- "output_config",
177
- "service_tier",
178
- "stop_sequences",
179
- "thinking",
180
- "tool_choice",
181
- "top_k",
182
- "temperature",
183
- "top_p"
184
- ];
185
- const droppedKeyExemptSet = /* @__PURE__ */ new Set([...validKeys, "max_tokens"]);
186
- const droppedKeys = Object.keys(modelOptions).filter(
187
- (key) => !droppedKeyExemptSet.has(key)
188
- );
189
- if (droppedKeys.length > 0) {
190
- options.logger.errors(
191
- `anthropic.mapCommonOptionsToAnthropic dropped unknown modelOptions key(s): ${droppedKeys.join(", ")}`,
192
- {
193
- source: "anthropic.mapCommonOptionsToAnthropic",
194
- droppedKeys,
195
- hint: droppedKeys.includes("system") ? "pass system prompts via the top-level `systemPrompts` option; `modelOptions.system` is no longer honored" : void 0
196
- }
197
- );
198
- }
199
- for (const key of validKeys) {
200
- if (key in modelOptions) {
201
- const value = modelOptions[key];
202
- if (key === "tool_choice" && typeof value === "string") {
203
- validProviderOptions[key] = {
204
- type: value
205
- };
206
- } else {
207
- validProviderOptions[key] = value;
208
- }
209
- }
210
- }
211
- }
212
- const thinkingBudget = validProviderOptions.thinking?.type === "enabled" ? validProviderOptions.thinking.budget_tokens : void 0;
213
- const defaultMaxTokens = modelOptions?.max_tokens ?? 1024;
214
- const maxTokens = thinkingBudget && thinkingBudget >= defaultMaxTokens ? thinkingBudget + 1 : defaultMaxTokens;
215
- const systemBlocks = (() => {
216
- const normalized = normalizeSystemPrompts(
217
- options.systemPrompts
218
- );
219
- if (normalized.length === 0) return void 0;
220
- return normalized.map(
221
- (p) => ({
222
- type: "text",
223
- text: p.content,
224
- ...p.metadata?.cache_control && {
225
- cache_control: p.metadata.cache_control
226
- }
227
- })
228
- );
229
- })();
230
- const combinedSchema = options.outputSchema;
231
- const outputConfig = combinedSchema ? {
232
- output_config: {
233
- ...validProviderOptions.output_config ?? {},
234
- format: {
235
- type: "json_schema",
236
- schema: combinedSchema
237
- }
238
- }
239
- } : void 0;
240
- const toolSkills = options.tools?.map(
241
- (tool) => tool.name === "code_execution" ? readCodeExecutionSkills(tool) : void 0
242
- ).find((skills) => skills && skills.length > 0);
243
- if (toolSkills && toolSkills.length > 0) {
244
- const existingContainer = validProviderOptions.container ?? void 0;
245
- validProviderOptions.container = {
246
- id: existingContainer?.id ?? null,
247
- skills: toolSkills
248
- };
249
- }
250
- const requestParams = {
251
- model: options.model,
252
- max_tokens: maxTokens,
253
- messages: formattedMessages,
254
- ...systemBlocks !== void 0 && { system: systemBlocks },
255
- ...tools !== void 0 && { tools },
256
- ...validProviderOptions,
257
- ...outputConfig ?? {}
258
- };
259
- validateTextProviderOptions(requestParams);
260
- return requestParams;
261
- }
262
- /**
263
- * Anthropic supports `output_config.format` + `tools` in a single streaming
264
- * Messages request only for Claude 4.5+ (GA 2026-01-29). For 4.4 and
265
- * earlier we keep the forced-tool-use workaround in
266
- * {@link structuredOutput} via the engine's finalization path.
267
- */
268
- supportsCombinedToolsAndSchema() {
269
- return ANTHROPIC_COMBINED_TOOLS_AND_SCHEMA_MODELS.has(this.model);
270
- }
271
- convertContentPartToAnthropic(part) {
272
- switch (part.type) {
273
- case "text": {
274
- const metadata = part.metadata;
275
- return {
276
- type: "text",
277
- text: part.content,
278
- ...metadata
279
- };
280
- }
281
- case "image": {
282
- const metadata = part.metadata;
283
- const imageSource = part.source.type === "data" ? {
284
- type: "base64",
285
- data: part.source.value,
286
- media_type: part.source.mimeType
287
- } : {
288
- type: "url",
289
- url: part.source.value
290
- };
291
- return {
292
- type: "image",
293
- source: imageSource,
294
- ...metadata
295
- };
296
- }
297
- case "document": {
298
- const metadata = part.metadata;
299
- const docSource = part.source.type === "data" ? {
300
- type: "base64",
301
- data: part.source.value,
302
- media_type: part.source.mimeType
303
- } : {
304
- type: "url",
305
- url: part.source.value
306
- };
307
- return {
308
- type: "document",
309
- source: docSource,
310
- ...metadata
311
- };
312
- }
313
- case "audio":
314
- case "video":
315
- throw new Error(
316
- `Anthropic does not support ${part.type} content directly`
317
- );
318
- default: {
319
- const _exhaustiveCheck = part;
320
- throw new Error(
321
- `Unsupported content part type: ${_exhaustiveCheck.type}`
322
- );
323
- }
324
- }
325
- }
326
- formatMessages(messages) {
327
- const formattedMessages = [];
328
- for (const message of messages) {
329
- const role = message.role;
330
- if (role === "tool" && message.toolCallId) {
331
- const toolContent = message.content;
332
- formattedMessages.push({
333
- role: "user",
334
- content: [
335
- {
336
- type: "tool_result",
337
- tool_use_id: message.toolCallId,
338
- content: Array.isArray(toolContent) ? toolContent.map(
339
- (part) => this.convertContentPartToAnthropic(part)
340
- ) : typeof toolContent === "string" ? toolContent : ""
341
- }
342
- ]
343
- });
344
- continue;
345
- }
346
- if (role === "assistant" && message.toolCalls?.length) {
347
- const contentBlocks = [];
348
- this.appendThinkingBlocks(contentBlocks, message.thinking);
349
- if (message.content) {
350
- const content = typeof message.content === "string" ? message.content : "";
351
- const textBlock = {
352
- type: "text",
353
- text: content
354
- };
355
- contentBlocks.push(textBlock);
356
- }
357
- for (const toolCall of message.toolCalls) {
358
- let parsedInput = {};
359
- try {
360
- const parsed = toolCall.function.arguments ? JSON.parse(toolCall.function.arguments) : {};
361
- parsedInput = parsed && typeof parsed === "object" ? parsed : {};
362
- } catch {
363
- parsedInput = toolCall.function.arguments;
364
- }
365
- const toolUseBlock = {
366
- type: "tool_use",
367
- id: toolCall.id,
368
- name: toolCall.function.name,
369
- input: parsedInput
370
- };
371
- contentBlocks.push(toolUseBlock);
372
- }
373
- formattedMessages.push({
374
- role: "assistant",
375
- content: contentBlocks
376
- });
377
- continue;
378
- }
379
- if (role === "assistant") {
380
- const contentBlocks = [];
381
- this.appendThinkingBlocks(contentBlocks, message.thinking);
382
- if (Array.isArray(message.content)) {
383
- for (const part of message.content) {
384
- contentBlocks.push(this.convertContentPartToAnthropic(part));
385
- }
386
- } else if (message.content) {
387
- contentBlocks.push({
388
- type: "text",
389
- text: message.content
390
- });
391
- }
392
- formattedMessages.push({
393
- role: "assistant",
394
- content: contentBlocks.length > 0 ? contentBlocks : ""
395
- });
396
- continue;
397
- }
398
- if (role === "user" && Array.isArray(message.content)) {
399
- const contentBlocks = message.content.map(
400
- (part) => this.convertContentPartToAnthropic(part)
401
- );
402
- formattedMessages.push({
403
- role: "user",
404
- content: contentBlocks
405
- });
406
- continue;
407
- }
408
- formattedMessages.push({
409
- role: "user",
410
- content: typeof message.content === "string" ? message.content : message.content ? message.content.map(
411
- (c) => this.convertContentPartToAnthropic(c)
412
- ) : ""
413
- });
414
- }
415
- return this.mergeConsecutiveSameRoleMessages(formattedMessages);
416
- }
417
- appendThinkingBlocks(contentBlocks, thinkingParts) {
418
- if (!thinkingParts?.length) return;
419
- for (const thinking of thinkingParts) {
420
- if (!thinking.signature) continue;
421
- const block = {
422
- type: "thinking",
423
- thinking: thinking.content,
424
- signature: thinking.signature
425
- };
426
- contentBlocks.push(block);
427
- }
428
- }
429
- /**
430
- * Merge consecutive messages of the same role into a single message.
431
- * Anthropic's API requires strictly alternating user/assistant roles.
432
- * Tool results are wrapped as role:'user' messages, which can collide
433
- * with actual user messages in multi-turn conversations.
434
- *
435
- * Also filters out empty assistant messages (e.g., from a previous failed request).
436
- */
437
- mergeConsecutiveSameRoleMessages(messages) {
438
- const merged = [];
439
- for (const msg of messages) {
440
- if (msg.role === "assistant") {
441
- const hasContent = Array.isArray(msg.content) ? msg.content.length > 0 : typeof msg.content === "string" && msg.content.length > 0;
442
- if (!hasContent) {
443
- continue;
444
- }
445
- }
446
- const prev = merged[merged.length - 1];
447
- if (prev && prev.role === msg.role) {
448
- const prevBlocks = Array.isArray(prev.content) ? prev.content : typeof prev.content === "string" && prev.content ? [{ type: "text", text: prev.content }] : [];
449
- const msgBlocks = Array.isArray(msg.content) ? msg.content : typeof msg.content === "string" && msg.content ? [{ type: "text", text: msg.content }] : [];
450
- prev.content = [...prevBlocks, ...msgBlocks];
451
- } else {
452
- merged.push({ ...msg });
453
- }
454
- }
455
- for (const msg of merged) {
456
- if (Array.isArray(msg.content)) {
457
- const seenToolResultIds = /* @__PURE__ */ new Set();
458
- msg.content = msg.content.filter((block) => {
459
- if (block.type === "tool_result" && block.tool_use_id) {
460
- if (seenToolResultIds.has(block.tool_use_id)) {
461
- return false;
462
- }
463
- seenToolResultIds.add(block.tool_use_id);
464
- }
465
- return true;
466
- });
467
- }
468
- }
469
- return merged;
470
- }
471
- async *processAnthropicStream(stream, options, genId, logger) {
472
- const model = options.model;
473
- let accumulatedContent = "";
474
- let accumulatedThinking = "";
475
- let accumulatedSignature = "";
476
- const toolCallsMap = /* @__PURE__ */ new Map();
477
- let currentToolIndex = -1;
478
- let currentServerTool = null;
479
- const runId = options.runId ?? genId();
480
- const threadId = options.threadId ?? genId();
481
- const messageId = genId();
482
- let stepId = null;
483
- let reasoningMessageId = null;
484
- let hasClosedReasoning = false;
485
- let hasEmittedRunStarted = false;
486
- let hasEmittedTextMessageStart = false;
487
- let hasEmittedRunFinished = false;
488
- let currentBlockType = null;
489
- try {
490
- for await (const event of stream) {
491
- logger.provider(`provider=anthropic type=${event.type}`, {
492
- chunk: event
493
- });
494
- if (!hasEmittedRunStarted) {
495
- hasEmittedRunStarted = true;
496
- yield {
497
- type: EventType.RUN_STARTED,
498
- runId,
499
- threadId,
500
- model,
501
- timestamp: Date.now(),
502
- parentRunId: options.parentRunId
503
- };
504
- }
505
- if (event.type === "content_block_start") {
506
- currentBlockType = event.content_block.type;
507
- if (event.content_block.type === "tool_use") {
508
- currentToolIndex++;
509
- toolCallsMap.set(currentToolIndex, {
510
- id: event.content_block.id,
511
- name: event.content_block.name,
512
- input: "",
513
- started: false
514
- });
515
- } else if (event.content_block.type === "server_tool_use") {
516
- currentServerTool = {
517
- id: event.content_block.id,
518
- name: event.content_block.name,
519
- input: ""
520
- };
521
- } else if (event.content_block.type === "web_fetch_tool_result" || event.content_block.type === "web_search_tool_result") {
522
- const content = event.content_block.content;
523
- const errorBlock = !Array.isArray(content) && (content.type === "web_fetch_tool_result_error" || content.type === "web_search_tool_result_error") ? content : null;
524
- if (errorBlock) {
525
- logger.errors(
526
- `anthropic.${event.content_block.type} error_code=${errorBlock.error_code}`,
527
- {
528
- toolUseId: event.content_block.tool_use_id,
529
- blockType: event.content_block.type,
530
- errorCode: errorBlock.error_code,
531
- source: "anthropic.processAnthropicStream"
532
- }
533
- );
534
- }
535
- } else if (event.content_block.type === "thinking") {
536
- accumulatedThinking = "";
537
- accumulatedSignature = "";
538
- stepId = genId();
539
- reasoningMessageId = genId();
540
- yield {
541
- type: EventType.REASONING_START,
542
- messageId: reasoningMessageId,
543
- model,
544
- timestamp: Date.now()
545
- };
546
- yield {
547
- type: EventType.REASONING_MESSAGE_START,
548
- messageId: reasoningMessageId,
549
- role: "reasoning",
550
- model,
551
- timestamp: Date.now()
552
- };
553
- yield {
554
- type: EventType.STEP_STARTED,
555
- stepName: stepId,
556
- stepId,
557
- model,
558
- timestamp: Date.now(),
559
- stepType: "thinking"
560
- };
561
- }
562
- } else if (event.type === "content_block_delta") {
563
- if (event.delta.type === "text_delta") {
564
- if (reasoningMessageId && !hasClosedReasoning) {
565
- hasClosedReasoning = true;
566
- yield {
567
- type: EventType.REASONING_MESSAGE_END,
568
- messageId: reasoningMessageId,
569
- model,
570
- timestamp: Date.now()
571
- };
572
- yield {
573
- type: EventType.REASONING_END,
574
- messageId: reasoningMessageId,
575
- model,
576
- timestamp: Date.now()
577
- };
578
- }
579
- if (!hasEmittedTextMessageStart) {
580
- hasEmittedTextMessageStart = true;
581
- yield {
582
- type: EventType.TEXT_MESSAGE_START,
583
- messageId,
584
- model,
585
- timestamp: Date.now(),
586
- role: "assistant"
587
- };
588
- }
589
- const delta = event.delta.text;
590
- accumulatedContent += delta;
591
- yield {
592
- type: EventType.TEXT_MESSAGE_CONTENT,
593
- messageId,
594
- model,
595
- timestamp: Date.now(),
596
- delta,
597
- content: accumulatedContent
598
- };
599
- } else if (event.delta.type === "thinking_delta" && reasoningMessageId) {
600
- const delta = event.delta.thinking;
601
- accumulatedThinking += delta;
602
- yield {
603
- type: EventType.REASONING_MESSAGE_CONTENT,
604
- messageId: reasoningMessageId,
605
- delta,
606
- model,
607
- timestamp: Date.now()
608
- };
609
- yield {
610
- type: EventType.STEP_FINISHED,
611
- stepName: stepId || genId(),
612
- stepId: stepId || genId(),
613
- model,
614
- timestamp: Date.now(),
615
- delta,
616
- content: accumulatedThinking
617
- };
618
- } else if (event.delta.type === "signature_delta") {
619
- accumulatedSignature += event.delta.signature || "";
620
- } else if (event.delta.type === "input_json_delta") {
621
- if (currentBlockType === "tool_use") {
622
- const existing = toolCallsMap.get(currentToolIndex);
623
- if (existing) {
624
- if (!existing.started) {
625
- existing.started = true;
626
- yield {
627
- type: EventType.TOOL_CALL_START,
628
- toolCallId: existing.id,
629
- toolCallName: existing.name,
630
- toolName: existing.name,
631
- parentMessageId: messageId,
632
- model,
633
- timestamp: Date.now(),
634
- index: currentToolIndex
635
- };
636
- }
637
- existing.input += event.delta.partial_json;
638
- yield {
639
- type: EventType.TOOL_CALL_ARGS,
640
- toolCallId: existing.id,
641
- model,
642
- timestamp: Date.now(),
643
- delta: event.delta.partial_json,
644
- args: existing.input
645
- };
646
- }
647
- } else if (currentBlockType === "server_tool_use" && currentServerTool) {
648
- currentServerTool.input += event.delta.partial_json;
649
- }
650
- }
651
- } else if (event.type === "content_block_stop") {
652
- if (currentBlockType === "thinking") {
653
- if (accumulatedSignature && stepId) {
654
- yield {
655
- type: EventType.STEP_FINISHED,
656
- stepName: stepId,
657
- stepId,
658
- model,
659
- timestamp: Date.now(),
660
- delta: "",
661
- content: accumulatedThinking,
662
- signature: accumulatedSignature
663
- };
664
- }
665
- } else if (currentBlockType === "tool_use") {
666
- const existing = toolCallsMap.get(currentToolIndex);
667
- if (existing) {
668
- if (!existing.started) {
669
- existing.started = true;
670
- yield {
671
- type: EventType.TOOL_CALL_START,
672
- toolCallId: existing.id,
673
- toolCallName: existing.name,
674
- toolName: existing.name,
675
- parentMessageId: messageId,
676
- model,
677
- timestamp: Date.now(),
678
- index: currentToolIndex
679
- };
680
- }
681
- let parsedInput = {};
682
- try {
683
- const parsed = existing.input ? JSON.parse(existing.input) : {};
684
- parsedInput = parsed && typeof parsed === "object" ? parsed : {};
685
- } catch {
686
- parsedInput = {};
687
- }
688
- yield {
689
- type: EventType.TOOL_CALL_END,
690
- toolCallId: existing.id,
691
- toolCallName: existing.name,
692
- toolName: existing.name,
693
- model,
694
- timestamp: Date.now(),
695
- input: parsedInput
696
- };
697
- hasEmittedTextMessageStart = false;
698
- }
699
- } else if (currentBlockType === "server_tool_use") {
700
- if (currentServerTool) {
701
- logger.provider(
702
- `provider=anthropic server_tool_use name=${currentServerTool.name}`,
703
- {
704
- toolUseId: currentServerTool.id,
705
- name: currentServerTool.name,
706
- input: currentServerTool.input
707
- }
708
- );
709
- }
710
- currentServerTool = null;
711
- } else if (currentBlockType === "web_fetch_tool_result" || currentBlockType === "web_search_tool_result") {
712
- } else {
713
- if (hasEmittedTextMessageStart && accumulatedContent) {
714
- yield {
715
- type: EventType.TEXT_MESSAGE_END,
716
- messageId,
717
- model,
718
- timestamp: Date.now()
719
- };
720
- }
721
- }
722
- currentBlockType = null;
723
- } else if (event.type === "message_stop") {
724
- if (reasoningMessageId && !hasClosedReasoning) {
725
- hasClosedReasoning = true;
726
- yield {
727
- type: EventType.REASONING_MESSAGE_END,
728
- messageId: reasoningMessageId,
729
- model,
730
- timestamp: Date.now()
731
- };
732
- yield {
733
- type: EventType.REASONING_END,
734
- messageId: reasoningMessageId,
735
- model,
736
- timestamp: Date.now()
737
- };
738
- }
739
- if (!hasEmittedRunFinished) {
740
- yield {
741
- type: EventType.RUN_FINISHED,
742
- runId,
743
- threadId,
744
- model,
745
- timestamp: Date.now(),
746
- finishReason: "stop"
747
- };
748
- }
749
- } else if (event.type === "message_delta") {
750
- if (event.delta.stop_reason) {
751
- hasEmittedRunFinished = true;
752
- if (reasoningMessageId && !hasClosedReasoning) {
753
- hasClosedReasoning = true;
754
- yield {
755
- type: EventType.REASONING_MESSAGE_END,
756
- messageId: reasoningMessageId,
757
- model,
758
- timestamp: Date.now()
759
- };
760
- yield {
761
- type: EventType.REASONING_END,
762
- messageId: reasoningMessageId,
763
- model,
764
- timestamp: Date.now()
765
- };
766
- }
767
- switch (event.delta.stop_reason) {
768
- case "tool_use": {
769
- yield {
770
- type: EventType.RUN_FINISHED,
771
- runId,
772
- threadId,
773
- model,
774
- timestamp: Date.now(),
775
- finishReason: "tool_calls",
776
- usage: buildAnthropicUsage(event.usage)
777
- };
778
- break;
779
- }
780
- case "max_tokens": {
781
- yield {
782
- type: EventType.RUN_ERROR,
783
- model,
784
- timestamp: Date.now(),
785
- message: "The response was cut off because the maximum token limit was reached.",
786
- code: "max_tokens",
787
- error: {
788
- message: "The response was cut off because the maximum token limit was reached.",
789
- code: "max_tokens"
790
- }
791
- };
792
- break;
793
- }
794
- case "stop_sequence":
795
- case "end_turn":
796
- case "pause_turn":
797
- case "refusal":
798
- case "model_context_window_exceeded":
799
- case "compaction":
800
- default: {
801
- yield {
802
- type: EventType.RUN_FINISHED,
803
- runId,
804
- threadId,
805
- model,
806
- timestamp: Date.now(),
807
- finishReason: "stop",
808
- usage: buildAnthropicUsage(event.usage)
809
- };
810
- }
811
- }
812
- }
813
- }
814
- }
815
- } catch (error) {
816
- const err = error;
817
- const rawEvent = toRunErrorRawEvent(error);
818
- logger.errors("anthropic.processAnthropicStream fatal", {
819
- error,
820
- source: "anthropic.processAnthropicStream"
821
- });
822
- yield {
823
- type: EventType.RUN_ERROR,
824
- model,
825
- timestamp: Date.now(),
826
- message: err.message || "Unknown error occurred",
827
- code: err.code || String(err.status),
828
- // Forward the Anthropic SDK error's `.error` response body when present.
829
- ...rawEvent !== void 0 && { rawEvent },
830
- error: {
831
- message: err.message || "Unknown error occurred",
832
- code: err.code || String(err.status)
833
- }
834
- };
835
- }
836
- }
837
- }
838
- function createAnthropicChat(model, apiKey, config) {
839
- return new AnthropicTextAdapter({ apiKey, ...config }, model);
840
- }
841
- function anthropicText(model, config) {
842
- const apiKey = getAnthropicApiKeyFromEnv();
843
- return createAnthropicChat(model, apiKey, config);
844
- }
845
- export {
846
- AnthropicTextAdapter,
847
- anthropicText,
848
- computeAnthropicBetas,
849
- createAnthropicChat
850
- };
851
- //# sourceMappingURL=text.js.map