Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion agent/transports/codex.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,31 @@
streaming, or the _run_codex_stream() call path.
"""

import hashlib
from typing import Any, Dict, List, Optional

from agent.transports.base import ProviderTransport
from agent.transports.types import NormalizedResponse, ToolCall


_PROMPT_CACHE_KEY_MAX_LENGTH = 64


def _safe_prompt_cache_key(value: str) -> str:
"""Return a Codex-compatible prompt_cache_key.

The Codex backend rejects prompt_cache_key values longer than 64
characters. Hermes session IDs can exceed that when gateway/platform
routing embeds long external identifiers. Preserve short IDs for
debuggability and hash only oversized values into a stable 64-character
scope key.
"""
raw = str(value or "").strip()
if len(raw) <= _PROMPT_CACHE_KEY_MAX_LENGTH:
return raw
return hashlib.sha256(raw.encode("utf-8")).hexdigest()


class ResponsesApiTransport(ProviderTransport):
"""Transport for api_mode='codex_responses'.

Expand Down Expand Up @@ -101,7 +120,7 @@ def build_kwargs(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only bounds the session_id-derived value. On current main, request overrides are merged afterward (agent/transports/codex.py:295-297), so an explicit prompt_cache_key can still replace it unbounded; the xAI extra_body override is similarly preserved. Please rework this around the final merged values if the goal includes caller-provided keys.

session_id = params.get("session_id")
if not is_github_responses and session_id:
kwargs["prompt_cache_key"] = session_id
kwargs["prompt_cache_key"] = _safe_prompt_cache_key(str(session_id))

if reasoning_enabled and is_xai_responses:
from agent.model_metadata import grok_supports_reasoning_effort
Expand Down
10 changes: 10 additions & 0 deletions tests/agent/transports/test_codex_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ def test_session_id_sets_cache_key(self, transport):
)
assert kw.get("prompt_cache_key") == "test-session-123"

def test_long_session_id_cache_key_is_hashed_to_backend_limit(self, transport):
messages = [{"role": "user", "content": "Hi"}]
long_session_id = "atlas:4CGVtvUxCQrizW2tuRbqNa25nLnClXPm:494fd2fb-ca04-431b-a26d-f6c255d0804e"
kw = transport.build_kwargs(
model="gpt-5.4", messages=messages, tools=[],
session_id=long_session_id,
)
assert len(kw.get("prompt_cache_key")) == 64
assert kw.get("prompt_cache_key") != long_session_id

def test_github_responses_no_cache_key(self, transport):
messages = [{"role": "user", "content": "Hi"}]
kw = transport.build_kwargs(
Expand Down