agent pane: Pause and Resume a Cloud chat's machine from the chat menu
A chat on one of the account's Cloud machines now has Pause Machine and Resume Machine in its chat menu, wired to the machine's own pause and 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". Its gap list says "A manual or billing pause can cut a live turn without warning." This PR is the chat-menu half of the pause/resume work. The banner half, a paused machine's chat reading "paused" with Resume instead of "offline", is the companion PR.
What changed
- Webview (
webviews/src/agent-session/acpmux/cloudMachineMenu.ts, wired inApp.tsx's chat menu):- A Cloud chat whose peer is one of the account's machines (matched by name, any case, as the app matches a peer to a Cloud machine) gets one row before the tools group:
- Pause Machine while the machine is
ready; - Stop and Pause Machine while the chat's turn runs, which sends
chat.cancelfirst; - Resume Machine while the machine is paused;
- nothing while it starts or has failed.
- Pause Machine while the machine is
- Stopping the turn first means the turn ends as stopped, on the chat and on its hand-off (cmux#26864 reports it), instead of freezing mid-call while the machine sleeps.
- A stop request returns before the turn stops. So Stop and Pause waits for the chat's turn to end, for at most 10 s (
STOP_WAIT_MS), and pauses nothing if the turn still runs then or the stop was refused. - The app runs pause and resume in the background. After each pick, the account's list is read at 0, 1, 2, 4 and 8 s (
ACTION_READS_MS), after any read already in flight, and the reads stop once the machine's stage moves. The list is also read when a Cloud chat shows.
- A Cloud chat whose peer is one of the account's machines (matched by name, any case, as the app matches a peer to a Cloud machine) gets one row before the tools group:
- Timers:
- The stop wait's timeout is cleared when the turn ends, and otherwise ends by itself after 10 s.
- The post-pick reads end at the stage change or after the fifth read (15 s).
- Nothing else repeats.
- Swift (
CmuxNextAgentPane/AgentPaneCloudMachineRequest.swift,CmuxNextApp/Cloud/AgentPaneCloudMachines+App.swift):- The pane bridge gains
cloudMachine.pause {id}. Like Open and Resume, it takes one user gesture. - The app runs it as its own
cloudPauseMachineaction, only on a machine of the loaded list whose status isrunning.
- The pane bridge gains
- Gating: behind Labs > Preview features (
labs.previewFeatures, off by default), the same gate as the account's Cloud machines in the composer's machine list. So it is off for everyone until Preview is on. - UI rules: the rows are ordinary chat-menu rows. The menu opens on the click with no fade-in, and the menu's own trigger keeps its lit state while open (ChatHeaderTools, unchanged). There is no new working indicator.
Visual evidence
Gallery: agent-pane.header-tools/menu-open, agent-pane.header-tools/menu-cloud-machine-running, agent-pane.header-tools/menu-cloud-machine-working, agent-pane.header-tools/menu-cloud-machine-paused
No capture: the Swift side adds only a bridge request and an app action, no native view; the visible change is the webview chat menu row, shown in the gallery before/after.
Risk: low.
- The feature is off by default (Preview).
- A new bridge method is refused unless the person clicked and the machine is in the loaded list and running.
- The chat menu gains at most one row.
Tests
- Webview:
test/agent-pane-cloud-machine-menu.test.tscovers:- name matching;
- Pause, and Stop and Pause, including that the stop comes first and that a turn which hasn't stopped isn't paused;
- the stop wait ends when the turn ends, or after its timeout;
- the post-pick reads stop when the stage moves, and after the last wait;
- Resume never stops a turn;
- no row while starting, failed or not the account's;
- a refused pick still reads the list again.
- Gallery:
agent-pane.header-toolsgainsmenu-cloud-machine-running,-workingand-paused. - Swift:
AgentPaneCloudMachineRequestTestsdecodescloudMachine.pause, refuses ids outside the contract, and checks that Pause takes one gesture.
Agent session: agent session
🤖 Generated with Claude Code