fix: write refreshed Codex tokens back to ~/.codex/auth.json (#8277)
OpenAI OAuth refresh tokens are single-use and rotate on every refresh. When Hermes refreshes a Codex token, it consumed the old refresh_token but never wrote the new pair back to ~/.codex/auth.json. This caused Codex CLI and VS Code to fail with 'refresh_token_reused' on their next refresh attempt. This mirrors the existing Anthropic write-back pattern where refreshed tokens are written to ~/.claude/.credentials.json via _write_claude_code_credentials(). Changes: - Add _write_codex_cli_tokens() in hermes_cli/auth.py (parallel to _write_claude_code_credentials in anthropic_adapter.py) - Call it from _refresh_codex_auth_tokens() (non-pool refresh path) - Call it from credential_pool._refresh_entry() (pool happy path + retry) - Add tests for the new write-back behavior - Update existing test docstring to clarify _save_codex_tokens vs _write_codex_cli_tokens separation Fixes refresh token conflict reported by @ec12edfae2cb221
This commit is contained in:
@@ -24,6 +24,7 @@ from hermes_cli.auth import (
|
||||
_codex_access_token_is_expiring,
|
||||
_decode_jwt_claims,
|
||||
_import_codex_cli_tokens,
|
||||
_write_codex_cli_tokens,
|
||||
_load_auth_store,
|
||||
_load_provider_state,
|
||||
_resolve_kimi_base_url,
|
||||
@@ -693,6 +694,14 @@ class CredentialPool:
|
||||
self._replace_entry(synced, updated)
|
||||
self._persist()
|
||||
self._sync_device_code_entry_to_auth_store(updated)
|
||||
try:
|
||||
_write_codex_cli_tokens(
|
||||
updated.access_token,
|
||||
updated.refresh_token,
|
||||
last_refresh=updated.last_refresh,
|
||||
)
|
||||
except Exception as wexc:
|
||||
logger.debug("Failed to write refreshed Codex tokens to CLI file (retry): %s", wexc)
|
||||
return updated
|
||||
except Exception as retry_exc:
|
||||
logger.debug("Codex retry refresh also failed: %s", retry_exc)
|
||||
@@ -718,6 +727,17 @@ class CredentialPool:
|
||||
# _seed_from_singletons() on the next load_pool() sees fresh state
|
||||
# instead of re-seeding stale/consumed tokens.
|
||||
self._sync_device_code_entry_to_auth_store(updated)
|
||||
# Write refreshed tokens back to ~/.codex/auth.json so Codex CLI
|
||||
# and VS Code don't hit "refresh_token_reused" on their next refresh.
|
||||
if self.provider == "openai-codex":
|
||||
try:
|
||||
_write_codex_cli_tokens(
|
||||
updated.access_token,
|
||||
updated.refresh_token,
|
||||
last_refresh=updated.last_refresh,
|
||||
)
|
||||
except Exception as wexc:
|
||||
logger.debug("Failed to write refreshed Codex tokens to CLI file: %s", wexc)
|
||||
return updated
|
||||
|
||||
def _entry_needs_refresh(self, entry: PooledCredential) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user