@dynamicu/chromedebug-mcp 2.2.0

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.
Files changed (95) hide show
  1. package/CLAUDE.md +344 -0
  2. package/LICENSE +21 -0
  3. package/README.md +250 -0
  4. package/chrome-extension/README.md +41 -0
  5. package/chrome-extension/background.js +3917 -0
  6. package/chrome-extension/chrome-session-manager.js +706 -0
  7. package/chrome-extension/content.css +181 -0
  8. package/chrome-extension/content.js +3022 -0
  9. package/chrome-extension/data-buffer.js +435 -0
  10. package/chrome-extension/dom-tracker.js +411 -0
  11. package/chrome-extension/extension-config.js +78 -0
  12. package/chrome-extension/firebase-client.js +278 -0
  13. package/chrome-extension/firebase-config.js +32 -0
  14. package/chrome-extension/firebase-config.module.js +22 -0
  15. package/chrome-extension/firebase-config.module.template.js +27 -0
  16. package/chrome-extension/firebase-config.template.js +36 -0
  17. package/chrome-extension/frame-capture.js +407 -0
  18. package/chrome-extension/icon128.png +1 -0
  19. package/chrome-extension/icon16.png +1 -0
  20. package/chrome-extension/icon48.png +1 -0
  21. package/chrome-extension/license-helper.js +181 -0
  22. package/chrome-extension/logger.js +23 -0
  23. package/chrome-extension/manifest.json +73 -0
  24. package/chrome-extension/network-tracker.js +510 -0
  25. package/chrome-extension/offscreen.html +10 -0
  26. package/chrome-extension/options.html +203 -0
  27. package/chrome-extension/options.js +282 -0
  28. package/chrome-extension/pako.min.js +2 -0
  29. package/chrome-extension/performance-monitor.js +533 -0
  30. package/chrome-extension/pii-redactor.js +405 -0
  31. package/chrome-extension/popup.html +532 -0
  32. package/chrome-extension/popup.js +2446 -0
  33. package/chrome-extension/upload-manager.js +323 -0
  34. package/chrome-extension/web-vitals.iife.js +1 -0
  35. package/config/api-keys.json +11 -0
  36. package/config/chrome-pilot-config.json +45 -0
  37. package/package.json +126 -0
  38. package/scripts/cleanup-processes.js +109 -0
  39. package/scripts/config-manager.js +280 -0
  40. package/scripts/generate-extension-config.js +53 -0
  41. package/scripts/setup-security.js +64 -0
  42. package/src/capture/architecture.js +426 -0
  43. package/src/capture/error-handling-tests.md +38 -0
  44. package/src/capture/error-handling-types.ts +360 -0
  45. package/src/capture/index.js +508 -0
  46. package/src/capture/interfaces.js +625 -0
  47. package/src/capture/memory-manager.js +713 -0
  48. package/src/capture/types.js +342 -0
  49. package/src/chrome-controller.js +2658 -0
  50. package/src/cli.js +19 -0
  51. package/src/config-loader.js +303 -0
  52. package/src/database.js +2178 -0
  53. package/src/firebase-license-manager.js +462 -0
  54. package/src/firebase-privacy-guard.js +397 -0
  55. package/src/http-server.js +1516 -0
  56. package/src/index-direct.js +157 -0
  57. package/src/index-modular.js +219 -0
  58. package/src/index-monolithic-backup.js +2230 -0
  59. package/src/index.js +305 -0
  60. package/src/legacy/chrome-controller-old.js +1406 -0
  61. package/src/legacy/index-express.js +625 -0
  62. package/src/legacy/index-old.js +977 -0
  63. package/src/legacy/routes.js +260 -0
  64. package/src/legacy/shared-storage.js +101 -0
  65. package/src/logger.js +10 -0
  66. package/src/mcp/handlers/chrome-tool-handler.js +306 -0
  67. package/src/mcp/handlers/element-tool-handler.js +51 -0
  68. package/src/mcp/handlers/frame-tool-handler.js +957 -0
  69. package/src/mcp/handlers/request-handler.js +104 -0
  70. package/src/mcp/handlers/workflow-tool-handler.js +636 -0
  71. package/src/mcp/server.js +68 -0
  72. package/src/mcp/tools/index.js +701 -0
  73. package/src/middleware/auth.js +371 -0
  74. package/src/middleware/security.js +267 -0
  75. package/src/port-discovery.js +258 -0
  76. package/src/routes/admin.js +182 -0
  77. package/src/services/browser-daemon.js +494 -0
  78. package/src/services/chrome-service.js +375 -0
  79. package/src/services/failover-manager.js +412 -0
  80. package/src/services/git-safety-service.js +675 -0
  81. package/src/services/heartbeat-manager.js +200 -0
  82. package/src/services/http-client.js +195 -0
  83. package/src/services/process-manager.js +318 -0
  84. package/src/services/process-tracker.js +574 -0
  85. package/src/services/profile-manager.js +449 -0
  86. package/src/services/project-manager.js +415 -0
  87. package/src/services/session-manager.js +497 -0
  88. package/src/services/session-registry.js +491 -0
  89. package/src/services/unified-session-manager.js +678 -0
  90. package/src/shared-storage-old.js +267 -0
  91. package/src/standalone-server.js +53 -0
  92. package/src/utils/extension-path.js +145 -0
  93. package/src/utils.js +187 -0
  94. package/src/validation/log-transformer.js +125 -0
  95. package/src/validation/schemas.js +391 -0
