Files
oh-my-pi/packages/coding-agent/src/tools/bash-pty-selection.ts
T
Sanskar Singh cffc94a978 fix: prevent ClosePseudoConsole deadlock hanging PTY on Windows
ConPTY's ClosePseudoConsole can deadlock when it tries to flush output
to a pipe that nobody is reading (microsoft/terminal#1810). This caused
the PTY Promise to never resolve on Windows, making bash commands with
pty:true hang indefinitely.

Root cause: portable-pty's drop(master) calls ClosePseudoConsole
synchronously. If ConPTY's internal render thread is blocked writing to
a full/undrained output pipe, ClosePseudoConsole waits forever.

Fix (three parts):

1. Rust (pty.rs): Reordered teardown to follow Microsoft's recommended
   shutdown sequence:
   - Drop writer first (close ConPTY input pipe)
   - Drain reader thread with 500ms timeout (consume output pipe)
   - Drop master in a background thread with recv_timeout(2s):
     * Clean case: ClosePseudoConsole completes, thread reclaimed
     * Hung case: timeout expires, main thread returns anyway
   - Replace child.wait() with try_wait() polling on Windows
     (WaitForSingleObject can also hang in ConPTY)

2. TypeScript (bash-pty-selection.ts): Remove the Windows blanket
   disable that prevented PTY from ever being used on Windows.

3. Tests: Updated to verify PTY works on Windows with UI context.
2026-05-16 07:02:24 +05:30

15 lines
522 B
TypeScript

import { $env } from "@oh-my-pi/pi-utils/env";
/** Minimal UI-capability fields needed to decide whether bash can use the local PTY overlay. */
export interface BashPtyContext {
hasUI?: boolean;
ui?: unknown;
}
/** Return whether a bash tool call should use the local interactive PTY overlay. */
export function canUseInteractiveBashPty(pty: boolean, ctx: BashPtyContext | undefined): boolean {
if (!pty) return false;
if ($env.PI_NO_PTY === "1") return false;
return ctx?.hasUI === true && ctx.ui !== undefined;
}