mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-20 01:11:18 +00:00
fix: reset terminal state before interactive session handoff (#1934)
* fix: reset terminal state before interactive session handoff The stdin handoff from TS orchestration to the interactive SSH session was leaving the terminal in a dirty state, causing users to need 2+ Enter presses or random keystrokes before input worked. Three fixes: 1. Unconditionally call setRawMode(false) instead of checking isRaw first — @clack/core's close() already resets the flag but the terminal can still be dirty after multiple readline instances 2. Run `stty sane` to fully reset the terminal line discipline, undoing any damage from readline's emitKeypressEvents 3. Resume stdin instead of pausing it — Bun.spawn with stdio:"inherit" needs an active stream, a paused stdin causes the child to see blocked input Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: fix Biome formatting for Bun.spawnSync call Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: spawn-bot <spawn-bot@openrouter.ai> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com> Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
This commit is contained in:
parent
b6f021ecf2
commit
556f32ecfc
2 changed files with 38 additions and 9 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@openrouter/spawn",
|
||||
"version": "0.10.15",
|
||||
"version": "0.10.16",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"spawn": "cli.js"
|
||||
|
|
|
|||
|
|
@ -263,15 +263,44 @@ export function sanitizeTermValue(term: string): string {
|
|||
}
|
||||
|
||||
/** Prepare stdin for clean handoff to an interactive child process.
|
||||
* Removes listeners, resets raw mode, and pauses stdin
|
||||
* so that child_process.spawn gets a pristine file descriptor. */
|
||||
* Removes listeners, resets raw mode, and restores the terminal
|
||||
* so that Bun.spawn with stdio:"inherit" gets a clean fd 0. */
|
||||
export function prepareStdinForHandoff(): void {
|
||||
// Remove any leftover keypress/data listeners (from @clack/prompts, etc.)
|
||||
// Remove any leftover keypress/data listeners (from @clack/prompts, readline, etc.)
|
||||
process.stdin.removeAllListeners();
|
||||
// Reset raw mode if it was left on by @clack/prompts
|
||||
if (process.stdin.isTTY && process.stdin.isRaw) {
|
||||
process.stdin.setRawMode(false);
|
||||
|
||||
// Unconditionally reset raw mode — @clack/core's close() may have already
|
||||
// called setRawMode(false) making isRaw report false, but the terminal
|
||||
// can still be in a dirty state after multiple readline instances
|
||||
if (process.stdin.isTTY) {
|
||||
try {
|
||||
process.stdin.setRawMode(false);
|
||||
} catch {
|
||||
// ignore — not a TTY or already closed
|
||||
}
|
||||
}
|
||||
// Pause stdin so Node/Bun stops buffering input before the child takes over
|
||||
process.stdin.pause();
|
||||
|
||||
// Reset terminal line discipline via stty to undo any damage from
|
||||
// readline's emitKeypressEvents or leftover raw mode. This is the
|
||||
// nuclear option that guarantees the terminal is in cooked mode with
|
||||
// proper echo and line editing before SSH takes over.
|
||||
try {
|
||||
Bun.spawnSync(
|
||||
[
|
||||
"stty",
|
||||
"sane",
|
||||
],
|
||||
{
|
||||
stdin: "inherit",
|
||||
stdout: "ignore",
|
||||
stderr: "ignore",
|
||||
},
|
||||
);
|
||||
} catch {
|
||||
// ignore — stty may not be available
|
||||
}
|
||||
|
||||
// Resume stdin so Bun.spawn inherits an active fd 0. A paused stream
|
||||
// can cause the child process to see a blocked/empty stdin on Bun.
|
||||
process.stdin.resume();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue