"""Tests for myagents.claude_settings.""" import json from pathlib import Path import pytest from myagents import claude_settings as cs_mod from myagents.backends import get_provider @pytest.fixture() def fake_settings_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: path = tmp_path / ".claude" / "settings.json" monkeypatch.setattr(cs_mod, "_settings_path", lambda: path) return path class TestLoadSaveSettings: def test_load_missing_returns_empty(self, fake_settings_path: Path) -> None: assert cs_mod.load_settings() == {} def test_save_and_load_roundtrip(self, fake_settings_path: Path) -> None: cs_mod.save_settings({"effortLevel": "medium"}) assert cs_mod.load_settings()["effortLevel"] == "medium" def test_load_corrupt_returns_empty(self, fake_settings_path: Path) -> None: fake_settings_path.parent.mkdir(parents=True) fake_settings_path.write_text("{not json") assert cs_mod.load_settings() == {} class TestApplyProvider: def test_applies_deepseek_env(self, fake_settings_path: Path) -> None: settings = cs_mod.apply_provider(get_provider("deepseek"), key="sk-test") env = settings["env"] assert env["ANTHROPIC_AUTH_TOKEN"] == "sk-test" assert env["ANTHROPIC_BASE_URL"] == "https://api.deepseek.com/anthropic" assert env["ANTHROPIC_MODEL"] == "deepseek-v4-pro" assert env["ANTHROPIC_DEFAULT_FABLE_MODEL"] == "deepseek-v4-pro" def test_model_override(self, fake_settings_path: Path) -> None: settings = cs_mod.apply_provider( get_provider("kimi"), key="sk-test", model="kimi-k2.5" ) assert settings["env"]["ANTHROPIC_MODEL"] == "kimi-k2.5" def test_base_url_override(self, fake_settings_path: Path) -> None: settings = cs_mod.apply_provider( get_provider("kimi"), key="sk-test", base_url="https://api.moonshot.cn/anthropic" ) assert settings["env"]["ANTHROPIC_BASE_URL"] == "https://api.moonshot.cn/anthropic" def test_preserves_unrelated_env(self, fake_settings_path: Path) -> None: fake_settings_path.parent.mkdir(parents=True) fake_settings_path.write_text( json.dumps({"env": {"DISABLE_AUTOUPDATER": "1", "CUSTOM_VAR": "keep"}}) ) settings = cs_mod.apply_provider(get_provider("deepseek"), key="sk-test") env = settings["env"] assert env["DISABLE_AUTOUPDATER"] == "1" assert env["CUSTOM_VAR"] == "keep" assert env["ANTHROPIC_AUTH_TOKEN"] == "sk-test" def test_removes_stale_managed_vars(self, fake_settings_path: Path) -> None: fake_settings_path.parent.mkdir(parents=True) fake_settings_path.write_text( json.dumps( { "env": { "ANTHROPIC_API_KEY": "old-key", "ANTHROPIC_BASE_URL": "https://old.example.com", "ANTHROPIC_MODEL": "old-model", "ANTHROPIC_DEFAULT_OPUS_MODEL": "old-model", } } ) ) settings = cs_mod.apply_provider(get_provider("kimi"), key="sk-test") env = settings["env"] assert "ANTHROPIC_API_KEY" not in env assert env["ANTHROPIC_BASE_URL"] == "https://api.moonshot.ai/anthropic" assert env["ANTHROPIC_MODEL"] == "kimi-k2.6" def test_claude_provider_clears_third_party_env(self, fake_settings_path: Path) -> None: fake_settings_path.parent.mkdir(parents=True) fake_settings_path.write_text( json.dumps( { "env": { "ANTHROPIC_AUTH_TOKEN": "sk-test", "ANTHROPIC_BASE_URL": "https://api.deepseek.com/anthropic", "ANTHROPIC_MODEL": "deepseek-v4-pro", } } ) ) settings = cs_mod.apply_provider(get_provider("claude")) assert "env" not in settings def test_claude_provider_preserves_user_api_key(self, fake_settings_path: Path) -> None: fake_settings_path.parent.mkdir(parents=True) fake_settings_path.write_text(json.dumps({"env": {"ANTHROPIC_API_KEY": "sk-ant"}})) settings = cs_mod.apply_provider(get_provider("claude")) assert settings["env"]["ANTHROPIC_API_KEY"] == "sk-ant" def test_missing_key_raises(self, fake_settings_path: Path) -> None: with pytest.raises(ValueError, match="API key required"): cs_mod.apply_provider(get_provider("deepseek")) class TestDetectActiveProvider: def test_detects_from_global_env(self, fake_settings_path: Path) -> None: fake_settings_path.parent.mkdir(parents=True) fake_settings_path.write_text( json.dumps({"env": {"ANTHROPIC_BASE_URL": "https://api.kimi.com/coding"}}) ) provider = cs_mod.get_active_provider() assert provider is not None assert provider.id == "kimi-code" class TestDescribeActiveBackend: def test_describes_kimi_code(self, fake_settings_path: Path) -> None: fake_settings_path.parent.mkdir(parents=True) fake_settings_path.write_text( json.dumps( { "env": { "ANTHROPIC_BASE_URL": "https://api.kimi.com/coding", "ANTHROPIC_MODEL": "kimi-for-coding", } } ) ) assert "Kimi Code" in cs_mod.describe_active_backend() def test_describes_default_when_unset(self, fake_settings_path: Path) -> None: assert cs_mod.describe_active_backend() == "Claude (default / not configured)"