diff --git a/cli.py b/cli.py
index a047471b63..ccc1e0d68d 100755
--- a/cli.py
+++ b/cli.py
@@ -1524,9 +1524,11 @@ class HermesCLI:
# Track whether we're inside a reasoning/thinking block.
# These tags are model-generated (system prompt tells the model
# to use them) and get stripped from final_response. We must
- # suppress them during streaming too.
- _OPEN_TAGS = ("", "", "", "")
- _CLOSE_TAGS = ("", "", "", "")
+ # suppress them during streaming too — unless show_reasoning is
+ # enabled, in which case we route the inner content to the
+ # reasoning display box instead of discarding it.
+ _OPEN_TAGS = ("", "", "", "", "")
+ _CLOSE_TAGS = ("", "", "", "", "")
# Append to a pre-filter buffer first
self._stream_prefilt = getattr(self, "_stream_prefilt", "") + text
@@ -1566,6 +1568,12 @@ class HermesCLI:
idx = self._stream_prefilt.find(tag)
if idx != -1:
self._in_reasoning_block = False
+ # When show_reasoning is on, route inner content to
+ # the reasoning display box instead of discarding.
+ if self.show_reasoning:
+ inner = self._stream_prefilt[:idx]
+ if inner:
+ self._stream_reasoning_delta(inner)
after = self._stream_prefilt[idx + len(tag):]
self._stream_prefilt = ""
# Process remaining text after close tag through full
@@ -1573,10 +1581,15 @@ class HermesCLI:
if after:
self._stream_delta(after)
return
- # Still inside reasoning block — keep only the tail that could
- # be a partial close tag prefix (save memory on long blocks).
+ # When show_reasoning is on, stream reasoning content live
+ # instead of silently accumulating. Keep only the tail that
+ # could be a partial close tag prefix.
max_tag_len = max(len(t) for t in _CLOSE_TAGS)
if len(self._stream_prefilt) > max_tag_len:
+ if self.show_reasoning:
+ # Route the safe prefix to reasoning display
+ safe_reasoning = self._stream_prefilt[:-max_tag_len]
+ self._stream_reasoning_delta(safe_reasoning)
self._stream_prefilt = self._stream_prefilt[-max_tag_len:]
return
diff --git a/run_agent.py b/run_agent.py
index 2655ac288c..ffcd809f92 100644
--- a/run_agent.py
+++ b/run_agent.py
@@ -1115,10 +1115,16 @@ class AIAgent:
return bool(cleaned.strip())
def _strip_think_blocks(self, content: str) -> str:
- """Remove ... blocks from content, returning only visible text."""
+ """Remove reasoning/thinking blocks from content, returning only visible text."""
if not content:
return ""
- return re.sub(r'.*?', '', content, flags=re.DOTALL)
+ # Strip all reasoning tag variants: , , ,
+ # ,
+ content = re.sub(r'.*?', '', content, flags=re.DOTALL)
+ 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)
+ return content
def _looks_like_codex_intermediate_ack(
self,