mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-27 06:11:40 +00:00
fix: surface Codex CLI-only models
This commit is contained in:
parent
c6dc295a35
commit
9457644390
4 changed files with 36 additions and 9 deletions
|
|
@ -80,8 +80,10 @@ def _fetch_models_from_api(access_token: str) -> List[str]:
|
||||||
if not isinstance(slug, str) or not slug.strip():
|
if not isinstance(slug, str) or not slug.strip():
|
||||||
continue
|
continue
|
||||||
slug = slug.strip()
|
slug = slug.strip()
|
||||||
if item.get("supported_in_api") is False:
|
# Codex CLI's catalog uses ``supported_in_api`` for the public OpenAI
|
||||||
continue
|
# API, not for the OAuth-backed Codex backend that this provider uses.
|
||||||
|
# Some valid Codex CLI models (for example gpt-5.3-codex-spark) are
|
||||||
|
# marked false here but are still accepted by the Codex route.
|
||||||
visibility = item.get("visibility", "")
|
visibility = item.get("visibility", "")
|
||||||
if isinstance(visibility, str) and visibility.strip().lower() in ("hide", "hidden"):
|
if isinstance(visibility, str) and visibility.strip().lower() in ("hide", "hidden"):
|
||||||
continue
|
continue
|
||||||
|
|
@ -130,8 +132,9 @@ def _read_cache_models(codex_home: Path) -> List[str]:
|
||||||
if not isinstance(slug, str) or not slug.strip():
|
if not isinstance(slug, str) or not slug.strip():
|
||||||
continue
|
continue
|
||||||
slug = slug.strip()
|
slug = slug.strip()
|
||||||
if item.get("supported_in_api") is False:
|
# Do not filter on ``supported_in_api`` here. It describes the
|
||||||
continue
|
# public OpenAI API, while Hermes openai-codex talks to the same
|
||||||
|
# OAuth-backed Codex backend as Codex CLI.
|
||||||
visibility = item.get("visibility")
|
visibility = item.get("visibility")
|
||||||
if isinstance(visibility, str) and visibility.strip().lower() in ("hide", "hidden"):
|
if isinstance(visibility, str) and visibility.strip().lower() in ("hide", "hidden"):
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -1342,7 +1342,7 @@ def list_authenticated_providers(
|
||||||
if not has_creds:
|
if not has_creds:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if hermes_slug in {"copilot", "copilot-acp"}:
|
if hermes_slug in {"openai-codex", "copilot", "copilot-acp"}:
|
||||||
model_ids = provider_model_ids(hermes_slug)
|
model_ids = provider_model_ids(hermes_slug)
|
||||||
# For aws_sdk providers (bedrock), use live discovery so the list
|
# For aws_sdk providers (bedrock), use live discovery so the list
|
||||||
# reflects the active region (eu.*, ap.*) not the static us.* list.
|
# reflects the active region (eu.*, ap.*) not the static us.* list.
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,30 @@ def test_normal_path_still_works(hermes_auth_only_env):
|
||||||
assert "openai-codex" in slugs
|
assert "openai-codex" in slugs
|
||||||
|
|
||||||
|
|
||||||
|
def test_codex_picker_uses_live_codex_catalog(hermes_auth_only_env, tmp_path, monkeypatch):
|
||||||
|
"""The gateway /model picker should surface Codex CLI-only listed models."""
|
||||||
|
from hermes_cli.model_switch import list_authenticated_providers
|
||||||
|
|
||||||
|
codex_home = tmp_path / "codex-home"
|
||||||
|
codex_home.mkdir()
|
||||||
|
(codex_home / "models_cache.json").write_text(json.dumps({
|
||||||
|
"models": [
|
||||||
|
{"slug": "gpt-5.5", "priority": 0, "supported_in_api": True},
|
||||||
|
{"slug": "gpt-5.3-codex-spark", "priority": 7, "supported_in_api": False},
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
monkeypatch.setenv("CODEX_HOME", str(codex_home))
|
||||||
|
|
||||||
|
providers = list_authenticated_providers(
|
||||||
|
current_provider="openai-codex",
|
||||||
|
max_models=10,
|
||||||
|
)
|
||||||
|
|
||||||
|
codex = next(p for p in providers if p["slug"] == "openai-codex")
|
||||||
|
assert "gpt-5.3-codex-spark" in codex["models"]
|
||||||
|
assert codex["total_models"] == len(codex["models"])
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def claude_code_only_env(tmp_path, monkeypatch):
|
def claude_code_only_env(tmp_path, monkeypatch):
|
||||||
"""Set up an environment where Anthropic credentials only exist in
|
"""Set up an environment where Anthropic credentials only exist in
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
||||||
|
|
||||||
from hermes_cli.codex_models import DEFAULT_CODEX_MODELS, get_codex_model_ids
|
from hermes_cli.codex_models import DEFAULT_CODEX_MODELS, get_codex_model_ids
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -17,6 +13,7 @@ def test_get_codex_model_ids_prioritizes_default_and_cache(tmp_path, monkeypatch
|
||||||
{
|
{
|
||||||
"models": [
|
"models": [
|
||||||
{"slug": "gpt-5.3-codex", "priority": 20, "supported_in_api": True},
|
{"slug": "gpt-5.3-codex", "priority": 20, "supported_in_api": True},
|
||||||
|
{"slug": "gpt-5.3-codex-spark", "priority": 6, "supported_in_api": False},
|
||||||
{"slug": "gpt-5.1-codex", "priority": 5, "supported_in_api": True},
|
{"slug": "gpt-5.1-codex", "priority": 5, "supported_in_api": True},
|
||||||
{"slug": "gpt-5.4", "priority": 1, "supported_in_api": True},
|
{"slug": "gpt-5.4", "priority": 1, "supported_in_api": True},
|
||||||
{"slug": "gpt-5-hidden-codex", "priority": 2, "visibility": "hidden"},
|
{"slug": "gpt-5-hidden-codex", "priority": 2, "visibility": "hidden"},
|
||||||
|
|
@ -31,6 +28,9 @@ def test_get_codex_model_ids_prioritizes_default_and_cache(tmp_path, monkeypatch
|
||||||
assert models[0] == "gpt-5.2-codex"
|
assert models[0] == "gpt-5.2-codex"
|
||||||
assert "gpt-5.1-codex" in models
|
assert "gpt-5.1-codex" in models
|
||||||
assert "gpt-5.3-codex" in models
|
assert "gpt-5.3-codex" in models
|
||||||
|
# Codex CLI marks Spark unsupported in the public API, but the Codex
|
||||||
|
# backend still accepts it via the OAuth-backed CLI/Hermes route.
|
||||||
|
assert "gpt-5.3-codex-spark" in models
|
||||||
# Non-codex-suffixed models are included when the cache says they're available
|
# Non-codex-suffixed models are included when the cache says they're available
|
||||||
assert "gpt-5.4" in models
|
assert "gpt-5.4" in models
|
||||||
assert "gpt-5.4-mini" in models
|
assert "gpt-5.4-mini" in models
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue