fix(acp): launch ACP/stdio mode for managed agents with no runtime preset - #3804
fix(acp): launch ACP/stdio mode for managed agents with no runtime preset#3804bradhallett wants to merge 2 commits into
Conversation
Managed agents pinned to a known ACP runtime via agent_command_override (e.g. `omp`, `grok`, `opencode`, `kimi`) but with no `runtime` id resolved the effective command (e.g. `omp`) yet launched it with empty args. With no controlling TTY under headless Buzz, the agent's interactive TUI started instead of its ACP/stdio mode, so the JSON-RPC `initialize` handshake never completed and the agent timed out at startup (omp/opencode/kimi: Request timeout; grok: ENXIO "Device not configured"). Root cause: resolve_effective_harness_descriptor only filled args when the record carried explicit instance args or a resolvable harness preset (record.runtime -> lookup_loaded_harness_by_id). A command-override agent with runtime=None hit neither, so descriptor.args stayed empty. Fix: when no preset resolves, fall back to the PRESET_HARNESSES entry whose command matches the effective command (new preset_args_for_command, mirroring the existing single-source preset_harness_ids helper and living alongside it in the managed_agents::discovery::presets submodule). The PresetHarness table stays the single source of truth for per-runtime launch args, so this covers omp, grok, opencode, kimi, cursor, openclaw, and devin at once with no hand-mirroring, and descriptor.args now flows correctly to the spawn env (BUZZ_ACP_AGENT_ARGS), the config hash, and the agent summary. No regressions: explicit instance args still win; goose still resolves via default_agent_args; amp/hermes presets (empty args) are unchanged; custom harness ids collide with reserved preset ids so cannot shadow them. Resolves block#3399 Resolves block#3457 Resolves block#3729 Signed-off-by: Brad Hallett <53977268+bradhallett@users.noreply.github.com>
def8c83 to
e0853e8
Compare
|
good for #3729. maybe add a log line of the resolved launch args at spawn so failed initialize is easier to debug |
|
@Chessing234 Implemented in b9825af and pushed to the PR branch. |
|
Maintainer approval requested: PR #3905 overlaps with #3804 on command-only preset argument resolution. I recommend keeping #3804 as the canonical fix:
#3905 additionally explores loaded-registry matching and runtime-ID/command mismatch diagnostics. I am happy to port the mismatch diagnostic if command-only custom-harness support is required, but I recommend not merging both implementations. Can we proceed with #3804 as the canonical PR and close #3905 in favor of it? |
Signed-off-by: Brad Hallett <53977268+bradhallett@users.noreply.github.com>
b9825af to
8b2db59
Compare
Summary
Managed agents pinned to a known ACP runtime via
agent_command_override(omp,grok,opencode,kimi, …) but with noruntimeid launched the agent's interactive TUI instead of its ACP/stdio mode. Under headless Buzz there is no controlling TTY, so the JSON-RPCinitializehandshake never completed and the agent timed out at startup:Request timeoutENXIO: Device not configuredRoot cause
resolve_effective_harness_descriptor(readiness.rs) only resolved launch args when the record carried explicit instance args or a resolvable harness preset (record.runtime→lookup_loaded_harness_by_id). A command-override agent withruntime = Nonesatisfied neither, sodescriptor.argsstayed empty — while the effective command (e.g.omp) was still correct. The bare command then ran the TUI.The correct per-runtime args already existed as the single source of truth in
PRESET_HARNESSES(now indiscovery/presets.rs); they just weren't consulted on this path.Fix
In
resolve_effective_harness_descriptor's finalelsebranch, fall back to thePRESET_HARNESSESentry whose command matches the effective command, via a newpreset_args_for_command()helper that mirrors the existing single-sourcepreset_harness_ids()helper and lives alongside it in themanaged_agents::discovery::presetssubmodule (re-exported throughdiscovery.rs).PRESET_HARNESSES; no hand-mirrored copy.descriptor.argsnow flows correctly to the spawn env (BUZZ_ACP_AGENT_ARGS), the config hash, and the agent summary.} else if let Some(ref def) = harness_def { normalize_agent_args(&effective_command, def.args.clone()) + } else if let Some(preset_args) = + crate::managed_agents::discovery::preset_args_for_command(&effective_command) + { + normalize_agent_args(&effective_command, preset_args) } else { normalize_agent_args(&effective_command, record_args) }Why not in
buzz-acpAn earlier iteration mirrored the args into
buzz-acp'sdefault_agent_args. That duplicated the preset table in a third place and still left the desktop'sdescriptor.args(env/hash/summary) empty — relying on the child to repair the parent's omission. Fixing atresolve_effective_harness_descriptorcorrects the source and needs nobuzz-acpchange;buzz-acp's existingdefault_value = "acp"still covers standalone CLI use with an unset env.Verification
resolve_effective_harness_descriptor_uses_preset_args_for_pinned_command— asserts omp/grok/opencode/kimi/cursor/openclaw/devin resolve correctly, explicit args win, unknown commands stay empty. ✅cargo fmt --checkclean (pinned1.95.0toolchain); fullmanaged_agents::lib suite: 910 passed, 0 failed.block/buzzmain(resolves the conflict with Add Devin as a preset ACP harness #3225, which relocatedPRESET_HARNESSESand its helpers intodiscovery/presets.rs; this helper follows it there).ompmanaged agent initializes without the ACP timeout.No regressions
goose(not inPRESET_HARNESSES) still resolves viadefault_agent_args.amp-acp/hermes-acppresets carry empty args — unchanged.Resolves #3399
Resolves #3457
Resolves #3729