From bdd9d752e13ee107375374a31b9c3f02a1d2a689 Mon Sep 17 00:00:00 2001 From: Aska Date: Mon, 7 Sep 2026 15:21:52 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20chat=20=E6=B0=94=E6=B3=A1=E6=8C=89?= =?UTF-8?q?=E6=AE=B5=E8=90=BD=E6=8B=86=E5=88=86=E2=80=94=E2=80=94=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=20no

=20=E7=9A=84=20\n\n=20=E5=8F=8C=E6=8D=A2?= =?UTF-8?q?=E8=A1=8C=E5=A4=9A=E6=AE=B5,=20=E4=B8=8D=E5=86=8D=E6=8C=A4?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E6=B0=94=E6=B3=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 她(LLM)常产出 \n\n(双换行)分隔多段 而非 design 约定的

标签(看最近消息原文

数0, 全\n\n) - splitParagraphs: 优先按

提取; 无完整

时按 /\n\s*\n/ 拆段(保留action/narration块, 不拆单\n句内换行) - 修: 之前只认

, 她\n\n多段被塞进一个气泡(whitespace-pre-wrap 显示双换行挤一个气泡), 主人反馈几个双换行挤一个气泡 - npm run build 绿 --- frontend/web/src/components/chat.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/frontend/web/src/components/chat.tsx b/frontend/web/src/components/chat.tsx index e012d12..aa91786 100644 --- a/frontend/web/src/components/chat.tsx +++ b/frontend/web/src/components/chat.tsx @@ -168,8 +168,22 @@ export function MessageBubble({ * Non-greedy + multi-line so a tag may span newlines; a still-streaming, * unclosed `

` simply does not match and stays out until it closes. */ function splitParagraphs(content: string): string[] { - const re = /]*>([\s\S]*?)<\/p>/g; - return [...content.matchAll(re)].map((m) => m[1]); + // Preferred: the agent wraps each paragraph in

…

(design/07 §2). When it + // emits plain \n\n runs instead (the model often does), split on those too so + // each logical paragraph becomes its own bubble. But never cut inside an + // … / … block, and never split on a + // single \n (that is an in-line break, kept inside the paragraph). + const pRe = /]*>([\s\S]*?)<\/p>/g; + const pSegments = [...content.matchAll(pRe)].map((m) => m[1].trim()); + if (pSegments.length > 0) return pSegments; + + // Keep non-

content (action/narration + body) so we don't strip the tags. + const segments: string[] = []; + for (const part of content.split(/\n\s*\n/)) { + if (!part.trim()) continue; + segments.push(part.trim()); + } + return segments; } /** Chat-mode body: a Miuix surface shell around a whitespace-preserving span,