fix(agent): keep Codex reasoning replay on Codex path

This commit is contained in:
Teknium 2026-06-13 14:08:11 -07:00
parent 1d584a301e
commit 069bfd6545
3 changed files with 25 additions and 5 deletions

View file

@ -881,6 +881,8 @@ def try_recover_primary_transport(
def drop_thinking_only_and_merge_users(
messages: List[Dict[str, Any]],
*,
drop_codex_reasoning_items: bool = True,
) -> List[Dict[str, Any]]:
"""Drop thinking-only assistant turns; merge any adjacent user messages left behind.
@ -902,7 +904,13 @@ def drop_thinking_only_and_merge_users(
return messages
# Pass 1: drop thinking-only assistant turns.
kept = [m for m in messages if not _ra().AIAgent._is_thinking_only_assistant(m)]
kept = [
m for m in messages
if not _ra().AIAgent._is_thinking_only_assistant(
m,
drop_codex_reasoning_items=drop_codex_reasoning_items,
)
]
dropped = len(messages) - len(kept)
if dropped == 0:
return messages

View file

@ -707,7 +707,10 @@ def run_conversation(
# a thinking-only turn. Runs on the per-call copy only — the
# stored conversation history keeps the reasoning block for the
# UI transcript and session persistence.
api_messages = agent._drop_thinking_only_and_merge_users(api_messages)
api_messages = agent._drop_thinking_only_and_merge_users(
api_messages,
drop_codex_reasoning_items=agent.api_mode != "codex_responses",
)
# Normalize message whitespace and tool-call JSON for consistent
# prefix matching. Ensures bit-perfect prefixes across turns,

View file

@ -3246,7 +3246,11 @@ class AIAgent:
return sanitize_api_messages(messages)
@staticmethod
def _is_thinking_only_assistant(msg: Dict[str, Any]) -> bool:
def _is_thinking_only_assistant(
msg: Dict[str, Any],
*,
drop_codex_reasoning_items: bool = True,
) -> bool:
"""Return True if ``msg`` is an assistant turn whose only payload is reasoning.
"Thinking-only" means the model emitted reasoning (``reasoning`` or
@ -3302,7 +3306,7 @@ class AIAgent:
# thinking-only; empty/junk lists should fall through to the generic
# empty-turn handling instead of being dropped here.
codex_items = msg.get("codex_reasoning_items")
if isinstance(codex_items, list):
if drop_codex_reasoning_items and isinstance(codex_items, list):
return any(
isinstance(item, dict) and item.get("type") == "reasoning"
for item in codex_items
@ -3312,10 +3316,15 @@ class AIAgent:
@staticmethod
def _drop_thinking_only_and_merge_users(
messages: List[Dict[str, Any]],
*,
drop_codex_reasoning_items: bool = True,
) -> List[Dict[str, Any]]:
"""Forwarder — see ``agent.agent_runtime_helpers.drop_thinking_only_and_merge_users``."""
from agent.agent_runtime_helpers import drop_thinking_only_and_merge_users
return drop_thinking_only_and_merge_users(messages)
return drop_thinking_only_and_merge_users(
messages,
drop_codex_reasoning_items=drop_codex_reasoning_items,
)
@staticmethod
def _cap_delegate_task_calls(tool_calls: list) -> list: