Skip to content

buzz-acp model switch never matches claude-agent-acp config options: expects configId, adapter sends id #2794

Closed

Description

@chillerno1

Summary

resolve_model_switch_method() in crates/buzz-acp/src/acp.rs reads the configId key from each session/new configOptions entry and skips any entry that lacks it. The claude-agent-acp adapter (v0.61.0) keys those entries with id, not configId. Every model-category entry is therefore skipped, the desired model never matches, and the session silently falls back to the CLI default from the user's ~/.claude/settings.json.

Reproduction

Buzz Desktop 0.4.24, macOS arm64, claude-agent-acp 0.61.0, Claude Code CLI 2.1.219.

  1. Set a Claude Code agent's model to Opus in Buzz Desktop (per-agent or global default).
  2. Restart the agent. buzz-acp is launched with BUZZ_ACP_MODEL=opus[1m] as expected.
  3. Ask the agent what model it is running. It reports whatever ~/.claude/settings.json pins (in my case claude-fable-5[1m]), not Opus.

Harness log shows the fallback:

WARN pool::model: desired model opus[1m] not found in agent's available models - proceeding with agent default

The pool::model tracing target is not written to the per-agent log files, so nothing user-visible records the miss.

Root cause

The adapter's actual session/new response (captured with a stdio JSON-RPC probe against the bundled adapter):

{
  "configOptions": [{
    "id": "model",
    "name": "Model",
    "category": "model",
    "type": "select",
    "currentValue": "claude-fable-5[1m]",
    "options": [
      { "value": "default" },
      { "value": "opus[1m]" },
      { "value": "claude-fable-5[1m]" },
      { "value": "sonnet" },
      { "value": "haiku" }
    ]
  }],
  "models": null
}

Note the key is id. But resolve_model_switch_method() does:

let config_id = match config_opt.get("configId").and_then(|v| v.as_str()) {
    Some(id) => id,
    None => continue,   // claude-agent-acp entries always take this branch
};

So opus[1m] is a valid option value sitting right there in the response, and the exact-match loop never sees it. The unstable models path cannot rescue it either because the adapter returns models: null.

The unit tests all use configId-keyed fixtures, which is why they pass despite the drift.

The set side is unaffected: the ACP SDK's SetSessionConfigOptionRequest schema takes configId as the request param, and the adapter's setSessionConfigOption handler looks entries up by params.configId against o.id. Only the read side in buzz-acp is wrong.

Relationship to existing issues and PRs

Fix

Accept both spellings when extracting the config id:

config_opt.get("configId").or_else(|| config_opt.get("id")).and_then(|v| v.as_str())

PR incoming with this change plus a regression test using an id-keyed payload that mirrors the real adapter response.

Activity

  1. jack-owen commented on Jul 27, 2026

    @jack-owen

    Still reproduces on current versions. Buzz Desktop 0.4.26, claude-agent-acp 0.62.0, Claude Code CLI 2.1.220, macOS 26.5.2.

    The agent is configured as sonnet, the live process carries BUZZ_ACP_MODEL=sonnet, and the buzz-acp startup line logs model=sonnet. Three restarts in a row, and every assistant message in all three Claude transcripts records claude-opus-5, which is what ~/.claude/settings.json pins.

    One more thing consistent with your read-side diagnosis: buzz-acp models prints the model group as configId: ?. The id is missing where the CLI displays it, not just where the switch resolves it.

    Nothing in the per-agent log records the miss, so from the user's side the setting simply appears to do nothing.

  2. chillerno1 commented on Jul 27, 2026

    @chillerno1
    ContributorAuthor

    @wpfleger96 any chance you could take a look at PR #2795 ? Small fix in acp.rs to accept id-keyed config options when resolving a model switch.

  3. self-assigned this
    on Jul 27, 2026
  4. added a commit that references this issue on Jul 28, 2026
    925a9a7
  5. added a commit that references this issue on Aug 3, 2026
    448458a
  6. added a commit that references this issue on Aug 23, 2026
    ba00d2c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions