@gotza02/sequential-thinking 10000.0.8 → 10000.1.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.
@@ -1,67 +1,472 @@
1
- import * as http from 'http';
2
- import * as fs from 'fs';
3
- import * as path from 'path';
1
+ /**
2
+ * DASHBOARD SERVER
3
+ * Real-time monitoring dashboard for the football analysis system
4
+ */
5
+ import { createServer } from 'http';
6
+ import { dirname } from 'path';
4
7
  import { fileURLToPath } from 'url';
5
- const __filename = fileURLToPath(import.meta.url);
6
- const __dirname = path.dirname(__filename);
7
- export function startDashboard(port, historyPath) {
8
- return new Promise((resolve, reject) => {
9
- const server = http.createServer((req, res) => {
10
- // Handle CORS
11
- res.setHeader('Access-Control-Allow-Origin', '*');
12
- res.setHeader('Access-Control-Allow-Methods', 'GET');
13
- if (req.url === '/') {
14
- // Serve index.html
15
- const indexPath = path.join(__dirname, 'index.html');
16
- fs.readFile(indexPath, (err, data) => {
17
- if (err) {
18
- res.writeHead(500);
19
- res.end('Error loading dashboard');
20
- return;
21
- }
22
- res.writeHead(200, { 'Content-Type': 'text/html' });
23
- res.end(data);
24
- });
25
- }
26
- else if (req.url === '/api/history') {
27
- // Serve thoughts_history.json
28
- fs.readFile(historyPath, (err, data) => {
29
- if (err) {
30
- // Try .tmp if main file is locked/missing (rare fallback)
31
- fs.readFile(historyPath + '.tmp', (err2, data2) => {
32
- if (err2) {
33
- res.writeHead(500);
34
- res.end(JSON.stringify({ error: 'History not found' }));
35
- return;
36
- }
37
- res.writeHead(200, { 'Content-Type': 'application/json' });
38
- res.end(data2);
39
- });
40
- return;
41
- }
42
- res.writeHead(200, { 'Content-Type': 'application/json' });
43
- res.end(data);
44
- });
8
+ import { logger } from '../utils.js';
9
+ import { getGlobalCache } from '../tools/sports/core/cache.js';
10
+ import { getAllCircuitBreakerStatus } from '../tools/sports/core/circuit-breaker.js';
11
+ import { getRealtimeManager } from '../tools/sports/core/realtime-manager.js';
12
+ import { getAlertManager } from '../tools/sports/core/alert-manager.js';
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ export class DashboardServer {
15
+ server = null;
16
+ port;
17
+ updateInterval = null;
18
+ constructor(port = 8080) {
19
+ this.port = port;
20
+ }
21
+ /**
22
+ * Start the dashboard server
23
+ */
24
+ start() {
25
+ if (this.server)
26
+ return;
27
+ this.server = createServer((req, res) => {
28
+ this.handleRequest(req, res);
29
+ });
30
+ this.server.listen(this.port, () => {
31
+ logger.info(`[Dashboard] Server running on http://localhost:${this.port}`);
32
+ });
33
+ // Start stats update interval
34
+ this.updateInterval = setInterval(() => {
35
+ this.broadcastStats();
36
+ }, 5000);
37
+ }
38
+ /**
39
+ * Stop the dashboard server
40
+ */
41
+ stop() {
42
+ if (this.updateInterval) {
43
+ clearInterval(this.updateInterval);
44
+ this.updateInterval = null;
45
+ }
46
+ if (this.server) {
47
+ this.server.close();
48
+ this.server = null;
49
+ logger.info('[Dashboard] Server stopped');
50
+ }
51
+ }
52
+ /**
53
+ * Handle HTTP requests
54
+ */
55
+ handleRequest(req, res) {
56
+ const url = new URL(req.url, `http://localhost:${this.port}`);
57
+ // Enable CORS
58
+ res.setHeader('Access-Control-Allow-Origin', '*');
59
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
60
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
61
+ if (req.method === 'OPTIONS') {
62
+ res.writeHead(200);
63
+ res.end();
64
+ return;
65
+ }
66
+ // Route handling
67
+ if (url.pathname === '/' || url.pathname === '/index.html') {
68
+ this.serveDashboard(res);
69
+ }
70
+ else if (url.pathname === '/api/stats') {
71
+ this.serveStats(res);
72
+ }
73
+ else if (url.pathname === '/api/cache/clear') {
74
+ this.clearCache(res);
75
+ }
76
+ else if (url.pathname === '/api/circuit-breakers/reset') {
77
+ this.resetCircuitBreakers(res);
78
+ }
79
+ else if (url.pathname === '/api/alerts/rules') {
80
+ this.serveAlertRules(res);
81
+ }
82
+ else if (url.pathname === '/api/alerts/history') {
83
+ this.serveAlertHistory(res);
84
+ }
85
+ else {
86
+ res.writeHead(404);
87
+ res.end(JSON.stringify({ error: 'Not found' }));
88
+ }
89
+ }
90
+ /**
91
+ * Serve the dashboard HTML
92
+ */
93
+ serveDashboard(res) {
94
+ const html = `<!DOCTYPE html>
95
+ <html lang="en">
96
+ <head>
97
+ <meta charset="UTF-8">
98
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
99
+ <title>Football Analysis Dashboard</title>
100
+ <style>
101
+ * { margin: 0; padding: 0; box-sizing: border-box; }
102
+ body {
103
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
104
+ background: #0f172a;
105
+ color: #e2e8f0;
106
+ padding: 20px;
107
+ }
108
+ .header {
109
+ text-align: center;
110
+ padding: 20px;
111
+ margin-bottom: 30px;
112
+ }
113
+ .header h1 {
114
+ font-size: 2.5em;
115
+ background: linear-gradient(135deg, #3b82f6, #8b5cf6);
116
+ -webkit-background-clip: text;
117
+ -webkit-text-fill-color: transparent;
118
+ }
119
+ .grid {
120
+ display: grid;
121
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
122
+ gap: 20px;
123
+ max-width: 1400px;
124
+ margin: 0 auto;
125
+ }
126
+ .card {
127
+ background: #1e293b;
128
+ border-radius: 12px;
129
+ padding: 20px;
130
+ border: 1px solid #334155;
131
+ }
132
+ .card h2 {
133
+ font-size: 1.2em;
134
+ margin-bottom: 15px;
135
+ color: #94a3b8;
136
+ text-transform: uppercase;
137
+ letter-spacing: 1px;
138
+ }
139
+ .stat {
140
+ display: flex;
141
+ justify-content: space-between;
142
+ padding: 10px 0;
143
+ border-bottom: 1px solid #334155;
144
+ }
145
+ .stat:last-child { border-bottom: none; }
146
+ .stat-value {
147
+ font-weight: bold;
148
+ color: #3b82f6;
149
+ }
150
+ .status {
151
+ display: inline-block;
152
+ padding: 4px 12px;
153
+ border-radius: 20px;
154
+ font-size: 0.85em;
155
+ font-weight: 500;
156
+ }
157
+ .status-online { background: #22c55e; color: #064e3b; }
158
+ .status-offline { background: #ef4444; color: #7f1d1d; }
159
+ .status-warning { background: #f59e0b; color: #78350f; }
160
+ .cb-closed { color: #22c55e; }
161
+ .cb-open { color: #ef4444; }
162
+ .cb-half { color: #f59e0b; }
163
+ button {
164
+ background: #3b82f6;
165
+ color: white;
166
+ border: none;
167
+ padding: 10px 20px;
168
+ border-radius: 6px;
169
+ cursor: pointer;
170
+ font-size: 0.9em;
171
+ margin-top: 10px;
172
+ }
173
+ button:hover { background: #2563eb; }
174
+ .refresh-indicator {
175
+ position: fixed;
176
+ top: 20px;
177
+ right: 20px;
178
+ width: 10px;
179
+ height: 10px;
180
+ background: #22c55e;
181
+ border-radius: 50%;
182
+ animation: pulse 2s infinite;
183
+ }
184
+ @keyframes pulse {
185
+ 0%, 100% { opacity: 1; }
186
+ 50% { opacity: 0.5; }
187
+ }
188
+ .alerts-list {
189
+ max-height: 200px;
190
+ overflow-y: auto;
191
+ }
192
+ .alert-item {
193
+ padding: 8px;
194
+ margin: 5px 0;
195
+ background: #334155;
196
+ border-radius: 6px;
197
+ font-size: 0.85em;
198
+ }
199
+ .alert-critical { border-left: 3px solid #ef4444; }
200
+ .alert-warning { border-left: 3px solid #f59e0b; }
201
+ .alert-info { border-left: 3px solid #3b82f6; }
202
+ </style>
203
+ </head>
204
+ <body>
205
+ <div class="refresh-indicator"></div>
206
+
207
+ <div class="header">
208
+ <h1>⚽ Football Analysis Dashboard</h1>
209
+ <p>Real-time System Monitoring</p>
210
+ </div>
211
+
212
+ <div class="grid">
213
+ <div class="card">
214
+ <h2>📊 System Status</h2>
215
+ <div class="stat">
216
+ <span>Realtime Manager</span>
217
+ <span class="status status-online" id="realtime-status">Online</span>
218
+ </div>
219
+ <div class="stat">
220
+ <span>Alert Manager</span>
221
+ <span class="status status-online" id="alert-status">Online</span>
222
+ </div>
223
+ <div class="stat">
224
+ <span>Cache Service</span>
225
+ <span class="status status-online" id="cache-status">Online</span>
226
+ </div>
227
+ <div class="stat">
228
+ <span>Last Update</span>
229
+ <span id="last-update">-</span>
230
+ </div>
231
+ </div>
232
+
233
+ <div class="card">
234
+ <h2>💾 Cache Statistics</h2>
235
+ <div class="stat">
236
+ <span>Cache Size</span>
237
+ <span class="stat-value" id="cache-size">0 / 2000</span>
238
+ </div>
239
+ <div class="stat">
240
+ <span>Cache Hits</span>
241
+ <span class="stat-value" id="cache-hits">0</span>
242
+ </div>
243
+ <div class="stat">
244
+ <span>Hit Rate</span>
245
+ <span class="stat-value" id="hit-rate">0%</span>
246
+ </div>
247
+ <button onclick="clearCache()">Clear Cache</button>
248
+ </div>
249
+
250
+ <div class="card">
251
+ <h2>🔒 Circuit Breakers</h2>
252
+ <div id="circuit-breakers">
253
+ <div class="stat">
254
+ <span>No circuit breakers active</span>
255
+ </div>
256
+ </div>
257
+ <button onclick="resetCircuitBreakers()">Reset All</button>
258
+ </div>
259
+
260
+ <div class="card">
261
+ <h2>⚡ Realtime Data</h2>
262
+ <div class="stat">
263
+ <span>Live Matches</span>
264
+ <span class="stat-value" id="live-matches">0</span>
265
+ </div>
266
+ <div class="stat">
267
+ <span>Active Subscribers</span>
268
+ <span class="stat-value" id="subscribers">0</span>
269
+ </div>
270
+ <div class="stat">
271
+ <span>Events/Minute</span>
272
+ <span class="stat-value" id="events-rate">0</span>
273
+ </div>
274
+ </div>
275
+
276
+ <div class="card">
277
+ <h2>🚨 Alert System</h2>
278
+ <div class="stat">
279
+ <span>Total Rules</span>
280
+ <span class="stat-value" id="total-rules">0</span>
281
+ </div>
282
+ <div class="stat">
283
+ <span>Enabled Rules</span>
284
+ <span class="stat-value" id="enabled-rules">0</span>
285
+ </div>
286
+ <div class="stat">
287
+ <span>Total Alerts</span>
288
+ <span class="stat-value" id="total-alerts">0</span>
289
+ </div>
290
+ <button onclick="viewAlertRules()">View Rules</button>
291
+ </div>
292
+
293
+ <div class="card">
294
+ <h2>🔔 Recent Alerts</h2>
295
+ <div class="alerts-list" id="alerts-list">
296
+ <div class="alert-item">No recent alerts</div>
297
+ </div>
298
+ </div>
299
+ </div>
300
+
301
+ <script>
302
+ let stats = {};
303
+
304
+ async function fetchStats() {
305
+ try {
306
+ const response = await fetch('/api/stats');
307
+ stats = await response.json();
308
+ updateDashboard();
309
+ } catch (error) {
310
+ console.error('Failed to fetch stats:', error);
45
311
  }
46
- else {
47
- res.writeHead(404);
48
- res.end('Not found');
312
+ }
313
+
314
+ function updateDashboard() {
315
+ document.getElementById('last-update').textContent = new Date().toLocaleTimeString();
316
+
317
+ // Cache stats
318
+ document.getElementById('cache-size').textContent =
319
+ \`\${stats.cache.size} / \${stats.cache.maxSize}\`;
320
+ document.getElementById('cache-hits').textContent = stats.cache.hits;
321
+
322
+ // Circuit breakers
323
+ const cbContainer = document.getElementById('circuit-breakers');
324
+ if (stats.circuitBreakers.length > 0) {
325
+ cbContainer.innerHTML = stats.circuitBreakers.map(cb => \`
326
+ <div class="stat">
327
+ <span>\${cb.name}</span>
328
+ <span class="cb-\${cb.state}">\${cb.state.toUpperCase()}</span>
329
+ </div>
330
+ \`).join('');
49
331
  }
50
- });
51
- server.on('error', (e) => {
52
- if (e.code === 'EADDRINUSE') {
53
- console.error(`[Dashboard] Port ${port} is busy. Trying ${port + 1}...`);
54
- // Recursive retry
55
- startDashboard(port + 1, historyPath).then(resolve).catch(reject);
332
+
333
+ // Realtime
334
+ document.getElementById('live-matches').textContent = stats.realtime.liveMatches;
335
+ document.getElementById('subscribers').textContent = stats.realtime.subscribers;
336
+
337
+ // Alerts
338
+ document.getElementById('total-rules').textContent = stats.alerts.totalRules;
339
+ document.getElementById('enabled-rules').textContent = stats.alerts.enabledRules;
340
+ document.getElementById('total-alerts').textContent = stats.alerts.totalAlerts;
341
+ }
342
+
343
+ async function clearCache() {
344
+ try {
345
+ await fetch('/api/cache/clear', { method: 'POST' });
346
+ alert('Cache cleared');
347
+ fetchStats();
348
+ } catch (error) {
349
+ alert('Failed to clear cache');
56
350
  }
57
- else {
58
- console.error('[Dashboard] Server error:', e);
59
- reject(e);
351
+ }
352
+
353
+ async function resetCircuitBreakers() {
354
+ try {
355
+ await fetch('/api/circuit-breakers/reset', { method: 'POST' });
356
+ alert('Circuit breakers reset');
357
+ fetchStats();
358
+ } catch (error) {
359
+ alert('Failed to reset circuit breakers');
60
360
  }
61
- });
62
- server.listen(port, () => {
63
- console.error(`[Dashboard] 📊 Dashboard running at http://localhost:${port}`);
64
- resolve(server);
65
- });
66
- });
361
+ }
362
+
363
+ function viewAlertRules() {
364
+ window.open('/api/alerts/rules', '_blank');
365
+ }
366
+
367
+ // Fetch stats every 5 seconds
368
+ fetchStats();
369
+ setInterval(fetchStats, 5000);
370
+ </script>
371
+ </body>
372
+ </html>`;
373
+ res.setHeader('Content-Type', 'text/html');
374
+ res.writeHead(200);
375
+ res.end(html);
376
+ }
377
+ /**
378
+ * Serve stats JSON
379
+ */
380
+ serveStats(res) {
381
+ const stats = this.collectStats();
382
+ res.setHeader('Content-Type', 'application/json');
383
+ res.writeHead(200);
384
+ res.end(JSON.stringify(stats));
385
+ }
386
+ /**
387
+ * Clear cache
388
+ */
389
+ clearCache(res) {
390
+ const cache = getGlobalCache();
391
+ cache.clear();
392
+ res.setHeader('Content-Type', 'application/json');
393
+ res.writeHead(200);
394
+ res.end(JSON.stringify({ success: true, message: 'Cache cleared' }));
395
+ }
396
+ /**
397
+ * Reset circuit breakers
398
+ */
399
+ resetCircuitBreakers(res) {
400
+ // Circuit breakers auto-reset based on timeout
401
+ // This endpoint just returns success
402
+ res.setHeader('Content-Type', 'application/json');
403
+ res.writeHead(200);
404
+ res.end(JSON.stringify({ success: true, message: 'Circuit breakers will reset automatically' }));
405
+ }
406
+ /**
407
+ * Serve alert rules
408
+ */
409
+ serveAlertRules(res) {
410
+ const alertManager = getAlertManager();
411
+ const rules = alertManager.getRules();
412
+ res.setHeader('Content-Type', 'application/json');
413
+ res.writeHead(200);
414
+ res.end(JSON.stringify(rules, null, 2));
415
+ }
416
+ /**
417
+ * Serve alert history
418
+ */
419
+ serveAlertHistory(res) {
420
+ const alertManager = getAlertManager();
421
+ const history = alertManager.getAlertHistory(50);
422
+ res.setHeader('Content-Type', 'application/json');
423
+ res.writeHead(200);
424
+ res.end(JSON.stringify(history, null, 2));
425
+ }
426
+ /**
427
+ * Collect all stats
428
+ */
429
+ collectStats() {
430
+ const cache = getGlobalCache();
431
+ const cacheStats = cache.getStats();
432
+ const realtimeManager = getRealtimeManager();
433
+ const alertManager = getAlertManager();
434
+ return {
435
+ cache: {
436
+ size: cacheStats.size,
437
+ maxSize: cacheStats.maxSize,
438
+ hits: cacheStats.hits,
439
+ breakdown: cache.getBreakdown(),
440
+ },
441
+ circuitBreakers: getAllCircuitBreakerStatus(),
442
+ realtime: {
443
+ isRunning: true, // Would check actual state
444
+ liveMatches: realtimeManager.getLiveMatches().length,
445
+ subscribers: realtimeManager.listenerCount('event'),
446
+ },
447
+ alerts: alertManager.getStats(),
448
+ };
449
+ }
450
+ /**
451
+ * Broadcast stats to all connected clients (for WebSocket upgrade)
452
+ */
453
+ broadcastStats() {
454
+ // In a full implementation, this would push to WebSocket clients
455
+ // For now, clients poll via HTTP
456
+ }
457
+ }
458
+ // Singleton instance
459
+ let globalDashboardServer = null;
460
+ export function startDashboard(port) {
461
+ if (!globalDashboardServer) {
462
+ globalDashboardServer = new DashboardServer(port);
463
+ globalDashboardServer.start();
464
+ }
465
+ return globalDashboardServer;
466
+ }
467
+ export function stopDashboard() {
468
+ if (globalDashboardServer) {
469
+ globalDashboardServer.stop();
470
+ globalDashboardServer = null;
471
+ }
67
472
  }
package/dist/index.js CHANGED
@@ -29,10 +29,7 @@ const server = new McpServer({
29
29
  });
30
30
  const thinkingServer = new SequentialThinkingServer(process.env.THOUGHTS_STORAGE_PATH || 'thoughts_history.json', parseInt(process.env.THOUGHT_DELAY_MS || '0', 10));
31
31
  // Start Dashboard
32
- const historyPath = process.env.THOUGHTS_STORAGE_PATH || 'thoughts_history.json';
33
- startDashboard(3001, historyPath).catch(err => {
34
- console.error("[Dashboard] Failed to start:", err);
35
- });
32
+ startDashboard(3001);
36
33
  const knowledgeGraph = new ProjectKnowledgeGraph();
37
34
  const memoryGraph = new KnowledgeGraphManager(process.env.MEMORY_GRAPH_PATH || 'knowledge_graph.json');
38
35
  const notesManager = new NotesManager(process.env.NOTES_STORAGE_PATH || 'project_notes.json');
@@ -0,0 +1,145 @@
1
+ /**
2
+ * ALERT MANAGER
3
+ * Real-time alert system with rule engine and notifications
4
+ */
5
+ import { EventEmitter } from 'events';
6
+ import type { LiveEvent } from './realtime-manager.js';
7
+ export interface AlertRule {
8
+ id: string;
9
+ name: string;
10
+ type: AlertType;
11
+ condition: AlertCondition;
12
+ channels: NotificationChannel[];
13
+ cooldown: number;
14
+ enabled: boolean;
15
+ createdAt: number;
16
+ lastTriggered?: number;
17
+ triggerCount?: number;
18
+ }
19
+ export type AlertType = 'odds_drop' | 'odds_value' | 'goal' | 'red_card' | 'lineup_change' | 'match_start' | 'match_end' | 'custom';
20
+ export type AlertCondition = OddsDropCondition | OddsValueCondition | EventCondition | CompositeCondition;
21
+ export interface OddsDropCondition {
22
+ type: 'odds_drop';
23
+ matchId?: string;
24
+ team?: string;
25
+ threshold: number;
26
+ percentage: number;
27
+ }
28
+ export interface OddsValueCondition {
29
+ type: 'odds_value';
30
+ matchId?: string;
31
+ minValue: number;
32
+ maxOdds?: number;
33
+ }
34
+ export interface EventCondition {
35
+ type: 'event';
36
+ matchId?: string;
37
+ eventTypes: string[];
38
+ }
39
+ export interface CompositeCondition {
40
+ type: 'composite';
41
+ conditions: AlertCondition[];
42
+ operator: 'AND' | 'OR';
43
+ }
44
+ export interface NotificationChannel {
45
+ type: 'webhook' | 'email' | 'slack' | 'discord' | 'console';
46
+ config: Record<string, any>;
47
+ }
48
+ export interface AlertMessage {
49
+ ruleId: string;
50
+ ruleName: string;
51
+ type: AlertType;
52
+ severity: 'info' | 'warning' | 'critical';
53
+ title: string;
54
+ body: string;
55
+ data: any;
56
+ timestamp: number;
57
+ }
58
+ export declare class AlertManager extends EventEmitter {
59
+ private rules;
60
+ private checkInterval?;
61
+ private alertHistory;
62
+ private maxHistorySize;
63
+ constructor();
64
+ /**
65
+ * Start the alert manager
66
+ */
67
+ start(): void;
68
+ /**
69
+ * Stop the alert manager
70
+ */
71
+ stop(): void;
72
+ /**
73
+ * Add a new alert rule
74
+ */
75
+ addRule(rule: Omit<AlertRule, 'id' | 'createdAt' | 'triggerCount'>): AlertRule;
76
+ /**
77
+ * Remove an alert rule
78
+ */
79
+ removeRule(ruleId: string): boolean;
80
+ /**
81
+ * Get all rules
82
+ */
83
+ getRules(): AlertRule[];
84
+ /**
85
+ * Get a specific rule
86
+ */
87
+ getRule(ruleId: string): AlertRule | undefined;
88
+ /**
89
+ * Enable/disable a rule
90
+ */
91
+ toggleRule(ruleId: string, enabled: boolean): boolean;
92
+ /**
93
+ * Process a live event and check for alerts
94
+ */
95
+ processEvent(event: LiveEvent): void;
96
+ /**
97
+ * Evaluate an alert condition against an event
98
+ */
99
+ private evaluateCondition;
100
+ private evaluateOddsDrop;
101
+ private evaluateOddsValue;
102
+ private evaluateEventCondition;
103
+ private evaluateCompositeCondition;
104
+ /**
105
+ * Trigger an alert
106
+ */
107
+ private triggerAlert;
108
+ /**
109
+ * Create an alert message
110
+ */
111
+ private createAlertMessage;
112
+ private determineSeverity;
113
+ private formatAlertTitle;
114
+ private formatAlertBody;
115
+ /**
116
+ * Send notification to a channel
117
+ */
118
+ private sendNotification;
119
+ private sendWebhook;
120
+ private sendSlack;
121
+ private sendDiscord;
122
+ private sendEmail;
123
+ /**
124
+ * Check scheduled alerts (for time-based alerts)
125
+ */
126
+ private checkScheduledAlerts;
127
+ /**
128
+ * Get alert history
129
+ */
130
+ getAlertHistory(limit?: number): AlertMessage[];
131
+ /**
132
+ * Clear alert history
133
+ */
134
+ clearHistory(): void;
135
+ /**
136
+ * Get statistics
137
+ */
138
+ getStats(): {
139
+ totalRules: number;
140
+ enabledRules: number;
141
+ totalAlerts: number;
142
+ };
143
+ }
144
+ export declare function getAlertManager(): AlertManager;
145
+ export declare function resetAlertManager(): void;