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:
- The hermes credential pool (
~/.hermes/profiles/<profile>/credential_pool/)
- 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
- Add to
config.yaml:
providers:
openai-codex:
api_key: <valid-oauth-token>
- Open Settings → Providers
- The "OpenAI Codex" card has no "Configured" badge and shows "Not configured"
- 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.
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 upopenai-codexviaconfig.yamland 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()inapi/providers.py(line ~272) handles OAuth providers with a hard override:_provider_has_key()runs first (line 268) and correctly checksconfig.yaml → providers.openai-codex.api_key. But for OAuth providers, its result is unconditionally discarded and replaced by theget_auth_status()result.get_auth_status("openai-codex")inhermes_cli/auth.pychecks two places:~/.hermes/profiles/<profile>/credential_pool/)~/.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 incredential_pool.pyexplains: "We do NOT auto-import from~/.codex/auth.jsonat 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_keyisFalsein any of these valid, working configurations:providers.openai-codex.api_keyset inconfig.yamlhermes authdone, but Codex CLI later consumed the refresh tokenhermes authdone successfullySteps to reproduce
config.yaml:openai-codexas the active provider works fineWhat 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 returnedTrue(e.g. token inconfig.yaml), that result should survive even whenget_auth_status()sayslogged_in=False:2. Show a useful status in the OAuth card body when
logged_in=Truebut 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
errorfield fromget_auth_status()in the Settings card (panels.js)get_auth_status("openai-codex")returns a descriptiveerrorstring when auth fails: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.pyline ~268–284 —get_providers()OAuth override blockstatic/panels.jsline ~2563 —_buildProviderCard()OAuth card renderingstatic/panels.jsline ~2586 — configured badge conditional (p.has_key)Impact
All users who configure OAuth providers (
openai-codex,nous,copilot) viaconfig.yamlrather thanhermes 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.