[eric] models: GPT-6 Astra on both lanes (gpt-6-astra, 1.05M ctx, $10/$50); the gpt-5 body patch covers gpt-6; the sub-lane row is unverified until ChatGPT is reconnected

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
ciregenz
2026-09-06 15:55:27 -07:00
co-authored by Claude Fable 5.1
parent a6f6fbedd7
commit cca034fce3
7 changed files with 55 additions and 2 deletions
+2 -1
View File
@@ -148,7 +148,8 @@ function isGpt5Model(model) {
for (const p of prefixes) {
if (m.startsWith(p)) { m = m.slice(p.length); break; }
}
return m.startsWith('gpt-5');
// GPT-6 Astra (2026-09-03) keeps every GPT-5 contract this patch exists for: max_completion_tokens, no sampling fields, the reasoning floor.
return m.startsWith('gpt-5') || m.startsWith('gpt-6');
}
// GPT-5 burns 8-30K reasoning tokens before any output; the CLI's default 4096 caps before content lands. Floor at 32K and only raise, never lower.
@@ -21,6 +21,7 @@ p_9router_cache: dict = {"available": None, "checked_at": 0}
# Per-model published pricing in $/1M tokens (input, output) for direct API key lanes. Sourced from each provider's official pricing page as of May 2026. The Claude Agent SDK ALWAYS computes total_cost_usd at Anthropic rates; for any non-Anthropic upstream the SDK number is 50-1000x wrong and we MUST recompute. Used by agent_manager's cost recompute logic.
P_DIRECT_API_PRICING: dict[str, tuple[float, float]] = {
# OpenAI GPT-5.x family (source: platform.openai.com/docs/pricing).
"gpt-6-astra": (10.00, 50.00),
"gpt-5.5": (1.25, 10.00),
"gpt-5.4": (1.25, 10.00),
"gpt-5.4-mini": (0.25, 2.00),
+3
View File
@@ -39,6 +39,9 @@ MODEL_TIERS: dict[str, tuple[int, int, int]] = {
"anthropic/claude-3-haiku": (2, 5, 1),
# OpenAI
"gpt-6-astra": (5, 2, 5),
"openai/gpt-6-astra": (5, 2, 5),
"gpt-6": (5, 2, 5),
"gpt-5.5": (5, 2, 5),
"openai/gpt-5.5": (5, 2, 5),
"gpt-5.5-pro": (5, 1, 5),
+15
View File
@@ -88,6 +88,14 @@ BUILTIN_MODELS: dict[str, list[dict[str, Any]]] = {
],
"OpenAI": [
# GPT-6 Astra (released 2026-09-03; API id gpt-6-astra; 1,050,000 ctx, 128k out; $10/$50 per 1M at short
# context, 2x input and 1.5x output above 272K input). The sub lane rides the same cx translator that
# forwards the 5.6 family to the ChatGPT Responses backend: EXPECTED, NOT VERIFIED on the pinned 0.3.60,
# because the only ChatGPT login on the dev box is dead (ENG-471); verify with one 1-token call once it is
# reconnected, and pull the row if ChatGPT's Codex backend names the model differently.
{"value": "gpt-6", "label": "GPT-6 Astra",
"context_window": 1_050_000, "router_model_id": "cx/gpt-6-astra",
"api": "codex", "subscription_only": True, "reasoning": True},
# Codex sub lanes re-probed 2026-07-26: cx/gpt-5.6-{sol,terra,luna} AND the previously pulled
# cx/gpt-5.5 all return real completions on the pinned 0.3.60 (the old 404 healed upstream;
# the cx translator forwards to the ChatGPT Responses backend, which now serves them).
@@ -115,6 +123,9 @@ BUILTIN_MODELS: dict[str, list[dict[str, Any]]] = {
# cp-openai passthrough, whose scrubs prefix-match "gpt-5" (max_tokens rename, sampling strip,
# and the reasoning_effort-with-tools drop that 5.6 still requires on /chat/completions).
# 1M+ ctx, 128k out; $5/$30 Sol, $2.50/$15 Terra, $1/$6 Luna per 1M.
{"value": "gpt-6-api", "label": "GPT-6 Astra (API key)",
"context_window": 1_050_000, "router_model_id": "cp-openai/gpt-6-astra", "model_id": "gpt-6-astra",
"api": "openai", "reasoning": True, "route": "api"},
{"value": "gpt-5.6-api", "label": "GPT-5.6 Sol (API key)",
"context_window": 1_000_000, "router_model_id": "cp-openai/gpt-5.6-sol", "model_id": "gpt-5.6-sol",
"api": "openai", "reasoning": True, "route": "api"},
@@ -404,11 +415,15 @@ COST_PER_1M_TOKENS: dict[tuple[str, str], tuple[float, float]] = {
("Anthropic", "opus-4-8"): (5.0, 25.0),
("Anthropic", "opus-5"): (5.0, 25.0),
("Anthropic", "haiku"): (1.0, 5.0),
# OpenAI API-key rates. GPT-6 Astra at its SHORT-context rate ($10/$50, 2026-09-03); above 272K input OpenAI
# bills 2x input and 1.5x output, which this flat table cannot express, so a long-context turn is UNDER-estimated here.
("OpenAI", "gpt-6-api"): (10.0, 50.0),
# OpenAI API-key rates (GPT-5.6 tiers, GA 2026-07-09)
("OpenAI", "gpt-5.6-api"): (5.0, 30.0),
("OpenAI", "gpt-5.6-terra-api"): (2.5, 15.0),
("OpenAI", "gpt-5.6-luna-api"): (1.0, 6.0),
# OpenAI; Codex subscription path, user pays nothing per token
("OpenAI", "gpt-6"): (0.0, 0.0),
("OpenAI", "gpt-5.6"): (0.0, 0.0),
("OpenAI", "gpt-5.6-terra"): (0.0, 0.0),
("OpenAI", "gpt-5.6-luna"): (0.0, 0.0),
+25
View File
@@ -0,0 +1,25 @@
"""GPT-6 Astra (2026-09-03): both lanes in the catalog, priced, tiered, and the passthrough rules extended to its prefix."""
from backend.apps.agents.providers.registry import find_builtin_model, BUILTIN_MODELS as PROVIDER_MODELS
def test_gpt6_astra_is_on_both_lanes_with_the_documented_ids():
sub = find_builtin_model("gpt-6")
assert sub and sub["router_model_id"] == "cx/gpt-6-astra" and sub["api"] == "codex" and sub["subscription_only"] is True
api = find_builtin_model("gpt-6-api")
assert api and api["router_model_id"] == "cp-openai/gpt-6-astra" and api["model_id"] == "gpt-6-astra" and api["route"] == "api"
assert sub["context_window"] == api["context_window"] == 1_050_000
def test_gpt6_astra_prices_and_tier():
from backend.apps.agents.providers.registry import COST_PER_1M_TOKENS as MODEL_PRICING
assert MODEL_PRICING[("OpenAI", "gpt-6-api")] == (10.0, 50.0), "the short-context API rate"
assert MODEL_PRICING[("OpenAI", "gpt-6")] == (0.0, 0.0), "the subscription lane bills nothing per token"
from backend.apps.agents.providers.pricing import MODEL_TIERS
assert MODEL_TIERS["gpt-6-astra"] == (5, 2, 5)
from backend.apps.agents.providers.openrouter import P_DIRECT_API_PRICING
assert P_DIRECT_API_PRICING["gpt-6-astra"] == (10.00, 50.00)
def test_gpt6_sits_beside_the_gpt5_family_in_the_openai_list():
values = [m["value"] for m in PROVIDER_MODELS["OpenAI"]]
assert values.index("gpt-6") < values.index("gpt-5.6") and values.index("gpt-6-api") < values.index("gpt-5.6-api")
@@ -72,3 +72,11 @@ def test_the_patch_loads_the_pruner_eagerly_not_lazily() -> None:
src = open("backend/apps/agents/9router_gpt5_patch.js").read()
assert re.search(r"^loadHistoryPrune\(\);", src, re.M), "a lazy load only speaks on the first request; the boot log would stay empty"
assert src.index("loadHistoryPrune();") < src.index("function historyPrune(")
def test_the_gpt5_patch_covers_gpt6():
# GPT-6 Astra needs the same body rewrites on /chat/completions (max_completion_tokens, no sampling, the reasoning floor);
# a prefix rule that stops at gpt-5 would silently 400 every GPT-6 API-key turn.
src = open("backend/apps/agents/9router_gpt5_patch.js").read()
assert "m.startsWith('gpt-5') || m.startsWith('gpt-6')" in src
+1 -1
View File
@@ -203,7 +203,7 @@ const DEFAULT_MODEL_PRIORITY: string[] = [
const DEFAULT_MODEL_PICKS: Record<string, string[]> = {
Anthropic: ['sonnet-5-cc', 'sonnet-5', 'sonnet-5-api', 'opus-5-cc', 'opus-5'],
OpenAI: ['gpt-5.6-terra', 'gpt-5.6', 'gpt-5.6-api', 'gpt-5.5', 'gpt-5.5-api'],
OpenAI: ['gpt-5.6-terra', 'gpt-5.6', 'gpt-5.6-api', 'gpt-5.5', 'gpt-5.5-api', 'gpt-6-api', 'gpt-6'],
Google: ['gemini-3.6-flash-api', 'gemini-3.5-flash-api', 'gemini-3.1-flash-lite'],
'OpenSwarm Pro': ['sonnet', 'opus'],
OpenSwarm: ['gpt-5-mini', 'claude-haiku-4.5', 'gpt-4.1'],