From 6367512052a0d8ab395a235e062244c5d94903ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 26 Jun 2026 18:00:10 -0400 Subject: [PATCH] Render light markdown in chat messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bodies were printed verbatim, so an agent's **bold**, `code`, or [link](https://...) showed as literal punctuation — the opposite of people talking. Render the inline markdown agents and humans actually use in chat into React nodes, composed around the existing @mention highlighting. Links are restricted to http(s) and nothing is ever set as raw HTML (no dangerouslySetInnerHTML), so a message body can never inject markup or a javascript: URL. A plain message still comes back as one string. --- .../src/pages/chat/ChatMessageRow.tsx | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/AgentCompany-New/src/renderer/src/pages/chat/ChatMessageRow.tsx b/AgentCompany-New/src/renderer/src/pages/chat/ChatMessageRow.tsx index 79517b1f..ffa751ce 100644 --- a/AgentCompany-New/src/renderer/src/pages/chat/ChatMessageRow.tsx +++ b/AgentCompany-New/src/renderer/src/pages/chat/ChatMessageRow.tsx @@ -132,7 +132,7 @@ export function ChatMessageRow({ } function renderBody(body: string, mentions: ChatMentionRecord[], context: MessageContext): ReactNode { - if (mentions.length === 0) return body; + if (mentions.length === 0) return formatInline(body, "b"); const parts: ReactNode[] = []; const ordered = [...mentions].sort((a, b) => a.offsetStart - b.offsetStart); let lastIndex = 0; @@ -143,7 +143,7 @@ function renderBody(body: string, mentions: ChatMentionRecord[], context: Messag } const token = body.slice(mention.offsetStart, mention.offsetEnd); if (!token.startsWith("@")) throw new Error("Message mention token is invalid."); - if (mention.offsetStart > lastIndex) parts.push(body.slice(lastIndex, mention.offsetStart)); + if (mention.offsetStart > lastIndex) parts.push(...formatInline(body.slice(lastIndex, mention.offsetStart), `s${lastIndex}`)); const label = mentionLabel(mention, context); parts.push( lastIndex) nodes.push(text.slice(lastIndex, match.index)); + const key = `${keyPrefix}-${token++}`; + if (match[2] !== undefined) nodes.push({match[2]}); + else if (match[3] !== undefined) nodes.push({match[3]}); + else if (match[4] !== undefined) nodes.push({match[4]}); + else nodes.push({match[5]}); + lastIndex = pattern.lastIndex; + } + if (lastIndex < text.length) nodes.push(text.slice(lastIndex)); + return nodes; +} + function mentionLabel(mention: ChatMentionRecord, context: MessageContext): string { if (mention.targetType === "employee") { const employee = context.employees.find((item) => item.id === mention.targetId);