Skip to content

Dynamic ACP agent registration + ACP-native model discovery#321

Open
SawyerHood wants to merge 3 commits into
mainfrom
bb/investigate-dynamic-acp-agent-registration-thr_5ip4wda8wu
Open

Dynamic ACP agent registration + ACP-native model discovery#321
SawyerHood wants to merge 3 commits into
mainfrom
bb/investigate-dynamic-acp-agent-registration-thr_5ip4wda8wu

Conversation

@SawyerHood

Copy link
Copy Markdown
Collaborator

Summary

Adds dynamic ACP agent registration — users register custom ACP (Agent Client Protocol) agents in ~/.bb/config.json, and they appear in the provider picker and run like built-in agents — plus ACP-native model discovery & selection so agents that advertise models over the protocol (e.g. opencode) list and switch models without a Cursor-style --list-models CLI.

Built-in providers (codex, claude-code, pi, acp-cursor) are unchanged. Scope is the co-located daemon only (remote daemons out of scope).

What's included

Dynamic ACP agent registration

  • customAcpAgents in ~/.bb/config.json: { id, displayName, command, args, env, cwd, modelCli? }; slug id → provider id acp-<id>. Fail-soft per-entry parsing (bad entries dropped + logged, never crash); the bb-app launcher preserves raw entries across config set/unset.
  • Shared ACP capability/policy recognizer for dynamic acp-* ids in @bb/agent-providers; the server picker (execution-options, /system/providers) lists them and attaches their launch spec.
  • Wire: optional acpLaunchSpec on provider.list_models / thread.start / turn.submit; HOST_DAEMON_PROTOCOL_VERSION → 43. Daemon/runtime build ACP adapters from the spec via acpProfileFromLaunchSpec, with a launch-spec fingerprint folded into the provider-process cache key so config edits take effect.

ACP-native model discovery & selection

  • Reads models from the session/new configOptions model select and selects via session/set_model { sessionId, modelId } — no --list-models CLI required.
  • Cursor's CLI list + launch-flag path stays as a fallback; an acp-default sentinel covers agents with no model option. Throwaway discovery sessions are timeout-bounded and always torn down.

Also

  • Fixes a pre-existing, unrelated @bb/host-daemon typecheck failure (fetch.preconnect) by narrowing the fetch dependency to its call signature (separate commit).
  • Docs: docs/configuration.md, the bb-cli skill, and the providers guide.

Testing

  • Unit + integration (real-subprocess ACP stub) + config-reload tests.
  • Verified live against opencode (opencode acp): registration, picker visibility, model discovery, non-default model selection, and message round-trip.
  • @bb/agent-runtime (701 tests), @bb/host-daemon (366 tests), and the changed-package typecheck/test matrix pass.

🤖 Generated with Claude Code

SawyerHood and others added 3 commits June 22, 2026 22:08
The host-daemon fetch dependency was typed `typeof fetch`, which now requires a
`preconnect` member, so the plain-function / vi.fn test mocks in app.test.ts and
server-client.test.ts no longer satisfied it and `@bb/host-daemon` typecheck
failed. This was independent of any feature work (present on the base branch).

The client only ever calls fetchFn(url, init); it never uses fetch.preconnect.
Narrow the dependency type (FetchFn) to fetch's call signature instead of
`typeof fetch` — precise about what's actually used, and satisfied by the mocks.
No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Let users register custom ACP (Agent Client Protocol) agents via
`customAcpAgents` in ~/.bb/config.json (slug id -> provider id `acp-<id>`,
command, args, env, cwd, optional modelCli). They appear in the provider picker
and run like built-in agents. Built-in providers (codex, claude-code, pi,
acp-cursor) are unchanged; remote daemons are out of scope (co-located only).

- Config: customAcpAgents schema with fail-soft per-entry parsing in @bb/config;
  threaded through ServerRuntimeConfig, managed-config reload, and the bb-app
  launcher (preserves raw entries across config writes).
- Catalog/policy: shared ACP capability/policy recognizer for dynamic acp-* ids
  in @bb/agent-providers; server picker (execution-options, /system/providers)
  lists dynamic agents and attaches their launch spec.
- Wire contract: optional acpLaunchSpec on provider.list_models, thread.start,
  and turn.submit; HOST_DAEMON_PROTOCOL_VERSION bumped to 43. Runtime/daemon
  resolve dynamic acp-* ids to ACP adapters via acpProfileFromLaunchSpec, with a
  launch-spec fingerprint folded into the provider-process cache key so config
  edits take effect.
- ACP-native model discovery + selection: read models from the session/new
  configOptions model select (no Cursor-style --list-models CLI required) and
  select via session/set_model. Cursor's CLI list + launch-flag path remains as
  a fallback, and a synthetic acp-default sentinel covers agents with no model
  option. Throwaway discovery sessions are bounded by a timeout and always torn
  down.

Verified live against opencode (`opencode acp`): registration, picker
visibility, model discovery + non-default selection, and message round-trip.
Adds unit, integration (real-subprocess stub), and config-reload tests; docs in
docs/configuration.md, the bb-cli skill, and the providers guide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
These tests spawn the fake ACP agent multiple times (model list now adds a discovery session), exceeding the 5s default on slower CI. Give them 30s headroom; no behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant