acpmux: Take over holds the managing agent's messages until Hand back
Leo asked for a ChatGPT-style "X is managing this chat [Take over]" on chats that Chief or another agent runs. #30765 adds the banner; this PR makes Take over actually stop the manager, in acpmux. This is item 3 of the agent group-chats plan.
What changes
-
New method
_acpmux/agent_hold {sessionId, held}(capabilityagent-hold-v1).held: true(Take over) tags the chatacpmux.agentHold. From then on, the pair guard (hub/agent_pairs.rs) holds every message from the chat's manager as a pause with reasontaken_over. Held messages are kept across restarts, as the guard already does.held: false(Hand back) removes the tag and delivers the held messages in order.
-
Manager means:
- the session that started the chat (
startedBy,spawnedBy), - its
delegator, - or, for a chat a Chief started (
mux.parent = optchat-chief[:<home>]), any turn of that Chief (cmux.chief = <home>).
Other agents' messages pass as before.
- the session that started the chat (
-
The person's own prompts into a taken-over chat run, and release nothing.
agent_pair_resume_inner(by: "person")skips pairs that a hold keeps. -
Only the person can take over or hand back. The method requires
local_personand is refused from web origins (remote_guard)._acpmux/tagrefuses the hold tag to anyone but the person (person.rs), so a manager cannot lift its own hold. -
The hold applies even when the pair guard is switched off.
-
Wired through
rpc.rs,protocol/mod.rsand the spec json,capabilities.rs,requests.rs,agent_messages.rsandpeer_forward.rs(daemon-own). -
Pane policy:
policy.json(gesturealways, paramssessionId,held) and its test cases.- The Swift mirror (
AcpmuxPaneMethods*.swift). - The webview's generated
methods.ts. direct.tsagentHold(held).
-
Wiring the banner's Take over to
agentHold(plus a Hand back line) is a follow-up once #30765 lands.
Tests
tests/hub_integration/agent_pairs.rs:a_taken_over_chat_holds_its_managers_messages_until_handed_back:- An agent cannot take over.
- The Chief's messages are held with trip
taken_over. - Another agent passes.
- The person's prompt runs and releases nothing.
- The manager can't lift the tag.
- Hand back delivers 3 messages in order.
- Later messages pass.
another_chiefs_turn_is_not_the_manager.
- Fleet (
cmux-ci test):cargo test -p acpmux --test hub_integration agent_pairs: 26 passed.cargo test -p acpmux --lib: 2572 passed.cargo test -p cmux-agent-pane-policy: all pass, includingthe_allowlist_is_what_the_page_sends.cargo clippy -p acpmux --all-targets -D warnings: clean.cargo fmt: clean.- Webview
bun run check: 0 lint errors, no type errors.
Risk
acpmux message delivery (state machine). It changes behaviour only for chats carrying the new tag, which only the person sets. The pair guard's paths for untagged chats are unchanged, apart from the guard-off early return moving below sender resolution.
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
Implements Take over / Hand back for agent-run chats in acpmux: the person can now stop a managing agent's messages on a chat and hold them until handing the chat back.
New Features
_acpmux/agent_hold {sessionId, held}(capabilityagent-hold-v1) tags the chatacpmux.agentHold; the pair guard then holds the manager's messages as ataken_overpause, kept across restarts, andheld: falsedelivers them in order.- The manager is the session that started the chat, its delegator, or the Chief that started it; other agents' messages and the person's own prompts pass as before, and a prompt releases nothing.
- Only the person on this machine can take over or hand back, the hold applies even when the pair guard is off, and the manager cannot lift the tag.
- Wired through rpc, the protocol spec, pane policy, the Swift mirror, and the webview (
agentHoldindirect.ts); wiring the take-over banner is a follow-up.