Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions hermes_cli/codex_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,15 @@
# curated fallback so Pro users still see Spark in `/model` when live
# discovery is unavailable (offline first run, transient API failure).
"gpt-5.3-codex-spark",
"gpt-5.2-codex",
"gpt-5.1-codex-max",
"gpt-5.1-codex-mini",
# gpt-5.2-codex, gpt-5.1-codex-max, and gpt-5.1-codex-mini are
# intentionally NOT listed here. The openai-codex provider always
# authenticates via the ChatGPT-account OAuth backend
# (chatgpt.com/backend-api/codex; resolve_codex_runtime_credentials
# always sets auth_mode="chatgpt"), and that backend rejects those
# older slugs with HTTP 400: "The '<model>' model is not supported
# when using Codex with a ChatGPT account." Issue #23097. They remain
# in _PROVIDER_MODELS["openai"] / opencode-zen because those backends
# still accept them; this fallback is openai-codex-only.
]

_FORWARD_COMPAT_TEMPLATE_MODELS: List[tuple[str, tuple[str, ...]]] = [
Expand Down
22 changes: 22 additions & 0 deletions tests/hermes_cli/test_codex_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,28 @@ def test_get_codex_model_ids_falls_back_to_curated_defaults(tmp_path, monkeypatc
assert "gpt-5.3-codex-spark" in models


def test_default_codex_models_excludes_chatgpt_account_unsupported():
"""Regression for #23097: the openai-codex picker fallback must not
surface slugs the ChatGPT-account Codex backend rejects with HTTP 400.

The openai-codex provider always authenticates via the ChatGPT-account
OAuth backend in Hermes (resolve_codex_runtime_credentials always sets
auth_mode="chatgpt"), so DEFAULT_CODEX_MODELS — used as the offline /
transient-failure fallback for the picker — must only contain models
that backend accepts.
"""
rejected_on_chatgpt_account = {
"gpt-5.2-codex",
"gpt-5.1-codex-max",
"gpt-5.1-codex-mini",
}
assert rejected_on_chatgpt_account.isdisjoint(DEFAULT_CODEX_MODELS), (
"DEFAULT_CODEX_MODELS still contains models the ChatGPT-account "
"Codex backend rejects: "
f"{rejected_on_chatgpt_account.intersection(DEFAULT_CODEX_MODELS)}"
)


def test_get_codex_model_ids_adds_forward_compat_models_from_templates(monkeypatch):
monkeypatch.setattr(
"hermes_cli.codex_models._fetch_models_from_api",
Expand Down
Loading