From 638e7a3e9f7d6d63b97dfb536f52376299488ce9 Mon Sep 17 00:00:00 2001 From: vominh1919 Date: Tue, 28 Apr 2026 11:14:04 +0700 Subject: [PATCH 1/2] fix(models): update stale xAI model list (#16699) _PROVIDER_MODELS["xai"] was pointing at model IDs the xAI direct API no longer accepts: - grok-4.20-reasoning - grok-4-1-fast-reasoning Replaced with the actual current xAI catalog IDs from models.dev ($HERMES_HOME/models_dev_cache.json, mirror of https://models.dev/api.json): grok-4.20-0309-reasoning grok-4.20-0309-non-reasoning grok-4.20-multi-agent-0309 grok-4-1-fast grok-4-1-fast-non-reasoning grok-4-fast grok-4-fast-non-reasoning grok-4 grok-code-fast-1 The xAI-direct API (https://api.x.ai/v1) serves the dated IDs shown above; the bare aliases (grok-4.20, grok-4.1-fast, etc.) are OpenRouter/Vercel-gateway normalizations and are not accepted on xAI-direct. Those gateways remain unaffected. Fixes #16699 --- hermes_cli/models.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hermes_cli/models.py b/hermes_cli/models.py index 19a036b923c85..3afc894d5960c 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -194,8 +194,15 @@ def _codex_curated_models() -> list[str]: "glm-4.5-flash", ], "xai": [ - "grok-4.20-reasoning", - "grok-4-1-fast-reasoning", + "grok-4.20-0309-reasoning", + "grok-4.20-0309-non-reasoning", + "grok-4.20-multi-agent-0309", + "grok-4-1-fast", + "grok-4-1-fast-non-reasoning", + "grok-4-fast", + "grok-4-fast-non-reasoning", + "grok-4", + "grok-code-fast-1", ], "nvidia": [ # NVIDIA flagship reasoning models From c2ea39ceb71bfa1ff69e7b879b668686acbfeb78 Mon Sep 17 00:00:00 2001 From: Teknium Date: Tue, 28 Apr 2026 01:47:31 -0700 Subject: [PATCH 2/2] fix(models): auto-derive xAI model list from models.dev cache (#16699) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the static list refresh: replace the hardcoded xAI entries with _xai_curated_models(), mirroring the _codex_curated_models() pattern from PR #7844. The helper reads $HERMES_HOME/models_dev_cache.json at import time (no network call) and falls back to a small static list when the cache is missing or malformed. Why: _PROVIDER_MODELS["xai"] has drifted once already (issue #16699) and will drift again next time xAI renames a model. Hermes already maintains the models.dev cache and uses it for context-length lookups; pointing _PROVIDER_MODELS at the same source means the /model picker self-heals on the next cache refresh instead of requiring a PR. Behavior: - With cache populated (normal user): shows every current xAI model ID, picks up renames automatically on next refresh. - Without cache (fresh install, offline): falls back to a static snapshot of the 9 current flagship IDs. - Malformed cache / unexpected shape: same static fallback, no crash. Import time verified <20ms — disk read only, no HTTP. Addresses the structural piece of #16699 ("consider a single _provider_models(provider) resolver") for xAI. Other per-provider lists can adopt the same pattern as drift is observed. --- hermes_cli/models.py | 57 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/hermes_cli/models.py b/hermes_cli/models.py index 3afc894d5960c..21fa3b74f35f7 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -106,6 +106,51 @@ def _codex_curated_models() -> list[str]: return _add_forward_compat_models(list(DEFAULT_CODEX_MODELS)) +# Static fallback for xAI when the models.dev disk cache is empty (fresh +# install, offline first run, etc.). Mirrors the xAI-direct model IDs from +# $HERMES_HOME/models_dev_cache.json as of 2026-04-28. Whenever xAI renames +# or retires a model, the disk cache picks it up on the next refresh and the +# fallback here only matters until that refresh lands. +_XAI_STATIC_FALLBACK: list[str] = [ + "grok-4.20-0309-reasoning", + "grok-4.20-0309-non-reasoning", + "grok-4.20-multi-agent-0309", + "grok-4-1-fast", + "grok-4-1-fast-non-reasoning", + "grok-4-fast", + "grok-4-fast-non-reasoning", + "grok-4", + "grok-code-fast-1", +] + + +def _xai_curated_models() -> list[str]: + """Derive the xAI-direct curated list from models.dev disk cache. + + Reads $HERMES_HOME/models_dev_cache.json directly (no network) so this + runs at import time without blocking. Falls back to ``_XAI_STATIC_FALLBACK`` + when the cache is empty or unreadable. Hermes refreshes the cache from + https://models.dev/api.json on normal use, so this list self-heals as + xAI renames models. + + Mirrors ``_codex_curated_models()``'s role for openai-codex. + """ + try: + from agent.models_dev import _load_disk_cache + data = _load_disk_cache() + xai = data.get("xai") if isinstance(data, dict) else None + models = xai.get("models") if isinstance(xai, dict) else None + if isinstance(models, dict) and models: + ids = [mid for mid in models.keys() if isinstance(mid, str)] + if ids: + return sorted(ids) + except Exception: + # Any failure (missing file, malformed JSON, import error) + # falls through to the static list. + pass + return list(_XAI_STATIC_FALLBACK) + + _PROVIDER_MODELS: dict[str, list[str]] = { "nous": [ "moonshotai/kimi-k2.6", @@ -193,17 +238,7 @@ def _codex_curated_models() -> list[str]: "glm-4.5", "glm-4.5-flash", ], - "xai": [ - "grok-4.20-0309-reasoning", - "grok-4.20-0309-non-reasoning", - "grok-4.20-multi-agent-0309", - "grok-4-1-fast", - "grok-4-1-fast-non-reasoning", - "grok-4-fast", - "grok-4-fast-non-reasoning", - "grok-4", - "grok-code-fast-1", - ], + "xai": _xai_curated_models(), "nvidia": [ # NVIDIA flagship reasoning models "nvidia/nemotron-3-super-120b-a12b",