mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
Merge ce805b771e into 4fade39c90
This commit is contained in:
commit
767f7aba75
3 changed files with 58 additions and 6 deletions
27
run_agent.py
27
run_agent.py
|
|
@ -5854,6 +5854,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.
|
||||
|
||||
|
|
@ -11675,11 +11695,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
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
|
||||
|
|
|
|||
|
|
@ -1453,6 +1453,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 = []
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue