From 5e69b62e4ce7b2fe1e36d19973833687740bdddd Mon Sep 17 00:00:00 2001 From: Stable Genius Date: Fri, 20 Mar 2026 19:52:46 -0700 Subject: [PATCH] fix(webchat): render standalone HTML replies as code (#6074) Co-authored-by: Stable Genius <259448942+stablegenius49@users.noreply.github.com> Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com> --- .../MessagePartsRenderer.vue | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/dashboard/src/components/chat/message_list_comps/MessagePartsRenderer.vue b/dashboard/src/components/chat/message_list_comps/MessagePartsRenderer.vue index fde69aabf..cadd5fb56 100644 --- a/dashboard/src/components/chat/message_list_comps/MessagePartsRenderer.vue +++ b/dashboard/src/components/chat/message_list_comps/MessagePartsRenderer.vue @@ -63,9 +63,10 @@ + custom-id="message-list" :custom-html-tags="['ref']" + :content="normalizeMarkdownContent(renderPart.part.text)" :typewriter="false" + class="markdown-content" :is-dark="isDark" :monacoOptions="{ theme: isDark ? 'vs-dark' : 'vs-light' }" + :key="`${renderPart.key}-${isDark ? 'dark' : 'light'}`"/>
@@ -152,6 +153,21 @@ const emitDownloadFile = (file) => { emit('download-file', file); }; +const isMarkdownCodeFence = (text) => /^(```|~~~)/.test(text.trim()); + +const looksLikeStandaloneHtml = (text) => { + const normalized = text.trim(); + if (!normalized) return false; + if (!/(|<\/body>|<\/head>| { + if (typeof text !== 'string') return text; + if (isMarkdownCodeFence(text) || !looksLikeStandaloneHtml(text)) return text; + return `\`\`\`\`html\n${text}\n\`\`\`\``; +}; + const formatDuration = (seconds) => { if (seconds < 1) { return `${Math.round(seconds * 1000)}ms`;