@gotza02/sequential-thinking 10000.1.0 → 10000.1.2

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,6 +1,5 @@
1
1
  /**
2
2
  * DASHBOARD SERVER
3
- * Real-time monitoring dashboard for the football analysis system
4
3
  */
5
4
  export interface DashboardStats {
6
5
  cache: {
@@ -30,49 +29,16 @@ export declare class DashboardServer {
30
29
  private port;
31
30
  private updateInterval;
32
31
  constructor(port?: number);
33
- /**
34
- * Start the dashboard server
35
- */
36
32
  start(): void;
37
- /**
38
- * Stop the dashboard server
39
- */
40
33
  stop(): void;
41
- /**
42
- * Handle HTTP requests
43
- */
44
34
  private handleRequest;
45
- /**
46
- * Serve the dashboard HTML
47
- */
48
35
  private serveDashboard;
49
- /**
50
- * Serve stats JSON
51
- */
52
36
  private serveStats;
53
- /**
54
- * Clear cache
55
- */
56
37
  private clearCache;
57
- /**
58
- * Reset circuit breakers
59
- */
60
38
  private resetCircuitBreakers;
61
- /**
62
- * Serve alert rules
63
- */
64
39
  private serveAlertRules;
65
- /**
66
- * Serve alert history
67
- */
68
40
  private serveAlertHistory;
69
- /**
70
- * Collect all stats
71
- */
72
41
  private collectStats;
73
- /**
74
- * Broadcast stats to all connected clients (for WebSocket upgrade)
75
- */
76
42
  private broadcastStats;
77
43
  }
78
44
  export declare function startDashboard(port?: number): DashboardServer;
@@ -1,16 +1,18 @@
1
1
  /**
2
2
  * DASHBOARD SERVER
3
- * Real-time monitoring dashboard for the football analysis system
4
3
  */
5
4
  import { createServer } from 'http';
6
- import { dirname } from 'path';
7
- import { fileURLToPath } from 'url';
8
- import { logger } from '../utils.js';
9
- import { getGlobalCache } from '../tools/sports/core/cache.js';
5
+ import { CacheService } from '../tools/sports/core/cache.js';
10
6
  import { getAllCircuitBreakerStatus } from '../tools/sports/core/circuit-breaker.js';
11
7
  import { getRealtimeManager } from '../tools/sports/core/realtime-manager.js';
12
8
  import { getAlertManager } from '../tools/sports/core/alert-manager.js';
13
- const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ // Simple logger fallback
10
+ const logger = {
11
+ info: (...args) => console.error('[INFO]', ...args),
12
+ warn: (...args) => console.warn('[WARN]', ...args),
13
+ error: (...args) => console.error('[ERROR]', ...args),
14
+ debug: (...args) => { }
15
+ };
14
16
  export class DashboardServer {
15
17
  server = null;
16
18
  port;
@@ -18,9 +20,6 @@ export class DashboardServer {
18
20
  constructor(port = 8080) {
19
21
  this.port = port;
20
22
  }
21
- /**
22
- * Start the dashboard server
23
- */
24
23
  start() {
25
24
  if (this.server)
26
25
  return;
@@ -30,14 +29,10 @@ export class DashboardServer {
30
29
  this.server.listen(this.port, () => {
31
30
  logger.info(`[Dashboard] Server running on http://localhost:${this.port}`);
32
31
  });
33
- // Start stats update interval
34
32
  this.updateInterval = setInterval(() => {
35
33
  this.broadcastStats();
36
34
  }, 5000);
37
35
  }
38
- /**
39
- * Stop the dashboard server
40
- */
41
36
  stop() {
42
37
  if (this.updateInterval) {
43
38
  clearInterval(this.updateInterval);
@@ -49,12 +44,8 @@ export class DashboardServer {
49
44
  logger.info('[Dashboard] Server stopped');
50
45
  }
51
46
  }
52
- /**
53
- * Handle HTTP requests
54
- */
55
47
  handleRequest(req, res) {
56
48
  const url = new URL(req.url, `http://localhost:${this.port}`);
57
- // Enable CORS
58
49
  res.setHeader('Access-Control-Allow-Origin', '*');
59
50
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
60
51
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
@@ -63,7 +54,6 @@ export class DashboardServer {
63
54
  res.end();
64
55
  return;
65
56
  }
66
- // Route handling
67
57
  if (url.pathname === '/' || url.pathname === '/index.html') {
68
58
  this.serveDashboard(res);
69
59
  }
@@ -87,9 +77,6 @@ export class DashboardServer {
87
77
  res.end(JSON.stringify({ error: 'Not found' }));
88
78
  }
89
79
  }
90
- /**
91
- * Serve the dashboard HTML
92
- */
93
80
  serveDashboard(res) {
94
81
  const html = `<!DOCTYPE html>
95
82
  <html lang="en">
@@ -99,272 +86,91 @@ export class DashboardServer {
99
86
  <title>Football Analysis Dashboard</title>
100
87
  <style>
101
88
  * { 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
- }
89
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0f172a; color: #e2e8f0; padding: 20px; }
90
+ .header { text-align: center; padding: 20px; margin-bottom: 30px; }
91
+ .header h1 { font-size: 2.5em; background: linear-gradient(135deg, #3b82f6, #8b5cf6); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
92
+ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; max-width: 1400px; margin: 0 auto; }
93
+ .card { background: #1e293b; border-radius: 12px; padding: 20px; border: 1px solid #334155; }
94
+ .card h2 { font-size: 1.2em; margin-bottom: 15px; color: #94a3b8; text-transform: uppercase; letter-spacing: 1px; }
95
+ .stat { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #334155; }
145
96
  .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
- }
97
+ .stat-value { font-weight: bold; color: #3b82f6; }
98
+ .status { display: inline-block; padding: 4px 12px; border-radius: 20px; font-size: 0.85em; font-weight: 500; }
157
99
  .status-online { background: #22c55e; color: #064e3b; }
158
100
  .status-offline { background: #ef4444; color: #7f1d1d; }
159
- .status-warning { background: #f59e0b; color: #78350f; }
160
101
  .cb-closed { color: #22c55e; }
161
102
  .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
- }
103
+ button { background: #3b82f6; color: white; border: none; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-size: 0.9em; margin-top: 10px; }
173
104
  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; }
105
+ .refresh-indicator { position: fixed; top: 20px; right: 20px; width: 10px; height: 10px; background: #22c55e; border-radius: 50%; animation: pulse 2s infinite; }
106
+ @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
202
107
  </style>
203
108
  </head>
204
109
  <body>
205
110
  <div class="refresh-indicator"></div>
206
-
207
111
  <div class="header">
208
- <h1>⚽ Football Analysis Dashboard</h1>
112
+ <h1>Football Analysis Dashboard</h1>
209
113
  <p>Real-time System Monitoring</p>
210
114
  </div>
211
-
212
115
  <div class="grid">
213
116
  <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>
117
+ <h2>System Status</h2>
118
+ <div class="stat"><span>Realtime Manager</span><span class="status status-online" id="realtime-status">Online</span></div>
119
+ <div class="stat"><span>Alert Manager</span><span class="status status-online" id="alert-status">Online</span></div>
120
+ <div class="stat"><span>Cache Service</span><span class="status status-online" id="cache-status">Online</span></div>
121
+ <div class="stat"><span>Last Update</span><span id="last-update">-</span></div>
231
122
  </div>
232
-
233
123
  <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>
124
+ <h2>Cache Statistics</h2>
125
+ <div class="stat"><span>Cache Size</span><span class="stat-value" id="cache-size">0 / 2000</span></div>
126
+ <div class="stat"><span>Cache Hits</span><span class="stat-value" id="cache-hits">0</span></div>
247
127
  <button onclick="clearCache()">Clear Cache</button>
248
128
  </div>
249
-
250
129
  <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>
130
+ <h2>Circuit Breakers</h2>
131
+ <div id="circuit-breakers"><div class="stat"><span>No circuit breakers active</span></div></div>
257
132
  <button onclick="resetCircuitBreakers()">Reset All</button>
258
133
  </div>
259
-
260
134
  <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>
135
+ <h2>Realtime Data</h2>
136
+ <div class="stat"><span>Live Matches</span><span class="stat-value" id="live-matches">0</span></div>
137
+ <div class="stat"><span>Active Subscribers</span><span class="stat-value" id="subscribers">0</span></div>
274
138
  </div>
275
-
276
139
  <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>
140
+ <h2>Alert System</h2>
141
+ <div class="stat"><span>Total Rules</span><span class="stat-value" id="total-rules">0</span></div>
142
+ <div class="stat"><span>Enabled Rules</span><span class="stat-value" id="enabled-rules">0</span></div>
143
+ <div class="stat"><span>Total Alerts</span><span class="stat-value" id="total-alerts">0</span></div>
298
144
  </div>
299
145
  </div>
300
-
301
146
  <script>
302
- let stats = {};
303
-
304
147
  async function fetchStats() {
305
148
  try {
306
149
  const response = await fetch('/api/stats');
307
- stats = await response.json();
308
- updateDashboard();
309
- } catch (error) {
310
- console.error('Failed to fetch stats:', error);
311
- }
150
+ const stats = await response.json();
151
+ updateDashboard(stats);
152
+ } catch (error) { console.error('Failed to fetch stats:', error); }
312
153
  }
313
-
314
- function updateDashboard() {
154
+ function updateDashboard(stats) {
315
155
  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}\`;
156
+ document.getElementById('cache-size').textContent = stats.cache.size + ' / ' + stats.cache.maxSize;
320
157
  document.getElementById('cache-hits').textContent = stats.cache.hits;
321
-
322
- // Circuit breakers
323
158
  const cbContainer = document.getElementById('circuit-breakers');
324
159
  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('');
160
+ cbContainer.innerHTML = stats.circuitBreakers.map(cb => '<div class="stat"><span>' + cb.name + '</span><span class="cb-' + cb.state + '">' + cb.state.toUpperCase() + '</span></div>').join('');
331
161
  }
332
-
333
- // Realtime
334
162
  document.getElementById('live-matches').textContent = stats.realtime.liveMatches;
335
163
  document.getElementById('subscribers').textContent = stats.realtime.subscribers;
336
-
337
- // Alerts
338
164
  document.getElementById('total-rules').textContent = stats.alerts.totalRules;
339
165
  document.getElementById('enabled-rules').textContent = stats.alerts.enabledRules;
340
166
  document.getElementById('total-alerts').textContent = stats.alerts.totalAlerts;
341
167
  }
342
-
343
168
  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');
350
- }
169
+ try { await fetch('/api/cache/clear', { method: 'POST' }); fetchStats(); } catch (e) { alert('Failed'); }
351
170
  }
352
-
353
171
  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');
360
- }
361
- }
362
-
363
- function viewAlertRules() {
364
- window.open('/api/alerts/rules', '_blank');
172
+ try { await fetch('/api/circuit-breakers/reset', { method: 'POST' }); fetchStats(); } catch (e) { alert('Failed'); }
365
173
  }
366
-
367
- // Fetch stats every 5 seconds
368
174
  fetchStats();
369
175
  setInterval(fetchStats, 5000);
370
176
  </script>
@@ -374,38 +180,24 @@ export class DashboardServer {
374
180
  res.writeHead(200);
375
181
  res.end(html);
376
182
  }
377
- /**
378
- * Serve stats JSON
379
- */
380
183
  serveStats(res) {
381
184
  const stats = this.collectStats();
382
185
  res.setHeader('Content-Type', 'application/json');
383
186
  res.writeHead(200);
384
187
  res.end(JSON.stringify(stats));
385
188
  }
386
- /**
387
- * Clear cache
388
- */
389
189
  clearCache(res) {
390
- const cache = getGlobalCache();
190
+ const cache = new CacheService();
391
191
  cache.clear();
392
192
  res.setHeader('Content-Type', 'application/json');
393
193
  res.writeHead(200);
394
194
  res.end(JSON.stringify({ success: true, message: 'Cache cleared' }));
395
195
  }
396
- /**
397
- * Reset circuit breakers
398
- */
399
196
  resetCircuitBreakers(res) {
400
- // Circuit breakers auto-reset based on timeout
401
- // This endpoint just returns success
402
197
  res.setHeader('Content-Type', 'application/json');
403
198
  res.writeHead(200);
404
199
  res.end(JSON.stringify({ success: true, message: 'Circuit breakers will reset automatically' }));
405
200
  }
406
- /**
407
- * Serve alert rules
408
- */
409
201
  serveAlertRules(res) {
410
202
  const alertManager = getAlertManager();
411
203
  const rules = alertManager.getRules();
@@ -413,9 +205,6 @@ export class DashboardServer {
413
205
  res.writeHead(200);
414
206
  res.end(JSON.stringify(rules, null, 2));
415
207
  }
416
- /**
417
- * Serve alert history
418
- */
419
208
  serveAlertHistory(res) {
420
209
  const alertManager = getAlertManager();
421
210
  const history = alertManager.getAlertHistory(50);
@@ -423,11 +212,8 @@ export class DashboardServer {
423
212
  res.writeHead(200);
424
213
  res.end(JSON.stringify(history, null, 2));
425
214
  }
426
- /**
427
- * Collect all stats
428
- */
429
215
  collectStats() {
430
- const cache = getGlobalCache();
216
+ const cache = new CacheService();
431
217
  const cacheStats = cache.getStats();
432
218
  const realtimeManager = getRealtimeManager();
433
219
  const alertManager = getAlertManager();
@@ -440,22 +226,17 @@ export class DashboardServer {
440
226
  },
441
227
  circuitBreakers: getAllCircuitBreakerStatus(),
442
228
  realtime: {
443
- isRunning: true, // Would check actual state
229
+ isRunning: true,
444
230
  liveMatches: realtimeManager.getLiveMatches().length,
445
231
  subscribers: realtimeManager.listenerCount('event'),
446
232
  },
447
233
  alerts: alertManager.getStats(),
448
234
  };
449
235
  }
450
- /**
451
- * Broadcast stats to all connected clients (for WebSocket upgrade)
452
- */
453
236
  broadcastStats() {
454
- // In a full implementation, this would push to WebSocket clients
455
- // For now, clients poll via HTTP
237
+ // WebSocket broadcast would go here
456
238
  }
457
239
  }
458
- // Singleton instance
459
240
  let globalDashboardServer = null;
460
241
  export function startDashboard(port) {
461
242
  if (!globalDashboardServer) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * ALERT MANAGER
3
- * Real-time alert system with rule engine and notifications
3
+ * Real-time alert system with rule engine
4
4
  */
5
5
  import { EventEmitter } from 'events';
6
6
  import type { LiveEvent } from './realtime-manager.js';
@@ -61,80 +61,31 @@ export declare class AlertManager extends EventEmitter {
61
61
  private alertHistory;
62
62
  private maxHistorySize;
63
63
  constructor();
64
- /**
65
- * Start the alert manager
66
- */
67
64
  start(): void;
68
- /**
69
- * Stop the alert manager
70
- */
71
65
  stop(): void;
72
- /**
73
- * Add a new alert rule
74
- */
75
66
  addRule(rule: Omit<AlertRule, 'id' | 'createdAt' | 'triggerCount'>): AlertRule;
76
- /**
77
- * Remove an alert rule
78
- */
79
67
  removeRule(ruleId: string): boolean;
80
- /**
81
- * Get all rules
82
- */
83
68
  getRules(): AlertRule[];
84
- /**
85
- * Get a specific rule
86
- */
87
69
  getRule(ruleId: string): AlertRule | undefined;
88
- /**
89
- * Enable/disable a rule
90
- */
91
70
  toggleRule(ruleId: string, enabled: boolean): boolean;
92
- /**
93
- * Process a live event and check for alerts
94
- */
95
71
  processEvent(event: LiveEvent): void;
96
- /**
97
- * Evaluate an alert condition against an event
98
- */
99
72
  private evaluateCondition;
100
73
  private evaluateOddsDrop;
101
74
  private evaluateOddsValue;
102
75
  private evaluateEventCondition;
103
76
  private evaluateCompositeCondition;
104
- /**
105
- * Trigger an alert
106
- */
107
77
  private triggerAlert;
108
- /**
109
- * Create an alert message
110
- */
111
78
  private createAlertMessage;
112
79
  private determineSeverity;
113
80
  private formatAlertTitle;
114
81
  private formatAlertBody;
115
- /**
116
- * Send notification to a channel
117
- */
118
82
  private sendNotification;
119
83
  private sendWebhook;
120
84
  private sendSlack;
121
85
  private sendDiscord;
122
- private sendEmail;
123
- /**
124
- * Check scheduled alerts (for time-based alerts)
125
- */
126
86
  private checkScheduledAlerts;
127
- /**
128
- * Get alert history
129
- */
130
87
  getAlertHistory(limit?: number): AlertMessage[];
131
- /**
132
- * Clear alert history
133
- */
134
88
  clearHistory(): void;
135
- /**
136
- * Get statistics
137
- */
138
89
  getStats(): {
139
90
  totalRules: number;
140
91
  enabledRules: number;