// 工具增强显示的渲染函数 export function escapeHtml(text: string): string { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } export function formatBytes(bytes: number): string { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i]; } function formatDuration(seconds: number): string { if (seconds <= 0) return '0 秒'; if (seconds < 60) return `${seconds} 秒`; const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; if (minutes < 60) { return remainingSeconds > 0 ? `${minutes} 分 ${remainingSeconds} 秒` : `${minutes} 分`; } const hours = Math.floor(minutes / 60); const remainingMinutes = minutes % 60; if (remainingMinutes === 0 && remainingSeconds === 0) { return `${hours} 小时`; } return `${hours} 小时 ${remainingMinutes} 分 ${remainingSeconds} 秒`; } function formatToolStatusLabel(result: any, successLabel: string, failedLabel = '✗ 失败'): string { const state = String(result?.status || '').toLowerCase(); if (state === 'awaiting_user_answer') { return '等待回答'; } if (state === 'awaiting_approval' || state === 'pending_approval' || state === 'pending') { return '待审批'; } if (state === 'rejected') { return '✗ 已拒绝'; } if (state === 'cancelled') { return '✗ 已取消'; } return result?.success ? successLabel : failedLabel; } export function renderEnhancedToolResult( action: any, formatSearchTopic: (filters: Record) => string, formatSearchTime: (filters: Record) => string, formatSearchDomains: (filters: Record) => string ): string { const tool = action.tool; const result = tool?.result; const args = tool?.arguments || {}; const name = tool?.name; if (!result) { return ''; } // 网络检索类 if (name === 'web_search') { return renderWebSearch(result, args, formatSearchTopic, formatSearchTime, formatSearchDomains); } else if (name === 'extract_webpage') { return renderExtractWebpage(result, args); } else if (name === 'save_webpage') { return renderSaveWebpage(result, args); } // 文件编辑类 else if (name === 'create_file' || name === 'create_folder') { return renderCreateFile(result, args); } else if (name === 'write_file') { return renderWriteFile(result, args); } else if (name === 'edit_file') { return renderEditFile(result, args); } else if (name === 'delete_file') { return renderDeleteFile(result, args); } else if (name === 'rename_file') { return renderRenameFile(result, args); } // 阅读聚焦 / Skills 类 else if (name === 'read_file' || name === 'read_skill') { return renderReadFile(result, args); } else if (name === 'create_skill') { return renderCreateSkill(result, args); } else if (name === 'vlm_analyze') { return renderVlmAnalyze(result, args); } else if (name === 'ocr_image') { return renderOcrImage(result, args); } else if (name === 'view_image') { return renderViewImage(result, args); } // 终端类 else if (name === 'terminal_session') { return renderTerminalSession(result, args); } else if (name === 'terminal_input') { return renderTerminalInput(result, args); } else if (name === 'terminal_snapshot') { return renderTerminalSnapshot(result, args); } else if (name === 'sleep') { return renderSleep(result, args); } // 终端指令类 else if (name === 'run_command') { return renderRunCommand(result, args); } // 记忆类 else if (name === 'update_memory') { return renderUpdateMemory(result, args); } else if (name === 'recall_project_memory') { return renderRecallProjectMemory(result, args); } else if (name === 'update_project_memory') { return renderUpdateProjectMemory(result, args); } else if (name === 'conversation_search') { return renderConversationSearch(result, args); } else if (name === 'conversation_review') { return renderConversationReview(result, args); } // 用户沟通类 else if (name === 'ask_user') { return renderAskUser(result, args); } // 个性化管理类 else if (name === 'manage_personalization') { return renderManagePersonalization(result, args); } // 待办事项类 else if (name === 'todo_create') { return renderTodoCreate(result, args); } else if (name === 'todo_update_task') { return renderTodoUpdate(result); } // 彩蛋类 else if (name === 'trigger_easter_egg') { return renderEasterEgg(result, args); } // 子智能体类 else if (name === 'create_sub_agent') { return renderCreateSubAgent(result, args); } else if (name === 'terminate_sub_agent') { return renderTerminateSubAgent(result, args); } else if (name === 'get_sub_agent_status') { return renderGetSubAgentStatus(result, args); } return ''; } // 网络检索类渲染函数 function renderWebSearch( result: any, args: any, formatSearchTopic: (filters: Record) => string, formatSearchTime: (filters: Record) => string, formatSearchDomains: (filters: Record) => string ): string { const query = result.query || args.query || ''; const filters = result.filters || {}; const totalResults = result.total_results || 0; const results = result.results || []; let html = '
'; html += `
搜索内容:${escapeHtml(query)}
`; html += `
主题:${escapeHtml(formatSearchTopic(filters))}
`; html += `
时间范围:${escapeHtml(formatSearchTime(filters))}
`; html += `
限定网站:${escapeHtml(formatSearchDomains(filters))}
`; html += `
结果数量:${totalResults}
`; html += '
'; if (results.length > 0) { html += '
'; results.forEach((item: any) => { html += '
'; html += `
${escapeHtml(item.title || '无标题')}
`; html += '
'; if (item.url) { html += `${escapeHtml(item.url)}`; } else { html += '无可用链接'; } html += '
'; }); html += '
'; } else { html += '
未返回详细的搜索结果。
'; } return html; } function renderExtractWebpage(result: any, args: any): string { const url = args.url || result.url || ''; const status = formatToolStatusLabel(result, '✓ 成功'); const content = result.content || result.text || ''; let html = '
'; html += `
URL:${escapeHtml(url)}
`; html += `
状态:${status}
`; html += '
'; if (content) { html += '
'; html += `
${escapeHtml(content)}
`; html += '
'; } return html; } function renderSaveWebpage(result: any, args: any): string { const url = args.url || result.url || ''; const path = result.path || args.save_path || ''; const status = formatToolStatusLabel(result, '✓ 已保存'); let html = '
'; html += `
URL:${escapeHtml(url)}
`; html += `
保存路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; html += '
'; return html; } // 文件编辑类渲染函数 function renderCreateFile(result: any, args: any): string { const path = args.path || result.path || ''; const status = formatToolStatusLabel(result, '✓ 已创建'); let html = '
'; html += `
路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; html += '
'; return html; } function renderWriteFile(result: any, args: any): string { const path = args.file_path || args.path || result.path || ''; const status = formatToolStatusLabel(result, '✓ 已写入'); const appendFlag = typeof args.append === 'boolean' ? args.append : null; const modeRaw = String(result.mode || '').toLowerCase(); const writeMode = appendFlag === true || modeRaw === 'a' ? '追加' : appendFlag === false || modeRaw === 'w' ? '覆盖' : '无'; const content = appendFlag === true || modeRaw === 'a' ? args.content || '' : (result.new_file ?? args.content ?? ''); let html = '
'; html += `
路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; html += `
模式:${writeMode}
`; if (!result.success && result.error) { html += `
错误:${escapeHtml(String(result.error))}
`; } html += '
'; // 显示写入的内容 if (result.success && content) { html += '
'; const lines = content.split('\n'); lines.forEach((line: string, idx: number) => { html += `
${idx + 1}+${escapeHtml(line)}
`; }); html += '
'; } return html; } function renderEditFile(result: any, args: any): string { const path = args.file_path || args.path || result.path || ''; const status = formatToolStatusLabel(result, '✓ 已编辑'); const foundCount = typeof result.found_matches === 'number' ? result.found_matches : typeof result.replacements === 'number' ? result.replacements : null; const replacedCount = typeof result.replacements === 'number' ? result.replacements : null; const details = Array.isArray(result.details) ? result.details.filter((d: any) => d && d.status === 'success') : []; let html = '
'; html += `
路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; html += `
替换组数:${(result.replacement_groups ?? details.length) || '无'}
`; html += `
找到:${foundCount ?? '无'}处
`; html += `
替换:${replacedCount ?? '无'}处
`; if (!result.success && result.error) { html += `
错误:${escapeHtml(String(result.error))}
`; } html += '
'; if (!result.success) { return html; } if (details.length > 0) { html += '
'; const renderDiffLine = (lineNo: number | null, marker: string, text: string, className = '') => { const lineNoText = typeof lineNo === 'number' && Number.isFinite(lineNo) ? String(lineNo) : ''; html += `
${escapeHtml(lineNoText)}${escapeHtml(marker)}${escapeHtml(text)}
`; }; const hunks: any[] = []; details.forEach((detail: any) => { const oldText = detail.old_string || ''; const newText = detail.new_string || ''; const contexts = Array.isArray(detail.contexts) ? detail.contexts : []; const oldLines = oldText ? oldText.split('\n') : []; const newLines = newText ? newText.split('\n') : []; const buildPairRows = (context?: any) => { const rows: any[] = []; const startLineCandidate = Number(context?.old_start_line ?? detail.matched_lines?.[0]); const startLine = Number.isFinite(startLineCandidate) ? startLineCandidate : null; if (oldText) { oldLines.forEach((line: string, lineIdx: number) => { rows.push({ lineNo: startLine === null ? null : startLine + lineIdx, marker: '-', text: line, className: 'diff-remove' }); }); } if (newText) { newLines.forEach((line: string, lineIdx: number) => { rows.push({ lineNo: startLine === null ? null : startLine + lineIdx, marker: '+', text: line, className: 'diff-add' }); }); } return rows; }; if (contexts.length > 0) { contexts.forEach((context: any) => { const rows: any[] = []; const rawBeforeLines = Array.isArray(context.before_lines) ? context.before_lines : []; const rawAfterLines = Array.isArray(context.after_lines) ? context.after_lines : []; const beforeLines = rawBeforeLines.length >= 2 && rawBeforeLines.every((item: any) => String(item?.text ?? '') === '') ? [] : rawBeforeLines.length >= 2 && String(rawBeforeLines[0]?.text ?? '') === '' ? rawBeforeLines.slice(1) : rawBeforeLines; const afterLines = rawAfterLines.length >= 2 && rawAfterLines.every((item: any) => String(item?.text ?? '') === '') ? [] : rawAfterLines.length >= 2 && String(rawAfterLines[rawAfterLines.length - 1]?.text ?? '') === '' ? rawAfterLines.slice(0, -1) : rawAfterLines; const contextOldStartLine = Number(context?.old_start_line ?? detail.matched_lines?.[0]); const contextOldEndLine = Number(context?.old_end_line ?? contextOldStartLine); const oldLineCount = Number.isFinite(contextOldStartLine) && Number.isFinite(contextOldEndLine) ? Math.max(1, contextOldEndLine - contextOldStartLine + 1) : Math.max(1, (oldText ? oldText.split('\n').length : 1)); const newLineCount = newText === '' ? 0 : newText.split('\n').length; const afterContextOffset = newLineCount - oldLineCount; beforeLines.forEach((item: any) => { rows.push({ lineNo: Number(item.line), marker: ' ', text: String(item.text ?? ''), className: '' }); }); rows.push(...buildPairRows(context)); afterLines.forEach((item: any) => { const rawLineNo = Number(item.line); const lineNo = Number.isFinite(rawLineNo) ? rawLineNo + afterContextOffset : rawLineNo; rows.push({ lineNo, marker: ' ', text: String(item.text ?? ''), className: '' }); }); const numberedRows = rows.filter((row) => typeof row.lineNo === 'number' && Number.isFinite(row.lineNo)); hunks.push({ rows, minLine: numberedRows.length ? Math.min(...numberedRows.map((row) => row.lineNo)) : null, maxLine: numberedRows.length ? Math.max(...numberedRows.map((row) => row.lineNo)) : null, }); }); } else { const rows = buildPairRows(); const numberedRows = rows.filter((row) => typeof row.lineNo === 'number' && Number.isFinite(row.lineNo)); hunks.push({ rows, minLine: numberedRows.length ? Math.min(...numberedRows.map((row) => row.lineNo)) : null, maxLine: numberedRows.length ? Math.max(...numberedRows.map((row) => row.lineNo)) : null, }); } }); const sortedHunks = hunks.sort((a, b) => (a.minLine ?? Number.MAX_SAFE_INTEGER) - (b.minLine ?? Number.MAX_SAFE_INTEGER)); const mergedHunks: any[] = []; sortedHunks.forEach((hunk) => { const last = mergedHunks[mergedHunks.length - 1]; if (last && hunk.minLine !== null && last.maxLine !== null && hunk.minLine <= last.maxLine + 1) { last.rows.push(...hunk.rows); last.maxLine = Math.max(last.maxLine, hunk.maxLine ?? last.maxLine); } else { mergedHunks.push({ ...hunk, rows: [...hunk.rows] }); } }); const markerOrder: Record = { ' ': 0, '-': 1, '+': 2 }; mergedHunks.forEach((hunk, hunkIdx) => { if (hunkIdx > 0) renderDiffLine(null, ' ', '⋮', 'diff-separator'); const seenContextLines = new Set(); const filteredRows = hunk.rows .filter((row: any) => { if (row.marker !== ' ' || typeof row.lineNo !== 'number') return true; if (seenContextLines.has(row.lineNo)) return false; seenContextLines.add(row.lineNo); return true; }) .sort((a: any, b: any) => { const aIsChange = a.marker === '-' || a.marker === '+'; const bIsChange = b.marker === '-' || b.marker === '+'; // 仅变更行之间优先按 marker 分组(- 在前 + 在后),再按行号 if (aIsChange && bIsChange) { const markerDelta = (markerOrder[a.marker] ?? 9) - (markerOrder[b.marker] ?? 9); return markerDelta || (a.lineNo ?? Number.MAX_SAFE_INTEGER) - (b.lineNo ?? Number.MAX_SAFE_INTEGER); } // 上下文行或跨类型:按行号优先 const lineDelta = (a.lineNo ?? Number.MAX_SAFE_INTEGER) - (b.lineNo ?? Number.MAX_SAFE_INTEGER); return lineDelta || (markerOrder[a.marker] ?? 9) - (markerOrder[b.marker] ?? 9); }); filteredRows.forEach((row: any) => renderDiffLine(row.lineNo, row.marker, row.text, row.className)); }); html += '
'; } return html; } function renderDeleteFile(result: any, args: any): string { const path = args.path || result.path || ''; const status = formatToolStatusLabel(result, '✓ 已删除'); let html = '
'; html += `
路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; html += '
'; return html; } function renderRenameFile(result: any, args: any): string { const oldPath = args.old_path || args.source || result.old_path || ''; const newPath = args.new_path || args.destination || result.new_path || ''; const status = formatToolStatusLabel(result, '✓ 已重命名'); let html = '
'; html += `
路径:${escapeHtml(oldPath)}
`; html += `
状态:${status}
`; html += `
重命名:${escapeHtml(oldPath)} → ${escapeHtml(newPath)}
`; html += '
'; return html; } // 阅读聚焦类渲染函数 function renderReadFile(result: any, args: any): string { const path = args.path || result.path || ''; const status = formatToolStatusLabel(result, '✓ 成功'); const size = result.size || result.file_size || 0; const readType = result.type || 'read'; let html = '
'; html += `
路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; if (size > 0) { html += `
大小:${formatBytes(size)}
`; } if (readType !== 'read') { html += `
模式:${escapeHtml(readType)}
`; } html += '
'; // 处理普通读取模式 if (readType === 'read') { const content = result.content || result.text || ''; if (content) { html += '
'; html += `
${escapeHtml(content)}
`; html += '
'; } } // 处理搜索模式 else if (readType === 'search') { const matches = result.matches || []; const query = result.query || args.query || ''; if (query) { html += '
'; html += `
搜索关键词:${escapeHtml(query)}
`; html += `
匹配数量:${matches.length}
`; html += '
'; } if (matches.length > 0) { html += '
'; matches.forEach((match: any, idx: number) => { if (idx > 0) html += '
'; html += '
'; const lineLabel = match.line_start === match.line_end ? `${match.line_start}` : `${match.line_start}-${match.line_end}`; html += `
行 ${lineLabel}
`; html += `
${escapeHtml(match.snippet || match.content || '')}
`; html += '
'; }); html += '
'; } else { html += '
未找到匹配内容
'; } } // 处理提取模式 else if (readType === 'extract') { const segments = result.segments || []; if (segments.length > 0) { html += '
'; html += `
提取片段数:${segments.length}
`; html += '
'; html += '
'; segments.forEach((segment: any, idx: number) => { if (idx > 0) html += '
'; html += '
'; const startLine = segment.start_line || segment.line_start || '?'; const endLine = segment.end_line || segment.line_end || '?'; html += `
行 ${startLine}-${endLine}
`; html += `
${escapeHtml(segment.content || segment.text || '')}
`; html += '
'; }); html += '
'; } else { html += '
未提取到内容
'; } } return html; } function renderVlmAnalyze(result: any, args: any): string { const path = args.image_path || args.path || result.path || ''; const status = formatToolStatusLabel(result, '✓ 成功'); const analysis = result.analysis || result.result || ''; let html = '
'; html += `
路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; html += '
'; if (analysis) { html += '
'; html += ''; html += `
${escapeHtml(analysis)}
`; html += '
'; } return html; } function renderOcrImage(result: any, args: any): string { const path = args.image_path || args.path || result.path || ''; const status = formatToolStatusLabel(result, '✓ 成功'); const size = result.size || result.file_size || 0; const text = result.text || result.ocr_text || ''; const imageUrl = result.image_url || result.url || ''; let html = '
'; html += `
路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; if (size > 0) { html += `
大小:${formatBytes(size)}
`; } html += '
'; if (imageUrl) { html += `
OCR图片
`; } if (text) { html += '
'; html += ''; html += `
${escapeHtml(text)}
`; html += '
'; } return html; } function renderViewImage(result: any, args: any): string { const path = args.image_path || args.path || result.path || ''; const status = formatToolStatusLabel(result, '✓ 成功'); const size = result.size || result.file_size || 0; const imageUrl = result.image_url || result.url || ''; let html = '
'; html += `
路径:${escapeHtml(path)}
`; html += `
状态:${status}
`; if (size > 0) { html += `
大小:${formatBytes(size)}
`; } html += '
'; if (imageUrl) { html += `
查看图片
`; } return html; } // 终端类渲染函数 function renderTerminalSession(result: any, args: any): string { const operation = args.operation || args.action || 'start'; const sessionName = args.session_name || args.name || result.session_name || ''; const status = formatToolStatusLabel(result, '✓ 成功'); let html = '
'; html += `
操作:${escapeHtml(operation)}
`; html += `
终端名:${escapeHtml(sessionName)}
`; html += `
状态:${status}
`; html += '
'; return html; } function renderTerminalInput(result: any, args: any): string { const command = args.command || args.input || ''; const outputWait = args.output_wait || 30; const output = result.output || result.result || ''; let html = '
'; html += `
指令:${escapeHtml(command)}
`; html += `
等待时间:${outputWait}秒
`; html += '
'; if (output) { html += '
'; html += ''; html += `
${escapeHtml(output)}
`; html += '
'; } return html; } function renderTerminalSnapshot(result: any, args: any): string { const sessionName = args.session_name || args.name || result.session_name || ''; const status = formatToolStatusLabel(result, '✓ 成功'); const startLine = args.start_line || 0; const endLine = args.end_line || 0; const content = result.content || result.output || ''; let html = '
'; html += `
状态:${status}
`; html += `
终端名:${escapeHtml(sessionName)}
`; if (startLine || endLine) { html += `
行范围:${startLine} - ${endLine}
`; } html += '
'; if (content) { html += '
'; html += ''; html += `
${escapeHtml(content)}
`; html += '
'; } return html; } function renderSleep(result: any, args: any): string { const seconds = args.seconds || args.duration || 0; const status = formatToolStatusLabel(result, '✓ 完成'); let html = '
'; html += `
等待时间:${seconds}秒
`; html += `
状态:${status}
`; html += '
'; return html; } // 终端指令类渲染函数 function renderRunCommand(result: any, args: any): string { const command = args.command || ''; const timeout = args.timeout || 30; const output = result.output || result.stdout || ''; const exitCode = result.exit_code !== undefined ? result.exit_code : result.returncode; let html = '
'; html += `
指令:${escapeHtml(command)}
`; html += `
超时时间:${timeout}秒
`; if (exitCode !== undefined) { html += `
退出码:${exitCode}
`; } html += '
'; if (output) { html += '
'; html += ''; html += `
${escapeHtml(output)}
`; html += '
'; } return html; } // 记忆类渲染函数 function renderUpdateMemory(result: any, args: any): string { const operation = args.operation || result.operation || ''; const content = args.content || ''; const index = args.index || result.index; const count = result.count || 0; let html = '
'; if (operation === 'append') { html += `
新增记忆
`; html += `
${count}. ${escapeHtml(content)}
`; } else if (operation === 'replace') { html += `
更新记忆
`; html += `
${index}. ${escapeHtml(content)}
`; } else if (operation === 'delete') { html += `
删除记忆
`; html += `
${index}. ${escapeHtml(content || '已删除')}
`; } html += '
'; return html; } function renderRecallProjectMemory(result: any, args: any): string { const name = args.name || result.memory_name || ''; const status = formatToolStatusLabel(result, '✓ 已读取'); const content = result.content || result.text || ''; let html = '
'; html += `
状态:${status}
`; html += `
记忆:${escapeHtml(name)}
`; html += '
'; if (result.success && content) { html += '
'; html += `
${escapeHtml(content)}
`; html += '
'; } else if (!result.success && result.error) { html += `
${escapeHtml(String(result.error))}
`; } return html; } function renderUpdateProjectMemory(result: any, args: any): string { const name = args.name || result.memory_name || ''; const description = args.description || ''; const content = args.content || ''; const status = formatToolStatusLabel(result, '✓ 已更新'); let html = '
'; html += `
状态:${status}
`; html += `
记忆:${escapeHtml(name)}
`; if (description) { html += `
描述:${escapeHtml(description)}
`; } if (!result.success && result.error) { html += `
错误:${escapeHtml(String(result.error))}
`; } html += '
'; if (result.success && content) { html += '
'; html += ''; html += `
${escapeHtml(content)}
`; html += '
'; } return html; } function renderConversationSearch(result: any, args: any): string { const results = Array.isArray(result?.results) ? result.results : []; const keywords = Array.isArray(result?.keywords) ? result.keywords : (Array.isArray(args?.keywords) ? args.keywords : []); const keywordText = keywords.length ? keywords.join(' / ') : (result?.query || args?.query || '(未指定)'); let html = '
'; html += `
关键词:${escapeHtml(keywordText)}
`; html += `
日期范围:${escapeHtml(result?.start_date || args?.start_date || '不限')} ~ ${escapeHtml(result?.end_date || args?.end_date || '不限')}
`; html += '
范围:当前工作区历史对话(已排除当前对话)
'; html += `
结果数量:${results.length}
`; html += '
'; if (!results.length) { html += '
未找到匹配对话。
'; return html; } html += '
'; results.forEach((item: any) => { html += '
'; html += `
${escapeHtml(item.title || '未命名对话')}
`; html += `
ID:${escapeHtml(item.id || '')}
`; html += `
规模:${escapeHtml(String(item.total_messages || 0))} 条消息,${escapeHtml(String(item.total_tools || 0))} 个工具
`; if (item.first_user_message) { html += `
首条用户消息:${escapeHtml(item.first_user_message)}
`; } if (item.updated_at) { html += `
更新时间:${escapeHtml(item.updated_at)}
`; } html += '
'; }); html += '
'; return html; } function renderConversationReview(result: any, args: any): string { const status = formatToolStatusLabel(result, result?.mode === 'read' ? '✓ 已返回' : '✓ 已生成'); let html = '
'; html += `
对话 ID:${escapeHtml(result?.conversation_id || args?.conversation_id || '')}
`; html += `
状态:${status}
`; html += `
模式:${escapeHtml(result?.mode || args?.mode || '')}
`; if (result?.title) { html += `
标题:${escapeHtml(result.title)}
`; } if (result?.path) { html += `
回顾文件:${escapeHtml(result.path)}
`; } if (result?.char_count !== undefined) { html += `
字符数:${escapeHtml(String(result.char_count))}
`; } html += '
'; if (!result?.success && result?.error) { html += `
${escapeHtml(result.error)}
`; } if (result?.too_long && result?.path) { html += '
内容太长,已保存到文件,请分段或查找阅读。
'; } if (result?.content) { html += '
'; html += ''; html += `
${escapeHtml(result.content)}
`; html += '
'; } return html; } function renderCreateSkill(result: any, args: any): string { const status = formatToolStatusLabel(result, '✓ 已归档'); let html = '
'; html += `
状态:${status}
`; if (result?.skill_name) { html += `
Skill:${escapeHtml(result.skill_name)}
`; } html += '
'; if (!result?.success && result?.error) { html += `
${escapeHtml(result.error)}
`; } if (result?.sync_warning) { html += `
${escapeHtml(result.sync_warning)}
`; } return html; } function formatPersonalizationFieldLabel(field: string): string { const labelMap: Record = { self_identify: 'AI 自称', user_name: '用户称呼', profession: '用户职业', tone: '交流语气', considerations: '注意事项', theme: '主题', communication_style: '交流风格', conversation_continuity: '对话连续性', enabled: '个性化开关' }; return labelMap[field] || field; } function formatPersonalizationFieldValue(field: string, value: any): string { if (value === null || value === undefined || value === '') { return '未设置'; } if (field === 'enabled') { return value ? '开启' : '关闭'; } if (field === 'considerations') { if (!Array.isArray(value) || value.length === 0) { return '未设置'; } return value.map((item) => String(item)).join('、'); } if (field === 'communication_style') { const styleMap: Record = { default: 'default(标准 AI 风格)', human_like: 'human_like(拟人聊天风格)', auto: 'auto(自动)' }; return styleMap[String(value)] || String(value); } if (field === 'conversation_continuity') { const independenceMap: Record = { low: 'low(低)', medium: 'medium(中)', high: 'high(高)' }; return independenceMap[String(value)] || String(value); } return String(value); } function renderAskUser(result: any, args: any): string { const question = args.question || result.question || ''; const context = args.context || result.context || ''; const status = formatToolStatusLabel(result, '✓ 已回答'); const answerText = result.status === 'answered' ? String(result.answer_text || result.message || '').trim() : ''; let html = '
'; html += `
状态:${escapeHtml(status)}
`; if (question) { html += `
问题:${escapeHtml(String(question))}
`; } if (context) { html += `
说明:${escapeHtml(String(context))}
`; } html += '
'; const options = Array.isArray(args.options) ? args.options : []; if (options.length > 0) { html += '
'; html += '
'; html += '
提供的选项:
'; options.forEach((option: any, idx: number) => { const label = String(option?.label || option?.id || `选项 ${idx + 1}`); const desc = String(option?.description || '').trim(); html += `
${idx + 1}. ${escapeHtml(label)}${desc ? ` — ${escapeHtml(desc)}` : ''}
`; }); html += '
'; } if (answerText) { html += '
'; html += '
'; answerText.split('\n').map((line) => line.trim()).filter(Boolean).forEach((line) => { const separator = line.indexOf(':'); if (separator > 0) { const label = line.slice(0, separator + 1); const value = line.slice(separator + 1); html += `
${escapeHtml(label)}${escapeHtml(value)}
`; } else { html += `
用户回答:${escapeHtml(line)}
`; } }); html += '
'; } return html; } function renderManagePersonalization(result: any, args: any): string { const action = String(args.action || result.action || 'read'); const status = formatToolStatusLabel(result, action === 'update' ? '✓ 已更新' : '✓ 已读取'); const field = String(result.updated_field || args.field || ''); const newValue = result.updated_value ?? args.value; let html = '
'; html += `
操作:${escapeHtml(action === 'update' ? '更新配置' : '读取配置')}
`; html += `
状态:${status}
`; if (!result?.success) { if (result?.error) { html += `
错误:${escapeHtml(String(result.error))}
`; } if (Array.isArray(result?.validation_errors) && result.validation_errors.length > 0) { html += `
校验:${escapeHtml(result.validation_errors.join(';'))}
`; } html += '
'; return html; } if (action === 'update' && field) { html += `
修改项:${escapeHtml(formatPersonalizationFieldLabel(field))}
`; html += `
修改后:${escapeHtml(formatPersonalizationFieldValue(field, newValue))}
`; } html += ''; return html; } // 待办事项类渲染函数 function renderTodoCreate(result: any, args: any): string { const status = formatToolStatusLabel(result, '✓ 已创建'); const todoList = result.todo_list || {}; const title = todoList.title || args.title || ''; const tasks = todoList.tasks || args.tasks || []; let html = '
'; html += `
状态:${status}
`; html += `
标题:${escapeHtml(title)}
`; html += '
'; if (tasks.length > 0) { html += '
'; html += '
'; tasks.forEach((task: any) => { const taskText = typeof task === 'string' ? task : task.text || task.title || task.content || ''; html += `
${escapeHtml(taskText)}
`; }); html += '
'; html += '
'; } return html; } function renderTodoUpdate(result: any): string { const status = formatToolStatusLabel(result, '✓ 已更新'); const todoList = result.todo_list || {}; const title = todoList.title || ''; const tasks = todoList.tasks || []; let html = '
'; html += `
状态:${status}
`; html += `
标题:${escapeHtml(title)}
`; html += '
'; if (tasks.length > 0) { html += '
'; html += '
'; tasks.forEach((task: any) => { const taskText = typeof task === 'string' ? task : task.text || task.title || task.content || ''; const completed = typeof task === 'object' && (task.status === 'done' || task.completed || task.done || task.checked); html += `
${escapeHtml(taskText)}
`; }); html += '
'; html += '
'; } return html; } // 彩蛋类渲染函数 function renderEasterEgg(result: any, args: any): string { const status = formatToolStatusLabel(result, '✓ 已触发'); const type = result.type || args.type || ''; const content = result.content || result.message || ''; let html = '
'; html += `
状态:${status}
`; html += `
类型:${escapeHtml(type)}
`; html += '
'; if (content) { html += '
'; html += `
${escapeHtml(content)}
`; html += '
'; } return html; } // 子智能体类渲染函数 function renderCreateSubAgent(result: any, args: any): string { const status = formatToolStatusLabel(result, '✓ 已创建', '✗ 创建失败'); const agentId = result.agent_id ?? args.agent_id ?? ''; const taskId = result.task_id ?? ''; const deliverablesDir = result.deliverables_dir ?? ''; const taskDescription = args.task ?? ''; const message = result.message ?? result.summary ?? ''; const stats = result.stats || {}; const runtimeSeconds = result.runtime_seconds ?? result.elapsed_seconds ?? stats.runtime_seconds ?? 0; const apiCalls = stats.api_calls ?? stats.turn_count ?? 0; const toolCount = (stats.files_read || 0) + (stats.write_files || 0) + (stats.edit_files || 0) + (stats.searches || 0) + (stats.web_pages || 0) + (stats.commands || 0); const hasStats = runtimeSeconds > 0 || apiCalls > 0 || toolCount > 0; let html = '
'; html += `
状态:${status}
`; if (agentId !== '') { html += `
子智能体 ID:${escapeHtml(String(agentId))}
`; } if (taskId !== '') { html += `
任务 ID:${escapeHtml(String(taskId))}
`; } if (deliverablesDir !== '') { html += `
交付目录:${escapeHtml(String(deliverablesDir))}
`; } if (taskDescription) { const preview = String(taskDescription).slice(0, 200); const suffix = String(taskDescription).length > 200 ? '…' : ''; html += `
任务:${escapeHtml(preview + suffix)}
`; } html += '
'; if (message || hasStats) { html += '
'; if (hasStats) { html += ''; if (runtimeSeconds > 0) { html += `
工作时间:${formatDuration(runtimeSeconds)}
`; } if (apiCalls > 0) { html += `
调用次数:${apiCalls} 次
`; } if (toolCount > 0) { html += `
工具次数:${toolCount} 次
`; } } if (message) { if (hasStats) { html += ''; } html += `
${escapeHtml(String(message))}
`; } html += '
'; } return html; } function renderTerminateSubAgent(result: any, args: any): string { const status = formatToolStatusLabel(result, '✓ 已关闭', '✗ 关闭失败'); const agentId = result.agent_id ?? args.agent_id ?? ''; const taskId = result.task_id ?? ''; const message = result.message ?? result.system_message ?? ''; let html = '
'; html += `
状态:${status}
`; if (agentId !== '') { html += `
子智能体 ID:${escapeHtml(String(agentId))}
`; } if (taskId !== '') { html += `
任务 ID:${escapeHtml(String(taskId))}
`; } html += '
'; if (message) { html += '
'; html += `
${escapeHtml(String(message))}
`; html += '
'; } return html; } function renderGetSubAgentStatus(result: any, args: any): string { if (!result.success) { const error = result.error ?? '查询失败'; return `
⚠️ ${escapeHtml(String(error))}
`; } const results = Array.isArray(result.results) ? result.results : []; if (results.length === 0) { return '
未返回子智能体状态。
'; } let html = '
'; results.forEach((item: any) => { const agentId = item.agent_id ?? ''; const found = item.found !== false; const status = String(item.status || ''); const taskId = item.task_id ?? ''; const summary = item.summary ?? (item.final_result?.message) ?? (item.final_result?.summary) ?? ''; html += '
'; html += `
子智能体 #${escapeHtml(String(agentId))}
`; if (!found) { html += '
'; html += '
状态:不存在
'; html += '
'; } else { html += '
'; if (status === 'completed') { html += '
状态:已完成
'; } else if (status === 'terminated') { html += '
状态:已终止
'; } else if (status === 'running') { html += '
状态:运行中
'; } else if (status === 'pending') { html += '
状态:等待中
'; } else { html += `
状态:${escapeHtml(status || '未知')}
`; } if (taskId !== '') { html += `
任务 ID:${escapeHtml(String(taskId))}
`; } html += '
'; if (summary) { html += '
'; html += `
${escapeHtml(String(summary))}
`; html += '
'; } } html += '
'; }); html += '
'; return html; }