agent pane: a paused Cloud machine's chat says paused and offers Resume
A chat whose Cloud machine is paused now says the machine is paused and offers Resume. Before, the banner over the chat said the machine was offline, with nothing to do about it. While the machine starts, the banner shows a spinner and "Starting" in place of a second Resume.
Leo, 2026-10-28: "whatever's convenient for cloud, like that can be productionized, operationalized, we ought to just put out there". The Cloud state-of-affairs issue (cmuxterm-hq#4755), quoting Leo: "we want to get a lot of good stuff wrt the pausing and resuming and how it integrates with acpmux + the gui chat". This PR fixes one item on its gap list: a paused machine's chat reads "offline", and the pane has no Resume. The chat-menu half (Pause and Resume rows) is cmux#26872.
What changed (webviews only)
peerCloudMachine.ts(new):- It matches an offline peer chat to the account's Cloud machine by name, in any case, the way the app matches a peer to a machine.
- It says whether the machine is
pausedorstarting; a Resume this page asked for counts as starting. usePeerCloudMachinereads the account's machine list once when the chat's machine goes down.
PeerCopyBanner.tsx: a machine the account lists as paused reads " is paused", with Resume. One that is starting reads "Starting …" with the sharedSpinner, never a pulsing dot. Anything else reads offline, as before.App.tsxpasses the hook's state andresumeto the banner.- Resume goes through the existing
cloudMachine.resumebridge method. That method takes one click, and the app runs it only on a paused machine from the account's list. After Resume, the list is read again, so a refused Resume leaves the machine paused with Resume back. - Timer: the list is read every 3 s, only while the machine starts. It stops when the machine leaves the starting stages, when the chat's machine answers again, or when the banner unmounts (effect cleanup,
clearInterval). There is no other timer or observer. - Strings:
peerCopy.paused.title,peerCopy.paused.resumeandpeerCopy.starting.title, in all 21 locales.
Design choice (gallery agent-pane.peer-copy-paused, experiment paused-machine-resume, 3 arms):
actions(ships): Resume in an actions row under the banner's text.inline: Resume as a link at the end of the first line.button: a small filled button at the trailing edge of the first line.
I picked actions because it matches the watch and open-elsewhere banners in the same pane, which put their choices in that row with the same button. The other two arms make this banner look different from its neighbours: a filled accent button is louder than anything else in the pane, and an inline link is easy to miss in a two-line banner.
Gating: none. This fixes the existing offline banner, which every user already sees on a peer chat whose machine stops answering. Only a machine the account lists as paused or starting changes what it says. Without Cloud machines, nothing changes.
Captures: the before/after captures are the gallery variants before, paused, starting and paused-no-time in agent-pane.peer-copy-paused (the gallery advisory run on this PR).
Risk: low. Webview only, no new bridge method, and at most one list read, plus the 3 s reads while a machine starts.
Tests (test/agent-pane-peer-copy-paused.test.tsx, cmux-ci Linux, together with the peer-copy, gallery-entry, coverage and strings suites; bun run check passes):
- a paused machine's chat says it is paused, and Resume starts it once;
- a starting machine is read again until it leaves the starting stages, and no read outlives the banner;
- a machine the account does not list, or one that is ready, reads offline as before;
- each arm of
paused-machine-resumeputs Resume where it says.
Agent session: agent session
🤖 Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
A chat whose Cloud machine is paused now says the machine is paused and offers Resume, instead of reading "offline" with nothing to do about it. While the machine starts, the banner shows a spinner and "Starting".
Details
- The offline chat's peer is matched to the account's Cloud machine by name, only when no other of the account's machines shares the name and the peer is not an ssh peer; the machine list is read once when the chat goes down and every 3 seconds only while it starts, capped at 60 reads.
- A Resume belongs to the machine it was asked for; another peer never reads as starting because of it.
- Resume runs the existing
cloudMachine.resumebridge, which consumes one click; a refused Resume leaves the machine paused, with Resume back. paused-machine-resumecompares three Resume placements; the actions row (matching the watch banner) ships, andinlineandbuttonarms stay in the gallery.- Webview-only with copy in all 21 locales; without a Cloud machine match, the banner reads offline exactly as before.