From 4af484d3ddf305427822d42aa8ddbf3cb3b50fe3 Mon Sep 17 00:00:00 2001 From: Kshitij Kapoor Date: Fri, 10 Jul 2026 00:26:28 +0530 Subject: [PATCH] =?UTF-8?q?feat(openai):=20complete=20gpt-5.6=20E2E=20?= =?UTF-8?q?=E2=80=94=20codex=20catalog=20+=20272K=20compaction=20auto-rais?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close the remaining end-to-end gaps so the full gpt-5.6 family (sol/ terra/luna + their -pro high-effort modes, 6 slugs) works on every surface a user can reach them through: - agent/auxiliary_client.py: the Codex OAuth backend hard-caps context at 272K for gpt-5.6 exactly as it does for 5.4/5.5, but the default 50% compaction trigger would summarize at ~136K and waste half the usable window. Extend the existing _is_codex_gpt54_or_gpt55 chokepoint (single enforced predicate feeding _compression_threshold_for_model) to match gpt-5.6* on the openai-codex route so those sessions get the same 0.85 auto-raise. Direct-API/OpenRouter routes (full 1.05M window) are unaffected; the historical codex_gpt55_autoraise opt-out still applies. The one-time notice banner is model-dynamic and already renders the correct slug/cap. - hermes_cli/config.py, agent/agent_init.py: refresh the autoraise comments/notice to mention the 5.6 family. - hermes_cli/codex_models.py: add the -pro variants to DEFAULT_CODEX_MODELS + forward-compat so ChatGPT-OAuth (openai-codex) Pro users see the full family in /model, not just the base tiers. Supersedes the earlier commit's note that 5.6 was intentionally kept out of the codex catalog: the slugs are confirmed routable (OpenRouter live + codex backend), so they belong there like every other codex-capable gpt-5.x slug. E2E verified across all 6 slugs: direct-API ctx 1.05M, codex ctx 272K, pricing reachable from openai + openai-api routes, codex compaction override 0.85 (and None on direct-API + when opted out), present in openai-api picker + codex catalog, /model gpt resolves to sol on both native routes. Guard tests added for the compaction route matrix. --- agent/agent_init.py | 4 +- agent/auxiliary_client.py | 43 +++++++++++------- hermes_cli/codex_models.py | 9 +++- hermes_cli/config.py | 23 +++++----- tests/hermes_cli/test_gpt56_registration.py | 50 +++++++++++++++++++++ 5 files changed, 98 insertions(+), 31 deletions(-) diff --git a/agent/agent_init.py b/agent/agent_init.py index 495260d2188..f1666a1aafb 100644 --- a/agent/agent_init.py +++ b/agent/agent_init.py @@ -77,8 +77,8 @@ def _build_codex_gpt5_autoraise_notice(autoraise: Dict[str, Any]) -> str: include the exact opt-back-out command. """ model = str(autoraise.get("model") or "gpt-5.4/5.5").strip().lower().rsplit("/", 1)[-1] - # gpt-5.3-codex-spark has a native 128K window; the gpt-5.4/5.5 family is - # capped at 272K by the Codex OAuth backend. + # gpt-5.3-codex-spark has a native 128K window; the gpt-5.4/5.5/5.6 family + # is capped at 272K by the Codex OAuth backend. cap = "128K" if model.startswith("gpt-5.3-codex-spark") else "272K" from_pct = int(round(autoraise["from"] * 100)) to_pct = int(round(autoraise["to"] * 100)) diff --git a/agent/auxiliary_client.py b/agent/auxiliary_client.py index d55f7df4fcd..b1d9a8135e6 100644 --- a/agent/auxiliary_client.py +++ b/agent/auxiliary_client.py @@ -314,15 +314,18 @@ def _is_arcee_trinity_thinking(model: Optional[str]) -> bool: return bare == "trinity-large-thinking" -# Context window enforced by ChatGPT's Codex OAuth backend for gpt-5.4/5.5. -# The raw OpenAI API and OpenRouter expose 1.05M for the same slug, but the -# Codex backend hard-caps at 272K (verified live: a ~330K-token request to +# Context window enforced by ChatGPT's Codex OAuth backend for the +# gpt-5.4 / gpt-5.5 / gpt-5.6 families. The raw OpenAI API and OpenRouter +# expose 1.05M for the same slugs, but the Codex backend hard-caps at 272K +# (verified live for 5.4/5.5: a ~330K-token request to # chatgpt.com/backend-api/codex/responses is rejected with -# ``context_length_exceeded`` while ~250K succeeds). With a 272K ceiling the -# default 50% compaction trigger fires at ~136K — wasteful, since the model -# can hold far more raw context before summarization actually buys anything. -# We raise the trigger to 85% (~231K) on this exact route so Codex gpt-5.4/ -# gpt-5.5 sessions use the window they actually have. +# ``context_length_exceeded`` while ~250K succeeds; gpt-5.6 shares the same +# 272K Codex cap — see _CODEX_OAUTH_CONTEXT_FALLBACK in model_metadata.py). +# With a 272K ceiling the default 50% compaction trigger fires at ~136K — +# wasteful, since the model can hold far more raw context before +# summarization actually buys anything. We raise the trigger to 85% (~231K) +# on this exact route so Codex gpt-5.4 / gpt-5.5 / gpt-5.6 sessions use the +# window they actually have. _CODEX_GPT54_GPT55_COMPACTION_THRESHOLD = 0.85 # gpt-5.3-codex-spark is Codex-OAuth-only (ChatGPT Pro entitlement) with a @@ -336,14 +339,16 @@ _CODEX_SPARK_COMPACTION_THRESHOLD = 0.70 def _is_codex_gpt54_or_gpt55(model: Optional[str], provider: Optional[str] = None) -> bool: - """True for gpt-5.4 / gpt-5.5 on the ChatGPT Codex OAuth backend. + """True for gpt-5.4 / gpt-5.5 / gpt-5.6 on the ChatGPT Codex OAuth backend. Matches only the Codex OAuth route (provider ``openai-codex``), not the direct OpenAI API, OpenRouter, or GitHub Copilot paths — those expose a larger context window for the same slug and must keep the user's default - compaction threshold. ``gpt-5.4-pro`` / ``gpt-5.5-pro`` and dated snapshots - are matched via prefix so the override tracks both 272K-capped families - without re-listing every variant. + compaction threshold. ``-pro`` variants and dated snapshots are matched + via prefix so the override tracks every 272K-capped family (5.4, 5.5, + 5.6 sol/terra/luna incl. their ``-pro`` modes) without re-listing every + variant. (Name kept for backward compatibility with the + ``compression.codex_gpt55_autoraise`` config key.) """ prov = (provider or "").strip().lower() if prov != "openai-codex": @@ -356,6 +361,9 @@ def _is_codex_gpt54_or_gpt55(model: Optional[str], provider: Optional[str] = Non or bare == "gpt-5.5" or bare.startswith("gpt-5.5-") or bare.startswith("gpt-5.5.") + or bare == "gpt-5.6" + or bare.startswith("gpt-5.6-") + or bare.startswith("gpt-5.6.") ) @@ -410,11 +418,12 @@ def _compression_threshold_for_model( Per-model/route overrides: - Arcee Trinity Large Thinking → 0.75 (preserve reasoning context). - - gpt-5.4 / gpt-5.5 on the Codex OAuth route → 0.85, because Codex caps - both families at 272K and the default 50% trigger would compact at - ~136K. Gated by ``allow_codex_gpt55_autoraise`` (historical config-key - name kept for backward compatibility) so the user can opt back down to - the global default (the caller passes the config flag through here). + - gpt-5.4 / gpt-5.5 / gpt-5.6 on the Codex OAuth route → 0.85, because + Codex caps all three families at 272K and the default 50% trigger + would compact at ~136K. Gated by ``allow_codex_gpt55_autoraise`` + (historical config-key name kept for backward compatibility) so the + user can opt back down to the global default (the caller passes the + config flag through here). - gpt-5.3-codex-spark on the Codex OAuth route → 0.70, because the model has a native 128K window and the default 50% trigger would compact at ~64K — wasting half the usable context. Not gated by the gpt-5.5 diff --git a/hermes_cli/codex_models.py b/hermes_cli/codex_models.py index bd7b2d78e8b..a56cddf73a2 100644 --- a/hermes_cli/codex_models.py +++ b/hermes_cli/codex_models.py @@ -12,10 +12,14 @@ import os logger = logging.getLogger(__name__) DEFAULT_CODEX_MODELS: List[str] = [ - # GPT-5.6 series (Sol/Terra/Luna) — GA 2026-07-09 (previewed 2026-06-26). + # GPT-5.6 series (Sol/Terra/Luna + -pro high-effort modes) — GA 2026-07-09 + # (previewed 2026-06-26). "gpt-5.6-sol", + "gpt-5.6-sol-pro", "gpt-5.6-terra", + "gpt-5.6-terra-pro", "gpt-5.6-luna", + "gpt-5.6-luna-pro", "gpt-5.5", "gpt-5.4-mini", "gpt-5.4", @@ -49,8 +53,11 @@ DEFAULT_CODEX_MODELS: List[str] = [ _FORWARD_COMPAT_TEMPLATE_MODELS: List[tuple[str, tuple[str, ...]]] = [ ("gpt-5.6-sol", ("gpt-5.5", "gpt-5.4")), + ("gpt-5.6-sol-pro", ("gpt-5.5", "gpt-5.4")), ("gpt-5.6-terra", ("gpt-5.5", "gpt-5.4")), + ("gpt-5.6-terra-pro", ("gpt-5.5", "gpt-5.4")), ("gpt-5.6-luna", ("gpt-5.5", "gpt-5.4")), + ("gpt-5.6-luna-pro", ("gpt-5.5", "gpt-5.4")), ("gpt-5.5", ("gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex")), ("gpt-5.4-mini", ("gpt-5.3-codex",)), ("gpt-5.4", ("gpt-5.3-codex",)), diff --git a/hermes_cli/config.py b/hermes_cli/config.py index 7c83c6f167a..678cdb869af 100644 --- a/hermes_cli/config.py +++ b/hermes_cli/config.py @@ -1423,17 +1423,18 @@ DEFAULT_CONFIG = { # True if you'd rather pause than silently lose # context turns when your aux model is flaky. "codex_gpt55_autoraise": True, # Historical key name kept for compatibility. - # When True, gpt-5.4 / gpt-5.5 on the ChatGPT Codex - # OAuth route raise their compaction trigger to 85% - # (vs the global `threshold` above). Codex hard-caps - # both families at a 272K window, so the default 50% - # would compact at ~136K and waste half the usable - # context. Set to False to opt back down to the global - # threshold (e.g. 0.50) for those Codex sessions. - # Only this exact route is affected — gpt-5.4 / 5.5 - # on OpenAI's direct API, OpenRouter, and Copilot keep - # the global threshold regardless. - "codex_gpt55_autoraise_notice": True, # Display the one-time Codex gpt-5.4/5.5 + # When True, gpt-5.4 / gpt-5.5 / gpt-5.6 on the + # ChatGPT Codex OAuth route raise their compaction + # trigger to 85% (vs the global `threshold` above). + # Codex hard-caps these families at a 272K window, so + # the default 50% would compact at ~136K and waste half + # the usable context. Set to False to opt back down to + # the global threshold (e.g. 0.50) for those Codex + # sessions. Only this exact route is affected — + # gpt-5.4 / 5.5 / 5.6 on OpenAI's direct API, + # OpenRouter, and Copilot keep the global threshold + # regardless. + "codex_gpt55_autoraise_notice": True, # Display the one-time Codex gpt-5.4/5.5/5.6 # autoraise banner. Set False to keep the # 85% threshold autoraise but suppress the # user-facing notice in CLI/gateway output. diff --git a/tests/hermes_cli/test_gpt56_registration.py b/tests/hermes_cli/test_gpt56_registration.py index 9d63992ecaa..5799fa08358 100644 --- a/tests/hermes_cli/test_gpt56_registration.py +++ b/tests/hermes_cli/test_gpt56_registration.py @@ -81,3 +81,53 @@ class TestGpt56PricingRoute: _OFFICIAL_DOCS_PRICING[("openai", f"{base}-pro")] is _OFFICIAL_DOCS_PRICING[("openai", base)] ), base + + +class TestGpt56CodexCompaction: + """Codex OAuth caps the whole gpt-5.6 family at 272K, same as 5.4/5.5, so + the compaction auto-raise (0.85) must fire for every 5.6 variant on the + openai-codex route and NOT on the direct-API/OpenRouter routes.""" + + def test_autoraise_applies_to_all_56_on_codex(self): + from agent.auxiliary_client import _compression_threshold_for_model + + for slug in ( + "gpt-5.6-sol", + "gpt-5.6-sol-pro", + "gpt-5.6-terra", + "gpt-5.6-terra-pro", + "gpt-5.6-luna", + "gpt-5.6-luna-pro", + ): + assert ( + _compression_threshold_for_model(slug, provider="openai-codex") + == 0.85 + ), slug + + def test_no_autoraise_on_direct_api_route(self): + from agent.auxiliary_client import _compression_threshold_for_model + + # Direct OpenAI API / OpenRouter expose the full 1.05M window, so the + # 272K-cap override must NOT apply there. + assert ( + _compression_threshold_for_model("gpt-5.6-sol", provider="openai") + is None + ) + assert ( + _compression_threshold_for_model( + "openai/gpt-5.6-sol", provider="openrouter" + ) + is None + ) + + def test_autoraise_respects_opt_out(self): + from agent.auxiliary_client import _compression_threshold_for_model + + assert ( + _compression_threshold_for_model( + "gpt-5.6-sol", + provider="openai-codex", + allow_codex_gpt55_autoraise=False, + ) + is None + )