Add destination-aware New Agent Chat

Merged
TE
7d ago
+2536-347

Adds “New Agent Chat on…” using the same acpmux status peers and signed-in account Cloud inventory consumed by the composer Environment picker. Offline peers stay visible and disabled with their actual state. Ready Cloud destinations connect through the existing machine path before opening a chat. Palette selection forwards to the shared New Agent Chat action, also exposed as cmux agent new-chat --cwd /tmp --harness codex --model M --host H and through MCP. --machine is an alias for --host.

Explicit startup arguments survive the targeted and untargeted creation paths, seed peek/take, and page handshake; --cwd /tmp reaches the new chat instead of being dropped. No-argument Cmd-I retains its existing dock/inheritance behavior. Environment and model picker components and defaults are unchanged. Remote model selection uses an additive capability; an old daemon refuses an explicit unsupported model rather than silently using its default.

Leo: “Are you guys able to, like, okay, simultaneously, like through the CLI and through commands, through maybe even slash commands in the command palette, are you able to do stuff? Am I able to do stuff, like with this current version of the app? And in addition, of course, like clicking around, starting up a new workspace, a new tab, a new chat. How ergonomic is that? Are the things properly exposed?”

Observed / Not run

Latest Swift repair at 9bc791af951f98b4473083dfe55ee71ea1a30da8: a Cloud chat seeded with a harness and model now inherits that model only while the effective harness still matches the seed. Choosing another harness's default before Send no longer restores the previous model. The tests-first ancestor 9e96ca338b6b32ca6eb0dcc838311f2cd42724b6 adds six cases through the real remote-start client and a bounded daemon socket, observing the actual start request and resulting remote session. It covers changed-harness default selection, unchanged-harness inheritance, and explicit model overrides. Red-first and final focused Mac execution plus a fresh independent review are pending; the earlier Mac receipt does not validate this new Swift delta. Static checks and primary diff review pass. Web sources/tests are unchanged from the passing run at f875db35ba83522bd06f8b548e7d081ee0c225bc (web tree 454d181a09dd6b3ba36a8e5974e11e4cbb95002c).

Focused final Mac command: cmux-ci run --class light --script scripts/ci/package-test-lane.sh --ref 9bc791af951f98b4473083dfe55ee71ea1a30da8 --arg=suite --arg=Packages/macOS/CmuxNext --arg=AgentTabRemoteStartTests,AgentChatInUnshownPaneTests,AgentChatDestinationsTests,AgentChatDestinationActionTests.

The latest web-only repair keeps the seeded peer when a failed startup is retried through the actual composer Send action. Local prewarming stays disabled while that peer startup is pending. The tests-first run 40868154083 at 3fcdb86bc935ed084b24cdfb94224323e7f01f2c passed full web checks and 13 tests, but failed the new browser regression: typing a prompt and pressing Enter sent it to local-session-1 instead of peer-session-1. The fixture accepts local starts so wrong routing cannot hide behind another rejection. It also verifies one connection, remote cwd/harness/model, peer persistence and no local prewarm. Exact-head repaired run 40868640127 passes all 14 tests with 69 assertions, plus full formatting, lint, type and protocol checks (source/head f875db35ba83522bd06f8b548e7d081ee0c225bc, tree b183edc0b7ec0a17a5968bd94e4b8dbf72efdfef, exit 0). Swift sources and tests are unchanged from the final Mac receipt below.

The latest repair retains Cloud catalog identities when their names match peers; raw and prefixed Cloud UUIDs remain selectable with the Cloud machine’s own state. A successful peer start also consumes its remote folder, so a subsequent local chat cannot inherit it. Tests-first run 40861950540 at 867294fbf3b7f7eb0f9662c3de6067e96865e423 reproduced both remote-folder leakage cases (8 pass, 2 fail); the explicit local-inheritance test passed. Repaired web run 40862282590 targeted d134a3dccbbae7e9fec5cbee23710d263c29af39; the final delta only strengthens a Swift assertion to require concrete workspace IDs. The exact final-head run 40863563011 passes all 13 tests with 53 assertions, plus full formatting, lint, type and protocol checks. Its source and final SHA both equal bba8c8a839f7ce18324c10c004feab7c139857ed (tree cd65917c9079af976eda092d3494d3a4b33989dc, exit 0).

Current head: 9bc791af951f98b4473083dfe55ee71ea1a30da8. Static prepush checks and git diff --check pass. The earlier focused web run 40858020485 passes all 10 tests, with 43 assertions, plus the full web formatting, lint, type and protocol checks. Formatting produced no diff. No local builds or test suites were run.

The tests-first run 40857373140 at 60ada1ab167feeb41702062c4bf719be5b5068ad had 7 passes and 3 failures: rejected peer folder/model startup and subsequent Send losing the peer. The repaired browser tests prove one handshake, one live connection and one creation attempt after a rejection, then a successful corrected retry and persistence on the same connection. A rejected startup now reports the error on that connection; it does not enter handshake backoff. A later Send retains the seeded peer and folder until creation succeeds. Successful creation consumes the optional harness/model/peer startup choices.

Focused web command: CMUX_BROWSER_TESTS=1 bun test --timeout 120000 test/agent-pane-peer-chat.test.ts test/agent-chat-seed-start.test.ts from webviews/, through cmux-ci test --setup playwright. The earlier startup-model regression also has red/green evidence.

