From cae5ed447874ea15050c4874265005fbefa3253a Mon Sep 17 00:00:00 2001 From: ciregenz Date: Thu, 2 Jul 2026 16:34:57 -0700 Subject: [PATCH] [eric] models: re-add Claude Fable 5 (cc sub + api-key rows; ban lifted, access confirmed by eric) --- backend/apps/agents/providers/registry.py | 7 ++++++- backend/tests/test_v2_invariants.py | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/backend/apps/agents/providers/registry.py b/backend/apps/agents/providers/registry.py index 5279c1ea..407b8e1d 100644 --- a/backend/apps/agents/providers/registry.py +++ b/backend/apps/agents/providers/registry.py @@ -65,7 +65,11 @@ BUILTIN_MODELS: dict[str, list[dict[str, Any]]] = { {"value": "haiku-cc", "label": "Claude Haiku 4.5", "context_window": 200_000, "model_id": "claude-haiku-4-5", "router_model_id": "cc/claude-haiku-4-5-20251001", "api": "anthropic", "reasoning": True, "route": "cc"}, - # Fable 5 pulled: the model got banned, so both its cc/ sub and api-key rows are gone. Don't re-add without confirming access is restored. + # Fable 5 re-added 2026-07-02 after the ban lifted (Eric confirmed access is back); pull both rows again if it errors live. + {"value": "fable-5-cc", "label": "Claude Fable 5", "context_window": 1_000_000, + "model_id": "claude-fable-5", "router_model_id": "cc/claude-fable-5", "api": "anthropic", "reasoning": True, "route": "cc"}, + {"value": "fable-5-api", "label": "Claude Fable 5 (API key)", "context_window": 1_000_000, + "model_id": "claude-fable-5", "router_model_id": "claude-fable-5", "api": "anthropic", "reasoning": True, "route": "api"}, {"value": "opus-4-8-api", "label": "Claude Opus 4.8 (API key)", "context_window": 1_000_000, "model_id": "claude-opus-4-8", "router_model_id": "claude-opus-4-8", "api": "anthropic", "reasoning": True, "route": "api"}, {"value": "opus-4-7-api", "label": "Claude Opus 4.7 (API key)", "context_window": 1_000_000, @@ -371,6 +375,7 @@ COST_PER_1M_TOKENS: dict[tuple[str, str], tuple[float, float]] = { ("Anthropic", "opus"): (5.0, 25.0), ("Anthropic", "opus-4-7"): (5.0, 25.0), ("Anthropic", "opus-4-8"): (5.0, 25.0), + ("Anthropic", "fable-5-api"): (10.0, 50.0), ("Anthropic", "haiku"): (1.0, 5.0), # OpenAI; Codex subscription path, user pays nothing per token ("OpenAI", "gpt-5.5"): (0.0, 0.0), diff --git a/backend/tests/test_v2_invariants.py b/backend/tests/test_v2_invariants.py index 7425ba92..2c4abd9b 100644 --- a/backend/tests/test_v2_invariants.py +++ b/backend/tests/test_v2_invariants.py @@ -663,16 +663,16 @@ def test_dashboard_get_strips_only_orphan_session_cards(): def test_banned_models_not_offered(): - """Claude Fable (banned) and Gemini 3.1 Pro (no working lane: AG can't serve - it, AI Studio key 429s pro-preview) were pulled from the picker. Guard so a - refactor can't silently re-list a model that can't run.""" + """Gemini 3.1 Pro (no working lane: AG can't serve it, AI Studio key 429s + pro-preview) stays pulled from the picker. Guard so a refactor can't + silently re-list a model that can't run. (Fable 5 was re-listed 2026-07-02 + after its ban lifted, so it left this list.)""" from backend.apps.agents.providers.registry import BUILTIN_MODELS all_values = {m["value"] for models in BUILTIN_MODELS.values() for m in models} - for dead in ("fable-5-cc", "fable-5-api", "gemini-3.1-pro", "gemini-3.1-pro-api"): + for dead in ("gemini-3.1-pro", "gemini-3.1-pro-api"): assert dead not in all_values, f"{dead} is back in the picker" - # No 'fable' or '3.1 pro' label survives in any provider group either. + # No '3.1 pro' label survives in any provider group either. all_labels = " | ".join(m["label"].lower() for models in BUILTIN_MODELS.values() for m in models) - assert "fable" not in all_labels assert "3.1 pro" not in all_labels