import type { CliAdapter } from '../adapters/cli/types.js'; export type IdleEvidenceSource = 'screen' | 'external'; export declare class IdleDetector { private outputTail; private lastSpinnerAt; private quiescenceTimer; private isIdle; private idleCallback; private busyCallback; private completionPattern; private idleToBusyPattern; private staticBusyPattern; private staticBusyClearPattern; private busyTransitionArmed; private readyPattern; private readySeen; /** Pre-idle latch for static busy screens (capacity queue). Set from PTY * chunks carrying explicit static-busy evidence (scanned across chunks * via the rolling tail); suppresses screen-derived idle until a chunk * with explicit composer evidence (staticBusyClearPattern) redraws. * See CliAdapter.staticBusyPattern / staticBusyClearPattern. */ private staticBusyLatch; /** Tail position of the last composer clear evidence. Queue evidence in * the tail at or before this position is stale (from before the clear) * and must not re-set the latch. -1 = no clear recorded. */ private staticBusyClearTailPos; constructor(cli: CliAdapter); onIdle(cb: (source: IdleEvidenceSource) => void): void; onBusy(cb: () => void): void; /** * Seed readyPattern evidence for a prompt that IS on screen but was rendered * before resetReadyEvidence() cleared the flag. A new session (SessionStart * source=startup) never redraws after that boundary, so Strategy 2's * `!readySeen` early return would suppress quiescence detection forever. * * The caller must first confirm the PTY is quiet AND the current rendered * screen matches readyPattern. This only restores readySeen — a full * quiescence check (spinner guard included) still runs on top of it, so no * existing check is bypassed. */ seedReadyEvidence(): boolean; feed(data: string): void; reset(): void; /** * Drop prompt evidence observed before a SessionStart boundary. Unlike the * ordinary per-turn reset, this does not synthesize a recent spinner: once * Claude finishes the remaining parallel hooks, its newly rendered prompt * should need only the normal quiescence window. */ resetReadyEvidence(): void; /** External idle source — lets transcript-driven detectors (Claude jsonl * Stop, Codex rollout assistant_final, CoCo events.jsonl finish_reason * stop) push idle without waiting for screen-pattern + quiescence to * agree. Idempotent within a turn (gated by isIdle); reset() re-arms it * for the next turn — same lifecycle as the internal markIdle path. */ fireIdle(): void; dispose(): void; private quiescenceCheck; private markIdle; private clearTimer; private stripAnsi; } //# sourceMappingURL=idle-detector.d.ts.map