diff --git a/plugins/memory/honcho/cli.py b/plugins/memory/honcho/cli.py index 5c829a4c98..9581df17eb 100644 --- a/plugins/memory/honcho/cli.py +++ b/plugins/memory/honcho/cli.py @@ -273,9 +273,19 @@ def _write_config(cfg: dict, path: Path | None = None) -> None: def _resolve_api_key(cfg: dict) -> str: - """Resolve API key with host -> root -> env fallback.""" + """Resolve API key with host -> root -> env fallback. + + For self-hosted instances configured with ``baseUrl`` instead of an API + key, returns ``"local"`` so that credential guards throughout the CLI + don't reject a valid configuration. + """ host_key = ((cfg.get("hosts") or {}).get(_host_key()) or {}).get("apiKey") - return host_key or cfg.get("apiKey", "") or os.environ.get("HONCHO_API_KEY", "") + key = host_key or cfg.get("apiKey", "") or os.environ.get("HONCHO_API_KEY", "") + if not key: + base_url = cfg.get("baseUrl") or cfg.get("base_url") or os.environ.get("HONCHO_BASE_URL", "") + if base_url.strip(): + return "local" + return key def _prompt(label: str, default: str | None = None, secret: bool = False) -> str: diff --git a/tests/honcho_plugin/test_cli.py b/tests/honcho_plugin/test_cli.py index a6fc39ea7c..70b015d181 100644 --- a/tests/honcho_plugin/test_cli.py +++ b/tests/honcho_plugin/test_cli.py @@ -3,6 +3,45 @@ from types import SimpleNamespace +class TestResolveApiKey: + """Test _resolve_api_key with various config shapes.""" + + def test_returns_api_key_from_root(self, monkeypatch): + import plugins.memory.honcho.cli as honcho_cli + monkeypatch.setattr(honcho_cli, "_host_key", lambda: "hermes") + monkeypatch.delenv("HONCHO_API_KEY", raising=False) + assert honcho_cli._resolve_api_key({"apiKey": "root-key"}) == "root-key" + + def test_returns_api_key_from_host_block(self, monkeypatch): + import plugins.memory.honcho.cli as honcho_cli + monkeypatch.setattr(honcho_cli, "_host_key", lambda: "hermes") + monkeypatch.delenv("HONCHO_API_KEY", raising=False) + cfg = {"hosts": {"hermes": {"apiKey": "host-key"}}, "apiKey": "root-key"} + assert honcho_cli._resolve_api_key(cfg) == "host-key" + + def test_returns_local_for_base_url_without_api_key(self, monkeypatch): + import plugins.memory.honcho.cli as honcho_cli + monkeypatch.setattr(honcho_cli, "_host_key", lambda: "hermes") + monkeypatch.delenv("HONCHO_API_KEY", raising=False) + monkeypatch.delenv("HONCHO_BASE_URL", raising=False) + cfg = {"baseUrl": "http://localhost:8000"} + assert honcho_cli._resolve_api_key(cfg) == "local" + + def test_returns_local_for_base_url_env_var(self, monkeypatch): + import plugins.memory.honcho.cli as honcho_cli + monkeypatch.setattr(honcho_cli, "_host_key", lambda: "hermes") + monkeypatch.delenv("HONCHO_API_KEY", raising=False) + monkeypatch.setenv("HONCHO_BASE_URL", "http://10.0.0.5:8000") + assert honcho_cli._resolve_api_key({}) == "local" + + def test_returns_empty_when_nothing_configured(self, monkeypatch): + import plugins.memory.honcho.cli as honcho_cli + monkeypatch.setattr(honcho_cli, "_host_key", lambda: "hermes") + monkeypatch.delenv("HONCHO_API_KEY", raising=False) + monkeypatch.delenv("HONCHO_BASE_URL", raising=False) + assert honcho_cli._resolve_api_key({}) == "" + + class TestCmdStatus: def test_reports_connection_failure_when_session_setup_fails(self, monkeypatch, capsys, tmp_path): import plugins.memory.honcho.cli as honcho_cli