From 714fc8071cf130985ff608618cdfca98f961b9df Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Wed, 7 Oct 2026 17:16:36 +0530 Subject: [PATCH] refactor(agent): share the hidden interrupt placeholder row message_sanitization.close_interrupted_tool_sequence and the turn_api_call repetition-loop exit each spelled the same hidden assistant row literal (content "", display_kind hidden, api_content _INTERRUPTED_PLACEHOLDER), and the conversation loop's redirect built it field by field. Add hidden_interrupt_placeholder_row() to the leaf placeholders module and use it at all three sites so the shape cannot drift between them. Gate rP finding 6 (reuse). --- agent/agent_runtime_helpers_placeholders.py | 6 ++++++ agent/conversation_loop.py | 13 ++++--------- agent/message_sanitization.py | 9 ++------- agent/turn_api_call.py | 7 ++----- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/agent/agent_runtime_helpers_placeholders.py b/agent/agent_runtime_helpers_placeholders.py index 3d6ccc6d90..9e0067dc3b 100644 --- a/agent/agent_runtime_helpers_placeholders.py +++ b/agent/agent_runtime_helpers_placeholders.py @@ -18,3 +18,9 @@ _INTERRUPTED_PLACEHOLDER = "[interrupt: no assistant output for this turn]" # The spelling shipped before #132949. Models reproduce it verbatim, so rows already carrying it # stay poisoned after the wording change; the replay filters reference this name to retire them. _LEGACY_INTERRUPTED_PLACEHOLDER = "[response interrupted]" + + +def hidden_interrupt_placeholder_row() -> dict: + """A fresh assistant row that is invisible in transcripts but carries the placeholder as its + non-empty ``api_content``, so the pre-call sanitizer does not re-heal it every call (#88955).""" + return {"role": "assistant", "content": "", "display_kind": "hidden", "api_content": _INTERRUPTED_PLACEHOLDER} diff --git a/agent/conversation_loop.py b/agent/conversation_loop.py index 8ef5968014..5c54a1908c 100644 --- a/agent/conversation_loop.py +++ b/agent/conversation_loop.py @@ -343,15 +343,10 @@ def _apply_active_turn_redirect(agent: Any, messages: List[Dict[str, Any]], text # preserves alternation only — scaffold bytes must never land in it, since api_content # is substituted back into content on replay (#81841). if not (messages and messages[-1].get("role") == "assistant"): - placeholder: Dict[str, Any] = {"role": "assistant", "content": visible or ""} - if not visible: - placeholder["display_kind"] = "hidden" - # Hidden row, but a non-empty neutral api_content so the pre-call sanitizer - # does not re-heal it every call (#88955). Never _INTERRUPT_SCAFFOLD_MARKER: - # as assistant text the model echoes it (#81841). - from agent.agent_runtime_helpers_placeholders import _INTERRUPTED_PLACEHOLDER - placeholder["api_content"] = _INTERRUPTED_PLACEHOLDER - append_message(messages, placeholder) + # Hidden row with a neutral api_content (#88955). Never _INTERRUPT_SCAFFOLD_MARKER: + # as assistant text the model echoes it (#81841). + from agent.agent_runtime_helpers_placeholders import hidden_interrupt_placeholder_row + append_message(messages, {"role": "assistant", "content": visible} if visible else hidden_interrupt_placeholder_row()) # Transcript shows the user's own words; the provider replays the scaffolded form. append_message(messages, {"role": "user", "content": text, "api_content": correction}) diff --git a/agent/message_sanitization.py b/agent/message_sanitization.py index d4d6edbb41..60f0a2971e 100644 --- a/agent/message_sanitization.py +++ b/agent/message_sanitization.py @@ -302,16 +302,11 @@ def close_interrupted_tool_sequence(messages: list, final_response: Any = None) return False text = final_response if isinstance(final_response, str) else "" from agent.message_metadata import append_message - from agent.agent_runtime_helpers_placeholders import _INTERRUPTED_PLACEHOLDER + from agent.agent_runtime_helpers_placeholders import _INTERRUPTED_PLACEHOLDER, hidden_interrupt_placeholder_row stripped = text.strip() if not stripped or stripped == _INTERRUPTED_PLACEHOLDER: - append_message(messages, { - "role": "assistant", - "content": "", - "display_kind": "hidden", - "api_content": _INTERRUPTED_PLACEHOLDER, - }) + append_message(messages, hidden_interrupt_placeholder_row()) else: append_message(messages, {"role": "assistant", "content": stripped}) return True diff --git a/agent/turn_api_call.py b/agent/turn_api_call.py index 87d1cfe82d..87f21f77c9 100644 --- a/agent/turn_api_call.py +++ b/agent/turn_api_call.py @@ -15,7 +15,7 @@ import time from typing import Any, Dict, Optional from agent.error_classifier import FailoverReason -from agent.agent_runtime_helpers_placeholders import _INTERRUPTED_PLACEHOLDER +from agent.agent_runtime_helpers_placeholders import hidden_interrupt_placeholder_row from agent.message_metadata import append_message from agent.repetition_guard import REPETITION_LOOP_INTERRUPTED, is_runaway_repetition from agent.turn_failure_copy import site_copy, stamp_failure @@ -198,10 +198,7 @@ def handle_api_interrupt( # The interrupted row is replayed next turn; looped bytes there re-seed the loop # (#112764). Same hidden shape as the redirect placeholder: nothing visible in the # transcript, a neutral api_content so the pre-call sanitizer does not re-heal it. - append_message(messages, { - "role": "assistant", "content": "", "display_kind": "hidden", - "api_content": _INTERRUPTED_PLACEHOLDER, - }) + append_message(messages, hidden_interrupt_placeholder_row()) final_response = REPETITION_LOOP_INTERRUPTED elif _partial: append_message(messages, {