fix(tui-gateway): restore openrouter provider override on session.resume - #57597
Closed
Ahmett101 wants to merge 1 commit into
Closed
fix(tui-gateway): restore openrouter provider override on session.resume#57597Ahmett101 wants to merge 1 commit into
Ahmett101 wants to merge 1 commit into
Conversation
…ume (NousResearch#57588) _BARE_BILLING_PROVIDERS at tui_gateway/server.py:2011 incorrectly bundled 'openrouter' with the actual bare buckets 'auto' and 'custom'. OpenRouter is a fully routable provider — it owns the session's API key, base_url, and live /v1/models catalog — so dropping its billing provider on session.resume silently redirected the restored model through the user's current config default (any newly-added custom endpoint like Featherless). That endpoint then probed its own /v1/models for the restored Opus model's context length, didn't find Opus, and surfaced as 'context window of 2,048 tokens, which is below the minimum 64,000 required by Hermes Agent'. Drop 'openrouter' from the bare set. The remaining two bare buckets ('auto' = global-default sentinel, 'custom' = unnamed billing class) stay filtered because restoring either as a provider override breaks resume for the documented reason: 'auto' defeats session-scoped restore, 'custom' is non-routable and surfaces as 'No LLM provider configured'. Verified the new test catches the bug by reverting the production change: test_restore_preserves_openrouter_billing_provider fails with 'provider_override' dropped — the exact symptom the reporter saw. Unreverted, all 4 new+updated tests pass alongside 346 pre-existing tui_gateway picker/server tests (no regressions). Tests: - tests/test_tui_gateway_server.py::test_stored_session_runtime_overrides_skips_bare_billing_provider Updated to drop 'openrouter' from the bare-tuple assertion and add a positive check that openrouter IS restored as provider_override. - tests/tui_gateway/test_custom_provider_session_persistence.py Added two tests under TestBareCustomNoBaseUrlHealsFromConfig: - test_restore_preserves_openrouter_billing_provider: pins the bug — row.model='anthropic/claude-opus-4.8', row.billing_provider='openrouter' → overrides['provider_override'] == 'openrouter' and overrides['model_override']['provider'] == 'openrouter'. - test_restore_drops_auto_billing_provider: companion negative check that the 'auto' sentinel stays filtered.
1 task
Collaborator
Duplicate of #57593 — both PRs fix #57588 with the byte-identical change (drop |
This was referenced Aug 13, 2026
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
_BARE_BILLING_PROVIDERSattui_gateway/server.py:2011incorrectly bundled"openrouter"with the real bare buckets"auto"and"custom". OpenRouter is a fully routable provider — it owns the session's API key, base_url, and live model catalog — so dropping its billing provider onsession.resumesilently redirected the restored model through whatever the user's current config default was (typically a newly-added custom endpoint like Featherless). That endpoint then probed its own/v1/modelsfor the restored Opus model's context length, didn't find Opus, and surfaced as "context window of 2,048 tokens, which is below the minimum 64,000 required by Hermes Agent". Fixes #57588.Fix: drop
"openrouter"from the bare set. The remaining two bare buckets ("auto"global-default sentinel,"custom"unnamed billing class) stay filtered because restoring either as a provider override breaks resume for the documented reason —"auto"defeats session-scoped restore,"custom"is non-routable and surfaces as "No LLM provider configured".Composition note: this fix is independent of the in-flight #57503 (picker filter) and #50289 (first-class mistral plugin). All three merge cleanly with no overlap; the bare-bucket set in tui_gateway does not interact with the picker or provider plugin registries.
Changes
tui_gateway/server.py: drop"openrouter"from_BARE_BILLING_PROVIDERS, expand the docstring to spell out why each of the two remaining bare buckets is bare and why openrouter is not. Single conceptual change:{"auto", "openrouter", "custom"}→{"auto", "custom"}.tests/test_tui_gateway_server.py: updatetest_stored_session_runtime_overrides_skips_bare_billing_provider—"openrouter"is now removed from the bare-tuple loop and added as a positive assertion (ov["provider_override"] == "openrouter").tests/tui_gateway/test_custom_provider_session_persistence.py: add two tests underTestBareCustomNoBaseUrlHealsFromConfig:test_restore_preserves_openrouter_billing_provider— pins the bug. row.model=anthropic/claude-opus-4-8, row.billing_provider="openrouter"→overrides["provider_override"] == "openrouter"ANDoverrides["model_override"]["provider"] == "openrouter". Failure mode reproduces the reporter's "context window … below 64,000" error.test_restore_drops_auto_billing_provider— companion negative check that the"auto"sentinel stays filtered (resume falls back to the configured default for bare"auto").How to Test
Bug-catch verification (the new regression test catches the bug):
git stash push -m bug-check tui_gateway/server.py pytest tests/tui_gateway/test_custom_provider_session_persistence.py::TestBareCustomNoBaseUrlHealsFromConfig::test_restore_preserves_openrouter_billing_provider -vs # FAILS: AssertionError — provider_override dropped on resume (the exact symptom #57588 reports) git stash popChecklist
fix(scope):)_BARE_BILLING_PROVIDERS, doc update, test coveragemistrallisted in /model picker but fails with "Unknown provider 'mistral'" #57503 and feat: add Mistral AI as first-class LLM provider #50289 — no overlapRisk & Impact
Low. Strictly removes a spurious
continue-equivalent in a session-restore path: stored OpenRouter rows now come through with their provider override intact instead of being silently dropped. Users who currently hit the bug get a fixed resume immediately; users with working environments see no change. The two real bare-bucket cases (auto,custom) still filter identically to before.Type: Bug fix
Closes #57588
Related findings (out of scope here, flagged for maintainers):
"custom"but bundled"openrouter"along for what was likely a "route via OpenRouter if any credential resolves to OR" mental model. If a similar bundling exists elsewhere (e.g. a sibling bare-bucket check that mistakenly skips"anthropic","google", or other routable names), an audit pass driven by the now-shrunk_BARE_BILLING_PROVIDERSsemantics would surface it. Strictly out of scope for this PR; happy to file/follow up if asked.resolve_provider_client("openrouter", ...)as an early sanity check rather than deferring toagent_init's 64K-context guard, but that's a hermes_init-level change and depends on design buy-in.