- claude_settings: 目标文件改为全局 ~/.claude/settings.json,与 cc-switch 行为一致 - claude_settings: 切回 claude 时保留用户已有的 ANTHROPIC_API_KEY - backend: 修正 save_project_settings -> save_settings,提示文本同步 - test_backends: 清理未用 import - test_entrypoints: 新增 backend 命令注册测试 - 新增 test_claude_settings / test_secrets / test_backend_command(共 36 tests)
140 lines
5.6 KiB
Python
140 lines
5.6 KiB
Python
"""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)"
|