From 584409affc316e8114b489cdc3339d5ebca78b7a Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Wed, 29 Apr 2026 18:03:06 +0200 Subject: [PATCH] fix tool output being collapsed into args MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The greedy regex matched from the first { to the last } in the entire message, swallowing output (especially diffs containing braces) into the collapsed args section. Split on first newline instead—the call is always a single line (squashWhitespace in the backend ensures this). Also use trimEnd instead of trim to preserve leading whitespace in output. --- src/components/ChatPane.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/ChatPane.tsx b/src/components/ChatPane.tsx index 7750951..d555ab9 100644 --- a/src/components/ChatPane.tsx +++ b/src/components/ChatPane.tsx @@ -347,19 +347,22 @@ function DiagramModal({ html, onClose }: { html: string; onClose: () => void }) } function formatToolContent(raw: string): { name: string; detail: string; body: string; output: string } { - const m = raw.match(/^(\w+)\((\{[\s\S]*\})\)(.*)$/s) + // Call is always on the first line; output follows after the newline. + const nl = raw.indexOf('\n') + const callLine = nl === -1 ? raw : raw.slice(0, nl) + const output = nl === -1 ? '' : raw.slice(nl + 1).trimEnd() + const m = callLine.match(/^(\w+)\((.*)\)$/) if (!m) return { name: '', detail: '', body: raw, output: '' } const name = m[1] - const output = m[3].trim() + const argsRaw = m[2] try { - const obj = JSON.parse(m[2]) - // Extract a useful detail: tool name or language + const obj = JSON.parse(argsRaw) let detail = '' if (obj.steps?.[0]?.tool) detail = obj.steps[0].tool else if (obj.steps?.[0]?.code) detail = obj.language ?? 'bash' return { name, detail, body: JSON.stringify(obj, null, 2), output } } catch { - return { name, detail: '', body: m[2], output } + return { name, detail: '', body: argsRaw, output } } }