/** * OutputLedger — session memory of what each tool already returned. * * `ReadWorkspaceCache` solves this for file reads, but reads are not where the weight is. * A debug loop runs `npm test` six times and `tsc --noEmit` four; each run dumps hundreds * of near-identical lines into the transcript, and every one of those copies is re-sent on * every later turn. By the end of a session the same failing stack trace can account for * more context than the source files being debugged. * * So: key on (tool, call signature), remember the exact text emitted, and on a repeat * answer with `IDENTICAL` or a diff instead of the payload. * * The correctness rule is the same one that governs the read cache, and it is absolute: * a ledger hit may only suppress text the model demonstrably already received in this * session. Anything else — a cold start, an evicted entry, a caller that didn't record — * resolves to sending the full output. Under-suppressing costs tokens; over-suppressing * costs the user a correct answer. */ /** * Build a stable key from the arguments that determine the output. * * Only pass arguments that actually change the result. Including an incidental field * (a verbosity flag that doesn't alter the payload, a timestamp) makes every call a * fresh key and silently disables the ledger; including too few makes two genuinely * different calls collide, which would suppress output the model never saw. When unsure, * include the field — a missed saving is recoverable, a wrong suppression is not. */ export declare function ledgerKey(toolName: string, signature: Record): string; export type LedgerStatus = "new" | "identical" | "changed"; export interface LedgerResult { status: LedgerStatus; /** Replacement text to return instead of the payload; null means "send the full output". */ replacement: string | null; /** Characters saved by the replacement, for the savings ledger. 0 when nothing was suppressed. */ savedChars: number; } export interface LedgerOptions { /** * Human-readable description of the call, used in the marker so the model can tell which * earlier result it is being pointed at ("npm test", "search for 'foo' in src/"). */ label: string; /** * Set when re-deriving the suppressed output is not free for the caller — a command that * must actually run again. Purely informational; it does not change the decision. */ rerunHint?: string; } /** * Check a freshly produced output against what this tool last returned for the same call. * * Always call `record` afterwards with the text you actually emitted, including when this * returns `new` — otherwise the next repeat has no base to compare against. */ export declare function checkOutput(key: string, text: string, options: LedgerOptions): LedgerResult; /** Record the text a tool emitted (the full payload, not a marker) as the base for next time. */ export declare function recordOutput(key: string, text: string): void; /** Test seam — the map is process-global and would otherwise leak between test cases. */ export declare function resetOutputLedger(): void; //# sourceMappingURL=OutputLedger.d.ts.map