From 1e222efe29b2ff96c8ec566e16bbb92d8baaa1a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Wed, 25 Mar 2026 21:12:16 +0800 Subject: [PATCH] Add files via upload --- web/static/js/monitor.js | 95 +++++++++++++--------------------------- 1 file changed, 31 insertions(+), 64 deletions(-) diff --git a/web/static/js/monitor.js b/web/static/js/monitor.js index 23bbd1d5..1420263a 100644 --- a/web/static/js/monitor.js +++ b/web/static/js/monitor.js @@ -628,6 +628,29 @@ function handleStreamEvent(event, progressElement, progressId, getAssistantId, setAssistantId, getMcpIds, setMcpIds) { const timeline = document.getElementById(progressId + '-timeline'); if (!timeline) return; + + // 终态事件(error/cancelled)优先复用现有助手消息,避免重复追加相同报错 + const upsertTerminalAssistantMessage = (message, preferredMessageId = null) => { + const preferredIds = []; + if (preferredMessageId) preferredIds.push(preferredMessageId); + const existingAssistantId = typeof getAssistantId === 'function' ? getAssistantId() : null; + if (existingAssistantId && !preferredIds.includes(existingAssistantId)) { + preferredIds.push(existingAssistantId); + } + + for (const id of preferredIds) { + const element = document.getElementById(id); + if (element) { + updateAssistantBubbleContent(id, message, true); + setAssistantId(id); + return { assistantId: id, assistantElement: element }; + } + } + + const assistantId = addMessage('assistant', message, null, progressId); + setAssistantId(assistantId); + return { assistantId: assistantId, assistantElement: document.getElementById(assistantId) }; + }; switch (event.type) { case 'conversation': @@ -1033,47 +1056,19 @@ function handleStreamEvent(event, progressElement, progressId, finalizeProgressTask(progressId, typeof window.t === 'function' ? window.t('tasks.statusCancelled') : '已取消'); } - // 如果取消事件包含messageId,说明有助手消息,需要显示取消内容 - if (event.data && event.data.messageId) { - // 检查助手消息是否已存在 - let assistantId = event.data.messageId; - let assistantElement = document.getElementById(assistantId); - - // 如果助手消息不存在,创建它 - if (!assistantElement) { - assistantId = addMessage('assistant', event.message, null, progressId); - setAssistantId(assistantId); - assistantElement = document.getElementById(assistantId); - } else { - // 如果已存在,更新内容 - const bubble = assistantElement.querySelector('.message-bubble'); - if (bubble) { - bubble.innerHTML = escapeHtml(event.message).replace(/\n/g, '
'); - } - } - - // 将进度详情集成到工具调用区域(如果还没有) + // 复用已有助手消息(若有),避免终态事件重复插入消息 + { + const preferredMessageId = event.data && event.data.messageId ? event.data.messageId : null; + const { assistantId, assistantElement } = upsertTerminalAssistantMessage(event.message, preferredMessageId); if (assistantElement) { const detailsId = 'process-details-' + assistantId; if (!document.getElementById(detailsId)) { integrateProgressToMCPSection(progressId, assistantId, typeof getMcpIds === 'function' ? (getMcpIds() || []) : []); } - // 立即折叠详情(取消时应该默认折叠) setTimeout(() => { collapseAllProgressDetails(assistantId, progressId); }, 100); } - } else { - // 如果没有messageId,创建助手消息并集成详情 - const assistantId = addMessage('assistant', event.message, null, progressId); - setAssistantId(assistantId); - - // 将进度详情集成到工具调用区域 - setTimeout(() => { - integrateProgressToMCPSection(progressId, assistantId, typeof getMcpIds === 'function' ? (getMcpIds() || []) : []); - // 确保详情默认折叠 - collapseAllProgressDetails(assistantId, progressId); - }, 100); } // 立即刷新任务状态 @@ -1232,47 +1227,19 @@ function handleStreamEvent(event, progressElement, progressId, finalizeProgressTask(progressId, typeof window.t === 'function' ? window.t('tasks.statusFailed') : '执行失败'); } - // 如果错误事件包含messageId,说明有助手消息,需要显示错误内容 - if (event.data && event.data.messageId) { - // 检查助手消息是否已存在 - let assistantId = event.data.messageId; - let assistantElement = document.getElementById(assistantId); - - // 如果助手消息不存在,创建它 - if (!assistantElement) { - assistantId = addMessage('assistant', event.message, null, progressId); - setAssistantId(assistantId); - assistantElement = document.getElementById(assistantId); - } else { - // 如果已存在,更新内容 - const bubble = assistantElement.querySelector('.message-bubble'); - if (bubble) { - bubble.innerHTML = escapeHtml(event.message).replace(/\n/g, '
'); - } - } - - // 将进度详情集成到工具调用区域(如果还没有) + // 复用已有助手消息(若有),避免终态事件重复插入消息 + { + const preferredMessageId = event.data && event.data.messageId ? event.data.messageId : null; + const { assistantId, assistantElement } = upsertTerminalAssistantMessage(event.message, preferredMessageId); if (assistantElement) { const detailsId = 'process-details-' + assistantId; if (!document.getElementById(detailsId)) { integrateProgressToMCPSection(progressId, assistantId, typeof getMcpIds === 'function' ? (getMcpIds() || []) : []); } - // 立即折叠详情(错误时应该默认折叠) setTimeout(() => { collapseAllProgressDetails(assistantId, progressId); }, 100); } - } else { - // 如果没有messageId(比如任务已运行时的错误),创建助手消息并集成详情 - const assistantId = addMessage('assistant', event.message, null, progressId); - setAssistantId(assistantId); - - // 将进度详情集成到工具调用区域 - setTimeout(() => { - integrateProgressToMCPSection(progressId, assistantId, typeof getMcpIds === 'function' ? (getMcpIds() || []) : []); - // 确保详情默认折叠 - collapseAllProgressDetails(assistantId, progressId); - }, 100); } // 立即刷新任务状态(执行失败时任务状态会更新)