diff --git a/agent/transports/codex.py b/agent/transports/codex.py index 446e878623..6da9038172 100644 --- a/agent/transports/codex.py +++ b/agent/transports/codex.py @@ -273,9 +273,11 @@ def _is_official_openai_responses_route(model: Any, base_url: Any) -> bool: """Astra cache semantics apply only to the official OpenAI API host.""" if not _is_astra_model(model): return False - from utils import base_url_host_matches + from utils import base_url_hostname - return base_url_host_matches(str(base_url or ""), "api.openai.com") + # Astra's account-gated cache contract is for the canonical API origin only. + # Do not extend it to subdomains (or lookalike hosts) by suffix matching. + return base_url_hostname(str(base_url or "")).lower() == "api.openai.com" def _codex_efforts_for_route(model: Any, base_url: Any, *, is_codex_backend: bool = False) -> tuple[str, ...]: diff --git a/tests/agent/transports/test_codex_transport.py b/tests/agent/transports/test_codex_transport.py index 01e5e7c9f7..4ff7a3859e 100644 --- a/tests/agent/transports/test_codex_transport.py +++ b/tests/agent/transports/test_codex_transport.py @@ -103,6 +103,18 @@ class TestCodexBuildKwargs: assert "prompt_cache_options" not in kw assert kw["reasoning"]["effort"] == "none" + def test_astra_openai_subdomain_is_not_official_route(self, transport): + """Only api.openai.com gets Astra's official cache contract.""" + kw = transport.build_kwargs( + model="gpt-6-astra", + messages=[{"role": "user", "content": "Hi"}], + tools=[], + base_url="https://evil.api.openai.com/v1", + request_overrides={"prompt_cache_options": {"ttl": "30m"}}, + ) + + assert "prompt_cache_options" not in kw + def test_900k_context_variant_suffix_stripped_on_wire(self, transport): """``-900k`` large-context picker variants are Hermes-side aliases — the Codex backend only knows the base slug, so build_kwargs must