fix(cli): sync credential_pool on Codex re-auth - #33074
Closed
konsisumer wants to merge 1 commit into
Closed
Conversation
Codex re-auth via `hermes setup` / `hermes model` wrote fresh OAuth tokens to providers.openai-codex.tokens but left the credential_pool device_code entry holding the consumed refresh token and stale error markers. Since the runtime selects from the pool, the next request spent a dead token and got a 401 token_invalidated. Update the singleton-seeded pool entries in lockstep and clear their error state. Fixes NousResearch#33000
Contributor
|
Salvaged onto current main via #33164 (merged as 2bbd534). Your authorship is preserved in |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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?
Codex re-authentication via
hermes setup/hermes modelwrote the fresh OAuth pair toproviders.openai-codex.tokensbut never updatedcredential_pool.openai-codex. Because the runtime selects credentials from the pool (not from the provider singleton), the pool'sdevice_codeentry kept holding the now-consumed refresh token plus the stalelast_error_*/last_statusmarkers from the prior invalidation. The next request spent a dead token and got an immediate401 token_invalidatedfrom OpenAI.This makes
_save_codex_tokensupdate the singleton-seeded pool entries in lockstep with the provider tokens — within the same_auth_store_lock, so the write is atomic — and clears the entry's error state. Manual (manual:*) pool entries are independent credentials and are deliberately left untouched, matching the existing_sync_device_code_entry_to_auth_storeconvention.Scope note: the linked issue also reports a secondary
agent/codex_runtime.pybug (anulloutputfield crashingparse_response). That is an unrelated change in a different module, so it is intentionally out of scope here and the issue is referenced withRefsrather than auto-closed.Related Issue
Refs #33000
Type of Change
Changes Made
hermes_cli/auth.py: add_sync_codex_pool_entries()and call it from_save_codex_tokens()so re-auth updates thedevice_codecredential_pool.openai-codexentries (access/refresh token,last_refresh) and clearslast_status/last_error_*markers, atomically under_auth_store_lock.tests/hermes_cli/test_auth_codex_provider.py: addtest_save_codex_tokens_syncs_credential_poolcovering the device_code entry sync, error-marker clearing, and that manual entries are left untouched.How to Test
openai-codexprovider, then re-auth viahermes setup/hermes model(e.g. after a token invalidation).~/.hermes/auth.json:credential_pool.openai-codex[0]now carries the sameaccess_token/refresh_tokenasproviders.openai-codex.tokens, and itslast_error_*/last_statusfields are cleared.401 token_invalidated.pytest tests/hermes_cli/test_auth_codex_provider.py -q(17 passing, including the new regression test).Verified locally on macOS (darwin-arm64) with the repo venv;
ruff checkclean on the changed files andscripts/check-windows-footguns.pyclean (the change is pure dict manipulation — no process, path, signal, or subprocess surface).What platforms tested on
pytest tests/hermes_cli/test_auth_codex_provider.py(17 passed), plustests/agent/test_credential_pool.pyandtests/hermes_cli/test_auth_commands.py(116 passed) with no regressions.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/hermes_cli/test_auth_codex_provider.py -q) and all 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/A