fix(terminal): psmux wheel scrolling, per-platform tmux upgrade advice, Windows-safe server tests

- Server tests on Windows no longer reach the user's real psmux: psmux
  ignores TMUX_TMPDIR (and 3.3.x PSMUX_DATA_DIR), so quit.test.js's Quit and
  the runner's kill-server ended every live lane pane — the pre-commit hook
  included. scripts/test-server.js now takes tmux off the suites' PATH there.
- Wheel scrolling on Windows: psmux never turns mouse tracking on for its
  client, so xterm.js never reported the wheel and a pane could not scroll.
  A Windows attach is told {type:"wheel"} and the browser sends the SGR wheel
  report itself; psmux scrolls or forwards it to the pane's app.
- tmux.upgradeAdvice(): the oldest tmux AgentHub asks for and how each
  platform upgrades (psmux 3.4.0 -> winget upgrade marlocarlo.psmux; tmux 3.7
  -> brew upgrade tmux / build the release on Linux). Used by the doctor,
  GET /api/run/tmux ({available, version, upgrade}), `agenthub doctor`, and a
  sticky toast on the Workspace page. Advice only: nothing installs tmux.

Committed with --no-verify (user's call): the pre-commit hook runs the full
backend suite, which has ~378 pre-existing failures on Windows (S3/Linux-only
tests: sudo, /proc, systemd, members). Every test touching this change passes:
pty-attach, tmux, run, plugin-doctor-tmux, TerminalView, Workspace, and the
client tests related to the changed files; tsc and the header audit are clean.
This commit is contained in:
Nguyễn Ngọc Trí Vĩ
2026-10-15 11:46:09 +07:00
parent 7a88b74016
commit cd427d218b
19 changed files with 218 additions and 45 deletions
+17
View File
@@ -68,6 +68,23 @@ const env = {
};
delete env.TMUX;
delete env.TMUX_PANE;
// psmux (the WinGet `tmux` on Windows) ignores TMUX_TMPDIR — and 3.3.x its
// PSMUX_DATA_DIR too — so every tmux call reached the user's REAL server:
// quit.test.js's Quit killed every live lane pane, and the kill-server below
// the rest. Only `-L` isolates there, which no env var can add to each call,
// so on Windows the suites get no tmux at all; theirs skip (or fail) instead.
if (process.platform === "win32") {
const key = Object.keys(env).find((k) => k.toUpperCase() === "PATH");
if (key) {
env[key] = env[key]
.split(path.delimiter)
.filter(
(d) => !["tmux.exe", "tmux.cmd", "tmux.bat"].some((f) => fs.existsSync(path.join(d, f)))
)
.join(path.delimiter);
}
delete env.PSMUX_SESSION;
}
// Git exports these to a hook it runs from a linked worktree (the pre-commit
// hook runs this suite): inherited, every `git init`/`commit` a test makes in
// its temp folder went to the REAL repository instead — commits on the