Compare commits

...

1 Commits

Author SHA1 Message Date
yoniebans
d5684f0cdf fix(cli): require explicit setup before treating env keys as configured
A stale OPENAI_API_KEY (or any other provider env var) left over from an
unrelated tool currently makes _has_any_provider_configured() return
True, which skips the Desktop/CLI onboarding flow entirely. The user is
dropped into a broken state with no in-app affordance to recover.

Gate the env-var and .env paths on _has_hermes_config — the same signal
the Claude Code OAuth path already uses below in the same function. Env
vars only count as "configured" once setup has been completed.

Fixes #38471
2026-06-05 11:50:51 +02:00
2 changed files with 49 additions and 2 deletions

View File

@@ -665,12 +665,14 @@ def _has_any_provider_configured() -> bool:
for pconfig in PROVIDER_REGISTRY.values():
if pconfig.auth_type == "api_key":
provider_env_vars.update(pconfig.api_key_env_vars)
if any(os.getenv(v) for v in provider_env_vars):
# Env-detected keys only count once Hermes has been explicitly set up
# — same precedent as the Claude Code path below. See #38471.
if _has_hermes_config and any(os.getenv(v) for v in provider_env_vars):
return True
# Check .env file for keys
env_file = get_env_path()
if env_file.exists():
if _has_hermes_config and env_file.exists():
try:
for line in env_file.read_text(encoding="utf-8").splitlines():
line = line.strip()

View File

@@ -692,22 +692,67 @@ class TestRuntimeProviderResolution:
class TestHasAnyProviderConfigured:
def test_glm_key_counts(self, monkeypatch, tmp_path):
import yaml
from hermes_cli import config as config_module
monkeypatch.setenv("GLM_API_KEY", "test-key")
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
(hermes_home / "config.yaml").write_text(
yaml.dump({"model": {"default": "my-configured-model"}})
)
monkeypatch.setattr(config_module, "get_env_path", lambda: hermes_home / ".env")
monkeypatch.setattr(config_module, "get_hermes_home", lambda: hermes_home)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
from hermes_cli.main import _has_any_provider_configured
assert _has_any_provider_configured() is True
def test_minimax_key_counts(self, monkeypatch, tmp_path):
import yaml
from hermes_cli import config as config_module
monkeypatch.setenv("MINIMAX_API_KEY", "test-key")
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
(hermes_home / "config.yaml").write_text(
yaml.dump({"model": {"default": "my-configured-model"}})
)
monkeypatch.setattr(config_module, "get_env_path", lambda: hermes_home / ".env")
monkeypatch.setattr(config_module, "get_hermes_home", lambda: hermes_home)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
from hermes_cli.main import _has_any_provider_configured
assert _has_any_provider_configured() is True
def test_stale_env_key_without_hermes_config_does_not_skip_onboarding(
self, monkeypatch, tmp_path
):
"""Regression test for #38471."""
from hermes_cli import config as config_module
from hermes_cli.auth import PROVIDER_REGISTRY
monkeypatch.setenv("OPENAI_API_KEY", "sk-stale-key-from-some-other-tool")
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
monkeypatch.setattr(config_module, "get_env_path", lambda: hermes_home / ".env")
monkeypatch.setattr(config_module, "get_hermes_home", lambda: hermes_home)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
monkeypatch.setattr("hermes_cli.copilot_auth.resolve_copilot_token", lambda: ("", ""))
monkeypatch.setattr("hermes_cli.auth.get_auth_status", lambda _pid: {})
monkeypatch.setattr(
"agent.anthropic_adapter.read_claude_code_credentials", lambda: None,
)
from hermes_cli.main import _has_any_provider_configured
assert _has_any_provider_configured() is False
def test_stale_env_key_with_hermes_config_counts(self, monkeypatch, tmp_path):
import yaml
from hermes_cli import config as config_module
monkeypatch.setenv("OPENAI_API_KEY", "sk-user-key-from-onboarding")
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
(hermes_home / "config.yaml").write_text(
yaml.dump({"model": {"default": "anthropic/claude-opus-4.6", "provider": "openrouter"}})
)
monkeypatch.setattr(config_module, "get_env_path", lambda: hermes_home / ".env")
monkeypatch.setattr(config_module, "get_hermes_home", lambda: hermes_home)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
from hermes_cli.main import _has_any_provider_configured
assert _has_any_provider_configured() is True