Skip to content

bug(providers): OAuth provider cards always show Not Configured when auth is via config.yaml or token consumed by native CLI #1202

@nesquena-hermes

Description

@nesquena-hermes

Summary

The Settings → Providers panel shows openai-codex (and other OAuth providers) as "Not configured" even when the provider is fully working. Reported after a user set up openai-codex via config.yaml and found the badge missing.

This is distinct from #1189 (provider group not appearing in the model picker). The group can show up in the picker and the provider can route chats correctly, while Settings still shows "Not configured."

Root cause

get_providers() in api/providers.py (line ~272) handles OAuth providers with a hard override:

if is_oauth:
    key_source = "oauth"
    try:
        from hermes_cli.auth import get_auth_status as _gas
        status = _gas(pid)
        if isinstance(status, dict) and status.get("logged_in"):
            has_key = True
            key_source = status.get("key_source", "oauth")
        else:
            has_key = False   # ← hard override, ignores _provider_has_key() result
    except Exception:
        has_key = False       # ← exception also forces False

_provider_has_key() runs first (line 268) and correctly checks config.yaml → providers.openai-codex.api_key. But for OAuth providers, its result is unconditionally discarded and replaced by the get_auth_status() result.

get_auth_status("openai-codex") in hermes_cli/auth.py checks two places:

  1. The hermes credential pool (~/.hermes/profiles/<profile>/credential_pool/)
  2. The legacy hermes auth store (~/.hermes/auth.json)

It intentionally does not check ~/.codex/auth.json (the native Codex CLI token store) — this is by design to avoid OAuth refresh-token collision. A comment in credential_pool.py explains: "We do NOT auto-import from ~/.codex/auth.json at pool-load time. OAuth refresh tokens are single-use, so sharing them with Codex CLI / VS Code causes refresh_token_reused race failures."

This means has_key is False in any of these valid, working configurations:

Scenario Provider works? Badge shows?
providers.openai-codex.api_key set in config.yaml
hermes auth done, but Codex CLI later consumed the refresh token ✅ (if access token still valid)
hermes auth done successfully

Steps to reproduce

  1. Add to config.yaml:
    providers:
      openai-codex:
        api_key: <valid-oauth-token>
  2. Open Settings → Providers
  3. The "OpenAI Codex" card has no "Configured" badge and shows "Not configured"
  4. Sending a chat using openai-codex as the active provider works fine

What needs to change

Three things, in priority order:

1. Stop discarding _provider_has_key() for OAuth providers (api/providers.py ~line 272)

The get_auth_status() call should augment the check, not replace it. If _provider_has_key() already returned True (e.g. token in config.yaml), that result should survive even when get_auth_status() says logged_in=False:

if is_oauth:
    key_source = "oauth"
    try:
        from hermes_cli.auth import get_auth_status as _gas
        status = _gas(pid)
        if isinstance(status, dict) and status.get("logged_in"):
            has_key = True
            key_source = status.get("key_source", "oauth")
        elif has_key:
            # _provider_has_key() found a token in config.yaml — respect it
            key_source = "config_yaml"
        else:
            has_key = False
    except Exception:
        # Don't override a known-good key just because auth import failed
        pass  # keep has_key from _provider_has_key()

2. Show a useful status in the OAuth card body when logged_in=True but via config.yaml (panels.js ~line 2594)

Currently the OAuth card body only shows a static hint ("managed via CLI"). When key_source == "config_yaml", it should show a note like "Token configured via config.yaml" so users know what they have and how to change it.

3. Surface the error field from get_auth_status() in the Settings card (panels.js)

get_auth_status("openai-codex") returns a descriptive error string when auth fails:

"Codex refresh token was already consumed by another client (e.g. Codex CLI or VS Code extension). Run `codex` in your terminal to generate fresh tokens, then run `hermes auth` to re-authenticate."

This string is currently discarded. It should appear in the provider card body so users know what broke and how to fix it — instead of a silent "Not configured."

Files

  • api/providers.py line ~268–284 — get_providers() OAuth override block
  • static/panels.js line ~2563 — _buildProviderCard() OAuth card rendering
  • static/panels.js line ~2586 — configured badge conditional (p.has_key)

Impact

All users who configure OAuth providers (openai-codex, nous, copilot) via config.yaml rather than hermes auth. Also affects anyone whose Codex refresh token was consumed by the native Codex CLI or VS Code — the provider may still be working (access token not yet expired) but the badge disappears with no explanation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions