import type { BackendType } from '../adapters/backend/types.js'; /** * Codex App turn liveness, driven by the app-server runner's explicit turn * activity markers. This deliberately reports "no observable progress" * rather than failure: a long-running tool may recover and emit activity * later, at which point the stalled projection clears without replaying work. */ export declare const CODEX_APP_NO_PROGRESS_TIMEOUT_MS = 90000; /** * Decide whether an existing persistent pane needs a synthetic observation. * This deliberately does not depend on pipe mode: Zellij reattaches through * its own PTY (`isPipeMode=false`) but preserves the same running CLI. */ export declare function shouldBeginCodexAppReattachObservation(input: { cliId?: string; backendType: BackendType; isReattach: boolean; }): boolean; export interface CodexAppLivenessPoll { active: boolean; stalled: boolean; /** True only on the working -> stalled edge. */ newlyStalled: boolean; /** True at most once for one submitted turn, even if it later recovers. */ shouldNotify: boolean; turnId?: string; } export interface CodexAppActivityApplyResult { accepted: boolean; phase?: 'submitted' | 'progress' | 'completed'; /** A previously rejected inter-turn prompt became authoritative. */ shouldReplayPrompt?: boolean; } export interface CodexAppStateApplyResult { accepted: boolean; busy?: boolean; tracksTurn?: boolean; /** Signed idle arrived after the tracker's explicit queue drained. */ shouldPublishReady?: boolean; atMs?: number; } /** * Signed runner state is the Codex App ready authority. Terminal prompt bytes * remain useful as a recovery hint, but PTY/tmux/Herdr/Zellij delivery can be * delayed or lost and must never publish idle ahead of the signed final queue. */ export declare class CodexAppReadyAuthority { private signedIdle; private latePromptRecoveryArmed; reset(): void; beginWork(): void; /** Returns true only for an authenticated runner's idle boundary. */ noteSignedState(busy: boolean): boolean; canPublishPromptReady(): boolean; /** Arm only after the worker cancels the exact local submit slot. */ armLatePromptRecovery(): void; /** * Consume one late terminal prompt after the cancelled slot left no tracked * work. New work, authenticated activity/state, or reset clears the arm. */ consumeLatePromptRecovery(trackerEmpty: boolean): boolean; } /** Apply a state payload from an already authenticated runner connection. */ export declare function applyTrustedCodexAppStateMarker(tracker: CodexAppTurnLiveness, authority: CodexAppReadyAuthority, payload: unknown, receivedAtMs?: number): CodexAppStateApplyResult; export declare class CodexAppTurnLiveness { private readonly timeoutMs; private readonly turns; private nextHandle; private promptDeferred; constructor(timeoutMs?: number); /** * Queue one Botmux input immediately before its control line is submitted. * Codex App's runner is serial, so only the head turn owns activity/stall * state; queued turns get a fresh clock when the head completes. */ begin(turnId?: string, nowMs?: number): number; /** Observe an authenticated runner whose in-memory turn state survived reattach. */ beginReattachObservation(nowMs?: number): number | undefined; /** Drop only the synthetic reconnect slot when signed state identifies work * as a native Goal continuation rather than a Botmux-owned turn. */ discardReattachObservation(): void; /** * Record runner/app-server activity. Activity after a stall makes the turn * working again, but the same turn will not notify the user a second time. */ noteActivity(nowMs?: number): void; /** * A signed submitted record can be the first event after worker reattach. * Recover an explicit slot when no local flush state survived the restart. */ noteSubmitted(nowMs?: number): void; /** Complete only the runner's current turn and activate the next queued one. */ completeCurrent(nowMs?: number): boolean; /** Remove the exact control-line submission that failed, preserving peers. */ cancelExact(handle: number, nowMs?: number): { cancelled: boolean; shouldReplayPrompt: boolean; }; /** Backwards-compatible shorthand for callers that only need replay state. */ cancel(handle: number, nowMs?: number): boolean; /** * A prompt is authoritative only for the synthetic reattach observation. * Returns whether no explicit/queued turn remains, so the worker can reject * a transient inter-turn prompt instead of publishing prompt_ready / idle. */ notePrompt(nowMs?: number): boolean; hasActiveTurn(): boolean; /** Drop every queued turn on CLI exit, kill, or worker reinitialization. */ clear(): void; poll(nowMs?: number): CodexAppLivenessPoll; private consumeDeferredPrompt; } /** * One flush may cancel a queued liveness slot because writeInput throws or * it returns submitted=false. Preserve the deferred real prompt across that * async boundary, but replay it only after every peer slot has drained. */ export declare class CodexAppFlushPromptReplay { private replayRequested; cancelSubmission(tracker: CodexAppTurnLiveness, authority: CodexAppReadyAuthority, handle: number | undefined, nowMs?: number): void; consumeAfterFlush(tracker: CodexAppTurnLiveness): boolean; } /** Apply an activity payload whose signed socket connection was authenticated. */ export declare function applyTrustedCodexAppActivityMarker(tracker: CodexAppTurnLiveness, payload: unknown, receivedAtMs?: number): CodexAppActivityApplyResult; //# sourceMappingURL=codex-app-turn-liveness.d.ts.map