feat(desktop): route voice tasks to Codex/OpenClaw/Hermes with best-agent selection, fallback, and install help#9765
Conversation
…rnel Adds a codex adapter (ACP-bridged, OMI_CODEX_ADAPTER_COMMAND activation) alongside hermes/openclaw: capability matrix entry, adapter profile and registration, spawn_agent provider enum, provider_setup_needed translation, and speakable install instructions for uninstalled directed providers. Evidence: cd desktop/macos/agent && npx tsc --noEmit && npx vitest run (48 files, 561 tests passing, incl. new Codex setup-needed regression test).
… and install help Kernel: sharedSemanticGuidance now carries the local-provider selection policy — explicit mention dispatches that exact provider (setup instructions relayed when missing, never a silent switch), otherwise the best installed provider by task fit, with one same-turn fallback retry when a model-chosen spawn fails. Swift: Codex joins DirectedProvider/BridgeMode/AIProvider/harness routing; codex-acp detection seeds OMI_CODEX_ADAPTER_COMMAND; spawn_agent's realtime provider enum now always advertises every known agent with an installed/missing split; a failed spawn keeps the turn open once so the model can relay setup instructions or retry another installed agent, with recordFallback(area:realtime_hub, reason:spawn_failed) telemetry on a same-turn provider switch; setup prompts carry real install commands. Evidence: cd desktop/macos/agent && npx vitest run (561 tests). Swift suite run recorded in the follow-up commit.
Evidence: ./scripts/agent-logic-harness.sh --swift-only (passed); xcrun swift test --filter 'HubSystemInstructionTests|RealtimeHubSpawnAgentTests|PiMonoWiringTests|AgentRuntimeProcessTests|AgentPillLifecycleTests|VoiceTurnUIProjectionCopyTests|AgentDelegationResolverTests|AgentRuntimeContractFixtureTests' (207 tests, 0 failures).
Adds a stub codex-acp JSON-RPC server driven by the production CodexRuntimeAdapter (spawn, initialize, session/new, session/prompt, streaming update translation), and a kernel-level test proving a realtime spawn_agent with provider=codex crosses into the local_user:codex boundary and completes the child run with the adapter's answer. Extends adapter-selection tests to pin codex activation env and error copy. Evidence: cd desktop/macos/agent && npx vitest run (563 tests, 0 failures).
…ioral tests Extracts the one-continuation-per-turn recovery (relay setup guidance or retry a different agent, never loop) into RealtimeSpawnFailureContinuationPolicy and covers it behaviorally: first failure continues, second terminates, fallback from-label is consumed exactly once. Evidence: xcrun swift test --filter 'RealtimeSpawnFailureContinuationPolicyTests|RealtimeHubSpawnAgentTests' (29 tests); ./scripts/agent-logic-harness.sh (passed, 27s).
Evidence: scripts/pr-preflight --pr-body-file <draft> now passes all 18 selected checks (desktop-e2e-flow-coverage previously flagged AIProvider.swift as uncovered).
When a named agent isn't installed, guidance now has the model offer to run the install itself via a default-agent background task (only on the user's yes), instead of leaving the user to copy the command into a terminal. Evidence: cd desktop/macos/agent && npx vitest run (563 tests).
…package @zed-industries/codex-acp is deprecated in favor of @agentclientprotocol/codex-acp (same codex-acp bin). Evidence: vitest external-surface-authority (16 tests); swift test --filter PiMonoWiringTests (27 tests).
…ve parser Live PTT evidence: batch STT transcribed 'tell codex…' as 'Tell codes…', so the explicit-provider directive missed and the typed lane could not cross the provider boundary (the same-turn fallback then correctly ran the default agent and disclosed the switch). 'codes'/'codexs' now map to codex only inside the explicit command syntax. Root cause: deterministic directive syntax was exact-match against an ASR transcript. Durable guard: alias table lives in the same providerToken switch with regression tests for the observed mishear and for non-command sentences containing 'codes'. Evidence: xcrun swift test --filter PiMonoWiringTests (28 tests, 0 failures).
|
Thanks for the detailed implementation and validation notes. I did a static maintainer pass on this head. This looks directionally coherent: Codex is wired through the existing adapter/control-plane abstractions rather than bypassing the kernel, explicit-provider routing remains behind I’m not formally approving because this changes security- and product-sensitive desktop agent behavior and needs human maintainer review before merge:
If maintainers are comfortable with those product/security decisions, the implementation shape and added coverage look promising from this review. by AI on behalf of David — if you need David’s attention urgently, please @Git-on-my-level and escalate with |
What changed and why
Track 1 (Agents): Omi can now hand PTT and typed tasks to OpenClaw, Hermes, and (new) Codex.
Naming an agent dispatches
spawn_agentwith exactly that provider in the same turn; whennone is named, the model picks the best installed agent (codex: coding, openclaw:
messaging/automation, hermes: research) or the default; a failed model-chosen spawn gets one
same-turn retry with another agent (with
recordFallbacktelemetry); naming a not-installedagent returns spoken install steps plus an offer to run the install via the default agent.
Codex is a full directed provider: new kernel
CodexRuntimeAdapter(ACP viacodex-acp,activated by
OMI_CODEX_ADAPTER_COMMAND), Swift routing/detection, and pill/picker UI.Product invariants affected
registers through
ensureRegisteredAdapter; explicit-provider spawns still cross boundariesonly via
assertAdapterAllowedForTopLevelLocalProviderSpawn; selection policy lives inkernel
sharedSemanticGuidance, not Swift prompt fragments.failure continuation never writes a turn.
OMI_*_ADAPTER_COMMAND.How it was verified
omi-agent-routingnamed bundle, signed in, Codex CLI +codex-acpinstalled and ChatGPT-authenticated): "ask codex to create hello.txt on mydesktop" → voice model called
spawn_agent{provider:"codex"}→ kernel spawned the realcodex-acpsubprocess → file created on the Desktop.the same-turn fallback completed the task with the default agent and disclosed the switch
("Codex wasn't available, so I retried with the default agent"). The mishear is now handled
by the directive parser (see Tests).
cd desktop/macos/agent && npx tsc --noEmit && npx vitest run— 49 files, 563 tests passing.cd desktop/macos && ./scripts/agent-logic-harness.sh— passed (Swift lifecycle/state,agent runtime focused, pi-mono-extension).
make preflightwith this body — all 18 selected checks pass.they ride the same pre-existing adapter machinery Codex just proved, and are covered by the
contract suites. The not-installed → install-help path for them is contract-tested.
Tests
Core path:
codex-adapter-subprocess.test.ts(real spawned ACP subprocess through theproduction adapter) and
external-surface-authority.test.ts— "runs an explicitly requestedCodex child to completion through a real ACP subprocess" (realtime
spawn_agent→local_user:codexboundary → run succeeded).Main error path:
external-surface-authority.test.ts— "returns setup instructions when anuninstalled Codex is explicitly requested" (
provider_setup_needed+ install command), andRealtimeSpawnFailureContinuationPolicyTests(one continuation per turn, second failureterminates, fallback from-label consumed once).
Also: codex directive parsing incl. the observed "codes" STT mishear (
PiMonoWiringTests),detection (
codex-acpdiscovery + missing-prompt install copy), provider enum withinstalled/missing split (
HubSystemInstructionTests), adapter-selection/capability-matrix andcross-language contract fixture pins.
Root cause and durable guard (bug fixes)
Two small fixes shipped alongside the feature:
leave the user a next step. Durable guard: typed
RealtimeSpawnFailureContinuationPolicy(bounded one-continuation-per-turn, behaviorally tested) instead of an ad-hoc boolean.
codex). Durable guard: mishear aliases live in the same
providerTokenswitch, withregression tests for the observed transcript and for non-command sentences containing
"codes".
Scoped cleanups (optional)
@zed-industries/codex-acpreplaced by@agentclientprotocol/codex-acpin allinstall hints (own commit).
AIProvider.swiftadded toai-chat-settings.yamle2ecovers:(it backs the providerpicker that flow drives; fixes a preflight coverage gap).
observed during testing, tracked separately (spun off as its own task).