import type { LogEntry } from '../core/logger.js'; import { RingBuffer } from './ring-buffer.js'; export interface ToolStats { tool: string; calls: number; errors: number; totalDurationMs: number; minDurationMs: number; maxDurationMs: number; lastCalled: string; } export interface TimeSeriesBucket { minute: string; calls: number; errors: number; totalDurationMs: number; count: number; } export interface DashboardState { startTime: string; mode: string; projectPath: string; totalCalls: number; totalErrors: number; toolStats: Map; timeSeries: TimeSeriesBucket[]; recentLogs: RingBuffer; } export declare class Aggregator { private totalCalls; private totalErrors; private toolStats; private timeSeriesBuf; private timeSeriesMap; private recentLogs; private mode; private projectPath; private startTime; private byProject; private projectAggregate; /** A-12 幽灵清理同源:桶被 RingBuffer 挤出后 map 仍持引用,后续同 key 条目会并入 * 幽灵桶(增量不回 buf),读取侧清理时整桶丢失。除 getState/getStateFor 读取侧外, * process 写入侧也前置调用(Task 7 交接注意 c),保证"挤出后再撞同 key"落新桶。 * O(30) 开销可忽略;顺带保证 map 规模受 buf 容量约束(无读取时也不无界增长)。 */ private evictGhostTimeSeries; process(entry: LogEntry): void; getState(): DashboardState; getProjectKeys(): string[]; /** per-project 视图(设计 §8.1):结构与 getState() 同构(含 A-12 幽灵清理)。 * recentLogs 共享全局日志流(不按项目复制,省内存)。 */ getStateFor(project: string): DashboardState; getTopTools(n: number): ToolStats[]; }