/** * Tracks user inputs that have been written to the CLI's PTY but whose turn * hasn't completed yet (the CLI hasn't returned to its idle prompt since the * write). If the CLI process dies first, those inputs would otherwise vanish: * codex crashing mid-submit never records them in history.jsonl, the * auto-restarted CLI comes up idle and empty, and nothing re-delivers — the * user-visible symptom is a session stuck at 「等待输入」 that "never received" * the message (2026-06-10 incident, codex 0.137.0 exit 1 ~3s after paste). * * The worker wires it up as: * - flushPending dequeues an item and writes it → onWrite(item) * - CLI returns to idle prompt (markPromptReady) → onTurnComplete() * - CLI process exits (backend.onExit) → onCliExit() * - fresh CLI spawning (spawnCli, non-adopt) → takeCarryOver() and * unshift the result back into pendingMessages * * Trade-off: if the CLI accepted the input and died mid-turn, re-delivery * makes the restarted CLI see the prompt twice — a duplicate ask beats a * silently lost message. A false-idle blip mid-turn clears the in-flight set * early and degrades to the old lose-on-crash behavior for that turn only. */ import type { CodexAppTurnInput, VcMeetingImTurnOrigin } from '../types.js'; export type InflightItem = { content: string; logicalContent?: string; turnId?: string; replyTurnId?: string; dispatchAttempt?: number; codexAppDispatchId?: string; queuedActivationToken?: string; vcMeetingImTurnOrigin?: VcMeetingImTurnOrigin; codexAppInput?: CodexAppTurnInput; /** At-most-once turn (idempotency lease): must NEVER be carried over to a * respawned CLI (codex #776 round-7 finding #1). See PendingCliInput.noReplay. */ noReplay?: boolean; }; export declare class InflightInputTracker { private unacked; private carryOver; /** An input just went onto the CLI's PTY. */ onWrite(item: InflightItem): void; /** Remove one exact item after a definitive local write failure before the * caller re-queues it. Covers both the live in-flight set and a synchronous * backend-exit handoff that may already have moved it to carryOver. */ forget(item: InflightItem): void; /** Retire one exact write whose transport outcome is ambiguous and must not * be replayed automatically. Other type-ahead items remain tracked. */ retire(item: InflightItem): boolean; /** CLI is back at its idle prompt — everything written has been consumed * (answered, steered into the active turn, or drained from the TUI's own * type-ahead queue). Nothing is in flight anymore. */ onTurnComplete(): void; /** CLI process died. Stash whatever was in flight for the next spawn. * Appends (rather than replaces) so a double exit before the respawn * consumes the stash can't drop the earlier batch. Returns how many * items were newly stashed by THIS exit. */ onCliExit(shouldCarry?: (item: InflightItem) => boolean): number; /** A fresh CLI is spawning: hand back everything that must be re-queued, * and reset the in-flight set (a brand-new process can't have anything * in flight — covers a previous life whose exit event never fired, e.g. * a detach-style kill). */ takeCarryOver(): InflightItem[]; } //# sourceMappingURL=inflight-input-tracker.d.ts.map