fix(server): ACP mode picks reach agents that name their mode option differently - #13724
Conversation
…differently `runtime.setMode` always sent `session/set_config_option` with the id `mode`. An agent whose mode option has another id (a `permission-mode` option with `category: "mode"`) got a request for an option it does not have. An ACP v1 agent that advertises only `modes` (gemini-cli) got a config-option request it does not handle. Either way the user's pick from the agent's own mode picker never applied. setMode now follows the ACP spec: it sets the session's `category: "mode"` config option under its own id, and takes the mode from the agent's answer instead of assuming it switched. A session that advertises only `modes` gets `session/set_mode`. effect-acp gains `agent.setSessionMode`, v1-only like `setSessionModel`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a contained ACP compatibility fix that corrects mode selection for agents using alternate config IDs or ACP v1 mode transport. The new transport path is protocol-gated, existing defaults and unrelated paths remain unchanged, and both cases are covered by focused tests. You can add or adjust custom eligibility rules. Learn more. |
cbe13c4
into
t3code/codex-turn-mapping
A user's pick from an ACP Registry agent's own mode picker could silently fail to apply.
runtime.setModealways sentsession/set_config_optionwith the idmode. An agent whose mode option has a different id (for examplepermission-modewithcategory: "mode") got a request for an option it doesn't have. An ACP v1 agent that advertises onlymodes(gemini-cli) got a config-option request it doesn't handle.This is the agent-agnostic part of #13629 that survives its spec-only reshape (see "Replaces" below).
What changed
AcpSessionRuntime.setModefollows the ACP spec:category: "mode"config option, it sendssession/set_config_optionunder that option's own id. It then takes the current mode from the agent's answer instead of assuming the switch happened.modes(ACP v1), it sendssession/set_mode.agent.setSessionMode. It is v1-only likesetSessionModel, and on a v2 session it fails with method-not-found. ACP v2 removedsession/set_mode.session/request_permissionby the thread's mode, and nothing new reads the runtime mode.Replaces #13629
With the per-agent parts removed (the mode table, the per-agent
sessionModeForPolicy, the gooseset_config_option→set_modefallback,omitModes, andenforcement: "native"for registry agents), this transport fix is all that's left of #13629. I propose closing #13629 in favour of this PR. Its open High finding, about claimingnativeenforcement when the live session lacks the mapped mode, goes away with thenativeclaim.Verification
In
apps/serverunless noted, withTMPDIRunder /home:AcpRegistryAdapterV2.test.ts > the agent's own mode pickerdrives the real registry adapter against scripted ACP v1 agents (acp-replay-agent.ts), and each script must be consumed exactly:switches an agent that only advertises modes with session/set_mode: a storedautoEditpick sendssession/set_mode.switches a mode config option under its own id: a storedautopick sendssession/set_config_optionwithconfigId: "permission-mode".setMode, both fail.vp test runonAcpRegistryAdapterV2,AcpAdapterV2,AntigravityAdapterV2,GrokAdapterV2,AntigravityAcpSupport,AcpSessionConfig,AcpRegistryProbe,AntigravityTextGeneration: 229 passed. Antigravity's mode switching goes through the samesetMode.OrchestratorReplayFixtures -t "grok|antigravity|acpRegistry|registry": 21 passed. No ACP fixture switches modes.packages/effect-acp:vp test run src/client.test.ts29/29. The v1 flow sendssession/set_mode, and a v2 session gets -32601.tsc --noEmitfor apps/server and packages/effect-acp: clean.vp run knip:check: clean.vp linton touched files: only the pre-existing inline-schema warning ineffect-acp/src/client.ts.Model: Claude Opus 5.5 (Claude Code)
🤖 Generated with Claude Code