fix: restore codex fallback auth-store lookup
This commit is contained in:
@@ -629,11 +629,19 @@ def _nous_base_url() -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _read_codex_access_token() -> Optional[str]:
|
def _read_codex_access_token() -> Optional[str]:
|
||||||
"""Read a valid, non-expired Codex OAuth access token from Hermes auth store."""
|
"""Read a valid, non-expired Codex OAuth access token from Hermes auth store.
|
||||||
|
|
||||||
|
If a credential pool exists but currently has no selectable runtime entry
|
||||||
|
(for example all pool slots are marked exhausted), fall back to the
|
||||||
|
profile's auth.json token instead of hard-failing. This keeps explicit
|
||||||
|
fallback-to-Codex working when the pool state is stale but the stored OAuth
|
||||||
|
token is still valid.
|
||||||
|
"""
|
||||||
pool_present, entry = _select_pool_entry("openai-codex")
|
pool_present, entry = _select_pool_entry("openai-codex")
|
||||||
if pool_present:
|
if pool_present:
|
||||||
token = _pool_runtime_api_key(entry)
|
token = _pool_runtime_api_key(entry)
|
||||||
return token or None
|
if token:
|
||||||
|
return token
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from hermes_cli.auth import _read_codex_tokens
|
from hermes_cli.auth import _read_codex_tokens
|
||||||
@@ -894,9 +902,13 @@ def _try_codex() -> Tuple[Optional[Any], Optional[str]]:
|
|||||||
pool_present, entry = _select_pool_entry("openai-codex")
|
pool_present, entry = _select_pool_entry("openai-codex")
|
||||||
if pool_present:
|
if pool_present:
|
||||||
codex_token = _pool_runtime_api_key(entry)
|
codex_token = _pool_runtime_api_key(entry)
|
||||||
if not codex_token:
|
if codex_token:
|
||||||
return None, None
|
base_url = _pool_runtime_base_url(entry, _CODEX_AUX_BASE_URL) or _CODEX_AUX_BASE_URL
|
||||||
base_url = _pool_runtime_base_url(entry, _CODEX_AUX_BASE_URL) or _CODEX_AUX_BASE_URL
|
else:
|
||||||
|
codex_token = _read_codex_access_token()
|
||||||
|
if not codex_token:
|
||||||
|
return None, None
|
||||||
|
base_url = _CODEX_AUX_BASE_URL
|
||||||
else:
|
else:
|
||||||
codex_token = _read_codex_access_token()
|
codex_token = _read_codex_access_token()
|
||||||
if not codex_token:
|
if not codex_token:
|
||||||
|
|||||||
@@ -77,6 +77,20 @@ class TestReadCodexAccessToken:
|
|||||||
result = _read_codex_access_token()
|
result = _read_codex_access_token()
|
||||||
assert result == "tok-123"
|
assert result == "tok-123"
|
||||||
|
|
||||||
|
def test_pool_without_selected_entry_falls_back_to_auth_store(self, tmp_path, monkeypatch):
|
||||||
|
hermes_home = tmp_path / "hermes"
|
||||||
|
hermes_home.mkdir(parents=True, exist_ok=True)
|
||||||
|
monkeypatch.setenv("HERMES_HOME", str(hermes_home))
|
||||||
|
|
||||||
|
valid_jwt = "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjk5OTk5OTk5OTl9.sig"
|
||||||
|
with patch("agent.auxiliary_client._select_pool_entry", return_value=(True, None)), \
|
||||||
|
patch("hermes_cli.auth._read_codex_tokens", return_value={
|
||||||
|
"tokens": {"access_token": valid_jwt, "refresh_token": "refresh"}
|
||||||
|
}):
|
||||||
|
result = _read_codex_access_token()
|
||||||
|
|
||||||
|
assert result == valid_jwt
|
||||||
|
|
||||||
def test_missing_returns_none(self, tmp_path, monkeypatch):
|
def test_missing_returns_none(self, tmp_path, monkeypatch):
|
||||||
hermes_home = tmp_path / "hermes"
|
hermes_home = tmp_path / "hermes"
|
||||||
hermes_home.mkdir(parents=True, exist_ok=True)
|
hermes_home.mkdir(parents=True, exist_ok=True)
|
||||||
@@ -238,6 +252,24 @@ class TestAnthropicOAuthFlag:
|
|||||||
assert mock_build.call_args.args[0] == "sk-ant-oat01-pooled"
|
assert mock_build.call_args.args[0] == "sk-ant-oat01-pooled"
|
||||||
|
|
||||||
|
|
||||||
|
class TestTryCodex:
|
||||||
|
def test_pool_without_selected_entry_falls_back_to_auth_store(self):
|
||||||
|
with (
|
||||||
|
patch("agent.auxiliary_client._select_pool_entry", return_value=(True, None)),
|
||||||
|
patch("agent.auxiliary_client._read_codex_access_token", return_value="codex-auth-token"),
|
||||||
|
patch("agent.auxiliary_client.OpenAI") as mock_openai,
|
||||||
|
):
|
||||||
|
mock_openai.return_value = MagicMock()
|
||||||
|
from agent.auxiliary_client import _try_codex
|
||||||
|
|
||||||
|
client, model = _try_codex()
|
||||||
|
|
||||||
|
assert client is not None
|
||||||
|
assert model == "gpt-5.2-codex"
|
||||||
|
assert mock_openai.call_args.kwargs["api_key"] == "codex-auth-token"
|
||||||
|
assert mock_openai.call_args.kwargs["base_url"] == "https://chatgpt.com/backend-api/codex"
|
||||||
|
|
||||||
|
|
||||||
class TestExpiredCodexFallback:
|
class TestExpiredCodexFallback:
|
||||||
"""Test that expired Codex tokens don't block the auto chain."""
|
"""Test that expired Codex tokens don't block the auto chain."""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user