UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

106 lines • 5.94 kB
/** * anthropicThinkingWire — the one translation of `LLMRequest.thinking` onto * the Messages body, in the shape each Claude model takes. * * Pattern: pure translation over a declaration (the `anthropicCacheWire.ts` twin). * Role: Outer ring. Two jobs, one file — which mode each model takes is * the `thinking` column of the ONE model table * (`anthropicModels.ts` · `ANTHROPIC_MODELS`): * 1. `thinkingModeWith` — the ONE mode function an adapter declares * (`LLMProvider.thinkingMode`) and builds its body with: the app's own * answer for an id the table cannot read, else the table's. * 2. `anthropicThinkingPlan` — the `thinking` field a request gets on that * model, or a typed refusal before anything is sent. * * Why it exists: `.thinking({ budget })` used to send * `{ type: 'enabled', budget_tokens }` to every model, and Claude 4.7 and later * reject that with HTTP 400 — every call of every agent that asked to think * failed. The models disagree, so the shape is decided per model, here, for * the three adapters that build this body (`anthropic()`, `browserAnthropic()`, * `invokeModelGateway()`). * * The rules, from Anthropic's documentation (fetched 2026-10-08): * - per-model thinking types and the ones each model rejects with a 400 — * https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting * ("Thinking support, defaults, and rejected configurations by model") and * https://platform.claude.com/docs/en/build-with-claude/thinking ("Configuring thinking"); * - "Claude 4.7 and later models do not support it [budget_tokens] and reject * requests that use it, returning a 400 error"; deprecated but accepted on * the Claude 4.6 models; the only mode on Claude 4.5 and earlier, where * `type: "adaptive"` is a 400 — * https://platform.claude.com/docs/en/build-with-claude/extended-thinking; * - `budget_tokens` at least 1,024 and below `max_tokens`; forced tool use is * incompatible with manual (budget) thinking; while thinking, older models * take no `temperature` but the default and Claude 4.7 and later reject a * non-default one on every request — same pages ("Budget rules and * tuning", "Limits and feature compatibility"); * - `display` defaults to `"omitted"` (empty thinking text) on Claude 4.7 and * later; `"summarized"` returns readable thinking on every adaptive model — * https://platform.claude.com/docs/en/build-with-claude/thinking ("Controlling thinking display"); * - model ids per platform — * https://platform.claude.com/docs/en/about-claude/models/overview, * https://platform.claude.com/docs/en/about-claude/model-deprecations, * https://platform.claude.com/docs/en/build-with-claude/claude-on-amazon-bedrock-legacy, * https://platform.claude.com/docs/en/build-with-claude/claude-on-vertex-ai. * * @example * const modeOf = thinkingModeWith(undefined); // the table's answer, per model * anthropicThinkingPlan({ thinking: { budget: 2048 } }, { * model: 'claude-opus-5-5', provider: 'anthropic', maxTokensDefault: 4096, thinkingMode: modeOf, * }); // { thinking: { type: 'adaptive', display: 'summarized' }, maxTokens: 4096 } */ import type { LLMRequest } from '../../provider-contract/types.js'; import type { ThinkingMode } from '../../thinking/types.js'; /** * An adapter's ONE mode function: the app's own answer for an id the table * cannot read (the adapter's `thinkingMode` option), else the table's. The * adapter declares it as `LLMProvider.thinkingMode` AND builds its body with * it, so what the agent checks at build and what reaches the wire cannot * disagree. * * @example * const modeOf = thinkingModeWith((id) => (id === 'haiku-fast' ? 'budget' : undefined)); * modeOf('haiku-fast'); // 'budget' — the app's answer * modeOf('claude-opus-5-5'); // 'adaptive' — the table's */ export declare function thinkingModeWith(own: ((model: string) => ThinkingMode | undefined) | undefined): (model: string) => ThinkingMode; /** The `thinking` field of a Messages body, in the two shapes this wire sends. */ export type AnthropicThinkingParam = { type: 'enabled'; budget_tokens: number; } | { type: 'adaptive'; display: 'summarized'; }; /** * The `thinking` field and `max_tokens` for one request on one model, or * `undefined` when the request does not ask to think. * * - `'budget'`: `{ type: 'enabled', budget_tokens: budget }`. * - `'adaptive'`: `{ type: 'adaptive', display: 'summarized' }` — no budget * (the wire has no field for one), and `display: 'summarized'` because * `.thinking()` asks for readable thinking and these models otherwise * return it empty. * - Either way `max_tokens` stays above the budget: one at or below it * becomes `budget + 1024` (on an adaptive model the budget only sizes this). * * `thinkingMode` is the adapter's own mode function ({@link thinkingModeWith}) * — the one it declares — never the table read on the side. * * @throws UnsupportedThinkingError — before anything is sent — when the model * cannot think, when a budget model is given a budget `budget_tokens` does * not accept or a forced tool choice, or when a non-default `temperature` * rides along (rejected whenever thinking is on). * @throws TypeError when the adapter's `thinkingMode` option answers * something other than `'adaptive'`, `'budget'` or `'none'`. */ export declare function anthropicThinkingPlan(req: Pick<LLMRequest, 'thinking' | 'temperature' | 'toolChoice' | 'tools' | 'maxTokens'>, args: { readonly model: string; readonly provider: string; readonly maxTokensDefault: number; readonly thinkingMode: (model: string) => ThinkingMode; }): { readonly thinking: AnthropicThinkingParam; readonly maxTokens: number; } | undefined; //# sourceMappingURL=anthropicThinkingWire.d.ts.map