From 6a13cc2f507925041da633cd40934f3cc64fea8c Mon Sep 17 00:00:00 2001 From: matevip Date: Mon, 15 Jun 2026 11:39:24 +0800 Subject: [PATCH] perf(chat): throttle streaming markdown render and defer chart mounts - add useStreamingMarkdown: cap mid-stream markdown re-render to ~140ms, full-fidelity render once the segment completes - skip code-block language auto-detection while streaming (escaped plain text), restore full highlighting on the final render - defer echarts/mermaid blocks to a lightweight loading placeholder while streaming so their parsers never run on truncated source - bypass the render cache for streaming-mode output - wire into ContentSegment and MessageBubble (content + thinking) --- mateclaw-ui/src/assets/main.css | 23 +++++ .../src/components/chat/ContentSegment.vue | 12 ++- .../src/components/chat/MessageBubble.vue | 21 ++--- .../__tests__/streaming-render.test.ts | 72 +++++++++++++++ .../src/composables/useMarkdownRenderer.ts | 82 ++++++++++++++--- .../src/composables/useStreamingMarkdown.ts | 87 +++++++++++++++++++ 6 files changed, 273 insertions(+), 24 deletions(-) create mode 100644 mateclaw-ui/src/composables/__tests__/streaming-render.test.ts create mode 100644 mateclaw-ui/src/composables/useStreamingMarkdown.ts diff --git a/mateclaw-ui/src/assets/main.css b/mateclaw-ui/src/assets/main.css index 1acc63c9..072bb1d6 100644 --- a/mateclaw-ui/src/assets/main.css +++ b/mateclaw-ui/src/assets/main.css @@ -616,6 +616,29 @@ html.dark body::before { font-size: 13px; } +/* Streaming placeholder for echarts/mermaid blocks (shown until the fenced + source finishes streaming, then replaced by the real chart). */ +.markdown-body .chart-loading { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + margin: 14px 0; + min-height: 120px; + border-radius: 12px; + background: var(--mc-bg-elevated); + border: 1px solid var(--mc-border-light); +} +.markdown-body .chart-loading__dot { + width: 9px; + height: 9px; + border-radius: 50%; + background: var(--mc-border, #cbd5e1); + animation: mc-product-pulse 1.4s ease-in-out infinite; +} +.markdown-body .chart-loading__dot:nth-child(2) { animation-delay: 0.2s; } +.markdown-body .chart-loading__dot:nth-child(3) { animation-delay: 0.4s; } + /* ================================================================ Product cards (from ```product-cards fenced blocks — shopping / price-comparison results rendered as a clickable card grid) diff --git a/mateclaw-ui/src/components/chat/ContentSegment.vue b/mateclaw-ui/src/components/chat/ContentSegment.vue index 1d6fef1d..0e3c3906 100644 --- a/mateclaw-ui/src/components/chat/ContentSegment.vue +++ b/mateclaw-ui/src/components/chat/ContentSegment.vue @@ -1,6 +1,6 @@