claude-flow-novice 1.6.3 → 1.6.4

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 (27) hide show
  1. package/.claude/settings.json +12 -2
  2. package/.claude/settings.local.json +3 -2
  3. package/.claude-flow-novice/dist/src/coordination/index.js +3 -0
  4. package/.claude-flow-novice/dist/src/coordination/index.js.map +1 -1
  5. package/.claude-flow-novice/dist/src/coordination/v1-transparency/interfaces/v1-transparency-system.js +12 -0
  6. package/.claude-flow-novice/dist/src/coordination/v1-transparency/interfaces/v1-transparency-system.js.map +1 -0
  7. package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-to-v2-bridge.js +433 -0
  8. package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-to-v2-bridge.js.map +1 -0
  9. package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-transparency-adapter.js +1468 -0
  10. package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-transparency-adapter.js.map +1 -0
  11. package/.claude-flow-novice/dist/src/monitoring/apm/apm-integration.js +5 -0
  12. package/.claude-flow-novice/dist/src/monitoring/apm/apm-integration.js.map +1 -1
  13. package/.claude-flow-novice/dist/src/providers/provider-manager.js +5 -3
  14. package/.claude-flow-novice/dist/src/providers/provider-manager.js.map +1 -1
  15. package/.claude-flow-novice/dist/src/providers/tiered-router.js +9 -17
  16. package/.claude-flow-novice/dist/src/providers/tiered-router.js.map +1 -1
  17. package/.claude-flow-novice/metrics.db +0 -0
  18. package/CLAUDE.md +72 -0
  19. package/config/hooks/post-edit-pipeline.js +68 -118
  20. package/config/hooks/pre-tool-memory-safety.js +209 -0
  21. package/package.json +6 -3
  22. package/scripts/cleanup-idle-sessions.sh +59 -0
  23. package/scripts/test-provider-routing.cjs +7 -9
  24. package/wiki/Provider-Routing.md +57 -69
  25. package/.claude-flow-novice/metrics.db-shm +0 -0
  26. package/.claude-flow-novice/metrics.db-wal +0 -0
  27. package/MEMORY_LEAK_ROOT_CAUSE.md +0 -149
