feat(shared): map MCP run config and CLI validation onto the target model's catalog - #346
Open
Tigatron wants to merge 5 commits into
Open
feat(shared): map MCP run config and CLI validation onto the target model's catalog#346Tigatron wants to merge 5 commits into
Tigatron wants to merge 5 commits into
Conversation
An ACP probe snapshot only describes the model that was current when the probe ran, while an agent such as cursor-agent publishes a distinct option set for every model. AcpCapabilityCacheEntry gains configOptionsByModel, the per-model catalog an explicit probe may store, where a model mapped to an empty list has no model-dependent options and a missing key means the catalog does not know that model. resolveAcpConfigOptionsForModel is the one composition rule for a model's options: the snapshot options no catalog entry owns plus the selected model's entry, falling back to the snapshot for an unknown model. model and mode options always come from the snapshot, so a catalog can neither shrink the model picker nor replace the permission modes. resolveAcpTargetModelId names the model a run config targets. Fast mode now also recognises a select whose values are exactly true and false, the shape cursor-agent uses for boolean parameters, and writes back the advertised representation instead of on/off. Implemented with cursor-grok-4.6-xhigh-fast subagents. Model: claude-fable-5.1 Co-authored-by: Cursor <cursoragent@cursor.com>
Registry Cursor now declares clientCapabilities._meta.parameterizedModelPicker at initialize, so probes and sessions see clean model ids plus per-model thinking, effort, context, and fast options instead of exploded variant strings whose in-session model switch silently fails. The gate is registry identity, never a same-named custom or builtin config. A session/new snapshot only describes the model current at probe time, so an explicit machine/acp-capabilities-refresh additionally calls the agent's cursor/list_available_models once and stores every model's options as AcpCapabilityCacheEntry.configOptionsByModel. That method is the only extension cursor-agent serves and performs no writes, unlike enumerating models through session/set_config_option, which rewrites the user's global Cursor config. Real sessions never fetch the catalog; their snapshot write keeps the stored catalog for the same sourceVersion, and the unchanged-entry comparison includes it so a refreshed catalog is committed. JSON-RPC -32601 means no catalog; a response that fails validation or lists a model twice, a timeout, or any other failure fails the probe with [ACP_CAPABILITIES_INCOMPLETE] so the settings test button can retry. Implemented with cursor-grok-4.6-xhigh-fast subagents. Model: claude-fable-5.1 Co-authored-by: Cursor <cursoragent@cursor.com>
Registry and custom agents carry the selected model in the model config option rather than modelId, and the applier switched it inside the option loop at its key position. Cursor validates thinking, effort, and fast against the model that is current when each option arrives, so options ordered before the model key were checked against the previous model and rejected. Apply the config-option model right after the explicit modelId path and skip its loop entry; the unstable_setSessionModel channel and its fallback are unchanged. Implemented with cursor-grok-4.6-xhigh-fast subagents. Model: claude-fable-5.1 Co-authored-by: Cursor <cursoragent@cursor.com>
lody_session_create takes reasoningEffort and fastMode semantically, and the mapping onto an agent's option ids read only the probe snapshot: for a Cursor target it could write a reasoning level into the two-valued thinking select, reject fast mode for a model whose own catalog offers it, and publish the probed model's effort values for every model. The mapping now reads the target model's composed options: reasoning effort binds to a multi-level thought_level select when the model has one and to a lone thinking toggle otherwise, a value is validated against the target model's catalog entry and returned in validatedConfigIds, fast mode is looked up per model, and lody_session_create_options publishes each catalogued model's effort values. Agents without a catalog keep the snapshot-based unverified-selection path. Implemented with cursor-grok-4.6-xhigh-fast subagents. Model: claude-fable-5.1 Co-authored-by: Cursor <cursoragent@cursor.com>
CLI and MCP create/chat validated configOptionValues against the probe snapshot, so a Cursor turn targeting another model was checked against the probed model's options: a value the target model allows could be rejected as unknown, a value it lacks could pass, and inherited create defaults kept a parent's opus-only fast or effort for a child that will run sonnet. validateTurnConfigOptionValues and filterCompatibleTurnConfigOptionValues now compose the target model's options through resolveAcpConfigOptionsForModel, inherited defaults are filtered against the MERGED target model (explicit create modelId, then the inherited modelId, then the model option), and an explicit create modelId drops a parent's superseded model option so the frozen Turn names one model. Implemented with cursor-grok-4.6-xhigh-fast subagents. Model: claude-fable-5.1 Co-authored-by: Cursor <cursoragent@cursor.com>
Tigatron
marked this pull request as ready for review
September 3, 2026 10:57
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
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.
Related issue
Closes #343
Problem / pressure
lody_session_createtakes run config semantically, and the mapping onto an agent's option ids read only the probe snapshot: for a Cursor target it could write a reasoning level into the two-valuedthinkingselect, rejectfastModefor a model whose own catalog offers it, andlody_session_create_optionspublished the probed model's effort values for every model. CLI and MCP create/chat validatedconfigOptionValuesagainst the same snapshot, so a value the target model allows could be rejected as unknown, a value it lacks could pass, and inherited create defaults kept a parent's opus-onlyfast/xhighfor a child that will run sonnet.Summary
de9b74a,be8f415,2675f4fare that PR's foundation and are included so this branch typechecks and runs CI on its own; review the two commits after2675f4f. Independent of the composer PR.resolveAgentRunConfigSelectionreads the target model's composed options:reasoningEffortbinds to a multi-levelthought_levelselect when the model has one and to a lone thinking toggle otherwise (Kimi models without effort levels keep working), is validated against the target model's catalog entry, and returns the id invalidatedConfigIds;fastModeis looked up per model, and the unverified-selection path remains only for agents without a catalog.summarizeAgentRunConfigCapabilitiespublishes each catalogued model's effort values, still preferring legacymodelReasoningEfforts.validateTurnConfigOptionValuesandfilterCompatibleTurnConfigOptionValuescompose the target model's options throughresolveAcpConfigOptionsForModel; inherited defaults are filtered against the MERGED target model (explicit createmodelId, then the inheritedmodelId, then the model option), and an explicit createmodelIddrops a parent's supersededmodeloption so the frozen Turn names one model.apps/cli/AGENTS.mdrecords the per-model invariant.Before / after
reasoningEffort: 'extra-high'forgpt-5.4wrote intothinking.reasoningand validated against gpt's ladder.fast/xhighfrom an opus parent survived into a sonnet child.create_optionslisted one effort ladder for all models.Test plan
cd packages/shared && corepack pnpm exec tsgo --noEmit && corepack pnpm exec vitest run tests/acp-run-config.test.ts— 36 passed (per-model reasoning/fast mapping, catalog validation errors, no-catalog regression path, Kimi lone-toggle mapping, per-modelcreate_optionsvalues).cd apps/cli && corepack pnpm exec tsgo --noEmit && corepack pnpm exec vitest run src/commands/session.test.ts src/session/acp-session-config-applier.test.ts— 78 passed (validation against the target catalog, inherited filtering against the merged target and against the inherited model, superseded model option removal).cd packages/components && corepack pnpm exec tsgo --noEmit— passed (shared is consumed as source).corepack pnpm typecheck,corepack pnpm lint(0 errors),corepack pnpm format:check— passed. Skipped: an end-to-end MCPlody_session_createrun against a live Cursor agent (mapping covered by unit tests against the observed catalog shapes).Context handoff
Instructions for reviewing agents
resolveAgentRunConfigSelectionandfindReasoningEffortOptionIninpackages/shared/src/acp-run-config.ts(ladder-first, toggle-fallback), andfilterCompatibleInheritedTurnConfigplusdropSupersededInheritedModelOptioninapps/cli/src/commands/session.ts(three-level target model chain).reasoningEffortinstead of rejecting it for models without a ladder; not pushingfastintovalidatedConfigIds(the CLI check now composes the same options).mergeTurnDispatchConfigstill replaces the whole inheritedconfigOptionValuestable with??(pre-existing), which narrows the inherit path to creates that carry no options of their own;unverifiedSelectionshas no consumer on the create path (pre-existing). Both are left as-is and worth separate issues.Authoring context
modelReasoningEffortspath first; no change tomergeTurnDispatchConfig.modeloption when a create names a different model; validatingreasoningEffortagainst the catalog entry and skipping the snapshot check for that id viavalidatedConfigIds.