feat: update model version from claude-sonnet-4-5 to claude-sonnet-4-6 and related adjustments

This commit is contained in:
X-iZhang
2026-05-29 00:40:46 +01:00
parent f75bfcda51
commit 721a03c25b
14 changed files with 78 additions and 58 deletions
+4 -4
View File
@@ -76,7 +76,7 @@ class TestEvoScientistConfig:
assert config.openai_api_key == ""
assert config.tavily_api_key == ""
assert config.provider == "anthropic"
assert config.model == "claude-sonnet-4-5"
assert config.model == "claude-sonnet-4-6"
assert config.default_mode == "daemon"
assert config.default_workdir == ""
assert config.show_thinking is True
@@ -157,7 +157,7 @@ class TestLoadSaveReset:
"""Test that load returns defaults when config file doesn't exist."""
config = load_config()
assert config.provider == "anthropic"
assert config.model == "claude-sonnet-4-5"
assert config.model == "claude-sonnet-4-6"
def test_save_creates_file(self, temp_config_dir, clean_env):
"""Test that save creates the config file."""
@@ -350,8 +350,8 @@ class TestPriorityChain:
"""Test CLI arguments override file config."""
save_config(EvoScientistConfig(model="gpt-4o"))
config = get_effective_config(cli_overrides={"model": "claude-opus-4-5"})
assert config.model == "claude-opus-4-5"
config = get_effective_config(cli_overrides={"model": "claude-opus-4-8"})
assert config.model == "claude-opus-4-8"
def test_env_ui_backend_override(self, temp_config_dir, monkeypatch):
"""UI backend can be selected via environment variable."""
+2 -2
View File
@@ -196,7 +196,7 @@ class TestModelOverride:
with (
_patched_config(
{"model": "claude-opus-4-7", "model_provider": "anthropic"}
{"model": "claude-opus-4-8", "model_provider": "anthropic"}
),
patch(
"EvoScientist.llm.get_chat_model", return_value=new_model
@@ -205,7 +205,7 @@ class TestModelOverride:
result = _run(mw.awrap_model_call(req, handler))
assert result == "ok"
mock_get.assert_called_once_with(model="claude-opus-4-7", provider="anthropic")
mock_get.assert_called_once_with(model="claude-opus-4-8", provider="anthropic")
def test_provider_omitted_passed_as_none(self):
mw = ConfigurableModelMiddleware()
+7 -7
View File
@@ -63,7 +63,7 @@ def test_resolve_context_window_falls_back_when_missing():
def test_patch_table_resolves_known_model_name():
model = SimpleNamespace(model_name="claude-opus-4.7", profile=None)
model = SimpleNamespace(model_name="claude-opus-4.8", profile=None)
assert get_context_window(model) == 1_000_000
@@ -78,7 +78,7 @@ def test_patch_table_strips_provider_prefix():
def test_real_attribute_beats_patch_table():
model = SimpleNamespace(
model_name="claude-opus-4.7",
model_name="claude-opus-4.8",
context_window=500_000,
profile=None,
)
@@ -95,10 +95,10 @@ def test_unknown_model_falls_through_to_fallback():
def test_claude_family_pattern_covers_all_variants():
# Native Anthropic (dash form)
native = SimpleNamespace(model_name="claude-opus-4-7", profile=None)
native = SimpleNamespace(model_name="claude-opus-4-8", profile=None)
# OpenRouter (dot form, with vendor prefix)
openrouter = SimpleNamespace(model_name="anthropic/claude-sonnet-4.6", profile=None)
sonnet = SimpleNamespace(model_name="claude-sonnet-4-5", profile=None)
sonnet = SimpleNamespace(model_name="claude-sonnet-4-6", profile=None)
# Haiku 4.5 is a dict-level exception (200K, not 1M).
haiku = SimpleNamespace(model_name="claude-haiku-4-5", profile=None)
@@ -141,7 +141,7 @@ def test_claude_3x_matches_family_but_upstream_profile_wins_in_practice():
def test_apply_injects_into_empty_profile():
model = SimpleNamespace(model_name="claude-opus-4-7", profile=None)
model = SimpleNamespace(model_name="claude-opus-4-8", profile=None)
apply_known_context_window(model)
@@ -164,7 +164,7 @@ def test_apply_preserves_existing_profile_keys():
def test_apply_does_not_overwrite_existing_max_input_tokens():
model = SimpleNamespace(
model_name="claude-opus-4-7",
model_name="claude-opus-4-8",
profile={"max_input_tokens": 500_000},
)
@@ -185,7 +185,7 @@ def test_apply_handles_non_dict_profile_safely():
# Non-dict profile (e.g. namespace from a future langchain version) must
# not raise — fall back to a fresh dict so deepagents can still read it.
model = SimpleNamespace(
model_name="claude-opus-4-7",
model_name="claude-opus-4-8",
profile=SimpleNamespace(name="opaque object"),
)
+21 -9
View File
@@ -137,7 +137,7 @@ class TestListModels:
class TestGetModelInfo:
def test_returns_tuple_for_valid_model(self):
"""Test that get_model_info returns tuple for valid model."""
result = get_model_info("claude-sonnet-4-5")
result = get_model_info("claude-sonnet-4-6")
assert result is not None
assert isinstance(result, tuple)
assert len(result) == 2
@@ -179,10 +179,10 @@ class TestGetChatModel:
"""Test that get_chat_model resolves short names correctly."""
mock_init.return_value = "mock_model"
get_chat_model("claude-opus-4-5")
get_chat_model("claude-opus-4-8")
call_kwargs = mock_init.call_args[1]
assert call_kwargs["model"] == "claude-opus-4-5"
assert call_kwargs["model"] == "claude-opus-4-8"
assert call_kwargs["model_provider"] == "anthropic"
@patch("EvoScientist.llm.models.init_chat_model")
@@ -213,7 +213,7 @@ class TestGetChatModel:
"""Test that provider can be overridden."""
mock_init.return_value = "mock_model"
get_chat_model("claude-sonnet-4-5", provider="custom_provider")
get_chat_model("claude-sonnet-4-6", provider="custom_provider")
call_kwargs = mock_init.call_args[1]
assert call_kwargs["model_provider"] == "custom_provider"
@@ -403,7 +403,7 @@ class TestThirdPartyRouting:
mock_init.return_value = "mock_model"
monkeypatch.setenv("OPENROUTER_API_KEY", "or-key-456")
get_chat_model("x-ai/grok-4.1-fast", provider="openrouter")
get_chat_model("x-ai/grok-4.3", provider="openrouter")
call_kwargs = mock_init.call_args[1]
assert call_kwargs["model_provider"] == "openrouter"
@@ -417,7 +417,7 @@ class TestThirdPartyRouting:
monkeypatch.setenv("OPENROUTER_API_KEY", "or-key")
get_chat_model(
"x-ai/grok-4.1-fast",
"x-ai/grok-4.3",
provider="openrouter",
reasoning={"effort": "low"},
)
@@ -432,7 +432,7 @@ class TestThirdPartyRouting:
monkeypatch.setenv("OPENROUTER_API_KEY", "or-key")
monkeypatch.setenv("EVOSCIENTIST_REASONING_EFFORT", "medium")
get_chat_model("x-ai/grok-4.1-fast", provider="openrouter")
get_chat_model("x-ai/grok-4.3", provider="openrouter")
call_kwargs = mock_init.call_args[1]
assert call_kwargs["reasoning"] == {"effort": "medium", "summary": "disabled"}
@@ -1176,7 +1176,7 @@ class TestAutoConfig:
mock_init.return_value = "mock_model"
monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
get_chat_model("claude-sonnet-4-5")
get_chat_model("claude-haiku-4-5")
call_kwargs = mock_init.call_args[1]
assert call_kwargs["thinking"] == {"type": "enabled", "budget_tokens": 10000}
@@ -1193,6 +1193,18 @@ class TestAutoConfig:
assert call_kwargs["thinking"] == {"type": "adaptive"}
assert call_kwargs["effort"] == "max"
@patch("EvoScientist.llm.models.init_chat_model")
def test_anthropic_4_8_adaptive_thinking(self, mock_init, monkeypatch):
"""Anthropic 4-8 models get adaptive thinking with max effort."""
mock_init.return_value = "mock_model"
monkeypatch.delenv("ANTHROPIC_BASE_URL", raising=False)
get_chat_model("claude-opus-4-8")
call_kwargs = mock_init.call_args[1]
assert call_kwargs["thinking"] == {"type": "adaptive"}
assert call_kwargs["effort"] == "max"
@patch("EvoScientist.llm.models.init_chat_model")
def test_anthropic_4_6_proxy_no_thinking(self, mock_init, monkeypatch):
"""Anthropic 4-6 models via proxy skip thinking (history round-trip 422)."""
@@ -1213,7 +1225,7 @@ class TestAutoConfig:
monkeypatch.setenv("ANTHROPIC_BASE_URL", "http://127.0.0.1:8000")
monkeypatch.setenv("ANTHROPIC_API_KEY", "ccproxy-oauth")
get_chat_model("claude-sonnet-4-5")
get_chat_model("claude-haiku-4-5")
call_kwargs = mock_init.call_args[1]
assert "thinking" not in call_kwargs
+8 -8
View File
@@ -158,10 +158,10 @@ class TestModelCommandSwitch:
return_value=new_agent,
),
):
_run(cmd.execute(ctx, ["claude-opus-4-6"]))
_run(cmd.execute(ctx, ["claude-opus-4-8"]))
# Config should be updated
assert cfg.model == "claude-opus-4-6"
assert cfg.model == "claude-opus-4-8"
assert cfg.provider == "anthropic"
# Agent should be replaced on context
@@ -170,7 +170,7 @@ class TestModelCommandSwitch:
# Success message shown
ui.append_system.assert_called_once()
msg = ui.append_system.call_args[0][0]
assert "claude-opus-4-6" in msg
assert "claude-opus-4-8" in msg
assert "anthropic" in msg
def test_switch_with_save_flag(self):
@@ -198,10 +198,10 @@ class TestModelCommandSwitch:
),
patch("EvoScientist.config.settings.set_config_value") as mock_save,
):
_run(cmd.execute(ctx, ["claude-opus-4-6", "--save"]))
_run(cmd.execute(ctx, ["claude-opus-4-8", "--save"]))
# Config file should be updated
mock_save.assert_any_call("model", "claude-opus-4-6")
mock_save.assert_any_call("model", "claude-opus-4-8")
mock_save.assert_any_call("provider", "anthropic")
# Success message should mention save
@@ -233,7 +233,7 @@ class TestModelCommandSwitch:
),
patch("EvoScientist.config.settings.set_config_value") as mock_save,
):
_run(cmd.execute(ctx, ["claude-opus-4-6"]))
_run(cmd.execute(ctx, ["claude-opus-4-8"]))
# Config file should NOT be updated
mock_save.assert_not_called()
@@ -273,7 +273,7 @@ class TestModelCommandFailure:
side_effect=RuntimeError("API key missing"),
) as mock_set,
):
_run(cmd.execute(ctx, ["claude-opus-4-6"]))
_run(cmd.execute(ctx, ["claude-opus-4-8"]))
mock_set.assert_called_once()
ui.append_system.assert_called_once()
@@ -558,7 +558,7 @@ class TestModelCommandLoadAgentFailure:
# Pass ``--save`` to strengthen the assertion: if the ordering
# ever regresses, ``set_config_value`` would be called with
# stale data.
_run(cmd.execute(ctx, ["claude-opus-4-6", "--save"]))
_run(cmd.execute(ctx, ["claude-opus-4-8", "--save"]))
# _load_agent was attempted (transactional first step).
mock_load.assert_called_once()
+7 -7
View File
@@ -373,10 +373,10 @@ class TestStepModel:
config = EvoScientistConfig()
with patch("EvoScientist.config.onboard.steps.questionary") as mock_q:
mock_q.select.return_value.ask.return_value = "claude-sonnet-4-5"
mock_q.select.return_value.ask.return_value = "claude-sonnet-4-6"
result = _step_model(config, "anthropic")
assert result == "claude-sonnet-4-5"
assert result == "claude-sonnet-4-6"
def test_raises_keyboard_interrupt_on_cancel(self):
"""Test that _step_model raises KeyboardInterrupt on cancel."""
@@ -1142,7 +1142,7 @@ class TestRunOnboard:
"tui", # UI backend
"anthropic", # Provider
"api_key", # Anthropic auth mode (API key, not OAuth)
"claude-sonnet-4-5", # Model
"claude-sonnet-4-6", # Model
"daemon", # Workspace mode
True, # Show thinking
]
@@ -1168,7 +1168,7 @@ class TestRunOnboard:
# downstream prompts to consume the wrong values.
final_config = mock_save.call_args_list[-1].args[0]
assert final_config.provider == "anthropic"
assert final_config.model == "claude-sonnet-4-5"
assert final_config.model == "claude-sonnet-4-6"
assert final_config.anthropic_auth_mode == "api_key"
assert final_config.ui_backend == "tui"
assert final_config.default_mode == "daemon"
@@ -1217,7 +1217,7 @@ class TestRunOnboard:
"tui", # UI backend
"anthropic", # Provider
"api_key", # Anthropic auth mode
"claude-sonnet-4-5", # Model
"claude-sonnet-4-6", # Model
"daemon", # Workspace mode
True, # Show thinking
]
@@ -1287,7 +1287,7 @@ class TestRunOnboard:
"tui",
"anthropic",
"api_key",
"claude-sonnet-4-5",
"claude-sonnet-4-6",
"daemon",
True,
]
@@ -1334,7 +1334,7 @@ class TestRunOnboard:
"tui",
"anthropic",
"api_key",
"claude-sonnet-4-5",
"claude-sonnet-4-6",
"daemon",
True,
]
+1 -1
View File
@@ -120,7 +120,7 @@ class TestUpdateStatusHook:
def test_no_op(self):
ui, console = _make_ui()
ui.update_status_after_model_change("claude-opus-4-6", "anthropic")
ui.update_status_after_model_change("claude-opus-4-8", "anthropic")
console.print.assert_not_called()
+2 -2
View File
@@ -163,7 +163,7 @@ class TestThreadFunctions(unittest.TestCase):
"agent_name": AGENT_NAME,
"updated_at": f"2025-01-{15 + i}T10:00:00+00:00",
"workspace_dir": f"/tmp/ws_{tid}",
"model": "claude-sonnet-4-5",
"model": "claude-sonnet-4-6",
}
)
await conn.execute(
@@ -272,7 +272,7 @@ class TestThreadFunctions(unittest.TestCase):
meta = _run(get_thread_metadata("abc12345"))
assert meta is not None
assert meta["workspace_dir"] == "/tmp/ws_abc12345"
assert meta["model"] == "claude-sonnet-4-5"
assert meta["model"] == "claude-sonnet-4-6"
def test_get_thread_metadata_missing(self):
meta = _run(get_thread_metadata("nonexist"))