/** * Typed value object for a single tool result. * * A tool result crosses the wire as an opaque JSON **string** (both LLM provider * APIs require `tool_result.content` to be a string). Historically the pruning * code re-`JSON.parse`d that string and inspected untyped fields * (`parsed._summary`, `.label`, `.success`, ...) to decide how to compress it. * `ToolResult` does that classification ONCE, into a typed {@link ToolResultEnvelope}, * and exposes pure, deterministic transforms used by the conversation projection. * * It keeps the original wire string verbatim (`raw`) so an un-compressed result * re-serialises byte-identically (important for Anthropic prompt-cache prefix * matching); compressed/stale forms are tiny fixed-shape objects. * * Pure utility shared by the client-facing protocol and the server projection, * mirroring the `shared/toolParams.ts` precedent. No client-tool Zod schemas are * imported here — classification is field-driven, matching the fact that results * are never validated against their schema server-side. */ /** * Typed classification of a tool result, derived once from its wire content. * The `summaryText` carried on several variants is the explicit summary the * client/tool provided (`_summary ?? label ?? summary`), which takes precedence * when compressing — preserving the historical compression precedence. */ export type ToolResultEnvelope = { kind: 'opaque'; text: string; } | { kind: 'stale'; summary: string; } | { kind: 'error'; message: string; summaryText?: string; } | { kind: 'mutationSuccess'; summaryText?: string; } | { kind: 'mutationRejected'; summaryText?: string; } | { kind: 'selection'; selected: unknown; summaryText?: string; } | { kind: 'summary'; summary: string; }; export declare class ToolResult { /** The original (or compressed) wire string, emitted verbatim by `toWire`. */ private readonly raw; private readonly envelope; private readonly isError; /** Summary used when this result is evicted as stale (`_summary ?? summary`). */ private readonly staleSummary; private constructor(); /** * Classify a wire string (the form stored in a `tool_result` block) once. * Mirrors the historical `compressToolResult` precedence. */ static fromWire(content: string, isError?: boolean): ToolResult; /** * Build from a live client result object (server tool-dispatch path). * Applies the `agentMessage → label` rewrite and serialises with the same * bytes the previous code produced, then classifies. */ static fromClientResult(result: unknown, opts?: { isError?: boolean; }): ToolResult; /** An explicit error result (malformed input, loop guard, validation, ...). */ static error(message: string): ToolResult; /** The wire string for this result — verbatim original, or the compressed form. */ toWire(): string; isErrorResult(): boolean; /** True for an applied mutation (`{ success: true }`), independent of summary. */ isMutationSuccess(): boolean; /** Best human-readable summary of this result. */ summary(): string; /** Estimated token cost of the full wire content (~4 chars per token). */ estimatedTokens(): number; /** * Compressed form: collapse to the minimal payload. Pure (returns a new * `ToolResult`) and idempotent. Replicates the historical `compressToolResult` * precedence: an explicit `summaryText` wins; otherwise the kind-specific * minimal shape (`{error}` / `{success}` / `{selected}`) is kept. */ compressed(): ToolResult; /** * Stale form: a volatile query whose data is outdated because a mutation * happened after it. Pure and idempotent. * * Error results are preserved verbatim — a failed call isn't "stale data", * it's a failure the LLM may still need to act on (e.g. fix its input and * retry). Collapsing it to a generic stale summary hides the cause. */ stale(): ToolResult; }