/** * Model-visible size cap for a single tool result. * * ~40k characters is roughly 10k tokens: large enough that ordinary reads, * greps and command output pass through untouched, small enough that one * oversized result cannot consume a fifth of a 200k window. * * Nothing capped tool output before this. `read` returned a whole file when * `limit` was omitted, `bash` allowed a 100 MB buffer, and the MCP adapter * joined every text block uncapped — so a 2 MB lockfile became ~500k tokens * in a single `tool_result` and the turn died on a provider error with * everything lost. */ export declare const DEFAULT_MAX_TOOL_OUTPUT_CHARS = 40000; /** * Opening of the line that points at a spilled output. * * A constant rather than a phrase repeated in two files, because the line * has to survive later editing: compaction clears stale tool results, and * clearing a spilled one destroys the only route back to the content this * budget deliberately kept. Whatever clears a result has to be able to * recognise this line and keep it. */ export declare const SPILL_MARKER = "The full output was written to:"; export interface ToolOutputBudgetResult { /** What the model sees. */ readonly output: string; /** Size before any reduction, for telemetry. */ readonly originalLength: number; readonly truncated: boolean; /** Where the full output was written, when it was. */ readonly spillPath?: string; /** Digest of the bounded chunk manifest, recorded at retention time. */ readonly spillIntegrity?: string; } /** * Name what a truncated result took with it. * * Returns `undefined` when there was nothing but text to lose, so the * ordinary case adds no noise. * * The model is the reader here, and it is reasoning about a result it can * no longer fully see. "An image was returned and is not shown" is a fact * it can act on — ask for a smaller region, re-run against a file — where * silence looks exactly like a tool that only ever returns text. */ export declare function describeDroppedContent(content: readonly { type?: string; }[] | unknown): string | undefined; /** * Total size of the rich channel, in base64 characters. * * Measured on the payload rather than the block count, because one block * is the whole cost: a single screenshot is the largest thing a tool * result can carry. */ export declare function measureContentBytes(content: readonly unknown[] | unknown): number; export interface ApplyToolOutputBudgetOptions { readonly toolName: string; readonly toolUseId: string; readonly output: string; readonly maxChars: number; /** Optional condensed presentation; used only after authenticated retention of output. */ readonly preview?: string; /** Smaller preview only after the full output and its integrity manifest are saved. */ readonly retainedPreviewChars?: number; /** An omission notice that shares the text budget, never extends it. */ readonly notice?: string; /** * Directory to spill overflow into. When absent the output is * middle-elided instead — degraded, but never unbounded. */ readonly spillDir?: string | undefined; readonly onError?: (message: string) => void; } /** * Bound a tool result to the model-visible budget. * * Retention keeps the original while bounding its model-visible preview. * The host owns the recovery route and its permissions; a spill path is not * proof that workspace read/grep tools can access it. Middle-elision is the * fallback for a turn with no directory to write to. * * The preview keeps head AND tail because the two ends carry different * information: the head has the schema/opening of a document, the tail has * the error a command died on. */ export declare function applyToolOutputBudget(opts: ApplyToolOutputBudgetOptions): ToolOutputBudgetResult; //# sourceMappingURL=tool-output-budget.d.ts.map