From cea1a09454d914ad87aed00e6d58f00112f1bba9 Mon Sep 17 00:00:00 2001 From: konsisumer Date: Sun, 10 May 2026 14:24:50 +0200 Subject: [PATCH] fix(cli): drop ChatGPT-account-rejected models from openai-codex picker fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEFAULT_CODEX_MODELS — the offline / transient-failure fallback for the openai-codex /model picker — listed three slugs the ChatGPT-account Codex backend rejects with HTTP 400 ("The '' model is not supported when using Codex with a ChatGPT account."): - gpt-5.2-codex - gpt-5.1-codex-max - gpt-5.1-codex-mini The openai-codex provider always authenticates via that backend in Hermes (resolve_codex_runtime_credentials hard-codes auth_mode="chatgpt"), so users would see "Model switched: " then hit a non-retryable 400 on the next request whenever live model discovery wasn't available. Remove them from the curated fallback. They remain in the openai (api.openai.com) and opencode-zen catalogs where the backend still accepts them. Fixes #23097 --- hermes_cli/codex_models.py | 12 +++++++++--- tests/hermes_cli/test_codex_models.py | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/hermes_cli/codex_models.py b/hermes_cli/codex_models.py index 8e50004c2d6c7..a954edde63ede 100644 --- a/hermes_cli/codex_models.py +++ b/hermes_cli/codex_models.py @@ -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 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, ...]]] = [ diff --git a/tests/hermes_cli/test_codex_models.py b/tests/hermes_cli/test_codex_models.py index c1e92df755aa1..efb0735f7c5ba 100644 --- a/tests/hermes_cli/test_codex_models.py +++ b/tests/hermes_cli/test_codex_models.py @@ -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",