mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-21 09:07:40 +02:00
[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:
co-authored by
Claude Fable 5.1
parent
a6f6fbedd7
commit
cca034fce3
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'],
|
||||
|
||||
Reference in New Issue
Block a user