From 0240baa357522654026e4aa04c716d209f79b704 Mon Sep 17 00:00:00 2001 From: arasovic Date: Tue, 31 Mar 2026 19:42:44 +0300 Subject: [PATCH] fix: strip orphaned think/reasoning tags from user-facing responses Some models (e.g. Kimi K2.5 on Alibaba OpenAI-compatible endpoint) emit reasoning text followed by a closing without a matching opening tag. The existing paired-tag regexes in _strip_think_blocks() cannot match these orphaned tags, so leaks into user-facing responses on all platforms. Add a catch-all regex that strips any remaining opening or closing think/thinking/reasoning/REASONING_SCRATCHPAD tags after the existing paired-block removal pass. Closes #4285 --- run_agent.py | 1 + tests/test_run_agent.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/run_agent.py b/run_agent.py index 13278d94c04..717c26b4a7d 100644 --- a/run_agent.py +++ b/run_agent.py @@ -1389,6 +1389,7 @@ class AIAgent: content = re.sub(r'.*?', '', content, flags=re.DOTALL | re.IGNORECASE) content = re.sub(r'.*?', '', content, flags=re.DOTALL) content = re.sub(r'.*?', '', content, flags=re.DOTALL) + content = re.sub(r'\s*', '', content, flags=re.IGNORECASE) return content def _looks_like_codex_intermediate_ack( diff --git a/tests/test_run_agent.py b/tests/test_run_agent.py index 7ea3a63fe23..aa74164a754 100644 --- a/tests/test_run_agent.py +++ b/tests/test_run_agent.py @@ -230,6 +230,27 @@ class TestStripThinkBlocks: assert "line1" not in result assert "visible" in result + def test_orphaned_closing_think_tag(self, agent): + result = agent._strip_think_blocks("some reasoningactual answer") + assert "" not in result + assert "actual answer" in result + + def test_orphaned_closing_thinking_tag(self, agent): + result = agent._strip_think_blocks("reasoninganswer") + assert "" not in result + assert "answer" in result + + def test_orphaned_opening_think_tag(self, agent): + result = agent._strip_think_blocks("orphaned reasoning without close") + assert "" not in result + + def test_mixed_orphaned_and_paired_tags(self, agent): + text = "straypaired reasoning visible" + result = agent._strip_think_blocks(text) + assert "" not in result + assert "" not in result + assert "visible" in result + class TestExtractReasoning: def test_reasoning_field(self, agent):