import { type Component, Container } from "@kolisachint/hoocode-tui"; import type { ToolOutputView } from "../../../core/tool-output-view.js"; import type { ToolExecutionComponent } from "./tool-execution.js"; /** * A run of consecutive tool calls, rendered as one line in the radar view. * * The chain owns its blocks rather than sitting beside them, so there is one * place that decides whether you are looking at a summary or at the calls. In * every view but a collapsed radar it is a plain pass-through container and the * blocks render exactly as they always did. * * A chain closes when the agent next speaks, or when the turn settles. Closing * early matters more than it looks: rewriting a line that has scrolled above * the viewport forces the TUI into a full redraw, which clears the terminal's * scrollback. Chains that close while they are still the bottom of the screen * flip for the price of one line. */ export declare class ToolChainComponent extends Container { private blocks; private view; private state; /** The newest run in the transcript; radar marks it. */ private latest; private memo?; /** Lead-in memo, keyed on the rows it wraps, so the array stays stable. */ private leadIn?; constructor(view: ToolOutputView); /** Every cache this chain keeps. The two go stale for the same reasons. */ private forget; add(block: ToolExecutionComponent): void; /** True until the agent speaks or the turn settles. */ get isOpen(): boolean; /** Whether a summary line is standing in for this chain's calls right now. */ get isSummarised(): boolean; get isEmpty(): boolean; get toolBlocks(): readonly ToolExecutionComponent[]; /** * Settle the chain. * * `interrupted` keeps the running rendering, because the settled phrase is a * claim about what the run amounted to and a run cut off partway through has * no such claim to make — the same reason an aborted turn's plan items settle * to cancelled rather than done. */ close(outcome: "done" | "interrupted"): void; setView(view: ToolOutputView): void; /** * Mark this run as the newest in the transcript, or no longer it. * * The per-call rows carry the same mark, but they are not what radar usually * shows: a run of more than one call folds to this single line, so without * marking the line too the stroke would be invisible in the view it was * built for. */ setLatest(latest: boolean): void; invalidate(): void; /** * Whether this chain is currently drawn as a single summary line. * * A chain of one is not summarised. Its phrase would be `Ran npm run check`, * which is strictly less than the radar row it replaced: the row names the * tool and how much came back, and the phrase drops both to say the same * thing in prose. Summarising is only worth a lossy rewrite when there is * more than one call to fold — and by measurement most chains have exactly * one, so this is the common case, not an edge. */ private isCollapsed; /** * The blank row that holds a run off whatever came before it. * * Radar's rows stack without gaps on purpose, and that is right *between* * rows — but it left the first row of a run pressed against the prose that * introduced it, with the turn above and the run below reading as one * paragraph. The gap belongs to the run rather than to its rows: one blank * line at the top of the chain, and the rows go on stacking underneath it. * * Only radar needs it. Every other view gives each block a leading spacer of * its own, so asking the first block whether it draws one keeps the two from * doubling up. */ private needsLeadIn; render(width: number): string[]; private rows; /** * Each failed call's reason, indented under the chain line. * * A collapsed chain hides its blocks, so without this a failure would be a * count in the stats and nothing else. Whatever else these views fold away, * they never fold away why something broke. */ private failureLines; } /** Narrow a transcript child to a chain. */ export declare function isToolChain(child: Component): child is ToolChainComponent; //# sourceMappingURL=tool-chain.d.ts.map