fix: control UI model selector sends correct provider prefix#47581
Conversation
The model selector was using just the model ID (e.g. "gpt-5.2") as the
option value. When sent to sessions.patch, the server would fall back to
the session's current provider ("anthropic") yielding "anthropic/gpt-5.2"
instead of "openai/gpt-5.2".
Now option values use "provider/model" format, and resolveModelOverrideValue
and resolveDefaultModelValue also return the full provider-prefixed key so
selected state stays consistent.
Greptile SummaryThis PR fixes a long-standing bug where the Control UI model dropdown sent bare model IDs (e.g. The fix is well-scoped and internally consistent:
Issues found:
Confidence Score: 4/5
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5769b05277
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const value = provider ? `${provider}/${entry.id}` : entry.id; | ||
| addOption(value, provider ? `${entry.id} · ${provider}` : entry.id); |
There was a problem hiding this comment.
Normalize cached override values before comparing option keys
The new provider/model option values here assume currentOverride is also provider-qualified, but resolveModelOverrideValue still returns cached chatModelOverrides[sessionKey] verbatim; that cache is populated by /model with raw user input (often bare model IDs). In that flow, the select value (gpt-5.2) no longer matches catalog values (openai/gpt-5.2), so a synthetic bare option is injected and the picker can drift from server-resolved state until reload. Normalizing cached overrides to the same key format (or updating cache from resolved patch data) would keep selection behavior consistent.
Useful? React with 👍 / 👎.
The default option showed 'Default (openai/gpt-5.2)' while individual options used the friendlier 'gpt-5.2 · openai' format.
|
Landed via temp rebase onto main.
Thanks @chrishham! |
Summary
The Control UI model dropdown sends the wrong provider prefix when switching to a model from a different provider than the session's current one.
Root cause:
buildChatModelOptions()inui/src/ui/app-render.helpers.tsuses justentry.id(e.g.gpt-5.2) as the<option>value, while the label correctly showsgpt-5.2 · openai. WhenswitchChatModelsends this bare model ID tosessions.patch, the server'sparseModelRef()sees no/and falls back to the session's currentdefaultProvider(e.g.anthropic), yieldinganthropic/gpt-5.2instead ofopenai/gpt-5.2.Fix:
buildChatModelOptions: useprovider/modelas option values (e.g.openai/gpt-5.2)resolveModelOverrideValue: returnprovider/modelfrom server session data so selected state stays in syncresolveDefaultModelValue: same treatment for the default model valuemodelProvidertoGatewaySessionsDefaultsUI type (server already sends it)Reproduces when: you have models from multiple providers (e.g. Anthropic + OpenAI, Anthropic + Ollama, OpenRouter models) and switch between them in the Control UI.
Related issues
Closes #47559, closes #47352, closes #46764, closes #46577, closes #46453, closes #45938, closes #46859, closes #45630
All report the same root cause: the Control UI model dropdown strips or misassigns the provider prefix.
Test plan
anthropic/claude-sonnet-4-5andopenai/gpt-5.2)sessions.patchsendsopenai/gpt-5.2(notanthropic/gpt-5.2)