From bd767b574be4c65036d2bef2e74b189704d39cad Mon Sep 17 00:00:00 2001 From: Kshitij Kapoor Date: Thu, 9 Jul 2026 23:13:51 +0530 Subject: [PATCH] =?UTF-8?q?feat(openai):=20complete=20gpt-5.6=20registrati?= =?UTF-8?q?on=20=E2=80=94=20context,=20codex=20catalog,=20native=20picker,?= =?UTF-8?q?=20pricing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #61578 added the GPT-5.6 series (sol/terra/luna) to the two aggregator surfaces (OPENROUTER_MODELS, _PROVIDER_MODELS[nous]). This completes the registration on the remaining surfaces per the standard add-model checklist: - agent/model_metadata.py: DEFAULT_CONTEXT_LENGTHS 1.05M (direct API, same as gpt-5.5; more-specific keys precede gpt-5.5 for longest-substring matching) + _CODEX_OAUTH_CONTEXT_FALLBACK 272K for all three slugs. Without these the direct-API fallback matched generic "gpt-5" = 400K. - hermes_cli/codex_models.py: DEFAULT_CODEX_MODELS + forward-compat templates so ChatGPT-OAuth (openai-codex) pickers surface the series. - hermes_cli/models.py: _PROVIDER_MODELS[openai-api] (native API picker). - agent/usage_pricing.py: _OFFICIAL_DOCS_PRICING snapshot — sol 5/30, terra 2.50/15, luna 1/6 per 1M in/out; cache read 0.10x input, cache write 1.25x input (OpenAI billing change starting with the 5.6 series). GA 2026-07-09 at preview rates. Sol Fast mode (Cerebras tier) excluded. - hermes_cli/model_switch.py: rank "sol" as a flagship suffix so /model gpt resolves to gpt-5.6-sol, not alphabetical-first luna. Verified: registry E2E via real imports (both context tables, codex forward-compat from a gpt-5.5 template, billing-route lookup for openai/gpt-5.6-sol -> 5.00/M), alias resolution on openai-codex and openai-api resolves to gpt-5.6-sol; 183 targeted tests pass (model_metadata, usage_pricing, codex_models, model_catalog). --- agent/model_metadata.py | 9 ++++++++ agent/usage_pricing.py | 44 ++++++++++++++++++++++++++++++++++++++ hermes_cli/codex_models.py | 7 ++++++ hermes_cli/model_switch.py | 5 ++++- hermes_cli/models.py | 3 +++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/agent/model_metadata.py b/agent/model_metadata.py index 3e966899b9c..ada9cd15536 100644 --- a/agent/model_metadata.py +++ b/agent/model_metadata.py @@ -229,6 +229,12 @@ DEFAULT_CONTEXT_LENGTHS = { # ChatGPT Codex OAuth caps it at 272K; both paths resolve via their own # provider-aware branches (_resolve_codex_oauth_context_length + models.dev). # This hardcoded value is only reached when every probe misses. + # GPT-5.6 series (Sol/Terra/Luna, GA 2026-07-09) — 1.05M on the direct + # OpenAI API (same as gpt-5.5). Codex OAuth caps these at 272K. + # More-specific keys precede "gpt-5.5" for longest-substring matching. + "gpt-5.6-luna": 1050000, + "gpt-5.6-terra": 1050000, + "gpt-5.6-sol": 1050000, "gpt-5.5": 1050000, "gpt-5.4-nano": 400000, # 400k (not 1.05M like full 5.4) "gpt-5.4-mini": 400000, # 400k (not 1.05M like full 5.4) @@ -1837,6 +1843,9 @@ _CODEX_OAUTH_CONTEXT_FALLBACK: Dict[str, int] = { "gpt-5.3-codex-spark": 128_000, "gpt-5.2-codex": 272_000, "gpt-5.4-mini": 272_000, + "gpt-5.6-sol": 272_000, + "gpt-5.6-terra": 272_000, + "gpt-5.6-luna": 272_000, "gpt-5.5": 272_000, "gpt-5.4": 272_000, "gpt-5.2": 272_000, diff --git a/agent/usage_pricing.py b/agent/usage_pricing.py index d7b56a9fac4..112ab21be71 100644 --- a/agent/usage_pricing.py +++ b/agent/usage_pricing.py @@ -103,6 +103,50 @@ _UTC_NOW = lambda: datetime.now(timezone.utc) # Official docs snapshot entries. Models whose published pricing and cache # semantics are stable enough to encode exactly. _OFFICIAL_DOCS_PRICING: Dict[tuple[str, str], PricingEntry] = { + # ── OpenAI GPT-5.6 series (Sol/Terra/Luna) ─────────────────────────── + # Announced in limited preview 2026-06-26; GA 2026-07-09 at the same + # rates (Sol $5/$30, Terra $2.50/$15, Luna $1/$6 per 1M in/out). Cache + # writes are billed at 1.25x the uncached input rate; cache reads get the + # standard 90% discount (0.10x input, confirmed: Sol $0.50/M cached). + # Note: "Sol Fast mode" ($12.5/$75, up to 750 tok/s via Cerebras) is a + # separate serving tier, not covered by these entries. + # Source: https://openai.com/index/previewing-gpt-5-6-sol/ + ( + "openai", + "gpt-5.6-sol", + ): PricingEntry( + input_cost_per_million=Decimal("5.00"), + output_cost_per_million=Decimal("30.00"), + cache_read_cost_per_million=Decimal("0.50"), + cache_write_cost_per_million=Decimal("6.25"), + source="official_docs_snapshot", + source_url="https://openai.com/index/previewing-gpt-5-6-sol/", + pricing_version="openai-gpt-5.6-preview-2026-07", + ), + ( + "openai", + "gpt-5.6-terra", + ): PricingEntry( + input_cost_per_million=Decimal("2.50"), + output_cost_per_million=Decimal("15.00"), + cache_read_cost_per_million=Decimal("0.25"), + cache_write_cost_per_million=Decimal("3.125"), + source="official_docs_snapshot", + source_url="https://openai.com/index/previewing-gpt-5-6-sol/", + pricing_version="openai-gpt-5.6-preview-2026-07", + ), + ( + "openai", + "gpt-5.6-luna", + ): PricingEntry( + input_cost_per_million=Decimal("1.00"), + output_cost_per_million=Decimal("6.00"), + cache_read_cost_per_million=Decimal("0.10"), + cache_write_cost_per_million=Decimal("1.25"), + source="official_docs_snapshot", + source_url="https://openai.com/index/previewing-gpt-5-6-sol/", + pricing_version="openai-gpt-5.6-preview-2026-07", + ), # ── Anthropic Claude 4.8 ───────────────────────────────────────────── # Same $5/$25 base pricing as 4.6/4.7. Fast-mode variant is a separate # model ID with 2x premium (vs the 6x premium on older Opus generations). diff --git a/hermes_cli/codex_models.py b/hermes_cli/codex_models.py index 768e68bee38..bd7b2d78e8b 100644 --- a/hermes_cli/codex_models.py +++ b/hermes_cli/codex_models.py @@ -12,6 +12,10 @@ 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-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", "gpt-5.5", "gpt-5.4-mini", "gpt-5.4", @@ -44,6 +48,9 @@ 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-terra", ("gpt-5.5", "gpt-5.4")), + ("gpt-5.6-luna", ("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/model_switch.py b/hermes_cli/model_switch.py index 5d9ecfd2050..2767b088a7d 100644 --- a/hermes_cli/model_switch.py +++ b/hermes_cli/model_switch.py @@ -548,7 +548,10 @@ def _model_sort_key(model_id: str, prefix: str) -> tuple: # Suffix quality ranking: pro/max > (no suffix) > omni/flash/mini/lite # Lower number = preferred - _SUFFIX_RANK = {"pro": 0, "max": 0, "plus": 0, "turbo": 0} + # "sol" is the flagship tier of the GPT-5.6 series (sol > terra > luna); + # without it, alias resolution would tiebreak alphabetically and pick + # luna (the cheapest) for `/model gpt`. + _SUFFIX_RANK = {"pro": 0, "max": 0, "plus": 0, "turbo": 0, "sol": 0} suffix_rank = _SUFFIX_RANK.get(suffix, 1) return version_key + (suffix_rank, suffix) diff --git a/hermes_cli/models.py b/hermes_cli/models.py index bcde00c47b4..af2aba931dc 100644 --- a/hermes_cli/models.py +++ b/hermes_cli/models.py @@ -239,6 +239,9 @@ _PROVIDER_MODELS: dict[str, list[str]] = { "gpt-4o-mini", ], "openai-api": [ + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", "gpt-5.5", "gpt-5.5-pro", "gpt-5.4",