fix(desktop): persist custom provider entry identity in session runtime, not the resolved "custom"#44109
Closed
AIalliAI wants to merge 1 commit into
Closed
Conversation
_runtime_model_config persisted the live agent's RESOLVED provider into the session row's model_config JSON. For any named providers:/ custom_providers: entry, agent.provider is the literal string "custom", so the entry name was lost (and the api_key is deliberately never persisted). On session.resume or _reset_session_agent the stored provider="custom" fed resolve_runtime_provider(requested="custom"), which cannot match a named entry — the rebuild either raised "No LLM provider configured" or silently resolved placeholder credentials against the patched-back base_url. Persist the REQUESTED/entry identity instead: a new reverse lookup find_custom_provider_identity(base_url) maps the endpoint URL back to the canonical custom:<name> menu key. _runtime_model_config stores that key; _make_agent performs the same recovery for rows persisted before the fix, falling back to passing the stored base_url as explicit_base_url so the direct-alias branch still targets the session's endpoint when no entry matches. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Author
|
Requesting maintainer review — this is ready to land from my side. Standalone fork CI is pending first-run approval here; the rollup branch in #44061 carrying this session's batch is fully green on upstream CI (all test shards, typecheck, e2e). |
This was referenced Jun 13, 2026
Contributor
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.
Fixes #44108
Problem
_runtime_model_config()(tui_gateway/server.py) persists the live agent's resolved provider into the session row'smodel_configJSON. For any namedproviders:/custom_providers:entry,agent.provideris the literal string"custom"— the entry name is lost, and the api_key is deliberately never persisted (credentials must keep coming from config/env, see_stored_session_runtime_overrides).On
session.resume/_reset_session_agent, the storedprovider="custom"feedsresolve_runtime_provider(requested="custom"), which_get_named_custom_providercannot match back to the named entry. Depending on config, the rebuild either raisesNo LLM provider configured. Runhermes model...(resume fails) or silently resolves placeholder credentials ("no-key-required") against the patched-back base_url.Sibling of #44022 (which covers rows where
model_configwas never written and only the barebilling_providercolumn exists — that path is not changed here). Same resolved-vs-requested identity-loss family as the #44070 investigation in #44099.Fix
Persist the requested/entry identity, not the resolved one:
hermes_cli/runtime_provider.py: new reverse lookupfind_custom_provider_identity(base_url)mapping an endpoint URL back to the canonicalcustom:<normalized-name>menu key (scansproviders:dict and legacycustom_providers:list; trailing-slash/case tolerant). The slug form matches what a live/modelswitch already records viapdef.idand what_get_named_custom_providerresolves.tui_gateway/server.py::_runtime_model_config: whenagent.provider == "custom"and the base_url maps to an entry, persist thecustom:<name>key instead of the lossy"custom". Built-in providers never trigger the lookup.tui_gateway/server.py::_make_agent: heals rows persisted before this fix — when the stored override isprovider="custom"with a base_url, recover the entry identity the same way; if no entry matches, pass the stored base_url asexplicit_base_urlso the direct-alias branch resolves pool/env credentials for the session's actual endpoint instead of raisingauth_unavailable.Tests
tests/tui_gateway/test_custom_provider_session_persistence.py(style mirrors the #44070 regression tests):_runtime_model_configpersistscustom:<name>for both config shapes; keeps bare"custom"when nothing matches; never persists api_key; built-ins untouched._stored_session_runtime_overrides→_make_agentround-trip through the realresolve_runtime_providerrestores the entry's credentials (the exact path that raised before).provider="custom"+ base_url) heals via base_url recovery; unmatched legacy row keeps its endpoint via the direct-alias branch.tests/hermes_cli/test_custom_provider_identity.py: unit coverage for the reverse lookup, including that the returned slug round-trips through_get_named_custom_provider.Red/green verified: 5/7 gateway tests fail on origin/main sources, all pass with the fix.
tests/test_tui_gateway_server.py,tests/tui_gateway/,tests/hermes_cli/pass (the 12 pre-existing failures there — WSL/service-manager/browser-hint, macOS environment — fail identically on pristine origin/main).🤖 Generated with Claude Code