From 2bba972272944550cdedf8f0a367b6f3fe219b46 Mon Sep 17 00:00:00 2001 From: lintsinghua Date: Tue, 16 Dec 2025 18:04:09 +0800 Subject: [PATCH] =?UTF-8?q?feat(AgentAudit):=20=E6=B7=BB=E5=8A=A0=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=97=A5=E5=BF=97=E5=8A=9F=E8=83=BD=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加 progress 日志类型,支持通过 progressKey 更新或添加进度日志 在日志组件中增加进度日志的样式和显示 处理进度消息的匹配和更新逻辑,避免重复添加日志 --- .../pages/AgentAudit/components/LogEntry.tsx | 3 + frontend/src/pages/AgentAudit/constants.tsx | 5 + .../AgentAudit/hooks/useAgentAuditState.ts | 28 ++++ frontend/src/pages/AgentAudit/index.tsx | 122 ++++++++++++++---- frontend/src/pages/AgentAudit/types.ts | 5 +- 5 files changed, 136 insertions(+), 27 deletions(-) diff --git a/frontend/src/pages/AgentAudit/components/LogEntry.tsx b/frontend/src/pages/AgentAudit/components/LogEntry.tsx index 60db2d0..932f7f4 100644 --- a/frontend/src/pages/AgentAudit/components/LogEntry.tsx +++ b/frontend/src/pages/AgentAudit/components/LogEntry.tsx @@ -24,6 +24,7 @@ const LOG_TYPE_LABELS: Record = { info: 'INFO', error: 'ERROR', user: 'USER', + progress: 'PROGRESS', }; // Helper to format title (remove emojis and clean up) @@ -73,6 +74,7 @@ export const LogEntry = memo(function LogEntry({ item, isExpanded, onToggle }: L const isFinding = item.type === 'finding'; const isError = item.type === 'error'; const isInfo = item.type === 'info'; + const isProgress = item.type === 'progress'; const showContent = isThinking || isExpanded; const isCollapsible = !isThinking && item.content; @@ -124,6 +126,7 @@ export const LogEntry = memo(function LogEntry({ item, isExpanded, onToggle }: L ${isFinding ? 'bg-rose-500/25 text-rose-300' : ''} ${isError ? 'bg-red-500/25 text-red-300' : ''} ${isInfo ? 'bg-slate-500/25 text-slate-300' : ''} + ${isProgress ? 'bg-cyan-500/25 text-cyan-300' : ''} ${item.type === 'dispatch' ? 'bg-sky-500/25 text-sky-300' : ''} ${item.type === 'phase' ? 'bg-teal-500/25 text-teal-300' : ''} ${item.type === 'user' ? 'bg-indigo-500/25 text-indigo-300' : ''} diff --git a/frontend/src/pages/AgentAudit/constants.tsx b/frontend/src/pages/AgentAudit/constants.tsx index d7a4c2d..9a802be 100644 --- a/frontend/src/pages/AgentAudit/constants.tsx +++ b/frontend/src/pages/AgentAudit/constants.tsx @@ -78,6 +78,11 @@ export const LOG_TYPE_CONFIG: Record log.type === 'progress' && log.progressKey === progressKey + ); + + if (existingIndex >= 0) { + // 更新现有日志的 title 和 time + const updatedLogs = [...state.logs]; + updatedLogs[existingIndex] = { + ...updatedLogs[existingIndex], + title, + time: new Date().toLocaleTimeString('en-US', { hour12: false }), + }; + return { ...state, logs: updatedLogs }; + } else { + // 添加新的进度日志 + const newLog = createLogItem({ + type: 'progress', + title, + progressKey, + agentName, + }); + return { ...state, logs: [...state.logs, newLog] }; + } + } + case 'SELECT_AGENT': return { ...state, diff --git a/frontend/src/pages/AgentAudit/index.tsx b/frontend/src/pages/AgentAudit/index.tsx index 2ca9e12..1fc32c9 100644 --- a/frontend/src/pages/AgentAudit/index.tsx +++ b/frontend/src/pages/AgentAudit/index.tsx @@ -317,16 +317,36 @@ function AgentAuditPageContent() { // 进度事件 case 'progress': - // 进度事件可以选择显示或跳过 + // 进度事件使用 UPDATE_OR_ADD_PROGRESS_LOG 来更新而不是添加 if (event.message) { - dispatch({ - type: 'ADD_LOG', - payload: { - type: 'info', - title: event.message, - agentName, - } - }); + const progressPatterns: { pattern: RegExp; key: string }[] = [ + { pattern: /索引进度[::]?\s*\d+\/\d+/, key: 'index_progress' }, + { pattern: /克隆进度[::]?\s*\d+%/, key: 'clone_progress' }, + { pattern: /下载进度[::]?\s*\d+%/, key: 'download_progress' }, + { pattern: /上传进度[::]?\s*\d+%/, key: 'upload_progress' }, + { pattern: /扫描进度[::]?\s*\d+/, key: 'scan_progress' }, + { pattern: /分析进度[::]?\s*\d+/, key: 'analyze_progress' }, + ]; + const matchedProgress = progressPatterns.find(p => p.pattern.test(event.message || '')); + if (matchedProgress) { + dispatch({ + type: 'UPDATE_OR_ADD_PROGRESS_LOG', + payload: { + progressKey: matchedProgress.key, + title: event.message, + agentName, + } + }); + } else { + dispatch({ + type: 'ADD_LOG', + payload: { + type: 'info', + title: event.message, + agentName, + } + }); + } processedCount++; } break; @@ -335,17 +355,40 @@ function AgentAuditPageContent() { case 'info': case 'complete': case 'error': - case 'warning': - dispatch({ - type: 'ADD_LOG', - payload: { - type: event.event_type === 'error' ? 'error' : 'info', - title: event.message || `${event.event_type}`, - agentName, - } - }); + case 'warning': { + const message = event.message || `${event.event_type}`; + // 检测进度类型消息 + const progressPatterns: { pattern: RegExp; key: string }[] = [ + { pattern: /索引进度[::]?\s*\d+\/\d+/, key: 'index_progress' }, + { pattern: /克隆进度[::]?\s*\d+%/, key: 'clone_progress' }, + { pattern: /下载进度[::]?\s*\d+%/, key: 'download_progress' }, + { pattern: /上传进度[::]?\s*\d+%/, key: 'upload_progress' }, + { pattern: /扫描进度[::]?\s*\d+/, key: 'scan_progress' }, + { pattern: /分析进度[::]?\s*\d+/, key: 'analyze_progress' }, + ]; + const matchedProgress = progressPatterns.find(p => p.pattern.test(message)); + if (matchedProgress) { + dispatch({ + type: 'UPDATE_OR_ADD_PROGRESS_LOG', + payload: { + progressKey: matchedProgress.key, + title: message, + agentName, + } + }); + } else { + dispatch({ + type: 'ADD_LOG', + payload: { + type: event.event_type === 'error' ? 'error' : 'info', + title: message, + agentName, + } + }); + } processedCount++; break; + } // 跳过 thinking_token 等高频事件(它们不会被保存到数据库) case 'thinking_token': @@ -410,14 +453,41 @@ function AgentAuditPageContent() { // 🔥 处理 info、warning、error 类型事件(克隆进度、索引进度等) const infoEvents = ['info', 'warning', 'error', 'progress']; if (infoEvents.includes(event.type)) { - dispatch({ - type: 'ADD_LOG', - payload: { - type: event.type === 'error' ? 'error' : 'info', - title: event.message || event.type, - agentName: getCurrentAgentName() || undefined, - } - }); + const message = event.message || event.type; + + // 🔥 检测进度类型消息,使用更新而不是添加 + const progressPatterns: { pattern: RegExp; key: string }[] = [ + { pattern: /索引进度[::]?\s*\d+\/\d+/, key: 'index_progress' }, + { pattern: /克隆进度[::]?\s*\d+%/, key: 'clone_progress' }, + { pattern: /下载进度[::]?\s*\d+%/, key: 'download_progress' }, + { pattern: /上传进度[::]?\s*\d+%/, key: 'upload_progress' }, + { pattern: /扫描进度[::]?\s*\d+/, key: 'scan_progress' }, + { pattern: /分析进度[::]?\s*\d+/, key: 'analyze_progress' }, + ]; + + const matchedProgress = progressPatterns.find(p => p.pattern.test(message)); + + if (matchedProgress) { + // 使用 UPDATE_OR_ADD_PROGRESS_LOG 来更新进度而不是添加新日志 + dispatch({ + type: 'UPDATE_OR_ADD_PROGRESS_LOG', + payload: { + progressKey: matchedProgress.key, + title: message, + agentName: getCurrentAgentName() || undefined, + } + }); + } else { + // 非进度消息正常添加 + dispatch({ + type: 'ADD_LOG', + payload: { + type: event.type === 'error' ? 'error' : 'info', + title: message, + agentName: getCurrentAgentName() || undefined, + } + }); + } return; } }, diff --git a/frontend/src/pages/AgentAudit/types.ts b/frontend/src/pages/AgentAudit/types.ts index e099f5d..d04562c 100644 --- a/frontend/src/pages/AgentAudit/types.ts +++ b/frontend/src/pages/AgentAudit/types.ts @@ -15,7 +15,8 @@ export type LogType = | 'info' | 'error' | 'user' - | 'dispatch'; + | 'dispatch' + | 'progress'; export type ToolStatus = 'running' | 'completed' | 'failed'; @@ -33,6 +34,7 @@ export interface LogItem { }; severity?: string; agentName?: string; + progressKey?: string; // 用于标识进度日志的唯一键,如 "index_progress" } // ============ Connection Types ============ @@ -76,6 +78,7 @@ export type AgentAuditAction = | { type: 'SET_LOGS'; payload: LogItem[] } | { type: 'ADD_LOG'; payload: Omit & { id?: string } } | { type: 'UPDATE_LOG'; payload: { id: string; updates: Partial } } + | { type: 'UPDATE_OR_ADD_PROGRESS_LOG'; payload: { progressKey: string; title: string; agentName?: string } } | { type: 'COMPLETE_TOOL_LOG'; payload: { toolName: string; output: string; duration: number } } | { type: 'REMOVE_LOG'; payload: string } | { type: 'SELECT_AGENT'; payload: string | null }