Final-head Mac step b37281515b78b493bbafdc47 at bba8c8a839f7ce18324c10c004feab7c139857ed passed AgentChatDestinationsTests (5 tests), AgentChatDestinationActionTests (6 tests, all parameterized cases), and both targeted/untargeted created-page cwd tests. The only failures were the two unchanged legacy tests aScriptOpensAChatInAWorkspaceNoWindowShows and aScriptOpensAChatInAShownPaneWithoutChangingItsSelection: the same tab-membership assertions failed on the same machine at merge base 67053da36d1f9f64cdae110669976723c53703b8 (step ce108610d4fcd0491195d8d2). No crash occurred. Those legacy tests also passed in the product-identical d134a3dc run on another fleet Mac (step cef436cd6a1de11ec97e7859), confirming the machine-dependent failure.

Mac red-first step 1c556569362516668c67ffe6 at tests-only head 867294fbf3b7f7eb0f9662c3de6067e96865e423 failed three catalog tests because same-name Cloud entries and stable ID routes were missing; all pass in the repaired runs. The fixtures await tracked creation and the authoritative tab, and isolate the external handshake host while retaining real daemon folder resolution. Local tests request /private/tmp literally and assert exact created-page cwd equality. Explicit targets assert the exact pane; untargeted actions assert the same workspace while preserving chat-dock placement.

Mac command: cmux-ci run --class light --script scripts/ci/package-test-lane.sh --ref bba8c8a839f7ce18324c10c004feab7c139857ed --arg=suite --arg=Packages/macOS/CmuxNext --arg=AgentChatInUnshownPaneTests,AgentChatDestinationsTests,AgentChatDestinationActionTests.

Resolved dependency: #26809 repairs the broad Swift test harness; this PR has no product-code dependency on it. The blanket Swift hold is resolved for this PR because focused Mac step b37281515b78b493bbafdc47 covered every new Swift case on the unchanged harness, completed without a crash or cut-short run, and its only two failures match the same named tests and errors on base step ce108610d4fcd0491195d8d2. The Swift package tree is identical at the earlier head f875db35ba83522bd06f8b548e7d081ee0c225bc and the tested head bba8c8a839f7ce18324c10c004feab7c139857ed: 3d2660a98999b970c812b2eabe640d7201a86121. Landing this PR no longer waits for #26809.

Fresh-home live session-state proof, public-fixture before/after palette captures and independent exact-head review at 9bc791af951f98b4473083dfe55ee71ea1a30da8 remain pending. Created-page cwd tests do not replace live session cwd/harness/model and peer sidebar evidence.

Overlap: #25405 and #23071 touch the creation flow in AgentHandlers.swift and AgentHandlers+Pane.swift; #23071 also overlaps the seed/ready handling in AgentPaneHandshakeReply.swift. These changes stay on this PR’s branch; whichever overlapping PR lands later rebases. This is one creation lifecycle across the native action, page and remote protocol. The larger diff includes 390 lines of translations plus regression coverage, so splitting would leave incomplete argument routing.

Risk: an explicit destination now reads live availability before creating the tab. Unknown/offline destinations fail without a local fallback; account ownership is rechecked after Cloud connection. No reverse relay allowlist or trust policy changes are introduced. Palette styling and fade remain unchanged; cached rows show immediately and refresh work is canceled with the page.

Review and verification at 9bc791af

  • Independent review (Codex gpt-6-astra, high): the full PR at f875db35 had one finding (the model fallback ignored a harness switch); the delta f875db35..9bc791af fixes it, SHIP.
  • Fleet Mac, red first: at 9e96ca33 (tests only) changingHarnessBeforeSendUsesItsDefaultModel fails (the Claude seed model was sent to Codex); at 9bc791af AgentTabRemoteStartTests 3/3 (6 cases), AgentChatInUnshownPaneTests 4/4, AgentChatDestinationsTests 5/5, AgentChatDestinationActionTests 6/6, with no crash and no cut-short run.
  • The web tree is unchanged since f875db35; web receipt run 40868640127 (14/14) carries.

Before / after (fresh home, fleet capture, live peer)

A second acpmux daemon runs in the capture slot as peer pf (a fake harness, its own temp home). Acceptance at 9bc791af:

  1. cmux agent new-chat --host pf --cwd /private/tmp opens the chat on the peer (session/new answered "peer":"pf"; no local session).
  2. Composer Send runs on the peer (session/prompt answered "peer":"pf").
  3. First start refused by the peer (trust.pending); the composer Send retries session/new on pf, not locally, and the prompt is answered there.
  4. Palette: "new agent chat on" selects "New Agent Chat on…" (base 67053da3 selected "Animations…"). Text readout only: the capture driver can't image the palette panel.
  5. A peer whose daemon is down is refused ("the machine is not connected"), with no local fallback (checked at f875db35).

Known follow-up: after the retry in (3) succeeds, the stale "Trust tmp?" card from the refused first start stays visible; it gets its own PR.

Composer New Chat on a peer host, retry after a failed first start:

LightDark
lightdark

New Agent Chat on a peer host, prompt runs on the peer:

LightDark
lightdark

Changelog

Added: Choose a peer or Cloud machine when starting an agent chat, and pass a folder, harness and model through CLI or MCP.

agent-identity footer --repo manaflow-ai/cmux: https://cmux.com/deeplink/agent?id=aid-812ea78d4e52585d9c37