UNPKG

agentfootprint

Version:

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

52 lines • 2.73 kB
/** * AnthropicThinkingHandler — normalizes Anthropic's extended-thinking * response shape into the framework's `ThinkingBlock[]` contract. * * Anthropic emits thinking via blocks in `response.content`: * * ```ts * { type: 'thinking', thinking: 'reasoning text', signature: 'opaque-base64' } * { type: 'redacted_thinking', data: 'opaque-encrypted' } * { type: 'text', text: 'visible content' } * { type: 'tool_use', id, name, input } * ``` * * The handler filters for `'thinking'` + `'redacted_thinking'` blocks, * preserves the `signature` field BYTE-EXACT (Anthropic validates * signatures server-side on the next turn — any modification = HTTP 400), * and ignores other block types (visible text + tool calls flow through * the existing `LLMResponse.content` / `LLMResponse.toolCalls` paths). * * The same shapes in both thinking modes (budget and adaptive). Two * adaptive-mode facts the echo already honours: a turn may carry NO * thinking block (the model chose not to think), and a block's `thinking` * text may be EMPTY — `display: 'omitted'`, the default on Claude 4.7 and * later when the request does not ask to think (`.thinking()` asks for * `'summarized'`), and the progress notes some models write between tool * calls. An empty block is still complete — its `signature` carries the * reasoning — so it is kept and echoed like any other, never dropped. * * **Critical invariant:** signature pass-through is byte-exact. The * handler MUST NOT trim, normalize encoding, JSON-roundtrip, or * otherwise touch the signature string. Tests verify this explicitly. * * **Three input shapes** Anthropic produces (per Phase 4a panel review): * 1. Non-streaming response: full `response.content` array * 2. Streaming aggregated: AnthropicProvider accumulates chunks + * calls handler with the same array shape * 3. Bedrock-via-Anthropic: deferred to Phase 5+ (separate handler * or extension of this one) * * Streaming + non-streaming converge on shape #1 because the provider * handles the distinction — handler only sees the assembled content * array. * * **`parseChunk` is OPTIONAL** — Phase 3's framework path populates * `LLMChunk.thinkingDelta` from inside AnthropicProvider's `stream()` * directly, bypassing handler.parseChunk. We still implement it for * consumer integrations that want to use the handler on raw Anthropic * chunks directly (e.g., custom transports). */ import type { ThinkingHandler } from './types.js'; export declare const anthropicThinkingHandler: ThinkingHandler; //# sourceMappingURL=AnthropicThinkingHandler.d.ts.map