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:
@@ -665,6 +665,25 @@ export function Workspace() {
|
||||
const { local } = usePermissions();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
// The server's tmux is older than this platform needs (psmux < 3.4.0 on
|
||||
// Windows, tmux < 3.7 elsewhere): say how to upgrade it, until it is.
|
||||
// Sticky (an error toast) so the command can be copied. An older server or
|
||||
// no answer says nothing.
|
||||
useEffect(() => {
|
||||
let live = true;
|
||||
(async () => {
|
||||
try {
|
||||
const { upgrade } = await api.run.tmuxAvailable();
|
||||
if (live && upgrade) toast.error(tLanes("tmuxUpgrade", { advice: upgrade }));
|
||||
} catch {
|
||||
/* nothing to say */
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
live = false;
|
||||
};
|
||||
}, [tLanes]);
|
||||
|
||||
// Lane state: the list is the shared store the sidebar reads too; the
|
||||
// selection is the URL's `?lane=` (the sidebar sets it, so does a
|
||||
// notification click), falling back to the last one shown, then the first.
|
||||
|
||||
@@ -459,6 +459,23 @@ describe("Workspace page — lane integration", () => {
|
||||
});
|
||||
|
||||
describe("Workspace layout", () => {
|
||||
it("asks the user to upgrade a tmux older than their platform needs", async () => {
|
||||
const { toast } = await import("../../lib/toast");
|
||||
const shown = vi.spyOn(toast, "error");
|
||||
const run = api.run as unknown as Record<string, unknown>;
|
||||
run.tmuxAvailable = vi.fn().mockResolvedValue({
|
||||
available: true,
|
||||
version: "3.3.2",
|
||||
upgrade: "psmux 3.3.2 is older than 3.4.0 — winget upgrade marlocarlo.psmux",
|
||||
});
|
||||
onTestFinished(() => {
|
||||
delete run.tmuxAvailable;
|
||||
shown.mockRestore();
|
||||
});
|
||||
await renderWorkspace();
|
||||
expect(shown).toHaveBeenCalledWith(expect.stringContaining("winget upgrade marlocarlo.psmux"));
|
||||
});
|
||||
|
||||
it("shows no empty banner when there is no workspace (the sidebar's + adds one)", async () => {
|
||||
lanesToReturn = [];
|
||||
await renderWorkspace();
|
||||
|
||||
Reference in New Issue
Block a user