fix(auth): preserve Codex pool-only rate-limit state

Classify exhausted pool-only openai-codex credentials as quota/rate-limited instead of missing auth. This prevents auth status and runtime credential resolution from reporting missing credentials when a valid manual:device_code pool credential exists but is temporarily in a 429 usage-limit cooldown.

Adds regression coverage for pool-only Codex auth status and runtime resolution.
This commit is contained in:
MrDiamondBallz
2026-06-16 05:56:11 -07:00
committed by Teknium
parent 6373aba80f
commit 9a59ad73dd
2 changed files with 179 additions and 0 deletions
+70
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
import base64
import json
import time
from datetime import datetime, timezone
from unittest.mock import patch
@@ -25,6 +26,37 @@ def _jwt_with_email(email: str) -> str:
return f"{header}.{payload}.signature"
def _codex_pool_only_store(*, exhausted: bool = False) -> dict:
entry = {
"id": "codex-1",
"label": "codex@example.com",
"auth_type": "oauth",
"priority": 0,
"source": "manual:device_code",
"access_token": _jwt_with_email("codex@example.com"),
"refresh_token": "refresh-token",
"base_url": "https://chatgpt.com/backend-api/codex",
"last_refresh": "2026-06-15T10:00:00Z",
}
if exhausted:
entry.update(
{
"last_status": "exhausted",
"last_status_at": time.time(),
"last_error_code": 429,
"last_error_reason": "usage_limit_reached",
"last_error_message": "The usage limit has been reached",
"last_error_reset_at": time.time() + 3600,
}
)
return {
"version": 1,
"active_provider": "openai-codex",
"providers": {},
"credential_pool": {"openai-codex": [entry]},
}
@pytest.fixture(autouse=True)
def _clear_provider_env(monkeypatch):
for key in (
@@ -483,6 +515,44 @@ def test_auth_add_codex_oauth_keeps_distinct_pool_accounts(tmp_path, monkeypatch
assert payload["active_provider"] == "openai-codex"
def test_codex_auth_status_reports_pool_only_credential(tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes"))
_write_auth_store(tmp_path, _codex_pool_only_store())
from hermes_cli.auth import get_codex_auth_status
status = get_codex_auth_status()
assert status["logged_in"] is True
assert status["source"] == "pool:codex@example.com"
def test_codex_auth_status_reports_pool_only_rate_limit(tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes"))
_write_auth_store(tmp_path, _codex_pool_only_store(exhausted=True))
from hermes_cli.auth import get_codex_auth_status
status = get_codex_auth_status()
assert status["logged_in"] is True
assert status["rate_limited"] is True
assert status["error_code"] == "codex_rate_limited"
def test_codex_runtime_pool_only_rate_limit_is_not_missing_auth(tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path / "hermes"))
_write_auth_store(tmp_path, _codex_pool_only_store(exhausted=True))
from hermes_cli.auth import AuthError, CODEX_RATE_LIMITED_CODE, resolve_codex_runtime_credentials
with pytest.raises(AuthError) as exc_info:
resolve_codex_runtime_credentials()
assert exc_info.value.code == CODEX_RATE_LIMITED_CODE
assert exc_info.value.relogin_required is False
def test_auth_add_xai_oauth_sets_active_provider(tmp_path, monkeypatch):
"""hermes auth add xai-oauth must write providers singleton and set active_provider.