Skip to content

Release LR — v0.51.354 (#3950 preserve @provider:model picks across cold catalogs)#3951

Merged
nesquena-hermes merged 2 commits into
masterfrom
release/stage-lr2
Jun 10, 2026
Merged

Release LR — v0.51.354 (#3950 preserve @provider:model picks across cold catalogs)#3951
nesquena-hermes merged 2 commits into
masterfrom
release/stage-lr2

Conversation

@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Single backend PR (api/routes.py + api/config.py + tests). @starship-s, contributor-fixed across 3 rounds responding to the gate findings.

Gate results — both SAFE

Fixes the @ollama-cloud:minimax-m3 snaps to default report (#3737 lineage). Keeps the #3867 cached-catalog hot path intact.

nesquena-hermes and others added 2 commits June 10, 2026 22:16
_resolve_compatible_session_model_state() no longer reverts an explicit
@Provider:model selection to the default when the provider's group is missing from
the cached catalog snapshot. explicit picks always honored; non-explicit (2nd+ turn
/ chat switch) preservation requires the provider to be KNOWN/CONFIGURED via the new
_provider_is_known_or_configured() (static registry + custom-provider config, NOT the
cold catalog) — so a cold live-discovery provider (ollama-cloud/deepseek/xai) is
preserved while a genuinely-unknown provider (@removed:...) falls through to
default-repair. A known-but-unconfigured builtin is deliberately preserved (surfaces
a clear runtime auth error rather than a silent swap; a cheap env/config credential
check would mis-classify OAuth/auth-store providers). Keeps the #3867 cached-catalog
hot path intact.

Co-authored-by: starship-s <starship-s@users.noreply.github.com>
@nesquena-hermes nesquena-hermes merged commit b1a4750 into master Jun 10, 2026
11 checks passed
@nesquena-hermes nesquena-hermes deleted the release/stage-lr2 branch June 10, 2026 22:20
@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a silent model-revert bug where an explicit @provider:model pick (e.g. @ollama-cloud:minimax-m3) was being snapped back to the global default on 2nd-and-later turns or chat-switches whenever the provider's group was absent from the cached catalog snapshot. The fix introduces two cooperating changes in _resolve_compatible_session_model_state: an early-return for fresh explicit picks (above the family-match repair) and a cold-catalog preserve guard for non-explicit paths.

  • api/config.py: New _provider_is_known_or_configured() helper decides "known vs. genuinely removed" from the static provider registry + global config alone, deliberately avoiding any catalog/credential lookup that would defeat the prefer_cached_catalog hot-path win.
  • api/routes.py: Explicit picks return immediately with their provider intact; non-explicit paths preserve the selection when the provider normalizes to \"\" (live-discovery providers), the bare model name isn't a first-party family prefix, and _provider_is_known_or_configured() returns True.
  • tests/test_provider_mismatch.py: Seven new tests cover the fixed case, the removed-provider revert, the intentional known-but-unconfigured preservation, and the documented gpt-prefix known-limitation — all clearly pinned.

Confidence Score: 4/5

Safe to merge; the fix is well-scoped, all three logical branches are covered by new tests, and the deliberate design decisions are clearly documented inline.

The explicit-pick early return and the cold-catalog guard are correctly ordered and logically sound. One gap: @openrouter:... picks still revert on a cold catalog because _normalize_provider_id("openrouter") returns a non-empty string, excluding it from the preserve path — the same class of issue fixed for ollama-cloud/deepseek/xai. Whether this is in-scope or intentional warrants a follow-up.

api/routes.py — specifically the not provider_normalized condition in the cold-catalog guard and whether openrouter should be included.

Important Files Changed

Filename Overview
api/config.py Adds _provider_is_known_or_configured() helper; correctly consults static _PROVIDER_DISPLAY/_PROVIDER_MODELS registries + config-global cfg (no catalog); _PROVIDER_MODELS is defined after the function in the file but Python name lookup at call-time makes this safe.
api/routes.py Adds explicit-pick early return and cold-catalog preserve guard in _resolve_compatible_session_model_state; logic is correct, but openrouter (normalizes to "openrouter", non-empty) is implicitly excluded from the new cold-catalog guard and still reverts on cold catalog — same as pre-PR, but worth noting.
tests/test_provider_mismatch.py Adds 7 new tests covering the fixed bug (ollama-cloud cold catalog), removed-provider revert, intentional known-unconfigured-builtin preservation, explicit-pick family-match bypass, and the gpt-prefix false-positive known limitation; all pinned correctly.
CHANGELOG.md Adds v0.51.354 release entry accurately describing the fix and its deliberate design boundaries.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["_resolve_compatible_session_model_state\n(model='@provider:model')"] --> B{explicit_model_pick?}
    B -- "True (fresh pick)" --> C["return model, provider_raw, False\n(never reroute)"]
    B -- "False (2nd+ turn / chat-switch)" --> D{provider in\ncatalog?}
    D -- "Yes" --> E["return model, provider_raw, False\n(catalog confirms provider)"]
    D -- "No" --> F{bare_model matches\nactive family?}
    F -- "Yes" --> G["return bare_model, active_provider, True\n(stale cross-provider repair)"]
    F -- "No" --> H{not provider_normalized\nAND not first-party prefix\nAND known/configured?}
    H -- "Yes\n(cold live-discovery provider)" --> I["return model, provider_raw, False\n(preserve across cold catalog)"]
    H -- "No\n(removed/unknown provider)" --> J{default_model?}
    J -- "Yes" --> K["return default_model, active_provider, True\n(revert to default)"]
    J -- "No" --> L["return model, provider_raw, False\n(last-resort pass-through)"]
Loading

Reviews (1): Last reviewed commit: "chore: stamp v0.51.354 — Release LR (@pr..." | Re-trigger Greptile

Comment thread api/routes.py
Comment on lines +2720 to +2725
if (
not provider_normalized
and not _bare_is_first_party_family
and _provider_is_known_or_configured(provider_raw)
):
return model, provider_raw, False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 openrouter still reverts on cold catalog

_normalize_provider_id("openrouter") returns "openrouter" (non-empty), so not provider_normalized is False and the new cold-catalog preserve guard never fires for @openrouter:... picks. A user with a cold catalog and an @openrouter:some-private-model selection will still silently revert to the default on 2nd+ turns, the same class of bug being fixed here for ollama-cloud/deepseek/xai. If openrouter's live-model-discovery behaviour is similar enough that cold-catalog transients occur in practice, it should be added to the preserve path (or _normalize_provider_id updated to return "" for it alongside the other live-discovery providers). Is openrouter intentionally left out of the cold-catalog preserve guard, or is this an oversight that should be addressed in a follow-up?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant