/** * Context garbage collection. * * The whole transcript is re-sent on every turn, so a tool result that has * become useless keeps costing tokens for the rest of the session. This pass * runs on the OUTGOING message copy (via the agent's `transformContext` hook), * never on the persisted session, and replaces provably-dead `read` results * with a short stub. Nothing is lost: the persisted history is untouched and * the file is re-readable on demand. * * Current rule — superseded reads only (the read-then-edit / re-read pattern, * which dominates coding sessions): * * A `read` result for a path P is stale once, later in the transcript, the * same path is edited/written (its on-disk content changed) or read again * over an overlapping line range (the newer read reflects that region's newer * state). Reads of disjoint regions of the same file coexist — a later read of * lines 200-260 does not evict an earlier read of lines 1-40 — so paginating * through a large file never makes the model re-fetch a region it already has. * A read is only evicted when a *successful* later event supersedes it — so a * read whose edit failed (and which the model still needs to retry) is never * touched. * * Deliberately conservative: paths are matched after `path.resolve`, so two * different files never collide, and any ambiguity results in NOT evicting. * * This post-hoc pass is complemented by an at-call-time guard in the `read` * tool (see `tools/read-dedup.ts`), which short-circuits a redundant re-read * before it fetches. Both share the range math in that module, and this pass * skips the guard's pointer results so they never supersede the read they name. * * Bash-output eviction is additionally gated on token-budget pressure * (`options.budgetPressure`, the fraction of the model's context window in * use). At 0 pressure — the default — behaviour is identical to read-only GC. * Bash output is not always recoverable, so it carries its own safeguards: a * command that looks side-effecting is never elided (re-running it, as the * stub invites, could repeat a destructive action), and below 80% pressure * only large outputs are elided. */ import type { AgentMessage } from "@kolisachint/hoocode-agent-core"; export interface ContextGcOptions { /** Working directory used to resolve relative tool path arguments. */ cwd: string; /** * Token-budget pressure in [0, 1] — the fraction of the model's context * window currently in use. Absent or 0 reproduces read-only GC behaviour. * Bash-output eviction begins at 0.6 and becomes unconditional at 0.8. */ budgetPressure?: number; } /** * Return a message array with superseded `read` results stubbed out. Returns the * original array reference unchanged when there is nothing to evict, so a * no-op turn does not needlessly perturb the outgoing context. */ export declare function evictSupersededReads(messages: AgentMessage[], options: ContextGcOptions): AgentMessage[]; //# sourceMappingURL=context-gc.d.ts.map