feat: update model version from claude-sonnet-4-5 to claude-sonnet-4-6 and related adjustments
This commit is contained in:
@@ -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."""
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
]
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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"))
|
||||
|
||||
Reference in New Issue
Block a user