Repository navigation
fix(models): validate OpenRouter presets structurally on custom endpoints (#97907) - #97951
Tranquil-Flow wants to merge 1 commit into
Conversation
…ints (NousResearch#97907) OpenRouter dashboard presets (@preset/<slug>) are server-side objects that never appear in /models listings. On OpenRouter-compatible custom providers the custom-endpoint validation branch probed the catalog, missed, and soft-accepted with a false "not found" warning embedding the raw catalog URL — which Telegram's link preview fetched and rendered as a models.json document on every preset switch. Validate preset references structurally instead: a bare @preset/<slug> is accepted without probing (OpenRouter validates the slug at request time) with a URL-free message; <model>@preset/<slug> validates the BASE model against the listing and preserves the suffix through auto-correction (same rule as the :nitro routing variants); malformed slugs are rejected with the slug contract. Non-preset identifiers keep the existing behavior.
PR #97951 — fix(models): validate OpenRouter presets structurally on custom endpointsSummary: OpenRouter Non-blocking observations:
Verdict: Well-tested fix for #97907 (four layers: bare, combined, malformed, non-preset unchanged). No blocking issues. |
What
OpenRouter dashboard presets (
@preset/<slug>) are account-scoped server-side objects — they never appear in a/modelslisting. On OpenRouter-compatible custom providers,validate_requested_model()'s custom-endpoint branch probed the catalog, always missed, and soft-accepted with a false "not found in this custom endpoint's model listing" warning embedding the raw catalog URL. Telegram's link preview fetched that URL and rendered the large JSON response as amodels.jsondocument on every preset switch.Note the premise:
validate_requested_model()reclassifiesopenrouter+ non-openrouter.aibase_urltocustom(models.py:6508-6509), so the custom branch is exactly the path this issue reports.Fix
Handle preset references structurally in the custom branch instead of catalog-probing them:
@preset/<slug>— accepted without probing (OpenRouter validates the slug at request time), with a URL-free message. Nothing for a link preview to fetch.<model>@preset/<slug>— the BASE model is validated against the live listing; the preset suffix is preserved verbatim on the persisted/corrected id (same rule as the existing:nitrorouting-variant handling, which the fuzzy corrector would otherwise strip).[A-Za-z0-9._~-]+), not a misleading catalog warning.@preset/markers — not a defined form; keeps existing behavior.No gateway/Telegram adapter change: the document trigger is removed at the source (no URL in the message), and normal link previews remain enabled per the issue's Expected section.
Verification
tests/hermes_cli/test_openrouter_preset_custom_validation.py— 13 new tests covering all four layers (bare preset, combined form, malformed slug, non-preset unchanged).0d02f0d1dc.test_model_validation.py,test_model_switch_custom_providers.py,test_custom_provider_model_switch.py,test_user_providers_model_switch.py,test_openai_codex_model_validation_fallback.py): 140 passed, 2 failed — both failures reproduce identically on clean upstream/main (pre-existing, unrelated).git rev-list --left-right --count→0 1).Competitor analysis
Open PR #89129 "fix(models): support OpenRouter preset references" handles
@preset/only in thenormalized == "openrouter"branch — correct for native OpenRouter, but the custom-provider scenario of this issue never satisfies that gate (it is reclassified tocustomupstream of the branch). Scopes are complementary with no gated-code-path overlap; the slug-charset rule mirrors #89129's for cross-branch consistency.Fixes #97907.
Auto-published by Moonsong via Path B automated pipeline.