From d8984b8112db608a647b74bfdbccf4b2b1625e93 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Tue, 14 Apr 2026 17:57:56 -0300 Subject: [PATCH] fix: robust signal extraction in frontend --- ui/suite/chat/chat.html | 47 ++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/ui/suite/chat/chat.html b/ui/suite/chat/chat.html index 8aafb39..0986036 100644 --- a/ui/suite/chat/chat.html +++ b/ui/suite/chat/chat.html @@ -816,33 +816,36 @@ function finalizeStreaming() { } function processMessage(data) { - // If content is a JSON string or contains it, try to intercept internal signals - if (data.content && typeof data.content === "string") { - var jsonStart = data.content.indexOf('{"type":"thinking'); - if (jsonStart !== -1) { + // If content contains JSON signals, extract and handle them + if (data.content && typeof data.content === "string" && data.content.includes('{')) { + var signalRegex = /\{[^{}]*"type"\s*:\s*"(thinking|thinking_clear)"[^{}]*\}/g; + var match; + var hasAnySignal = false; + + while ((match = signalRegex.exec(data.content)) !== null) { try { - // Extract only the JSON part - var remaining = data.content.substring(jsonStart); - var jsonEnd = remaining.indexOf("}") + 1; - if (jsonEnd > 0) { - var jsonStr = remaining.substring(0, jsonEnd); - var inner = JSON.parse(jsonStr); - - if (inner.type === "thinking") { - showThinkingIndicator(inner.content); - // If there is text before or after, keep processing that as content - data.content = data.content.replace(jsonStr, "").trim(); - if (data.content === "") return; - } else if (inner.type === "thinking_clear") { - hideThinkingIndicator(); - data.content = data.content.replace(jsonStr, "").trim(); - if (data.content === "") return; - } + var jsonStr = match[0]; + var inner = JSON.parse(jsonStr); + hasAnySignal = true; + + if (inner.type === "thinking") { + showThinkingIndicator(inner.content); + } else if (inner.type === "thinking_clear") { + hideThinkingIndicator(); } + + // Remove this signal from the content + data.content = data.content.replace(jsonStr, ""); + // Reset regex index since we modified the string + signalRegex.lastIndex = 0; } catch (e) { - console.error("Failed to parse embedded signal:", e); + console.error("Failed to parse signal:", e); } } + + if (hasAnySignal && data.content.trim() === "" && !data.is_complete) { + return; + } } // Fallback for direct type matches