From d3c38977bcd1ece519523d79c4c3d1dcbd41892d Mon Sep 17 00:00:00 2001 From: thzxx Date: Thu, 23 Apr 2026 16:50:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20AI=E6=B6=88=E6=81=AF=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E6=88=B3=E6=98=BE=E7=A4=BA=E3=80=81=E5=B7=A5=E5=85=B7=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E5=8D=A1=E7=89=87=E6=81=A2=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 修复AI回复消息不显示时间戳的问题:updateLastAssistantMessage 新增 timestamp 参数 2. 恢复工具调用卡片显示(工具名称+参数,不显示执行结果):updateLastAssistantMessage 新增 toolCalls 参数 3. 根因:流式消息通过 updateLastAssistantMessage 更新 DOM,但该函数未渲染时间戳和工具卡片, 而 renderMessages 因 placeholder 已被计数而跳过 appendMessageDOM --- src/renderer/components/chat-area.ts | 44 ++++++++++++++++++++++++++- src/renderer/components/input-area.ts | 12 +++++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/renderer/components/chat-area.ts b/src/renderer/components/chat-area.ts index 725d663..51fb8f6 100644 --- a/src/renderer/components/chat-area.ts +++ b/src/renderer/components/chat-area.ts @@ -260,7 +260,10 @@ function renderToolCallCard(tc: ToolCallRecord): string { `; } -export function updateLastAssistantMessage(content: string, think: string | null, _stats: unknown, model?: string): void { +export function updateLastAssistantMessage( + content: string, think: string | null, _stats: unknown, model?: string, + timestamp?: number, toolCalls?: ToolCallRecord[] +): void { const lastMsg = currentPlaceholder; if (!lastMsg) return; @@ -307,6 +310,45 @@ export function updateLastAssistantMessage(content: string, think: string | null thinkBlock.querySelector('pre')!.textContent = think; } + // ── 工具调用历史记录(可折叠)── + if (toolCalls && toolCalls.length > 0) { + let existingHistory = lastMsg.querySelector('.tool-calls-history'); + if (existingHistory) existingHistory.remove(); + + const tcCount = toolCalls.length; + const successCount = toolCalls.filter(t => t.status === 'success').length; + const errorCount = toolCalls.filter(t => t.status === 'error').length; + + const historyDiv = document.createElement('div'); + historyDiv.className = 'tool-calls-history'; + historyDiv.innerHTML = ` +
+ + 🔧 ${tcCount} 个工具调用(✅${successCount} ❌${errorCount}) +
+
+ ${toolCalls.map(tc => renderToolCallCard(tc)).join('')} +
+ `; + const msgBody = lastMsg.querySelector('.msg-body'); + if (msgBody) { + const refNode = contentDiv?.nextSibling || null; + msgBody.insertBefore(historyDiv, refNode); + } + } + + // ── 时间戳 ── + if (timestamp) { + let statsDiv = lastMsg.querySelector('.msg-stats'); + if (!statsDiv) { + statsDiv = document.createElement('div'); + statsDiv.className = 'msg-stats'; + const msgBody = lastMsg.querySelector('.msg-body'); + if (msgBody) msgBody.appendChild(statsDiv); + } + statsDiv.innerHTML = `${formatTime(timestamp)}`; + } + scrollToBottom(); } diff --git a/src/renderer/components/input-area.ts b/src/renderer/components/input-area.ts index 17f47b8..36be12a 100644 --- a/src/renderer/components/input-area.ts +++ b/src/renderer/components/input-area.ts @@ -356,7 +356,7 @@ async function handleRetry(): Promise { ...s, messages: [...s.messages, lastMsg], updatedAt: Date.now() })); } - updateLastAssistantMessage(finalContent, retryThinkContent || null, loopStats || null); + updateLastAssistantMessage(finalContent, retryThinkContent || null, loopStats || null, undefined, Date.now(), toolRecords?.length ? toolRecords : undefined); } else { const assistantMsg: ChatMessage = { role: 'assistant', content: finalContent || '', timestamp: Date.now(), @@ -369,7 +369,7 @@ async function handleRetry(): Promise { state.update(KEYS.CURRENT_SESSION, (s: ChatSession | null) => ({ ...s, messages: [...s.messages, assistantMsg], updatedAt: Date.now() })); - updateLastAssistantMessage(finalContent, retryThinkContent || null, loopStats || null); + updateLastAssistantMessage(finalContent, retryThinkContent || null, loopStats || null, undefined, Date.now(), toolRecords?.length ? toolRecords : undefined); } renderMessages(); await saveCurrentSession(); @@ -749,7 +749,9 @@ export async function sendMessage(): Promise { })); if (finalStats) { - updateLastAssistantMessage(assistantContent, thinkContent || null, finalStats, modelName || undefined); + updateLastAssistantMessage(assistantContent, thinkContent || null, finalStats, modelName || undefined, Date.now()); + } else { + updateLastAssistantMessage(assistantContent, thinkContent || null, null, modelName || undefined, Date.now()); } await saveCurrentSession(); @@ -1067,7 +1069,7 @@ async function sendMessageWithAgentLoop(text: string, currentSession: ChatSessio updatedAt: Date.now() })); } - updateLastAssistantMessage(assistantContent, thinkContent || null, loopStats || null); + updateLastAssistantMessage(assistantContent, thinkContent || null, loopStats || null, undefined, Date.now(), toolRecords?.length ? toolRecords : undefined); } else { // 单迭代模式:正常保存 const assistantMsg: ChatMessage = { @@ -1085,7 +1087,7 @@ async function sendMessageWithAgentLoop(text: string, currentSession: ChatSessio messages: [...session.messages, assistantMsg], updatedAt: Date.now() })); - updateLastAssistantMessage(assistantContent, thinkContent || null, loopStats || null); + updateLastAssistantMessage(assistantContent, thinkContent || null, loopStats || null, undefined, Date.now(), toolRecords?.length ? toolRecords : undefined); } renderMessages(); await saveCurrentSession();