Skip to main content

answer_conpty_handshake_if_seen

Function answer_conpty_handshake_if_seen 

Source
pub(super) async fn answer_conpty_handshake_if_seen(
    state: &AppState,
    block_id: &str,
    baseline_len: usize,
)
Expand description

Answer Windows ConPTY’s own startup handshake, if seen, before the caller proceeds. Discovered live (not assumed): the moment a Windows ConPTY is created, it queries the cursor position (ESC[6n, Device Status Report) and blocks its own internal state — and therefore every later write — until it sees a ESC[<row>;<col>R reply. A human-facing term pane gets this for free because xterm.js, running in the browser, answers real cursor queries as part of being an actual terminal emulator; this headless facility has nothing playing that role, so without this the PTY would sit permanently stuck before printing even its first prompt — confirmed by a live round trip that hung indefinitely until this was added. ESC[1;1R (cursor at row 1, col 1) is a plausible-enough fixed answer: nothing here has rendered anything yet, so “top-left” is as true as any other coordinate, and ConPTY only wants to reconcile its internal buffer, not validate the value against anything a person would see.

baseline_len MUST be the “term” file’s byte length taken immediately before resync_controller ran (0 for a genuinely new block) — see the call sites. Only bytes appended AFTER that offset are ever inspected. Not safe to scan the whole file regardless of reuse/fresh (an earlier version of this function did exactly that): the “term” file is append-only for the block’s entire lifetime (handle_append_block_file’s FILE_OP_APPEND), so a long-running reused shell’s history almost always still contains its own original, long-since-answered ESC[6n from whenever it first started — matching against that stale byte sequence would inject an unsolicited ESC[1;1R into whatever a human is doing RIGHT NOW on that shell (Codex P1 on PR #3194, confirmed live before this fix: create on an already-running reused shell always found the old query and misfired). The baseline makes every case correct uniformly: nothing new appears (the common reuse case) → correctly finds nothing; resync_controller had to respawn a dead process → correctly sees only ITS fresh query, never anything from the block’s former life.