180 lines
6.7 KiB
Python
180 lines
6.7 KiB
Python
"""Tests for Honcho CLI helpers."""
|
|
|
|
import json
|
|
from unittest.mock import patch
|
|
|
|
from honcho_integration.cli import _resolve_api_key, clone_honcho_for_profile, sync_honcho_profiles_quiet
|
|
|
|
|
|
class TestResolveApiKey:
|
|
def test_prefers_host_scoped_key(self):
|
|
cfg = {
|
|
"apiKey": "root-key",
|
|
"hosts": {
|
|
"hermes": {
|
|
"apiKey": "host-key",
|
|
}
|
|
},
|
|
}
|
|
assert _resolve_api_key(cfg) == "host-key"
|
|
|
|
def test_falls_back_to_root_key(self):
|
|
cfg = {
|
|
"apiKey": "root-key",
|
|
"hosts": {"hermes": {}},
|
|
}
|
|
assert _resolve_api_key(cfg) == "root-key"
|
|
|
|
def test_falls_back_to_env_key(self, monkeypatch):
|
|
monkeypatch.setenv("HONCHO_API_KEY", "env-key")
|
|
assert _resolve_api_key({}) == "env-key"
|
|
monkeypatch.delenv("HONCHO_API_KEY", raising=False)
|
|
|
|
|
|
class TestCloneHonchoForProfile:
|
|
def test_clones_default_settings_to_new_profile(self, tmp_path):
|
|
config_file = tmp_path / "config.json"
|
|
config_file.write_text(json.dumps({
|
|
"apiKey": "test-key",
|
|
"hosts": {
|
|
"hermes": {
|
|
"peerName": "alice",
|
|
"memoryMode": "honcho",
|
|
"recallMode": "tools",
|
|
"writeFrequency": "turn",
|
|
"dialecticReasoningLevel": "medium",
|
|
"enabled": True,
|
|
},
|
|
},
|
|
}))
|
|
|
|
with patch("honcho_integration.cli._config_path", return_value=config_file), \
|
|
patch("honcho_integration.cli._local_config_path", return_value=config_file):
|
|
result = clone_honcho_for_profile("coder")
|
|
|
|
assert result is True
|
|
|
|
cfg = json.loads(config_file.read_text())
|
|
new_block = cfg["hosts"]["hermes.coder"]
|
|
assert new_block["peerName"] == "alice"
|
|
assert new_block["memoryMode"] == "honcho"
|
|
assert new_block["recallMode"] == "tools"
|
|
assert new_block["writeFrequency"] == "turn"
|
|
assert new_block["aiPeer"] == "hermes.coder"
|
|
assert new_block["workspace"] == "hermes" # shared, not profile-derived
|
|
assert new_block["enabled"] is True
|
|
|
|
def test_skips_when_no_honcho_configured(self, tmp_path):
|
|
config_file = tmp_path / "config.json"
|
|
config_file.write_text("{}")
|
|
|
|
with patch("honcho_integration.cli._config_path", return_value=config_file), \
|
|
patch("honcho_integration.cli._local_config_path", return_value=config_file):
|
|
result = clone_honcho_for_profile("coder")
|
|
|
|
assert result is False
|
|
|
|
def test_skips_when_host_block_already_exists(self, tmp_path):
|
|
config_file = tmp_path / "config.json"
|
|
config_file.write_text(json.dumps({
|
|
"apiKey": "key",
|
|
"hosts": {
|
|
"hermes": {"peerName": "alice"},
|
|
"hermes.coder": {"peerName": "existing"},
|
|
},
|
|
}))
|
|
|
|
with patch("honcho_integration.cli._config_path", return_value=config_file), \
|
|
patch("honcho_integration.cli._local_config_path", return_value=config_file):
|
|
result = clone_honcho_for_profile("coder")
|
|
|
|
assert result is False
|
|
cfg = json.loads(config_file.read_text())
|
|
assert cfg["hosts"]["hermes.coder"]["peerName"] == "existing"
|
|
|
|
def test_inherits_peer_name_from_root_when_not_in_host(self, tmp_path):
|
|
config_file = tmp_path / "config.json"
|
|
config_file.write_text(json.dumps({
|
|
"apiKey": "key",
|
|
"peerName": "root-alice",
|
|
"hosts": {"hermes": {}},
|
|
}))
|
|
|
|
with patch("honcho_integration.cli._config_path", return_value=config_file), \
|
|
patch("honcho_integration.cli._local_config_path", return_value=config_file):
|
|
clone_honcho_for_profile("dreamer")
|
|
|
|
cfg = json.loads(config_file.read_text())
|
|
assert cfg["hosts"]["hermes.dreamer"]["peerName"] == "root-alice"
|
|
|
|
def test_works_with_api_key_only_no_host_block(self, tmp_path):
|
|
config_file = tmp_path / "config.json"
|
|
config_file.write_text(json.dumps({"apiKey": "key"}))
|
|
|
|
with patch("honcho_integration.cli._config_path", return_value=config_file), \
|
|
patch("honcho_integration.cli._local_config_path", return_value=config_file):
|
|
result = clone_honcho_for_profile("coder")
|
|
|
|
assert result is True
|
|
cfg = json.loads(config_file.read_text())
|
|
assert cfg["hosts"]["hermes.coder"]["aiPeer"] == "hermes.coder"
|
|
assert cfg["hosts"]["hermes.coder"]["workspace"] == "hermes" # shared
|
|
|
|
|
|
class TestSyncHonchoProfilesQuiet:
|
|
def test_syncs_missing_profiles(self, tmp_path):
|
|
config_file = tmp_path / "config.json"
|
|
config_file.write_text(json.dumps({
|
|
"apiKey": "key",
|
|
"hosts": {"hermes": {"peerName": "alice", "memoryMode": "honcho"}},
|
|
}))
|
|
|
|
class FakeProfile:
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.is_default = name == "default"
|
|
|
|
profiles = [FakeProfile("default"), FakeProfile("coder"), FakeProfile("dreamer")]
|
|
|
|
with patch("honcho_integration.cli._config_path", return_value=config_file), \
|
|
patch("honcho_integration.cli._local_config_path", return_value=config_file), \
|
|
patch("hermes_cli.profiles.list_profiles", return_value=profiles):
|
|
count = sync_honcho_profiles_quiet()
|
|
|
|
assert count == 2
|
|
cfg = json.loads(config_file.read_text())
|
|
assert "hermes.coder" in cfg["hosts"]
|
|
assert "hermes.dreamer" in cfg["hosts"]
|
|
|
|
def test_returns_zero_when_no_honcho(self, tmp_path):
|
|
config_file = tmp_path / "config.json"
|
|
config_file.write_text("{}")
|
|
|
|
with patch("honcho_integration.cli._config_path", return_value=config_file), \
|
|
patch("honcho_integration.cli._local_config_path", return_value=config_file):
|
|
count = sync_honcho_profiles_quiet()
|
|
|
|
assert count == 0
|
|
|
|
def test_skips_already_synced(self, tmp_path):
|
|
config_file = tmp_path / "config.json"
|
|
config_file.write_text(json.dumps({
|
|
"apiKey": "key",
|
|
"hosts": {
|
|
"hermes": {"peerName": "alice"},
|
|
"hermes.coder": {"peerName": "existing"},
|
|
},
|
|
}))
|
|
|
|
class FakeProfile:
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.is_default = name == "default"
|
|
|
|
with patch("honcho_integration.cli._config_path", return_value=config_file), \
|
|
patch("hermes_cli.profiles.list_profiles", return_value=[FakeProfile("default"), FakeProfile("coder")]):
|
|
count = sync_honcho_profiles_quiet()
|
|
|
|
assert count == 0
|
|
|