/** * Reading what the CLI says while it is still saying it. * * `claude -p --output-format json` answers once, at the end, with everything. * That shape cost lookout two things at once. The page had nothing to show for * the minutes a panel takes, and the answer was released not when the model * finished but when the subprocess's stdout reached end-of-file, which is a * different moment: anything still holding the inherited pipe holds the reply * with it. Runs were observed sitting idle for the full ten-minute timeout with * the verdict already written and the child already gone. * * `stream-json` fixes both, because it makes the end of the answer something * lookout can SEE rather than something it has to wait for. The last line of * the stream is the result message; once that has been read there is nothing * further to wait for, whatever else is still holding the pipe open. * * This module is only the reading. It knows the envelope and nothing about * judging, which is why it can be given to the refuter, the healer and the * acceptance verifier unchanged. */ /** One thing the model did, as it did it. */ export interface JudgeSay { /** `text` is reply prose as it is written; `tool` is a tool call it made. */ kind: "text" | "tool"; text: string; } /** The CLI's terminal message: the same object `--output-format json` returns. */ export interface ResultLine { result?: string; total_cost_usd?: number; is_error?: boolean; subtype?: string; } /** * The stream, folded as it arrives. * * Chunks do not arrive on line boundaries, so a partial tail is carried to the * next push. A line that is not JSON is dropped rather than thrown on: the CLI * is entitled to print to stdout, and one stray line must not lose a verdict * that has already been paid for. */ export declare class ReplyStream { private readonly onSay?; private tail; private everything; /** The terminal message, once the CLI has sent it. */ result: ResultLine | null; /** * Every file the model asked the Read tool for, in order, whether or not * anybody is narrating. What a judge looked at is part of its verdict: a * shot it called clean without opening is not clean, and only this list * can say so. */ readonly reads: string[]; constructor(onSay?: ((say: JudgeSay) => void) | undefined); push(chunk: string): void; /** End of stream: whatever is left is a whole line or it is nothing. */ end(): void; /** Everything stdout produced, which is what an unparseable reply is reported as. */ raw(): string; private line; }