fix: first-run guard stuck in loop when provider configured via config.yaml (#4298)

The _has_any_provider_configured() guard only checked env vars, .env file,
and auth.json — missing config.yaml model.provider/base_url/api_key entirely.
Users who configured a provider through setup (saving to config.yaml) but had
empty API key placeholders in .env from the install template were permanently
blocked by the 'not configured' message.

Changes:
- _has_any_provider_configured() now checks config.yaml model section for
  explicit provider, base_url, or api_key — covers custom endpoints and
  providers that store credentials in config rather than env vars
- .env.example: comment out all empty API key placeholders so they don't
  pollute the environment when copied to .env by the installer
- .env.example: mark LLM_MODEL as deprecated (config.yaml is source of truth)
- 4 new tests for the config.yaml detection path

Reported by OkadoOP on Discord.
This commit is contained in:
Teknium
2026-03-31 11:42:52 -07:00
committed by GitHub
parent 57625329a2
commit 143b74ec00
3 changed files with 110 additions and 21 deletions

View File

@@ -246,6 +246,17 @@ def _has_any_provider_configured() -> bool:
pass
# Check config.yaml — if model is a dict with an explicit provider set,
# the user has gone through setup (fresh installs have model as a plain
# string). Also covers custom endpoints that store api_key/base_url in
# config rather than .env.
if isinstance(model_cfg, dict):
cfg_provider = (model_cfg.get("provider") or "").strip()
cfg_base_url = (model_cfg.get("base_url") or "").strip()
cfg_api_key = (model_cfg.get("api_key") or "").strip()
if cfg_provider or cfg_base_url or cfg_api_key:
return True
# Check for Claude Code OAuth credentials (~/.claude/.credentials.json)
# Only count these if Hermes has been explicitly configured — Claude Code
# being installed doesn't mean the user wants Hermes to use their tokens.