// @ts-nocheck import { debugLog } from './common'; export const historyMethods = { // ========================================== // 关键功能:获取并显示历史对话内容 // ========================================== async fetchAndDisplayHistory(options = {}) { const { force = false } = options as { force?: boolean }; const targetConversationId = this.currentConversationId; if (!targetConversationId || targetConversationId.startsWith('temp_')) { debugLog('没有当前对话ID,跳过历史加载'); this.refreshBlankHeroState(); return; } // 若同一对话正在加载,直接复用;若是切换对话则允许并发但后来的请求会赢 if (this.historyLoading && this.historyLoadingFor === targetConversationId) { debugLog('同一对话历史正在加载,跳过重复请求'); return; } // 已经有完整历史且非强制刷新时,避免重复加载导致动画播放两次 const alreadyHydrated = !force && this.lastHistoryLoadedConversationId === targetConversationId && Array.isArray(this.messages) && this.messages.length > 0; if (alreadyHydrated) { debugLog('历史已加载,跳过重复请求'); this.logMessageState('fetchAndDisplayHistory:skip-duplicate', { conversationId: targetConversationId }); return; } const loadSeq = ++this.historyLoadSeq; this.historyLoading = true; this.historyLoadingFor = targetConversationId; try { debugLog('开始获取历史对话内容...'); this.logMessageState('fetchAndDisplayHistory:start', { conversationId: this.currentConversationId }); try { // 使用专门的API获取对话消息历史 const messagesResponse = await fetch(`/api/conversations/${targetConversationId}/messages`); if (!messagesResponse.ok) { console.warn('无法获取消息历史,尝试备用方法'); // 备用方案:通过状态API获取 const statusResponse = await fetch('/api/status'); const status = await statusResponse.json(); debugLog('系统状态:', status); this.applyStatusSnapshot(status); // 如果状态中有对话历史字段 if (status.conversation_history && Array.isArray(status.conversation_history)) { this.renderHistoryMessages(status.conversation_history); return; } debugLog('备用方案也无法获取历史消息'); return; } // 如果在等待期间用户已切换到其他对话,则丢弃结果 if (loadSeq !== this.historyLoadSeq || this.currentConversationId !== targetConversationId) { debugLog('检测到对话已切换,丢弃过期的历史加载结果'); return; } const messagesData = await messagesResponse.json(); debugLog('获取到消息数据:', messagesData); if (messagesData.success && messagesData.data && messagesData.data.messages) { const messages = messagesData.data.messages; debugLog(`发现 ${messages.length} 条历史消息`); if (messages.length > 0) { // 清空当前显示的消息 this.logMessageState('fetchAndDisplayHistory:before-clear-existing'); this.messages = []; this.logMessageState('fetchAndDisplayHistory:after-clear-existing'); // 渲染历史消息 - 这是关键功能 this.renderHistoryMessages(messages); // 滚动到底部 this.$nextTick(() => { this.scrollToBottom(); }); debugLog('历史对话内容显示完成'); } else { debugLog('对话存在但没有历史消息'); this.logMessageState('fetchAndDisplayHistory:no-history-clear'); this.messages = []; this.logMessageState('fetchAndDisplayHistory:no-history-cleared'); } } else { debugLog('消息数据格式不正确:', messagesData); this.logMessageState('fetchAndDisplayHistory:invalid-data-clear'); this.messages = []; this.logMessageState('fetchAndDisplayHistory:invalid-data-cleared'); } } catch (error) { console.error('获取历史对话失败:', error); debugLog('尝试不显示错误弹窗,仅在控制台记录'); // 不显示alert,避免打断用户体验 this.logMessageState('fetchAndDisplayHistory:error-clear', { error: error?.message || String(error) }); this.messages = []; this.logMessageState('fetchAndDisplayHistory:error-cleared'); } } finally { // 仅在本次加载仍是最新请求时清除 loading 状态 if (loadSeq === this.historyLoadSeq) { this.historyLoading = false; this.historyLoadingFor = null; } this.refreshBlankHeroState(); } }, // ========================================== // 关键功能:渲染历史消息 // ========================================== renderHistoryMessages(historyMessages) { debugLog('开始渲染历史消息...', historyMessages); debugLog('历史消息数量:', historyMessages.length); this.logMessageState('renderHistoryMessages:start', { historyCount: historyMessages.length }); if (!Array.isArray(historyMessages)) { console.error('历史消息不是数组格式'); return; } let currentAssistantMessage = null; let historyHasImages = false; let historyHasVideos = false; historyMessages.forEach((message, index) => { debugLog(`处理消息 ${index + 1}/${historyMessages.length}:`, message.role, message); const meta = message.metadata || {}; if (message.role === 'user' && (meta.system_injected_image || meta.system_injected_video)) { debugLog('跳过系统代发的图片/视频消息(仅用于模型查看,不在前端展示)'); return; } if (message.role === 'user') { // 用户消息 - 先结束之前的assistant消息 if (currentAssistantMessage && currentAssistantMessage.actions.length > 0) { this.messages.push(currentAssistantMessage); currentAssistantMessage = null; } const images = message.images || (message.metadata && message.metadata.images) || []; const videos = message.videos || (message.metadata && message.metadata.videos) || []; if (Array.isArray(images) && images.length) { historyHasImages = true; } if (Array.isArray(videos) && videos.length) { historyHasVideos = true; } this.messages.push({ role: 'user', content: message.content || '', images, videos }); debugLog('添加用户消息:', message.content?.substring(0, 50) + '...'); } else if (message.role === 'assistant') { // AI消息 - 如果没有当前assistant消息,创建一个 if (!currentAssistantMessage) { currentAssistantMessage = { role: 'assistant', actions: [], streamingThinking: '', streamingText: '', currentStreamingType: null, activeThinkingId: null, awaitingFirstContent: false, generatingLabel: '' }; } const content = message.content || ''; const reasoningText = (message.reasoning_content || '').trim(); if (reasoningText) { const blockId = `history-thinking-${Date.now()}-${Math.random().toString(36).slice(2)}`; currentAssistantMessage.actions.push({ id: `history-think-${Date.now()}-${Math.random()}`, type: 'thinking', content: reasoningText, streaming: false, collapsed: true, timestamp: Date.now(), blockId }); debugLog('添加思考内容:', reasoningText.substring(0, 50) + '...'); } // 处理普通文本内容(移除思考标签后的内容) const metadata = message.metadata || {}; const appendPayloadMeta = metadata.append_payload; const modifyPayloadMeta = metadata.modify_payload; const isAppendMessage = message.name === 'append_to_file'; const isModifyMessage = message.name === 'modify_file'; const containsAppendMarkers = /<<<\s*(APPEND|MODIFY)/i.test(content || '') || /<<>>/i.test(content || ''); const textContent = content.trim(); if (appendPayloadMeta) { currentAssistantMessage.actions.push({ id: `history-append-payload-${Date.now()}-${Math.random()}`, type: 'append_payload', append: { path: appendPayloadMeta.path || '未知文件', forced: !!appendPayloadMeta.forced, success: appendPayloadMeta.success === undefined ? true : !!appendPayloadMeta.success, lines: appendPayloadMeta.lines ?? null, bytes: appendPayloadMeta.bytes ?? null }, timestamp: Date.now() }); debugLog('添加append占位信息:', appendPayloadMeta.path); } else if (modifyPayloadMeta) { currentAssistantMessage.actions.push({ id: `history-modify-payload-${Date.now()}-${Math.random()}`, type: 'modify_payload', modify: { path: modifyPayloadMeta.path || '未知文件', total: modifyPayloadMeta.total_blocks ?? null, completed: modifyPayloadMeta.completed || [], failed: modifyPayloadMeta.failed || [], forced: !!modifyPayloadMeta.forced, details: modifyPayloadMeta.details || [] }, timestamp: Date.now() }); debugLog('添加modify占位信息:', modifyPayloadMeta.path); } if (textContent && !appendPayloadMeta && !modifyPayloadMeta && !isAppendMessage && !isModifyMessage && !containsAppendMarkers) { currentAssistantMessage.actions.push({ id: `history-text-${Date.now()}-${Math.random()}`, type: 'text', content: textContent, streaming: false, timestamp: Date.now() }); debugLog('添加文本内容:', textContent.substring(0, 50) + '...'); } // 处理工具调用 if (message.tool_calls && Array.isArray(message.tool_calls)) { message.tool_calls.forEach((toolCall, tcIndex) => { let arguments_obj = {}; try { arguments_obj = typeof toolCall.function.arguments === 'string' ? JSON.parse(toolCall.function.arguments || '{}') : (toolCall.function.arguments || {}); } catch (e) { console.warn('解析工具参数失败:', e); arguments_obj = {}; } const action = { id: `history-tool-${toolCall.id || Date.now()}-${tcIndex}`, type: 'tool', tool: { id: toolCall.id, name: toolCall.function.name, arguments: arguments_obj, argumentSnapshot: this.cloneToolArguments(arguments_obj), argumentLabel: this.buildToolLabel(arguments_obj), intent_full: arguments_obj.intent || '', intent_rendered: arguments_obj.intent || '', status: 'preparing', result: null }, timestamp: Date.now() }; // 如果是历史加载的动作且状态仍为进行中,标记为 stale,避免刷新后按钮卡死 if (['preparing', 'running', 'awaiting_content'].includes(action.tool.status)) { action.tool.status = 'stale'; action.tool.awaiting_content = false; action.streaming = false; } currentAssistantMessage.actions.push(action); debugLog('添加工具调用:', toolCall.function.name); }); } } else if (message.role === 'tool') { // 工具结果 - 更新当前assistant消息中对应的工具 if (currentAssistantMessage) { // 查找对应的工具action - 使用更灵活的匹配 let toolAction = null; // 优先按tool_call_id匹配 if (message.tool_call_id) { toolAction = currentAssistantMessage.actions.find(action => action.type === 'tool' && action.tool.id === message.tool_call_id ); } // 如果找不到,按name匹配最后一个同名工具 if (!toolAction && message.name) { const sameNameTools = currentAssistantMessage.actions.filter(action => action.type === 'tool' && action.tool.name === message.name ); toolAction = sameNameTools[sameNameTools.length - 1]; // 取最后一个 } if (toolAction) { // 解析工具结果(优先使用JSON,其次使用元数据的 tool_payload,以保证搜索结果在刷新后仍可展示) let result; try { result = JSON.parse(message.content); } catch (e) { if (message.metadata && message.metadata.tool_payload) { result = message.metadata.tool_payload; } else { result = { output: message.content, success: true }; } } toolAction.tool.status = 'completed'; toolAction.tool.result = result; if (result && typeof result === 'object') { if (result.error) { toolAction.tool.message = result.error; } else if (result.message && !toolAction.tool.message) { toolAction.tool.message = result.message; } } if (message.name === 'append_to_file' && result && result.message) { toolAction.tool.message = result.message; } debugLog(`更新工具结果: ${message.name} -> ${message.content?.substring(0, 50)}...`); // append_to_file 的摘要在 append_payload 占位中呈现,此处无需重复 } else { console.warn('找不到对应的工具调用:', message.name, message.tool_call_id); } } } else { // 其他类型消息(如system)- 先结束当前assistant消息 if (currentAssistantMessage && currentAssistantMessage.actions.length > 0) { this.messages.push(currentAssistantMessage); currentAssistantMessage = null; } debugLog('处理其他类型消息:', message.role); this.messages.push({ role: message.role, content: message.content || '' }); } }); // 处理最后一个assistant消息 if (currentAssistantMessage && currentAssistantMessage.actions.length > 0) { this.messages.push(currentAssistantMessage); } this.conversationHasImages = historyHasImages; this.conversationHasVideos = historyHasVideos; debugLog(`历史消息渲染完成,共 ${this.messages.length} 条消息`); this.logMessageState('renderHistoryMessages:after-render'); this.lastHistoryLoadedConversationId = this.currentConversationId || null; // 强制更新视图 this.$forceUpdate(); // 确保滚动到底部 this.$nextTick(() => { this.scrollToBottom(); setTimeout(() => { const blockCount = this.$el && this.$el.querySelectorAll ? this.$el.querySelectorAll('.message-block').length : 'N/A'; debugLog('[Messages] DOM 渲染统计', { blocks: blockCount, conversationId: this.currentConversationId }); }, 0); }); } };