From 42d72b59223dca923f8bbc4c723c54837b282fc8 Mon Sep 17 00:00:00 2001 From: briandevans <252620095+briandevans@users.noreply.github.com> Date: Mon, 4 May 2026 05:13:46 -0700 Subject: [PATCH] fix(status): add missing popular provider API keys to hermes status display Closes #16082. `hermes status` silently omitted four widely-used LLM providers (Google/Gemini, DeepSeek, xAI/Grok, NVIDIA NIM) from the API Keys and API-Key Providers sections. Add them, along with tuple-valued env var support (first found wins) so Google can accept either GOOGLE_API_KEY or GEMINI_API_KEY. Also deduplicates the "NVIDIA" and "NVIDIA NIM" rows that were both pointing at NVIDIA_API_KEY. Salvage of #16159 (core behavior preserved + NVIDIA dedup fixup on top of the tuple-support refactor). Co-authored-by: briandevans <252620095+briandevans@users.noreply.github.com> --- hermes_cli/status.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/hermes_cli/status.py b/hermes_cli/status.py index 3a4219fd4..9a40c8d9b 100644 --- a/hermes_cli/status.py +++ b/hermes_cli/status.py @@ -122,11 +122,16 @@ def show_status(args): print() print(color("◆ API Keys", Colors.CYAN, Colors.BOLD)) - keys = { + # Values may be a single env var name (str) or a tuple of alternates (first found wins). + keys: dict[str, str | tuple[str, ...]] = { "OpenRouter": "OPENROUTER_API_KEY", "OpenAI": "OPENAI_API_KEY", - "NVIDIA": "NVIDIA_API_KEY", - "Z.AI/GLM": "GLM_API_KEY", + "Anthropic": ("ANTHROPIC_API_KEY", "ANTHROPIC_TOKEN"), + "Google / Gemini": ("GOOGLE_API_KEY", "GEMINI_API_KEY"), + "DeepSeek": "DEEPSEEK_API_KEY", + "xAI / Grok": "XAI_API_KEY", + "NVIDIA NIM": "NVIDIA_API_KEY", + "Z.AI / GLM": "GLM_API_KEY", "Kimi": "KIMI_API_KEY", "StepFun Step Plan": "STEPFUN_API_KEY", "MiniMax": "MINIMAX_API_KEY", @@ -140,11 +145,25 @@ def show_status(args): "WandB": "WANDB_API_KEY", "ElevenLabs": "ELEVENLABS_API_KEY", "GitHub": "GITHUB_TOKEN", - "NVIDIA NIM": "NVIDIA_API_KEY", } - for name, env_var in keys.items(): - value = get_env_value(env_var) or "" + def _resolve_env(env_ref) -> str: + """Return first non-empty env var value from a str or tuple of names.""" + if isinstance(env_ref, tuple): + for candidate in env_ref: + v = get_env_value(candidate) or "" + if v: + return v + return "" + return get_env_value(env_ref) or "" + + for name, env_ref in keys.items(): + # Anthropic already has a dedicated lookup below; keep that as the + # single source of truth (it also resolves OAuth tokens), skip here + # so we don't print two "Anthropic" rows. + if name == "Anthropic": + continue + value = _resolve_env(env_ref) has_key = bool(value) display = redact_key(value) if not show_all else value print(f" {name:<12} {check_mark(has_key)} {display}")