@tanstack/ai-anthropic 0.15.13 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 { CacheControlEphemeral } from '@anthropic-ai/sdk/resources'\nimport type { AnthropicContainerSkill, 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 * @deprecated Configure skills on the `code_execution` tool instead:\n * `codeExecutionTool(config, { skills })`. The adapter lifts those into\n * `container.skills` and attaches the required beta headers. Setting\n * skills here bypasses the beta-header wiring and may stop working.\n */\n skills: Array<AnthropicContainerSkill> | 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 * Controls what (if any) thinking content is streamed back.\n *\n * - `'summarized'`: stream summarized thinking via `thinking_delta`\n * events (the user-visible reasoning text).\n * - `'omitted'`: stream the thinking block's `signature_delta` only\n * (no reasoning text reaches the client).\n *\n * On Claude Opus 4.6 the default is `'summarized'`. On\n * Claude Opus 4.7 the default flipped to `'omitted'` — callers\n * must set `'summarized'` explicitly to get the reasoning text.\n */\n display?: 'summarized' | 'omitted'\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 AnthropicOutputConfigOptions {\n /**\n * Output configuration for the model's response.\n *\n * On Claude 4.7+ the top-level `effort` field was relocated under\n * `output_config.effort`, and `thinking: { type: 'enabled', budget_tokens }`\n * was replaced by `thinking: { type: 'adaptive' }` paired with\n * `output_config.effort`. Earlier models continue to accept the legacy\n * top-level `effort` / `thinking.type: 'enabled'` shape.\n *\n * The engine also writes `output_config.format` here when the caller\n * passes `outputSchema` to a Claude 4.5+ adapter (issue #605 native\n * combined mode). Both fields coexist: user-supplied `effort` is\n * preserved when the engine adds `format`.\n */\n output_config?: {\n effort?: 'low' | 'medium' | 'high' | 'max' | null\n }\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 * 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 * Use nucleus sampling.\n *\n * In 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 * The maximum number of tokens to generate before stopping. This parameter only specifies the absolute maximum number of tokens to generate. Required by the API; the adapter defaults to 1024 when omitted.\n * Range x >= 1.\n */\n max_tokens?: 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 Partial<AnthropicOutputConfigOptions>\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 tools?: Array<AnthropicTool>\n\n /**\n * Schema-constrained final answer in a single Messages request (issue\n * #605). Set by the engine when the adapter declared\n * `supportsCombinedToolsAndSchema` and a caller passed `outputSchema`\n * to `chat()`. The model emits tool calls during the agent loop and a\n * schema-matching JSON message on the natural final turn — no separate\n * finalization round-trip needed.\n *\n * The SDK type (`BetaOutputConfig`) currently exposes only `effort`;\n * `format` is accepted at runtime per the deprecation notice on the\n * older `output_format` field\n * (https://platform.claude.com/docs/en/build-with-claude/structured-outputs).\n * We type it explicitly here so the adapter call site doesn't need a\n * cast.\n */\n output_config?: {\n effort?: 'low' | 'medium' | 'high' | 'max' | null\n format?: {\n type: 'json_schema'\n schema: Record<string, unknown>\n }\n }\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":"AA6RA,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
+ {"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 { AnthropicContainerSkill, 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 * @deprecated Configure skills on the `code_execution` tool instead:\n * `codeExecutionTool(config, { skills })`. The adapter lifts those into\n * `container.skills` and attaches the required beta headers. Setting\n * skills here bypasses the beta-header wiring and may stop working.\n */\n skills: Array<AnthropicContainerSkill> | 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 * Controls what (if any) thinking content is streamed back.\n *\n * - `'summarized'`: stream summarized thinking via `thinking_delta`\n * events (the user-visible reasoning text).\n * - `'omitted'`: stream the thinking block's `signature_delta` only\n * (no reasoning text reaches the client).\n *\n * On Claude Opus 4.6 the default is `'summarized'`. On\n * Claude Opus 4.7 the default flipped to `'omitted'` — callers\n * must set `'summarized'` explicitly to get the reasoning text.\n */\n display?: 'summarized' | 'omitted'\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\n/**\n * Thinking configuration for models where thinking is always on\n * (e.g. Claude Fable 5).\n *\n * On these models the only accepted explicit configuration is\n * `{type: 'adaptive'}` — both `{type: 'disabled'}` and\n * `{type: 'enabled', budget_tokens}` are rejected with a 400. Omitting the\n * `thinking` field entirely also runs adaptive thinking.\n */\nexport interface AnthropicAdaptiveOnlyThinkingOptions {\n thinking?: {\n type: 'adaptive'\n /**\n * Controls what (if any) thinking content is streamed back.\n *\n * - `'summarized'`: stream summarized thinking via `thinking_delta`\n * events (the user-visible reasoning text).\n * - `'omitted'` (default): stream the thinking block's\n * `signature_delta` only (no reasoning text reaches the client).\n */\n display?: 'summarized' | 'omitted'\n }\n}\n\n/**\n * Thinking configuration for models that accept adaptive thinking or an\n * explicit opt-out, but no manual token budget (e.g. Claude Sonnet 5,\n * Claude Opus 4.7/4.8).\n *\n * `{type: 'enabled', budget_tokens}` is rejected with a 400 on these\n * models. On Claude Sonnet 5, omitting the `thinking` field runs adaptive\n * thinking by default; on Opus 4.7/4.8 it runs without thinking — set\n * `{type: 'adaptive'}` explicitly there.\n */\nexport interface AnthropicAdaptiveOrDisabledThinkingOptions {\n thinking?:\n | {\n type: 'adaptive'\n /**\n * Controls what (if any) thinking content is streamed back.\n * Defaults to `'omitted'` — set `'summarized'` to receive the\n * reasoning text.\n */\n display?: 'summarized' | 'omitted'\n }\n | {\n type: 'disabled'\n }\n}\n\n/**\n * `max_tokens` on its own, for models that reject the sampling parameters\n * (`temperature`, `top_p`, `top_k`) — e.g. Claude Fable 5 and Claude Opus\n * 4.7/4.8 reject them outright, and Claude Sonnet 5 returns a 400 when a\n * non-default sampling value is sent.\n */\nexport interface AnthropicMaxTokensOptions {\n /**\n * The maximum number of tokens to generate before stopping. This parameter only specifies the absolute maximum number of tokens to generate. Required by the API; the adapter defaults to 1024 when omitted.\n * Range x >= 1.\n */\n max_tokens?: number\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 AnthropicOutputConfigOptions {\n /**\n * Output configuration for the model's response.\n *\n * On Claude 4.7+ the top-level `effort` field was relocated under\n * `output_config.effort`, and `thinking: { type: 'enabled', budget_tokens }`\n * was replaced by `thinking: { type: 'adaptive' }` paired with\n * `output_config.effort`. Earlier models continue to accept the legacy\n * top-level `effort` / `thinking.type: 'enabled'` shape.\n *\n * The engine also writes `output_config.format` here when the caller\n * passes `outputSchema` to a Claude 4.5+ adapter (issue #605 native\n * combined mode). Both fields coexist: user-supplied `effort` is\n * preserved when the engine adds `format`.\n */\n output_config?: {\n /**\n * `'xhigh'` is accepted on Claude Opus 4.7+, Claude Sonnet 5, and\n * Claude Fable 5; older models support `'low'`–`'max'` only.\n */\n effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null\n }\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 * 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 * Use nucleus sampling.\n *\n * In 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 * The maximum number of tokens to generate before stopping. This parameter only specifies the absolute maximum number of tokens to generate. Required by the API; the adapter defaults to 1024 when omitted.\n * Range x >= 1.\n */\n max_tokens?: 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 Partial<AnthropicOutputConfigOptions>\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 tools?: Array<AnthropicTool>\n\n /**\n * Schema-constrained final answer in a single Messages request (issue\n * #605). Set by the engine when the adapter declared\n * `supportsCombinedToolsAndSchema` and a caller passed `outputSchema`\n * to `chat()`. The model emits tool calls during the agent loop and a\n * schema-matching JSON message on the natural final turn — no separate\n * finalization round-trip needed.\n *\n * The SDK type (`BetaOutputConfig`) currently exposes only `effort`;\n * `format` is accepted at runtime per the deprecation notice on the\n * older `output_format` field\n * (https://platform.claude.com/docs/en/build-with-claude/structured-outputs).\n * We type it explicitly here so the adapter call site doesn't need a\n * cast.\n */\n output_config?: {\n effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null\n format?: {\n type: 'json_schema'\n schema: Record<string, unknown>\n }\n }\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":"AAiWA,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;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai-anthropic",
3
- "version": "0.15.13",
3
+ "version": "0.16.0",
4
4
  "description": "Anthropic Claude adapter for TanStack AI chat, tool calling, thinking, and structured outputs.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -53,12 +53,12 @@
53
53
  },
54
54
  "peerDependencies": {
55
55
  "zod": "^4.0.0",
56
- "@tanstack/ai": "^0.39.0"
56
+ "@tanstack/ai": "^0.39.1"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@vitest/coverage-v8": "4.0.14",
60
60
  "zod": "^4.2.0",
61
- "@tanstack/ai": "0.39.0"
61
+ "@tanstack/ai": "0.39.1"
62
62
  },
63
63
  "scripts": {
64
64
  "build": "vite build",
@@ -17,7 +17,7 @@ export type AnthropicSummarizeModel = (typeof ANTHROPIC_MODELS)[number]
17
17
  * Creates an Anthropic summarize adapter with explicit API key.
18
18
  * Type resolution happens here at the call site.
19
19
  *
20
- * @param model - The model name (e.g., 'claude-sonnet-4-5', 'claude-3-5-haiku-latest')
20
+ * @param model - The model name (e.g., 'claude-sonnet-5', 'claude-haiku-4-5')
21
21
  * @param apiKey - Your Anthropic API key
22
22
  * @param config - Optional additional configuration
23
23
  * @returns Configured Anthropic summarize adapter instance with resolved types
@@ -48,7 +48,7 @@ export function createAnthropicSummarize<
48
48
  * Creates an Anthropic summarize adapter with automatic API key detection.
49
49
  * Type resolution happens here at the call site.
50
50
  *
51
- * @param model - The model name (e.g., 'claude-sonnet-4-5', 'claude-3-5-haiku-latest')
51
+ * @param model - The model name (e.g., 'claude-sonnet-5', 'claude-haiku-4-5')
52
52
  * @param config - Optional configuration (excluding apiKey which is auto-detected)
53
53
  * @returns Configured Anthropic summarize adapter instance with resolved types
54
54
  *
@@ -28,11 +28,14 @@ import type {
28
28
  ContentBlockParam,
29
29
  DocumentBlockParam,
30
30
  ImageBlockParam,
31
+ ServerToolUseBlockParam,
31
32
  TextBlockParam,
32
33
  ThinkingBlockParam,
33
34
  ToolUseBlockParam,
34
35
  URLImageSource,
35
36
  URLPDFSource,
37
+ WebFetchToolResultBlockParam,
38
+ WebSearchToolResultBlockParam,
36
39
  } from '@anthropic-ai/sdk/resources/messages'
37
40
  import type Anthropic_SDK from '@anthropic-ai/sdk'
38
41
  import type { AnthropicBeta } from '@anthropic-ai/sdk/resources/beta/beta'
@@ -57,6 +60,83 @@ import type {
57
60
  } from '../message-types'
58
61
  import type { AnthropicClientConfig } from '../utils'
59
62
 
63
+ /**
64
+ * The block type carried by an Anthropic provider-executed (server) tool's
65
+ * stored result. Mirrors the `*_tool_result` block emitted by the streaming
66
+ * API so it can be replayed verbatim into a later turn.
67
+ */
68
+ type AnthropicServerToolResultBlockType =
69
+ | 'web_search_tool_result'
70
+ | 'web_fetch_tool_result'
71
+
72
+ /**
73
+ * Anthropic payload stashed on a provider-executed tool call's `metadata`
74
+ * (under the `anthropic` key, alongside `providerExecuted: true`). Holds enough
75
+ * to reconstruct the original `server_tool_use` + `*_tool_result` blocks so the
76
+ * model still sees prior `web_search` / `web_fetch` evidence on the next turn.
77
+ */
78
+ interface AnthropicServerToolMetadata {
79
+ serverToolType: ServerToolUseBlockParam['name']
80
+ resultBlockType: AnthropicServerToolResultBlockType
81
+ /** Raw result block content, preserved verbatim from the stream. */
82
+ result: unknown
83
+ }
84
+
85
+ /**
86
+ * Narrow an opaque tool-call `metadata` to {@link AnthropicServerToolMetadata}
87
+ * when it follows the provider-executed convention, else `null`.
88
+ */
89
+ function readAnthropicServerToolMetadata(
90
+ metadata: unknown,
91
+ ): AnthropicServerToolMetadata | null {
92
+ if (typeof metadata !== 'object' || metadata === null) return null
93
+ const outer = metadata as { providerExecuted?: unknown; anthropic?: unknown }
94
+ if (outer.providerExecuted !== true) return null
95
+ const inner = outer.anthropic
96
+ if (typeof inner !== 'object' || inner === null) return null
97
+ const { serverToolType, resultBlockType, result } = inner as {
98
+ serverToolType?: unknown
99
+ resultBlockType?: unknown
100
+ result?: unknown
101
+ }
102
+ if (
103
+ typeof serverToolType !== 'string' ||
104
+ (resultBlockType !== 'web_search_tool_result' &&
105
+ resultBlockType !== 'web_fetch_tool_result')
106
+ ) {
107
+ return null
108
+ }
109
+ return {
110
+ // Validated as a string above; widen back to the SDK's tool-name union.
111
+ serverToolType: serverToolType as ServerToolUseBlockParam['name'],
112
+ resultBlockType,
113
+ result,
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Reconstruct the `*_tool_result` block param from stored server-tool metadata.
119
+ * The `result` content is opaque round-trip data, asserted to the SDK's param
120
+ * content type at this single boundary.
121
+ */
122
+ function buildServerToolResultBlock(
123
+ toolUseId: string,
124
+ meta: AnthropicServerToolMetadata,
125
+ ): WebSearchToolResultBlockParam | WebFetchToolResultBlockParam {
126
+ if (meta.resultBlockType === 'web_search_tool_result') {
127
+ return {
128
+ type: 'web_search_tool_result',
129
+ tool_use_id: toolUseId,
130
+ content: meta.result as WebSearchToolResultBlockParam['content'],
131
+ }
132
+ }
133
+ return {
134
+ type: 'web_fetch_tool_result',
135
+ tool_use_id: toolUseId,
136
+ content: meta.result as WebFetchToolResultBlockParam['content'],
137
+ }
138
+ }
139
+
60
140
  /**
61
141
  * Computes the `betas` array for a Messages request. Unions:
62
142
  * - `interleaved-thinking-2025-05-14` when interleaved thinking is enabled,
@@ -636,6 +716,25 @@ export class AnthropicTextAdapter<
636
716
  parsedInput = toolCall.function.arguments
637
717
  }
638
718
 
719
+ // Provider-executed server tools (e.g. web_search) replay as the
720
+ // original `server_tool_use` + result blocks so the model still sees
721
+ // the prior evidence. Their result was captured verbatim during
722
+ // streaming (see processAnthropicStream).
723
+ const serverMeta = readAnthropicServerToolMetadata(toolCall.metadata)
724
+ if (serverMeta) {
725
+ const serverToolUseBlock: ServerToolUseBlockParam = {
726
+ type: 'server_tool_use',
727
+ id: toolCall.id,
728
+ name: serverMeta.serverToolType,
729
+ input: parsedInput,
730
+ }
731
+ contentBlocks.push(serverToolUseBlock)
732
+ contentBlocks.push(
733
+ buildServerToolResultBlock(toolCall.id, serverMeta),
734
+ )
735
+ continue
736
+ }
737
+
639
738
  const toolUseBlock: ToolUseBlockParam = {
640
739
  type: 'tool_use',
641
740
  id: toolCall.id,
@@ -806,6 +905,14 @@ export class AnthropicTextAdapter<
806
905
  // input.
807
906
  let currentServerTool: { id: string; name: string; input: string } | null =
808
907
  null
908
+ // Completed server tools awaiting their matching result block. Anthropic
909
+ // emits `server_tool_use` then a separate `*_tool_result` block; we hold
910
+ // the call here (keyed by id) until the result arrives so we can emit a
911
+ // single provider-executed tool call carrying the raw result for round-trip.
912
+ const completedServerTools = new Map<
913
+ string,
914
+ { id: string; name: string; input: string }
915
+ >()
809
916
 
810
917
  // AG-UI lifecycle tracking
811
918
  const runId = options.runId ?? genId()
@@ -881,6 +988,61 @@ export class AnthropicTextAdapter<
881
988
  },
882
989
  )
883
990
  }
991
+
992
+ // Emit the server tool as a single provider-executed tool call,
993
+ // carrying its raw result so the evidence (e.g. web_search sources)
994
+ // round-trips into the next turn's request. The agent loop skips
995
+ // provider-executed calls, so this never triggers client execution.
996
+ const serverTool = completedServerTools.get(
997
+ event.content_block.tool_use_id,
998
+ )
999
+ if (serverTool) {
1000
+ completedServerTools.delete(serverTool.id)
1001
+
1002
+ let parsedInput: unknown = {}
1003
+ try {
1004
+ const parsed = serverTool.input
1005
+ ? JSON.parse(serverTool.input)
1006
+ : {}
1007
+ parsedInput = parsed && typeof parsed === 'object' ? parsed : {}
1008
+ } catch {
1009
+ parsedInput = {}
1010
+ }
1011
+
1012
+ const serverToolMetadata = {
1013
+ providerExecuted: true,
1014
+ anthropic: {
1015
+ serverToolType: serverTool.name,
1016
+ resultBlockType: event.content_block.type,
1017
+ result: content,
1018
+ },
1019
+ }
1020
+
1021
+ currentToolIndex++
1022
+ yield {
1023
+ type: EventType.TOOL_CALL_START,
1024
+ toolCallId: serverTool.id,
1025
+ toolCallName: serverTool.name,
1026
+ toolName: serverTool.name,
1027
+ parentMessageId: messageId,
1028
+ model,
1029
+ timestamp: Date.now(),
1030
+ index: currentToolIndex,
1031
+ metadata: serverToolMetadata,
1032
+ }
1033
+ yield {
1034
+ type: EventType.TOOL_CALL_END,
1035
+ toolCallId: serverTool.id,
1036
+ toolCallName: serverTool.name,
1037
+ toolName: serverTool.name,
1038
+ model,
1039
+ timestamp: Date.now(),
1040
+ input: parsedInput,
1041
+ }
1042
+
1043
+ // Text after the server tool starts a fresh message segment.
1044
+ hasEmittedTextMessageStart = false
1045
+ }
884
1046
  } else if (event.content_block.type === 'thinking') {
885
1047
  accumulatedThinking = ''
886
1048
  accumulatedSignature = ''
@@ -1095,6 +1257,9 @@ export class AnthropicTextAdapter<
1095
1257
  input: currentServerTool.input,
1096
1258
  },
1097
1259
  )
1260
+ // Hold the call until its result block arrives so we can emit
1261
+ // both together as one provider-executed tool call.
1262
+ completedServerTools.set(currentServerTool.id, currentServerTool)
1098
1263
  }
1099
1264
  currentServerTool = null
1100
1265
  } else if (