From eaddeaf2e6b91e5b6543f4db46b969d153c067d0 Mon Sep 17 00:00:00 2001 From: definitelynotguru Date: Wed, 17 Jun 2026 19:54:24 +0530 Subject: [PATCH] feat(xai): add grok-composer-2.5-fast to xAI OAuth model picker The model is callable via xAI OAuth but omitted from models.dev and /v1/models listings. Merge it into the curated xAI catalog so it appears in `hermes model` without requiring a custom model name. --- agent/model_metadata.py | 1 + hermes_cli/models.py | 21 +++++++++++++++++++-- tests/hermes_cli/test_xai_curated_models.py | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/hermes_cli/test_xai_curated_models.py diff --git a/agent/model_metadata.py b/agent/model_metadata.py index e31fcdea48d..4d14826b9ef 100644 --- a/agent/model_metadata.py +++ b/agent/model_metadata.py @@ -275,6 +275,7 @@ DEFAULT_CONTEXT_LENGTHS = { # via a custom provider. Values sourced from models.dev (2026-04). # Keys use substring matching (longest-first), so e.g. "grok-4.20" # matches "grok-4.20-0309-reasoning" / "-non-reasoning" / "-multi-agent-0309". + "grok-composer": 200000, # grok-composer-2.5-fast (Grok Build CLI) "grok-build": 256000, # grok-build-0.1 "grok-code-fast": 256000, # grok-code-fast-1 "grok-2-vision": 8192, # grok-2-vision, -1212, -latest diff --git a/hermes_cli/models.py b/hermes_cli/models.py index dc605ab001f..f84ac69564e 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -117,6 +117,11 @@ _XAI_STATIC_FALLBACK: list[str] = [ "grok-4.20-multi-agent-0309", ] +# Callable via xAI OAuth but omitted from models.dev and /v1/models listings. +_XAI_CURATED_EXTRAS: list[str] = [ + "grok-composer-2.5-fast", +] + _XAI_TOP_MODEL = "grok-build-0.1" @@ -128,6 +133,18 @@ def _xai_promote_top(ids: list[str]) -> list[str]: return ids +def _xai_merge_curated_extras(ids: list[str]) -> list[str]: + """Append Hermes-curated xAI models that are missing from models.dev.""" + out = list(ids) + for extra in _XAI_CURATED_EXTRAS: + if extra in out: + continue + # Keep the headline model pinned; slot extras immediately after it. + insert_at = 1 if out and out[0] == _XAI_TOP_MODEL else len(out) + out.insert(insert_at, extra) + return out + + def _xai_curated_models() -> list[str]: """Derive the xAI-direct curated list from models.dev disk cache. @@ -147,12 +164,12 @@ def _xai_curated_models() -> list[str]: if isinstance(models, dict) and models: ids = [mid for mid in models.keys() if isinstance(mid, str)] if ids: - return _xai_promote_top(sorted(ids)) + return _xai_merge_curated_extras(_xai_promote_top(sorted(ids))) except Exception: # Any failure (missing file, malformed JSON, import error) # falls through to the static list. pass - return list(_XAI_STATIC_FALLBACK) + return _xai_merge_curated_extras(list(_XAI_STATIC_FALLBACK)) _PROVIDER_MODELS: dict[str, list[str]] = { diff --git a/tests/hermes_cli/test_xai_curated_models.py b/tests/hermes_cli/test_xai_curated_models.py new file mode 100644 index 00000000000..77b493b3c8f --- /dev/null +++ b/tests/hermes_cli/test_xai_curated_models.py @@ -0,0 +1,14 @@ +"""Regression tests for xAI curated model list (OAuth picker).""" + +from hermes_cli.models import _PROVIDER_MODELS, provider_model_ids + + +def test_xai_oauth_includes_grok_composer_2_5_fast(): + models = provider_model_ids("xai-oauth") + assert "grok-composer-2.5-fast" in models + + +def test_grok_composer_slots_after_grok_build(): + models = _PROVIDER_MODELS["xai-oauth"] + assert models[0] == "grok-build-0.1" + assert models[1] == "grok-composer-2.5-fast" \ No newline at end of file