fix(gateway): don't restore a bare billing provider as the resumed session's provider#44062
Conversation
…ssion's provider `_stored_session_runtime_overrides` restored the session provider from `billing_provider` when `model_config` had no explicit provider. For a `custom:<name>` endpoint that only ran normal turns (no `/model` switch), the persisted `billing_provider` is the bare billing bucket `"custom"`, which `agent_init` treats as non-routable, so `session.resume` failed with "No LLM provider configured" even though new chats and CLI `--resume` work. Only restore an explicit `model_config.provider`; skip a bare billing bucket (`auto`/`openrouter`/`custom`) so resume falls back to the configured default, matching the CLI path. Fixes NousResearch#44022
|
✅ Verified — Bare billing provider exclusion on session resume Reviewed the diff for
Targeted fix for a real resume regression. No issues found. |
|
Verification: reviewed diff — clean fix. The root cause is clear: The fix correctly separates Priority chain is clean:
Test coverage is thorough: bare "custom"/"auto"/"openrouter" all correctly skipped, real provider "anthropic" correctly restored, explicit |
|
Hit this exact bug on Windows desktop with a custom provider. Resume fails with "No LLM provider configured" for every older session, while CLI --resume works fine. The root cause diagnosis and the fix look correct (i've tested it locally on my windows instance). skipping bare billing buckets ("custom", "auto", "openrouter") from being restored as provider identity matches the CLI path and doesn't break real provider restoration. Currently working around it by backfilling model_config in the sessions DB, but that's obviously not viable long-term. Would be great to get this in. the bug makes the desktop app basically unusable for custom provider users. |
|
Thanks for testing on Windows — good to have the independent confirmation, the older-sessions resume path is exactly it. |
What does this PR do?
Resuming an older chat in the desktop/TUI gateway failed with
resume failed: No LLM provider configuredwhenever the session had only ever run normal turns (no/modelswitch) against acustom:<name>endpoint — even though new chats andhermes chat --resume <id>from the CLI work fine for the same sessions.Root cause:
_stored_session_runtime_overrides(tui_gateway/server.py) restored the session provider frombilling_providerwhenmodel_confighad no explicitprovider. For a custom endpoint, the only thing persisted on a normal turn isbilling_provider, and its value is the bare billing bucket"custom"(not the routablecustom:<name>identity). That bare class was then set as the resumed session'sprovider_override/model_override.provider, andagent_inittreats a bareauto/openrouter/customas non-routable, so provider resolution returned no client and raisedNo LLM provider configured. The CLI is unaffected because it does not go through the session-scoped runtime-restore path.Fix: only restore an explicit
model_config.provider; skip a bare billing bucket so resume falls back to the configured default provider, matching the working CLI path. A real provider stored inbilling_provider(e.g.anthropic) is still restored. Introduced by #43702.Related Issue
Fixes #44022
Type of Change
Changes Made
tui_gateway/server.py—_stored_session_runtime_overrides: split provider resolution so a bare billing bucket (auto/openrouter/custom, mirrored from the gate inagent_init) is no longer restored as the session provider; only an explicitmodel_config.provider(or a non-barebilling_provider) is.tests/test_tui_gateway_server.py— addedtest_stored_session_runtime_overrides_skips_bare_billing_provider.How to Test
custom_providersendpoint as the default (model.provider: custom:<name>,api_mode: anthropic_messages)./model(so the row persists onlybilling_provider="custom").mainit fails withNo LLM provider configured; with this change it resumes against the configured default.Regression test:
pytest tests/test_tui_gateway_server.py::test_stored_session_runtime_overrides_skips_bare_billing_provider(fails before, passes after). The existingtest_session_resume_passes_stored_runtime_to_agent(a non-barebilling_provider) still passes, confirming real providers are still restored.Checklist
ruff checkpasses on the changed files