fix(cli): validate per-model ACP options against the target model - #316
Closed
zxch3n wants to merge 1 commit into
Closed
fix(cli): validate per-model ACP options against the target model#316zxch3n wants to merge 1 commit into
zxch3n wants to merge 1 commit into
Conversation
A probe's `configOptions` only describe the model that was current when it ran: Codex publishes `fast-mode` only while that model has a fast speed tier, and rebuilds the effort list on every model switch. Dispatch already knew this for a SEMANTIC selection, but concrete ids that never pass through that resolver — an Agent Role's stored `runConfig`, `--config-option`, a frozen Operation replayed after recovery — were still checked against the probed snapshot, so a Role pinning a fast-capable model failed create with "Unknown ACP config option for the selected agent: fast-mode" whenever the agent's default model had no fast tier. Apply the same rule to the values themselves. `resolvePerModelConfigOptionSelection` exempts per-model ids from the snapshot check when the turn runs a model other than the probed one, still validating effort strictly wherever the agent published its per-model breakdown, and reports the rest as unverified rather than rejecting them. A turn that runs the probed model keeps the snapshot authoritative, so a genuinely missing control is still refused. Also record the fast toggle in `validatedConfigIds` on a model switch, which the effort branch already did. Model: claude-opus-5[1m] Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Sep 3, 2026
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Creating a Session fails with
Unknown ACP config option for the selected agent: fast-mode.An ACP capability probe starts the agent with its default settings and snapshots the
session/newresponse, soconfigOptionsonly ever describes the model that was current at probe time. Codex publishesfast-modeonly while that model has a fast speed tier (CodexAcpServer.ts:if (sessionState.currentModelSupportsFast)), and rebuilds the effort list on every model switch. A probe undergpt-5.2/gpt-5.4-mini/gpt-daybreak-*— or one whose model catalog fetch failed — therefore produces a snapshot with nofast-modeat all.Dispatch already knew this for a semantic selection (
runConfig.fastMode/reasoningEffort):resolveAgentRunConfigSelectionvalidates effort against the TARGET model and returnsvalidatedConfigIdsforvalidateTurnConfigOptionValuesto skip. But concrete ids that never pass through that resolver were still checked against the probed snapshot:resolveMcpSessionCreatedispatches{ ...role.runConfig }, i.e. stored concreteconfigOptionValues, with no semantic selection to resolve;lody session create/chat --config-option fast-mode=true;targetDispatchConfigs), which is the already-resolved result being re-validated.So a Role pinning
gpt-5.6-luna+ Fast was refused before the agent ever saw it, on the authority of a snapshot describing a different model.Fix
Make the rule follow the VALUES, not the caller.
resolvePerModelConfigOptionSelection(@lody/shared) classifies concrete config values against the model the turn actually runs:unverifiedSelections— the snapshot cannot prove the agent will reject them, and the runtime is the authority;modelReasoningEfforts), so a value the target model does not accept still fails loudly, now with the right model named;This also removes the recovery hazard: a frozen config carries its
modelId, so replay reaches the same verdict that accepted it instead of re-judging it against the probed model.Also records the fast toggle in
validatedConfigIdson a model switch, which the effort branch already did.Tests
packages/shared/tests/acp-run-config.test.ts— stored fast toggle on another model (including a snapshot that omits the option entirely), snapshot stays authoritative for its own model, effort still validated against the target breakdown, and an agent publishing effort under its own id (Claudeeffort/fast).apps/cli/src/commands/session.test.ts— the reported failure end to end throughapplyAgentRunConfigSelection+validateTurnConfigOptionValues, plus the probed-model case that must still throw.pnpm --filter @lody/shared test(1021),pnpm --filter lody test(2466),typecheck,lint,check:public-boundaryall pass.Not in this PR
Once the request reaches the agent, a rejection of Fast / effort / model / Plan on Codex or Claude is deliberately not promoted to a visible
agent_warning(documented inapps/cli/AGENTS.md), so the turn runs without Fast and says nothing. Surfacing that divergence means amending that invariant — worth doing, but a separate decision.🤖 Generated with Claude Code