/** * What everything that runs subagents needs while they work: the dots, the * footer, the transcripts. * * It exists because the `subagent` tool, `/run` and `/step` must look * **identical** while they run. They had every reason to drift - three call * sites, three timers, three ways of clearing a widget - and the one that drifts * is the one nobody is watching that day. One painter, one `finally`, one * report. A run that walks a flow draws the flow's plan in the same widget, * through `flow.ts`, and everything else about it is the same. * * Painting lives here rather than in `execute.ts` so the dependency runs one * way: the tool body and the commands both reach for this file, and it reaches * for none of them. */ import { type CheckedFlow, type EventListener, type JournalEntry, type MainSession, type RunPicture, type RunSnapshot, type SpawnFn } from "../../src/index.ts"; import type { RunUi, WidgetTheme } from "../pi.ts"; /** Key for the footer status and the widget above the prompt. */ export declare const STATUS = "combo"; /** What a caller may vary about a live run. Everything else is the same everywhere. */ export type LiveRunOptions = { /** * Widget repaint period. `0` disables the timer - tests want that. * * A period rather than a redraw on every event: `busyMs` only lands when a * turn ends, so a subagent thinking for twenty seconds emits nothing at all, * and a frozen clock reads as a hung agent. */ tickMs?: number; /** * A second observer beside the picture. * * Defaults to the herdr reporter, which is `undefined` unless pi itself runs * inside herdr. Injected so the wiring is testable offline - a herdr reporter * nobody subscribed is one of the bugs that reached a user through here. */ reporter?: EventListener; /** Give every subagent of this run a split, not only the ones that asked. */ herdrAll?: boolean; /** Called on every event, after the widget: the tool streams a progress line. */ onChange?: (snapshot: RunSnapshot) => void; /** * The caller's own signal - pi's, when it has one. * * It is folded into {@link LiveRun.signal} rather than passed to the workflow * directly, so that a run has **one** thing to obey whether it was called off * by pi, by Escape or by `/stop all`. */ signal?: AbortSignal; /** The `spawn` the run should use. Defaults to the real one. */ spawn?: SpawnFn; /** Where `usage.json` lands when the run is over. Absent writes none. */ dir?: string; /** The parent session, `ctx.sessionManager`, whose JSONL lands beside the subagents' transcripts. */ mainSession?: MainSession; /** * The flow this run walks, and what its earlier lives wrote in its * journal: the widget then draws its plan, filled as the visits go, * rather than a row per subagent. */ flow?: { readonly checked: CheckedFlow; readonly journal: readonly JournalEntry[]; }; }; /** A live view of a run, and the one call that takes it down. */ export type LiveRun = { /** Subscribe this to the workflow: the TUI picture and herdr, composed. */ onEvent: EventListener; /** The state the widget is drawn from, and the usage report is built from. */ picture: RunPicture; /** Give the workflow this signal, not the caller's: Escape fires it too. */ signal: AbortSignal; /** Give the workflow this `spawn`: it is what makes one subagent stoppable. */ spawn: SpawnFn; /** How long the view has been up. The run's wall time, measured once, here. */ elapsedMs(): number; /** * Clears the footer and the widget, and closes the measurement: the run's * `usage.json`, with the time this view measured, when a `dir` was given. * * Call it in a `finally`: a thrown workflow must not leave a dead row of dots * above the prompt for the rest of the session, and a run that was cancelled * still has work worth keeping. */ stop(): void; }; /** Starts painting a run. `ui` is absent for a headless caller: nothing is drawn. */ export declare function liveRun(ui: RunUi | undefined, options?: LiveRunOptions): LiveRun; /** * Paints the dots that sit above the prompt. * * The lines themselves come from `widgetRows`, which knows nothing about * colour; this only applies the theme, and marks the selected row. Keeping the * two apart is what lets the layout be tested without a terminal - a selection * is a fact about this terminal, and lives no deeper than the paint. */ export declare function paintWidget(snapshot: RunSnapshot, theme: WidgetTheme, selected?: string): string[]; /** * What a reader can do about the run they are watching, while there is * something left to stop and no question card is up: a card holds the stop * key and says what it means there, and a second line saying otherwise would * be read as well. * * Spelled out under the dots rather than left to a `--help`: a key nobody knows * about is a key nobody presses, and this one exists for the moment where the * run has gone wrong and reading documentation is the last thing on anyone's * mind. The keys are the ones bound now, read at each paint, and one that is * unbound is not offered. * * On one line, or one key a line when `width` is too narrow for it, as a * card's help line does: a key is never cut from what it does. With no * `width`, pi wraps the line itself. */ export declare function hint(running: boolean, theme: WidgetTheme, width?: number): string[]; //# sourceMappingURL=run.d.ts.map