From 3cede6fb7ff47d7bb8409ff17d10fae74c7081cb Mon Sep 17 00:00:00 2001 From: GoldenFishX Date: Wed, 27 May 2026 09:42:04 +0800 Subject: [PATCH] fix(bridge): block thinking spinner kaomoji from contaminating conversation history (#1051) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hermes-agent CLI KawaiiSpinner sends decorative kaomoji text like "(◕‿◕✿) pondering..." through thinking_callback for its TUI widget. The bridge forwarded this as thinking.delta events, which the frontend stored in the message reasoning field. Over long conversations this contaminated the model's context: _copy_reasoning_content_for_api promoted the kaomoji text to reasoning_content, causing the LLM to reproduce kaomoji patterns in a self-reinforcing degradation loop. Fix: _make_thinking_callback unconditionally sends empty text. thinking_callback is purely CLI spinner status — it has no place in conversation history. Actual model reasoning (reasoning.delta) is unaffected. --- .../hermes/agent-bridge/hermes_bridge.py | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/server/src/services/hermes/agent-bridge/hermes_bridge.py b/packages/server/src/services/hermes/agent-bridge/hermes_bridge.py index 383ea88..62f2833 100755 --- a/packages/server/src/services/hermes/agent-bridge/hermes_bridge.py +++ b/packages/server/src/services/hermes/agent-bridge/hermes_bridge.py @@ -740,7 +740,7 @@ class AgentPool: session_db=self._db.get_for_profile(profile), ephemeral_system_prompt=prompt, status_callback=self._status_callback(session_id), - thinking_callback=self._text_event_callback(session_id, "thinking.delta"), + thinking_callback=self._make_thinking_callback(session_id), reasoning_callback=self._text_event_callback(session_id, "reasoning.delta"), tool_progress_callback=self._tool_progress_callback(session_id), tool_start_callback=self._tool_start_callback(session_id), @@ -992,6 +992,28 @@ class AgentPool: return callback + def _make_thinking_callback(self, session_id: str): + """Create a thinking callback that never forwards spinner text as content. + + The hermes-agent CLI uses thinking_callback for its KawaiiSpinner TUI + widget — sending decorative text like "(◕‿◕✿) pondering..." during + API calls. This is pure CLI UX decoration; it has no place in Web UI + conversation history. + + Prior behaviour forwarded this text as thinking.delta events, which the + frontend stored in the message reasoning field. Over long conversations + this contaminated the model's context: the LLM learned to reproduce + kaomoji patterns, creating a self-reinforcing degradation loop. + + This callback sends empty text unconditionally. The model's real + reasoning content arrives through reasoning_callback → reasoning.delta, + which is unaffected. + """ + def callback(text=None): + self._append_event(session_id, {"event": "thinking.delta", "text": ""}) + + return callback + def _tool_start_callback(self, session_id: str): def callback(tool_call_id, function_name, function_args): self._append_event(session_id, {