From 0f70af2f31c17d623ecedf35f2ea258a1ecccf92 Mon Sep 17 00:00:00 2001 From: Yijia-Xiao Date: Sun, 5 Jul 2026 14:29:07 +0000 Subject: [PATCH] feat(llm): add Claude Sonnet 5 and Fable 5 to the catalog - refresh the Anthropic lineup to the current GA set (Fable 5, Opus 4.8, Sonnet 5, Opus 4.7, Haiku 4.5) - extend the effort gate to single-number Claude 5 IDs (claude-sonnet-5, claude-fable-5) so their effort setting is honored --- tests/test_anthropic_effort.py | 10 ++++++++++ tests/test_temperature_config.py | 7 +++++-- tradingagents/llm_clients/anthropic_client.py | 19 +++++++++++-------- tradingagents/llm_clients/model_catalog.py | 8 ++++---- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/tests/test_anthropic_effort.py b/tests/test_anthropic_effort.py index 7c4b1e5bf..04db66d4c 100644 --- a/tests/test_anthropic_effort.py +++ b/tests/test_anthropic_effort.py @@ -57,6 +57,16 @@ class TestEffortGate: mod.AnthropicClient(model=model, effort="low", api_key="x").get_llm() assert captured["kwargs"]["effort"] == "low" + @pytest.mark.parametrize( + "model", + # Claude 5 family uses single-number version IDs; all are effort-capable. + ["claude-sonnet-5", "claude-fable-5", "claude-mythos-5"], + ) + def test_claude_5_family_receives_effort(self, monkeypatch, model): + captured = _capture_kwargs(monkeypatch) + mod.AnthropicClient(model=model, effort="high", api_key="x").get_llm() + assert captured["kwargs"]["effort"] == "high" + def test_mythos_preview_receives_effort(self, monkeypatch): captured = _capture_kwargs(monkeypatch) mod.AnthropicClient( diff --git a/tests/test_temperature_config.py b/tests/test_temperature_config.py index 4266a1618..758f80822 100644 --- a/tests/test_temperature_config.py +++ b/tests/test_temperature_config.py @@ -16,9 +16,12 @@ class TestTemperatureForwarding: @pytest.mark.parametrize( "provider,model", [ + # gpt-4.1 is intentionally a non-reasoning model: the GPT-5 family + # are reasoning models and correctly drop temperature (see + # test_openai_reasoning_effort), so forwarding is tested on gpt-4.1. ("openai", "gpt-4.1"), - ("anthropic", "claude-sonnet-4-6"), - ("google", "gemini-2.5-flash"), + ("anthropic", "claude-sonnet-5"), + ("google", "gemini-3.5-flash"), ("deepseek", "deepseek-chat"), ], ) diff --git a/tradingagents/llm_clients/anthropic_client.py b/tradingagents/llm_clients/anthropic_client.py index 880381e4f..04afee071 100644 --- a/tradingagents/llm_clients/anthropic_client.py +++ b/tradingagents/llm_clients/anthropic_client.py @@ -11,16 +11,17 @@ _PASSTHROUGH_KWARGS = ( "callbacks", "http_client", "http_async_client", "effort", ) -# Anthropic's extended-thinking ``effort`` parameter is accepted by Opus 4.5+ -# and Sonnet 4.6+ only. Sonnet 4.5 and any Haiku version 400 with -# ``"This model does not support the effort parameter"`` (#831). The per-family -# minimum version below is forward-compatible: future ``claude-{opus,sonnet}-X-Y`` -# releases inherit support automatically, while Sonnet 4.5 and Haiku stay excluded. +# Anthropic's extended-thinking ``effort`` parameter is accepted by Opus 4.5+, +# Sonnet 4.6+, and the Claude 5 family (Sonnet 5, Fable 5). Sonnet 4.5 and any +# Haiku version 400 with ``"This model does not support the effort parameter"`` +# (#831). Versions may be dotted (``opus-4-8``) or single-number (``sonnet-5``, +# ``fable-5``); the per-family minimum below is forward-compatible. _EFFORT_EXACT = { "claude-mythos-preview", # non-standard preview name; effort-capable + "claude-mythos-5", # Fable 5 twin (Project Glasswing); effort-capable } -_EFFORT_MODEL = re.compile(r"^claude-(opus|sonnet)-(\d+)-(\d+)$") -_EFFORT_MIN_VERSION = {"opus": (4, 5), "sonnet": (4, 6)} +_EFFORT_MODEL = re.compile(r"^claude-(opus|sonnet|fable)-(\d+)(?:-(\d+))?$") +_EFFORT_MIN_VERSION = {"opus": (4, 5), "sonnet": (4, 6), "fable": (5, 0)} def _supports_effort(model: str) -> bool: @@ -31,7 +32,9 @@ def _supports_effort(model: str) -> bool: match = _EFFORT_MODEL.match(model_lc) if not match: return False - family, major, minor = match.group(1), int(match.group(2)), int(match.group(3)) + family = match.group(1) + major = int(match.group(2)) + minor = int(match.group(3)) if match.group(3) else 0 return (major, minor) >= _EFFORT_MIN_VERSION[family] diff --git a/tradingagents/llm_clients/model_catalog.py b/tradingagents/llm_clients/model_catalog.py index bcec44add..3dd717151 100644 --- a/tradingagents/llm_clients/model_catalog.py +++ b/tradingagents/llm_clients/model_catalog.py @@ -94,14 +94,14 @@ MODEL_OPTIONS: ProviderModeOptions = { }, "anthropic": { "quick": [ - ("Claude Sonnet 4.6 - Best speed and intelligence balance", "claude-sonnet-4-6"), + ("Claude Sonnet 5 - Best speed and intelligence balance", "claude-sonnet-5"), ("Claude Haiku 4.5 - Fastest with near-frontier intelligence", "claude-haiku-4-5"), ], "deep": [ - ("Claude Opus 4.8 - Latest frontier, agentic coding and reasoning", "claude-opus-4-8"), + ("Claude Fable 5 - Most capable, long-running agents", "claude-fable-5"), + ("Claude Opus 4.8 - Frontier agentic coding and reasoning", "claude-opus-4-8"), + ("Claude Sonnet 5 - Near-frontier intelligence at Sonnet cost", "claude-sonnet-5"), ("Claude Opus 4.7 - Previous frontier, long-running agents", "claude-opus-4-7"), - ("Claude Opus 4.6 - Frontier intelligence, agents and coding", "claude-opus-4-6"), - ("Claude Sonnet 4.6 - Best speed and intelligence balance", "claude-sonnet-4-6"), ], }, "google": {