feat(transport): imply prompt_cache_key capability for api.openai.com
Review follow-up on the #56798 salvage: the gate shipped fully dormant (no provider profile sets supports_prompt_cache_key, no production caller passes it, and no plain 'openai' profile exists to set it on) — AGENTS.md rejects dead code wired in without E2E proof. Activate the one endpoint where the field is first-class: exact-host api.openai.com (OpenAI documents prompt_cache_key; GPT-5.6+ docs recommend it for cache routing). Deliberately NOT substring matching — Azure/OpenAI-compat endpoints may reject unknown fields and stay opt-in via the flag. 4 new tests (imply + 3 spoof/proxy/Azure negatives); mutation-checked (substring-weakened host check fails the spoof tests).
This commit is contained in:
@@ -163,6 +163,24 @@ def _is_gemini_openai_compat_base_url(base_url: Any) -> bool:
|
||||
return normalized.endswith("/openai")
|
||||
|
||||
|
||||
def _is_openai_api_base_url(base_url: Any) -> bool:
|
||||
"""True only for api.openai.com itself (exact host).
|
||||
|
||||
OpenAI documents ``prompt_cache_key`` as a first-class body field and
|
||||
GPT-5.6+ docs recommend it for reliable cache routing, so the flag is
|
||||
implied for the real endpoint. Deliberately NOT a substring match:
|
||||
Azure OpenAI and strict OpenAI-compat endpoints may reject unknown
|
||||
fields and must stay opt-in via ``supports_prompt_cache_key``.
|
||||
"""
|
||||
try:
|
||||
from urllib.parse import urlparse
|
||||
|
||||
host = (urlparse(str(base_url or "").strip()).hostname or "").lower()
|
||||
except Exception:
|
||||
return False
|
||||
return host == "api.openai.com"
|
||||
|
||||
|
||||
def _model_consumes_thought_signature(model: Any) -> bool:
|
||||
"""True when the outgoing model is a Gemini family model that requires
|
||||
``extra_content`` (thought_signature) to be replayed on tool calls.
|
||||
@@ -564,7 +582,8 @@ class ChatCompletionsTransport(ProviderTransport):
|
||||
api_kwargs,
|
||||
messages=sanitized,
|
||||
tools=api_kwargs.get("tools"),
|
||||
supports_prompt_cache_key=bool(params.get("supports_prompt_cache_key")),
|
||||
supports_prompt_cache_key=bool(params.get("supports_prompt_cache_key"))
|
||||
or _is_openai_api_base_url(params.get("base_url")),
|
||||
)
|
||||
|
||||
return api_kwargs
|
||||
|
||||
@@ -647,6 +647,37 @@ class TestPromptCacheKeyCapability:
|
||||
|
||||
assert body["prompt_cache_key"] == kwargs["prompt_cache_key"]
|
||||
|
||||
def test_openai_api_base_url_implies_capability(self, transport):
|
||||
"""api.openai.com gets the key WITHOUT an explicit flag (exact host)."""
|
||||
kwargs = transport.build_kwargs(
|
||||
model="gpt-cache-model",
|
||||
messages=self._messages(),
|
||||
tools=self._tools(),
|
||||
session_id="cron_job_2026-07-15T10:07:00Z",
|
||||
base_url="https://api.openai.com/v1",
|
||||
)
|
||||
|
||||
assert kwargs["prompt_cache_key"].startswith("pck_")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"base_url",
|
||||
[
|
||||
"https://myproxy.example.com/api.openai.com/v1", # host embedded in path
|
||||
"https://api.openai.com.evil.example/v1", # prefix-spoofed host
|
||||
"https://eastus.api.cognitive.microsoft.com/openai/v1", # Azure
|
||||
],
|
||||
)
|
||||
def test_non_openai_hosts_do_not_imply_capability(self, transport, base_url):
|
||||
kwargs = transport.build_kwargs(
|
||||
model="strict-model",
|
||||
messages=self._messages(),
|
||||
tools=self._tools(),
|
||||
session_id="cron_job_2026-07-15T10:08:00Z",
|
||||
base_url=base_url,
|
||||
)
|
||||
|
||||
assert "prompt_cache_key" not in kwargs
|
||||
|
||||
@pytest.mark.parametrize("provider", [None, "anthropic", "custom"])
|
||||
def test_default_off_never_leaks_unknown_body_field(self, transport, provider):
|
||||
from providers import get_provider_profile
|
||||
|
||||
Reference in New Issue
Block a user