@electron-memory/monitor 0.2.2 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ipc/preload-api.ts","../src/ipc/channels.ts","../src/core/dashboard-preload.ts"],"sourcesContent":["/**\r\n * Preload API 辅助\r\n * \r\n * 定义暴露给监控面板渲染进程的 API\r\n */\r\n\r\nimport { contextBridge, ipcRenderer } from 'electron'\r\nimport { IPC_CHANNELS } from './channels'\r\n\r\n/** 监控面板 preload 注入的 API 类型 */\r\nexport interface MonitorPanelAPI {\r\n // 会话控制\r\n startSession: (label: string, description?: string) => Promise<string>\r\n stopSession: () => Promise<unknown>\r\n getSessions: () => Promise<unknown[]>\r\n getSessionReport: (sessionId: string) => Promise<unknown>\r\n compareSessions: (baseId: string, targetId: string) => Promise<unknown>\r\n\r\n // 数据查询\r\n getSessionSnapshots: (sessionId: string, startTime?: number, endTime?: number, maxPoints?: number) => Promise<unknown[]>\r\n\r\n // 导入导出\r\n exportSession: (sessionId: string) => Promise<{ success: boolean; filePath?: string; error?: string }>\r\n importSession: () => Promise<{ success: boolean; session?: unknown; error?: string }>\r\n deleteSession: (sessionId: string) => Promise<boolean>\r\n\r\n // 工具\r\n triggerGC: () => Promise<unknown>\r\n takeHeapSnapshot: (filePath?: string) => Promise<string>\r\n addMark: (label: string, metadata?: Record<string, unknown>) => Promise<void>\r\n getConfig: () => Promise<unknown>\r\n\r\n // 数据订阅\r\n onSnapshot: (callback: (data: unknown) => void) => void\r\n onAnomaly: (callback: (data: unknown) => void) => void\r\n\r\n // 移除监听器\r\n removeSnapshotListener: () => void\r\n removeAnomalyListener: () => void\r\n}\r\n\r\n/** 在监控面板的 preload 中注入 API */\r\nexport function injectMonitorPanelAPI(): void {\r\n const api: MonitorPanelAPI = {\r\n // 会话控制\r\n startSession: (label: string, description?: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_START, { label, description }),\r\n stopSession: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_STOP),\r\n getSessions: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.GET_SESSIONS),\r\n getSessionReport: (sessionId: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_REPORT, sessionId),\r\n compareSessions: (baseId: string, targetId: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_COMPARE, { baseId, targetId }),\r\n\r\n // 数据查询\r\n getSessionSnapshots: (sessionId: string, startTime?: number, endTime?: number, maxPoints?: number) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_SNAPSHOTS, { sessionId, startTime, endTime, maxPoints }),\r\n\r\n // 导入导出\r\n exportSession: (sessionId: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_EXPORT, sessionId),\r\n importSession: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_IMPORT),\r\n deleteSession: (sessionId: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_DELETE, sessionId),\r\n\r\n // 工具\r\n triggerGC: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.TRIGGER_GC),\r\n takeHeapSnapshot: (filePath?: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.HEAP_SNAPSHOT, filePath),\r\n addMark: (label: string, metadata?: Record<string, unknown>) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.MARK, { label, metadata }),\r\n getConfig: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.GET_CONFIG),\r\n\r\n // 数据订阅\r\n onSnapshot: (callback: (data: unknown) => void) => {\r\n ipcRenderer.on(IPC_CHANNELS.SNAPSHOT, (_event, data) => callback(data))\r\n },\r\n onAnomaly: (callback: (data: unknown) => void) => {\r\n ipcRenderer.on(IPC_CHANNELS.ANOMALY, (_event, data) => callback(data))\r\n },\r\n\r\n // 移除监听器\r\n removeSnapshotListener: () => {\r\n ipcRenderer.removeAllListeners(IPC_CHANNELS.SNAPSHOT)\r\n },\r\n removeAnomalyListener: () => {\r\n ipcRenderer.removeAllListeners(IPC_CHANNELS.ANOMALY)\r\n },\r\n }\r\n\r\n contextBridge.exposeInMainWorld('monitorAPI', api)\r\n}\r\n","/**\r\n * IPC 通道常量定义\r\n * 所有通道以 'emm:' 为前缀,避免与业务 IPC 冲突\r\n */\r\n\r\nexport const IPC_CHANNELS = {\r\n // === 数据推送(主进程 → 监控面板)===\r\n SNAPSHOT: 'emm:snapshot',\r\n ANOMALY: 'emm:anomaly',\r\n\r\n // === 会话控制(面板 → 主进程)===\r\n SESSION_START: 'emm:session:start',\r\n SESSION_STOP: 'emm:session:stop',\r\n SESSION_LIST: 'emm:session:list',\r\n SESSION_REPORT: 'emm:session:report',\r\n SESSION_COMPARE: 'emm:session:compare',\r\n\r\n // === 数据查询(面板 → 主进程)===\r\n SESSION_SNAPSHOTS: 'emm:session:snapshots',\r\n\r\n // === 工具操作(面板 → 主进程)===\r\n TRIGGER_GC: 'emm:gc',\r\n HEAP_SNAPSHOT: 'emm:heap-snapshot',\r\n MARK: 'emm:mark',\r\n CONFIG_UPDATE: 'emm:config:update',\r\n GET_CONFIG: 'emm:config:get',\r\n GET_SESSIONS: 'emm:sessions:get',\r\n\r\n // === 导入导出(面板 → 主进程)===\r\n SESSION_EXPORT: 'emm:session:export',\r\n SESSION_IMPORT: 'emm:session:import',\r\n SESSION_DELETE: 'emm:session:delete',\r\n\r\n // === 渲染进程上报(可选)===\r\n RENDERER_REPORT: 'emm:renderer:report',\r\n RENDERER_REQUEST: 'emm:renderer:request',\r\n} as const\r\n","/**\r\n * Dashboard Preload 脚本\r\n * 在监控面板 BrowserWindow 中使用\r\n */\r\n\r\nimport { injectMonitorPanelAPI } from '../ipc/preload-api'\r\n\r\ninjectMonitorPanelAPI()\r\n"],"mappings":";;;AAMA,sBAA2C;;;ACDpC,IAAM,eAAe;AAAA;AAAA,EAE1B,UAAU;AAAA,EACV,SAAS;AAAA;AAAA,EAGT,eAAe;AAAA,EACf,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,iBAAiB;AAAA;AAAA,EAGjB,mBAAmB;AAAA;AAAA,EAGnB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,MAAM;AAAA,EACN,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc;AAAA;AAAA,EAGd,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,iBAAiB;AAAA,EACjB,kBAAkB;AACpB;;;ADMO,SAAS,wBAA8B;AAC5C,QAAM,MAAuB;AAAA;AAAA,IAE3B,cAAc,CAAC,OAAe,gBAC5B,4BAAY,OAAO,aAAa,eAAe,EAAE,OAAO,YAAY,CAAC;AAAA,IACvE,aAAa,MACX,4BAAY,OAAO,aAAa,YAAY;AAAA,IAC9C,aAAa,MACX,4BAAY,OAAO,aAAa,YAAY;AAAA,IAC9C,kBAAkB,CAAC,cACjB,4BAAY,OAAO,aAAa,gBAAgB,SAAS;AAAA,IAC3D,iBAAiB,CAAC,QAAgB,aAChC,4BAAY,OAAO,aAAa,iBAAiB,EAAE,QAAQ,SAAS,CAAC;AAAA;AAAA,IAGvE,qBAAqB,CAAC,WAAmB,WAAoB,SAAkB,cAC7E,4BAAY,OAAO,aAAa,mBAAmB,EAAE,WAAW,WAAW,SAAS,UAAU,CAAC;AAAA;AAAA,IAGjG,eAAe,CAAC,cACd,4BAAY,OAAO,aAAa,gBAAgB,SAAS;AAAA,IAC3D,eAAe,MACb,4BAAY,OAAO,aAAa,cAAc;AAAA,IAChD,eAAe,CAAC,cACd,4BAAY,OAAO,aAAa,gBAAgB,SAAS;AAAA;AAAA,IAG3D,WAAW,MACT,4BAAY,OAAO,aAAa,UAAU;AAAA,IAC5C,kBAAkB,CAAC,aACjB,4BAAY,OAAO,aAAa,eAAe,QAAQ;AAAA,IACzD,SAAS,CAAC,OAAe,aACvB,4BAAY,OAAO,aAAa,MAAM,EAAE,OAAO,SAAS,CAAC;AAAA,IAC3D,WAAW,MACT,4BAAY,OAAO,aAAa,UAAU;AAAA;AAAA,IAG5C,YAAY,CAAC,aAAsC;AACjD,kCAAY,GAAG,aAAa,UAAU,CAAC,QAAQ,SAAS,SAAS,IAAI,CAAC;AAAA,IACxE;AAAA,IACA,WAAW,CAAC,aAAsC;AAChD,kCAAY,GAAG,aAAa,SAAS,CAAC,QAAQ,SAAS,SAAS,IAAI,CAAC;AAAA,IACvE;AAAA;AAAA,IAGA,wBAAwB,MAAM;AAC5B,kCAAY,mBAAmB,aAAa,QAAQ;AAAA,IACtD;AAAA,IACA,uBAAuB,MAAM;AAC3B,kCAAY,mBAAmB,aAAa,OAAO;AAAA,IACrD;AAAA,EACF;AAEA,gCAAc,kBAAkB,cAAc,GAAG;AACnD;;;AEzFA,sBAAsB;","names":[]}
1
+ {"version":3,"sources":["../src/ipc/preload-api.ts","../src/ipc/channels.ts","../src/core/dashboard-preload.ts"],"sourcesContent":["/**\r\n * Preload API 辅助\r\n * \r\n * 定义暴露给监控面板渲染进程的 API\r\n */\r\n\r\nimport { contextBridge, ipcRenderer } from 'electron'\r\nimport { IPC_CHANNELS } from './channels'\r\nimport type { SessionsListPayload, TestSession } from '../types/session'\r\n\r\n/** 监控面板 preload 注入的 API 类型 */\r\nexport interface MonitorPanelAPI {\r\n // 会话控制\r\n startSession: (label: string, description?: string) => Promise<string>\r\n stopSession: () => Promise<unknown>\r\n getSessions: () => Promise<SessionsListPayload | TestSession[]>\r\n getSessionReport: (sessionId: string) => Promise<unknown>\r\n compareSessions: (baseId: string, targetId: string) => Promise<unknown>\r\n\r\n // 数据查询\r\n getSessionSnapshots: (sessionId: string, startTime?: number, endTime?: number, maxPoints?: number) => Promise<unknown[]>\r\n\r\n // 导入导出\r\n exportSession: (sessionId: string) => Promise<{ success: boolean; filePath?: string; error?: string }>\r\n importSession: () => Promise<{ success: boolean; session?: unknown; error?: string }>\r\n deleteSession: (sessionId: string) => Promise<boolean>\r\n\r\n // 工具\r\n triggerGC: () => Promise<unknown>\r\n takeHeapSnapshot: (filePath?: string) => Promise<string>\r\n addMark: (label: string, metadata?: Record<string, unknown>) => Promise<void>\r\n getConfig: () => Promise<unknown>\r\n\r\n // 数据订阅\r\n onSnapshot: (callback: (data: unknown) => void) => void\r\n onAnomaly: (callback: (data: unknown) => void) => void\r\n\r\n // 移除监听器\r\n removeSnapshotListener: () => void\r\n removeAnomalyListener: () => void\r\n}\r\n\r\n/** 在监控面板的 preload 中注入 API */\r\nexport function injectMonitorPanelAPI(): void {\r\n const api: MonitorPanelAPI = {\r\n // 会话控制\r\n startSession: (label: string, description?: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_START, { label, description }),\r\n stopSession: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_STOP),\r\n getSessions: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.GET_SESSIONS),\r\n getSessionReport: (sessionId: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_REPORT, sessionId),\r\n compareSessions: (baseId: string, targetId: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_COMPARE, { baseId, targetId }),\r\n\r\n // 数据查询\r\n getSessionSnapshots: (sessionId: string, startTime?: number, endTime?: number, maxPoints?: number) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_SNAPSHOTS, { sessionId, startTime, endTime, maxPoints }),\r\n\r\n // 导入导出\r\n exportSession: (sessionId: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_EXPORT, sessionId),\r\n importSession: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_IMPORT),\r\n deleteSession: (sessionId: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.SESSION_DELETE, sessionId),\r\n\r\n // 工具\r\n triggerGC: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.TRIGGER_GC),\r\n takeHeapSnapshot: (filePath?: string) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.HEAP_SNAPSHOT, filePath),\r\n addMark: (label: string, metadata?: Record<string, unknown>) =>\r\n ipcRenderer.invoke(IPC_CHANNELS.MARK, { label, metadata }),\r\n getConfig: () =>\r\n ipcRenderer.invoke(IPC_CHANNELS.GET_CONFIG),\r\n\r\n // 数据订阅\r\n onSnapshot: (callback: (data: unknown) => void) => {\r\n ipcRenderer.on(IPC_CHANNELS.SNAPSHOT, (_event, data) => callback(data))\r\n },\r\n onAnomaly: (callback: (data: unknown) => void) => {\r\n ipcRenderer.on(IPC_CHANNELS.ANOMALY, (_event, data) => callback(data))\r\n },\r\n\r\n // 移除监听器\r\n removeSnapshotListener: () => {\r\n ipcRenderer.removeAllListeners(IPC_CHANNELS.SNAPSHOT)\r\n },\r\n removeAnomalyListener: () => {\r\n ipcRenderer.removeAllListeners(IPC_CHANNELS.ANOMALY)\r\n },\r\n }\r\n\r\n contextBridge.exposeInMainWorld('monitorAPI', api)\r\n}\r\n","/**\r\n * IPC 通道常量定义\r\n * 所有通道以 'emm:' 为前缀,避免与业务 IPC 冲突\r\n */\r\n\r\nexport const IPC_CHANNELS = {\r\n // === 数据推送(主进程 → 监控面板)===\r\n SNAPSHOT: 'emm:snapshot',\r\n ANOMALY: 'emm:anomaly',\r\n\r\n // === 会话控制(面板 → 主进程)===\r\n SESSION_START: 'emm:session:start',\r\n SESSION_STOP: 'emm:session:stop',\r\n SESSION_LIST: 'emm:session:list',\r\n SESSION_REPORT: 'emm:session:report',\r\n SESSION_COMPARE: 'emm:session:compare',\r\n\r\n // === 数据查询(面板 → 主进程)===\r\n SESSION_SNAPSHOTS: 'emm:session:snapshots',\r\n\r\n // === 工具操作(面板 → 主进程)===\r\n TRIGGER_GC: 'emm:gc',\r\n HEAP_SNAPSHOT: 'emm:heap-snapshot',\r\n MARK: 'emm:mark',\r\n CONFIG_UPDATE: 'emm:config:update',\r\n GET_CONFIG: 'emm:config:get',\r\n GET_SESSIONS: 'emm:sessions:get',\r\n\r\n // === 导入导出(面板 → 主进程)===\r\n SESSION_EXPORT: 'emm:session:export',\r\n SESSION_IMPORT: 'emm:session:import',\r\n SESSION_DELETE: 'emm:session:delete',\r\n\r\n // === 渲染进程上报(可选)===\r\n RENDERER_REPORT: 'emm:renderer:report',\r\n RENDERER_REQUEST: 'emm:renderer:request',\r\n} as const\r\n","/**\r\n * Dashboard Preload 脚本\r\n * 在监控面板 BrowserWindow 中使用\r\n */\r\n\r\nimport { injectMonitorPanelAPI } from '../ipc/preload-api'\r\n\r\ninjectMonitorPanelAPI()\r\n"],"mappings":";;;AAMA,sBAA2C;;;ACDpC,IAAM,eAAe;AAAA;AAAA,EAE1B,UAAU;AAAA,EACV,SAAS;AAAA;AAAA,EAGT,eAAe;AAAA,EACf,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,iBAAiB;AAAA;AAAA,EAGjB,mBAAmB;AAAA;AAAA,EAGnB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,MAAM;AAAA,EACN,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc;AAAA;AAAA,EAGd,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,iBAAiB;AAAA,EACjB,kBAAkB;AACpB;;;ADOO,SAAS,wBAA8B;AAC5C,QAAM,MAAuB;AAAA;AAAA,IAE3B,cAAc,CAAC,OAAe,gBAC5B,4BAAY,OAAO,aAAa,eAAe,EAAE,OAAO,YAAY,CAAC;AAAA,IACvE,aAAa,MACX,4BAAY,OAAO,aAAa,YAAY;AAAA,IAC9C,aAAa,MACX,4BAAY,OAAO,aAAa,YAAY;AAAA,IAC9C,kBAAkB,CAAC,cACjB,4BAAY,OAAO,aAAa,gBAAgB,SAAS;AAAA,IAC3D,iBAAiB,CAAC,QAAgB,aAChC,4BAAY,OAAO,aAAa,iBAAiB,EAAE,QAAQ,SAAS,CAAC;AAAA;AAAA,IAGvE,qBAAqB,CAAC,WAAmB,WAAoB,SAAkB,cAC7E,4BAAY,OAAO,aAAa,mBAAmB,EAAE,WAAW,WAAW,SAAS,UAAU,CAAC;AAAA;AAAA,IAGjG,eAAe,CAAC,cACd,4BAAY,OAAO,aAAa,gBAAgB,SAAS;AAAA,IAC3D,eAAe,MACb,4BAAY,OAAO,aAAa,cAAc;AAAA,IAChD,eAAe,CAAC,cACd,4BAAY,OAAO,aAAa,gBAAgB,SAAS;AAAA;AAAA,IAG3D,WAAW,MACT,4BAAY,OAAO,aAAa,UAAU;AAAA,IAC5C,kBAAkB,CAAC,aACjB,4BAAY,OAAO,aAAa,eAAe,QAAQ;AAAA,IACzD,SAAS,CAAC,OAAe,aACvB,4BAAY,OAAO,aAAa,MAAM,EAAE,OAAO,SAAS,CAAC;AAAA,IAC3D,WAAW,MACT,4BAAY,OAAO,aAAa,UAAU;AAAA;AAAA,IAG5C,YAAY,CAAC,aAAsC;AACjD,kCAAY,GAAG,aAAa,UAAU,CAAC,QAAQ,SAAS,SAAS,IAAI,CAAC;AAAA,IACxE;AAAA,IACA,WAAW,CAAC,aAAsC;AAChD,kCAAY,GAAG,aAAa,SAAS,CAAC,QAAQ,SAAS,SAAS,IAAI,CAAC;AAAA,IACvE;AAAA;AAAA,IAGA,wBAAwB,MAAM;AAC5B,kCAAY,mBAAmB,aAAa,QAAQ;AAAA,IACtD;AAAA,IACA,uBAAuB,MAAM;AAC3B,kCAAY,mBAAmB,aAAa,OAAO;AAAA,IACrD;AAAA,EACF;AAEA,gCAAc,kBAAkB,cAAc,GAAG;AACnD;;;AE1FA,sBAAsB;","names":[]}
package/dist/index.d.mts CHANGED
@@ -175,6 +175,17 @@ interface MonitorConfig {
175
175
  autoStart: boolean;
176
176
  /** 启动后是否自动打开监控面板,默认 true */
177
177
  openDashboardOnStart: boolean;
178
+ session: {
179
+ /**
180
+ * 监控启动后自动创建一条「进行中」会话并开始写入快照,无需在看板点「开始会话」。
181
+ * 每次进程启动一条新会话,标签带本地时间。默认 true。
182
+ */
183
+ autoStartOnLaunch: boolean;
184
+ /** 自动会话标签前缀,完整标签为 `${prefix} YYYY-MM-DD HH:mm:ss` */
185
+ autoLabelPrefix: string;
186
+ /** 自动会话描述,可选 */
187
+ autoDescription?: string;
188
+ };
178
189
  /** 采集间隔 (ms),默认 2000 */
179
190
  collectInterval: number;
180
191
  /** 落盘间隔 (条数),默认 60 */
@@ -243,6 +254,11 @@ interface SessionIndex {
243
254
  sessions: TestSession[];
244
255
  lastUpdated: number;
245
256
  }
257
+ /** IPC 拉取会话列表时附带「当前是否在录」:以主进程内存为准,避免索引里僵尸 running */
258
+ interface SessionsListPayload {
259
+ sessions: TestSession[];
260
+ activeSessionId: string | null;
261
+ }
246
262
 
247
263
  /**
248
264
  * 报告与对比相关类型
@@ -277,6 +293,17 @@ interface TrendInfo {
277
293
  /** 置信度 */
278
294
  confidence: 'high' | 'medium' | 'low';
279
295
  }
296
+ /** 会话中的阶段标记(写入报告,便于对照各阶段内存) */
297
+ interface SessionEventMark {
298
+ timestamp: number;
299
+ label: string;
300
+ metadata?: Record<string, unknown>;
301
+ /** 该标记随附快照时刻的总工作集 (KB) */
302
+ totalWorkingSetKB: number;
303
+ browserKB: number;
304
+ rendererKB: number;
305
+ gpuKB: number;
306
+ }
280
307
  /** 改进建议 */
281
308
  interface Suggestion {
282
309
  /** 建议 ID */
@@ -339,6 +366,8 @@ interface SessionReport {
339
366
  };
340
367
  anomalies: AnomalyEvent[];
341
368
  suggestions: Suggestion[];
369
+ /** 阶段标记汇总(与快照中的 marks 一致,便于表格展示) */
370
+ eventMarks?: SessionEventMark[];
342
371
  dataFile: string;
343
372
  }
344
373
  /** 指标差异 */
@@ -438,6 +467,8 @@ declare class ElectronMemoryMonitor extends EventEmitter {
438
467
  startSession(label: string, description?: string): string;
439
468
  /** 结束当前会话 */
440
469
  stopSession(): Promise<SessionReport | null>;
470
+ /** 为已落盘元数据的会话生成并写入 report.json(显式结束或被新会话顶替) */
471
+ private persistCompletedSessionReport;
441
472
  /** 打开监控面板 */
442
473
  openDashboard(): void;
443
474
  /** 关闭监控面板 */
@@ -446,6 +477,10 @@ declare class ElectronMemoryMonitor extends EventEmitter {
446
477
  getCurrentSnapshot(): MemorySnapshot | null;
447
478
  /** 获取历史会话列表 */
448
479
  getSessions(): Promise<TestSession[]>;
480
+ /**
481
+ * 供监控面板 IPC:列表来自磁盘索引,是否在录制以内存中的 currentSession 为准(避免索引僵尸 running)
482
+ */
483
+ getSessionsPayloadForIpc(): SessionsListPayload;
449
484
  /** 获取指定会话报告 */
450
485
  getSessionReport(sessionId: string): Promise<SessionReport | null>;
451
486
  /** 获取指定会话的快照数据(支持时间过滤和降采样) */
@@ -478,6 +513,7 @@ declare class ElectronMemoryMonitor extends EventEmitter {
478
513
  getConfig(): MonitorConfig;
479
514
  on(event: 'snapshot', handler: (data: MemorySnapshot) => void): this;
480
515
  on(event: 'anomaly', handler: (event: AnomalyEvent) => void): this;
516
+ on(event: 'session-start', handler: (session: TestSession) => void): this;
481
517
  on(event: 'session-end', handler: (report: SessionReport) => void): this;
482
518
  private onSnapshot;
483
519
  private mergeConfig;
@@ -515,4 +551,4 @@ declare const IPC_CHANNELS: {
515
551
  readonly RENDERER_REQUEST: "emm:renderer:request";
516
552
  };
517
553
 
518
- export { type AnomalyCategory, type AnomalyEvent, type AnomalyRule, type AnomalySeverity, type CompareReport, ElectronMemoryMonitor, type EventMark, type GCResult, IPC_CHANNELS, type Improvement, type MemorySnapshot, type MetricDiff, type MetricSummary, type MonitorConfig, type ProcessMemoryInfo, type Regression, type RendererV8Detail, type SessionIndex, type SessionReport, type Suggestion, type SystemMemoryInfo, type TestSession, type TrendInfo, type V8HeapDetailStats, type V8HeapSpaceInfo, type V8HeapStats, registerDashboardSchemePrivileged };
554
+ export { type AnomalyCategory, type AnomalyEvent, type AnomalyRule, type AnomalySeverity, type CompareReport, ElectronMemoryMonitor, type EventMark, type GCResult, IPC_CHANNELS, type Improvement, type MemorySnapshot, type MetricDiff, type MetricSummary, type MonitorConfig, type ProcessMemoryInfo, type Regression, type RendererV8Detail, type SessionEventMark, type SessionIndex, type SessionReport, type SessionsListPayload, type Suggestion, type SystemMemoryInfo, type TestSession, type TrendInfo, type V8HeapDetailStats, type V8HeapSpaceInfo, type V8HeapStats, registerDashboardSchemePrivileged };
package/dist/index.d.ts CHANGED
@@ -175,6 +175,17 @@ interface MonitorConfig {
175
175
  autoStart: boolean;
176
176
  /** 启动后是否自动打开监控面板,默认 true */
177
177
  openDashboardOnStart: boolean;
178
+ session: {
179
+ /**
180
+ * 监控启动后自动创建一条「进行中」会话并开始写入快照,无需在看板点「开始会话」。
181
+ * 每次进程启动一条新会话,标签带本地时间。默认 true。
182
+ */
183
+ autoStartOnLaunch: boolean;
184
+ /** 自动会话标签前缀,完整标签为 `${prefix} YYYY-MM-DD HH:mm:ss` */
185
+ autoLabelPrefix: string;
186
+ /** 自动会话描述,可选 */
187
+ autoDescription?: string;
188
+ };
178
189
  /** 采集间隔 (ms),默认 2000 */
179
190
  collectInterval: number;
180
191
  /** 落盘间隔 (条数),默认 60 */
@@ -243,6 +254,11 @@ interface SessionIndex {
243
254
  sessions: TestSession[];
244
255
  lastUpdated: number;
245
256
  }
257
+ /** IPC 拉取会话列表时附带「当前是否在录」:以主进程内存为准,避免索引里僵尸 running */
258
+ interface SessionsListPayload {
259
+ sessions: TestSession[];
260
+ activeSessionId: string | null;
261
+ }
246
262
 
247
263
  /**
248
264
  * 报告与对比相关类型
@@ -277,6 +293,17 @@ interface TrendInfo {
277
293
  /** 置信度 */
278
294
  confidence: 'high' | 'medium' | 'low';
279
295
  }
296
+ /** 会话中的阶段标记(写入报告,便于对照各阶段内存) */
297
+ interface SessionEventMark {
298
+ timestamp: number;
299
+ label: string;
300
+ metadata?: Record<string, unknown>;
301
+ /** 该标记随附快照时刻的总工作集 (KB) */
302
+ totalWorkingSetKB: number;
303
+ browserKB: number;
304
+ rendererKB: number;
305
+ gpuKB: number;
306
+ }
280
307
  /** 改进建议 */
281
308
  interface Suggestion {
282
309
  /** 建议 ID */
@@ -339,6 +366,8 @@ interface SessionReport {
339
366
  };
340
367
  anomalies: AnomalyEvent[];
341
368
  suggestions: Suggestion[];
369
+ /** 阶段标记汇总(与快照中的 marks 一致,便于表格展示) */
370
+ eventMarks?: SessionEventMark[];
342
371
  dataFile: string;
343
372
  }
344
373
  /** 指标差异 */
@@ -438,6 +467,8 @@ declare class ElectronMemoryMonitor extends EventEmitter {
438
467
  startSession(label: string, description?: string): string;
439
468
  /** 结束当前会话 */
440
469
  stopSession(): Promise<SessionReport | null>;
470
+ /** 为已落盘元数据的会话生成并写入 report.json(显式结束或被新会话顶替) */
471
+ private persistCompletedSessionReport;
441
472
  /** 打开监控面板 */
442
473
  openDashboard(): void;
443
474
  /** 关闭监控面板 */
@@ -446,6 +477,10 @@ declare class ElectronMemoryMonitor extends EventEmitter {
446
477
  getCurrentSnapshot(): MemorySnapshot | null;
447
478
  /** 获取历史会话列表 */
448
479
  getSessions(): Promise<TestSession[]>;
480
+ /**
481
+ * 供监控面板 IPC:列表来自磁盘索引,是否在录制以内存中的 currentSession 为准(避免索引僵尸 running)
482
+ */
483
+ getSessionsPayloadForIpc(): SessionsListPayload;
449
484
  /** 获取指定会话报告 */
450
485
  getSessionReport(sessionId: string): Promise<SessionReport | null>;
451
486
  /** 获取指定会话的快照数据(支持时间过滤和降采样) */
@@ -478,6 +513,7 @@ declare class ElectronMemoryMonitor extends EventEmitter {
478
513
  getConfig(): MonitorConfig;
479
514
  on(event: 'snapshot', handler: (data: MemorySnapshot) => void): this;
480
515
  on(event: 'anomaly', handler: (event: AnomalyEvent) => void): this;
516
+ on(event: 'session-start', handler: (session: TestSession) => void): this;
481
517
  on(event: 'session-end', handler: (report: SessionReport) => void): this;
482
518
  private onSnapshot;
483
519
  private mergeConfig;
@@ -515,4 +551,4 @@ declare const IPC_CHANNELS: {
515
551
  readonly RENDERER_REQUEST: "emm:renderer:request";
516
552
  };
517
553
 
518
- export { type AnomalyCategory, type AnomalyEvent, type AnomalyRule, type AnomalySeverity, type CompareReport, ElectronMemoryMonitor, type EventMark, type GCResult, IPC_CHANNELS, type Improvement, type MemorySnapshot, type MetricDiff, type MetricSummary, type MonitorConfig, type ProcessMemoryInfo, type Regression, type RendererV8Detail, type SessionIndex, type SessionReport, type Suggestion, type SystemMemoryInfo, type TestSession, type TrendInfo, type V8HeapDetailStats, type V8HeapSpaceInfo, type V8HeapStats, registerDashboardSchemePrivileged };
554
+ export { type AnomalyCategory, type AnomalyEvent, type AnomalyRule, type AnomalySeverity, type CompareReport, ElectronMemoryMonitor, type EventMark, type GCResult, IPC_CHANNELS, type Improvement, type MemorySnapshot, type MetricDiff, type MetricSummary, type MonitorConfig, type ProcessMemoryInfo, type Regression, type RendererV8Detail, type SessionEventMark, type SessionIndex, type SessionReport, type SessionsListPayload, type Suggestion, type SystemMemoryInfo, type TestSession, type TrendInfo, type V8HeapDetailStats, type V8HeapSpaceInfo, type V8HeapStats, registerDashboardSchemePrivileged };