fix(agent): emit only extracted reasoning progress

This commit is contained in:
sgaofen 2026-04-20 21:54:27 -07:00
parent f81c0394d0
commit ce805b771e
3 changed files with 58 additions and 6 deletions

View file

@ -5356,6 +5356,26 @@ class AIAgent:
except Exception:
pass
def _fire_reasoning_available(self, assistant_message) -> None:
"""Fire structured reasoning progress if registered.
This reuses the existing reasoning extractor so the callback only
receives tagged/structured reasoning, never ordinary assistant reply
text.
"""
cb = self.tool_progress_callback
if cb is None:
return
reasoning_text = self._extract_reasoning(assistant_message)
if not reasoning_text:
return
try:
cb("reasoning.available", "_thinking", reasoning_text[:500], None)
except Exception:
pass
def _fire_tool_gen_started(self, tool_name: str) -> None:
"""Notify display layer that the model is generating tool call arguments.
@ -10833,11 +10853,8 @@ class AIAgent:
self.tool_progress_callback("_thinking", first_line)
except Exception:
pass
elif _think_text:
try:
self.tool_progress_callback("reasoning.available", "_thinking", _think_text[:500], None)
except Exception:
pass
else:
self._fire_reasoning_available(assistant_message)
# Check for incomplete <REASONING_SCRATCHPAD> (opened but never closed)
# This means the model ran out of output tokens mid-reasoning — retry up to 2 times

View file

@ -322,6 +322,18 @@ class TestThinkingCallback:
)
assert len(calls) == 0
def test_thinking_callback_keeps_stripped_preview(self):
"""Subagent thinking relay should still expose the stripped preview."""
calls = []
self._simulate_thinking_callback(
"<think>internal reasoning</think> visible summary",
lambda name, preview=None: calls.append((name, preview))
)
assert len(calls) == 1
assert calls[0][0] == "_thinking"
assert "internal reasoning" in calls[0][1]
assert "visible summary" in calls[0][1]
# =========================================================================
# Gateway batch flush tests
@ -386,4 +398,3 @@ class TestBatchFlush:
if __name__ == "__main__":
pytest.main([__file__, "-v"])

View file

@ -1212,6 +1212,30 @@ class TestBuildAssistantMessage:
assert result["content"] == ""
class TestReasoningAvailableProgress:
def test_emits_only_extracted_reasoning(self, agent):
calls = []
agent.tool_progress_callback = lambda *args, **kwargs: calls.append(args)
msg = _mock_assistant_msg(
content="<think>internal analysis</think>The actual answer."
)
agent._fire_reasoning_available(msg)
assert calls == [("reasoning.available", "_thinking", "internal analysis", None)]
def test_skips_plain_answer_text(self, agent):
calls = []
agent.tool_progress_callback = lambda *args, **kwargs: calls.append(args)
msg = _mock_assistant_msg(content="The actual answer only.")
agent._fire_reasoning_available(msg)
assert calls == []
class TestFormatToolsForSystemMessage:
def test_no_tools_returns_empty_array(self, agent):
agent.tools = []