From e8955f222cecb6ed7ac3f0c541b9b5b02d22843f Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 27 May 2026 12:16:15 -0700 Subject: [PATCH] fix(codex): drop dead model slugs that HTTP 400 on ChatGPT Pro (#33424) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEFAULT_CODEX_MODELS shipped three slugs that the chatgpt.com Codex backend rejects with HTTP 400 'The model is not supported when using Codex with a ChatGPT account.' on every account tested live: gpt-5.2-codex gpt-5.1-codex-max gpt-5.1-codex-mini Live verified against https://chatgpt.com/backend-api/codex/models which returns gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.3-codex, gpt-5.3-codex-spark, gpt-5.2 for ChatGPT Pro accounts. When _fetch_models_from_api fell back to DEFAULT_CODEX_MODELS (offline first-run, transient API failure) the picker surfaced these dead slugs and crashed on selection. The forward-compat synthesis table chained them downstream too. If OpenAI re-enables them on the OAuth-backed Codex backend, live discovery will pick them up automatically — the defaults list is only consulted when live discovery is unavailable. Test fixture pivoted to use gpt-5.3-codex (templated by 4 entries) as the synthesis driver so the forward-compat test still exercises the synthesis path. --- hermes_cli/codex_models.py | 22 +++++++++++++++------- tests/hermes_cli/test_codex_models.py | 9 ++++++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/hermes_cli/codex_models.py b/hermes_cli/codex_models.py index e45ba33f8eb..768e68bee38 100644 --- a/hermes_cli/codex_models.py +++ b/hermes_cli/codex_models.py @@ -29,21 +29,29 @@ DEFAULT_CODEX_MODELS: List[str] = [ # 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", + # NOTE: gpt-5.2-codex / gpt-5.1-codex-max / gpt-5.1-codex-mini were + # previously listed here but the chatgpt.com Codex backend returns + # HTTP 400 "The '' model is not supported when using Codex with + # a ChatGPT account." for all three on every ChatGPT Pro account we've + # tested (verified live 2026-05-27). Keeping them in the fallback list + # leaked dead slugs into /model when live discovery was unavailable + # (transient API failure, first-run before refresh) and surfaced HTTP 400 + # crashes on selection. The Codex CLI public catalog still references + # these slugs, which is why they survived previously — but those entries + # describe the public OpenAI API, not the OAuth-backed Codex backend + # Hermes uses. Removed here. If OpenAI re-enables them on Codex backend, + # live discovery will pick them up automatically via _fetch_models_from_api. ] _FORWARD_COMPAT_TEMPLATE_MODELS: List[tuple[str, tuple[str, ...]]] = [ ("gpt-5.5", ("gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex")), - ("gpt-5.4-mini", ("gpt-5.3-codex", "gpt-5.2-codex")), - ("gpt-5.4", ("gpt-5.3-codex", "gpt-5.2-codex")), - ("gpt-5.3-codex", ("gpt-5.2-codex",)), + ("gpt-5.4-mini", ("gpt-5.3-codex",)), + ("gpt-5.4", ("gpt-5.3-codex",)), # Surface Spark whenever any compatible Codex template is present so # accounts hitting the live endpoint with an older lineup still see # Spark in the picker. Backend gates real availability by ChatGPT Pro # entitlement; Hermes does not. - ("gpt-5.3-codex-spark", ("gpt-5.3-codex", "gpt-5.2-codex")), + ("gpt-5.3-codex-spark", ("gpt-5.3-codex",)), ] diff --git a/tests/hermes_cli/test_codex_models.py b/tests/hermes_cli/test_codex_models.py index c1e92df755a..7d8fa81dc91 100644 --- a/tests/hermes_cli/test_codex_models.py +++ b/tests/hermes_cli/test_codex_models.py @@ -60,16 +60,19 @@ def test_get_codex_model_ids_falls_back_to_curated_defaults(tmp_path, monkeypatc def test_get_codex_model_ids_adds_forward_compat_models_from_templates(monkeypatch): monkeypatch.setattr( "hermes_cli.codex_models._fetch_models_from_api", - lambda access_token: ["gpt-5.2-codex"], + lambda access_token: ["gpt-5.3-codex"], ) models = get_codex_model_ids(access_token="codex-access-token") + # When live discovery only returns gpt-5.3-codex, forward-compat synthesis + # should surface gpt-5.5, gpt-5.4, gpt-5.4-mini, and gpt-5.3-codex-spark + # (each is templated off gpt-5.3-codex). assert models == [ - "gpt-5.2-codex", + "gpt-5.3-codex", + "gpt-5.5", "gpt-5.4-mini", "gpt-5.4", - "gpt-5.3-codex", "gpt-5.3-codex-spark", ]