@@ -0,0 +1,713 @@
1
+ /**
2
+ * Unified Interaction Capture System - Memory Management & Performance
3
+ *
4
+ * This module provides memory management and performance optimization
5
+ * for the capture system. It handles:
6
+ *
7
+ * 1. Memory usage monitoring and limits
8
+ * 2. Automatic cleanup and garbage collection
9
+ * 3. Event buffering and streaming
10
+ * 4. Performance optimization strategies
11
+ * 5. Backpressure handling
12
+ *
13
+ * MEMORY STRATEGY:
14
+ * ================
15
+ * • Hot Path: Recent events in memory for instant access
16
+ * • Warm Path: Session events in database for quick queries
17
+ * • Cold Path: Archived events in file system for long-term storage
18
+ * • Size-based routing: Small events cached, large events streamed
19
+ *
20
+ * PERFORMANCE STRATEGY:
21
+ * =====================
22
+ * • Async pipelines with backpressure
23
+ * • Batch processing for efficiency
24
+ * • Circular buffers for high-frequency events
25
+ * • Lazy loading for large datasets
26
+ * • Compression for storage optimization
27
+ */
28
+
29
+ import { ICaptureMemoryManager } from './interfaces.js';
30
+ import { ARCHITECTURE_CONFIG } from './architecture.js';
31
+
32
+ /**
33
+ * Memory-efficient circular buffer for high-frequency events
34
+ */
35
+ export class CircularEventBuffer {
36
+ constructor(maxSize = 1000) {
37
+ this.buffer = new Array(maxSize);
38
+ this.maxSize = maxSize;
39
+ this.head = 0;
40
+ this.tail = 0;
41
+ this.count = 0;
42
+ this.overflowCount = 0;
43
+ }
44
+
45
+ /**
46
+ * Add event to buffer
47
+ * @param {CaptureEvent} event - Event to add
48
+ * @returns {boolean} True if added, false if buffer full
49
+ */
50
+ add(event) {
51
+ this.buffer[this.tail] = event;
52
+ this.tail = (this.tail + 1) % this.maxSize;
53
+
54
+ if (this.count < this.maxSize) {
55
+ this.count++;
56
+ return true;
57
+ } else {
58
+ // Buffer full, overwrite oldest
59
+ this.head = (this.head + 1) % this.maxSize;
60
+ this.overflowCount++;
61
+ return false;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Get events from buffer
67
+ * @param {number} [limit] - Maximum events to return
68
+ * @returns {CaptureEvent[]} Events from buffer
69
+ */
70
+ getEvents(limit = this.count) {
71
+ const events = [];
72
+ const actualLimit = Math.min(limit, this.count);
73
+
74
+ for (let i = 0; i < actualLimit; i++) {
75
+ const index = (this.head + i) % this.maxSize;
76
+ events.push(this.buffer[index]);
77
+ }
78
+
79
+ return events;
80
+ }
81
+
82
+ /**
83
+ * Remove events from buffer
84
+ * @param {number} count - Number of events to remove
85
+ */
86
+ remove(count) {
87
+ const actualCount = Math.min(count, this.count);
88
+ this.head = (this.head + actualCount) % this.maxSize;
89
+ this.count -= actualCount;
90
+ }
91
+
92
+ /**
93
+ * Clear all events from buffer
94
+ */
95
+ clear() {
96
+ this.head = 0;
97
+ this.tail = 0;
98
+ this.count = 0;
99
+ }
100
+
101
+ /**
102
+ * Get buffer statistics
103
+ * @returns {Object} Buffer stats
104
+ */
105
+ getStats() {
106
+ return {
107
+ count: this.count,
108
+ maxSize: this.maxSize,
109
+ utilization: this.count / this.maxSize,
110
+ overflowCount: this.overflowCount,
111
+ memoryUsageBytes: this.estimateMemoryUsage()
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Estimate memory usage of buffer
117
+ * @returns {number} Estimated bytes
118
+ */
119
+ estimateMemoryUsage() {
120
+ // Rough estimate: 1KB per event on average
121
+ return this.count * 1024;
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Event batch processor for efficient database writes
127
+ */
128
+ export class EventBatchProcessor {
129
+ constructor(storage, batchSize = 100, flushInterval = 5000) {
130
+ this.storage = storage;
131
+ this.batchSize = batchSize;
132
+ this.flushInterval = flushInterval;
133
+ this.batch = [];
134
+ this.flushTimer = null;
135
+ this.processing = false;
136
+ this.stats = {
137
+ batchesProcessed: 0,
138
+ eventsProcessed: 0,
139
+ errors: 0,
140
+ avgBatchSize: 0
141
+ };
142
+ }
143
+
144
+ /**
145
+ * Add event to batch
146
+ * @param {CaptureEvent} event - Event to add
147
+ * @returns {Promise<void>}
148
+ */
149
+ async addEvent(event) {
150
+ this.batch.push(event);
151
+
152
+ // Flush if batch is full
153
+ if (this.batch.length >= this.batchSize) {
154
+ await this.flush();
155
+ } else if (!this.flushTimer) {
156
+ // Start flush timer if not already running
157
+ this.flushTimer = setTimeout(() => this.flush(), this.flushInterval);
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Flush current batch to storage
163
+ * @returns {Promise<void>}
164
+ */
165
+ async flush() {
166
+ if (this.processing || this.batch.length === 0) {
167
+ return;
168
+ }
169
+
170
+ this.processing = true;
171
+
172
+ if (this.flushTimer) {
173
+ clearTimeout(this.flushTimer);
174
+ this.flushTimer = null;
175
+ }
176
+
177
+ const currentBatch = this.batch.splice(0);
178
+
179
+ try {
180
+ await this.storage.storeEvents(currentBatch);
181
+
182
+ // Update statistics
183
+ this.stats.batchesProcessed++;
184
+ this.stats.eventsProcessed += currentBatch.length;
185
+ this.stats.avgBatchSize = this.stats.eventsProcessed / this.stats.batchesProcessed;
186
+
187
+ } catch (error) {
188
+ this.stats.errors++;
189
+ console.error('Error flushing event batch:', error);
190
+
191
+ // Re-add events to batch for retry
192
+ this.batch.unshift(...currentBatch);
193
+ } finally {
194
+ this.processing = false;
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Stop processor and flush remaining events
200
+ * @returns {Promise<void>}
201
+ */
202
+ async stop() {
203
+ if (this.flushTimer) {
204
+ clearTimeout(this.flushTimer);
205
+ this.flushTimer = null;
206
+ }
207
+
208
+ await this.flush();
209
+ }
210
+
211
+ /**
212
+ * Get processor statistics
213
+ * @returns {Object} Processor stats
214
+ */
215
+ getStats() {
216
+ return {
217
+ ...this.stats,
218
+ pendingEvents: this.batch.length,
219
+ processing: this.processing
220
+ };
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Memory usage monitor
226
+ */
227
+ export class MemoryMonitor {
228
+ constructor() {
229
+ this.components = new Map();
230
+ this.limits = {
231
+ maxMemoryMB: ARCHITECTURE_CONFIG.MEMORY.MAX_MEMORY_MB,
232
+ warningThresholdMB: ARCHITECTURE_CONFIG.MEMORY.WARNING_THRESHOLD_MB,
233
+ criticalThresholdMB: ARCHITECTURE_CONFIG.MEMORY.CRITICAL_THRESHOLD_MB
234
+ };
235
+ this.callbacks = {
236
+ warning: [],
237
+ critical: [],
238
+ cleanup: []
239
+ };
240
+ this.monitoring = false;
241
+ this.monitorInterval = null;
242
+ }
243
+
244
+ /**
245
+ * Register component for monitoring
246
+ * @param {string} componentId - Component identifier
247
+ * @param {Object} component - Component with getMemoryUsage method
248
+ */
249
+ registerComponent(componentId, component) {
250
+ this.components.set(componentId, component);
251
+ }
252
+
253
+ /**
254
+ * Unregister component
255
+ * @param {string} componentId - Component identifier
256
+ */
257
+ unregisterComponent(componentId) {
258
+ this.components.delete(componentId);
259
+ }
260
+
261
+ /**
262
+ * Start memory monitoring
263
+ * @param {number} [intervalMs=30000] - Monitoring interval
264
+ */
265
+ startMonitoring(intervalMs = 30000) {
266
+ if (this.monitoring) return;
267
+
268
+ this.monitoring = true;
269
+ this.monitorInterval = setInterval(() => {
270
+ this.checkMemoryUsage();
271
+ }, intervalMs);
272
+ }
273
+
274
+ /**
275
+ * Stop memory monitoring
276
+ */
277
+ stopMonitoring() {
278
+ if (!this.monitoring) return;
279
+
280
+ this.monitoring = false;
281
+ if (this.monitorInterval) {
282
+ clearInterval(this.monitorInterval);
283
+ this.monitorInterval = null;
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Check current memory usage
289
+ * @returns {Promise<Object>} Memory usage statistics
290
+ */
291
+ async checkMemoryUsage() {
292
+ const usage = await this.getMemoryUsage();
293
+ const totalMB = usage.totalBytes / (1024 * 1024);
294
+
295
+ // Trigger callbacks based on usage
296
+ if (totalMB >= this.limits.criticalThresholdMB) {
297
+ this.triggerCallbacks('critical', usage);
298
+ } else if (totalMB >= this.limits.warningThresholdMB) {
299
+ this.triggerCallbacks('warning', usage);
300
+ }
301
+
302
+ return usage;
303
+ }
304
+
305
+ /**
306
+ * Get comprehensive memory usage
307
+ * @returns {Promise<Object>} Memory usage data
308
+ */
309
+ async getMemoryUsage() {
310
+ const componentUsage = new Map();
311
+ let totalBytes = 0;
312
+
313
+ // Get usage from registered components
314
+ for (const [id, component] of this.components) {
315
+ try {
316
+ let usage = 0;
317
+ if (typeof component.getMemoryUsage === 'function') {
318
+ usage = await component.getMemoryUsage();
319
+ } else if (typeof component.estimateMemoryUsage === 'function') {
320
+ usage = component.estimateMemoryUsage();
321
+ }
322
+
323
+ componentUsage.set(id, usage);
324
+ totalBytes += usage;
325
+ } catch (error) {
326
+ console.warn(`Error getting memory usage for component ${id}:`, error);
327
+ componentUsage.set(id, 0);
328
+ }
329
+ }
330
+
331
+ // Get Node.js process memory usage
332
+ const processUsage = process.memoryUsage();
333
+
334
+ return {
335
+ totalBytes,
336
+ totalMB: totalBytes / (1024 * 1024),
337
+ componentUsage: Object.fromEntries(componentUsage),
338
+ processUsage,
339
+ limits: this.limits,
340
+ timestamp: Date.now()
341
+ };
342
+ }
343
+
344
+ /**
345
+ * Register callback for memory events
346
+ * @param {string} event - Event type (warning, critical, cleanup)
347
+ * @param {Function} callback - Callback function
348
+ */
349
+ onMemoryEvent(event, callback) {
350
+ if (!this.callbacks[event]) {
351
+ this.callbacks[event] = [];
352
+ }
353
+ this.callbacks[event].push(callback);
354
+ }
355
+
356
+ /**
357
+ * Trigger callbacks for event type
358
+ * @param {string} event - Event type
359
+ * @param {Object} data - Event data
360
+ */
361
+ triggerCallbacks(event, data) {
362
+ const callbacks = this.callbacks[event] || [];
363
+ for (const callback of callbacks) {
364
+ try {
365
+ callback(data);
366
+ } catch (error) {
367
+ console.error(`Error in memory event callback for ${event}:`, error);
368
+ }
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Request immediate cleanup
374
+ * @param {string} [priority='normal'] - Cleanup priority
375
+ * @returns {Promise<Object>} Cleanup results
376
+ */
377
+ async requestCleanup(priority = 'normal') {
378
+ const results = {
379
+ beforeUsage: await this.getMemoryUsage(),
380
+ componentsProcessed: 0,
381
+ bytesFreed: 0,
382
+ errors: []
383
+ };
384
+
385
+ // Trigger cleanup callbacks
386
+ this.triggerCallbacks('cleanup', { priority, results });
387
+
388
+ // Call cleanup on registered components
389
+ for (const [id, component] of this.components) {
390
+ try {
391
+ if (typeof component.cleanup === 'function') {
392
+ const beforeBytes = component.estimateMemoryUsage?.() || 0;
393
+ await component.cleanup(priority);
394
+ const afterBytes = component.estimateMemoryUsage?.() || 0;
395
+
396
+ results.componentsProcessed++;
397
+ results.bytesFreed += Math.max(0, beforeBytes - afterBytes);
398
+ }
399
+ } catch (error) {
400
+ console.error(`Error cleaning up component ${id}:`, error);
401
+ results.errors.push({ component: id, error: error.message });
402
+ }
403
+ }
404
+
405
+ results.afterUsage = await this.getMemoryUsage();
406
+
407
+ return results;
408
+ }
409
+ }
410
+
411
+ /**
412
+ * Backpressure manager for flow control
413
+ */
414
+ export class BackpressureManager {
415
+ constructor() {
416
+ this.thresholds = {
417
+ warning: 0.7, // 70% capacity
418
+ critical: 0.9, // 90% capacity
419
+ max: 1.0 // 100% capacity
420
+ };
421
+ this.components = new Map();
422
+ this.state = 'normal'; // normal, warning, critical, blocked
423
+ this.callbacks = new Map();
424
+ }
425
+
426
+ /**
427
+ * Register component for backpressure monitoring
428
+ * @param {string} componentId - Component identifier
429
+ * @param {Object} component - Component with capacity info
430
+ */
431
+ registerComponent(componentId, component) {
432
+ this.components.set(componentId, {
433
+ component,
434
+ capacity: component.getCapacity?.() || 1.0,
435
+ utilization: 0
436
+ });
437
+ }
438
+
439
+ /**
440
+ * Update component utilization
441
+ * @param {string} componentId - Component identifier
442
+ * @param {number} utilization - Current utilization (0-1)
443
+ */
444
+ updateUtilization(componentId, utilization) {
445
+ const info = this.components.get(componentId);
446
+ if (info) {
447
+ info.utilization = utilization;
448
+ this.checkBackpressure();
449
+ }
450
+ }
451
+
452
+ /**
453
+ * Check if backpressure should be applied
454
+ */
455
+ checkBackpressure() {
456
+ let maxUtilization = 0;
457
+
458
+ for (const [id, info] of this.components) {
459
+ maxUtilization = Math.max(maxUtilization, info.utilization);
460
+ }
461
+
462
+ const newState = this.calculateState(maxUtilization);
463
+
464
+ if (newState !== this.state) {
465
+ const oldState = this.state;
466
+ this.state = newState;
467
+ this.notifyStateChange(oldState, newState, maxUtilization);
468
+ }
469
+ }
470
+
471
+ /**
472
+ * Calculate backpressure state
473
+ * @param {number} utilization - Maximum utilization
474
+ * @returns {string} New state
475
+ */
476
+ calculateState(utilization) {
477
+ if (utilization >= this.thresholds.max) {
478
+ return 'blocked';
479
+ } else if (utilization >= this.thresholds.critical) {
480
+ return 'critical';
481
+ } else if (utilization >= this.thresholds.warning) {
482
+ return 'warning';
483
+ } else {
484
+ return 'normal';
485
+ }
486
+ }
487
+
488
+ /**
489
+ * Notify components of state change
490
+ * @param {string} oldState - Previous state
491
+ * @param {string} newState - New state
492
+ * @param {number} utilization - Current utilization
493
+ */
494
+ notifyStateChange(oldState, newState, utilization) {
495
+ const callbacks = this.callbacks.get(newState) || [];
496
+ for (const callback of callbacks) {
497
+ try {
498
+ callback({ oldState, newState, utilization });
499
+ } catch (error) {
500
+ console.error('Error in backpressure callback:', error);
501
+ }
502
+ }
503
+ }
504
+
505
+ /**
506
+ * Register callback for state changes
507
+ * @param {string} state - State to listen for
508
+ * @param {Function} callback - Callback function
509
+ */
510
+ onStateChange(state, callback) {
511
+ if (!this.callbacks.has(state)) {
512
+ this.callbacks.set(state, []);
513
+ }
514
+ this.callbacks.get(state).push(callback);
515
+ }
516
+
517
+ /**
518
+ * Check if system should throttle input
519
+ * @returns {boolean} True if should throttle
520
+ */
521
+ shouldThrottle() {
522
+ return this.state === 'critical' || this.state === 'blocked';
523
+ }
524
+
525
+ /**
526
+ * Get suggested delay for throttling
527
+ * @returns {number} Delay in milliseconds
528
+ */
529
+ getThrottleDelay() {
530
+ switch (this.state) {
531
+ case 'warning': return 10;
532
+ case 'critical': return 100;
533
+ case 'blocked': return 1000;
534
+ default: return 0;
535
+ }
536
+ }
537
+ }
538
+
539
+ /**
540
+ * Main memory manager implementation
541
+ */
542
+ export class CaptureMemoryManager extends ICaptureMemoryManager {
543
+ constructor() {
544
+ super();
545
+ this.monitor = new MemoryMonitor();
546
+ this.backpressure = new BackpressureManager();
547
+ this.buffers = new Map();
548
+ this.processors = new Map();
549
+ this.initialized = false;
550
+ }
551
+
552
+ /**
553
+ * Initialize the memory manager
554
+ * @param {Object} config - Memory management configuration
555
+ * @returns {Promise<void>}
556
+ */
557
+ async initialize(config = {}) {
558
+ if (this.initialized) return;
559
+
560
+ // Apply configuration
561
+ Object.assign(this.monitor.limits, config.limits || {});
562
+ Object.assign(this.backpressure.thresholds, config.thresholds || {});
563
+
564
+ // Set up memory monitoring
565
+ this.monitor.onMemoryEvent('critical', async (usage) => {
566
+ console.warn('Critical memory usage detected:', usage.totalMB, 'MB');
567
+ await this.requestCleanup('aggressive');
568
+ });
569
+
570
+ this.monitor.onMemoryEvent('warning', (usage) => {
571
+ console.info('High memory usage detected:', usage.totalMB, 'MB');
572
+ });
573
+
574
+ // Set up backpressure monitoring
575
+ this.backpressure.onStateChange('critical', ({ utilization }) => {
576
+ console.warn('Critical backpressure detected, utilization:', utilization);
577
+ });
578
+
579
+ this.backpressure.onStateChange('blocked', ({ utilization }) => {
580
+ console.error('System blocked due to backpressure, utilization:', utilization);
581
+ });
582
+
583
+ // Start monitoring
584
+ this.monitor.startMonitoring();
585
+
586
+ this.initialized = true;
587
+ }
588
+
589
+ /**
590
+ * Check current memory usage
591
+ * @returns {Promise<Object>} Memory usage statistics
592
+ */
593
+ async getMemoryUsage() {
594
+ return await this.monitor.getMemoryUsage();
595
+ }
596
+
597
+ /**
598
+ * Request memory cleanup
599
+ * @param {string} [priority='normal'] - Cleanup priority
600
+ * @returns {Promise<Object>} Cleanup results
601
+ */
602
+ async requestCleanup(priority = 'normal') {
603
+ return await this.monitor.requestCleanup(priority);
604
+ }
605
+
606
+ /**
607
+ * Set memory limits
608
+ * @param {Object} limits - Memory limits configuration
609
+ * @returns {Promise<void>}
610
+ */
611
+ async setLimits(limits) {
612
+ Object.assign(this.monitor.limits, limits);
613
+ }
614
+
615
+ /**
616
+ * Register component for memory monitoring
617
+ * @param {string} componentId - Component identifier
618
+ * @param {Object} component - Component to monitor
619
+ * @returns {Promise<void>}
620
+ */
621
+ async registerComponent(componentId, component) {
622
+ this.monitor.registerComponent(componentId, component);
623
+
624
+ if (component.getCapacity) {
625
+ this.backpressure.registerComponent(componentId, component);
626
+ }
627
+ }
628
+
629
+ /**
630
+ * Create optimized event buffer
631
+ * @param {string} bufferId - Buffer identifier
632
+ * @param {Object} options - Buffer options
633
+ * @returns {CircularEventBuffer} Created buffer
634
+ */
635
+ createBuffer(bufferId, options = {}) {
636
+ const buffer = new CircularEventBuffer(options.maxSize);
637
+ this.buffers.set(bufferId, buffer);
638
+ this.monitor.registerComponent(`buffer_${bufferId}`, buffer);
639
+ return buffer;
640
+ }
641
+
642
+ /**
643
+ * Create batch processor
644
+ * @param {string} processorId - Processor identifier
645
+ * @param {Object} storage - Storage backend
646
+ * @param {Object} options - Processor options
647
+ * @returns {EventBatchProcessor} Created processor
648
+ */
649
+ createBatchProcessor(processorId, storage, options = {}) {
650
+ const processor = new EventBatchProcessor(
651
+ storage,
652
+ options.batchSize,
653
+ options.flushInterval
654
+ );
655
+ this.processors.set(processorId, processor);
656
+ this.monitor.registerComponent(`processor_${processorId}`, processor);
657
+ return processor;
658
+ }
659
+
660
+ /**
661
+ * Get system performance metrics
662
+ * @returns {Promise<Object>} Performance metrics
663
+ */
664
+ async getPerformanceMetrics() {
665
+ const memoryUsage = await this.getMemoryUsage();
666
+ const bufferStats = {};
667
+ const processorStats = {};
668
+
669
+ for (const [id, buffer] of this.buffers) {
670
+ bufferStats[id] = buffer.getStats();
671
+ }
672
+
673
+ for (const [id, processor] of this.processors) {
674
+ processorStats[id] = processor.getStats();
675
+ }
676
+
677
+ return {
678
+ memory: memoryUsage,
679
+ backpressure: {
680
+ state: this.backpressure.state,
681
+ shouldThrottle: this.backpressure.shouldThrottle(),
682
+ throttleDelay: this.backpressure.getThrottleDelay()
683
+ },
684
+ buffers: bufferStats,
685
+ processors: processorStats,
686
+ timestamp: Date.now()
687
+ };
688
+ }
689
+
690
+ /**
691
+ * Shutdown memory manager
692
+ * @returns {Promise<void>}
693
+ */
694
+ async shutdown() {
695
+ this.monitor.stopMonitoring();
696
+
697
+ // Stop all processors
698
+ const stopPromises = [];
699
+ for (const processor of this.processors.values()) {
700
+ stopPromises.push(processor.stop());
701
+ }
702
+ await Promise.all(stopPromises);
703
+
704
+ // Clear all buffers
705
+ for (const buffer of this.buffers.values()) {
706
+ buffer.clear();
707
+ }
708
+
709
+ this.initialized = false;
710
+ }
711
+ }
712
+
713
+ export default CaptureMemoryManager;