Repository navigation
agents_wait: wait for idle, dialog or text instead of polling snapshots (cx-ncc.93) - #20810
Conversation
…x-ncc.93) Behavior tests at the MCP boundary (agents_wait listed as a bounded read, idle mid-wait, already true, timeout as an unmatched receipt, dialog, text through the daemon's terminal.wait, bad arguments refused as not_run, progress notifications) and one CLI test through a real daemon. They fail until the tool and the cmux agents wait verb exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cx-ncc.93) One code path for the MCP tool and the CLI verb (cli/agents/wait.rs). text waits on the daemon's terminal.wait; idle and dialog hold the daemon's session.events stream open and check on each event, and every second for app-only state (chat agent state, dialogs). A timeout is a matched: false receipt with a fresh state. MCP calls with a progressToken get notifications/progress; the CLI shows the long-wait notes app waits show. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ed text target, CLI exit 1 (cx-ncc.93) An invalid regex and an unknown agent named by a dialog wait are refused as not_run before any wait; a text target that closes mid-wait reports match.state closed as idle does; cmux agents wait exits 1 when it times out, as screen wait does, and still prints the receipt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…orts a closed text target, CLI exits 1 on timeout (cx-ncc.93) The regex is compiled with the daemon's crate and limits before any wait. A dialog target that names a terminal, tab or agent must exist, as for idle and text; other dialog targets may not exist yet and wait. A text target that closes mid-wait reports match.state closed. cmux agents wait prints the unmatched receipt and exits 1, as screen wait does (docs/cli-contract.md, cmux-workspace skill). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cmux-agents-wait-tool
…d (cx-ncc.93) No dialog feed item carries surface_id, and the resource API boundary check refuses the legacy word in public code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Found 1 test failure on Blacksmith runners: Failure
|
|
Landed on head e246a83 with the blocking gates green: crash ratchet, CmuxNextApp size cap and fast tier passed; react-apps-check didn't run because the PR has no web changes. The Rust build and tests passed on this exact head (focused run 38693394419; all 12 agents_wait tests ran). One red in 'cmux-next checks' comes from base: the package-conventions lint on BuiltInAdBlockerSetting.swift, which this PR doesn't touch. #20927 fixes it, and coord-standby confirmed it isn't a blocking check. The Swift Release compile doesn't apply because no Swift changed. |
Summary
An agent that waits for another agent in cmux had to poll
agents_snapshot. It can now callagents_wait(MCP) orcmux agents wait(CLI), which share one code path (cli/agents/wait.rs) and answer when the condition holds:until: idle: the agent of aterm_,tab_oragent_id, or an agent chat's session, stops working (idle, done, or blocked on a dialog;match.statesays which).until: dialog: a permission or question dialog is pending, a target's when given (theagents_dialog_listread).until: text: literal text, or a regex withregex: true, appears on a terminal's screen.timeout_secondsdefaults to 30 and is at most 120. The receipt is{until, matched, waited_seconds, match, state}, wherestateis a freshagents_snapshot-shaped snapshot cut by the #20609 receipt rule. A timeout ismatched: false, not an error; a condition that already holds answers at once. Bad arguments, an invalid regex (checked with theregexcrate, the daemon's own engine and limits) and an unknown target are refused asnot_runbefore any wait. Foruntil: dialog, aterm_,tab_oragent_target that no owner knows is refused likeidleandtext; a target of another kind is taken as a dialog request id, which may name a dialog that has not appeared yet, so that wait runs to its timeout instead of being refused. Atexttarget whose terminal closes mid-wait reportsmatch.state: "closed", the same resultidlegives.cmux agents waitexits 1 onmatched: falseand still prints the JSON receipt, asscreen waitdoes (docs/cli-contract.mdand thecmux-workspaceskill say so).The MCP server answers one request at a time, so an
agents_waitcall holds later calls on the same connection for up to its timeout (at most 120 s).terminal_waitalready behaves this way; this PR does not change it.What wakes a wait:
textis event-driven: it is the daemon's ownterminal.wait, which wakes on terminal output.idleanddialoghold the daemon'ssession.eventsstream open and check on each event (at most every 200 ms). They also check every second, because an agent chat's state and the dialog feed live in the app, whoseevents.streampublishes no event for them. So dialogs and chat-only agent state are polled at 1 s; terminal agents (daemon agent records, OSC 7501 program status) wake on daemon events. With no daemon stream, the wait checks every second.An MCP call with
_meta.progressTokengetsnotifications/progressevery 5 s (progress= seconds waited,total= timeout). The CLI shows the #20627 stderr notes for waits of 35 s or more (human output, or JSON with a TTY), with a newagents_waiting_progressstring (English and Japanese).Security: the tool is read-only (
readOnlyHint, idempotent, no key). It reads other agents' state and pending dialogs, asagents_snapshotandagents_dialog_listalready do, and a terminal's screen, asterminal_waitalready does; its description says so. Chat transcripts are not readable fortext, because no existing read exposes them. No socket method or relay policy changed;RemoteRelayCommandPolicystays deny.plans/cmux-next/mcp.mdlists the tool.Proof
Behavior tests: eleven at the MCP boundary (nine originally, two added in review) (
cli/mcp/tests/agent_wait.rs, throughServer::handle/runwith the fake owners, whose daemon snapshot and dialog feed change mid-wait) and one CLI test through a real headless daemon (tests/cli/agents_wait_cli.rs: text written to a terminal, an agent reported working then idle, a 1 s timeout, a usage error).dispatch.sh <wt> agents_wait, run 38651317708. The nine MCP tests failed onunknown tool: agents_wait(behavior, not compile).test (linux); its Linux clippy flagged two lints, fixed in c9ee02a; focused run 38656540524 on that head (c9ee02a) passed every job, with all tenagents_waittests run and passing on Linux (macOS ran the same filter).cargo testpassed, including all tenagents_waittests. The run is red on failures outside this diff:cli/wire/socket.rscallscrate::app_identity, which is#[cfg(unix)]. This is a base break from bc697be (cx-is1kf.5), and it stops the Windows Rust tests before they run.smoke-tui.py:953): a workspace-order assertion afterprefix-W, in TUI code this PR doesn't touch.Set up runner), so they never ran. The macOS clippy and focused filter passed in run 38656540524.scripts/cmux-next/crash_ratchet.pyok;check-no-godfiles.sh --only rust --base origin/feat-cmux-nextpasses (the first version grewcli/app.rspast 1000 lines; it no longer does).Review fixups (one red, one green, same focused command
dispatch.sh <worktree> agents_wait):agents_wait_refuses_an_invalid_regex_and_an_unknown_dialog_agent_before_waiting(an invalid regex was not refused) andagents_wait_text_reports_a_terminal_that_closes_mid_wait(a closed terminal was an error). The other nine passed.agent_waittests and the real-daemon CLI testagents_wait_cli_answers_on_text_and_idle_through_a_real_daemonran and passed.crash_ratchet.pyok;check-no-godfiles.sh --only rust --base be93becd1f4cpasses.Changelog
Added:
agents_waitMCP tool andcmux agents wait, which wait until an agent goes idle, a dialog appears or text reaches a terminal, instead of polling snapshots.🤖 Generated with Claude Code