fix(models): add xai to _MODELS_DEV_PREFERRED; refresh stale curated IDs (#16699)#16734
Conversation
…IDs (NousResearch#16699) The curated `_PROVIDER_MODELS["xai"]` list contained two slugs that no longer match xAI's catalog (`grok-4.20-reasoning`, `grok-4-1-fast-reasoning`). Selecting either from the `/model` picker yields HTTP 400 "Unknown Model". Two changes, applied together because each is incomplete on its own: 1. Add `"xai"` to `_MODELS_DEV_PREFERRED`. xAI's catalog drifts (e.g. the `grok-4.20` family was renamed to date-suffixed IDs like `grok-4.20-0309-reasoning`), so the picker should merge fresh models.dev entries on top of the curated list — the same pattern already in place for opencode-go, opencode-zen, deepseek, zai, gemini, etc. Without this, even refreshing the curated list locks us into another stale snapshot the moment xAI renames again. 2. Replace the curated entries with current valid IDs (taken from the live models.dev `xai` provider catalog, filtered to `tool_call=True`). This is the offline / restricted-network fallback path — when models.dev is unreachable, users still see the curated list, so it must contain real current IDs that don't 400 on selection. Regression test asserts: - xAI is in `_MODELS_DEV_PREFERRED`. - Fresh models.dev entries surface via `provider_model_ids("xai")` (the reported picker bug). - Offline fallback contains current IDs and excludes the two stale entries (`grok-4.20-reasoning`, `grok-4-1-fast-reasoning`). The new tests fail on clean origin/main with `assert 'grok-4.20-0309-reasoning' in ['grok-4.20-reasoning', 'grok-4-1-fast-reasoning']`, which is the exact symptom reporters hit. Fixes NousResearch#16699 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates Hermes’ model catalog behavior for the xai provider to prevent stale curated IDs from breaking /model selection, while keeping an offline fallback.
Changes:
- Add
xaito_MODELS_DEV_PREFERREDsoprovider_model_ids("xai")and the/modelpicker merge freshmodels.deventries on top of curated IDs. - Refresh
_PROVIDER_MODELS["xai"]curated fallback to currently valid xAI model IDs. - Add regression tests covering preferred-merge and offline-fallback behavior for
xai.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
hermes_cli/models.py |
Updates xAI curated fallback IDs and enables models.dev-preferred merging for xai. |
tests/hermes_cli/test_models_dev_preferred_merge.py |
Adds tests to prevent regressions in xAI model merging and offline curated fallback behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
CI audit — all 16 Touched-code tests pass locally: The 16 failures (env-specific WSL detection, |
|
Closing — superseded by @vominh1919's #16934 (static refresh, merged 6c78305) and @teknium1's follow-up a83f669 (auto-derive xAI list from The auto-derive approach is strictly better:
The Teknium follow-up is the cleaner shape — replacing the static list with a cache-backed helper means the next xAI rename won't require any code change at all. Thanks @vominh1919 + @teknium1. |
Summary
"xai"to_MODELS_DEV_PREFERREDso the/modelpicker merges freshmodels.deventries on top of curated, matching the existing pattern for opencode-go, deepseek, zai, gemini, etc.grok-4.20-reasoning,grok-4-1-fast-reasoning— both 400 on selection) with current valid IDs taken from the livemodels.devxai catalog (filtered totool_call=True).provider_model_ids("xai")for both the live-merge and offline-fallback paths.The bug
_PROVIDER_MODELS["xai"]inhermes_cli/models.pycontains two slugs that no longer match xAI's catalog:Reproduction (from the issue, verified against live xAI catalog):
Configure xAI provider via
XAI_API_KEYand basehttps://api.x.ai/v1.Run
hermes, open/model, select xAI, pick either entry.Result:
Verified against a fresh
https://models.dev/api.jsonfetch — the xai provider'stool_call=TrueIDs are date-suffixed:grok-4.20-0309-reasoning,grok-4.20-0309-non-reasoning, plusgrok-4-fast,grok-4-fast-non-reasoning,grok-code-fast-1, etc. None of those match the curated list.The fix
Two changes — each is incomplete on its own:
Add
"xai"to_MODELS_DEV_PREFERRED. xAI's catalog drifts (thegrok-4.20family was renamed to date-suffixed IDs upstream). Adding xai to the preferred set causesprovider_model_idsand the gateway/modelpicker to merge freshmodels.deventries on top of the curated list — the exact pattern already in place for opencode-go, opencode-zen, deepseek, zai, gemini, etc. Without this, refreshing the curated list just locks us into another stale snapshot the next time xAI renames a model.Refresh the curated fallback to current valid IDs. This list is the offline / restricted-network fallback (when
models.devis unreachable, this is the only catalog users see), so it has to contain real current IDs that don't 400 on selection. New entries are pulled from the livemodels.devxai catalog filtered totool_call=True:xAI doesn't fit either documented exclusion (
openrouter— too many models to dump;nous— Portal/modelsendpoint is the source of truth), so adding it is consistent with the existing block comment.Test plan
tests/hermes_cli/test_models_dev_preferred_merge.py— 14 passed (3 new):test_xai_is_preferred— xai is in_MODELS_DEV_PREFERRED.test_xai_includes_fresh_models_dev_entries— fresh models.dev entries surface (the picker bug from [Bug] _PROVIDER_MODELS["xai"] is stale — grok-4.20-reasoning renamed; broader fragility from hardcoded provider lists #16699).test_xai_offline_falls_back_to_curated— curated floor contains current IDs, excludes the two stale ones.Adjacent suite:
test_model_catalog,test_user_providers_model_switch,test_api_key_providers,test_model_validation,test_model_metadata— 354 passed.Regression guard: ran the 3 new tests against unmodified
hermes_cli/models.py(only test file diffed) — all 3 fail with the exact reporter symptom:After applying the source fix, all 3 pass.
Notes
/model grok-4-1-fast-reasoninginwebsite/docs/integrations/providers.mdand the test fixture intests/agent/test_model_metadata.py(substring-matching context-length lookup) are intentionally not touched here — both are independent of the picker behaviour and would broaden scope. Worth a small follow-up.VERCEL_AI_GATEWAY_MODELSand OpenRouter slug entries (xai/grok-4.20-reasoning,x-ai/grok-4.20) are gateway-specific aliases, not direct xAI API IDs, so they are left alone here.Related
openai-codexprecedent [Bug] Telegram /model picker missing gpt-5.4 for openai-codex provider (stale _PROVIDER_MODELS hardcoded list) #6595 → PR fix: add gpt-5.3-codex-spark to openai-codex curated model list #7844.