Add ⌘S hotkey to open a task's merge confirmation

This commit is contained in:
Ian Gulliver
2026-10-15 12:30:10 -07:00
parent a855933dee
commit 7ea14bd7a8
7 changed files with 73 additions and 31 deletions
+2 -2
View File
@@ -126,7 +126,7 @@ Each user has one long-running lead agent, shown in the left pane. It is not tie
- **Compaction.** The pane's **Compact** button asks the lead for a handoff (`leadHandoffPrompt`). The lead can also call `compact_self` at a logical point; when that turn ends normally, byre sends the same request. The handoff turn ends the session, and a new lead session starts from `leadHandoffPreamble` plus the handoff; held input follows once that turn ends.
- **Restarts.** On shutdown, byre marks each running lead session idle with "byre stopped mid-turn" and holds a restart notice for it, so a lead is never left `running` for a build without lead support to find. After a crash, startup resumes a running lead like a task session. Startup then delivers any held input.
The UI is two panes: the left is the lead's transcript and composer (the same view as a task transcript, with only the Compact button in its header), the right shows the focused task, or project with no task, with the Transcript, Changes, Files, Terminal, Inbox and Project tabs, the lead's `tabs` first. ⌘P (Ctrl+P elsewhere) selects the Project tab, keeping the right pane's task, and replaces the browser's print shortcut.
The UI is two panes: the left is the lead's transcript and composer (the same view as a task transcript, with only the Compact button in its header), the right shows the focused task, or project with no task, with the Transcript, Changes, Files, Terminal, Inbox and Project tabs, the lead's `tabs` first. ⌘P (Ctrl+P elsewhere) selects the Project tab, keeping the right pane's task, and replaces the browser's print shortcut. ⌘S (Ctrl+S elsewhere) opens the right pane's task's Merge confirmation, from any tab, when the Merge button would be enabled, and replaces the browser's save shortcut.
## TODO
@@ -192,7 +192,7 @@ The view shows a breadcrumb from `worktree` down to the current directory or fil
Each active task can have one terminal: a login shell (`$SHELL -l`, from byre's environment) on a PTY (`github.com/creack/pty`), started in the task's worktree with byre's environment plus `TERM=xterm-256color`, `COLORTERM=truecolor` and the task's `PORT` (`internal/server/terminal.go`). `GET /api/tasks/{taskId}/terminal?cols=&rows=` is a WebSocket (`github.com/coder/websocket`), the only WebSocket in byre: it attaches to the task's terminal, starting the shell at that size if none is running, and works only while the task is active (409 otherwise). The server first sends the last `terminalBacklog` bytes the terminal printed, then its output as it comes, as binary messages; the client sends keystrokes as binary messages and a `TerminalSize` JSON text message on every resize. Any number of sockets can attach to one terminal: they all get its output and all type into it, and the last resize wins. A socket that falls `terminalClientBuf` reads behind is closed and the page reconnects. When the shell exits, every socket is closed with code 4000 and the exit status (`exit status 0`, `signal: hangup`) as the reason, and the next attach starts a new shell. Merging or discarding the task, and stopping byre, sends the shell's process group SIGHUP and closes the PTY, so terminals don't survive a restart. The WebSocket handshake checks that `Origin` matches `Host`, so another site can't open one through the user's Tailscale identity. The log records `terminal started` and `terminal ended` with the task, pid and exit status.
The **Terminal** tab (`web/src/terminal.ts`) draws it with xterm.js, vendored like Mermaid: `web/package.json` pins `@xterm/xterm` and `@xterm/addon-fit`, and `go generate ./web` copies their ES module builds, `xterm.css` and licenses into `web/vendor/`. Nothing loads them until the tab first opens, which imports the modules, adds the stylesheet and waits for the font. The terminal uses the UI font and is coloured from the custom properties in `web/style.css` (background, text, accent cursor, accent-tint selection); ANSI colours are xterm.js's defaults. It fits the pane and resizes with it. Opening the tab, or selecting another task while it is open, opens one socket for the selected task; switching tab or task closes it, and the shell keeps running, so coming back replays its recent output. A socket that drops for any other reason reconnects after 2s while the task is active; after a byre restart that starts a new shell. When the shell exits the header shows `shell ended: <status>` and a **New shell** button; when it can't be started (the socket closes with 1011, the error in byre's log as `start terminal`), the header says so, with the same button to try again. Ctrl key combinations typed in the terminal go to the shell, not to byre's Ctrl+K and Ctrl+P shortcuts; ⌘K and ⌘P still work.
The **Terminal** tab (`web/src/terminal.ts`) draws it with xterm.js, vendored like Mermaid: `web/package.json` pins `@xterm/xterm` and `@xterm/addon-fit`, and `go generate ./web` copies their ES module builds, `xterm.css` and licenses into `web/vendor/`. Nothing loads them until the tab first opens, which imports the modules, adds the stylesheet and waits for the font. The terminal uses the UI font and is coloured from the custom properties in `web/style.css` (background, text, accent cursor, accent-tint selection); ANSI colours are xterm.js's defaults. It fits the pane and resizes with it. Opening the tab, or selecting another task while it is open, opens one socket for the selected task; switching tab or task closes it, and the shell keeps running, so coming back replays its recent output. A socket that drops for any other reason reconnects after 2s while the task is active; after a byre restart that starts a new shell. When the shell exits the header shows `shell ended: <status>` and a **New shell** button; when it can't be started (the socket closes with 1011, the error in byre's log as `start terminal`), the header says so, with the same button to try again. Ctrl key combinations typed in the terminal go to the shell, not to byre's Ctrl+K, Ctrl+P and Ctrl+S shortcuts; ⌘K, ⌘P and ⌘S still work.
## Snapshots