@tanstack/ai-anthropic 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/adapters/text.d.ts +3 -3
- package/dist/esm/adapters/text.js +34 -12
- package/dist/esm/adapters/text.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/text/text-provider-options.d.ts +30 -0
- package/dist/esm/text/text-provider-options.js.map +1 -1
- package/dist/esm/tools/bash-tool.js +3 -2
- package/dist/esm/tools/bash-tool.js.map +1 -1
- package/dist/esm/tools/code-execution-tool.js +3 -2
- package/dist/esm/tools/code-execution-tool.js.map +1 -1
- package/dist/esm/tools/computer-use-tool.js +3 -2
- package/dist/esm/tools/computer-use-tool.js.map +1 -1
- package/dist/esm/tools/memory-tool.js +3 -2
- package/dist/esm/tools/memory-tool.js.map +1 -1
- package/dist/esm/tools/text-editor-tool.js +3 -2
- package/dist/esm/tools/text-editor-tool.js.map +1 -1
- package/dist/esm/tools/web-fetch-tool.js +3 -2
- package/dist/esm/tools/web-fetch-tool.js.map +1 -1
- package/dist/esm/tools/web-search-tool.js +13 -6
- package/dist/esm/tools/web-search-tool.js.map +1 -1
- package/package.json +3 -3
- package/src/adapters/text.ts +65 -29
- package/src/index.ts +1 -0
- package/src/text/text-provider-options.ts +31 -0
- package/src/tools/bash-tool.ts +3 -3
- package/src/tools/code-execution-tool.ts +3 -3
- package/src/tools/computer-use-tool.ts +3 -3
- package/src/tools/memory-tool.ts +3 -3
- package/src/tools/text-editor-tool.ts +3 -3
- package/src/tools/web-fetch-tool.ts +3 -3
- package/src/tools/web-search-tool.ts +16 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseTextAdapter, StructuredOutputOptions, StructuredOutputResult } from '@tanstack/ai/adapters';
|
|
2
2
|
import { ANTHROPIC_MODELS, AnthropicChatModelProviderOptionsByName, AnthropicChatModelToolCapabilitiesByName, AnthropicModelInputModalitiesByName } from '../model-meta.js';
|
|
3
3
|
import { Modality, StreamChunk, TextOptions } from '@tanstack/ai';
|
|
4
|
-
import { ExternalTextProviderOptions } from '../text/text-provider-options.js';
|
|
4
|
+
import { AnthropicSystemPromptMetadata, ExternalTextProviderOptions } from '../text/text-provider-options.js';
|
|
5
5
|
import { AnthropicMessageMetadataByModality } from '../message-types.js';
|
|
6
6
|
import { AnthropicClientConfig } from '../utils.js';
|
|
7
7
|
/**
|
|
@@ -30,10 +30,10 @@ type ResolveToolCapabilities<TModel extends string> = TModel extends keyof Anthr
|
|
|
30
30
|
* Tree-shakeable adapter for Anthropic chat/text completion functionality.
|
|
31
31
|
* Import only what you need for smaller bundle sizes.
|
|
32
32
|
*/
|
|
33
|
-
export declare class AnthropicTextAdapter<TModel extends (typeof ANTHROPIC_MODELS)[number], TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>, TInputModalities extends ReadonlyArray<Modality> = ResolveInputModalities<TModel>, TToolCapabilities extends ReadonlyArray<string> = ResolveToolCapabilities<TModel>> extends BaseTextAdapter<TModel, TProviderOptions, TInputModalities, AnthropicMessageMetadataByModality, TToolCapabilities> {
|
|
33
|
+
export declare class AnthropicTextAdapter<TModel extends (typeof ANTHROPIC_MODELS)[number], TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>, TInputModalities extends ReadonlyArray<Modality> = ResolveInputModalities<TModel>, TToolCapabilities extends ReadonlyArray<string> = ResolveToolCapabilities<TModel>> extends BaseTextAdapter<TModel, TProviderOptions, TInputModalities, AnthropicMessageMetadataByModality, TToolCapabilities, unknown, AnthropicSystemPromptMetadata> {
|
|
34
34
|
readonly kind: "text";
|
|
35
35
|
readonly name: "anthropic";
|
|
36
|
-
private client;
|
|
36
|
+
private readonly client;
|
|
37
37
|
constructor(config: AnthropicTextConfig, model: TModel);
|
|
38
38
|
chatStream(options: TextOptions<TProviderOptions>): AsyncIterable<StreamChunk>;
|
|
39
39
|
/**
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { EventType } from "@tanstack/ai";
|
|
1
|
+
import { EventType, normalizeSystemPrompts } from "@tanstack/ai";
|
|
2
2
|
import { BaseTextAdapter } from "@tanstack/ai/adapters";
|
|
3
3
|
import { convertToolsToProviderFormat } from "../tools/tool-converter.js";
|
|
4
4
|
import { validateTextProviderOptions } from "../text/text-provider-options.js";
|
|
5
5
|
import { createAnthropicClient, generateId, getAnthropicApiKeyFromEnv } from "../utils/client.js";
|
|
6
6
|
class AnthropicTextAdapter extends BaseTextAdapter {
|
|
7
|
+
kind = "text";
|
|
8
|
+
name = "anthropic";
|
|
9
|
+
client;
|
|
7
10
|
constructor(config, model) {
|
|
8
11
|
super({}, model);
|
|
9
|
-
this.kind = "text";
|
|
10
|
-
this.name = "anthropic";
|
|
11
12
|
this.client = createAnthropicClient(config);
|
|
12
13
|
}
|
|
13
14
|
async *chatStream(options) {
|
|
@@ -175,16 +176,31 @@ class AnthropicTextAdapter extends BaseTextAdapter {
|
|
|
175
176
|
const thinkingBudget = validProviderOptions.thinking?.type === "enabled" ? validProviderOptions.thinking.budget_tokens : void 0;
|
|
176
177
|
const defaultMaxTokens = options.maxTokens || 1024;
|
|
177
178
|
const maxTokens = thinkingBudget && thinkingBudget >= defaultMaxTokens ? thinkingBudget + 1 : defaultMaxTokens;
|
|
179
|
+
const systemBlocks = (() => {
|
|
180
|
+
const normalized = normalizeSystemPrompts(
|
|
181
|
+
options.systemPrompts
|
|
182
|
+
);
|
|
183
|
+
if (normalized.length === 0) return void 0;
|
|
184
|
+
return normalized.map(
|
|
185
|
+
(p) => ({
|
|
186
|
+
type: "text",
|
|
187
|
+
text: p.content,
|
|
188
|
+
...p.metadata?.cache_control && {
|
|
189
|
+
cache_control: p.metadata.cache_control
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
|
+
})();
|
|
178
194
|
const requestParams = {
|
|
179
195
|
model: options.model,
|
|
180
196
|
max_tokens: maxTokens,
|
|
181
|
-
|
|
182
|
-
|
|
197
|
+
...options.temperature !== void 0 && {
|
|
198
|
+
temperature: options.temperature
|
|
199
|
+
},
|
|
200
|
+
...options.topP !== void 0 && { top_p: options.topP },
|
|
183
201
|
messages: formattedMessages,
|
|
184
|
-
system:
|
|
185
|
-
|
|
186
|
-
) : void 0,
|
|
187
|
-
tools,
|
|
202
|
+
...systemBlocks !== void 0 && { system: systemBlocks },
|
|
203
|
+
...tools !== void 0 && { tools },
|
|
188
204
|
...validProviderOptions
|
|
189
205
|
};
|
|
190
206
|
validateTextProviderOptions(requestParams);
|
|
@@ -337,11 +353,12 @@ class AnthropicTextAdapter extends BaseTextAdapter {
|
|
|
337
353
|
if (!thinkingParts?.length) return;
|
|
338
354
|
for (const thinking of thinkingParts) {
|
|
339
355
|
if (!thinking.signature) continue;
|
|
340
|
-
|
|
356
|
+
const block = {
|
|
341
357
|
type: "thinking",
|
|
342
358
|
thinking: thinking.content,
|
|
343
359
|
signature: thinking.signature
|
|
344
|
-
}
|
|
360
|
+
};
|
|
361
|
+
contentBlocks.push(block);
|
|
345
362
|
}
|
|
346
363
|
}
|
|
347
364
|
/**
|
|
@@ -493,7 +510,7 @@ class AnthropicTextAdapter extends BaseTextAdapter {
|
|
|
493
510
|
delta,
|
|
494
511
|
content: accumulatedContent
|
|
495
512
|
};
|
|
496
|
-
} else if (event.delta.type === "thinking_delta") {
|
|
513
|
+
} else if (event.delta.type === "thinking_delta" && reasoningMessageId) {
|
|
497
514
|
const delta = event.delta.thinking;
|
|
498
515
|
accumulatedThinking += delta;
|
|
499
516
|
yield {
|
|
@@ -673,6 +690,11 @@ class AnthropicTextAdapter extends BaseTextAdapter {
|
|
|
673
690
|
};
|
|
674
691
|
break;
|
|
675
692
|
}
|
|
693
|
+
case "stop_sequence":
|
|
694
|
+
case "end_turn":
|
|
695
|
+
case "pause_turn":
|
|
696
|
+
case "refusal":
|
|
697
|
+
case "model_context_window_exceeded":
|
|
676
698
|
default: {
|
|
677
699
|
yield {
|
|
678
700
|
type: EventType.RUN_FINISHED,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import { EventType } from '@tanstack/ai'\nimport { BaseTextAdapter } from '@tanstack/ai/adapters'\nimport { convertToolsToProviderFormat } from '../tools/tool-converter'\nimport { validateTextProviderOptions } from '../text/text-provider-options'\nimport {\n createAnthropicClient,\n generateId,\n getAnthropicApiKeyFromEnv,\n} from '../utils'\nimport type {\n ANTHROPIC_MODELS,\n AnthropicChatModelProviderOptionsByName,\n AnthropicChatModelToolCapabilitiesByName,\n AnthropicModelInputModalitiesByName,\n} from '../model-meta'\nimport type {\n StructuredOutputOptions,\n StructuredOutputResult,\n} from '@tanstack/ai/adapters'\nimport type { InternalLogger } from '@tanstack/ai/adapter-internals'\nimport type {\n Base64ImageSource,\n Base64PDFSource,\n DocumentBlockParam,\n ImageBlockParam,\n MessageParam,\n TextBlockParam,\n URLImageSource,\n URLPDFSource,\n} from '@anthropic-ai/sdk/resources/messages'\nimport type Anthropic_SDK from '@anthropic-ai/sdk'\nimport type { AnthropicBeta } from '@anthropic-ai/sdk/resources/beta/beta'\nimport type {\n ContentPart,\n Modality,\n ModelMessage,\n StreamChunk,\n TextOptions,\n} from '@tanstack/ai'\nimport type {\n ExternalTextProviderOptions,\n InternalTextProviderOptions,\n} from '../text/text-provider-options'\nimport type {\n AnthropicDocumentMetadata,\n AnthropicImageMetadata,\n AnthropicMessageMetadataByModality,\n AnthropicTextMetadata,\n} from '../message-types'\nimport type { AnthropicClientConfig } from '../utils'\n\n/**\n * Configuration for Anthropic text adapter\n */\nexport interface AnthropicTextConfig extends AnthropicClientConfig {}\n\n/**\n * Anthropic-specific provider options for text/chat\n */\nexport type AnthropicTextProviderOptions = ExternalTextProviderOptions\n\ntype AnthropicContentBlocks =\n Extract<MessageParam['content'], Array<unknown>> extends Array<infer Block>\n ? Array<Block>\n : never\ntype AnthropicContentBlock =\n AnthropicContentBlocks extends Array<infer Block> ? Block : never\n\n// ===========================\n// Type Resolution Helpers\n// ===========================\n\n/**\n * Resolve provider options for a specific model.\n * If the model has explicit options in the map, use those; otherwise use base options.\n */\ntype ResolveProviderOptions<TModel extends string> =\n TModel extends keyof AnthropicChatModelProviderOptionsByName\n ? AnthropicChatModelProviderOptionsByName[TModel]\n : AnthropicTextProviderOptions\n\n/**\n * Resolve input modalities for a specific model.\n * If the model has explicit modalities in the map, use those; otherwise use default.\n */\ntype ResolveInputModalities<TModel extends string> =\n TModel extends keyof AnthropicModelInputModalitiesByName\n ? AnthropicModelInputModalitiesByName[TModel]\n : readonly ['text', 'image', 'document']\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof AnthropicChatModelToolCapabilitiesByName\n ? NonNullable<AnthropicChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n// ===========================\n// Adapter Implementation\n// ===========================\n\n/**\n * Anthropic Text (Chat) Adapter\n *\n * Tree-shakeable adapter for Anthropic chat/text completion functionality.\n * Import only what you need for smaller bundle sizes.\n */\nexport class AnthropicTextAdapter<\n TModel extends (typeof ANTHROPIC_MODELS)[number],\n TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends BaseTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n AnthropicMessageMetadataByModality,\n TToolCapabilities\n> {\n readonly kind = 'text' as const\n readonly name = 'anthropic' as const\n\n private client: Anthropic_SDK\n\n constructor(config: AnthropicTextConfig, model: TModel) {\n super({}, model)\n this.client = createAnthropicClient(config)\n }\n\n async *chatStream(\n options: TextOptions<TProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n const { logger } = options\n try {\n const requestParams = this.mapCommonOptionsToAnthropic(options)\n\n logger.request(\n `activity=chat provider=anthropic model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,\n { provider: 'anthropic', model: this.model },\n )\n\n // Interleaved thinking is only supported on the beta messages endpoint,\n // so the `betas` flag is attached here rather than in the shared mapper\n // (structuredOutput uses the non-beta endpoint which rejects `betas`).\n const modelOptions = options.modelOptions as\n | InternalTextProviderOptions\n | undefined\n const useInterleavedThinking =\n modelOptions?.thinking?.type === 'enabled' &&\n typeof modelOptions.thinking.budget_tokens === 'number' &&\n modelOptions.thinking.budget_tokens > 0\n const betas: Array<AnthropicBeta> | undefined = useInterleavedThinking\n ? ['interleaved-thinking-2025-05-14']\n : undefined\n\n const stream = await this.client.beta.messages.create(\n { ...requestParams, stream: true, ...(betas && { betas }) },\n {\n signal: options.request?.signal,\n headers: options.request?.headers,\n },\n )\n\n yield* this.processAnthropicStream(\n stream,\n options,\n () => generateId(this.name),\n logger,\n )\n } catch (error: unknown) {\n const err = error as Error & { status?: number; code?: string }\n logger.errors('anthropic.chatStream fatal', {\n error,\n source: 'anthropic.chatStream',\n })\n yield {\n type: EventType.RUN_ERROR,\n model: options.model,\n timestamp: Date.now(),\n message: err.message || 'Unknown error occurred',\n code: err.code || String(err.status),\n error: {\n message: err.message || 'Unknown error occurred',\n code: err.code || String(err.status),\n },\n }\n }\n }\n\n /**\n * Generate structured output using Anthropic's tool-based approach.\n * Anthropic doesn't have native structured output, so we use a tool with the schema\n * and force the model to call it.\n * The outputSchema is already JSON Schema (converted in the ai layer).\n */\n async structuredOutput(\n options: StructuredOutputOptions<TProviderOptions>,\n ): Promise<StructuredOutputResult<unknown>> {\n const { chatOptions, outputSchema } = options\n const { logger } = chatOptions\n\n const requestParams = this.mapCommonOptionsToAnthropic(chatOptions)\n\n // Create a tool that will capture the structured output\n // Anthropic's SDK requires input_schema with type: 'object' literal\n const structuredOutputTool = {\n name: 'structured_output',\n description:\n 'Use this tool to provide your response in the required structured format.',\n input_schema: {\n type: 'object' as const,\n properties: outputSchema.properties ?? {},\n required: outputSchema.required ?? [],\n },\n }\n\n try {\n logger.request(\n `activity=chat provider=anthropic model=${this.model} messages=${chatOptions.messages.length} tools=${chatOptions.tools?.length ?? 0} stream=false`,\n { provider: 'anthropic', model: this.model },\n )\n // Make non-streaming request with tool_choice forced to our structured output tool\n const response = await this.client.messages.create(\n {\n ...requestParams,\n stream: false,\n tools: [structuredOutputTool],\n tool_choice: { type: 'tool', name: 'structured_output' },\n },\n {\n signal: chatOptions.request?.signal,\n headers: chatOptions.request?.headers,\n },\n )\n\n // Extract the tool use content from the response\n let parsed: unknown = null\n let rawText = ''\n\n for (const block of response.content) {\n if (block.type === 'tool_use' && block.name === 'structured_output') {\n parsed = block.input\n rawText = JSON.stringify(block.input)\n break\n }\n }\n\n if (parsed === null) {\n // Fallback: try to extract text content and parse as JSON\n rawText = response.content\n .map((b) => {\n if (b.type === 'text') {\n return b.text\n }\n return ''\n })\n .join('')\n try {\n parsed = JSON.parse(rawText)\n } catch {\n throw new Error(\n `Failed to extract structured output from response. Content: ${rawText.slice(0, 200)}${rawText.length > 200 ? '...' : ''}`,\n )\n }\n }\n\n return {\n data: parsed,\n rawText,\n }\n } catch (error: unknown) {\n const err = error as Error\n logger.errors('anthropic.structuredOutput fatal', {\n error,\n source: 'anthropic.structuredOutput',\n })\n throw new Error(\n `Structured output generation failed: ${err.message || 'Unknown error occurred'}`,\n )\n }\n }\n\n private mapCommonOptionsToAnthropic(\n options: TextOptions<AnthropicTextProviderOptions>,\n ) {\n const modelOptions = options.modelOptions as\n | InternalTextProviderOptions\n | undefined\n\n const formattedMessages = this.formatMessages(options.messages)\n const tools = options.tools\n ? convertToolsToProviderFormat(options.tools)\n : undefined\n\n const validProviderOptions: Partial<InternalTextProviderOptions> = {}\n if (modelOptions) {\n const validKeys: Array<keyof InternalTextProviderOptions> = [\n 'container',\n 'context_management',\n 'effort',\n 'mcp_servers',\n 'service_tier',\n 'stop_sequences',\n 'thinking',\n 'tool_choice',\n 'top_k',\n ]\n const validKeySet = new Set<string>(validKeys)\n const droppedKeys = Object.keys(modelOptions).filter(\n (key) => !validKeySet.has(key),\n )\n if (droppedKeys.length > 0) {\n // Reachable when callers cast around the public type (e.g.\n // `modelOptions: { system: ... } as any`). Without this warning the\n // unknown keys are silently dropped — `system` in particular was a\n // previously-tested path for attaching `cache_control` and we don't\n // want that to fail in production with no signal.\n options.logger.errors(\n `anthropic.mapCommonOptionsToAnthropic dropped unknown modelOptions key(s): ${droppedKeys.join(', ')}`,\n {\n source: 'anthropic.mapCommonOptionsToAnthropic',\n droppedKeys,\n hint: droppedKeys.includes('system')\n ? 'pass system prompts via the top-level `systemPrompts` option; `modelOptions.system` is no longer honored'\n : undefined,\n },\n )\n }\n for (const key of validKeys) {\n if (key in modelOptions) {\n const value = modelOptions[key]\n if (key === 'tool_choice' && typeof value === 'string') {\n ;(validProviderOptions as Record<string, unknown>)[key] = {\n type: value,\n }\n } else {\n ;(validProviderOptions as Record<string, unknown>)[key] = value\n }\n }\n }\n }\n\n const thinkingBudget =\n validProviderOptions.thinking?.type === 'enabled'\n ? validProviderOptions.thinking.budget_tokens\n : undefined\n const defaultMaxTokens = options.maxTokens || 1024\n const maxTokens =\n thinkingBudget && thinkingBudget >= defaultMaxTokens\n ? thinkingBudget + 1\n : defaultMaxTokens\n\n const requestParams: InternalTextProviderOptions = {\n model: options.model,\n max_tokens: maxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n messages: formattedMessages,\n system: options.systemPrompts?.length\n ? options.systemPrompts.map(\n (text): TextBlockParam => ({ type: 'text', text }),\n )\n : undefined,\n tools: tools,\n ...validProviderOptions,\n }\n validateTextProviderOptions(requestParams)\n return requestParams\n }\n\n private convertContentPartToAnthropic(\n part: ContentPart,\n ): TextBlockParam | ImageBlockParam | DocumentBlockParam {\n switch (part.type) {\n case 'text': {\n const metadata = part.metadata as AnthropicTextMetadata | undefined\n return {\n type: 'text',\n text: part.content,\n ...metadata,\n }\n }\n\n case 'image': {\n const metadata = part.metadata as AnthropicImageMetadata | undefined\n const imageSource: Base64ImageSource | URLImageSource =\n part.source.type === 'data'\n ? {\n type: 'base64',\n data: part.source.value,\n media_type: part.source.mimeType as\n | 'image/jpeg'\n | 'image/png'\n | 'image/gif'\n | 'image/webp',\n }\n : {\n type: 'url',\n url: part.source.value,\n }\n return {\n type: 'image',\n source: imageSource,\n ...metadata,\n }\n }\n case 'document': {\n const metadata = part.metadata as AnthropicDocumentMetadata | undefined\n const docSource: Base64PDFSource | URLPDFSource =\n part.source.type === 'data'\n ? {\n type: 'base64',\n data: part.source.value,\n media_type: part.source.mimeType as 'application/pdf',\n }\n : {\n type: 'url',\n url: part.source.value,\n }\n return {\n type: 'document',\n source: docSource,\n ...metadata,\n }\n }\n case 'audio':\n case 'video':\n throw new Error(\n `Anthropic does not support ${part.type} content directly`,\n )\n default: {\n const _exhaustiveCheck: never = part\n throw new Error(\n `Unsupported content part type: ${(_exhaustiveCheck as ContentPart).type}`,\n )\n }\n }\n }\n\n private formatMessages(\n messages: Array<ModelMessage>,\n ): InternalTextProviderOptions['messages'] {\n const formattedMessages: InternalTextProviderOptions['messages'] = []\n\n for (const message of messages) {\n const role = message.role\n\n if (role === 'tool' && message.toolCallId) {\n formattedMessages.push({\n role: 'user',\n content: [\n {\n type: 'tool_result',\n tool_use_id: message.toolCallId,\n content:\n typeof message.content === 'string' ? message.content : '',\n },\n ],\n })\n continue\n }\n\n if (role === 'assistant' && message.toolCalls?.length) {\n const contentBlocks: AnthropicContentBlocks = []\n\n this.appendThinkingBlocks(contentBlocks, message.thinking)\n\n if (message.content) {\n const content =\n typeof message.content === 'string' ? message.content : ''\n const textBlock: AnthropicContentBlock = {\n type: 'text',\n text: content,\n }\n contentBlocks.push(textBlock)\n }\n\n for (const toolCall of message.toolCalls) {\n let parsedInput: unknown = {}\n try {\n const parsed = toolCall.function.arguments\n ? JSON.parse(toolCall.function.arguments)\n : {}\n parsedInput = parsed && typeof parsed === 'object' ? parsed : {}\n } catch {\n parsedInput = toolCall.function.arguments\n }\n\n const toolUseBlock: AnthropicContentBlock = {\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.function.name,\n input: parsedInput,\n }\n contentBlocks.push(toolUseBlock)\n }\n\n formattedMessages.push({\n role: 'assistant',\n content: contentBlocks,\n })\n\n continue\n }\n\n if (role === 'assistant') {\n const contentBlocks: AnthropicContentBlocks = []\n this.appendThinkingBlocks(contentBlocks, message.thinking)\n\n if (Array.isArray(message.content)) {\n for (const part of message.content) {\n contentBlocks.push(this.convertContentPartToAnthropic(part))\n }\n } else if (message.content) {\n contentBlocks.push({\n type: 'text',\n text: message.content,\n })\n }\n\n formattedMessages.push({\n role: 'assistant',\n content: contentBlocks.length > 0 ? contentBlocks : '',\n })\n continue\n }\n\n if (role === 'user' && Array.isArray(message.content)) {\n const contentBlocks = message.content.map((part) =>\n this.convertContentPartToAnthropic(part),\n )\n formattedMessages.push({\n role: 'user',\n content: contentBlocks,\n })\n continue\n }\n\n formattedMessages.push({\n role: 'user',\n content:\n typeof message.content === 'string'\n ? message.content\n : message.content\n ? message.content.map((c) =>\n this.convertContentPartToAnthropic(c),\n )\n : '',\n })\n }\n\n // Post-process: Anthropic requires strictly alternating user/assistant roles.\n // Tool results are sent as role:'user' messages, which can create consecutive\n // user messages when followed by a new user message. Merge them.\n return this.mergeConsecutiveSameRoleMessages(formattedMessages)\n }\n\n private appendThinkingBlocks(\n contentBlocks: AnthropicContentBlocks,\n thinkingParts: ModelMessage['thinking'],\n ): void {\n if (!thinkingParts?.length) return\n\n for (const thinking of thinkingParts) {\n if (!thinking.signature) continue\n contentBlocks.push({\n type: 'thinking',\n thinking: thinking.content,\n signature: thinking.signature,\n } as unknown as AnthropicContentBlock)\n }\n }\n\n /**\n * Merge consecutive messages of the same role into a single message.\n * Anthropic's API requires strictly alternating user/assistant roles.\n * Tool results are wrapped as role:'user' messages, which can collide\n * with actual user messages in multi-turn conversations.\n *\n * Also filters out empty assistant messages (e.g., from a previous failed request).\n */\n private mergeConsecutiveSameRoleMessages(\n messages: InternalTextProviderOptions['messages'],\n ): InternalTextProviderOptions['messages'] {\n const merged: InternalTextProviderOptions['messages'] = []\n\n for (const msg of messages) {\n // Skip empty assistant messages (no content or empty string)\n if (msg.role === 'assistant') {\n const hasContent = Array.isArray(msg.content)\n ? msg.content.length > 0\n : typeof msg.content === 'string' && msg.content.length > 0\n if (!hasContent) {\n continue\n }\n }\n\n const prev = merged[merged.length - 1]\n if (prev && prev.role === msg.role) {\n // Normalize both contents to arrays and concatenate\n const prevBlocks = Array.isArray(prev.content)\n ? prev.content\n : typeof prev.content === 'string' && prev.content\n ? [{ type: 'text' as const, text: prev.content }]\n : []\n const msgBlocks = Array.isArray(msg.content)\n ? msg.content\n : typeof msg.content === 'string' && msg.content\n ? [{ type: 'text' as const, text: msg.content }]\n : []\n prev.content = [...prevBlocks, ...msgBlocks]\n } else {\n merged.push({ ...msg })\n }\n }\n\n // De-duplicate tool_result blocks with the same tool_use_id.\n // This can happen when the core layer generates tool results from both\n // the tool-result part and the tool-call part's output field.\n for (const msg of merged) {\n if (Array.isArray(msg.content)) {\n const seenToolResultIds = new Set<string>()\n msg.content = msg.content.filter((block: any) => {\n if (block.type === 'tool_result' && block.tool_use_id) {\n if (seenToolResultIds.has(block.tool_use_id)) {\n return false // Remove duplicate\n }\n seenToolResultIds.add(block.tool_use_id)\n }\n return true\n })\n }\n }\n\n return merged\n }\n\n private async *processAnthropicStream(\n stream: AsyncIterable<Anthropic_SDK.Beta.BetaRawMessageStreamEvent>,\n options: TextOptions<AnthropicTextProviderOptions>,\n genId: () => string,\n logger: InternalLogger,\n ): AsyncIterable<StreamChunk> {\n const model = options.model\n let accumulatedContent = ''\n let accumulatedThinking = ''\n let accumulatedSignature = ''\n const toolCallsMap = new Map<\n number,\n { id: string; name: string; input: string; started: boolean }\n >()\n let currentToolIndex = -1\n\n // AG-UI lifecycle tracking\n const runId = options.runId ?? genId()\n const threadId = options.threadId ?? genId()\n const messageId = genId()\n let stepId: string | null = null\n let reasoningMessageId: string | null = null\n let hasClosedReasoning = false\n let hasEmittedRunStarted = false\n let hasEmittedTextMessageStart = false\n let hasEmittedRunFinished = false\n // Track current content block type for proper content_block_stop handling\n let currentBlockType: string | null = null\n\n try {\n for await (const event of stream) {\n logger.provider(`provider=anthropic type=${event.type}`, {\n chunk: event,\n })\n // Emit RUN_STARTED on first event\n if (!hasEmittedRunStarted) {\n hasEmittedRunStarted = true\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model,\n timestamp: Date.now(),\n parentRunId: options.parentRunId,\n }\n }\n\n if (event.type === 'content_block_start') {\n currentBlockType = event.content_block.type\n if (event.content_block.type === 'tool_use') {\n currentToolIndex++\n toolCallsMap.set(currentToolIndex, {\n id: event.content_block.id,\n name: event.content_block.name,\n input: '',\n started: false,\n })\n } else if (event.content_block.type === 'thinking') {\n accumulatedThinking = ''\n accumulatedSignature = ''\n // Emit REASONING and STEP_STARTED for thinking\n stepId = genId()\n reasoningMessageId = genId()\n\n // Spec REASONING events\n yield {\n type: EventType.REASONING_START,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n yield {\n type: EventType.REASONING_MESSAGE_START,\n messageId: reasoningMessageId,\n role: 'reasoning' as const,\n model,\n timestamp: Date.now(),\n }\n\n // Legacy STEP events (kept during transition)\n yield {\n type: EventType.STEP_STARTED,\n stepName: stepId,\n stepId,\n model,\n timestamp: Date.now(),\n stepType: 'thinking',\n }\n }\n } else if (event.type === 'content_block_delta') {\n if (event.delta.type === 'text_delta') {\n // Close reasoning before text starts\n if (reasoningMessageId && !hasClosedReasoning) {\n hasClosedReasoning = true\n yield {\n type: EventType.REASONING_MESSAGE_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n yield {\n type: EventType.REASONING_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n }\n\n // Emit TEXT_MESSAGE_START on first text content\n if (!hasEmittedTextMessageStart) {\n hasEmittedTextMessageStart = true\n yield {\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n model,\n timestamp: Date.now(),\n role: 'assistant',\n }\n }\n\n const delta = event.delta.text\n accumulatedContent += delta\n yield {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n model,\n timestamp: Date.now(),\n delta,\n content: accumulatedContent,\n }\n } else if (event.delta.type === 'thinking_delta') {\n const delta = event.delta.thinking\n accumulatedThinking += delta\n\n // Spec REASONING content event\n yield {\n type: EventType.REASONING_MESSAGE_CONTENT,\n messageId: reasoningMessageId!,\n delta,\n model,\n timestamp: Date.now(),\n }\n\n // Legacy STEP event\n yield {\n type: EventType.STEP_FINISHED,\n stepName: stepId || genId(),\n stepId: stepId || genId(),\n model,\n timestamp: Date.now(),\n delta,\n content: accumulatedThinking,\n }\n } else if (\n (event.delta as { type: string }).type === 'signature_delta'\n ) {\n accumulatedSignature +=\n (event.delta as { signature: string }).signature || ''\n } else if (event.delta.type === 'input_json_delta') {\n const existing = toolCallsMap.get(currentToolIndex)\n if (existing) {\n // Emit TOOL_CALL_START on first args delta\n if (!existing.started) {\n existing.started = true\n yield {\n type: EventType.TOOL_CALL_START,\n toolCallId: existing.id,\n toolCallName: existing.name,\n toolName: existing.name,\n model,\n timestamp: Date.now(),\n index: currentToolIndex,\n }\n }\n\n existing.input += event.delta.partial_json\n\n yield {\n type: EventType.TOOL_CALL_ARGS,\n toolCallId: existing.id,\n model,\n timestamp: Date.now(),\n delta: event.delta.partial_json,\n args: existing.input,\n }\n }\n }\n } else if (event.type === 'content_block_stop') {\n if (currentBlockType === 'thinking') {\n // Emit signature so it can be replayed in multi-turn context\n if (accumulatedSignature && stepId) {\n yield {\n type: EventType.STEP_FINISHED,\n stepName: stepId,\n stepId,\n model,\n timestamp: Date.now(),\n delta: '',\n content: accumulatedThinking,\n signature: accumulatedSignature,\n }\n }\n } else if (currentBlockType === 'tool_use') {\n const existing = toolCallsMap.get(currentToolIndex)\n if (existing) {\n // If tool call wasn't started yet (no args), start it now\n if (!existing.started) {\n existing.started = true\n yield {\n type: EventType.TOOL_CALL_START,\n toolCallId: existing.id,\n toolCallName: existing.name,\n toolName: existing.name,\n model,\n timestamp: Date.now(),\n index: currentToolIndex,\n }\n }\n\n // Emit TOOL_CALL_END\n let parsedInput: unknown = {}\n try {\n const parsed = existing.input ? JSON.parse(existing.input) : {}\n parsedInput = parsed && typeof parsed === 'object' ? parsed : {}\n } catch {\n parsedInput = {}\n }\n\n yield {\n type: EventType.TOOL_CALL_END,\n toolCallId: existing.id,\n toolCallName: existing.name,\n toolName: existing.name,\n model,\n timestamp: Date.now(),\n input: parsedInput,\n }\n\n // Reset so a new TEXT_MESSAGE_START is emitted if text follows tool calls\n hasEmittedTextMessageStart = false\n }\n } else {\n // Emit TEXT_MESSAGE_END only for text blocks (not tool_use blocks)\n if (hasEmittedTextMessageStart && accumulatedContent) {\n yield {\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n model,\n timestamp: Date.now(),\n }\n }\n }\n currentBlockType = null\n } else if (event.type === 'message_stop') {\n // Close reasoning events if still open\n if (reasoningMessageId && !hasClosedReasoning) {\n hasClosedReasoning = true\n yield {\n type: EventType.REASONING_MESSAGE_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n yield {\n type: EventType.REASONING_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n }\n\n // Only emit RUN_FINISHED from message_stop if message_delta didn't already emit one.\n // message_delta carries the real stop_reason (tool_use, end_turn, etc.),\n // while message_stop is just a completion signal.\n if (!hasEmittedRunFinished) {\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model,\n timestamp: Date.now(),\n finishReason: 'stop',\n }\n }\n } else if (event.type === 'message_delta') {\n if (event.delta.stop_reason) {\n hasEmittedRunFinished = true\n\n // Close reasoning events if still open\n if (reasoningMessageId && !hasClosedReasoning) {\n hasClosedReasoning = true\n yield {\n type: EventType.REASONING_MESSAGE_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n yield {\n type: EventType.REASONING_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n }\n\n switch (event.delta.stop_reason) {\n case 'tool_use': {\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model,\n timestamp: Date.now(),\n finishReason: 'tool_calls',\n usage: {\n promptTokens: event.usage.input_tokens || 0,\n completionTokens: event.usage.output_tokens || 0,\n totalTokens:\n (event.usage.input_tokens || 0) +\n (event.usage.output_tokens || 0),\n },\n }\n break\n }\n case 'max_tokens': {\n yield {\n type: EventType.RUN_ERROR,\n model,\n timestamp: Date.now(),\n message:\n 'The response was cut off because the maximum token limit was reached.',\n code: 'max_tokens',\n error: {\n message:\n 'The response was cut off because the maximum token limit was reached.',\n code: 'max_tokens',\n },\n }\n break\n }\n default: {\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model,\n timestamp: Date.now(),\n finishReason: 'stop',\n usage: {\n promptTokens: event.usage.input_tokens || 0,\n completionTokens: event.usage.output_tokens || 0,\n totalTokens:\n (event.usage.input_tokens || 0) +\n (event.usage.output_tokens || 0),\n },\n }\n }\n }\n }\n }\n }\n } catch (error: unknown) {\n const err = error as Error & { status?: number; code?: string }\n\n logger.errors('anthropic.processAnthropicStream fatal', {\n error,\n source: 'anthropic.processAnthropicStream',\n })\n yield {\n type: EventType.RUN_ERROR,\n model,\n timestamp: Date.now(),\n message: err.message || 'Unknown error occurred',\n code: err.code || String(err.status),\n error: {\n message: err.message || 'Unknown error occurred',\n code: err.code || String(err.status),\n },\n }\n }\n }\n}\n\n/**\n * Creates an Anthropic chat adapter with explicit API key.\n * Type resolution happens here at the call site.\n */\nexport function createAnthropicChat<\n TModel extends (typeof ANTHROPIC_MODELS)[number],\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<AnthropicTextConfig, 'apiKey'>,\n): AnthropicTextAdapter<\n TModel,\n ResolveProviderOptions<TModel>,\n ResolveInputModalities<TModel>\n> {\n return new AnthropicTextAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates an Anthropic text adapter with automatic API key detection.\n * Type resolution happens here at the call site.\n */\nexport function anthropicText<TModel extends (typeof ANTHROPIC_MODELS)[number]>(\n model: TModel,\n config?: Omit<AnthropicTextConfig, 'apiKey'>,\n): AnthropicTextAdapter<\n TModel,\n ResolveProviderOptions<TModel>,\n ResolveInputModalities<TModel>\n> {\n const apiKey = getAnthropicApiKeyFromEnv()\n return createAnthropicChat(model, apiKey, config)\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import { EventType, normalizeSystemPrompts } from '@tanstack/ai'\nimport { BaseTextAdapter } from '@tanstack/ai/adapters'\nimport { convertToolsToProviderFormat } from '../tools/tool-converter'\nimport { validateTextProviderOptions } from '../text/text-provider-options'\nimport {\n createAnthropicClient,\n generateId,\n getAnthropicApiKeyFromEnv,\n} from '../utils'\nimport type {\n ANTHROPIC_MODELS,\n AnthropicChatModelProviderOptionsByName,\n AnthropicChatModelToolCapabilitiesByName,\n AnthropicModelInputModalitiesByName,\n} from '../model-meta'\nimport type {\n StructuredOutputOptions,\n StructuredOutputResult,\n} from '@tanstack/ai/adapters'\nimport type { InternalLogger } from '@tanstack/ai/adapter-internals'\nimport type {\n Base64ImageSource,\n Base64PDFSource,\n ContentBlockParam,\n DocumentBlockParam,\n ImageBlockParam,\n TextBlockParam,\n ThinkingBlockParam,\n ToolUseBlockParam,\n URLImageSource,\n URLPDFSource,\n} from '@anthropic-ai/sdk/resources/messages'\nimport type Anthropic_SDK from '@anthropic-ai/sdk'\nimport type { AnthropicBeta } from '@anthropic-ai/sdk/resources/beta/beta'\nimport type {\n ContentPart,\n Modality,\n ModelMessage,\n StreamChunk,\n TextOptions,\n} from '@tanstack/ai'\nimport type {\n AnthropicSystemPromptMetadata,\n ExternalTextProviderOptions,\n InternalTextProviderOptions,\n} from '../text/text-provider-options'\nimport type {\n AnthropicDocumentMetadata,\n AnthropicImageMetadata,\n AnthropicMessageMetadataByModality,\n AnthropicTextMetadata,\n} from '../message-types'\nimport type { AnthropicClientConfig } from '../utils'\n\n/**\n * Configuration for Anthropic text adapter\n */\nexport interface AnthropicTextConfig extends AnthropicClientConfig {}\n\n/**\n * Anthropic-specific provider options for text/chat\n */\nexport type AnthropicTextProviderOptions = ExternalTextProviderOptions\n\n// ===========================\n// Type Resolution Helpers\n// ===========================\n\n/**\n * Resolve provider options for a specific model.\n * If the model has explicit options in the map, use those; otherwise use base options.\n */\ntype ResolveProviderOptions<TModel extends string> =\n TModel extends keyof AnthropicChatModelProviderOptionsByName\n ? AnthropicChatModelProviderOptionsByName[TModel]\n : AnthropicTextProviderOptions\n\n/**\n * Resolve input modalities for a specific model.\n * If the model has explicit modalities in the map, use those; otherwise use default.\n */\ntype ResolveInputModalities<TModel extends string> =\n TModel extends keyof AnthropicModelInputModalitiesByName\n ? AnthropicModelInputModalitiesByName[TModel]\n : readonly ['text', 'image', 'document']\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof AnthropicChatModelToolCapabilitiesByName\n ? NonNullable<AnthropicChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n// ===========================\n// Adapter Implementation\n// ===========================\n\n/**\n * Anthropic Text (Chat) Adapter\n *\n * Tree-shakeable adapter for Anthropic chat/text completion functionality.\n * Import only what you need for smaller bundle sizes.\n */\nexport class AnthropicTextAdapter<\n TModel extends (typeof ANTHROPIC_MODELS)[number],\n TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends BaseTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n AnthropicMessageMetadataByModality,\n TToolCapabilities,\n // TToolCallMetadata — anthropic has no tool-call metadata round-tripping\n unknown,\n // TSystemPromptMetadata — narrows `systemPrompts[i].metadata` at the\n // chat() call site so users get `cache_control` autocomplete.\n AnthropicSystemPromptMetadata\n> {\n override readonly kind = 'text' as const\n readonly name = 'anthropic' as const\n\n private readonly client: Anthropic_SDK\n\n constructor(config: AnthropicTextConfig, model: TModel) {\n super({}, model)\n this.client = createAnthropicClient(config)\n }\n\n async *chatStream(\n options: TextOptions<TProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n const { logger } = options\n try {\n const requestParams = this.mapCommonOptionsToAnthropic(options)\n\n logger.request(\n `activity=chat provider=anthropic model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,\n { provider: 'anthropic', model: this.model },\n )\n\n // Interleaved thinking is only supported on the beta messages endpoint,\n // so the `betas` flag is attached here rather than in the shared mapper\n // (structuredOutput uses the non-beta endpoint which rejects `betas`).\n const modelOptions = options.modelOptions as\n | InternalTextProviderOptions\n | undefined\n const useInterleavedThinking =\n modelOptions?.thinking?.type === 'enabled' &&\n typeof modelOptions.thinking.budget_tokens === 'number' &&\n modelOptions.thinking.budget_tokens > 0\n const betas: Array<AnthropicBeta> | undefined = useInterleavedThinking\n ? ['interleaved-thinking-2025-05-14']\n : undefined\n\n const stream = await this.client.beta.messages.create(\n { ...requestParams, stream: true, ...(betas && { betas }) },\n {\n signal: options.request?.signal,\n headers: options.request?.headers,\n },\n )\n\n yield* this.processAnthropicStream(\n stream,\n options,\n () => generateId(this.name),\n logger,\n )\n } catch (error: unknown) {\n const err = error as Error & { status?: number; code?: string }\n logger.errors('anthropic.chatStream fatal', {\n error,\n source: 'anthropic.chatStream',\n })\n yield {\n type: EventType.RUN_ERROR,\n model: options.model,\n timestamp: Date.now(),\n message: err.message || 'Unknown error occurred',\n code: err.code || String(err.status),\n error: {\n message: err.message || 'Unknown error occurred',\n code: err.code || String(err.status),\n },\n }\n }\n }\n\n /**\n * Generate structured output using Anthropic's tool-based approach.\n * Anthropic doesn't have native structured output, so we use a tool with the schema\n * and force the model to call it.\n * The outputSchema is already JSON Schema (converted in the ai layer).\n */\n async structuredOutput(\n options: StructuredOutputOptions<TProviderOptions>,\n ): Promise<StructuredOutputResult<unknown>> {\n const { chatOptions, outputSchema } = options\n const { logger } = chatOptions\n\n const requestParams = this.mapCommonOptionsToAnthropic(chatOptions)\n\n // Create a tool that will capture the structured output\n // Anthropic's SDK requires input_schema with type: 'object' literal\n const structuredOutputTool = {\n name: 'structured_output',\n description:\n 'Use this tool to provide your response in the required structured format.',\n input_schema: {\n type: 'object' as const,\n properties: outputSchema.properties ?? {},\n required: outputSchema.required ?? [],\n },\n }\n\n try {\n logger.request(\n `activity=chat provider=anthropic model=${this.model} messages=${chatOptions.messages.length} tools=${chatOptions.tools?.length ?? 0} stream=false`,\n { provider: 'anthropic', model: this.model },\n )\n // Make non-streaming request with tool_choice forced to our structured output tool\n const response = await this.client.messages.create(\n {\n ...requestParams,\n stream: false,\n tools: [structuredOutputTool],\n tool_choice: { type: 'tool', name: 'structured_output' },\n },\n {\n signal: chatOptions.request?.signal,\n headers: chatOptions.request?.headers,\n },\n )\n\n // Extract the tool use content from the response\n let parsed: unknown = null\n let rawText = ''\n\n for (const block of response.content) {\n if (block.type === 'tool_use' && block.name === 'structured_output') {\n parsed = block.input\n rawText = JSON.stringify(block.input)\n break\n }\n }\n\n if (parsed === null) {\n // Fallback: try to extract text content and parse as JSON\n rawText = response.content\n .map((b) => {\n if (b.type === 'text') {\n return b.text\n }\n return ''\n })\n .join('')\n try {\n parsed = JSON.parse(rawText)\n } catch {\n throw new Error(\n `Failed to extract structured output from response. Content: ${rawText.slice(0, 200)}${rawText.length > 200 ? '...' : ''}`,\n )\n }\n }\n\n return {\n data: parsed,\n rawText,\n }\n } catch (error: unknown) {\n const err = error as Error\n logger.errors('anthropic.structuredOutput fatal', {\n error,\n source: 'anthropic.structuredOutput',\n })\n throw new Error(\n `Structured output generation failed: ${err.message || 'Unknown error occurred'}`,\n )\n }\n }\n\n private mapCommonOptionsToAnthropic(\n options: TextOptions<AnthropicTextProviderOptions>,\n ) {\n const modelOptions = options.modelOptions as\n | InternalTextProviderOptions\n | undefined\n\n const formattedMessages = this.formatMessages(options.messages)\n const tools = options.tools\n ? convertToolsToProviderFormat(options.tools)\n : undefined\n\n const validProviderOptions: Partial<InternalTextProviderOptions> = {}\n if (modelOptions) {\n const validKeys: Array<keyof InternalTextProviderOptions> = [\n 'container',\n 'context_management',\n 'effort',\n 'mcp_servers',\n 'service_tier',\n 'stop_sequences',\n 'thinking',\n 'tool_choice',\n 'top_k',\n ]\n const validKeySet = new Set<string>(validKeys)\n const droppedKeys = Object.keys(modelOptions).filter(\n (key) => !validKeySet.has(key),\n )\n if (droppedKeys.length > 0) {\n // Reachable when callers cast around the public type (e.g.\n // `modelOptions: { system: ... } as any`). Without this warning the\n // unknown keys are silently dropped — `system` in particular was a\n // previously-tested path for attaching `cache_control` and we don't\n // want that to fail in production with no signal.\n options.logger.errors(\n `anthropic.mapCommonOptionsToAnthropic dropped unknown modelOptions key(s): ${droppedKeys.join(', ')}`,\n {\n source: 'anthropic.mapCommonOptionsToAnthropic',\n droppedKeys,\n hint: droppedKeys.includes('system')\n ? 'pass system prompts via the top-level `systemPrompts` option; `modelOptions.system` is no longer honored'\n : undefined,\n },\n )\n }\n for (const key of validKeys) {\n if (key in modelOptions) {\n const value = modelOptions[key]\n if (key === 'tool_choice' && typeof value === 'string') {\n ;(validProviderOptions as Record<string, unknown>)[key] = {\n type: value,\n }\n } else {\n ;(validProviderOptions as Record<string, unknown>)[key] = value\n }\n }\n }\n }\n\n const thinkingBudget =\n validProviderOptions.thinking?.type === 'enabled'\n ? validProviderOptions.thinking.budget_tokens\n : undefined\n const defaultMaxTokens = options.maxTokens || 1024\n const maxTokens =\n thinkingBudget && thinkingBudget >= defaultMaxTokens\n ? thinkingBudget + 1\n : defaultMaxTokens\n\n // `InternalTextProviderOptions.system` is typed\n // `string | Array<TextBlockParam>` (no `| undefined`), so build it\n // outside the literal and spread it conditionally rather than\n // assigning `undefined` under exactOptionalPropertyTypes.\n const systemBlocks = ((): Array<TextBlockParam> | undefined => {\n const normalized = normalizeSystemPrompts<AnthropicSystemPromptMetadata>(\n options.systemPrompts,\n )\n if (normalized.length === 0) return undefined\n return normalized.map(\n (p): TextBlockParam => ({\n type: 'text',\n text: p.content,\n ...(p.metadata?.cache_control && {\n cache_control: p.metadata.cache_control,\n }),\n }),\n )\n })()\n // `InternalTextProviderOptions` declares `temperature`, `top_p`,\n // and `tools` as `T?: ...` (no `| undefined`), so spread them\n // conditionally rather than passing explicit `undefined` from the\n // optional common `TextOptions` fields under\n // exactOptionalPropertyTypes.\n const requestParams: InternalTextProviderOptions = {\n model: options.model,\n max_tokens: maxTokens,\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { top_p: options.topP }),\n messages: formattedMessages,\n ...(systemBlocks !== undefined && { system: systemBlocks }),\n ...(tools !== undefined && { tools }),\n ...validProviderOptions,\n }\n validateTextProviderOptions(requestParams)\n return requestParams\n }\n\n private convertContentPartToAnthropic(\n part: ContentPart,\n ): TextBlockParam | ImageBlockParam | DocumentBlockParam {\n switch (part.type) {\n case 'text': {\n const metadata = part.metadata as AnthropicTextMetadata | undefined\n return {\n type: 'text',\n text: part.content,\n ...metadata,\n }\n }\n\n case 'image': {\n const metadata = part.metadata as AnthropicImageMetadata | undefined\n const imageSource: Base64ImageSource | URLImageSource =\n part.source.type === 'data'\n ? {\n type: 'base64',\n data: part.source.value,\n media_type: part.source.mimeType as\n | 'image/jpeg'\n | 'image/png'\n | 'image/gif'\n | 'image/webp',\n }\n : {\n type: 'url',\n url: part.source.value,\n }\n return {\n type: 'image',\n source: imageSource,\n ...metadata,\n }\n }\n case 'document': {\n const metadata = part.metadata as AnthropicDocumentMetadata | undefined\n const docSource: Base64PDFSource | URLPDFSource =\n part.source.type === 'data'\n ? {\n type: 'base64',\n data: part.source.value,\n media_type: part.source.mimeType as 'application/pdf',\n }\n : {\n type: 'url',\n url: part.source.value,\n }\n return {\n type: 'document',\n source: docSource,\n ...metadata,\n }\n }\n case 'audio':\n case 'video':\n throw new Error(\n `Anthropic does not support ${part.type} content directly`,\n )\n default: {\n const _exhaustiveCheck: never = part\n throw new Error(\n `Unsupported content part type: ${(_exhaustiveCheck as ContentPart).type}`,\n )\n }\n }\n }\n\n private formatMessages(\n messages: Array<ModelMessage>,\n ): InternalTextProviderOptions['messages'] {\n const formattedMessages: InternalTextProviderOptions['messages'] = []\n\n for (const message of messages) {\n const role = message.role\n\n if (role === 'tool' && message.toolCallId) {\n formattedMessages.push({\n role: 'user',\n content: [\n {\n type: 'tool_result',\n tool_use_id: message.toolCallId,\n content:\n typeof message.content === 'string' ? message.content : '',\n },\n ],\n })\n continue\n }\n\n if (role === 'assistant' && message.toolCalls?.length) {\n const contentBlocks: Array<ContentBlockParam> = []\n\n this.appendThinkingBlocks(contentBlocks, message.thinking)\n\n if (message.content) {\n const content =\n typeof message.content === 'string' ? message.content : ''\n const textBlock: TextBlockParam = {\n type: 'text',\n text: content,\n }\n contentBlocks.push(textBlock)\n }\n\n for (const toolCall of message.toolCalls) {\n let parsedInput: unknown = {}\n try {\n const parsed = toolCall.function.arguments\n ? JSON.parse(toolCall.function.arguments)\n : {}\n parsedInput = parsed && typeof parsed === 'object' ? parsed : {}\n } catch {\n parsedInput = toolCall.function.arguments\n }\n\n const toolUseBlock: ToolUseBlockParam = {\n type: 'tool_use',\n id: toolCall.id,\n name: toolCall.function.name,\n input: parsedInput,\n }\n contentBlocks.push(toolUseBlock)\n }\n\n formattedMessages.push({\n role: 'assistant',\n content: contentBlocks,\n })\n\n continue\n }\n\n if (role === 'assistant') {\n const contentBlocks: Array<ContentBlockParam> = []\n this.appendThinkingBlocks(contentBlocks, message.thinking)\n\n if (Array.isArray(message.content)) {\n for (const part of message.content) {\n contentBlocks.push(this.convertContentPartToAnthropic(part))\n }\n } else if (message.content) {\n contentBlocks.push({\n type: 'text',\n text: message.content,\n })\n }\n\n formattedMessages.push({\n role: 'assistant',\n content: contentBlocks.length > 0 ? contentBlocks : '',\n })\n continue\n }\n\n if (role === 'user' && Array.isArray(message.content)) {\n const contentBlocks = message.content.map((part) =>\n this.convertContentPartToAnthropic(part),\n )\n formattedMessages.push({\n role: 'user',\n content: contentBlocks,\n })\n continue\n }\n\n formattedMessages.push({\n role: 'user',\n content:\n typeof message.content === 'string'\n ? message.content\n : message.content\n ? message.content.map((c) =>\n this.convertContentPartToAnthropic(c),\n )\n : '',\n })\n }\n\n // Post-process: Anthropic requires strictly alternating user/assistant roles.\n // Tool results are sent as role:'user' messages, which can create consecutive\n // user messages when followed by a new user message. Merge them.\n return this.mergeConsecutiveSameRoleMessages(formattedMessages)\n }\n\n private appendThinkingBlocks(\n contentBlocks: Array<ContentBlockParam>,\n thinkingParts: ModelMessage['thinking'],\n ): void {\n if (!thinkingParts?.length) return\n\n for (const thinking of thinkingParts) {\n if (!thinking.signature) continue\n const block: ThinkingBlockParam = {\n type: 'thinking',\n thinking: thinking.content,\n signature: thinking.signature,\n }\n contentBlocks.push(block)\n }\n }\n\n /**\n * Merge consecutive messages of the same role into a single message.\n * Anthropic's API requires strictly alternating user/assistant roles.\n * Tool results are wrapped as role:'user' messages, which can collide\n * with actual user messages in multi-turn conversations.\n *\n * Also filters out empty assistant messages (e.g., from a previous failed request).\n */\n private mergeConsecutiveSameRoleMessages(\n messages: InternalTextProviderOptions['messages'],\n ): InternalTextProviderOptions['messages'] {\n const merged: InternalTextProviderOptions['messages'] = []\n\n for (const msg of messages) {\n // Skip empty assistant messages (no content or empty string)\n if (msg.role === 'assistant') {\n const hasContent = Array.isArray(msg.content)\n ? msg.content.length > 0\n : typeof msg.content === 'string' && msg.content.length > 0\n if (!hasContent) {\n continue\n }\n }\n\n const prev = merged[merged.length - 1]\n if (prev && prev.role === msg.role) {\n // Normalize both contents to arrays and concatenate\n const prevBlocks = Array.isArray(prev.content)\n ? prev.content\n : typeof prev.content === 'string' && prev.content\n ? [{ type: 'text' as const, text: prev.content }]\n : []\n const msgBlocks = Array.isArray(msg.content)\n ? msg.content\n : typeof msg.content === 'string' && msg.content\n ? [{ type: 'text' as const, text: msg.content }]\n : []\n prev.content = [...prevBlocks, ...msgBlocks]\n } else {\n merged.push({ ...msg })\n }\n }\n\n // De-duplicate tool_result blocks with the same tool_use_id.\n // This can happen when the core layer generates tool results from both\n // the tool-result part and the tool-call part's output field.\n for (const msg of merged) {\n if (Array.isArray(msg.content)) {\n const seenToolResultIds = new Set<string>()\n msg.content = msg.content.filter((block: any) => {\n if (block.type === 'tool_result' && block.tool_use_id) {\n if (seenToolResultIds.has(block.tool_use_id)) {\n return false // Remove duplicate\n }\n seenToolResultIds.add(block.tool_use_id)\n }\n return true\n })\n }\n }\n\n return merged\n }\n\n private async *processAnthropicStream(\n stream: AsyncIterable<Anthropic_SDK.Beta.BetaRawMessageStreamEvent>,\n options: TextOptions<AnthropicTextProviderOptions>,\n genId: () => string,\n logger: InternalLogger,\n ): AsyncIterable<StreamChunk> {\n const model = options.model\n let accumulatedContent = ''\n let accumulatedThinking = ''\n let accumulatedSignature = ''\n const toolCallsMap = new Map<\n number,\n { id: string; name: string; input: string; started: boolean }\n >()\n let currentToolIndex = -1\n\n // AG-UI lifecycle tracking\n const runId = options.runId ?? genId()\n const threadId = options.threadId ?? genId()\n const messageId = genId()\n let stepId: string | null = null\n let reasoningMessageId: string | null = null\n let hasClosedReasoning = false\n let hasEmittedRunStarted = false\n let hasEmittedTextMessageStart = false\n let hasEmittedRunFinished = false\n // Track current content block type for proper content_block_stop handling\n let currentBlockType: string | null = null\n\n try {\n for await (const event of stream) {\n logger.provider(`provider=anthropic type=${event.type}`, {\n chunk: event,\n })\n // Emit RUN_STARTED on first event\n if (!hasEmittedRunStarted) {\n hasEmittedRunStarted = true\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model,\n timestamp: Date.now(),\n parentRunId: options.parentRunId,\n }\n }\n\n if (event.type === 'content_block_start') {\n currentBlockType = event.content_block.type\n if (event.content_block.type === 'tool_use') {\n currentToolIndex++\n toolCallsMap.set(currentToolIndex, {\n id: event.content_block.id,\n name: event.content_block.name,\n input: '',\n started: false,\n })\n } else if (event.content_block.type === 'thinking') {\n accumulatedThinking = ''\n accumulatedSignature = ''\n // Emit REASONING and STEP_STARTED for thinking\n stepId = genId()\n reasoningMessageId = genId()\n\n // Spec REASONING events\n yield {\n type: EventType.REASONING_START,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n yield {\n type: EventType.REASONING_MESSAGE_START,\n messageId: reasoningMessageId,\n role: 'reasoning' as const,\n model,\n timestamp: Date.now(),\n }\n\n // Legacy STEP events (kept during transition)\n yield {\n type: EventType.STEP_STARTED,\n stepName: stepId,\n stepId,\n model,\n timestamp: Date.now(),\n stepType: 'thinking',\n }\n }\n } else if (event.type === 'content_block_delta') {\n if (event.delta.type === 'text_delta') {\n // Close reasoning before text starts\n if (reasoningMessageId && !hasClosedReasoning) {\n hasClosedReasoning = true\n yield {\n type: EventType.REASONING_MESSAGE_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n yield {\n type: EventType.REASONING_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n }\n\n // Emit TEXT_MESSAGE_START on first text content\n if (!hasEmittedTextMessageStart) {\n hasEmittedTextMessageStart = true\n yield {\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n model,\n timestamp: Date.now(),\n role: 'assistant',\n }\n }\n\n const delta = event.delta.text\n accumulatedContent += delta\n yield {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n model,\n timestamp: Date.now(),\n delta,\n content: accumulatedContent,\n }\n } else if (\n event.delta.type === 'thinking_delta' &&\n reasoningMessageId\n ) {\n const delta = event.delta.thinking\n accumulatedThinking += delta\n\n // Spec REASONING content event\n yield {\n type: EventType.REASONING_MESSAGE_CONTENT,\n messageId: reasoningMessageId,\n delta,\n model,\n timestamp: Date.now(),\n }\n\n // Legacy STEP event\n yield {\n type: EventType.STEP_FINISHED,\n stepName: stepId || genId(),\n stepId: stepId || genId(),\n model,\n timestamp: Date.now(),\n delta,\n content: accumulatedThinking,\n }\n } else if (\n (event.delta as { type: string }).type === 'signature_delta'\n ) {\n accumulatedSignature +=\n (event.delta as { signature: string }).signature || ''\n } else if (event.delta.type === 'input_json_delta') {\n const existing = toolCallsMap.get(currentToolIndex)\n if (existing) {\n // Emit TOOL_CALL_START on first args delta\n if (!existing.started) {\n existing.started = true\n yield {\n type: EventType.TOOL_CALL_START,\n toolCallId: existing.id,\n toolCallName: existing.name,\n toolName: existing.name,\n model,\n timestamp: Date.now(),\n index: currentToolIndex,\n }\n }\n\n existing.input += event.delta.partial_json\n\n yield {\n type: EventType.TOOL_CALL_ARGS,\n toolCallId: existing.id,\n model,\n timestamp: Date.now(),\n delta: event.delta.partial_json,\n args: existing.input,\n }\n }\n }\n } else if (event.type === 'content_block_stop') {\n if (currentBlockType === 'thinking') {\n // Emit signature so it can be replayed in multi-turn context\n if (accumulatedSignature && stepId) {\n yield {\n type: EventType.STEP_FINISHED,\n stepName: stepId,\n stepId,\n model,\n timestamp: Date.now(),\n delta: '',\n content: accumulatedThinking,\n signature: accumulatedSignature,\n }\n }\n } else if (currentBlockType === 'tool_use') {\n const existing = toolCallsMap.get(currentToolIndex)\n if (existing) {\n // If tool call wasn't started yet (no args), start it now\n if (!existing.started) {\n existing.started = true\n yield {\n type: EventType.TOOL_CALL_START,\n toolCallId: existing.id,\n toolCallName: existing.name,\n toolName: existing.name,\n model,\n timestamp: Date.now(),\n index: currentToolIndex,\n }\n }\n\n // Emit TOOL_CALL_END\n let parsedInput: unknown = {}\n try {\n const parsed = existing.input ? JSON.parse(existing.input) : {}\n parsedInput = parsed && typeof parsed === 'object' ? parsed : {}\n } catch {\n parsedInput = {}\n }\n\n yield {\n type: EventType.TOOL_CALL_END,\n toolCallId: existing.id,\n toolCallName: existing.name,\n toolName: existing.name,\n model,\n timestamp: Date.now(),\n input: parsedInput,\n }\n\n // Reset so a new TEXT_MESSAGE_START is emitted if text follows tool calls\n hasEmittedTextMessageStart = false\n }\n } else {\n // Emit TEXT_MESSAGE_END only for text blocks (not tool_use blocks)\n if (hasEmittedTextMessageStart && accumulatedContent) {\n yield {\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n model,\n timestamp: Date.now(),\n }\n }\n }\n currentBlockType = null\n } else if (event.type === 'message_stop') {\n // Close reasoning events if still open\n if (reasoningMessageId && !hasClosedReasoning) {\n hasClosedReasoning = true\n yield {\n type: EventType.REASONING_MESSAGE_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n yield {\n type: EventType.REASONING_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n }\n\n // Only emit RUN_FINISHED from message_stop if message_delta didn't already emit one.\n // message_delta carries the real stop_reason (tool_use, end_turn, etc.),\n // while message_stop is just a completion signal.\n if (!hasEmittedRunFinished) {\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model,\n timestamp: Date.now(),\n finishReason: 'stop',\n }\n }\n } else if (event.type === 'message_delta') {\n if (event.delta.stop_reason) {\n hasEmittedRunFinished = true\n\n // Close reasoning events if still open\n if (reasoningMessageId && !hasClosedReasoning) {\n hasClosedReasoning = true\n yield {\n type: EventType.REASONING_MESSAGE_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n yield {\n type: EventType.REASONING_END,\n messageId: reasoningMessageId,\n model,\n timestamp: Date.now(),\n }\n }\n\n switch (event.delta.stop_reason) {\n case 'tool_use': {\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model,\n timestamp: Date.now(),\n finishReason: 'tool_calls',\n usage: {\n promptTokens: event.usage.input_tokens || 0,\n completionTokens: event.usage.output_tokens || 0,\n totalTokens:\n (event.usage.input_tokens || 0) +\n (event.usage.output_tokens || 0),\n },\n }\n break\n }\n case 'max_tokens': {\n yield {\n type: EventType.RUN_ERROR,\n model,\n timestamp: Date.now(),\n message:\n 'The response was cut off because the maximum token limit was reached.',\n code: 'max_tokens',\n error: {\n message:\n 'The response was cut off because the maximum token limit was reached.',\n code: 'max_tokens',\n },\n }\n break\n }\n case 'stop_sequence':\n case 'end_turn':\n case 'pause_turn':\n case 'refusal':\n case 'model_context_window_exceeded':\n default: {\n // All remaining Anthropic stop_reason variants map to the\n // generic \"stop\" finish reason — they describe *why* the\n // stream ended, but for AG-UI consumers the resulting event\n // shape is identical.\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model,\n timestamp: Date.now(),\n finishReason: 'stop',\n usage: {\n promptTokens: event.usage.input_tokens || 0,\n completionTokens: event.usage.output_tokens || 0,\n totalTokens:\n (event.usage.input_tokens || 0) +\n (event.usage.output_tokens || 0),\n },\n }\n }\n }\n }\n }\n }\n } catch (error: unknown) {\n const err = error as Error & { status?: number; code?: string }\n\n logger.errors('anthropic.processAnthropicStream fatal', {\n error,\n source: 'anthropic.processAnthropicStream',\n })\n yield {\n type: EventType.RUN_ERROR,\n model,\n timestamp: Date.now(),\n message: err.message || 'Unknown error occurred',\n code: err.code || String(err.status),\n error: {\n message: err.message || 'Unknown error occurred',\n code: err.code || String(err.status),\n },\n }\n }\n }\n}\n\n/**\n * Creates an Anthropic chat adapter with explicit API key.\n * Type resolution happens here at the call site.\n */\nexport function createAnthropicChat<\n TModel extends (typeof ANTHROPIC_MODELS)[number],\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<AnthropicTextConfig, 'apiKey'>,\n): AnthropicTextAdapter<\n TModel,\n ResolveProviderOptions<TModel>,\n ResolveInputModalities<TModel>\n> {\n return new AnthropicTextAdapter({ apiKey, ...config }, model)\n}\n\n/**\n * Creates an Anthropic text adapter with automatic API key detection.\n * Type resolution happens here at the call site.\n */\nexport function anthropicText<TModel extends (typeof ANTHROPIC_MODELS)[number]>(\n model: TModel,\n config?: Omit<AnthropicTextConfig, 'apiKey'>,\n): AnthropicTextAdapter<\n TModel,\n ResolveProviderOptions<TModel>,\n ResolveInputModalities<TModel>\n> {\n const apiKey = getAnthropicApiKeyFromEnv()\n return createAnthropicChat(model, apiKey, config)\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AnthropicTextAdapter, anthropicText, createAnthropicChat, type AnthropicTextConfig, type AnthropicTextProviderOptions, } from './adapters/text.js';
|
|
2
|
+
export type { AnthropicSystemPromptMetadata } from './text/text-provider-options.js';
|
|
2
3
|
export { anthropicSummarize, createAnthropicSummarize, type AnthropicSummarizeConfig, type AnthropicSummarizeModel, } from './adapters/summarize.js';
|
|
3
4
|
export type { AnthropicChatModel, AnthropicChatModelProviderOptionsByName, AnthropicChatModelToolCapabilitiesByName, AnthropicModelInputModalitiesByName, } from './model-meta.js';
|
|
4
5
|
export { ANTHROPIC_MODELS } from './model-meta.js';
|
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
import { BetaContextManagementConfig, BetaToolChoiceAny, BetaToolChoiceAuto, BetaToolChoiceTool } from '@anthropic-ai/sdk/resources/beta/messages/messages';
|
|
2
|
+
import { CacheControlEphemeral } from '@anthropic-ai/sdk/resources';
|
|
2
3
|
import { AnthropicTool } from '../tools.js';
|
|
3
4
|
import { MessageParam, TextBlockParam } from '@anthropic-ai/sdk/resources/messages';
|
|
5
|
+
/**
|
|
6
|
+
* Per-prompt metadata Anthropic understands on `systemPrompts` entries.
|
|
7
|
+
*
|
|
8
|
+
* Used via the structured form of `systemPrompts`:
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* import type { AnthropicSystemPromptMetadata } from '@tanstack/ai-anthropic'
|
|
12
|
+
*
|
|
13
|
+
* chat({
|
|
14
|
+
* adapter: anthropicText(),
|
|
15
|
+
* model: 'claude-sonnet-4-6',
|
|
16
|
+
* systemPrompts: [
|
|
17
|
+
* {
|
|
18
|
+
* content: 'Stable instructions — cache me.',
|
|
19
|
+
* metadata: { cache_control: { type: 'ephemeral' } } satisfies AnthropicSystemPromptMetadata,
|
|
20
|
+
* },
|
|
21
|
+
* 'Volatile per-request instruction.',
|
|
22
|
+
* ],
|
|
23
|
+
* })
|
|
24
|
+
*/
|
|
25
|
+
export interface AnthropicSystemPromptMetadata {
|
|
26
|
+
/**
|
|
27
|
+
* Anthropic prompt-caching control applied to this system prompt's
|
|
28
|
+
* `TextBlockParam`.
|
|
29
|
+
*
|
|
30
|
+
* @see https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching
|
|
31
|
+
*/
|
|
32
|
+
cache_control?: CacheControlEphemeral;
|
|
33
|
+
}
|
|
4
34
|
export interface AnthropicContainerOptions {
|
|
5
35
|
/**
|
|
6
36
|
* Container identifier for reuse across requests.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-provider-options.js","sources":["../../../src/text/text-provider-options.ts"],"sourcesContent":["import type {\n BetaContextManagementConfig,\n BetaToolChoiceAny,\n BetaToolChoiceAuto,\n BetaToolChoiceTool,\n} from '@anthropic-ai/sdk/resources/beta/messages/messages'\nimport type { AnthropicTool } from '../tools'\nimport type {\n MessageParam,\n TextBlockParam,\n} from '@anthropic-ai/sdk/resources/messages'\n\nexport interface AnthropicContainerOptions {\n /**\n * Container identifier for reuse across requests.\n * Container parameters with skills to be loaded.\n */\n container?: {\n id: string | null\n /**\n * List of skills to load into the container\n */\n skills: Array<{\n /**\n * Between 1-64 characters\n */\n skill_id: string\n\n type: 'anthropic' | 'custom'\n /**\n * Skill version or latest by default\n */\n version?: string\n }> | null\n } | null\n}\n\nexport interface AnthropicContextManagementOptions {\n /**\n * Context management configuration.\n\nThis allows you to control how Claude manages context across multiple requests, such as whether to clear function results or not.\n */\n context_management?: BetaContextManagementConfig | null\n}\n\nexport interface AnthropicMCPOptions {\n /**\n * MCP servers to be utilized in this request\n * Maximum of 20 servers\n */\n mcp_servers?: Array<MCPServer>\n}\n\nexport interface AnthropicServiceTierOptions {\n /**\n * Determines whether to use priority capacity (if available) or standard capacity for this request.\n */\n service_tier?: 'auto' | 'standard_only'\n}\n\nexport interface AnthropicStopSequencesOptions {\n /**\n * Custom text sequences that will cause the model to stop generating.\n\nAnthropic models will normally stop when they have naturally completed their turn, which will result in a response stop_reason of \"end_turn\".\n\nIf you want the model to stop generating when it encounters custom strings of text, you can use the stop_sequences parameter. If the model encounters one of the custom sequences, the response stop_reason value will be \"stop_sequence\" and the response stop_sequence value will contain the matched stop sequence.\n */\n stop_sequences?: Array<string>\n}\n\nexport interface AnthropicThinkingOptions {\n /**\n * Configuration for enabling Claude's extended thinking.\n\nWhen enabled, responses include thinking content blocks showing Claude's thinking process before the final answer. Requires a minimum budget of 1,024 tokens and counts towards your max_tokens limit.\n */\n thinking?:\n | {\n /**\n* Determines how many tokens Claude can use for its internal reasoning process. Larger budgets can enable more thorough analysis for complex problems, improving response quality.\n\nMust be ≥1024 and less than max_tokens\n*/\n budget_tokens: number\n\n type: 'enabled'\n }\n | {\n type: 'disabled'\n }\n}\n\nexport interface AnthropicAdaptiveThinkingOptions {\n /**\n * Configuration for Claude's adaptive thinking (Opus 4.6+).\n *\n * In adaptive mode, Claude dynamically decides when and how much to think.\n * Use the effort parameter to control thinking depth.\n * `thinking: {type: \"enabled\"}` with `budget_tokens` is deprecated on Opus 4.6.\n */\n thinking?:\n | {\n type: 'adaptive'\n }\n | {\n /**\n * @deprecated Use `type: 'adaptive'` with the effort parameter on Opus 4.6+.\n */\n budget_tokens: number\n type: 'enabled'\n }\n | {\n type: 'disabled'\n }\n}\n\nexport interface AnthropicEffortOptions {\n /**\n * Controls the thinking depth for adaptive thinking mode (Opus 4.6+).\n *\n * - `max`: Absolute highest capability\n * - `high`: Default - Claude will almost always think\n * - `medium`: Balanced cost-quality\n * - `low`: May skip thinking for simpler problems\n */\n effort?: 'max' | 'high' | 'medium' | 'low'\n}\n\nexport interface AnthropicToolChoiceOptions {\n tool_choice?: BetaToolChoiceAny | BetaToolChoiceTool | BetaToolChoiceAuto\n}\n\nexport interface AnthropicSamplingOptions {\n /**\n * Only sample from the top K options for each subsequent token.\n\nUsed to remove \"long tail\" low probability responses.\nRecommended for advanced use cases only. You usually only need to use temperature.\n\nRequired range: x >= 0\n */\n top_k?: number\n}\n\nexport type ExternalTextProviderOptions = AnthropicContainerOptions &\n AnthropicContextManagementOptions &\n AnthropicMCPOptions &\n AnthropicServiceTierOptions &\n AnthropicStopSequencesOptions &\n AnthropicThinkingOptions &\n AnthropicToolChoiceOptions &\n AnthropicSamplingOptions &\n Partial<AnthropicAdaptiveThinkingOptions> &\n Partial<AnthropicEffortOptions>\n\nexport interface InternalTextProviderOptions extends ExternalTextProviderOptions {\n model: string\n\n messages: Array<MessageParam>\n\n /**\n * The maximum number of tokens to generate before stopping. This parameter only specifies the absolute maximum number of tokens to generate.\n * Range x >= 1.\n */\n max_tokens: number\n /**\n * Whether to incrementally stream the response using server-sent events.\n */\n stream?: boolean\n /**\n * System prompt — built by the adapter from the user-facing\n * `systemPrompts: Array<string>` on the chat call. This field is internal:\n * users should pass system prompts via `systemPrompts`, not via\n * `modelOptions`.\n *\n * A system prompt is a way of providing context and instructions to Claude,\n * such as specifying a particular goal or role.\n */\n system?: string | Array<TextBlockParam>\n /**\n * Amount of randomness injected into the response.\n * Either use this or top_p, but not both.\n * Defaults to 1.0. Ranges from 0.0 to 1.0. Use temperature closer to 0.0 for analytical / multiple choice, and closer to 1.0 for creative and generative tasks.\n * @default 1.0\n */\n temperature?: number\n\n tools?: Array<AnthropicTool>\n\n /**\n * Use nucleus sampling.\n\nIn nucleus sampling, we compute the cumulative distribution over all the options for each subsequent token in decreasing probability order and cut it off once it reaches a particular probability specified by top_p. You should either alter temperature or top_p, but not both.\n */\n top_p?: number\n}\n\nconst validateTopPandTemperature = (options: InternalTextProviderOptions) => {\n if (options.top_p !== undefined && options.temperature !== undefined) {\n throw new Error('You should either set top_p or temperature, but not both.')\n }\n}\n\nexport interface CacheControl {\n type: 'ephemeral'\n ttl: '5m' | '1h'\n}\n\nconst validateThinking = (options: InternalTextProviderOptions) => {\n const thinking = options.thinking\n if (thinking && thinking.type === 'enabled') {\n if (thinking.budget_tokens < 1024) {\n throw new Error('thinking.budget_tokens must be at least 1024.')\n }\n if (thinking.budget_tokens >= options.max_tokens) {\n throw new Error('thinking.budget_tokens must be less than max_tokens.')\n }\n }\n}\n\ninterface MCPServer {\n name: string\n url: string\n type: 'url'\n authorization_token?: string | null\n tool_configuration: {\n allowed_tools?: Array<string> | null\n enabled?: boolean | null\n } | null\n}\n\nconst validateMaxTokens = (options: InternalTextProviderOptions) => {\n if (options.max_tokens < 1) {\n throw new Error('max_tokens must be at least 1.')\n }\n}\n\nexport const validateTextProviderOptions = (\n options: InternalTextProviderOptions,\n) => {\n validateTopPandTemperature(options)\n validateThinking(options)\n validateMaxTokens(options)\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"text-provider-options.js","sources":["../../../src/text/text-provider-options.ts"],"sourcesContent":["import type {\n BetaContextManagementConfig,\n BetaToolChoiceAny,\n BetaToolChoiceAuto,\n BetaToolChoiceTool,\n} from '@anthropic-ai/sdk/resources/beta/messages/messages'\nimport type { CacheControlEphemeral } from '@anthropic-ai/sdk/resources'\nimport type { AnthropicTool } from '../tools'\nimport type {\n MessageParam,\n TextBlockParam,\n} from '@anthropic-ai/sdk/resources/messages'\n\n/**\n * Per-prompt metadata Anthropic understands on `systemPrompts` entries.\n *\n * Used via the structured form of `systemPrompts`:\n *\n * @example\n * import type { AnthropicSystemPromptMetadata } from '@tanstack/ai-anthropic'\n *\n * chat({\n * adapter: anthropicText(),\n * model: 'claude-sonnet-4-6',\n * systemPrompts: [\n * {\n * content: 'Stable instructions — cache me.',\n * metadata: { cache_control: { type: 'ephemeral' } } satisfies AnthropicSystemPromptMetadata,\n * },\n * 'Volatile per-request instruction.',\n * ],\n * })\n */\nexport interface AnthropicSystemPromptMetadata {\n /**\n * Anthropic prompt-caching control applied to this system prompt's\n * `TextBlockParam`.\n *\n * @see https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching\n */\n cache_control?: CacheControlEphemeral\n}\n\nexport interface AnthropicContainerOptions {\n /**\n * Container identifier for reuse across requests.\n * Container parameters with skills to be loaded.\n */\n container?: {\n id: string | null\n /**\n * List of skills to load into the container\n */\n skills: Array<{\n /**\n * Between 1-64 characters\n */\n skill_id: string\n\n type: 'anthropic' | 'custom'\n /**\n * Skill version or latest by default\n */\n version?: string\n }> | null\n } | null\n}\n\nexport interface AnthropicContextManagementOptions {\n /**\n * Context management configuration.\n\nThis allows you to control how Claude manages context across multiple requests, such as whether to clear function results or not.\n */\n context_management?: BetaContextManagementConfig | null\n}\n\nexport interface AnthropicMCPOptions {\n /**\n * MCP servers to be utilized in this request\n * Maximum of 20 servers\n */\n mcp_servers?: Array<MCPServer>\n}\n\nexport interface AnthropicServiceTierOptions {\n /**\n * Determines whether to use priority capacity (if available) or standard capacity for this request.\n */\n service_tier?: 'auto' | 'standard_only'\n}\n\nexport interface AnthropicStopSequencesOptions {\n /**\n * Custom text sequences that will cause the model to stop generating.\n\nAnthropic models will normally stop when they have naturally completed their turn, which will result in a response stop_reason of \"end_turn\".\n\nIf you want the model to stop generating when it encounters custom strings of text, you can use the stop_sequences parameter. If the model encounters one of the custom sequences, the response stop_reason value will be \"stop_sequence\" and the response stop_sequence value will contain the matched stop sequence.\n */\n stop_sequences?: Array<string>\n}\n\nexport interface AnthropicThinkingOptions {\n /**\n * Configuration for enabling Claude's extended thinking.\n\nWhen enabled, responses include thinking content blocks showing Claude's thinking process before the final answer. Requires a minimum budget of 1,024 tokens and counts towards your max_tokens limit.\n */\n thinking?:\n | {\n /**\n* Determines how many tokens Claude can use for its internal reasoning process. Larger budgets can enable more thorough analysis for complex problems, improving response quality.\n\nMust be ≥1024 and less than max_tokens\n*/\n budget_tokens: number\n\n type: 'enabled'\n }\n | {\n type: 'disabled'\n }\n}\n\nexport interface AnthropicAdaptiveThinkingOptions {\n /**\n * Configuration for Claude's adaptive thinking (Opus 4.6+).\n *\n * In adaptive mode, Claude dynamically decides when and how much to think.\n * Use the effort parameter to control thinking depth.\n * `thinking: {type: \"enabled\"}` with `budget_tokens` is deprecated on Opus 4.6.\n */\n thinking?:\n | {\n type: 'adaptive'\n }\n | {\n /**\n * @deprecated Use `type: 'adaptive'` with the effort parameter on Opus 4.6+.\n */\n budget_tokens: number\n type: 'enabled'\n }\n | {\n type: 'disabled'\n }\n}\n\nexport interface AnthropicEffortOptions {\n /**\n * Controls the thinking depth for adaptive thinking mode (Opus 4.6+).\n *\n * - `max`: Absolute highest capability\n * - `high`: Default - Claude will almost always think\n * - `medium`: Balanced cost-quality\n * - `low`: May skip thinking for simpler problems\n */\n effort?: 'max' | 'high' | 'medium' | 'low'\n}\n\nexport interface AnthropicToolChoiceOptions {\n tool_choice?: BetaToolChoiceAny | BetaToolChoiceTool | BetaToolChoiceAuto\n}\n\nexport interface AnthropicSamplingOptions {\n /**\n * Only sample from the top K options for each subsequent token.\n\nUsed to remove \"long tail\" low probability responses.\nRecommended for advanced use cases only. You usually only need to use temperature.\n\nRequired range: x >= 0\n */\n top_k?: number\n}\n\nexport type ExternalTextProviderOptions = AnthropicContainerOptions &\n AnthropicContextManagementOptions &\n AnthropicMCPOptions &\n AnthropicServiceTierOptions &\n AnthropicStopSequencesOptions &\n AnthropicThinkingOptions &\n AnthropicToolChoiceOptions &\n AnthropicSamplingOptions &\n Partial<AnthropicAdaptiveThinkingOptions> &\n Partial<AnthropicEffortOptions>\n\nexport interface InternalTextProviderOptions extends ExternalTextProviderOptions {\n model: string\n\n messages: Array<MessageParam>\n\n /**\n * The maximum number of tokens to generate before stopping. This parameter only specifies the absolute maximum number of tokens to generate.\n * Range x >= 1.\n */\n max_tokens: number\n /**\n * Whether to incrementally stream the response using server-sent events.\n */\n stream?: boolean\n /**\n * System prompt — built by the adapter from the user-facing\n * `systemPrompts: Array<string>` on the chat call. This field is internal:\n * users should pass system prompts via `systemPrompts`, not via\n * `modelOptions`.\n *\n * A system prompt is a way of providing context and instructions to Claude,\n * such as specifying a particular goal or role.\n */\n system?: string | Array<TextBlockParam>\n /**\n * Amount of randomness injected into the response.\n * Either use this or top_p, but not both.\n * Defaults to 1.0. Ranges from 0.0 to 1.0. Use temperature closer to 0.0 for analytical / multiple choice, and closer to 1.0 for creative and generative tasks.\n * @default 1.0\n */\n temperature?: number\n\n tools?: Array<AnthropicTool>\n\n /**\n * Use nucleus sampling.\n\nIn nucleus sampling, we compute the cumulative distribution over all the options for each subsequent token in decreasing probability order and cut it off once it reaches a particular probability specified by top_p. You should either alter temperature or top_p, but not both.\n */\n top_p?: number\n}\n\nconst validateTopPandTemperature = (options: InternalTextProviderOptions) => {\n if (options.top_p !== undefined && options.temperature !== undefined) {\n throw new Error('You should either set top_p or temperature, but not both.')\n }\n}\n\nexport interface CacheControl {\n type: 'ephemeral'\n ttl: '5m' | '1h'\n}\n\nconst validateThinking = (options: InternalTextProviderOptions) => {\n const thinking = options.thinking\n if (thinking && thinking.type === 'enabled') {\n if (thinking.budget_tokens < 1024) {\n throw new Error('thinking.budget_tokens must be at least 1024.')\n }\n if (thinking.budget_tokens >= options.max_tokens) {\n throw new Error('thinking.budget_tokens must be less than max_tokens.')\n }\n }\n}\n\ninterface MCPServer {\n name: string\n url: string\n type: 'url'\n authorization_token?: string | null\n tool_configuration: {\n allowed_tools?: Array<string> | null\n enabled?: boolean | null\n } | null\n}\n\nconst validateMaxTokens = (options: InternalTextProviderOptions) => {\n if (options.max_tokens < 1) {\n throw new Error('max_tokens must be at least 1.')\n }\n}\n\nexport const validateTextProviderOptions = (\n options: InternalTextProviderOptions,\n) => {\n validateTopPandTemperature(options)\n validateThinking(options)\n validateMaxTokens(options)\n}\n"],"names":[],"mappings":"AAsOA,MAAM,6BAA6B,CAAC,YAAyC;AAC3E,MAAI,QAAQ,UAAU,UAAa,QAAQ,gBAAgB,QAAW;AACpE,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACF;AAOA,MAAM,mBAAmB,CAAC,YAAyC;AACjE,QAAM,WAAW,QAAQ;AACzB,MAAI,YAAY,SAAS,SAAS,WAAW;AAC3C,QAAI,SAAS,gBAAgB,MAAM;AACjC,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AACA,QAAI,SAAS,iBAAiB,QAAQ,YAAY;AAChD,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAAA,EACF;AACF;AAaA,MAAM,oBAAoB,CAAC,YAAyC;AAClE,MAAI,QAAQ,aAAa,GAAG;AAC1B,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AACF;AAEO,MAAM,8BAA8B,CACzC,YACG;AACH,6BAA2B,OAAO;AAClC,mBAAiB,OAAO;AACxB,oBAAkB,OAAO;AAC3B;"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
function convertBashToolToAdapterFormat(tool) {
|
|
2
3
|
const metadata = tool.metadata;
|
|
3
4
|
return metadata;
|
|
4
5
|
}
|
|
5
6
|
function bashTool(config) {
|
|
6
|
-
return {
|
|
7
|
+
return brandProviderTool({
|
|
7
8
|
name: "bash",
|
|
8
9
|
description: "",
|
|
9
10
|
metadata: config
|
|
10
|
-
};
|
|
11
|
+
});
|
|
11
12
|
}
|
|
12
13
|
export {
|
|
13
14
|
bashTool,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-tool.js","sources":["../../../src/tools/bash-tool.ts"],"sourcesContent":["import type {\n BetaToolBash20241022,\n BetaToolBash20250124,\n} from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type BashToolConfig = BetaToolBash20241022 | BetaToolBash20250124\n\n/** @deprecated Renamed to `BashToolConfig`. Will be removed in a future release. */\nexport type BashTool = BashToolConfig\n\nexport type AnthropicBashTool = ProviderTool<'anthropic', 'bash'>\n\nexport function convertBashToolToAdapterFormat(tool: Tool): BashToolConfig {\n const metadata = tool.metadata as BashToolConfig\n return metadata\n}\n\nexport function bashTool(config: BashToolConfig): AnthropicBashTool {\n
|
|
1
|
+
{"version":3,"file":"bash-tool.js","sources":["../../../src/tools/bash-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type {\n BetaToolBash20241022,\n BetaToolBash20250124,\n} from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type BashToolConfig = BetaToolBash20241022 | BetaToolBash20250124\n\n/** @deprecated Renamed to `BashToolConfig`. Will be removed in a future release. */\nexport type BashTool = BashToolConfig\n\nexport type AnthropicBashTool = ProviderTool<'anthropic', 'bash'>\n\nexport function convertBashToolToAdapterFormat(tool: Tool): BashToolConfig {\n const metadata = tool.metadata as BashToolConfig\n return metadata\n}\n\nexport function bashTool(config: BashToolConfig): AnthropicBashTool {\n return brandProviderTool<AnthropicBashTool>({\n name: 'bash',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAcO,SAAS,+BAA+B,MAA4B;AACzE,QAAM,WAAW,KAAK;AACtB,SAAO;AACT;AAEO,SAAS,SAAS,QAA2C;AAClE,SAAO,kBAAqC;AAAA,IAC1C,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
function convertCodeExecutionToolToAdapterFormat(tool) {
|
|
2
3
|
const metadata = tool.metadata;
|
|
3
4
|
return metadata;
|
|
4
5
|
}
|
|
5
6
|
function codeExecutionTool(config) {
|
|
6
|
-
return {
|
|
7
|
+
return brandProviderTool({
|
|
7
8
|
name: "code_execution",
|
|
8
9
|
description: "",
|
|
9
10
|
metadata: config
|
|
10
|
-
};
|
|
11
|
+
});
|
|
11
12
|
}
|
|
12
13
|
export {
|
|
13
14
|
codeExecutionTool,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-execution-tool.js","sources":["../../../src/tools/code-execution-tool.ts"],"sourcesContent":["import type {\n BetaCodeExecutionTool20250522,\n BetaCodeExecutionTool20250825,\n} from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type CodeExecutionToolConfig =\n | BetaCodeExecutionTool20250522\n | BetaCodeExecutionTool20250825\n\n/** @deprecated Renamed to `CodeExecutionToolConfig`. Will be removed in a future release. */\nexport type CodeExecutionTool = CodeExecutionToolConfig\n\nexport type AnthropicCodeExecutionTool = ProviderTool<\n 'anthropic',\n 'code_execution'\n>\n\nexport function convertCodeExecutionToolToAdapterFormat(\n tool: Tool,\n): CodeExecutionToolConfig {\n const metadata = tool.metadata as CodeExecutionToolConfig\n return metadata\n}\n\nexport function codeExecutionTool(\n config: CodeExecutionToolConfig,\n): AnthropicCodeExecutionTool {\n
|
|
1
|
+
{"version":3,"file":"code-execution-tool.js","sources":["../../../src/tools/code-execution-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type {\n BetaCodeExecutionTool20250522,\n BetaCodeExecutionTool20250825,\n} from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type CodeExecutionToolConfig =\n | BetaCodeExecutionTool20250522\n | BetaCodeExecutionTool20250825\n\n/** @deprecated Renamed to `CodeExecutionToolConfig`. Will be removed in a future release. */\nexport type CodeExecutionTool = CodeExecutionToolConfig\n\nexport type AnthropicCodeExecutionTool = ProviderTool<\n 'anthropic',\n 'code_execution'\n>\n\nexport function convertCodeExecutionToolToAdapterFormat(\n tool: Tool,\n): CodeExecutionToolConfig {\n const metadata = tool.metadata as CodeExecutionToolConfig\n return metadata\n}\n\nexport function codeExecutionTool(\n config: CodeExecutionToolConfig,\n): AnthropicCodeExecutionTool {\n return brandProviderTool<AnthropicCodeExecutionTool>({\n name: 'code_execution',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAmBO,SAAS,wCACd,MACyB;AACzB,QAAM,WAAW,KAAK;AACtB,SAAO;AACT;AAEO,SAAS,kBACd,QAC4B;AAC5B,SAAO,kBAA8C;AAAA,IACnD,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
function convertComputerUseToolToAdapterFormat(tool) {
|
|
2
3
|
const metadata = tool.metadata;
|
|
3
4
|
return metadata;
|
|
4
5
|
}
|
|
5
6
|
function computerUseTool(config) {
|
|
6
|
-
return {
|
|
7
|
+
return brandProviderTool({
|
|
7
8
|
name: "computer",
|
|
8
9
|
description: "",
|
|
9
10
|
metadata: config
|
|
10
|
-
};
|
|
11
|
+
});
|
|
11
12
|
}
|
|
12
13
|
export {
|
|
13
14
|
computerUseTool,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computer-use-tool.js","sources":["../../../src/tools/computer-use-tool.ts"],"sourcesContent":["import type {\n BetaToolComputerUse20241022,\n BetaToolComputerUse20250124,\n} from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type ComputerUseToolConfig =\n | BetaToolComputerUse20241022\n | BetaToolComputerUse20250124\n\n/** @deprecated Renamed to `ComputerUseToolConfig`. Will be removed in a future release. */\nexport type ComputerUseTool = ComputerUseToolConfig\n\nexport type AnthropicComputerUseTool = ProviderTool<'anthropic', 'computer_use'>\n\nexport function convertComputerUseToolToAdapterFormat(\n tool: Tool,\n): ComputerUseToolConfig {\n const metadata = tool.metadata as ComputerUseToolConfig\n return metadata\n}\n\nexport function computerUseTool(\n config: ComputerUseToolConfig,\n): AnthropicComputerUseTool {\n
|
|
1
|
+
{"version":3,"file":"computer-use-tool.js","sources":["../../../src/tools/computer-use-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type {\n BetaToolComputerUse20241022,\n BetaToolComputerUse20250124,\n} from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type ComputerUseToolConfig =\n | BetaToolComputerUse20241022\n | BetaToolComputerUse20250124\n\n/** @deprecated Renamed to `ComputerUseToolConfig`. Will be removed in a future release. */\nexport type ComputerUseTool = ComputerUseToolConfig\n\nexport type AnthropicComputerUseTool = ProviderTool<'anthropic', 'computer_use'>\n\nexport function convertComputerUseToolToAdapterFormat(\n tool: Tool,\n): ComputerUseToolConfig {\n const metadata = tool.metadata as ComputerUseToolConfig\n return metadata\n}\n\nexport function computerUseTool(\n config: ComputerUseToolConfig,\n): AnthropicComputerUseTool {\n return brandProviderTool<AnthropicComputerUseTool>({\n name: 'computer',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAgBO,SAAS,sCACd,MACuB;AACvB,QAAM,WAAW,KAAK;AACtB,SAAO;AACT;AAEO,SAAS,gBACd,QAC0B;AAC1B,SAAO,kBAA4C;AAAA,IACjD,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
function convertMemoryToolToAdapterFormat(tool) {
|
|
2
3
|
const metadata = tool.metadata;
|
|
3
4
|
return {
|
|
@@ -6,11 +7,11 @@ function convertMemoryToolToAdapterFormat(tool) {
|
|
|
6
7
|
};
|
|
7
8
|
}
|
|
8
9
|
function memoryTool(config) {
|
|
9
|
-
return {
|
|
10
|
+
return brandProviderTool({
|
|
10
11
|
name: "memory",
|
|
11
12
|
description: "",
|
|
12
13
|
metadata: config
|
|
13
|
-
};
|
|
14
|
+
});
|
|
14
15
|
}
|
|
15
16
|
export {
|
|
16
17
|
convertMemoryToolToAdapterFormat,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-tool.js","sources":["../../../src/tools/memory-tool.ts"],"sourcesContent":["import type { BetaMemoryTool20250818 } from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type MemoryToolConfig = BetaMemoryTool20250818\n\n/** @deprecated Renamed to `MemoryToolConfig`. Will be removed in a future release. */\nexport type MemoryTool = MemoryToolConfig\n\nexport type AnthropicMemoryTool = ProviderTool<'anthropic', 'memory'>\n\nexport function convertMemoryToolToAdapterFormat(tool: Tool): MemoryToolConfig {\n const metadata = tool.metadata as Omit<MemoryToolConfig, 'type'>\n return {\n type: 'memory_20250818',\n ...metadata,\n }\n}\n\nexport function memoryTool(config?: MemoryToolConfig): AnthropicMemoryTool {\n
|
|
1
|
+
{"version":3,"file":"memory-tool.js","sources":["../../../src/tools/memory-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type { BetaMemoryTool20250818 } from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type MemoryToolConfig = BetaMemoryTool20250818\n\n/** @deprecated Renamed to `MemoryToolConfig`. Will be removed in a future release. */\nexport type MemoryTool = MemoryToolConfig\n\nexport type AnthropicMemoryTool = ProviderTool<'anthropic', 'memory'>\n\nexport function convertMemoryToolToAdapterFormat(tool: Tool): MemoryToolConfig {\n const metadata = tool.metadata as Omit<MemoryToolConfig, 'type'>\n return {\n type: 'memory_20250818',\n ...metadata,\n }\n}\n\nexport function memoryTool(config?: MemoryToolConfig): AnthropicMemoryTool {\n return brandProviderTool<AnthropicMemoryTool>({\n name: 'memory',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAWO,SAAS,iCAAiC,MAA8B;AAC7E,QAAM,WAAW,KAAK;AACtB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAEO,SAAS,WAAW,QAAgD;AACzE,SAAO,kBAAuC;AAAA,IAC5C,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
function convertTextEditorToolToAdapterFormat(tool) {
|
|
2
3
|
const metadata = tool.metadata;
|
|
3
4
|
return {
|
|
@@ -5,11 +6,11 @@ function convertTextEditorToolToAdapterFormat(tool) {
|
|
|
5
6
|
};
|
|
6
7
|
}
|
|
7
8
|
function textEditorTool(config) {
|
|
8
|
-
return {
|
|
9
|
+
return brandProviderTool({
|
|
9
10
|
name: "str_replace_editor",
|
|
10
11
|
description: "",
|
|
11
12
|
metadata: config
|
|
12
|
-
};
|
|
13
|
+
});
|
|
13
14
|
}
|
|
14
15
|
export {
|
|
15
16
|
convertTextEditorToolToAdapterFormat,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-editor-tool.js","sources":["../../../src/tools/text-editor-tool.ts"],"sourcesContent":["import type {\n ToolTextEditor20250124,\n ToolTextEditor20250429,\n ToolTextEditor20250728,\n} from '@anthropic-ai/sdk/resources/messages'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type TextEditorToolConfig =\n | ToolTextEditor20250124\n | ToolTextEditor20250429\n | ToolTextEditor20250728\n\n/** @deprecated Renamed to `TextEditorToolConfig`. Will be removed in a future release. */\nexport type TextEditorTool = TextEditorToolConfig\n\nexport type AnthropicTextEditorTool = ProviderTool<'anthropic', 'text_editor'>\n\nexport function convertTextEditorToolToAdapterFormat(\n tool: Tool,\n): TextEditorToolConfig {\n const metadata = tool.metadata as TextEditorToolConfig\n return {\n ...metadata,\n }\n}\n\nexport function textEditorTool<T extends TextEditorToolConfig>(\n config: T,\n): AnthropicTextEditorTool {\n
|
|
1
|
+
{"version":3,"file":"text-editor-tool.js","sources":["../../../src/tools/text-editor-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type {\n ToolTextEditor20250124,\n ToolTextEditor20250429,\n ToolTextEditor20250728,\n} from '@anthropic-ai/sdk/resources/messages'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type TextEditorToolConfig =\n | ToolTextEditor20250124\n | ToolTextEditor20250429\n | ToolTextEditor20250728\n\n/** @deprecated Renamed to `TextEditorToolConfig`. Will be removed in a future release. */\nexport type TextEditorTool = TextEditorToolConfig\n\nexport type AnthropicTextEditorTool = ProviderTool<'anthropic', 'text_editor'>\n\nexport function convertTextEditorToolToAdapterFormat(\n tool: Tool,\n): TextEditorToolConfig {\n const metadata = tool.metadata as TextEditorToolConfig\n return {\n ...metadata,\n }\n}\n\nexport function textEditorTool<T extends TextEditorToolConfig>(\n config: T,\n): AnthropicTextEditorTool {\n return brandProviderTool<AnthropicTextEditorTool>({\n name: 'str_replace_editor',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAkBO,SAAS,qCACd,MACsB;AACtB,QAAM,WAAW,KAAK;AACtB,SAAO;AAAA,IACL,GAAG;AAAA,EAAA;AAEP;AAEO,SAAS,eACd,QACyB;AACzB,SAAO,kBAA2C;AAAA,IAChD,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
function convertWebFetchToolToAdapterFormat(tool) {
|
|
2
3
|
const metadata = tool.metadata;
|
|
3
4
|
return {
|
|
@@ -7,11 +8,11 @@ function convertWebFetchToolToAdapterFormat(tool) {
|
|
|
7
8
|
};
|
|
8
9
|
}
|
|
9
10
|
function webFetchTool(config) {
|
|
10
|
-
return {
|
|
11
|
+
return brandProviderTool({
|
|
11
12
|
name: "web_fetch",
|
|
12
13
|
description: "",
|
|
13
14
|
metadata: config
|
|
14
|
-
};
|
|
15
|
+
});
|
|
15
16
|
}
|
|
16
17
|
export {
|
|
17
18
|
convertWebFetchToolToAdapterFormat,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-fetch-tool.js","sources":["../../../src/tools/web-fetch-tool.ts"],"sourcesContent":["import type { BetaWebFetchTool20250910 } from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type WebFetchToolConfig = BetaWebFetchTool20250910\n\n/** @deprecated Renamed to `WebFetchToolConfig`. Will be removed in a future release. */\nexport type WebFetchTool = WebFetchToolConfig\n\nexport type AnthropicWebFetchTool = ProviderTool<'anthropic', 'web_fetch'>\n\nexport function convertWebFetchToolToAdapterFormat(\n tool: Tool,\n): WebFetchToolConfig {\n const metadata = tool.metadata as Omit<WebFetchToolConfig, 'type' | 'name'>\n return {\n name: 'web_fetch',\n type: 'web_fetch_20250910',\n ...metadata,\n }\n}\n\nexport function webFetchTool(\n config?: Omit<WebFetchToolConfig, 'type' | 'name'>,\n): AnthropicWebFetchTool {\n
|
|
1
|
+
{"version":3,"file":"web-fetch-tool.js","sources":["../../../src/tools/web-fetch-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type { BetaWebFetchTool20250910 } from '@anthropic-ai/sdk/resources/beta'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type WebFetchToolConfig = BetaWebFetchTool20250910\n\n/** @deprecated Renamed to `WebFetchToolConfig`. Will be removed in a future release. */\nexport type WebFetchTool = WebFetchToolConfig\n\nexport type AnthropicWebFetchTool = ProviderTool<'anthropic', 'web_fetch'>\n\nexport function convertWebFetchToolToAdapterFormat(\n tool: Tool,\n): WebFetchToolConfig {\n const metadata = tool.metadata as Omit<WebFetchToolConfig, 'type' | 'name'>\n return {\n name: 'web_fetch',\n type: 'web_fetch_20250910',\n ...metadata,\n }\n}\n\nexport function webFetchTool(\n config?: Omit<WebFetchToolConfig, 'type' | 'name'>,\n): AnthropicWebFetchTool {\n return brandProviderTool<AnthropicWebFetchTool>({\n name: 'web_fetch',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAWO,SAAS,mCACd,MACoB;AACpB,QAAM,WAAW,KAAK;AACtB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,GAAG;AAAA,EAAA;AAEP;AAEO,SAAS,aACd,QACuB;AACvB,SAAO,kBAAyC;AAAA,IAC9C,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
const validateDomains = (tool) => {
|
|
2
3
|
if (tool.allowed_domains && tool.blocked_domains) {
|
|
3
4
|
throw new Error(
|
|
@@ -33,21 +34,27 @@ function convertWebSearchToolToAdapterFormat(tool) {
|
|
|
33
34
|
return {
|
|
34
35
|
name: "web_search",
|
|
35
36
|
type: "web_search_20250305",
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
...metadata.allowedDomains !== void 0 && {
|
|
38
|
+
allowed_domains: metadata.allowedDomains
|
|
39
|
+
},
|
|
40
|
+
...metadata.blockedDomains !== void 0 && {
|
|
41
|
+
blocked_domains: metadata.blockedDomains
|
|
42
|
+
},
|
|
43
|
+
...metadata.maxUses !== void 0 && { max_uses: metadata.maxUses },
|
|
44
|
+
...metadata.userLocation !== void 0 && {
|
|
45
|
+
user_location: metadata.userLocation
|
|
46
|
+
},
|
|
40
47
|
cache_control: metadata.cacheControl || null
|
|
41
48
|
};
|
|
42
49
|
}
|
|
43
50
|
function webSearchTool(config) {
|
|
44
51
|
validateDomains(config);
|
|
45
52
|
validateUserLocation(config);
|
|
46
|
-
return {
|
|
53
|
+
return brandProviderTool({
|
|
47
54
|
name: "web_search",
|
|
48
55
|
description: "",
|
|
49
56
|
metadata: config
|
|
50
|
-
};
|
|
57
|
+
});
|
|
51
58
|
}
|
|
52
59
|
export {
|
|
53
60
|
convertWebSearchToolToAdapterFormat,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-search-tool.js","sources":["../../../src/tools/web-search-tool.ts"],"sourcesContent":["import type { WebSearchTool20250305 } from '@anthropic-ai/sdk/resources/messages'\nimport type { CacheControl } from '../text/text-provider-options'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type WebSearchToolConfig = WebSearchTool20250305\n\n/** @deprecated Renamed to `WebSearchToolConfig`. Will be removed in a future release. */\nexport type WebSearchTool = WebSearchToolConfig\n\nexport type AnthropicWebSearchTool = ProviderTool<'anthropic', 'web_search'>\n\nconst validateDomains = (tool: WebSearchToolConfig) => {\n if (tool.allowed_domains && tool.blocked_domains) {\n throw new Error(\n 'allowed_domains and blocked_domains cannot be used together.',\n )\n }\n}\n\nconst validateUserLocation = (tool: WebSearchToolConfig) => {\n const userLocation = tool.user_location\n if (userLocation) {\n if (\n userLocation.city &&\n (userLocation.city.length < 1 || userLocation.city.length > 255)\n ) {\n throw new Error(\n 'user_location.city must be between 1 and 255 characters.',\n )\n }\n if (userLocation.country && userLocation.country.length !== 2) {\n throw new Error('user_location.country must be exactly 2 characters.')\n }\n if (\n userLocation.region &&\n (userLocation.region.length < 1 || userLocation.region.length > 255)\n ) {\n throw new Error(\n 'user_location.region must be between 1 and 255 characters.',\n )\n }\n if (\n userLocation.timezone &&\n (userLocation.timezone.length < 1 || userLocation.timezone.length > 255)\n ) {\n throw new Error(\n 'user_location.timezone must be between 1 and 255 characters.',\n )\n }\n }\n}\n\nexport function convertWebSearchToolToAdapterFormat(\n tool: Tool,\n): WebSearchToolConfig {\n const metadata = tool.metadata as {\n allowedDomains?: Array<string> | null\n blockedDomains?: Array<string> | null\n maxUses?: number | null\n userLocation?: {\n type: 'approximate'\n city?: string | null\n country?: string | null\n region?: string | null\n timezone?: string | null\n } | null\n cacheControl?: CacheControl | null\n }\n return {\n name: 'web_search',\n type: 'web_search_20250305',\n allowed_domains: metadata.allowedDomains,\n blocked_domains: metadata.blockedDomains,\n max_uses: metadata.maxUses,\n user_location: metadata.userLocation,\n cache_control: metadata.cacheControl || null,\n }\n}\n\nexport function webSearchTool(\n config: WebSearchToolConfig,\n): AnthropicWebSearchTool {\n validateDomains(config)\n validateUserLocation(config)\n
|
|
1
|
+
{"version":3,"file":"web-search-tool.js","sources":["../../../src/tools/web-search-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type { WebSearchTool20250305 } from '@anthropic-ai/sdk/resources/messages'\nimport type { CacheControl } from '../text/text-provider-options'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type WebSearchToolConfig = WebSearchTool20250305\n\n/** @deprecated Renamed to `WebSearchToolConfig`. Will be removed in a future release. */\nexport type WebSearchTool = WebSearchToolConfig\n\nexport type AnthropicWebSearchTool = ProviderTool<'anthropic', 'web_search'>\n\nconst validateDomains = (tool: WebSearchToolConfig) => {\n if (tool.allowed_domains && tool.blocked_domains) {\n throw new Error(\n 'allowed_domains and blocked_domains cannot be used together.',\n )\n }\n}\n\nconst validateUserLocation = (tool: WebSearchToolConfig) => {\n const userLocation = tool.user_location\n if (userLocation) {\n if (\n userLocation.city &&\n (userLocation.city.length < 1 || userLocation.city.length > 255)\n ) {\n throw new Error(\n 'user_location.city must be between 1 and 255 characters.',\n )\n }\n if (userLocation.country && userLocation.country.length !== 2) {\n throw new Error('user_location.country must be exactly 2 characters.')\n }\n if (\n userLocation.region &&\n (userLocation.region.length < 1 || userLocation.region.length > 255)\n ) {\n throw new Error(\n 'user_location.region must be between 1 and 255 characters.',\n )\n }\n if (\n userLocation.timezone &&\n (userLocation.timezone.length < 1 || userLocation.timezone.length > 255)\n ) {\n throw new Error(\n 'user_location.timezone must be between 1 and 255 characters.',\n )\n }\n }\n}\n\nexport function convertWebSearchToolToAdapterFormat(\n tool: Tool,\n): WebSearchToolConfig {\n const metadata = tool.metadata as {\n allowedDomains?: Array<string> | null\n blockedDomains?: Array<string> | null\n maxUses?: number | null\n userLocation?: {\n type: 'approximate'\n city?: string | null\n country?: string | null\n region?: string | null\n timezone?: string | null\n } | null\n cacheControl?: CacheControl | null\n }\n // Vendor `WebSearchTool20250305` declares these fields as `T | null`\n // (no `| undefined`) under exactOptionalPropertyTypes, so spread them\n // conditionally rather than passing explicit `undefined`.\n return {\n name: 'web_search',\n type: 'web_search_20250305',\n ...(metadata.allowedDomains !== undefined && {\n allowed_domains: metadata.allowedDomains,\n }),\n ...(metadata.blockedDomains !== undefined && {\n blocked_domains: metadata.blockedDomains,\n }),\n ...(metadata.maxUses !== undefined && { max_uses: metadata.maxUses }),\n ...(metadata.userLocation !== undefined && {\n user_location: metadata.userLocation,\n }),\n cache_control: metadata.cacheControl || null,\n }\n}\n\nexport function webSearchTool(\n config: WebSearchToolConfig,\n): AnthropicWebSearchTool {\n validateDomains(config)\n validateUserLocation(config)\n return brandProviderTool<AnthropicWebSearchTool>({\n name: 'web_search',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAYA,MAAM,kBAAkB,CAAC,SAA8B;AACrD,MAAI,KAAK,mBAAmB,KAAK,iBAAiB;AAChD,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACF;AAEA,MAAM,uBAAuB,CAAC,SAA8B;AAC1D,QAAM,eAAe,KAAK;AAC1B,MAAI,cAAc;AAChB,QACE,aAAa,SACZ,aAAa,KAAK,SAAS,KAAK,aAAa,KAAK,SAAS,MAC5D;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,QAAI,aAAa,WAAW,aAAa,QAAQ,WAAW,GAAG;AAC7D,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AACA,QACE,aAAa,WACZ,aAAa,OAAO,SAAS,KAAK,aAAa,OAAO,SAAS,MAChE;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,QACE,aAAa,aACZ,aAAa,SAAS,SAAS,KAAK,aAAa,SAAS,SAAS,MACpE;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AACF;AAEO,SAAS,oCACd,MACqB;AACrB,QAAM,WAAW,KAAK;AAgBtB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,GAAI,SAAS,mBAAmB,UAAa;AAAA,MAC3C,iBAAiB,SAAS;AAAA,IAAA;AAAA,IAE5B,GAAI,SAAS,mBAAmB,UAAa;AAAA,MAC3C,iBAAiB,SAAS;AAAA,IAAA;AAAA,IAE5B,GAAI,SAAS,YAAY,UAAa,EAAE,UAAU,SAAS,QAAA;AAAA,IAC3D,GAAI,SAAS,iBAAiB,UAAa;AAAA,MACzC,eAAe,SAAS;AAAA,IAAA;AAAA,IAE1B,eAAe,SAAS,gBAAgB;AAAA,EAAA;AAE5C;AAEO,SAAS,cACd,QACwB;AACxB,kBAAgB,MAAM;AACtB,uBAAqB,MAAM;AAC3B,SAAO,kBAA0C;AAAA,IAC/C,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-anthropic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Anthropic Claude adapter for TanStack AI",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"zod": "^4.0.0",
|
|
42
|
-
"@tanstack/ai": "^0.
|
|
42
|
+
"@tanstack/ai": "^0.20.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@vitest/coverage-v8": "4.0.14",
|
|
46
46
|
"zod": "^4.2.0",
|
|
47
|
-
"@tanstack/ai": "0.
|
|
47
|
+
"@tanstack/ai": "0.20.1"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "vite build",
|
package/src/adapters/text.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventType } from '@tanstack/ai'
|
|
1
|
+
import { EventType, normalizeSystemPrompts } from '@tanstack/ai'
|
|
2
2
|
import { BaseTextAdapter } from '@tanstack/ai/adapters'
|
|
3
3
|
import { convertToolsToProviderFormat } from '../tools/tool-converter'
|
|
4
4
|
import { validateTextProviderOptions } from '../text/text-provider-options'
|
|
@@ -21,10 +21,12 @@ import type { InternalLogger } from '@tanstack/ai/adapter-internals'
|
|
|
21
21
|
import type {
|
|
22
22
|
Base64ImageSource,
|
|
23
23
|
Base64PDFSource,
|
|
24
|
+
ContentBlockParam,
|
|
24
25
|
DocumentBlockParam,
|
|
25
26
|
ImageBlockParam,
|
|
26
|
-
MessageParam,
|
|
27
27
|
TextBlockParam,
|
|
28
|
+
ThinkingBlockParam,
|
|
29
|
+
ToolUseBlockParam,
|
|
28
30
|
URLImageSource,
|
|
29
31
|
URLPDFSource,
|
|
30
32
|
} from '@anthropic-ai/sdk/resources/messages'
|
|
@@ -38,6 +40,7 @@ import type {
|
|
|
38
40
|
TextOptions,
|
|
39
41
|
} from '@tanstack/ai'
|
|
40
42
|
import type {
|
|
43
|
+
AnthropicSystemPromptMetadata,
|
|
41
44
|
ExternalTextProviderOptions,
|
|
42
45
|
InternalTextProviderOptions,
|
|
43
46
|
} from '../text/text-provider-options'
|
|
@@ -59,13 +62,6 @@ export interface AnthropicTextConfig extends AnthropicClientConfig {}
|
|
|
59
62
|
*/
|
|
60
63
|
export type AnthropicTextProviderOptions = ExternalTextProviderOptions
|
|
61
64
|
|
|
62
|
-
type AnthropicContentBlocks =
|
|
63
|
-
Extract<MessageParam['content'], Array<unknown>> extends Array<infer Block>
|
|
64
|
-
? Array<Block>
|
|
65
|
-
: never
|
|
66
|
-
type AnthropicContentBlock =
|
|
67
|
-
AnthropicContentBlocks extends Array<infer Block> ? Block : never
|
|
68
|
-
|
|
69
65
|
// ===========================
|
|
70
66
|
// Type Resolution Helpers
|
|
71
67
|
// ===========================
|
|
@@ -115,12 +111,17 @@ export class AnthropicTextAdapter<
|
|
|
115
111
|
TProviderOptions,
|
|
116
112
|
TInputModalities,
|
|
117
113
|
AnthropicMessageMetadataByModality,
|
|
118
|
-
TToolCapabilities
|
|
114
|
+
TToolCapabilities,
|
|
115
|
+
// TToolCallMetadata — anthropic has no tool-call metadata round-tripping
|
|
116
|
+
unknown,
|
|
117
|
+
// TSystemPromptMetadata — narrows `systemPrompts[i].metadata` at the
|
|
118
|
+
// chat() call site so users get `cache_control` autocomplete.
|
|
119
|
+
AnthropicSystemPromptMetadata
|
|
119
120
|
> {
|
|
120
|
-
readonly kind = 'text' as const
|
|
121
|
+
override readonly kind = 'text' as const
|
|
121
122
|
readonly name = 'anthropic' as const
|
|
122
123
|
|
|
123
|
-
private client: Anthropic_SDK
|
|
124
|
+
private readonly client: Anthropic_SDK
|
|
124
125
|
|
|
125
126
|
constructor(config: AnthropicTextConfig, model: TModel) {
|
|
126
127
|
super({}, model)
|
|
@@ -350,18 +351,40 @@ export class AnthropicTextAdapter<
|
|
|
350
351
|
? thinkingBudget + 1
|
|
351
352
|
: defaultMaxTokens
|
|
352
353
|
|
|
354
|
+
// `InternalTextProviderOptions.system` is typed
|
|
355
|
+
// `string | Array<TextBlockParam>` (no `| undefined`), so build it
|
|
356
|
+
// outside the literal and spread it conditionally rather than
|
|
357
|
+
// assigning `undefined` under exactOptionalPropertyTypes.
|
|
358
|
+
const systemBlocks = ((): Array<TextBlockParam> | undefined => {
|
|
359
|
+
const normalized = normalizeSystemPrompts<AnthropicSystemPromptMetadata>(
|
|
360
|
+
options.systemPrompts,
|
|
361
|
+
)
|
|
362
|
+
if (normalized.length === 0) return undefined
|
|
363
|
+
return normalized.map(
|
|
364
|
+
(p): TextBlockParam => ({
|
|
365
|
+
type: 'text',
|
|
366
|
+
text: p.content,
|
|
367
|
+
...(p.metadata?.cache_control && {
|
|
368
|
+
cache_control: p.metadata.cache_control,
|
|
369
|
+
}),
|
|
370
|
+
}),
|
|
371
|
+
)
|
|
372
|
+
})()
|
|
373
|
+
// `InternalTextProviderOptions` declares `temperature`, `top_p`,
|
|
374
|
+
// and `tools` as `T?: ...` (no `| undefined`), so spread them
|
|
375
|
+
// conditionally rather than passing explicit `undefined` from the
|
|
376
|
+
// optional common `TextOptions` fields under
|
|
377
|
+
// exactOptionalPropertyTypes.
|
|
353
378
|
const requestParams: InternalTextProviderOptions = {
|
|
354
379
|
model: options.model,
|
|
355
380
|
max_tokens: maxTokens,
|
|
356
|
-
|
|
357
|
-
|
|
381
|
+
...(options.temperature !== undefined && {
|
|
382
|
+
temperature: options.temperature,
|
|
383
|
+
}),
|
|
384
|
+
...(options.topP !== undefined && { top_p: options.topP }),
|
|
358
385
|
messages: formattedMessages,
|
|
359
|
-
system:
|
|
360
|
-
|
|
361
|
-
(text): TextBlockParam => ({ type: 'text', text }),
|
|
362
|
-
)
|
|
363
|
-
: undefined,
|
|
364
|
-
tools: tools,
|
|
386
|
+
...(systemBlocks !== undefined && { system: systemBlocks }),
|
|
387
|
+
...(tools !== undefined && { tools }),
|
|
365
388
|
...validProviderOptions,
|
|
366
389
|
}
|
|
367
390
|
validateTextProviderOptions(requestParams)
|
|
@@ -461,14 +484,14 @@ export class AnthropicTextAdapter<
|
|
|
461
484
|
}
|
|
462
485
|
|
|
463
486
|
if (role === 'assistant' && message.toolCalls?.length) {
|
|
464
|
-
const contentBlocks:
|
|
487
|
+
const contentBlocks: Array<ContentBlockParam> = []
|
|
465
488
|
|
|
466
489
|
this.appendThinkingBlocks(contentBlocks, message.thinking)
|
|
467
490
|
|
|
468
491
|
if (message.content) {
|
|
469
492
|
const content =
|
|
470
493
|
typeof message.content === 'string' ? message.content : ''
|
|
471
|
-
const textBlock:
|
|
494
|
+
const textBlock: TextBlockParam = {
|
|
472
495
|
type: 'text',
|
|
473
496
|
text: content,
|
|
474
497
|
}
|
|
@@ -486,7 +509,7 @@ export class AnthropicTextAdapter<
|
|
|
486
509
|
parsedInput = toolCall.function.arguments
|
|
487
510
|
}
|
|
488
511
|
|
|
489
|
-
const toolUseBlock:
|
|
512
|
+
const toolUseBlock: ToolUseBlockParam = {
|
|
490
513
|
type: 'tool_use',
|
|
491
514
|
id: toolCall.id,
|
|
492
515
|
name: toolCall.function.name,
|
|
@@ -504,7 +527,7 @@ export class AnthropicTextAdapter<
|
|
|
504
527
|
}
|
|
505
528
|
|
|
506
529
|
if (role === 'assistant') {
|
|
507
|
-
const contentBlocks:
|
|
530
|
+
const contentBlocks: Array<ContentBlockParam> = []
|
|
508
531
|
this.appendThinkingBlocks(contentBlocks, message.thinking)
|
|
509
532
|
|
|
510
533
|
if (Array.isArray(message.content)) {
|
|
@@ -556,18 +579,19 @@ export class AnthropicTextAdapter<
|
|
|
556
579
|
}
|
|
557
580
|
|
|
558
581
|
private appendThinkingBlocks(
|
|
559
|
-
contentBlocks:
|
|
582
|
+
contentBlocks: Array<ContentBlockParam>,
|
|
560
583
|
thinkingParts: ModelMessage['thinking'],
|
|
561
584
|
): void {
|
|
562
585
|
if (!thinkingParts?.length) return
|
|
563
586
|
|
|
564
587
|
for (const thinking of thinkingParts) {
|
|
565
588
|
if (!thinking.signature) continue
|
|
566
|
-
|
|
589
|
+
const block: ThinkingBlockParam = {
|
|
567
590
|
type: 'thinking',
|
|
568
591
|
thinking: thinking.content,
|
|
569
592
|
signature: thinking.signature,
|
|
570
|
-
}
|
|
593
|
+
}
|
|
594
|
+
contentBlocks.push(block)
|
|
571
595
|
}
|
|
572
596
|
}
|
|
573
597
|
|
|
@@ -765,14 +789,17 @@ export class AnthropicTextAdapter<
|
|
|
765
789
|
delta,
|
|
766
790
|
content: accumulatedContent,
|
|
767
791
|
}
|
|
768
|
-
} else if (
|
|
792
|
+
} else if (
|
|
793
|
+
event.delta.type === 'thinking_delta' &&
|
|
794
|
+
reasoningMessageId
|
|
795
|
+
) {
|
|
769
796
|
const delta = event.delta.thinking
|
|
770
797
|
accumulatedThinking += delta
|
|
771
798
|
|
|
772
799
|
// Spec REASONING content event
|
|
773
800
|
yield {
|
|
774
801
|
type: EventType.REASONING_MESSAGE_CONTENT,
|
|
775
|
-
messageId: reasoningMessageId
|
|
802
|
+
messageId: reasoningMessageId,
|
|
776
803
|
delta,
|
|
777
804
|
model,
|
|
778
805
|
timestamp: Date.now(),
|
|
@@ -975,7 +1002,16 @@ export class AnthropicTextAdapter<
|
|
|
975
1002
|
}
|
|
976
1003
|
break
|
|
977
1004
|
}
|
|
1005
|
+
case 'stop_sequence':
|
|
1006
|
+
case 'end_turn':
|
|
1007
|
+
case 'pause_turn':
|
|
1008
|
+
case 'refusal':
|
|
1009
|
+
case 'model_context_window_exceeded':
|
|
978
1010
|
default: {
|
|
1011
|
+
// All remaining Anthropic stop_reason variants map to the
|
|
1012
|
+
// generic "stop" finish reason — they describe *why* the
|
|
1013
|
+
// stream ended, but for AG-UI consumers the resulting event
|
|
1014
|
+
// shape is identical.
|
|
979
1015
|
yield {
|
|
980
1016
|
type: EventType.RUN_FINISHED,
|
|
981
1017
|
runId,
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export {
|
|
|
10
10
|
type AnthropicTextConfig,
|
|
11
11
|
type AnthropicTextProviderOptions,
|
|
12
12
|
} from './adapters/text'
|
|
13
|
+
export type { AnthropicSystemPromptMetadata } from './text/text-provider-options'
|
|
13
14
|
|
|
14
15
|
// Summarize - thin factory functions over @tanstack/ai's ChatStreamSummarizeAdapter
|
|
15
16
|
export {
|
|
@@ -4,12 +4,43 @@ import type {
|
|
|
4
4
|
BetaToolChoiceAuto,
|
|
5
5
|
BetaToolChoiceTool,
|
|
6
6
|
} from '@anthropic-ai/sdk/resources/beta/messages/messages'
|
|
7
|
+
import type { CacheControlEphemeral } from '@anthropic-ai/sdk/resources'
|
|
7
8
|
import type { AnthropicTool } from '../tools'
|
|
8
9
|
import type {
|
|
9
10
|
MessageParam,
|
|
10
11
|
TextBlockParam,
|
|
11
12
|
} from '@anthropic-ai/sdk/resources/messages'
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Per-prompt metadata Anthropic understands on `systemPrompts` entries.
|
|
16
|
+
*
|
|
17
|
+
* Used via the structured form of `systemPrompts`:
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* import type { AnthropicSystemPromptMetadata } from '@tanstack/ai-anthropic'
|
|
21
|
+
*
|
|
22
|
+
* chat({
|
|
23
|
+
* adapter: anthropicText(),
|
|
24
|
+
* model: 'claude-sonnet-4-6',
|
|
25
|
+
* systemPrompts: [
|
|
26
|
+
* {
|
|
27
|
+
* content: 'Stable instructions — cache me.',
|
|
28
|
+
* metadata: { cache_control: { type: 'ephemeral' } } satisfies AnthropicSystemPromptMetadata,
|
|
29
|
+
* },
|
|
30
|
+
* 'Volatile per-request instruction.',
|
|
31
|
+
* ],
|
|
32
|
+
* })
|
|
33
|
+
*/
|
|
34
|
+
export interface AnthropicSystemPromptMetadata {
|
|
35
|
+
/**
|
|
36
|
+
* Anthropic prompt-caching control applied to this system prompt's
|
|
37
|
+
* `TextBlockParam`.
|
|
38
|
+
*
|
|
39
|
+
* @see https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching
|
|
40
|
+
*/
|
|
41
|
+
cache_control?: CacheControlEphemeral
|
|
42
|
+
}
|
|
43
|
+
|
|
13
44
|
export interface AnthropicContainerOptions {
|
|
14
45
|
/**
|
|
15
46
|
* Container identifier for reuse across requests.
|
package/src/tools/bash-tool.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type {
|
|
2
3
|
BetaToolBash20241022,
|
|
3
4
|
BetaToolBash20250124,
|
|
@@ -17,10 +18,9 @@ export function convertBashToolToAdapterFormat(tool: Tool): BashToolConfig {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export function bashTool(config: BashToolConfig): AnthropicBashTool {
|
|
20
|
-
|
|
21
|
-
return {
|
|
21
|
+
return brandProviderTool<AnthropicBashTool>({
|
|
22
22
|
name: 'bash',
|
|
23
23
|
description: '',
|
|
24
24
|
metadata: config,
|
|
25
|
-
}
|
|
25
|
+
})
|
|
26
26
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type {
|
|
2
3
|
BetaCodeExecutionTool20250522,
|
|
3
4
|
BetaCodeExecutionTool20250825,
|
|
@@ -26,10 +27,9 @@ export function convertCodeExecutionToolToAdapterFormat(
|
|
|
26
27
|
export function codeExecutionTool(
|
|
27
28
|
config: CodeExecutionToolConfig,
|
|
28
29
|
): AnthropicCodeExecutionTool {
|
|
29
|
-
|
|
30
|
-
return {
|
|
30
|
+
return brandProviderTool<AnthropicCodeExecutionTool>({
|
|
31
31
|
name: 'code_execution',
|
|
32
32
|
description: '',
|
|
33
33
|
metadata: config,
|
|
34
|
-
}
|
|
34
|
+
})
|
|
35
35
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type {
|
|
2
3
|
BetaToolComputerUse20241022,
|
|
3
4
|
BetaToolComputerUse20250124,
|
|
@@ -23,10 +24,9 @@ export function convertComputerUseToolToAdapterFormat(
|
|
|
23
24
|
export function computerUseTool(
|
|
24
25
|
config: ComputerUseToolConfig,
|
|
25
26
|
): AnthropicComputerUseTool {
|
|
26
|
-
|
|
27
|
-
return {
|
|
27
|
+
return brandProviderTool<AnthropicComputerUseTool>({
|
|
28
28
|
name: 'computer',
|
|
29
29
|
description: '',
|
|
30
30
|
metadata: config,
|
|
31
|
-
}
|
|
31
|
+
})
|
|
32
32
|
}
|
package/src/tools/memory-tool.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { BetaMemoryTool20250818 } from '@anthropic-ai/sdk/resources/beta'
|
|
2
3
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
3
4
|
|
|
@@ -17,10 +18,9 @@ export function convertMemoryToolToAdapterFormat(tool: Tool): MemoryToolConfig {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export function memoryTool(config?: MemoryToolConfig): AnthropicMemoryTool {
|
|
20
|
-
|
|
21
|
-
return {
|
|
21
|
+
return brandProviderTool<AnthropicMemoryTool>({
|
|
22
22
|
name: 'memory',
|
|
23
23
|
description: '',
|
|
24
24
|
metadata: config,
|
|
25
|
-
}
|
|
25
|
+
})
|
|
26
26
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type {
|
|
2
3
|
ToolTextEditor20250124,
|
|
3
4
|
ToolTextEditor20250429,
|
|
@@ -27,10 +28,9 @@ export function convertTextEditorToolToAdapterFormat(
|
|
|
27
28
|
export function textEditorTool<T extends TextEditorToolConfig>(
|
|
28
29
|
config: T,
|
|
29
30
|
): AnthropicTextEditorTool {
|
|
30
|
-
|
|
31
|
-
return {
|
|
31
|
+
return brandProviderTool<AnthropicTextEditorTool>({
|
|
32
32
|
name: 'str_replace_editor',
|
|
33
33
|
description: '',
|
|
34
34
|
metadata: config,
|
|
35
|
-
}
|
|
35
|
+
})
|
|
36
36
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { BetaWebFetchTool20250910 } from '@anthropic-ai/sdk/resources/beta'
|
|
2
3
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
3
4
|
|
|
@@ -22,10 +23,9 @@ export function convertWebFetchToolToAdapterFormat(
|
|
|
22
23
|
export function webFetchTool(
|
|
23
24
|
config?: Omit<WebFetchToolConfig, 'type' | 'name'>,
|
|
24
25
|
): AnthropicWebFetchTool {
|
|
25
|
-
|
|
26
|
-
return {
|
|
26
|
+
return brandProviderTool<AnthropicWebFetchTool>({
|
|
27
27
|
name: 'web_fetch',
|
|
28
28
|
description: '',
|
|
29
29
|
metadata: config,
|
|
30
|
-
}
|
|
30
|
+
})
|
|
31
31
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { WebSearchTool20250305 } from '@anthropic-ai/sdk/resources/messages'
|
|
2
3
|
import type { CacheControl } from '../text/text-provider-options'
|
|
3
4
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
@@ -66,13 +67,22 @@ export function convertWebSearchToolToAdapterFormat(
|
|
|
66
67
|
} | null
|
|
67
68
|
cacheControl?: CacheControl | null
|
|
68
69
|
}
|
|
70
|
+
// Vendor `WebSearchTool20250305` declares these fields as `T | null`
|
|
71
|
+
// (no `| undefined`) under exactOptionalPropertyTypes, so spread them
|
|
72
|
+
// conditionally rather than passing explicit `undefined`.
|
|
69
73
|
return {
|
|
70
74
|
name: 'web_search',
|
|
71
75
|
type: 'web_search_20250305',
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
...(metadata.allowedDomains !== undefined && {
|
|
77
|
+
allowed_domains: metadata.allowedDomains,
|
|
78
|
+
}),
|
|
79
|
+
...(metadata.blockedDomains !== undefined && {
|
|
80
|
+
blocked_domains: metadata.blockedDomains,
|
|
81
|
+
}),
|
|
82
|
+
...(metadata.maxUses !== undefined && { max_uses: metadata.maxUses }),
|
|
83
|
+
...(metadata.userLocation !== undefined && {
|
|
84
|
+
user_location: metadata.userLocation,
|
|
85
|
+
}),
|
|
76
86
|
cache_control: metadata.cacheControl || null,
|
|
77
87
|
}
|
|
78
88
|
}
|
|
@@ -82,10 +92,9 @@ export function webSearchTool(
|
|
|
82
92
|
): AnthropicWebSearchTool {
|
|
83
93
|
validateDomains(config)
|
|
84
94
|
validateUserLocation(config)
|
|
85
|
-
|
|
86
|
-
return {
|
|
95
|
+
return brandProviderTool<AnthropicWebSearchTool>({
|
|
87
96
|
name: 'web_search',
|
|
88
97
|
description: '',
|
|
89
98
|
metadata: config,
|
|
90
|
-
}
|
|
99
|
+
})
|
|
91
100
|
}
|