hedgequantx 2.5.13 → 2.5.15

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.
@@ -0,0 +1,713 @@
1
+ /**
2
+ * AI Supervisor
3
+ * Manages AI supervision of algo trading
4
+ */
5
+
6
+ let aiService = null;
7
+
8
+ // Lazy load to avoid circular dependency
9
+ const getAIService = () => {
10
+ if (!aiService) {
11
+ aiService = require('./index');
12
+ }
13
+ return aiService;
14
+ };
15
+
16
+ // In-memory supervision sessions
17
+ const supervisionSessions = new Map();
18
+
19
+ // Consensus supervision interval
20
+ let consensusInterval = null;
21
+
22
+ /**
23
+ * AI Supervisor Class
24
+ */
25
+ class AISupervisor {
26
+ /**
27
+ * Start supervision for an agent
28
+ */
29
+ static start(agentId, targetAlgo) {
30
+ if (supervisionSessions.has(agentId)) {
31
+ console.log(`Supervision already active for agent ${agentId}`);
32
+ return false;
33
+ }
34
+
35
+ const agentInfo = getAIService().getAgent(agentId);
36
+ if (!agentInfo) {
37
+ console.log(`Agent ${agentId} not found`);
38
+ return false;
39
+ }
40
+
41
+ const session = {
42
+ agentId,
43
+ agent: agentInfo,
44
+ algo: targetAlgo,
45
+ startTime: Date.now(),
46
+ lastCheck: Date.now(),
47
+ decisions: [],
48
+ metrics: {
49
+ totalDecisions: 0,
50
+ interventions: 0,
51
+ optimizations: 0,
52
+ riskWarnings: 0
53
+ },
54
+ interval: null
55
+ };
56
+
57
+ // Check if this is the first agent or if we need consensus mode
58
+ const currentSessionCount = supervisionSessions.size;
59
+
60
+ if (currentSessionCount === 0) {
61
+ // First agent - start individual supervision
62
+ session.interval = setInterval(() => {
63
+ this.supervise(agentId);
64
+ }, 5000);
65
+
66
+ supervisionSessions.set(agentId, session);
67
+ console.log(`AI supervision started: ${agentInfo.name} monitoring HQX algo`);
68
+ console.log(` Mode: Single agent supervision`);
69
+
70
+ } else {
71
+ // Additional agent - switch to consensus mode
72
+ console.log(`Adding ${agentInfo.name} to supervision`);
73
+ console.log(` Total agents: ${currentSessionCount + 1}`);
74
+
75
+ // Stop individual loops and start consensus loop
76
+ this.switchToConsensusMode();
77
+
78
+ session.interval = null; // Will use consensus loop
79
+ supervisionSessions.set(agentId, session);
80
+ }
81
+
82
+ return true;
83
+ }
84
+
85
+ /**
86
+ * Switch to consensus mode when multiple agents
87
+ */
88
+ static switchToConsensusMode() {
89
+ console.log(`\nšŸ¤ SWITCHING TO MULTI-AGENT CONSENSUS MODE`);
90
+
91
+ // Clear all individual intervals
92
+ for (const [agentId, session] of supervisionSessions.entries()) {
93
+ if (session.interval) {
94
+ clearInterval(session.interval);
95
+ session.interval = null;
96
+ }
97
+ }
98
+
99
+ // Start single consensus loop
100
+ if (!this.consensusInterval) {
101
+ this.consensusInterval = setInterval(() => {
102
+ this.superviseConsensus();
103
+ }, 5000);
104
+
105
+ console.log(` Consensus loop started - all agents will vote on decisions`);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Start supervision for an agent
111
+ */
112
+ static start(agentId, targetAlgo) {
113
+ if (supervisionSessions.has(agentId)) {
114
+ console.log(`Supervision already active for agent ${agentId}`);
115
+ return false;
116
+ }
117
+
118
+ const agent = getAIService().getAgent(agentId);
119
+ if (!agent) {
120
+ console.log(`Agent ${agentId} not found`);
121
+ return false;
122
+ }
123
+
124
+ const session = {
125
+ agentId,
126
+ agent: agent,
127
+ algo: targetAlgo,
128
+ startTime: Date.now(),
129
+ lastCheck: Date.now(),
130
+ decisions: [],
131
+ metrics: {
132
+ totalDecisions: 0,
133
+ interventions: 0,
134
+ optimizations: 0,
135
+ riskWarnings: 0
136
+ },
137
+ interval: null
138
+ };
139
+
140
+ // Start supervision loop (every 5 seconds)
141
+ session.interval = setInterval(() => {
142
+ this.supervise(agentId);
143
+ }, 5000);
144
+
145
+ supervisionSessions.set(agentId, session);
146
+ console.log(`AI supervision started: ${agent.name} monitoring HQX algo`);
147
+
148
+ return true;
149
+ }
150
+
151
+ /**
152
+ * Stop supervision for an agent
153
+ */
154
+ static stop(agentId) {
155
+ const session = supervisionSessions.get(agentId);
156
+ if (!session) {
157
+ return false;
158
+ }
159
+
160
+ if (session.interval) {
161
+ clearInterval(session.interval);
162
+ }
163
+
164
+ const duration = Date.now() - session.startTime;
165
+ supervisionSessions.delete(agentId);
166
+
167
+ console.log(`AI supervision stopped for ${session.agent.name}`);
168
+ console.log(`Session duration: ${Math.round(duration / 1000)}s`);
169
+ console.log(`Decisions: ${session.metrics.totalDecisions}, Interventions: ${session.metrics.interventions}`);
170
+
171
+ // Check if we need to switch back to single agent mode
172
+ const remainingSessions = supervisionSessions.size;
173
+ if (remainingSessions === 1 && consensusInterval) {
174
+ // Last agent - switch back to single mode
175
+ clearInterval(consensusInterval);
176
+ consensusInterval = null;
177
+
178
+ const remainingSession = supervisionSessions.values().next().value;
179
+ if (remainingSession && !remainingSession.interval) {
180
+ const remainingAgentId = remainingSession.agentId;
181
+ remainingSession.interval = setInterval(() => {
182
+ this.supervise(remainingAgentId);
183
+ }, 5000);
184
+
185
+ console.log(`Switched back to single agent supervision for ${remainingSession.agent.name}`);
186
+ }
187
+ } else if (remainingSessions === 0 && consensusInterval) {
188
+ // No agents left
189
+ clearInterval(consensusInterval);
190
+ consensusInterval = null;
191
+ }
192
+
193
+ return true;
194
+ }
195
+
196
+ /**
197
+ * Main supervision loop - single agent
198
+ */
199
+ static async supervise(agentId) {
200
+ const session = supervisionSessions.get(agentId);
201
+ if (!session) return;
202
+
203
+ try {
204
+ session.lastCheck = Date.now();
205
+
206
+ // Get algo status
207
+ const algoStatus = this.getAlgoStatus(session.algo);
208
+ const marketData = this.getMarketData();
209
+ const riskMetrics = this.getRiskMetrics(session.algo);
210
+
211
+ // Make AI decision
212
+ const decision = await this.makeAIDecision(session.agent, algoStatus, marketData, riskMetrics);
213
+
214
+ if (decision) {
215
+ session.decisions.push(decision);
216
+ session.metrics.totalDecisions++;
217
+
218
+ // Execute decision if confidence is high enough
219
+ if (decision.confidence > 75) {
220
+ await this.executeDecision(session, decision);
221
+ }
222
+ }
223
+
224
+ } catch (error) {
225
+ console.log(`Supervision error for agent ${agentId}: ${error.message}`);
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Multi-agent consensus supervision loop
231
+ */
232
+ static async superviseConsensus() {
233
+ const allSessions = Array.from(supervisionSessions.entries());
234
+ if (allSessions.length === 0) return;
235
+
236
+ try {
237
+ // Get all active agents
238
+ const allAgents = allSessions.map(([id, session]) => session.agent).filter(Boolean);
239
+
240
+ if (allAgents.length === 0) return;
241
+
242
+ console.log(`šŸ¤ MULTI-AGENT CONSENSUS: ${allAgents.length} agents participating`);
243
+
244
+ // Get algo status (use same algo for all agents)
245
+ const mockAlgo = { name: 'HQX Ultra Scalping' }; // Would be real algo
246
+ const algoStatus = this.getAlgoStatus(mockAlgo);
247
+ const marketData = this.getMarketData();
248
+ const riskMetrics = this.getRiskMetrics(mockAlgo);
249
+
250
+ // Make consensus decision
251
+ const consensusDecision = await this.makeConsensusDecision(allAgents, algoStatus, marketData, riskMetrics);
252
+
253
+ if (consensusDecision) {
254
+ // Update all sessions with the consensus decision
255
+ for (const [agentId, session] of allSessions) {
256
+ session.decisions.push({
257
+ ...consensusDecision,
258
+ timestamp: Date.now(),
259
+ isConsensus: true,
260
+ participantAgents: consensusDecision.agentNames
261
+ });
262
+
263
+ session.metrics.totalDecisions++;
264
+
265
+ // Execute decision if confidence is high enough (lower threshold for consensus)
266
+ if (consensusDecision.confidence > 70) {
267
+ await this.executeConsensusDecision(session, consensusDecision);
268
+ }
269
+ }
270
+ }
271
+
272
+ } catch (error) {
273
+ console.log(`Consensus supervision error: ${error.message}`);
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Execute multi-agent consensus decision
279
+ */
280
+ static async executeConsensusDecision(session, decision) {
281
+ const { agent, metrics } = session;
282
+
283
+ console.log(`\nšŸŽÆ MULTI-AGENT CONSENSUS ACTION:`);
284
+ console.log(` Agents: ${decision.agentNames.join(', ')}`);
285
+ console.log(` Type: ${decision.type}`);
286
+ console.log(` Confidence: ${decision.confidence}%`);
287
+ console.log(` Reason: ${decision.reason}`);
288
+
289
+ // Update metrics
290
+ switch (decision.type) {
291
+ case 'ADJUST_SIZE':
292
+ case 'ADJUST_PARAMETERS':
293
+ case 'ADJUST_STRATEGY':
294
+ metrics.optimizations++;
295
+ console.log(` Action: Consensus optimization - ${decision.agentNames.length} agents agree`);
296
+ break;
297
+ case 'PAUSE_TRADING':
298
+ case 'RISK_ADJUSTMENT':
299
+ metrics.interventions++;
300
+ console.log(` Action: Consensus risk intervention - ${decision.agentNames.length} agents agree`);
301
+ break;
302
+ case 'ADJUST_FREQUENCY':
303
+ metrics.interventions++;
304
+ console.log(` Action: Consensus frequency adjustment - ${decision.agentNames.length} agents agree`);
305
+ break;
306
+ }
307
+
308
+ // In real implementation, this would actually modify the algo
309
+ console.log(` Status: Consensus decision executed across all agents\n`);
310
+
311
+ return decision;
312
+ }
313
+
314
+ /**
315
+ * Get algo status (placeholder for real implementation)
316
+ */
317
+ static getAlgoStatus(algo) {
318
+ // This would interface with HQX Ultra Scalping
319
+ // For now, return mock data
320
+ return {
321
+ active: true,
322
+ positions: 1,
323
+ currentPnL: 145.50,
324
+ dayTrades: 8,
325
+ winRate: 0.75,
326
+ avgWin: 25.30,
327
+ avgLoss: 8.20,
328
+ lastTradeTime: Date.now() - 120000, // 2 minutes ago
329
+ currentStrategy: 'momentum_scalping',
330
+ parameters: {
331
+ tradeSize: 2,
332
+ stopLoss: 3,
333
+ takeProfit: 6,
334
+ maxPositions: 3
335
+ }
336
+ };
337
+ }
338
+
339
+ /**
340
+ * Get market data (placeholder)
341
+ */
342
+ static getMarketData() {
343
+ // This would get real market data
344
+ return {
345
+ symbol: 'ES',
346
+ price: 4502.25,
347
+ change: 12.50,
348
+ volume: 1250000,
349
+ volatility: 0.018,
350
+ trend: 'bullish',
351
+ momentum: 'strong',
352
+ timeframe: '1m'
353
+ };
354
+ }
355
+
356
+ /**
357
+ * Get risk metrics (placeholder)
358
+ */
359
+ static getRiskMetrics(algo) {
360
+ return {
361
+ maxDrawdown: 0.025, // 2.5%
362
+ currentDrawdown: 0.008, // 0.8%
363
+ exposure: 0.65, // 65% of max
364
+ dailyLoss: -45.30,
365
+ sharpeRatio: 1.8,
366
+ var95: 125.50 // Value at Risk
367
+ };
368
+ }
369
+
370
+ /**
371
+ * Make AI decision for single agent
372
+ */
373
+ static async makeAIDecision(agent, algoStatus, marketData, riskMetrics) {
374
+ // Simulate AI decision making based on provider
375
+ const decisions = [];
376
+
377
+ switch (agent.providerId) {
378
+ case 'anthropic':
379
+ // Claude: Technical analysis expert
380
+ if (marketData.volatility > 0.025 && algoStatus.parameters.tradeSize > 1) {
381
+ decisions.push({
382
+ type: 'ADJUST_SIZE',
383
+ action: 'REDUCE',
384
+ currentSize: algoStatus.parameters.tradeSize,
385
+ suggestedSize: Math.max(1, Math.floor(algoStatus.parameters.tradeSize * 0.7)),
386
+ reason: 'High volatility detected - reducing position size',
387
+ confidence: 85,
388
+ agentType: 'technical',
389
+ urgency: 'medium'
390
+ });
391
+ }
392
+
393
+ if (riskMetrics.currentDrawdown > 0.02) {
394
+ decisions.push({
395
+ type: 'PAUSE_TRADING',
396
+ reason: 'Drawdown exceeding 2% - pausing to preserve capital',
397
+ confidence: 92,
398
+ agentType: 'technical',
399
+ urgency: 'high'
400
+ });
401
+ }
402
+ break;
403
+
404
+ case 'openai':
405
+ // OpenAI: Parameter optimization expert
406
+ if (marketData.trend === 'bullish' && marketData.momentum === 'strong') {
407
+ decisions.push({
408
+ type: 'ADJUST_PARAMETERS',
409
+ parameter: 'takeProfit',
410
+ current: algoStatus.parameters.takeProfit,
411
+ suggested: algoStatus.parameters.takeProfit * 1.25,
412
+ reason: 'Strong bullish trend - increasing take profit target',
413
+ confidence: 78,
414
+ agentType: 'optimization',
415
+ urgency: 'low'
416
+ });
417
+ }
418
+
419
+ // OpenAI suggests scaling in consolidation
420
+ if (marketData.volatility < 0.015) {
421
+ decisions.push({
422
+ type: 'ADJUST_STRATEGY',
423
+ suggestedStrategy: 'scaling',
424
+ reason: 'Low volatility - switching to scaling strategy',
425
+ confidence: 72,
426
+ agentType: 'optimization',
427
+ urgency: 'medium'
428
+ });
429
+ }
430
+ break;
431
+
432
+ case 'deepseek':
433
+ // DeepSeek: Trading and prop firm expert
434
+ if (algoStatus.dayTrades > 8) {
435
+ decisions.push({
436
+ type: 'ADJUST_FREQUENCY',
437
+ action: 'REDUCE',
438
+ reason: 'Overtrading detected - reducing trade frequency',
439
+ confidence: 88,
440
+ agentType: 'trading',
441
+ urgency: 'high'
442
+ });
443
+ }
444
+
445
+ // DeepSeek focuses on prop firm rules
446
+ if (riskMetrics.dailyLoss < -100) {
447
+ decisions.push({
448
+ type: 'RISK_ADJUSTMENT',
449
+ adjustment: 'HALF_SIZE',
450
+ reason: 'Daily loss approaching limit - halving position size',
451
+ confidence: 95,
452
+ agentType: 'trading',
453
+ urgency: 'critical'
454
+ });
455
+ }
456
+ break;
457
+
458
+ default:
459
+ // Generic decision for other providers
460
+ if (marketData.volatility > 0.03) {
461
+ decisions.push({
462
+ type: 'ADJUST_SIZE',
463
+ action: 'REDUCE',
464
+ suggestedSize: Math.max(1, Math.floor(algoStatus.parameters.tradeSize * 0.6)),
465
+ reason: 'Very high volatility - significant size reduction',
466
+ confidence: 80,
467
+ agentType: 'generic',
468
+ urgency: 'medium'
469
+ });
470
+ }
471
+ break;
472
+ }
473
+
474
+ return decisions.length > 0 ? decisions[0] : null;
475
+ }
476
+
477
+ /**
478
+ * Make multi-agent consensus decision
479
+ */
480
+ static async makeConsensusDecision(allAgents, algoStatus, marketData, riskMetrics) {
481
+ if (!allAgents || allAgents.length === 0) return null;
482
+
483
+ if (allAgents.length === 1) {
484
+ // Single agent - use normal decision
485
+ return await this.makeAIDecision(allAgents[0], algoStatus, marketData, riskMetrics);
486
+ }
487
+
488
+ console.log(`šŸ¤ CONSENSUS: Getting decisions from ${allAgents.length} agents...`);
489
+
490
+ // Get decision from each agent
491
+ const agentDecisions = [];
492
+
493
+ for (const agent of allAgents) {
494
+ const decision = await this.makeAIDecision(agent, algoStatus, marketData, riskMetrics);
495
+
496
+ if (decision) {
497
+ agentDecisions.push({
498
+ agentId: agent.id,
499
+ agentName: agent.name,
500
+ providerId: agent.providerId,
501
+ agentType: decision.agentType,
502
+ ...decision
503
+ });
504
+
505
+ console.log(` ${agent.name} (${agent.providerId}): ${decision.type} (${decision.confidence}% confidence)`);
506
+ }
507
+ }
508
+
509
+ if (agentDecisions.length === 0) {
510
+ console.log(' No consensus - all agents agree current parameters are optimal');
511
+ return null;
512
+ }
513
+
514
+ // Group decisions by type
515
+ const decisionGroups = {};
516
+ for (const decision of agentDecisions) {
517
+ const key = `${decision.type}_${decision.action || ''}_${decision.parameter || ''}`;
518
+ if (!decisionGroups[key]) {
519
+ decisionGroups[key] = [];
520
+ }
521
+ decisionGroups[key].push(decision);
522
+ }
523
+
524
+ // Weight agents by their expertise
525
+ const agentWeights = {
526
+ 'anthropic': { technical: 1.2, optimization: 1.0, trading: 1.0, generic: 1.1 },
527
+ 'openai': { technical: 1.0, optimization: 1.3, trading: 0.9, generic: 1.2 },
528
+ 'deepseek': { technical: 0.9, optimization: 1.0, trading: 1.4, generic: 1.1 },
529
+ 'groq': { technical: 1.1, optimization: 1.0, trading: 1.2, generic: 1.0 },
530
+ 'gemini': { technical: 1.0, optimization: 1.1, trading: 1.0, generic: 1.2 }
531
+ };
532
+
533
+ // Calculate weighted consensus for each decision type
534
+ const consensusResults = [];
535
+
536
+ for (const [decisionKey, group] of Object.entries(decisionGroups)) {
537
+ let totalWeight = 0;
538
+ let weightedConfidence = 0;
539
+ let agentNames = [];
540
+
541
+ for (const decision of group) {
542
+ const weight = agentWeights[decision.providerId]?.[decision.agentType] || 1.0;
543
+ totalWeight += weight;
544
+ weightedConfidence += decision.confidence * weight;
545
+ agentNames.push(decision.agentName);
546
+ }
547
+
548
+ const consensusConfidence = weightedConfidence / totalWeight;
549
+
550
+ consensusResults.push({
551
+ type: group[0].type,
552
+ action: group[0].action,
553
+ parameter: group[0].parameter,
554
+ currentSize: group[0].currentSize,
555
+ suggestedSize: group[0].suggestedSize,
556
+ current: group[0].current,
557
+ suggested: group[0].suggested,
558
+ adjustment: group[0].adjustment,
559
+ suggestedStrategy: group[0].suggestedStrategy,
560
+ reason: this.buildConsensusReason(group, decisionKey),
561
+ confidence: Math.round(consensusConfidence),
562
+ agentCount: group.length,
563
+ agentNames: [...new Set(agentNames)], // Unique names
564
+ agentTypes: [...new Set(group.map(d => d.agentType))],
565
+ urgency: this.calculateUrgency(group),
566
+ consensusStrength: totalWeight
567
+ });
568
+ }
569
+
570
+ // Return highest confidence consensus decision
571
+ if (consensusResults.length > 0) {
572
+ const bestDecision = consensusResults.sort((a, b) => b.confidence - a.confidence)[0];
573
+
574
+ console.log(`šŸŽÆ CONSENSUS DECISION:`);
575
+ console.log(` Type: ${bestDecision.type}`);
576
+ console.log(` Confidence: ${bestDecision.confidence}%`);
577
+ console.log(` Agents: ${bestDecision.agentNames.join(', ')}`);
578
+ console.log(` Reason: ${bestDecision.reason}`);
579
+
580
+ return bestDecision;
581
+ }
582
+
583
+ return null;
584
+ }
585
+
586
+ /**
587
+ * Build consensus reason
588
+ */
589
+ static buildConsensusReason(group, decisionKey) {
590
+ const agentNames = group.map(d => d.agentName);
591
+ const agentTypes = [...new Set(group.map(d => d.agentType))];
592
+
593
+ let expertise = '';
594
+ if (agentTypes.length === 1) {
595
+ const typeMap = {
596
+ 'technical': 'technical analysis',
597
+ 'optimization': 'parameter optimization',
598
+ 'trading': 'trading strategy',
599
+ 'generic': 'general analysis'
600
+ };
601
+ expertise = `based on ${typeMap[agentTypes[0]]}`;
602
+ } else {
603
+ expertise = `based on multiple expertises (${agentTypes.join(', ')})`;
604
+ }
605
+
606
+ return `Consensus from ${agentNames.join(', ')} - ${expertise}`;
607
+ }
608
+
609
+ /**
610
+ * Calculate urgency from consensus
611
+ */
612
+ static calculateUrgency(group) {
613
+ const urgencyLevels = { 'low': 1, 'medium': 2, 'high': 3, 'critical': 4 };
614
+ const maxUrgency = Math.max(...group.map(d => urgencyLevels[d.urgency] || 1));
615
+
616
+ const urgencyMap = { 1: 'low', 2: 'medium', 3: 'high', 4: 'critical' };
617
+ return urgencyMap[maxUrgency];
618
+ }
619
+
620
+ /**
621
+ * Execute AI decision
622
+ */
623
+ static async executeDecision(session, decision) {
624
+ const { agent, algo, metrics } = session;
625
+
626
+ console.log(`\nšŸ¤– ${agent.name} Decision:`);
627
+ console.log(` Type: ${decision.type}`);
628
+ console.log(` Reason: ${decision.reason}`);
629
+ console.log(` Confidence: ${decision.confidence}%`);
630
+
631
+ // Update metrics
632
+ switch (decision.type) {
633
+ case 'ADJUST_SIZE':
634
+ case 'ADJUST_PARAMETERS':
635
+ metrics.optimizations++;
636
+ console.log(` Action: Optimizing algo parameters`);
637
+ break;
638
+ case 'PAUSE_TRADING':
639
+ case 'REDUCE_EXPOSURE':
640
+ metrics.interventions++;
641
+ console.log(` Action: Risk intervention - ${decision.reason.toLowerCase()}`);
642
+ break;
643
+ case 'RISK_WARNING':
644
+ metrics.riskWarnings++;
645
+ console.log(` Action: Risk warning issued`);
646
+ break;
647
+ }
648
+
649
+ // In real implementation, this would actually modify the algo
650
+ // For now, just log the decision
651
+ console.log(` Status: Decision logged for manual review\n`);
652
+
653
+ return decision;
654
+ }
655
+
656
+ /**
657
+ * Get supervision status for an agent
658
+ */
659
+ static getStatus(agentId) {
660
+ const session = supervisionSessions.get(agentId);
661
+ if (!session) {
662
+ return { active: false };
663
+ }
664
+
665
+ const duration = Date.now() - session.startTime;
666
+ return {
667
+ active: true,
668
+ agentName: session.agent.name,
669
+ duration: Math.round(duration / 1000),
670
+ decisions: session.metrics.totalDecisions,
671
+ interventions: session.metrics.interventions,
672
+ optimizations: session.metrics.optimizations,
673
+ lastDecision: session.decisions.length > 0 ? session.decisions[session.decisions.length - 1] : null
674
+ };
675
+ }
676
+
677
+ /**
678
+ * Get all active supervision sessions
679
+ */
680
+ static getAllStatus() {
681
+ const result = [];
682
+ const isConsensusMode = supervisionSessions.size > 1 && consensusInterval;
683
+
684
+ for (const [agentId, session] of supervisionSessions.entries()) {
685
+ result.push({
686
+ agentId,
687
+ agentName: session.agent.name,
688
+ duration: Date.now() - session.startTime,
689
+ metrics: session.metrics,
690
+ lastDecision: session.decisions.length > 0 ? session.decisions[session.decisions.length - 1] : null,
691
+ mode: isConsensusMode ? 'consensus' : 'single'
692
+ });
693
+ }
694
+
695
+ return {
696
+ sessions: result,
697
+ mode: isConsensusMode ? 'consensus' : 'single',
698
+ totalAgents: supervisionSessions.size
699
+ };
700
+ }
701
+
702
+ /**
703
+ * Stop all supervision sessions
704
+ */
705
+ static stopAll() {
706
+ const agentIds = Array.from(supervisionSessions.keys());
707
+ for (const agentId of agentIds) {
708
+ this.stop(agentId);
709
+ }
710
+ }
711
+ }
712
+
713
+ module.exports = AISupervisor;