Repository navigation
feat(orchestration): let an agent steer its message into a busy chat instead of queueing it - #26110
brennanb2025 wants to merge 6 commits into
Conversation
…l only on an answered prompt - redrive mail parked on a chat on the prompt-answered edge only, never per streamed status frame - a dispatch steered into a running turn reports its hand-off instead of waiting out a start - stamp an accepted send before holding a steer for an open prompt; merge rerun reserved types - refuse dispatch --delivery without --inject; unknown dispatch delivery arms print nothing - separate, accurate send and dispatch notes and guide text
… say a steered task can still be dropped - the answered-prompt edge also re-derives the chat's mailboxes, so an attempt in flight on a read from before the answer is rerun instead of waiting for the turn to end - dispatch note: --delivery (either value) needs --inject; a task handed to the chat but not taken yet can still be dropped if that turn ends first, so check on a worker that never reports
|
A message or task sent by an agent to a busy native chat previously waited until the running turn ended. This PR adds The two CI regressions were caused by this PR: the new real-SQLite migration test was missing from the Node-runtime test list, and the production-wiring test still expected the old one-argument callback. The fixes put the migration fixture in its required runtime and check that the retry receives the prior status needed to detect an answered prompt. Both original tests were reproduced on the PR and passed on main ( The reviewed limitations remain explicit: a steered dispatch can be dropped before the chat takes it, leaving the coordinator to check on a worker that never reports; a notice queued before a steer can later cause an extra turn; an older runtime ignores the optional delivery choice and queues it; cross-server mail does not yet carry steer and returns a warning. The approval/question state is read before sending, so a newly opened prompt can race that read; this remains deferred. Queue-mode notices can now appear sooner after an in-flight send or an answered prompt. For agents that run one prompt at a time, send-now stops the current turn and runs the message next, matching the person's Send now; that product choice is accepted. Hidden Electron QA on local macOS verified default queue, send now during a turn, mail held through an approval and delivered after the answer, idle delivery, invalid delivery/heartbeat/non-injected dispatch refusals, and busy task dispatch from a genuine native-chat sender. Full screenshots are embedded in the PR body, including the named sender caption beside the running status and Stop button. Copied raw journals and adapter records confirm same-turn delivery with no extra turn. The adapter was a stand-in and the QA CLI was an esbuild emission of the clean head, rather than the shipped TypeScript-emitted artifact. Real providers, executing the dispatched task, mobile, Windows/WSL, live SSH and cross-server delivery were not tested. Shared live-app configuration changed during the restart; real-configuration observations after 21:35:56 UTC are excluded as isolation evidence. No merge or auto-merge was performed. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (51)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughThe change adds queue and steer delivery options to orchestration messages and injected chat-task dispatches. The runtime stores the selected mode and applies it to structured-session delivery, including human-gate and in-flight-send handling. Status transitions now trigger mail redrive on specified edges. The CLI, SSH fallback, command guidance, and tests are updated to cover the new options and behavior. Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to No issue established in this review needs resolution before merging; normal checks still apply. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 52.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 36 functions across 48 files. (2 skipped: 2 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
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 |
|
Holding this PR and moving it back to draft. This PR lets an agent send a message to a busy chat with "send now", so it joins the running turn instead of waiting in the queue. We can't guarantee that behavior across all the agents Orca runs. Native chat can steer a running turn, but sending to a terminal (CLI) agent doesn't interrupt it. Depending on the CLI, the message can just sit queued in that agent's own input until its turn ends; Grok, for example, does this. So |
|
Closing: superseded by #28540, which gives native-chat agents their mail notice right away the same way for every agent. |
ELI5
When one agent sends another agent a message (or a task) and the receiving chat is busy, Orca holds it as a queued card until the chat's current turn ends. That is the right default, but sometimes the sender knows it is urgent ("stop, you're on the wrong branch"). This PR lets the sending agent choose: keep queueing (default), or
--delivery steer, which puts it into the running turn the same way a person's message goes in when they send while the agent works with queueing off.What Changed
Before:
orca orchestration sendandorca orchestration dispatchinto a busy chat always became a queued card. A coordinator correcting a worker mid-task waited for the worker's whole turn to end. The worker guide even says the coordinator's follow-up "does not interrupt you".After (what the person sees):
--delivery steer, a busy chat takes it into the running turn instead: no card, it shows mid-turn as "Message from ", exactly like a person's send with queueing off.Mechanism:
sendAgentTurn:queueis the composer's queued send,steeris its plain send (the composer's send with queueing off), which the chat host already steers into a running turn.dispatchpasses the choice straight through and its result now reports how the task was handed over (sent,still starting,queued).sendis asynchronous (the message is stored, then a short "you have N messages" notice is sent into the chat, batched and retried), so the sender's choice is stored on the message row (messages.busy_delivery, schema v44, defaultqueue). Each notice works out its delivery from the messages it points at: steer if any of them asked for it. Nothing is latched; the choice goes away with the delivered rows.CLI:
--delivery <queue|steer>onorchestration sendandorchestration dispatch --injectonly.--type heartbeatwithsteeris refused (it would interrupt the coordinator on every beat), and--deliveryon a dispatch without--injectis refused (nothing is sent to the chat then).Side effects on the default (queue) path, named so they're not a surprise:
Why
The common pattern gives the sender a delivery choice on each message. This change uses that choice and reuses Orca's existing composer send, while keeping queue as Orca's default. Differences in prompt handling and durable mail are listed below. Alternatives considered:
--priority urgentto mean "steer": rejected, it mixes how important a message is with how it is delivered and would silently change what existing urgent senders get.Differences from the common pattern:
senddoesn't report "steered" vs "queued" (intended): it returns once the message is stored; the notice is sent afterwards.dispatchdoes report it.sendreturns adelivery_not_relayedwarning. Follow-up: carry the choice in the cross-server mail payload.Linked Issue
Follow-up to #25078 (agent messages use the chat's queue) and #22972.
Visual Proof
QA at pushed
c61186876c1used a hidden local Electron renderer, normal orchestration CLI calls and a stand-in Codex adapter. The frames below are full, uncropped renderer screenshots. Stub records and copied raw session journals corroborate delivery timing.Default queue: the agent notice stays in a card with Steer/Delete while the recipient works, then starts a separate turn after completion.
Send now: the notice appears in the running turn without a queued card. This test used a placeholder sender, so its attribution is the generic fallback, “Message from an agent”.
Waiting for approval: no notice is injected while the approval is open. After Allow, it joins the same turn; the stub recorded the join 8 ms after the answer. This sender also used the generic fallback.
Send now for a task from a native chat: a genuine sender named “Codex Chat” dispatches into the busy recipient. Its caption is visible with the running status and Stop button, without a queued card. Accepted journal records and the stand-in adapter show the task joined the same turn, with no extra turn afterward.
Testing
Unit and rig tests: the notice lane (steer batch, queue batch, held while an approval is open then steered, retried after an in-flight send, an earlier queued card plus a later steer), dispatch (steer, prompt fallback to a card, result), send params and stored rows (single and group, heartbeat refused, cross-server warning), schema v44 migration, CLI flags, SSH bridge.
Both CI failures were reproduced on the PR with their fixes removed, and both original tests passed on main (
80d45095d2f). The migration fixture now runs in the required Node project; the runtime-wiring test verifies the prior approval status reaches mail redrive.Before the main merge: 85 selected files / 837 tests passed, including the real database downgrade/write/reopen test. At final head
c61186876c1: the narrow merge batch passed 14 files / 119 tests.CI passed on
c61186876c1: all five full unit-test shards, relay integration, static analysis and typecheck, packaging and verification.Node, CLI and web typechecks passed sequentially through the machine-wide gate after clearing old build-info. Required final static checks: 21/22 passed. The full type-aware audit did not run because the machine queue timed out; changed-file type-aware quality passed. CI static analysis and typecheck passed, covering the full audit.
Hidden Electron QA on local macOS verified default queue, send now, holding mail through an approval, idle delivery, invalid delivery/heartbeat/non-injected dispatch refusals, and busy task dispatch with a visibly named sender. The adapter was a stand-in; real providers, executing the dispatched task, mobile, Windows/WSL, live SSH and cross-server delivery were not exercised.
The QA CLI used an esbuild emission of clean
c61186876c1, invoked by absolute path only. The product build uses TypeScript emission; types were checked separately locally and in CI. This was not a test of the shipped CLI artifact.The rig used isolated homes/profile, mock keychain and guarded stand-in providers. Shared live-app configuration changed during the restart; all real-configuration observations after the last clean boundary at 21:35:56 UTC are excluded as evidence of isolation.
I manually tested these changes locally (hidden renderer through CDP, with a stand-in adapter)
Automated tests added/updated, or explained why not below
Review
Two independent review rounds converged; the final repair and main integration were checked separately. The readiness review found no P0/P1 issues; the remaining limitations are listed above and in the completion comment. The one-prompt-at-a-time Send now behavior is an accepted product choice.
Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
check --wait; typing into a busy agent terminal would race whatever the person is typing there. A dispatch to a terminal is already typed at once, so the choice changes nothing there.deliveryis a new optional parameter. An older Orca ignores it, so the message still arrives, queued as today. Nothing the host publishes changes shape; no protocol bump.--deliverythrough onsend.X / Twitter: @BrennanKB5
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)