hermes - 💡(How to fix) Fix [Bug] Mid-thought tool execution splits reasoning into separate "Thinking" blocks

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

appendReasoningPart() in apps/desktop/src/lib/chat-messages.ts only appends to the last reasoning part if it's the absolute last element in the parts array (next.at(-1)?.type === 'reasoning'). Mid-thought tool execution inserts a tool-call part at the end, so the reasoning delta creates a new part instead of extending the existing one.

Fix Action

Fix

Scan backwards from the end of the array to find the last reasoning part regardless of what part types sit between. Tool-call parts between reasoning fragments no longer split the block.

 export function appendReasoningPart(parts: ChatMessagePart[], delta: string): ChatMessagePart[] {
   const next = [...parts]
-  const last = next.at(-1)
-  if (last?.type === 'reasoning') {
-    next[next.length - 1] = { ...last, text: `${last.text}${delta}` }
-    return next
+  for (let i = next.length - 1; i >= 0; i--) {
+    const entry = next[i]
+    if (entry?.type === 'reasoning') {
+      next[i] = { ...entry, text: `${entry.text}${delta}` }
+      return next
+    }
   }
   next.push(reasoningPart(delta))

Workaround

None — this is a UI presentation bug. Reasoning content is preserved in the underlying message, it's just displayed as a fragmented block.

Code Example

export function appendReasoningPart(parts: ChatMessagePart[], delta: string): ChatMessagePart[] {
   const next = [...parts]
-  const last = next.at(-1)
-  if (last?.type === 'reasoning') {
-    next[next.length - 1] = { ...last, text: `${last.text}${delta}` }
-    return next
+  for (let i = next.length - 1; i >= 0; i--) {
+    const entry = next[i]
+    if (entry?.type === 'reasoning') {
+      next[i] = { ...entry, text: `${entry.text}${delta}` }
+      return next
+    }
   }
   next.push(reasoningPart(delta))
RAW_BUFFERClick to expand / collapse

Problem

When the model pauses its reasoning to make a tool call mid-thought, the desktop app splits what was one continuous reasoning sentence into two separate "Thinking" blocks. Visually jarring — you see:

Thinking… (first half)
Thinking… (second half)

instead of one seamless block.

Root cause

appendReasoningPart() in apps/desktop/src/lib/chat-messages.ts only appends to the last reasoning part if it's the absolute last element in the parts array (next.at(-1)?.type === 'reasoning'). Mid-thought tool execution inserts a tool-call part at the end, so the reasoning delta creates a new part instead of extending the existing one.

Fix

Scan backwards from the end of the array to find the last reasoning part regardless of what part types sit between. Tool-call parts between reasoning fragments no longer split the block.

 export function appendReasoningPart(parts: ChatMessagePart[], delta: string): ChatMessagePart[] {
   const next = [...parts]
-  const last = next.at(-1)
-  if (last?.type === 'reasoning') {
-    next[next.length - 1] = { ...last, text: `${last.text}${delta}` }
-    return next
+  for (let i = next.length - 1; i >= 0; i--) {
+    const entry = next[i]
+    if (entry?.type === 'reasoning') {
+      next[i] = { ...entry, text: `${entry.text}${delta}` }
+      return next
+    }
   }
   next.push(reasoningPart(delta))

Workaround

None — this is a UI presentation bug. Reasoning content is preserved in the underlying message, it's just displayed as a fragmented block.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING