fix(tui): clipboard copy on linux/wayland
`probeLinuxCopy` and `copyNative` in `osc.ts` await `execFileNoThrow` for wl-copy / xclip / xsel. Those tools double-fork a daemon that holds the system selection live, and the daemon inherits stdio pipes from `spawn(stdio: 'pipe')`. Node's 'close' event only fires when stdio is fully closed → the daemon keeps the pipes open → 'close' never fires → the await leaks past the timeout (kill(SIGTERM) on an already-exited child is a no-op, daemon survives). Result: `linuxCopy` cache stays `undefined` permanently, the actual copy never runs, ctrl-c silently does nothing on wayland/x11. Reproduced in isolation, confirmed across wl-copy and a daemonization-shaped fixture. Fix: add `resolveOnExit` option to `execFileNoThrow`. When set, the promise settles on the immediate child's 'exit' event instead of waiting for stdio drainage. Wired into both the probe and the actual copy spawns for every clipboard tool (pbcopy, wl-copy, xclip, xsel, clip). Tests: 5 new vitest cases covering daemon-style child handling, non-zero exit propagation, timeout behavior, and double-resolve guard. The forever-hang case is committed as `it.skip` with documentation so a reviewer can verify the bug by hand.
This commit is contained in:
@@ -345,7 +345,7 @@ export const coreCommands: SlashCommand[] = [
|
||||
return sys(`copied ${text.length} characters`)
|
||||
} else {
|
||||
return sys(
|
||||
'clipboard copy failed — try HERMES_TUI_FORCE_OSC52=1 to force the escape sequence; HERMES_TUI_DEBUG_CLIPBOARD=1 for details'
|
||||
'clipboard copy failed — try HERMES_TUI_FORCE_OSC52=1 to force the escape sequence'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user