/** * Inactivity watchdog for harness event streams: a wedged vendor CLI * that stops emitting events would otherwise park the run in `running` * forever — only reviewers had a timeout. The combinator pumps the source * iterator and re-arms a timer only when the caller's typed progress policy * accepts an event. Transport/status chatter remains observable without * turning into an unlimited lease on the child process. * * This is an INACTIVITY window, not a wall-clock cap: long runs are fine as * long as they keep talking. Distinct from cancellation by construction — * the caller decides what the timeout means (typed harness_timeout failure), * and a user cancel still routes through the run signal. */ import type { HarnessEvent } from "@claudexor/schema"; export declare class HarnessInactivityTimeoutError extends Error { readonly timeoutMs: number; constructor(timeoutMs: number); } /** * The one closed policy for the no-agent-progress window * (`runtime.harness_inactivity_timeout_ms`; its default is owned by the * config schema). Lifecycle, transport, retry, usage, error, and interaction * events stay in telemetry/UI but cannot postpone the watchdog. Interaction * waiting is handled separately by `isSuspended`: the interaction policy may * impose a finite answer deadline or disable it until * answer/cancel/terminal/restart. */ export declare function countsAsAgentProgress(event: HarnessEvent): boolean; export declare function withInactivityWatchdog(source: AsyncIterable, opts: { timeoutMs: number; /** Closed typed policy deciding which values prove useful progress. */ countsAsProgress: (value: T) => boolean; /** Called once when the window elapses; abort the stream here. */ onTimeout: () => void; /** * Legitimate-silence probe. When the window elapses while this returns * true (e.g. a question is awaiting the USER's answer), the watchdog * RE-ARMS instead of firing — waiting on a human is not a wedged harness, * while the interaction channel applies its configured finite deadline or * remains suspended until answer/cancel/terminal/restart when disabled. */ isSuspended?: () => boolean; /** Monotonic suspension transition counter. This closes the polling gap * where a wait begins and ends entirely between inactivity timer ticks. */ suspensionVersion?: () => number; /** * How long to drain the aborted source's cleanup after a timeout (or await * iterator.return on an early caller break) before giving up. MUST exceed * the source's process-reap deadline so its typed termination_unconfirmed * terminal fact surfaces; defaults to {@link REAP_PROOF_DEADLINE_MS}. */ cleanupDeadlineMs?: number; }): AsyncIterable; //# sourceMappingURL=inactivity.d.ts.map