fix: limit desktop model pickers to explicit providers (#56974) - #60514
Merged
Conversation
…+ non-desktop picker opt-ins Follow-up on the #56966 salvage: - is_provider_explicitly_configured(): an env-seeded credential-pool entry only counts as explicit while its env var still resolves to a usable secret. A stale auth.json entry left behind after the user deletes the var no longer keeps the provider in the picker forever (#55790). - TUI modelPicker + dashboard ModelPickerDialog/api.getModelOptions pass include_unconfigured=true explicitly, preserving their full-universe setup-affordance behavior now that the backend defaults to the configured subset. - desktop lib/model-options.ts routes explicit_only through the shared requestModelOptions() helper (added on main after the PR branched). - regression tests for ambient (gh_cli) pool sources, explicit manual/ device-code sources, and stale vs live env-seeded entries.
This was referenced Jul 7, 2026
9 tasks
This was referenced Jul 11, 2026
Closed
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.
Summary
Desktop chat model pickers now list only providers the user explicitly configured — ambient credentials (a GitHub CLI login surfacing Copilot, stale auth.json pool entries, residual provider state) no longer leak unconfigured providers into the picker, and switching to one of those phantom providers no longer fails and snaps back to the previous model.
Salvage of #56966 by @rarf (authorship preserved via cherry-pick), rebased onto current main, plus follow-up hardening.
Fixes #56974. Also addresses the stale-pool half of #55790 and the picker-clutter asks in #59483 / #57886 / #59733.
Root cause
list_authenticated_providers()treats any discoverable credential record as "authenticated": an env-seededcredential_poolentry whose env var no longer resolves, agh auth tokenlogin auto-seeded as a Copilot credential, or a stub left inauth.jsonby an abandoned setup. The desktop chat picker rendered all of them as selectable providers; picking one failed at switch time (Could not resolve credentials for provider ...) and the optimistic UI rolled back — the "model swaps back to the original" report.Changes
hermes_cli/inventory.py: newexplicit_onlyflag onbuild_models_payload()+_filter_explicit_provider_rows()— keeps rows for the current provider, user-defined endpoints, and providers passingis_provider_explicitly_configured().hermes_cli/auth.py:is_provider_explicitly_configured()gains a credential-pool check that counts explicit Hermes flows (manual add, device-code, PKCE) and env-seeded entries — but an env-seeded entry only counts while its env var still resolves to a usable secret, so stale auth.json records left after key removal no longer mark a provider configured ([Bug]: Stale credential pool entries cause removed providers to persist in model picker #55790). Ambient sources (gh_cli,claude_code) are excluded.tui_gateway/server.pymodel.options+web_server.py/api/model/options: acceptexplicit_only/include_unconfiguredparams; desktop chat surfaces requestexplicit_only, onboarding keeps the full universe.explicit_only: true(routed through the sharedrequestModelOptions()helper added on main after the PR branched); onboarding flows opt intoincludeUnconfigured.modelPicker.tsx+ dashboardModelPickerDialog.tsx/api.getModelOptions(): passinclude_unconfigured: trueexplicitly, preserving their full-universe setup-affordance behavior unchanged.Validation
scripts/run_tests.sh— inventory, auth gate, tui_gateway, web_server, opencode-go picker (5 files)web/src/lib/api.test.tsInfographic