fix(codex): honor HERMES_CODEX_BASE_URL on pooled and aux codex client resolution
This commit is contained in:
@@ -2787,13 +2787,14 @@ def _build_codex_client(model: str) -> Tuple[Optional[Any], Optional[str]]:
|
||||
return None, None
|
||||
pool_present, entry = _select_pool_entry("openai-codex")
|
||||
codex_token = _pool_runtime_api_key(entry) if pool_present else None
|
||||
codex_override = os.getenv("HERMES_CODEX_BASE_URL", "").strip().rstrip("/")
|
||||
if codex_token:
|
||||
base_url = _pool_runtime_base_url(entry, _CODEX_AUX_BASE_URL) or _CODEX_AUX_BASE_URL
|
||||
base_url = codex_override or _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
|
||||
base_url = codex_override or _CODEX_AUX_BASE_URL
|
||||
logger.debug("Auxiliary client: Codex OAuth (%s via Responses API)", model)
|
||||
real_client = _create_openai_client(
|
||||
api_key=codex_token, base_url=base_url,
|
||||
|
||||
@@ -449,6 +449,13 @@ def _pool_entry_mode_and_url(provider, entry, model_cfg, effective_model, base_u
|
||||
base_url = _config_base_url_for_provider(model_cfg, provider) or base_url
|
||||
if provider in _POOL_ENTRY_SIMPLE_MODES:
|
||||
api_mode, default_url = _POOL_ENTRY_SIMPLE_MODES[provider]
|
||||
if provider == "openai-codex":
|
||||
# Pool entries retain the canonical ChatGPT URL, but the profile-wide
|
||||
# HERMES_CODEX_BASE_URL override must apply consistently to every
|
||||
# credential source, including pooled OAuth credentials.
|
||||
override_url = get_secret_str("HERMES_CODEX_BASE_URL", "").strip().rstrip("/")
|
||||
if override_url:
|
||||
return api_mode, override_url
|
||||
return api_mode, base_url or (default_url() if callable(default_url) else default_url)
|
||||
if provider == "anthropic":
|
||||
return "anthropic_messages", _anthropic_cfg_base_url(model_cfg) or base_url or _ANTHROPIC_DEFAULT_BASE_URL
|
||||
|
||||
@@ -724,6 +724,26 @@ class TestBuildCodexClient:
|
||||
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"
|
||||
|
||||
def test_profile_codex_base_url_overrides_pool_endpoint(self, monkeypatch):
|
||||
"""Auxiliary Codex calls use the same profile endpoint override as the main client."""
|
||||
entry = SimpleNamespace(
|
||||
runtime_api_key="codex-pool-token",
|
||||
runtime_base_url="https://chatgpt.com/backend-api/codex",
|
||||
)
|
||||
with (
|
||||
patch("agent.auxiliary_client._select_pool_entry", return_value=(True, entry)),
|
||||
patch("agent.auxiliary_client.OpenAI") as mock_openai,
|
||||
):
|
||||
monkeypatch.setenv("HERMES_CODEX_BASE_URL", "http://127.0.0.1:8787/v1")
|
||||
mock_openai.return_value = MagicMock()
|
||||
from agent.auxiliary_client import _build_codex_client
|
||||
|
||||
client, model = _build_codex_client("gpt-5.4")
|
||||
|
||||
assert client is not None
|
||||
assert model == "gpt-5.4"
|
||||
assert mock_openai.call_args.kwargs["base_url"] == "http://127.0.0.1:8787/v1"
|
||||
|
||||
def test_rejects_missing_model(self):
|
||||
"""Callers must pass an explicit model; no hardcoded default."""
|
||||
from agent.auxiliary_client import _build_codex_client
|
||||
|
||||
@@ -86,6 +86,30 @@ def test_resolve_runtime_provider_uses_credential_pool(monkeypatch):
|
||||
assert resolved["source"] == "manual"
|
||||
|
||||
|
||||
def test_codex_pool_honors_hermes_codex_base_url(monkeypatch):
|
||||
"""The profile-wide Codex endpoint override must apply to pool credentials too."""
|
||||
class _Entry:
|
||||
access_token = "pool-token"
|
||||
source = "manual"
|
||||
base_url = "https://chatgpt.com/backend-api/codex"
|
||||
|
||||
class _Pool:
|
||||
def has_credentials(self):
|
||||
return True
|
||||
|
||||
def select(self):
|
||||
return _Entry()
|
||||
|
||||
monkeypatch.setattr(rp, "resolve_provider", lambda *a, **k: "openai-codex")
|
||||
monkeypatch.setattr(rp, "load_pool", lambda provider: _Pool())
|
||||
monkeypatch.setenv("HERMES_CODEX_BASE_URL", "http://127.0.0.1:8787/v1")
|
||||
|
||||
resolved = rp.resolve_runtime_provider(requested="openai-codex")
|
||||
|
||||
assert resolved["provider"] == "openai-codex"
|
||||
assert resolved["base_url"] == "http://127.0.0.1:8787/v1"
|
||||
|
||||
|
||||
class TestCustomProviderPoolLoopbackNoKeyExemption:
|
||||
"""Regression for issue #86864: legacy custom_providers configs often
|
||||
used short/placeholder api_keys ('123', 'm') for local no-auth
|
||||
|
||||
Reference in New Issue
Block a user