diff --git a/cli.py b/cli.py index af8ac4efc24..e831dab358e 100755 --- a/cli.py +++ b/cli.py @@ -1504,7 +1504,7 @@ class HermesCLI: _cprint(f"{_DIM}└{'─' * (w - 2)}┘{_RST}") self._reasoning_box_opened = False - def _stream_delta(self, text: str) -> None: + def _stream_delta(self, text) -> None: """Line-buffered streaming callback for real-time token rendering. Receives text deltas from the agent as tokens arrive. Buffers @@ -1514,7 +1514,15 @@ class HermesCLI: Reasoning/thinking blocks (, , etc.) are suppressed during streaming since they'd display raw XML tags. The agent strips them from the final response anyway. + + A ``None`` value signals an intermediate turn boundary (tools are + about to execute). Flushes any open boxes and resets state so + tool feed lines render cleanly between turns. """ + if text is None: + self._flush_stream() + self._reset_stream_state() + return if not text: return diff --git a/run_agent.py b/run_agent.py index 1c3b25fe227..0e444b1adf8 100644 --- a/run_agent.py +++ b/run_agent.py @@ -4838,7 +4838,7 @@ class AIAgent: spinner.stop(cute_msg) elif self.quiet_mode: self._vprint(f" {cute_msg}") - elif self.quiet_mode and not self._has_stream_consumers(): + elif self.quiet_mode: face = random.choice(KawaiiSpinner.KAWAII_WAITING) emoji = _get_tool_emoji(function_name) preview = _build_tool_preview(function_name, function_args) or function_name @@ -6568,7 +6568,19 @@ class AIAgent: self._vprint(f" ┊ 💬 {clean}") messages.append(assistant_msg) - + + # Close any open streaming display (response box, reasoning + # box) before tool execution begins. Intermediate turns may + # have streamed early content that opened the response box; + # flushing here prevents it from wrapping tool feed lines. + # Only signal the display callback — TTS (_stream_callback) + # should NOT receive None (it uses None as end-of-stream). + if self.stream_delta_callback: + try: + self.stream_delta_callback(None) + except Exception: + pass + _msg_count_before_tools = len(messages) self._execute_tool_calls(assistant_message, messages, effective_task_id, api_call_count)