/** * MetricsDashboard — Agent Metrics 可视化仪表盘 * 展示效率概览、工具热力图、Token 趋势 */ import { getMetricsHistory, aggregateMetrics, generateImprovementSuggestions } from '../services/agent-metrics.js'; import { logInfo } from '../services/log-service.js'; let metricsModalEl: HTMLElement | null = null; export function initMetricsDashboard(): void { metricsModalEl = document.querySelector('#metricsDashboardModal'); document.querySelector('#btnMetrics')?.addEventListener('click', openMetricsDashboard); document.querySelector('#btnCloseMetrics')?.addEventListener('click', closeMetricsDashboard); if (metricsModalEl) { metricsModalEl.addEventListener('click', (e) => { if (e.target === metricsModalEl) closeMetricsDashboard(); }); } } function openMetricsDashboard(): void { if (!metricsModalEl) return; metricsModalEl.style.display = ''; renderMetricsDashboard(); } function closeMetricsDashboard(): void { if (metricsModalEl) metricsModalEl.style.display = 'none'; } function renderMetricsDashboard(): void { const history = getMetricsHistory(); const agg = aggregateMetrics(); const suggestions = generateImprovementSuggestions(); // ── 效率概览 ── const overviewEl = document.querySelector('#mdOverview'); if (overviewEl) { if (agg.totalSessions === 0) { overviewEl.innerHTML = '
暂无度量数据,开始对话后将有统计数据
'; } else { const successRate = (agg.toolSuccessRate * 100).toFixed(1); const avgIter = agg.avgIterationsPerTask.toFixed(1); const tokenEff = agg.tokenEfficiency.toFixed(2); overviewEl.innerHTML = `暂无工具调用数据
'; } else { const toolStats = new Map暂无 Token 趋势数据
'; } else { const recent = history.slice(-20); const maxTokens = Math.max(...recent.map(s => s.totalInputTokens + s.totalOutputTokens), 1); tokenTrendEl.innerHTML = recent.map((s, i) => { const inputPct = (s.totalInputTokens / maxTokens * 100).toFixed(1); const outputPct = (s.totalOutputTokens / maxTokens * 100).toFixed(1); return ` `; }).join(''); } } // ── 改进建议 ── const suggestionsEl = document.querySelector('#mdSuggestions'); if (suggestionsEl) { if (suggestions.length === 0) { suggestionsEl.innerHTML = '暂无改进建议
'; } else { suggestionsEl.innerHTML = suggestions.map(s => `