@tanstack/ai-anthropic 0.15.13 → 0.16.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/summarize.d.ts +2 -2
- package/dist/esm/adapters/summarize.js.map +1 -1
- package/dist/esm/adapters/text.js +107 -4
- package/dist/esm/adapters/text.js.map +1 -1
- package/dist/esm/model-meta.d.ts +77 -207
- package/dist/esm/model-meta.js +45 -45
- package/dist/esm/model-meta.js.map +1 -1
- package/dist/esm/text/text-provider-options.d.ts +65 -2
- package/dist/esm/text/text-provider-options.js.map +1 -1
- package/package.json +3 -3
- package/src/adapters/summarize.ts +2 -2
- package/src/adapters/text.ts +204 -3
- package/src/model-meta.ts +174 -466
- package/src/text/text-provider-options.ts +70 -2
|
@@ -131,6 +131,65 @@ export interface AnthropicAdaptiveThinkingOptions {
|
|
|
131
131
|
type: 'disabled';
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Thinking configuration for models where thinking is always on
|
|
136
|
+
* (e.g. Claude Fable 5).
|
|
137
|
+
*
|
|
138
|
+
* On these models the only accepted explicit configuration is
|
|
139
|
+
* `{type: 'adaptive'}` — both `{type: 'disabled'}` and
|
|
140
|
+
* `{type: 'enabled', budget_tokens}` are rejected with a 400. Omitting the
|
|
141
|
+
* `thinking` field entirely also runs adaptive thinking.
|
|
142
|
+
*/
|
|
143
|
+
export interface AnthropicAdaptiveOnlyThinkingOptions {
|
|
144
|
+
thinking?: {
|
|
145
|
+
type: 'adaptive';
|
|
146
|
+
/**
|
|
147
|
+
* Controls what (if any) thinking content is streamed back.
|
|
148
|
+
*
|
|
149
|
+
* - `'summarized'`: stream summarized thinking via `thinking_delta`
|
|
150
|
+
* events (the user-visible reasoning text).
|
|
151
|
+
* - `'omitted'` (default): stream the thinking block's
|
|
152
|
+
* `signature_delta` only (no reasoning text reaches the client).
|
|
153
|
+
*/
|
|
154
|
+
display?: 'summarized' | 'omitted';
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Thinking configuration for models that accept adaptive thinking or an
|
|
159
|
+
* explicit opt-out, but no manual token budget (e.g. Claude Sonnet 5,
|
|
160
|
+
* Claude Opus 4.7/4.8).
|
|
161
|
+
*
|
|
162
|
+
* `{type: 'enabled', budget_tokens}` is rejected with a 400 on these
|
|
163
|
+
* models. On Claude Sonnet 5, omitting the `thinking` field runs adaptive
|
|
164
|
+
* thinking by default; on Opus 4.7/4.8 it runs without thinking — set
|
|
165
|
+
* `{type: 'adaptive'}` explicitly there.
|
|
166
|
+
*/
|
|
167
|
+
export interface AnthropicAdaptiveOrDisabledThinkingOptions {
|
|
168
|
+
thinking?: {
|
|
169
|
+
type: 'adaptive';
|
|
170
|
+
/**
|
|
171
|
+
* Controls what (if any) thinking content is streamed back.
|
|
172
|
+
* Defaults to `'omitted'` — set `'summarized'` to receive the
|
|
173
|
+
* reasoning text.
|
|
174
|
+
*/
|
|
175
|
+
display?: 'summarized' | 'omitted';
|
|
176
|
+
} | {
|
|
177
|
+
type: 'disabled';
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* `max_tokens` on its own, for models that reject the sampling parameters
|
|
182
|
+
* (`temperature`, `top_p`, `top_k`) — e.g. Claude Fable 5 and Claude Opus
|
|
183
|
+
* 4.7/4.8 reject them outright, and Claude Sonnet 5 returns a 400 when a
|
|
184
|
+
* non-default sampling value is sent.
|
|
185
|
+
*/
|
|
186
|
+
export interface AnthropicMaxTokensOptions {
|
|
187
|
+
/**
|
|
188
|
+
* 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.
|
|
189
|
+
* Range x >= 1.
|
|
190
|
+
*/
|
|
191
|
+
max_tokens?: number;
|
|
192
|
+
}
|
|
134
193
|
export interface AnthropicEffortOptions {
|
|
135
194
|
/**
|
|
136
195
|
* Controls the thinking depth for adaptive thinking mode (Opus 4.6+).
|
|
@@ -158,7 +217,11 @@ export interface AnthropicOutputConfigOptions {
|
|
|
158
217
|
* preserved when the engine adds `format`.
|
|
159
218
|
*/
|
|
160
219
|
output_config?: {
|
|
161
|
-
|
|
220
|
+
/**
|
|
221
|
+
* `'xhigh'` is accepted on Claude Opus 4.7+, Claude Sonnet 5, and
|
|
222
|
+
* Claude Fable 5; older models support `'low'`–`'max'` only.
|
|
223
|
+
*/
|
|
224
|
+
effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;
|
|
162
225
|
};
|
|
163
226
|
}
|
|
164
227
|
export interface AnthropicToolChoiceOptions {
|
|
@@ -233,7 +296,7 @@ export interface InternalTextProviderOptions extends ExternalTextProviderOptions
|
|
|
233
296
|
* cast.
|
|
234
297
|
*/
|
|
235
298
|
output_config?: {
|
|
236
|
-
effort?: 'low' | 'medium' | 'high' | 'max' | null;
|
|
299
|
+
effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;
|
|
237
300
|
format?: {
|
|
238
301
|
type: 'json_schema';
|
|
239
302
|
schema: Record<string, unknown>;
|
|
@@ -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.
|
|
3
|
+
"version": "0.16.1",
|
|
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.
|
|
56
|
+
"@tanstack/ai": "^0.40.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@vitest/coverage-v8": "4.0.14",
|
|
60
60
|
"zod": "^4.2.0",
|
|
61
|
-
"@tanstack/ai": "0.
|
|
61
|
+
"@tanstack/ai": "0.40.0"
|
|
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-
|
|
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-
|
|
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
|
*
|
package/src/adapters/text.ts
CHANGED
|
@@ -10,7 +10,10 @@ import {
|
|
|
10
10
|
generateId,
|
|
11
11
|
getAnthropicApiKeyFromEnv,
|
|
12
12
|
} from '../utils'
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
ANTHROPIC_COMBINED_TOOLS_AND_SCHEMA_MODELS,
|
|
15
|
+
getAnthropicDefaultMaxTokens,
|
|
16
|
+
} from '../model-meta'
|
|
14
17
|
import type {
|
|
15
18
|
ANTHROPIC_MODELS,
|
|
16
19
|
AnthropicChatModelProviderOptionsByName,
|
|
@@ -28,11 +31,14 @@ import type {
|
|
|
28
31
|
ContentBlockParam,
|
|
29
32
|
DocumentBlockParam,
|
|
30
33
|
ImageBlockParam,
|
|
34
|
+
ServerToolUseBlockParam,
|
|
31
35
|
TextBlockParam,
|
|
32
36
|
ThinkingBlockParam,
|
|
33
37
|
ToolUseBlockParam,
|
|
34
38
|
URLImageSource,
|
|
35
39
|
URLPDFSource,
|
|
40
|
+
WebFetchToolResultBlockParam,
|
|
41
|
+
WebSearchToolResultBlockParam,
|
|
36
42
|
} from '@anthropic-ai/sdk/resources/messages'
|
|
37
43
|
import type Anthropic_SDK from '@anthropic-ai/sdk'
|
|
38
44
|
import type { AnthropicBeta } from '@anthropic-ai/sdk/resources/beta/beta'
|
|
@@ -57,6 +63,83 @@ import type {
|
|
|
57
63
|
} from '../message-types'
|
|
58
64
|
import type { AnthropicClientConfig } from '../utils'
|
|
59
65
|
|
|
66
|
+
/**
|
|
67
|
+
* The block type carried by an Anthropic provider-executed (server) tool's
|
|
68
|
+
* stored result. Mirrors the `*_tool_result` block emitted by the streaming
|
|
69
|
+
* API so it can be replayed verbatim into a later turn.
|
|
70
|
+
*/
|
|
71
|
+
type AnthropicServerToolResultBlockType =
|
|
72
|
+
| 'web_search_tool_result'
|
|
73
|
+
| 'web_fetch_tool_result'
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Anthropic payload stashed on a provider-executed tool call's `metadata`
|
|
77
|
+
* (under the `anthropic` key, alongside `providerExecuted: true`). Holds enough
|
|
78
|
+
* to reconstruct the original `server_tool_use` + `*_tool_result` blocks so the
|
|
79
|
+
* model still sees prior `web_search` / `web_fetch` evidence on the next turn.
|
|
80
|
+
*/
|
|
81
|
+
interface AnthropicServerToolMetadata {
|
|
82
|
+
serverToolType: ServerToolUseBlockParam['name']
|
|
83
|
+
resultBlockType: AnthropicServerToolResultBlockType
|
|
84
|
+
/** Raw result block content, preserved verbatim from the stream. */
|
|
85
|
+
result: unknown
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Narrow an opaque tool-call `metadata` to {@link AnthropicServerToolMetadata}
|
|
90
|
+
* when it follows the provider-executed convention, else `null`.
|
|
91
|
+
*/
|
|
92
|
+
function readAnthropicServerToolMetadata(
|
|
93
|
+
metadata: unknown,
|
|
94
|
+
): AnthropicServerToolMetadata | null {
|
|
95
|
+
if (typeof metadata !== 'object' || metadata === null) return null
|
|
96
|
+
const outer = metadata as { providerExecuted?: unknown; anthropic?: unknown }
|
|
97
|
+
if (outer.providerExecuted !== true) return null
|
|
98
|
+
const inner = outer.anthropic
|
|
99
|
+
if (typeof inner !== 'object' || inner === null) return null
|
|
100
|
+
const { serverToolType, resultBlockType, result } = inner as {
|
|
101
|
+
serverToolType?: unknown
|
|
102
|
+
resultBlockType?: unknown
|
|
103
|
+
result?: unknown
|
|
104
|
+
}
|
|
105
|
+
if (
|
|
106
|
+
typeof serverToolType !== 'string' ||
|
|
107
|
+
(resultBlockType !== 'web_search_tool_result' &&
|
|
108
|
+
resultBlockType !== 'web_fetch_tool_result')
|
|
109
|
+
) {
|
|
110
|
+
return null
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
// Validated as a string above; widen back to the SDK's tool-name union.
|
|
114
|
+
serverToolType: serverToolType as ServerToolUseBlockParam['name'],
|
|
115
|
+
resultBlockType,
|
|
116
|
+
result,
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Reconstruct the `*_tool_result` block param from stored server-tool metadata.
|
|
122
|
+
* The `result` content is opaque round-trip data, asserted to the SDK's param
|
|
123
|
+
* content type at this single boundary.
|
|
124
|
+
*/
|
|
125
|
+
function buildServerToolResultBlock(
|
|
126
|
+
toolUseId: string,
|
|
127
|
+
meta: AnthropicServerToolMetadata,
|
|
128
|
+
): WebSearchToolResultBlockParam | WebFetchToolResultBlockParam {
|
|
129
|
+
if (meta.resultBlockType === 'web_search_tool_result') {
|
|
130
|
+
return {
|
|
131
|
+
type: 'web_search_tool_result',
|
|
132
|
+
tool_use_id: toolUseId,
|
|
133
|
+
content: meta.result as WebSearchToolResultBlockParam['content'],
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
type: 'web_fetch_tool_result',
|
|
138
|
+
tool_use_id: toolUseId,
|
|
139
|
+
content: meta.result as WebFetchToolResultBlockParam['content'],
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
60
143
|
/**
|
|
61
144
|
* Computes the `betas` array for a Messages request. Unions:
|
|
62
145
|
* - `interleaved-thinking-2025-05-14` when interleaved thinking is enabled,
|
|
@@ -263,7 +346,12 @@ export class AnthropicTextAdapter<
|
|
|
263
346
|
const { chatOptions, outputSchema } = options
|
|
264
347
|
const { logger } = chatOptions
|
|
265
348
|
|
|
266
|
-
|
|
349
|
+
// `structuredOutput()` issues a non-streaming `messages.create({ stream:
|
|
350
|
+
// false })` below, so the defaulted `max_tokens` must stay under the SDK's
|
|
351
|
+
// non-streaming 10-minute guard (issue #849) — pass `stream: false`.
|
|
352
|
+
const requestParams = this.mapCommonOptionsToAnthropic(chatOptions, {
|
|
353
|
+
stream: false,
|
|
354
|
+
})
|
|
267
355
|
|
|
268
356
|
// Create a tool that will capture the structured output
|
|
269
357
|
// Anthropic's SDK requires input_schema with type: 'object' literal
|
|
@@ -352,6 +440,7 @@ export class AnthropicTextAdapter<
|
|
|
352
440
|
|
|
353
441
|
private mapCommonOptionsToAnthropic(
|
|
354
442
|
options: TextOptions<AnthropicTextProviderOptions>,
|
|
443
|
+
{ stream = true }: { stream?: boolean } = {},
|
|
355
444
|
) {
|
|
356
445
|
const modelOptions = options.modelOptions
|
|
357
446
|
|
|
@@ -420,7 +509,18 @@ export class AnthropicTextAdapter<
|
|
|
420
509
|
validProviderOptions.thinking?.type === 'enabled'
|
|
421
510
|
? validProviderOptions.thinking.budget_tokens
|
|
422
511
|
: undefined
|
|
423
|
-
|
|
512
|
+
// Anthropic's Messages API *requires* `max_tokens`, so we must always send a
|
|
513
|
+
// value. When the caller doesn't specify one, default to the resolved
|
|
514
|
+
// model's real output ceiling (from model-meta) rather than a low constant
|
|
515
|
+
// that silently truncates long responses with `stop_reason: "max_tokens"`
|
|
516
|
+
// (issue #849). `max_tokens` is a ceiling, not a reservation — billing is on
|
|
517
|
+
// tokens actually generated, so a higher default costs nothing extra.
|
|
518
|
+
// For non-streaming requests (the `structuredOutput()` path) the default is
|
|
519
|
+
// clamped to the SDK's non-streaming-safe limit so it doesn't trip the
|
|
520
|
+
// "streaming required" 10-minute guard — see getAnthropicDefaultMaxTokens.
|
|
521
|
+
const defaultMaxTokens =
|
|
522
|
+
modelOptions?.max_tokens ??
|
|
523
|
+
getAnthropicDefaultMaxTokens(this.model, { stream })
|
|
424
524
|
const maxTokens =
|
|
425
525
|
thinkingBudget && thinkingBudget >= defaultMaxTokens
|
|
426
526
|
? thinkingBudget + 1
|
|
@@ -636,6 +736,25 @@ export class AnthropicTextAdapter<
|
|
|
636
736
|
parsedInput = toolCall.function.arguments
|
|
637
737
|
}
|
|
638
738
|
|
|
739
|
+
// Provider-executed server tools (e.g. web_search) replay as the
|
|
740
|
+
// original `server_tool_use` + result blocks so the model still sees
|
|
741
|
+
// the prior evidence. Their result was captured verbatim during
|
|
742
|
+
// streaming (see processAnthropicStream).
|
|
743
|
+
const serverMeta = readAnthropicServerToolMetadata(toolCall.metadata)
|
|
744
|
+
if (serverMeta) {
|
|
745
|
+
const serverToolUseBlock: ServerToolUseBlockParam = {
|
|
746
|
+
type: 'server_tool_use',
|
|
747
|
+
id: toolCall.id,
|
|
748
|
+
name: serverMeta.serverToolType,
|
|
749
|
+
input: parsedInput,
|
|
750
|
+
}
|
|
751
|
+
contentBlocks.push(serverToolUseBlock)
|
|
752
|
+
contentBlocks.push(
|
|
753
|
+
buildServerToolResultBlock(toolCall.id, serverMeta),
|
|
754
|
+
)
|
|
755
|
+
continue
|
|
756
|
+
}
|
|
757
|
+
|
|
639
758
|
const toolUseBlock: ToolUseBlockParam = {
|
|
640
759
|
type: 'tool_use',
|
|
641
760
|
id: toolCall.id,
|
|
@@ -806,6 +925,14 @@ export class AnthropicTextAdapter<
|
|
|
806
925
|
// input.
|
|
807
926
|
let currentServerTool: { id: string; name: string; input: string } | null =
|
|
808
927
|
null
|
|
928
|
+
// Completed server tools awaiting their matching result block. Anthropic
|
|
929
|
+
// emits `server_tool_use` then a separate `*_tool_result` block; we hold
|
|
930
|
+
// the call here (keyed by id) until the result arrives so we can emit a
|
|
931
|
+
// single provider-executed tool call carrying the raw result for round-trip.
|
|
932
|
+
const completedServerTools = new Map<
|
|
933
|
+
string,
|
|
934
|
+
{ id: string; name: string; input: string }
|
|
935
|
+
>()
|
|
809
936
|
|
|
810
937
|
// AG-UI lifecycle tracking
|
|
811
938
|
const runId = options.runId ?? genId()
|
|
@@ -881,6 +1008,61 @@ export class AnthropicTextAdapter<
|
|
|
881
1008
|
},
|
|
882
1009
|
)
|
|
883
1010
|
}
|
|
1011
|
+
|
|
1012
|
+
// Emit the server tool as a single provider-executed tool call,
|
|
1013
|
+
// carrying its raw result so the evidence (e.g. web_search sources)
|
|
1014
|
+
// round-trips into the next turn's request. The agent loop skips
|
|
1015
|
+
// provider-executed calls, so this never triggers client execution.
|
|
1016
|
+
const serverTool = completedServerTools.get(
|
|
1017
|
+
event.content_block.tool_use_id,
|
|
1018
|
+
)
|
|
1019
|
+
if (serverTool) {
|
|
1020
|
+
completedServerTools.delete(serverTool.id)
|
|
1021
|
+
|
|
1022
|
+
let parsedInput: unknown = {}
|
|
1023
|
+
try {
|
|
1024
|
+
const parsed = serverTool.input
|
|
1025
|
+
? JSON.parse(serverTool.input)
|
|
1026
|
+
: {}
|
|
1027
|
+
parsedInput = parsed && typeof parsed === 'object' ? parsed : {}
|
|
1028
|
+
} catch {
|
|
1029
|
+
parsedInput = {}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
const serverToolMetadata = {
|
|
1033
|
+
providerExecuted: true,
|
|
1034
|
+
anthropic: {
|
|
1035
|
+
serverToolType: serverTool.name,
|
|
1036
|
+
resultBlockType: event.content_block.type,
|
|
1037
|
+
result: content,
|
|
1038
|
+
},
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
currentToolIndex++
|
|
1042
|
+
yield {
|
|
1043
|
+
type: EventType.TOOL_CALL_START,
|
|
1044
|
+
toolCallId: serverTool.id,
|
|
1045
|
+
toolCallName: serverTool.name,
|
|
1046
|
+
toolName: serverTool.name,
|
|
1047
|
+
parentMessageId: messageId,
|
|
1048
|
+
model,
|
|
1049
|
+
timestamp: Date.now(),
|
|
1050
|
+
index: currentToolIndex,
|
|
1051
|
+
metadata: serverToolMetadata,
|
|
1052
|
+
}
|
|
1053
|
+
yield {
|
|
1054
|
+
type: EventType.TOOL_CALL_END,
|
|
1055
|
+
toolCallId: serverTool.id,
|
|
1056
|
+
toolCallName: serverTool.name,
|
|
1057
|
+
toolName: serverTool.name,
|
|
1058
|
+
model,
|
|
1059
|
+
timestamp: Date.now(),
|
|
1060
|
+
input: parsedInput,
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// Text after the server tool starts a fresh message segment.
|
|
1064
|
+
hasEmittedTextMessageStart = false
|
|
1065
|
+
}
|
|
884
1066
|
} else if (event.content_block.type === 'thinking') {
|
|
885
1067
|
accumulatedThinking = ''
|
|
886
1068
|
accumulatedSignature = ''
|
|
@@ -1095,6 +1277,9 @@ export class AnthropicTextAdapter<
|
|
|
1095
1277
|
input: currentServerTool.input,
|
|
1096
1278
|
},
|
|
1097
1279
|
)
|
|
1280
|
+
// Hold the call until its result block arrives so we can emit
|
|
1281
|
+
// both together as one provider-executed tool call.
|
|
1282
|
+
completedServerTools.set(currentServerTool.id, currentServerTool)
|
|
1098
1283
|
}
|
|
1099
1284
|
currentServerTool = null
|
|
1100
1285
|
} else if (
|
|
@@ -1181,6 +1366,22 @@ export class AnthropicTextAdapter<
|
|
|
1181
1366
|
break
|
|
1182
1367
|
}
|
|
1183
1368
|
case 'max_tokens': {
|
|
1369
|
+
// Surface a warning when the truncating cap was the
|
|
1370
|
+
// adapter-supplied default (caller didn't pass `max_tokens`), so
|
|
1371
|
+
// the truncation isn't silently attributed to the model "doing
|
|
1372
|
+
// nothing" (issue #849). When the caller set `max_tokens`
|
|
1373
|
+
// themselves, hitting it is their own deliberate ceiling.
|
|
1374
|
+
if (options.modelOptions?.max_tokens == null) {
|
|
1375
|
+
const defaultedMaxTokens = getAnthropicDefaultMaxTokens(model)
|
|
1376
|
+
logger.warn(
|
|
1377
|
+
`anthropic response truncated at the default max_tokens (${defaultedMaxTokens}) for model=${model}; pass maxTokens (or modelOptions.max_tokens) to raise the output ceiling`,
|
|
1378
|
+
{
|
|
1379
|
+
source: 'anthropic.processAnthropicStream',
|
|
1380
|
+
model,
|
|
1381
|
+
defaultedMaxTokens,
|
|
1382
|
+
},
|
|
1383
|
+
)
|
|
1384
|
+
}
|
|
1184
1385
|
yield {
|
|
1185
1386
|
type: EventType.RUN_ERROR,
|
|
1186
1387
|
model,
|