You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Consolidates the competing fixes for #32790 so Codex OAuth quota exhaustion is no longer surfaced as missing credentials. The gateway now uses AuthError.relogin_required to avoid logging transient upstream failures as authentication failures, and pool-only openai-codex credentials that are all in active 429 cooldown now raise the existing Codex rate-limit error instead of codex_auth_missing.
🐛 Bug fix (non-breaking change that fixes an issue)
✨ New feature (non-breaking change that adds functionality)
🔒 Security fix
📝 Documentation update
✅ Tests (adding or improving test coverage)
♻️ Refactor (no behavior change)
🎯 New skill (bundled or hub)
Changes Made
hermes_cli/auth.py: detects the pool-only case where every token-bearing openai-codex credential is in a live 429 cooldown and raises CODEX_RATE_LIMITED_CODE with retry guidance instead of reusing the missing-credentials error.
gateway/run.py: logs non-relogin AuthErrors as transient provider unavailability while preserving auth-failed wording for real credential failures.
tests/hermes_cli/test_auth_codex_provider.py: covers all-429 pool cooldowns, 401 cooldowns, and mixed 429/401 pools.
tests/gateway/test_auth_fallback.py: covers transient-vs-auth gateway log wording and config-provider fallback labels.
/opt/homebrew/bin/timeout -k 30 480 sh -c 'pytest tests/ -q -x --timeout=60 "$@"' sh aborted during collection because local dev deps do not include fastapi for tests/hermes_cli/test_dashboard_auth_401_reauth.py.
Rerunning the broad suite with that file ignored then aborted on the same missing fastapi dependency in tests/hermes_cli/test_dashboard_auth_cookies.py; CI should cover the full suite in the hermetic environment.
Reviewed the full diff across hermes_cli/auth.py, gateway/run.py, and 3 test files.
What I checked:
relogin_required flag discrimination — The gateway now uses getattr(auth_exc, "relogin_required", False) instead of is_rate_limited_auth_error() to classify AuthErrors. This is a cleaner signal: relogin_required=True means credential problem (auth failed), relogin_required=False means transient/quota (provider unavailable). The log messages correctly reflect the distinction. ✅
_pool_codex_rate_limit_remaining() early-return semantics — Returns None (not rate-limited) if ANY pool entry has a non-429 error code or an expired cooldown. This correctly handles mixed pools (429 + 401 = not all-rate-limited → auth remediation). The saw_token guard prevents false negatives on empty pools. ✅
Insertion point in resolve_codex_runtime_credentials — The cooldown check is placed AFTER the singleton check and BEFORE the read_error re-raise. This means: if a singleton token exists, it's used directly (no pool check). If no singleton, the pool is checked for all-429 before falling through to the generic "no credentials" error. ✅
Test coverage — 5 tests covering: all-pool-429 → rate-limit error, 401 pool → auth error, mixed 429+401 → auth error, transient log classification, credential log classification. The tests verify both code and relogin_required fields. ✅
No findings. The PR correctly separates quota exhaustion from credential failure in the Codex provider path, with proper fallback chain behavior.
Rebased onto origin/main and resolved the hermes_cli/auth.py conflict while keeping the PR's Codex pool cooldown behavior intact. ruff check, scripts/check-windows-footguns.py, git diff --check, and the PR-scoped tests (tests/gateway/test_auth_fallback.py, tests/hermes_cli/test_auth_codex_provider.py) passed locally. The bounded full-suite pytest tests/ -q -x --timeout=60 run still stops during collection on the pre-existing missing fastapi dev dependency in tests/hermes_cli/test_dashboard_auth_401_reauth.py.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
comp/cliCLI entry point, hermes_cli/, setup wizardcomp/gatewayGateway runner, session dispatch, deliveryP2Medium — degraded but workaround existsprovider/openaiOpenAI / Codex Responses APItype/bugSomething isn't working
3 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Consolidates the competing fixes for #32790 so Codex OAuth quota exhaustion is no longer surfaced as missing credentials. The gateway now uses
AuthError.relogin_requiredto avoid logging transient upstream failures as authentication failures, and pool-onlyopenai-codexcredentials that are all in active 429 cooldown now raise the existing Codex rate-limit error instead ofcodex_auth_missing.Supersedes
Supersedes #32881, #34325
Related Issue
Fixes #32790
Type of Change
Changes Made
hermes_cli/auth.py: detects the pool-only case where every token-bearingopenai-codexcredential is in a live 429 cooldown and raisesCODEX_RATE_LIMITED_CODEwith retry guidance instead of reusing the missing-credentials error.gateway/run.py: logs non-reloginAuthErrors as transient provider unavailability while preserving auth-failed wording for real credential failures.tests/hermes_cli/test_auth_codex_provider.py: covers all-429 pool cooldowns, 401 cooldowns, and mixed 429/401 pools.tests/gateway/test_auth_fallback.py: covers transient-vs-auth gateway log wording and config-provider fallback labels.How to Test
HERMES_HOME=/private/tmp/pr-consolidate-1d689186-hermes-home /opt/homebrew/bin/timeout -k 30 480 pytest tests/gateway/test_auth_fallback.py tests/hermes_cli/test_auth_codex_provider.py tests/hermes_cli/test_auth_codex_self_heal.py tests/hermes_cli/test_runtime_provider_resolution.py tests/agent/test_credential_pool_routing.py tests/cron/test_codex_execution_paths.py tests/run_agent/test_run_agent_codex_responses.py tests/test_account_usage.py -q --timeout=60(266 passed)/opt/homebrew/bin/timeout -k 30 480 sh -c 'pytest tests/ -q -x --timeout=60 "$@"' shaborted during collection because local dev deps do not includefastapifortests/hermes_cli/test_dashboard_auth_401_reauth.py.fastapidependency intests/hermes_cli/test_dashboard_auth_cookies.py; CI should cover the full suite in the hermetic environment.python scripts/check-windows-footguns.py gateway/run.py hermes_cli/auth.py tests/gateway/test_auth_fallback.py tests/hermes_cli/test_auth_codex_provider.pyruff check gateway/run.py hermes_cli/auth.py tests/gateway/test_auth_fallback.py tests/hermes_cli/test_auth_codex_provider.pygit diff --check main...HEADChecklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AFor New Skills
hermes --toolsets skills -q "Use the X skill to do Y"Screenshots / Logs
N/A