@@ -0,0 +1,1468 @@
1
+ /**
2
+ * V1 Transparency System Adapter
3
+ *
4
+ * Adapts existing V1 coordinators (QueenAgent, MeshCoordinator) to provide
5
+ * transparency features without modifying the original coordinator implementations.
6
+ *
7
+ * @module coordination/v1-transparency/v1-transparency-adapter
8
+ */ import { EventEmitter } from 'events';
9
+ import { v4 as uuidv4 } from 'uuid';
10
+ /**
11
+ * V1 Transparency System Implementation
12
+ *
13
+ * Wraps existing V1 coordinators to provide transparency features
14
+ * by listening to their events and collecting metrics.
15
+ */ export class V1TransparencySystem extends EventEmitter {
16
+ logger;
17
+ config;
18
+ isInitialized = false;
19
+ isMonitoring = false;
20
+ // V1 Coordinator tracking
21
+ coordinatorAdapters = new Map();
22
+ coordinatorInfo = new Map();
23
+ agentInfo = new Map();
24
+ taskInfo = new Map();
25
+ transparencyEvents = [];
26
+ eventListeners = new Set();
27
+ // Monitoring intervals
28
+ metricsCollectionInterval;
29
+ healthCheckInterval;
30
+ // Performance tracking
31
+ lastMetricsUpdate = new Date();
32
+ eventsPerSecond = 0;
33
+ recentEventTimestamps = [];
34
+ // Rate limiting for security
35
+ eventCountsBySource = new Map();
36
+ RATE_LIMIT_WINDOW_MS = 60000;
37
+ RATE_LIMIT_MAX_EVENTS = 1000;
38
+ constructor(logger){
39
+ super();
40
+ this.logger = logger;
41
+ this.config = this.getDefaultConfig();
42
+ }
43
+ // ===========================
44
+ // System Lifecycle
45
+ // ===========================
46
+ async initialize(config = {}) {
47
+ if (this.isInitialized) {
48
+ this.logger.warn('V1TransparencySystem already initialized');
49
+ return;
50
+ }
51
+ this.config = {
52
+ ...this.getDefaultConfig(),
53
+ ...config
54
+ };
55
+ this.logger.info('Initializing V1TransparencySystem', this.config);
56
+ // Initialize data structures
57
+ this.transparencyEvents = [];
58
+ this.agentInfo.clear();
59
+ this.taskInfo.clear();
60
+ this.coordinatorAdapters.clear();
61
+ this.eventListeners.clear();
62
+ this.isInitialized = true;
63
+ this.emit('initialized');
64
+ this.logger.info('V1TransparencySystem initialized successfully');
65
+ }
66
+ async startMonitoring() {
67
+ if (!this.isInitialized) {
68
+ throw new Error('V1TransparencySystem not initialized');
69
+ }
70
+ if (this.isMonitoring) {
71
+ this.logger.warn('V1TransparencySystem monitoring already started');
72
+ return;
73
+ }
74
+ this.logger.info('Starting V1 transparency monitoring');
75
+ // Start metrics collection
76
+ if (this.config.enableRealTimeMonitoring) {
77
+ this.metricsCollectionInterval = setInterval(()=>this.collectMetrics(), this.config.metricsCollectionIntervalMs);
78
+ }
79
+ // Start health checks
80
+ if (this.config.enableHealthMonitoring) {
81
+ this.healthCheckInterval = setInterval(()=>this.performHealthChecks(), 30000 // 30 seconds
82
+ );
83
+ }
84
+ // Start all coordinator monitoring
85
+ for (const adapter of this.coordinatorAdapters.values()){
86
+ if (adapter.isActive) {
87
+ this.startCoordinatorMonitoring(adapter);
88
+ }
89
+ }
90
+ this.isMonitoring = true;
91
+ this.emit('monitoringStarted');
92
+ this.logger.info('V1 transparency monitoring started');
93
+ }
94
+ async stopMonitoring() {
95
+ if (!this.isMonitoring) {
96
+ return;
97
+ }
98
+ this.logger.info('Stopping V1 transparency monitoring');
99
+ // Clear intervals
100
+ if (this.metricsCollectionInterval) {
101
+ clearInterval(this.metricsCollectionInterval);
102
+ this.metricsCollectionInterval = undefined;
103
+ }
104
+ if (this.healthCheckInterval) {
105
+ clearInterval(this.healthCheckInterval);
106
+ this.healthCheckInterval = undefined;
107
+ }
108
+ this.isMonitoring = false;
109
+ this.emit('monitoringStopped');
110
+ this.logger.info('V1 transparency monitoring stopped');
111
+ }
112
+ async cleanup() {
113
+ this.logger.info('Cleaning up V1TransparencySystem');
114
+ await this.stopMonitoring();
115
+ // Cleanup all data
116
+ this.transparencyEvents = [];
117
+ this.agentInfo.clear();
118
+ this.taskInfo.clear();
119
+ this.coordinatorAdapters.clear();
120
+ this.eventListeners.clear();
121
+ this.removeAllListeners();
122
+ this.isInitialized = false;
123
+ this.logger.info('V1TransparencySystem cleanup complete');
124
+ }
125
+ // ===========================
126
+ // V1 Coordinator Registration
127
+ // ===========================
128
+ /**
129
+ * Register a QueenAgent for transparency monitoring
130
+ */ registerQueenAgent(coordinatorId, queenAgent) {
131
+ const adapter = {
132
+ id: coordinatorId,
133
+ type: 'queen-agent',
134
+ instance: queenAgent,
135
+ eventEmitter: queenAgent,
136
+ isActive: true,
137
+ registeredAt: new Date()
138
+ };
139
+ this.coordinatorAdapters.set(coordinatorId, adapter);
140
+ this.setupCoordinatorEventListeners(adapter);
141
+ this.recordEvent({
142
+ eventId: uuidv4(),
143
+ timestamp: new Date(),
144
+ eventType: 'coordinator_initialized',
145
+ eventData: {
146
+ coordinatorId,
147
+ coordinatorType: 'queen-agent'
148
+ },
149
+ source: {
150
+ component: 'V1TransparencySystem',
151
+ instance: this.constructor.name
152
+ },
153
+ severity: 'info',
154
+ category: 'lifecycle'
155
+ });
156
+ this.logger.info(`QueenAgent registered for transparency: ${coordinatorId}`);
157
+ }
158
+ /**
159
+ * Register a MeshCoordinator for transparency monitoring
160
+ */ registerMeshCoordinator(coordinatorId, meshCoordinator) {
161
+ const adapter = {
162
+ id: coordinatorId,
163
+ type: 'mesh-coordinator',
164
+ instance: meshCoordinator,
165
+ eventEmitter: meshCoordinator,
166
+ isActive: true,
167
+ registeredAt: new Date()
168
+ };
169
+ this.coordinatorAdapters.set(coordinatorId, adapter);
170
+ this.setupCoordinatorEventListeners(adapter);
171
+ this.recordEvent({
172
+ eventId: uuidv4(),
173
+ timestamp: new Date(),
174
+ eventType: 'coordinator_initialized',
175
+ eventData: {
176
+ coordinatorId,
177
+ coordinatorType: 'mesh-coordinator'
178
+ },
179
+ source: {
180
+ component: 'V1TransparencySystem',
181
+ instance: this.constructor.name
182
+ },
183
+ severity: 'info',
184
+ category: 'lifecycle'
185
+ });
186
+ this.logger.info(`MeshCoordinator registered for transparency: ${coordinatorId}`);
187
+ }
188
+ /**
189
+ * Register metrics collector for a coordinator
190
+ */ registerMetricsCollector(coordinatorId, metricsCollector) {
191
+ const adapter = this.coordinatorAdapters.get(coordinatorId);
192
+ if (adapter) {
193
+ adapter.metrics = metricsCollector;
194
+ this.logger.debug(`Metrics collector registered for coordinator: ${coordinatorId}`);
195
+ }
196
+ }
197
+ // ===========================
198
+ // Agent Monitoring
199
+ // ===========================
200
+ async getAllAgents() {
201
+ return Array.from(this.agentInfo.values());
202
+ }
203
+ async getAgentsByCoordinator(coordinatorId) {
204
+ return Array.from(this.agentInfo.values()).filter((agent)=>agent.coordinatorId === coordinatorId);
205
+ }
206
+ async getAgentsByType(agentType) {
207
+ return Array.from(this.agentInfo.values()).filter((agent)=>agent.agentType === agentType);
208
+ }
209
+ async getAgentInfo(agentId) {
210
+ const agent = this.agentInfo.get(agentId);
211
+ if (!agent) {
212
+ throw new Error(`Agent ${agentId} not found`);
213
+ }
214
+ return agent;
215
+ }
216
+ // ===========================
217
+ // Task Monitoring
218
+ // ===========================
219
+ async getAllTasks() {
220
+ return Array.from(this.taskInfo.values());
221
+ }
222
+ async getTasksByAgent(agentId) {
223
+ return Array.from(this.taskInfo.values()).filter((task)=>task.assignedAgents.includes(agentId));
224
+ }
225
+ async getTasksByStatus(status) {
226
+ return Array.from(this.taskInfo.values()).filter((task)=>task.status === status);
227
+ }
228
+ async getTaskInfo(taskId) {
229
+ const task = this.taskInfo.get(taskId);
230
+ if (!task) {
231
+ throw new Error(`Task ${taskId} not found`);
232
+ }
233
+ return task;
234
+ }
235
+ // ===========================
236
+ // Coordinator Monitoring
237
+ // ===========================
238
+ async getAllCoordinators() {
239
+ const coordinators = [];
240
+ for (const [id, adapter] of this.coordinatorAdapters.entries()){
241
+ const coordinatorInfo = {
242
+ coordinatorId: id,
243
+ coordinatorType: adapter.type,
244
+ topology: adapter.type === 'queen-agent' ? 'hierarchical' : 'mesh',
245
+ config: {
246
+ maxAgents: this.getMaxAgentsForCoordinator(adapter),
247
+ currentAgents: this.getAgentCountForCoordinator(id),
248
+ strategy: 'balanced',
249
+ enableConsensus: false
250
+ },
251
+ status: adapter.isActive ? 'active' : 'offline',
252
+ agents: (await this.getAgentsByCoordinator(id)).map((a)=>a.agentId),
253
+ tasks: (await this.getTasksByCoordinator(id)).map((t)=>t.taskId),
254
+ performance: await this.getCoordinatorPerformance(adapter),
255
+ timestamps: {
256
+ startedAt: adapter.registeredAt,
257
+ lastActivity: new Date(),
258
+ lastHealthCheck: new Date()
259
+ }
260
+ };
261
+ coordinators.push(coordinatorInfo);
262
+ }
263
+ return coordinators;
264
+ }
265
+ async getCoordinatorInfo(coordinatorId) {
266
+ const coordinators = await this.getAllCoordinators();
267
+ const coordinator = coordinators.find((c)=>c.coordinatorId === coordinatorId);
268
+ if (!coordinator) {
269
+ throw new Error(`Coordinator ${coordinatorId} not found`);
270
+ }
271
+ return coordinator;
272
+ }
273
+ async getTasksByCoordinator(coordinatorId) {
274
+ return Array.from(this.taskInfo.values()).filter((task)=>task.assignedAgents.some((agentId)=>{
275
+ const agent = this.agentInfo.get(agentId);
276
+ return agent?.coordinatorId === coordinatorId;
277
+ }));
278
+ }
279
+ async getTopologyInfo(coordinatorId) {
280
+ const adapter = this.coordinatorAdapters.get(coordinatorId);
281
+ if (!adapter) {
282
+ throw new Error(`Coordinator ${coordinatorId} not found`);
283
+ }
284
+ // Return topology-specific information
285
+ if (adapter.type === 'queen-agent') {
286
+ return {
287
+ type: 'hierarchical',
288
+ coordinatorId,
289
+ workers: await this.getAgentsByCoordinator(coordinatorId),
290
+ hierarchy: this.buildHierarchyFromQueenAgent(adapter.instance)
291
+ };
292
+ } else {
293
+ return {
294
+ type: 'mesh',
295
+ coordinatorId,
296
+ agents: await this.getAgentsByCoordinator(coordinatorId),
297
+ connections: this.getMeshConnections(adapter.instance)
298
+ };
299
+ }
300
+ }
301
+ // ===========================
302
+ // Event Streaming
303
+ // ===========================
304
+ async getRecentEvents(limit = 100, eventType) {
305
+ let events = [
306
+ ...this.transparencyEvents
307
+ ].reverse();
308
+ if (eventType) {
309
+ events = events.filter((event)=>event.eventType === eventType);
310
+ }
311
+ return events.slice(0, limit);
312
+ }
313
+ async getAgentEvents(agentId, limit = 50) {
314
+ const events = this.transparencyEvents.filter((event)=>event.eventData.agentId === agentId).reverse();
315
+ return events.slice(0, limit);
316
+ }
317
+ async getCoordinatorEvents(coordinatorId, limit = 50) {
318
+ const events = this.transparencyEvents.filter((event)=>event.eventData.coordinatorId === coordinatorId).reverse();
319
+ return events.slice(0, limit);
320
+ }
321
+ async getEventsInTimeRange(startTime, endTime, limit = 100) {
322
+ const events = this.transparencyEvents.filter((event)=>event.timestamp >= startTime && event.timestamp <= endTime).reverse();
323
+ return events.slice(0, limit);
324
+ }
325
+ // ===========================
326
+ // Metrics and Analytics
327
+ // ===========================
328
+ async getTransparencyMetrics() {
329
+ const agents = Array.from(this.agentInfo.values());
330
+ const tasks = Array.from(this.taskInfo.values());
331
+ const coordinators = Array.from(this.coordinatorAdapters.values());
332
+ // Calculate events per second
333
+ this.calculateEventsPerSecond();
334
+ return {
335
+ timestamp: new Date(),
336
+ coordinators: {
337
+ total: coordinators.length,
338
+ active: coordinators.filter((c)=>c.isActive).length,
339
+ byType: {
340
+ 'queen-agent': coordinators.filter((c)=>c.type === 'queen-agent').length,
341
+ 'mesh-coordinator': coordinators.filter((c)=>c.type === 'mesh-coordinator').length
342
+ },
343
+ byTopology: {
344
+ hierarchical: coordinators.filter((c)=>c.type === 'queen-agent').length,
345
+ mesh: coordinators.filter((c)=>c.type === 'mesh-coordinator').length
346
+ }
347
+ },
348
+ agents: {
349
+ total: agents.length,
350
+ active: agents.filter((a)=>a.status === 'busy' || a.status === 'ready' || a.status === 'working').length,
351
+ idle: agents.filter((a)=>a.status === 'idle').length,
352
+ busy: agents.filter((a)=>a.status === 'busy' || a.status === 'working').length,
353
+ degraded: agents.filter((a)=>a.status === 'degraded').length,
354
+ offline: agents.filter((a)=>a.status === 'offline').length,
355
+ byType: this.groupAgentsByType(agents),
356
+ byCoordinator: this.groupAgentsByCoordinator(agents),
357
+ averageHealth: this.calculateAverageHealth(agents),
358
+ utilizationRate: this.calculateAgentUtilization(agents)
359
+ },
360
+ tasks: {
361
+ total: tasks.length,
362
+ active: tasks.filter((t)=>t.status === 'active').length,
363
+ completed: tasks.filter((t)=>t.status === 'completed').length,
364
+ failed: tasks.filter((t)=>t.status === 'failed').length,
365
+ cancelled: tasks.filter((t)=>t.status === 'cancelled').length,
366
+ byType: this.groupTasksByType(tasks),
367
+ byPriority: this.groupTasksByPriority(tasks),
368
+ averageDuration: this.calculateAverageTaskDuration(tasks),
369
+ successRate: this.calculateTaskSuccessRate(tasks)
370
+ },
371
+ performance: {
372
+ taskThroughput: this.calculateTaskThroughput(tasks),
373
+ averageResponseTime: this.calculateAverageResponseTime(agents),
374
+ memoryUsage: this.calculateTotalMemoryUsage(agents),
375
+ cpuUsage: this.calculateTotalCpuUsage(agents),
376
+ networkIO: this.calculateTotalNetworkIO(agents),
377
+ errorRate: this.calculateErrorRate(tasks)
378
+ },
379
+ resources: {
380
+ totalResources: agents.reduce((sum, a)=>sum + a.topology.maxConnections, 0),
381
+ allocatedResources: agents.reduce((sum, a)=>sum + a.topology.connections, 0),
382
+ freeResources: agents.reduce((sum, a)=>sum + (a.topology.maxConnections - a.topology.connections), 0),
383
+ resourceUtilization: this.calculateResourceUtilization(agents),
384
+ lockContention: 0
385
+ },
386
+ events: {
387
+ totalEvents: this.transparencyEvents.length,
388
+ eventsByType: this.groupEventsByType(),
389
+ eventsBySeverity: this.groupEventsBySeverity(),
390
+ eventsByCategory: this.groupEventsByCategory(),
391
+ eventsPerSecond: this.eventsPerSecond
392
+ }
393
+ };
394
+ }
395
+ async getPerformanceAnalytics() {
396
+ const agents = Array.from(this.agentInfo.values());
397
+ const tasks = Array.from(this.taskInfo.values());
398
+ return {
399
+ agentPerformance: {
400
+ healthDistribution: this.getHealthDistribution(agents),
401
+ utilizationTrends: this.getUtilizationTrends(agents),
402
+ performanceByType: this.getPerformanceByAgentType(agents)
403
+ },
404
+ taskPerformance: {
405
+ completionRates: this.getTaskCompletionRates(tasks),
406
+ averageDurations: this.getTaskDurationsByType(tasks),
407
+ failurePatterns: this.getFailurePatterns(tasks)
408
+ },
409
+ systemPerformance: {
410
+ scalabilityMetrics: this.getScalabilityMetrics(),
411
+ bottleneckAnalysis: this.getBottleneckAnalysis(),
412
+ efficiencyMetrics: this.getEfficiencyMetrics()
413
+ }
414
+ };
415
+ }
416
+ async getTopologyAnalytics() {
417
+ const queenAgents = Array.from(this.coordinatorAdapters.values()).filter((adapter)=>adapter.type === 'queen-agent');
418
+ const meshCoordinators = Array.from(this.coordinatorAdapters.values()).filter((adapter)=>adapter.type === 'mesh-coordinator');
419
+ return {
420
+ hierarchicalTopology: {
421
+ count: queenAgents.length,
422
+ averageWorkersPerQueen: this.getAverageWorkersPerQueen(queenAgents),
423
+ hierarchyDepth: this.getHierarchyDepth(queenAgents),
424
+ efficiency: this.getHierarchicalEfficiency(queenAgents)
425
+ },
426
+ meshTopology: {
427
+ count: meshCoordinators.length,
428
+ averageConnectionsPerAgent: this.getAverageConnectionsPerAgent(meshCoordinators),
429
+ networkDiameter: this.getNetworkDiameter(meshCoordinators),
430
+ clustering: this.getMeshClusteringMetrics(meshCoordinators)
431
+ },
432
+ overallMetrics: {
433
+ totalCoordinators: this.coordinatorAdapters.size,
434
+ topologyEfficiency: this.getOverallTopologyEfficiency(),
435
+ scalingCharacteristics: this.getScalingCharacteristics()
436
+ }
437
+ };
438
+ }
439
+ // ===========================
440
+ // Event Listeners
441
+ // ===========================
442
+ async registerEventListener(listener) {
443
+ this.eventListeners.add(listener);
444
+ this.logger.debug('V1 transparency event listener registered');
445
+ }
446
+ async unregisterEventListener(listener) {
447
+ this.eventListeners.delete(listener);
448
+ this.logger.debug('V1 transparency event listener unregistered');
449
+ }
450
+ // ===========================
451
+ // Private Helper Methods
452
+ // ===========================
453
+ getDefaultConfig() {
454
+ return {
455
+ enableRealTimeMonitoring: true,
456
+ enableEventStreaming: true,
457
+ eventRetentionHours: 24,
458
+ metricsCollectionIntervalMs: 5000,
459
+ enablePerformanceMonitoring: true,
460
+ enableDependencyTracking: true,
461
+ maxEventsInMemory: 10000,
462
+ enableCoordinatorMonitoring: true,
463
+ enableHealthMonitoring: true,
464
+ enableTaskTracking: true
465
+ };
466
+ }
467
+ setupCoordinatorEventListeners(adapter) {
468
+ const { eventEmitter, id: coordinatorId } = adapter;
469
+ // Listen to all coordinator events
470
+ eventEmitter.on('workerSpawned', (data)=>this.handleWorkerSpawned(coordinatorId, data));
471
+ eventEmitter.on('workerStatusChanged', (data)=>this.handleWorkerStatusChanged(coordinatorId, data));
472
+ eventEmitter.on('taskDelegated', (data)=>this.handleTaskDelegated(coordinatorId, data));
473
+ eventEmitter.on('taskCompleted', (data)=>this.handleTaskCompleted(coordinatorId, data));
474
+ eventEmitter.on('taskFailed', (data)=>this.handleTaskFailed(coordinatorId, data));
475
+ eventEmitter.on('error', (error)=>this.handleCoordinatorError(coordinatorId, error));
476
+ // Start monitoring if already started
477
+ if (this.isMonitoring) {
478
+ this.startCoordinatorMonitoring(adapter);
479
+ }
480
+ }
481
+ startCoordinatorMonitoring(adapter) {
482
+ // Initial data collection
483
+ this.collectCoordinatorData(adapter);
484
+ }
485
+ collectCoordinatorData(adapter) {
486
+ // This would collect initial data from the coordinator
487
+ // Implementation depends on the specific coordinator type
488
+ }
489
+ collectMetrics() {
490
+ if (!this.isMonitoring) return;
491
+ // Collect metrics from all registered coordinators
492
+ for (const adapter of this.coordinatorAdapters.values()){
493
+ if (adapter.metrics) {
494
+ const metrics = adapter.metrics.getCurrentMetrics();
495
+ // Process metrics...
496
+ }
497
+ }
498
+ this.notifyMetricsUpdate();
499
+ }
500
+ performHealthChecks() {
501
+ // Perform health checks on all agents and coordinators
502
+ for (const [agentId, agent] of this.agentInfo.entries()){
503
+ const now = new Date();
504
+ const timeSinceLastActivity = now.getTime() - agent.timestamps.lastActivity.getTime();
505
+ if (timeSinceLastActivity > 300000) {
506
+ agent.status = 'degraded';
507
+ this.recordEvent({
508
+ eventId: uuidv4(),
509
+ timestamp: now,
510
+ eventType: 'agent_health_updated',
511
+ eventData: {
512
+ agentId,
513
+ previousState: agent.status,
514
+ newState: 'degraded',
515
+ reason: 'No recent activity'
516
+ },
517
+ source: {
518
+ component: 'V1TransparencySystem',
519
+ instance: 'health-check'
520
+ },
521
+ severity: 'warning',
522
+ category: 'coordination'
523
+ });
524
+ }
525
+ }
526
+ }
527
+ recordEvent(event) {
528
+ // Rate limiting check to prevent event flooding attacks
529
+ const sourceId = event.source?.instance || 'unknown';
530
+ if (!this.checkRateLimit(sourceId)) {
531
+ this.logger.warn(`Event rate limit exceeded for source: ${sourceId}`);
532
+ return; // Drop the event if rate limit exceeded
533
+ }
534
+ // Input sanitization for security
535
+ const sanitizedEvent = this.sanitizeEvent(event);
536
+ this.transparencyEvents.push(sanitizedEvent);
537
+ // Enforce event retention limit
538
+ if (this.transparencyEvents.length > this.config.maxEventsInMemory) {
539
+ const excess = this.transparencyEvents.length - this.config.maxEventsInMemory;
540
+ this.transparencyEvents.splice(0, excess);
541
+ }
542
+ // Update events per second calculation
543
+ this.recentEventTimestamps.push(sanitizedEvent.timestamp);
544
+ this.cleanupOldEventTimestamps();
545
+ // Notify listeners
546
+ this.eventListeners.forEach((listener)=>{
547
+ if (listener.onTransparencyEvent) {
548
+ try {
549
+ listener.onTransparencyEvent(sanitizedEvent);
550
+ } catch (error) {
551
+ this.logger.error('Error in transparency event listener', error);
552
+ }
553
+ }
554
+ });
555
+ this.emit('transparencyEvent', sanitizedEvent);
556
+ }
557
+ /**
558
+ * Check rate limiting for event sources to prevent DoS attacks
559
+ *
560
+ * Note: This is a basic implementation. In production, consider:
561
+ * - Distributed rate limiting for multi-instance deployments
562
+ * - Adaptive rate limits based on system load
563
+ * - Different limits for different event types/severities
564
+ * - Configurable rate limits per coordinator type
565
+ */ checkRateLimit(sourceId) {
566
+ const now = new Date();
567
+ const sourceData = this.eventCountsBySource.get(sourceId);
568
+ if (!sourceData) {
569
+ // First event from this source
570
+ this.eventCountsBySource.set(sourceId, {
571
+ count: 1,
572
+ lastReset: now
573
+ });
574
+ return true;
575
+ }
576
+ // Check if we need to reset the counter (time window passed)
577
+ const timeSinceReset = now.getTime() - sourceData.lastReset.getTime();
578
+ if (timeSinceReset > this.RATE_LIMIT_WINDOW_MS) {
579
+ // Reset counter for new time window
580
+ this.eventCountsBySource.set(sourceId, {
581
+ count: 1,
582
+ lastReset: now
583
+ });
584
+ return true;
585
+ }
586
+ // Check if source has exceeded rate limit
587
+ if (sourceData.count >= this.RATE_LIMIT_MAX_EVENTS) {
588
+ return false; // Rate limit exceeded
589
+ }
590
+ // Increment counter
591
+ sourceData.count++;
592
+ return true;
593
+ }
594
+ /**
595
+ * Sanitize event data to prevent security issues
596
+ *
597
+ * Security considerations:
598
+ * - Remove potentially malicious HTML/JS from event data
599
+ * - Limit string lengths to prevent DoS attacks
600
+ * - Validate event structure before processing
601
+ * - Rate limiting concept for event streams (implementation note)
602
+ */ sanitizeEvent(event) {
603
+ const sanitized = {
604
+ ...event
605
+ };
606
+ // Sanitize event data fields
607
+ if (sanitized.eventData) {
608
+ sanitized.eventData = this.sanitizeEventData(sanitized.eventData);
609
+ }
610
+ // Limit string lengths to prevent memory issues
611
+ if (sanitized.eventType && sanitized.eventType.length > 100) {
612
+ sanitized.eventType = sanitized.eventType.substring(0, 100);
613
+ }
614
+ if (sanitized.category && sanitized.category.length > 50) {
615
+ sanitized.category = sanitized.category.substring(0, 50);
616
+ }
617
+ // Ensure severity is valid
618
+ const validSeverities = [
619
+ 'info',
620
+ 'warning',
621
+ 'error',
622
+ 'critical'
623
+ ];
624
+ if (!validSeverities.includes(sanitized.severity)) {
625
+ sanitized.severity = 'info';
626
+ }
627
+ return sanitized;
628
+ }
629
+ /**
630
+ * Sanitize event data object to prevent injection attacks
631
+ */ sanitizeEventData(eventData) {
632
+ if (!eventData || typeof eventData !== 'object') {
633
+ return {};
634
+ }
635
+ const sanitized = {};
636
+ Object.keys(eventData).forEach((key)=>{
637
+ const value = eventData[key];
638
+ // Limit key length
639
+ const sanitizedKey = key.length > 100 ? key.substring(0, 100) : key;
640
+ // Sanitize different value types
641
+ if (typeof value === 'string') {
642
+ // Remove potential XSS patterns and limit length
643
+ const cleanValue = value.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '[SCRIPT_REMOVED]').replace(/javascript:/gi, '[JS_REMOVED]').replace(/on\w+\s*=/gi, '[EVENT_HANDLER_REMOVED]').substring(0, 1000); // Limit string length
644
+ sanitized[sanitizedKey] = cleanValue;
645
+ } else if (typeof value === 'object' && value !== null) {
646
+ // Recursively sanitize nested objects
647
+ sanitized[sanitizedKey] = this.sanitizeEventData(value);
648
+ } else {
649
+ // Keep primitive types as-is
650
+ sanitized[sanitizedKey] = value;
651
+ }
652
+ });
653
+ return sanitized;
654
+ }
655
+ notifyMetricsUpdate() {
656
+ this.getTransparencyMetrics().then((metrics)=>{
657
+ this.eventListeners.forEach((listener)=>{
658
+ if (listener.onMetricsUpdate) {
659
+ try {
660
+ listener.onMetricsUpdate(metrics);
661
+ } catch (error) {
662
+ this.logger.error('Error in metrics update listener', error);
663
+ }
664
+ }
665
+ });
666
+ this.emit('metricsUpdate', metrics);
667
+ }).catch((error)=>{
668
+ this.logger.error('Error getting transparency metrics', error);
669
+ });
670
+ }
671
+ // Event handlers
672
+ handleWorkerSpawned(coordinatorId, data) {
673
+ const agent = {
674
+ agentId: data.workerId,
675
+ agentType: data.workerType,
676
+ capabilities: data.capabilities,
677
+ status: 'idle',
678
+ level: 2,
679
+ coordinatorId,
680
+ peerAgentIds: [],
681
+ childAgentIds: [],
682
+ currentTasks: [],
683
+ taskStats: {
684
+ completed: 0,
685
+ failed: 0,
686
+ total: 0,
687
+ successRate: 100
688
+ },
689
+ health: {
690
+ successRate: 100,
691
+ averageResponseTime: 0,
692
+ errorCount: 0,
693
+ consecutiveFailures: 0,
694
+ lastHealthCheck: new Date()
695
+ },
696
+ resources: {
697
+ memoryUsage: 0,
698
+ cpuUsage: 0,
699
+ networkIO: 0
700
+ },
701
+ timestamps: {
702
+ spawnedAt: new Date(),
703
+ lastActivity: new Date(),
704
+ lastStateChange: new Date()
705
+ },
706
+ topology: {
707
+ connections: 0,
708
+ maxConnections: data.capabilities?.maxConcurrentTasks || 5,
709
+ workload: 0
710
+ },
711
+ dependencies: {
712
+ dependsOn: [],
713
+ blocksCompletion: [],
714
+ waitingFor: []
715
+ }
716
+ };
717
+ this.agentInfo.set(data.workerId, agent);
718
+ this.recordEvent({
719
+ eventId: uuidv4(),
720
+ timestamp: new Date(),
721
+ eventType: 'agent_spawned',
722
+ eventData: {
723
+ agentId: data.workerId,
724
+ coordinatorId,
725
+ agentType: data.workerType
726
+ },
727
+ source: {
728
+ component: 'V1TransparencySystem',
729
+ instance: coordinatorId
730
+ },
731
+ severity: 'info',
732
+ category: 'lifecycle'
733
+ });
734
+ }
735
+ handleWorkerStatusChanged(coordinatorId, data) {
736
+ const agent = this.agentInfo.get(data.workerId);
737
+ if (agent) {
738
+ const previousStatus = agent.status;
739
+ agent.status = data.newStatus;
740
+ agent.timestamps.lastStateChange = new Date();
741
+ this.recordEvent({
742
+ eventId: uuidv4(),
743
+ timestamp: new Date(),
744
+ eventType: 'agent_status_changed',
745
+ eventData: {
746
+ agentId: data.workerId,
747
+ coordinatorId,
748
+ previousState: previousStatus,
749
+ newState: data.newStatus,
750
+ reason: data.reason
751
+ },
752
+ source: {
753
+ component: 'V1TransparencySystem',
754
+ instance: coordinatorId
755
+ },
756
+ severity: 'info',
757
+ category: 'lifecycle'
758
+ });
759
+ }
760
+ }
761
+ handleTaskDelegated(coordinatorId, data) {
762
+ const task = {
763
+ taskId: data.taskId,
764
+ taskType: data.taskType,
765
+ description: data.description,
766
+ status: 'active',
767
+ priority: data.priority || 5,
768
+ assignedAgents: [
769
+ data.workerId
770
+ ],
771
+ dependencies: data.dependencies || [],
772
+ progress: {
773
+ percentage: 0
774
+ },
775
+ timing: {
776
+ createdAt: new Date(),
777
+ startedAt: new Date()
778
+ },
779
+ resources: {
780
+ required: data.resources || {},
781
+ used: {}
782
+ },
783
+ quality: {
784
+ confidence: 0
785
+ }
786
+ };
787
+ this.taskInfo.set(data.taskId, task);
788
+ // Update agent's current tasks
789
+ const agent = this.agentInfo.get(data.workerId);
790
+ if (agent) {
791
+ agent.currentTasks.push(data.taskId);
792
+ agent.status = 'busy';
793
+ }
794
+ this.recordEvent({
795
+ eventId: uuidv4(),
796
+ timestamp: new Date(),
797
+ eventType: 'task_assigned',
798
+ eventData: {
799
+ taskId: data.taskId,
800
+ agentId: data.workerId,
801
+ coordinatorId
802
+ },
803
+ source: {
804
+ component: 'V1TransparencySystem',
805
+ instance: coordinatorId
806
+ },
807
+ severity: 'info',
808
+ category: 'coordination'
809
+ });
810
+ }
811
+ handleTaskCompleted(coordinatorId, data) {
812
+ const task = this.taskInfo.get(data.taskId);
813
+ if (task) {
814
+ task.status = 'completed';
815
+ task.timing.completedAt = new Date();
816
+ task.result = data.result;
817
+ task.quality.confidence = data.confidence || 0.8;
818
+ // Update agent's task stats
819
+ for (const agentId of task.assignedAgents){
820
+ const agent = this.agentInfo.get(agentId);
821
+ if (agent) {
822
+ agent.taskStats.completed++;
823
+ agent.taskStats.total++;
824
+ agent.taskStats.successRate = agent.taskStats.completed / agent.taskStats.total * 100;
825
+ // Remove from current tasks
826
+ agent.currentTasks = agent.currentTasks.filter((id)=>id !== data.taskId);
827
+ if (agent.currentTasks.length === 0) {
828
+ agent.status = 'idle';
829
+ }
830
+ }
831
+ }
832
+ this.recordEvent({
833
+ eventId: uuidv4(),
834
+ timestamp: new Date(),
835
+ eventType: 'task_completed',
836
+ eventData: {
837
+ taskId: data.taskId,
838
+ agentIds: task.assignedAgents,
839
+ coordinatorId,
840
+ confidence: task.quality.confidence
841
+ },
842
+ source: {
843
+ component: 'V1TransparencySystem',
844
+ instance: coordinatorId
845
+ },
846
+ severity: 'info',
847
+ category: 'coordination'
848
+ });
849
+ }
850
+ }
851
+ handleTaskFailed(coordinatorId, data) {
852
+ const task = this.taskInfo.get(data.taskId);
853
+ if (task) {
854
+ task.status = 'failed';
855
+ task.timing.completedAt = new Date();
856
+ task.error = data.error;
857
+ // Update agent's task stats
858
+ for (const agentId of task.assignedAgents){
859
+ const agent = this.agentInfo.get(agentId);
860
+ if (agent) {
861
+ agent.taskStats.failed++;
862
+ agent.taskStats.total++;
863
+ agent.taskStats.successRate = agent.taskStats.completed / agent.taskStats.total * 100;
864
+ agent.health.errorCount++;
865
+ agent.health.consecutiveFailures++;
866
+ // Remove from current tasks
867
+ agent.currentTasks = agent.currentTasks.filter((id)=>id !== data.taskId);
868
+ if (agent.currentTasks.length === 0) {
869
+ agent.status = 'idle';
870
+ }
871
+ }
872
+ }
873
+ this.recordEvent({
874
+ eventId: uuidv4(),
875
+ timestamp: new Date(),
876
+ eventType: 'task_failed',
877
+ eventData: {
878
+ taskId: data.taskId,
879
+ agentIds: task.assignedAgents,
880
+ coordinatorId,
881
+ error: data.error
882
+ },
883
+ source: {
884
+ component: 'V1TransparencySystem',
885
+ instance: coordinatorId
886
+ },
887
+ severity: 'error',
888
+ category: 'error'
889
+ });
890
+ }
891
+ }
892
+ handleCoordinatorError(coordinatorId, error) {
893
+ this.recordEvent({
894
+ eventId: uuidv4(),
895
+ timestamp: new Date(),
896
+ eventType: 'error_occurred',
897
+ eventData: {
898
+ coordinatorId,
899
+ error: error.message,
900
+ stack: error.stack
901
+ },
902
+ source: {
903
+ component: 'V1TransparencySystem',
904
+ instance: coordinatorId
905
+ },
906
+ severity: 'error',
907
+ category: 'error'
908
+ });
909
+ }
910
+ // Helper methods for metrics calculation
911
+ calculateEventsPerSecond() {
912
+ const now = new Date();
913
+ const oneSecondAgo = new Date(now.getTime() - 1000);
914
+ const recentEvents = this.recentEventTimestamps.filter((timestamp)=>timestamp >= oneSecondAgo);
915
+ this.eventsPerSecond = recentEvents.length;
916
+ }
917
+ cleanupOldEventTimestamps() {
918
+ const fiveMinutesAgo = new Date(Date.now() - 300000);
919
+ this.recentEventTimestamps = this.recentEventTimestamps.filter((timestamp)=>timestamp >= fiveMinutesAgo);
920
+ }
921
+ groupAgentsByType(agents) {
922
+ const groups = {};
923
+ agents.forEach((agent)=>{
924
+ groups[agent.agentType] = (groups[agent.agentType] || 0) + 1;
925
+ });
926
+ return groups;
927
+ }
928
+ groupAgentsByCoordinator(agents) {
929
+ const groups = {};
930
+ agents.forEach((agent)=>{
931
+ groups[agent.coordinatorId] = (groups[agent.coordinatorId] || 0) + 1;
932
+ });
933
+ return groups;
934
+ }
935
+ calculateAverageHealth(agents) {
936
+ if (agents.length === 0) return 100;
937
+ const totalHealth = agents.reduce((sum, agent)=>sum + agent.health.successRate, 0);
938
+ return totalHealth / agents.length;
939
+ }
940
+ calculateAgentUtilization(agents) {
941
+ if (agents.length === 0) return 0;
942
+ const busyAgents = agents.filter((agent)=>agent.status === 'busy' || agent.status === 'working').length;
943
+ return busyAgents / agents.length * 100;
944
+ }
945
+ groupTasksByType(tasks) {
946
+ const groups = {};
947
+ tasks.forEach((task)=>{
948
+ groups[task.taskType] = (groups[task.taskType] || 0) + 1;
949
+ });
950
+ return groups;
951
+ }
952
+ groupTasksByPriority(tasks) {
953
+ const groups = {};
954
+ tasks.forEach((task)=>{
955
+ const priorityKey = `priority_${task.priority}`;
956
+ groups[priorityKey] = (groups[priorityKey] || 0) + 1;
957
+ });
958
+ return groups;
959
+ }
960
+ calculateAverageTaskDuration(tasks) {
961
+ const completedTasks = tasks.filter((task)=>task.timing.completedAt && task.timing.startedAt);
962
+ if (completedTasks.length === 0) return 0;
963
+ const totalDuration = completedTasks.reduce((sum, task)=>{
964
+ return sum + (task.timing.completedAt.getTime() - task.timing.startedAt.getTime());
965
+ }, 0);
966
+ return totalDuration / completedTasks.length;
967
+ }
968
+ calculateTaskSuccessRate(tasks) {
969
+ const completedTasks = tasks.filter((task)=>task.status === 'completed' || task.status === 'failed');
970
+ if (completedTasks.length === 0) return 100;
971
+ const successfulTasks = completedTasks.filter((task)=>task.status === 'completed').length;
972
+ return successfulTasks / completedTasks.length * 100;
973
+ }
974
+ calculateTaskThroughput(tasks) {
975
+ const now = new Date();
976
+ const oneHourAgo = new Date(now.getTime() - 3600000);
977
+ const recentTasks = tasks.filter((task)=>task.timing.completedAt && task.timing.completedAt >= oneHourAgo);
978
+ return recentTasks.length; // tasks per hour
979
+ }
980
+ calculateAverageResponseTime(agents) {
981
+ if (agents.length === 0) return 0;
982
+ const totalResponseTime = agents.reduce((sum, agent)=>sum + agent.health.averageResponseTime, 0);
983
+ return totalResponseTime / agents.length;
984
+ }
985
+ calculateTotalMemoryUsage(agents) {
986
+ return agents.reduce((sum, agent)=>sum + agent.resources.memoryUsage, 0);
987
+ }
988
+ calculateTotalCpuUsage(agents) {
989
+ if (agents.length === 0) return 0;
990
+ const totalCpu = agents.reduce((sum, agent)=>sum + agent.resources.cpuUsage, 0);
991
+ return totalCpu / agents.length;
992
+ }
993
+ calculateTotalNetworkIO(agents) {
994
+ return agents.reduce((sum, agent)=>sum + agent.resources.networkIO, 0);
995
+ }
996
+ calculateErrorRate(tasks) {
997
+ const totalTasks = tasks.length;
998
+ const failedTasks = tasks.filter((task)=>task.status === 'failed').length;
999
+ return totalTasks > 0 ? failedTasks / totalTasks * 100 : 0;
1000
+ }
1001
+ calculateResourceUtilization(agents) {
1002
+ if (agents.length === 0) return 0;
1003
+ const totalAllocated = agents.reduce((sum, agent)=>sum + agent.topology.connections, 0);
1004
+ const totalAvailable = agents.reduce((sum, agent)=>sum + agent.topology.maxConnections, 0);
1005
+ return totalAvailable > 0 ? totalAllocated / totalAvailable * 100 : 0;
1006
+ }
1007
+ groupEventsByType() {
1008
+ const groups = {};
1009
+ this.transparencyEvents.forEach((event)=>{
1010
+ groups[event.eventType] = (groups[event.eventType] || 0) + 1;
1011
+ });
1012
+ return groups;
1013
+ }
1014
+ groupEventsBySeverity() {
1015
+ const groups = {};
1016
+ this.transparencyEvents.forEach((event)=>{
1017
+ groups[event.severity] = (groups[event.severity] || 0) + 1;
1018
+ });
1019
+ return groups;
1020
+ }
1021
+ groupEventsByCategory() {
1022
+ const groups = {};
1023
+ this.transparencyEvents.forEach((event)=>{
1024
+ groups[event.category] = (groups[event.category] || 0) + 1;
1025
+ });
1026
+ return groups;
1027
+ }
1028
+ // Additional helper methods for analytics
1029
+ getHealthDistribution(agents) {
1030
+ const distribution = {
1031
+ excellent: 0,
1032
+ good: 0,
1033
+ fair: 0,
1034
+ poor: 0
1035
+ };
1036
+ agents.forEach((agent)=>{
1037
+ const health = agent.health.successRate;
1038
+ if (health >= 90) distribution.excellent++;
1039
+ else if (health >= 75) distribution.good++;
1040
+ else if (health >= 60) distribution.fair++;
1041
+ else distribution.poor++;
1042
+ });
1043
+ return distribution;
1044
+ }
1045
+ getUtilizationTrends(agents) {
1046
+ // Simple implementation - in real system, this would track trends over time
1047
+ const utilization = this.calculateAgentUtilization(agents);
1048
+ return {
1049
+ current: utilization,
1050
+ trend: 'stable',
1051
+ forecast: utilization
1052
+ };
1053
+ }
1054
+ getPerformanceByAgentType(agents) {
1055
+ const performanceByType = {};
1056
+ agents.forEach((agent)=>{
1057
+ if (!performanceByType[agent.agentType]) {
1058
+ performanceByType[agent.agentType] = {
1059
+ count: 0,
1060
+ averageHealth: 0,
1061
+ averageUtilization: 0,
1062
+ totalTasks: 0
1063
+ };
1064
+ }
1065
+ const typeData = performanceByType[agent.agentType];
1066
+ typeData.count++;
1067
+ typeData.averageHealth += agent.health.successRate;
1068
+ typeData.totalTasks += agent.taskStats.total;
1069
+ });
1070
+ // Calculate averages
1071
+ Object.values(performanceByType).forEach((data)=>{
1072
+ if (data.count > 0) {
1073
+ data.averageHealth /= data.count;
1074
+ data.averageUtilization = data.count > 0 ? 100 : 0; // Simplified
1075
+ }
1076
+ });
1077
+ return performanceByType;
1078
+ }
1079
+ // Additional methods would be implemented here for complete functionality...
1080
+ getMaxAgentsForCoordinator(adapter) {
1081
+ // Extract max agents from coordinator instance
1082
+ return 50; // Default value
1083
+ }
1084
+ getAgentCountForCoordinator(coordinatorId) {
1085
+ return this.agentInfo.size; // Simplified
1086
+ }
1087
+ async getCoordinatorPerformance(adapter) {
1088
+ return {
1089
+ taskThroughput: 10,
1090
+ agentUtilization: 75,
1091
+ averageResponseTime: 150,
1092
+ errorRate: 2
1093
+ };
1094
+ }
1095
+ buildHierarchyFromQueenAgent(queenAgent) {
1096
+ // Build hierarchy from QueenAgent instance
1097
+ return {
1098
+ level: 1,
1099
+ type: 'queen-agent',
1100
+ children: this.getAgentCountForCoordinator(queenAgent.toString())
1101
+ };
1102
+ }
1103
+ getAgentCountForCoordinator(coordinatorId) {
1104
+ return Array.from(this.agentInfo.values()).filter((agent)=>agent.coordinatorId === coordinatorId).length;
1105
+ }
1106
+ getMeshConnections(meshCoordinator) {
1107
+ // Get connection information from MeshCoordinator
1108
+ return {
1109
+ totalConnections: 0,
1110
+ averageConnectionsPerAgent: 0
1111
+ };
1112
+ }
1113
+ // Analytics implementations
1114
+ /**
1115
+ * Calculate task completion rates by task type and status
1116
+ */ getTaskCompletionRates(tasks) {
1117
+ const totalTasks = tasks.length;
1118
+ if (totalTasks === 0) return {
1119
+ overall: 0,
1120
+ byType: {}
1121
+ };
1122
+ const completedTasks = tasks.filter((task)=>task.status === 'completed').length;
1123
+ const rates = {
1124
+ overall: completedTasks / totalTasks * 100,
1125
+ byType: {}
1126
+ };
1127
+ // Calculate completion rates by task type
1128
+ const tasksByType = {};
1129
+ tasks.forEach((task)=>{
1130
+ if (!tasksByType[task.taskType]) {
1131
+ tasksByType[task.taskType] = [];
1132
+ }
1133
+ tasksByType[task.taskType].push(task);
1134
+ });
1135
+ Object.entries(tasksByType).forEach(([type, typeTasks])=>{
1136
+ const completed = typeTasks.filter((task)=>task.status === 'completed').length;
1137
+ rates.byType[type] = typeTasks.length > 0 ? completed / typeTasks.length * 100 : 0;
1138
+ });
1139
+ return rates;
1140
+ }
1141
+ /**
1142
+ * Analyze task durations by type for performance insights
1143
+ */ getTaskDurationsByType(tasks) {
1144
+ const durationsByType = {};
1145
+ tasks.forEach((task)=>{
1146
+ if (!durationsByType[task.taskType]) {
1147
+ durationsByType[task.taskType] = {
1148
+ durations: [],
1149
+ count: 0
1150
+ };
1151
+ }
1152
+ if (task.timing.completedAt && task.timing.startedAt) {
1153
+ const duration = task.timing.completedAt.getTime() - task.timing.startedAt.getTime();
1154
+ durationsByType[task.taskType].durations.push(duration);
1155
+ durationsByType[task.taskType].count++;
1156
+ }
1157
+ });
1158
+ const stats = {};
1159
+ Object.entries(durationsByType).forEach(([type, data])=>{
1160
+ if (data.durations.length > 0) {
1161
+ data.durations.sort((a, b)=>a - b);
1162
+ const sum = data.durations.reduce((acc, val)=>acc + val, 0);
1163
+ stats[type] = {
1164
+ average: sum / data.durations.length,
1165
+ median: data.durations[Math.floor(data.durations.length / 2)],
1166
+ min: Math.min(...data.durations),
1167
+ max: Math.max(...data.durations),
1168
+ count: data.count
1169
+ };
1170
+ }
1171
+ });
1172
+ return stats;
1173
+ }
1174
+ /**
1175
+ * Identify failure patterns in tasks for debugging and optimization
1176
+ */ getFailurePatterns(tasks) {
1177
+ const failedTasks = tasks.filter((task)=>task.status === 'failed');
1178
+ if (failedTasks.length === 0) {
1179
+ return {
1180
+ totalFailures: 0,
1181
+ patterns: []
1182
+ };
1183
+ }
1184
+ const patterns = {
1185
+ byType: {},
1186
+ byAgent: {},
1187
+ byErrorType: {},
1188
+ commonErrors: []
1189
+ };
1190
+ failedTasks.forEach((task)=>{
1191
+ // Group by task type
1192
+ patterns.byType[task.taskType] = (patterns.byType[task.taskType] || 0) + 1;
1193
+ // Group by assigned agents
1194
+ task.assignedAgents.forEach((agentId)=>{
1195
+ patterns.byAgent[agentId] = (patterns.byAgent[agentId] || 0) + 1;
1196
+ });
1197
+ // Extract error patterns from task metadata or results
1198
+ if (task.error && typeof task.error === 'object' && task.error.type) {
1199
+ patterns.byErrorType[task.error.type] = (patterns.byErrorType[task.error.type] || 0) + 1;
1200
+ }
1201
+ });
1202
+ // Identify most common failures
1203
+ patterns.commonErrors = Object.entries(patterns.byType).sort(([, a], [, b])=>b - a).slice(0, 5).map(([type, count])=>`${type}: ${count} failures`);
1204
+ return {
1205
+ totalFailures: failedTasks.length,
1206
+ failureRate: failedTasks.length / tasks.length * 100,
1207
+ patterns
1208
+ };
1209
+ }
1210
+ /**
1211
+ * Calculate scalability metrics for system capacity planning
1212
+ */ getScalabilityMetrics() {
1213
+ const activeAgents = this.agentInfo.size;
1214
+ const totalTasks = this.taskInfo.size;
1215
+ const activeCoordinators = this.coordinatorAdapters.size;
1216
+ return {
1217
+ currentCapacity: {
1218
+ agents: activeAgents,
1219
+ tasks: totalTasks,
1220
+ coordinators: activeCoordinators
1221
+ },
1222
+ utilization: {
1223
+ agentUtilization: this.calculateAgentUtilization(Array.from(this.agentInfo.values())),
1224
+ taskThroughput: totalTasks > 0 ? this.taskInfo.size / activeAgents : 0,
1225
+ coordinatorLoad: activeCoordinators > 0 ? activeAgents / activeCoordinators : 0
1226
+ },
1227
+ scalingLimits: {
1228
+ maxAgents: this.config.maxAgents || 100,
1229
+ maxTasksPerAgent: 10,
1230
+ maxCoordinators: 20
1231
+ }
1232
+ };
1233
+ }
1234
+ /**
1235
+ * Analyze system bottlenecks for performance optimization
1236
+ */ getBottleneckAnalysis() {
1237
+ const bottlenecks = [];
1238
+ const agents = Array.from(this.agentInfo.values());
1239
+ // Check for overloaded agents
1240
+ const overloadedAgents = agents.filter((agent)=>agent.currentTasks.length > agent.capabilities.maxConcurrentTasks);
1241
+ if (overloadedAgents.length > 0) {
1242
+ bottlenecks.push({
1243
+ type: 'agent_overload',
1244
+ severity: 'high',
1245
+ description: `${overloadedAgents.length} agents exceeding task capacity`,
1246
+ affectedAgents: overloadedAgents.map((a)=>a.agentId)
1247
+ });
1248
+ }
1249
+ // Check for idle agents
1250
+ const idleAgents = agents.filter((agent)=>agent.status === 'idle' && agent.currentTasks.length === 0);
1251
+ if (idleAgents.length > agents.length * 0.5) {
1252
+ bottlenecks.push({
1253
+ type: 'agent_underutilization',
1254
+ severity: 'medium',
1255
+ description: `${idleAgents.length} agents idle while tasks may be pending`,
1256
+ affectedAgents: idleAgents.map((a)=>a.agentId)
1257
+ });
1258
+ }
1259
+ // Check for coordinator bottlenecks
1260
+ const coordinatorLoads = {};
1261
+ agents.forEach((agent)=>{
1262
+ if (agent.coordinatorId) {
1263
+ coordinatorLoads[agent.coordinatorId] = (coordinatorLoads[agent.coordinatorId] || 0) + 1;
1264
+ }
1265
+ });
1266
+ Object.entries(coordinatorLoads).forEach(([coordinatorId, load])=>{
1267
+ if (load > 20) {
1268
+ bottlenecks.push({
1269
+ type: 'coordinator_overload',
1270
+ severity: 'medium',
1271
+ description: `Coordinator ${coordinatorId} managing ${load} agents`,
1272
+ coordinatorId,
1273
+ load
1274
+ });
1275
+ }
1276
+ });
1277
+ return {
1278
+ bottlenecks,
1279
+ bottleneckCount: bottlenecks.length,
1280
+ recommendations: this.generateBottleneckRecommendations(bottlenecks)
1281
+ };
1282
+ }
1283
+ /**
1284
+ * Generate optimization recommendations based on bottlenecks
1285
+ */ generateBottleneckRecommendations(bottlenecks) {
1286
+ const recommendations = [];
1287
+ bottlenecks.forEach((bottleneck)=>{
1288
+ switch(bottleneck.type){
1289
+ case 'agent_overload':
1290
+ recommendations.push('Reduce task assignment to overloaded agents or spawn additional agents');
1291
+ break;
1292
+ case 'agent_underutilization':
1293
+ recommendations.push('Optimize task distribution to utilize idle agents more effectively');
1294
+ break;
1295
+ case 'coordinator_overload':
1296
+ recommendations.push('Consider adding additional coordinators or rebalancing agent distribution');
1297
+ break;
1298
+ }
1299
+ });
1300
+ return recommendations;
1301
+ }
1302
+ /**
1303
+ * Calculate system efficiency metrics
1304
+ */ getEfficiencyMetrics() {
1305
+ const agents = Array.from(this.agentInfo.values());
1306
+ const tasks = Array.from(this.taskInfo.values());
1307
+ const completedTasks = tasks.filter((task)=>task.status === 'completed');
1308
+ const failedTasks = tasks.filter((task)=>task.status === 'failed');
1309
+ return {
1310
+ taskEfficiency: tasks.length > 0 ? completedTasks.length / tasks.length * 100 : 0,
1311
+ agentEfficiency: this.calculateAgentUtilization(agents),
1312
+ successRate: tasks.length > 0 ? completedTasks.length / tasks.length * 100 : 0,
1313
+ errorRate: tasks.length > 0 ? failedTasks.length / tasks.length * 100 : 0,
1314
+ averageTaskCompletionTime: this.calculateAverageCompletionTime(completedTasks)
1315
+ };
1316
+ }
1317
+ /**
1318
+ * Calculate average task completion time
1319
+ */ calculateAverageCompletionTime(completedTasks) {
1320
+ if (completedTasks.length === 0) return 0;
1321
+ const totalDuration = completedTasks.reduce((sum, task)=>{
1322
+ if (task.timing.completedAt && task.timing.startedAt) {
1323
+ return sum + (task.timing.completedAt.getTime() - task.timing.startedAt.getTime());
1324
+ }
1325
+ return sum;
1326
+ }, 0);
1327
+ return totalDuration / completedTasks.length;
1328
+ }
1329
+ // Hierarchical topology metrics
1330
+ getAverageWorkersPerQueen(queenAgents) {
1331
+ if (queenAgents.length === 0) return 0;
1332
+ const totalWorkers = queenAgents.reduce((sum, queen)=>{
1333
+ const workers = Array.from(this.agentInfo.values()).filter((agent)=>agent.coordinatorId === queen.id);
1334
+ return sum + workers.length;
1335
+ }, 0);
1336
+ return totalWorkers / queenAgents.length;
1337
+ }
1338
+ getHierarchyDepth(queenAgents) {
1339
+ // Simple implementation - count coordinator levels
1340
+ if (queenAgents.length === 0) return 0;
1341
+ let maxDepth = 1;
1342
+ const visited = new Set();
1343
+ const calculateDepth = (coordinatorId, currentDepth)=>{
1344
+ if (visited.has(coordinatorId)) return currentDepth;
1345
+ visited.add(coordinatorId);
1346
+ const children = Array.from(this.agentInfo.values()).filter((agent)=>agent.coordinatorId === coordinatorId);
1347
+ if (children.length === 0) return currentDepth;
1348
+ return Math.max(...children.map((child)=>calculateDepth(child.agentId, currentDepth + 1)));
1349
+ };
1350
+ queenAgents.forEach((queen)=>{
1351
+ maxDepth = Math.max(maxDepth, calculateDepth(queen.id, 1));
1352
+ });
1353
+ return maxDepth;
1354
+ }
1355
+ getHierarchicalEfficiency(queenAgents) {
1356
+ if (queenAgents.length === 0) return 0;
1357
+ const totalAgents = this.agentInfo.size;
1358
+ const queenAgentsCount = queenAgents.length;
1359
+ // Efficiency based on optimal span of control (5-10 agents per queen)
1360
+ const optimalSpan = 7;
1361
+ const actualSpan = totalAgents / queenAgentsCount;
1362
+ const spanEfficiency = Math.max(0, 100 - Math.abs(actualSpan - optimalSpan) * 5);
1363
+ return Math.round(spanEfficiency);
1364
+ }
1365
+ // Mesh topology metrics
1366
+ getAverageConnectionsPerAgent(meshCoordinators) {
1367
+ const agents = Array.from(this.agentInfo.values());
1368
+ if (agents.length === 0) return 0;
1369
+ // Calculate average connections based on agent collaboration
1370
+ let totalConnections = 0;
1371
+ agents.forEach((agent)=>{
1372
+ // Estimate connections based on shared tasks and coordinator relationships
1373
+ const sharedTasks = Array.from(this.taskInfo.values()).filter((task)=>task.assignedAgents.includes(agent.agentId) && task.assignedAgents.length > 1);
1374
+ totalConnections += sharedTasks.length;
1375
+ });
1376
+ return totalConnections / agents.length;
1377
+ }
1378
+ getNetworkDiameter(meshCoordinators) {
1379
+ // Simplified network diameter calculation
1380
+ // In a real implementation, this would use graph algorithms
1381
+ const agentCount = this.agentInfo.size;
1382
+ const coordinatorCount = meshCoordinators.length;
1383
+ if (agentCount === 0) return 0;
1384
+ // Estimate diameter based on network size and topology
1385
+ return Math.ceil(Math.log2(agentCount + coordinatorCount));
1386
+ }
1387
+ getMeshClusteringMetrics(meshCoordinators) {
1388
+ const agents = Array.from(this.agentInfo.values());
1389
+ const tasks = Array.from(this.taskInfo.values());
1390
+ // Calculate clustering coefficient based on task collaboration
1391
+ let totalTriangles = 0;
1392
+ let possibleTriangles = 0;
1393
+ agents.forEach((agent)=>{
1394
+ const collaborators = new Set();
1395
+ tasks.forEach((task)=>{
1396
+ if (task.assignedAgents.includes(agent.agentId)) {
1397
+ task.assignedAgents.forEach((otherAgent)=>{
1398
+ if (otherAgent !== agent.agentId) {
1399
+ collaborators.add(otherAgent);
1400
+ }
1401
+ });
1402
+ }
1403
+ });
1404
+ const collaboratorList = Array.from(collaborators);
1405
+ if (collaboratorList.length >= 2) {
1406
+ possibleTriangles += collaboratorList.length * (collaboratorList.length - 1) / 2;
1407
+ // Count actual triangles (simplified)
1408
+ for(let i = 0; i < collaboratorList.length; i++){
1409
+ for(let j = i + 1; j < collaboratorList.length; j++){
1410
+ // Check if these collaborators also work together
1411
+ const sharedTasks = tasks.filter((task)=>task.assignedAgents.includes(collaboratorList[i]) && task.assignedAgents.includes(collaboratorList[j]));
1412
+ if (sharedTasks.length > 0) {
1413
+ totalTriangles++;
1414
+ }
1415
+ }
1416
+ }
1417
+ }
1418
+ });
1419
+ const clusteringCoefficient = possibleTriangles > 0 ? totalTriangles / possibleTriangles : 0;
1420
+ return {
1421
+ clusteringCoefficient,
1422
+ totalClusters: Math.round(agents.length * clusteringCoefficient),
1423
+ averageClusterSize: clusteringCoefficient > 0 ? Math.round(agents.length / (agents.length * clusteringCoefficient)) : 0
1424
+ };
1425
+ }
1426
+ getOverallTopologyEfficiency() {
1427
+ const agents = Array.from(this.agentInfo.values());
1428
+ const tasks = Array.from(this.taskInfo.values());
1429
+ if (agents.length === 0 || tasks.length === 0) return 0;
1430
+ // Calculate efficiency based on multiple factors
1431
+ const utilizationEfficiency = this.calculateAgentUtilization(agents);
1432
+ const taskSuccessRate = this.getTaskCompletionRates(tasks).overall;
1433
+ const collaborationEfficiency = Math.min(this.getAverageConnectionsPerAgent([]) * 10, 100); // Scale to 0-100
1434
+ return Math.round((utilizationEfficiency + taskSuccessRate + collaborationEfficiency) / 3);
1435
+ }
1436
+ getScalingCharacteristics() {
1437
+ const currentLoad = this.agentInfo.size;
1438
+ const taskLoad = this.taskInfo.size;
1439
+ return {
1440
+ currentScale: {
1441
+ agents: currentLoad,
1442
+ tasks: taskLoad,
1443
+ coordinators: this.coordinatorAdapters.size
1444
+ },
1445
+ scalingLimits: {
1446
+ maxAgents: this.config.maxAgents || 100,
1447
+ maxTasks: this.config.maxEventsInMemory || 1000,
1448
+ maxCoordinators: 20
1449
+ },
1450
+ scalingRecommendations: this.generateScalingRecommendations(currentLoad, taskLoad)
1451
+ };
1452
+ }
1453
+ generateScalingRecommendations(currentAgents, currentTasks) {
1454
+ const recommendations = [];
1455
+ if (currentAgents > (this.config.maxAgents || 100) * 0.8) {
1456
+ recommendations.push('Approaching agent limit - consider scaling coordinator infrastructure');
1457
+ }
1458
+ if (currentTasks > currentAgents * 8) {
1459
+ recommendations.push('High task-to-agent ratio - consider spawning additional agents');
1460
+ }
1461
+ if (currentAgents < (this.config.maxAgents || 100) * 0.3 && currentTasks > 0) {
1462
+ recommendations.push('Low agent utilization - optimize task distribution or reduce agent count');
1463
+ }
1464
+ return recommendations;
1465
+ }
1466
+ }
1467
+
1468
+ //# sourceMappingURL=v1-transparency-adapter.js.map