@gotza02/sequential-thinking 10000.1.2 → 10000.1.3

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,96 +0,0 @@
1
- /**
2
- * ALERT MANAGER
3
- * Real-time alert system with rule engine
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
- start(): void;
65
- stop(): void;
66
- addRule(rule: Omit<AlertRule, 'id' | 'createdAt' | 'triggerCount'>): AlertRule;
67
- removeRule(ruleId: string): boolean;
68
- getRules(): AlertRule[];
69
- getRule(ruleId: string): AlertRule | undefined;
70
- toggleRule(ruleId: string, enabled: boolean): boolean;
71
- processEvent(event: LiveEvent): void;
72
- private evaluateCondition;
73
- private evaluateOddsDrop;
74
- private evaluateOddsValue;
75
- private evaluateEventCondition;
76
- private evaluateCompositeCondition;
77
- private triggerAlert;
78
- private createAlertMessage;
79
- private determineSeverity;
80
- private formatAlertTitle;
81
- private formatAlertBody;
82
- private sendNotification;
83
- private sendWebhook;
84
- private sendSlack;
85
- private sendDiscord;
86
- private checkScheduledAlerts;
87
- getAlertHistory(limit?: number): AlertMessage[];
88
- clearHistory(): void;
89
- getStats(): {
90
- totalRules: number;
91
- enabledRules: number;
92
- totalAlerts: number;
93
- };
94
- }
95
- export declare function getAlertManager(): AlertManager;
96
- export declare function resetAlertManager(): void;
@@ -1,319 +0,0 @@
1
- /**
2
- * ALERT MANAGER
3
- * Real-time alert system with rule engine
4
- */
5
- import { EventEmitter } from 'events';
6
- import { ALERT_CONFIG } from './constants.js';
7
- // Simple logger fallback
8
- const logger = {
9
- info: (...args) => console.error('[INFO]', ...args),
10
- warn: (...args) => console.warn('[WARN]', ...args),
11
- error: (...args) => console.error('[ERROR]', ...args),
12
- debug: (...args) => { }
13
- };
14
- export class AlertManager extends EventEmitter {
15
- rules = new Map();
16
- checkInterval;
17
- alertHistory = [];
18
- maxHistorySize = 1000;
19
- constructor() {
20
- super();
21
- this.setMaxListeners(100);
22
- }
23
- start() {
24
- if (this.checkInterval)
25
- return;
26
- this.checkInterval = setInterval(() => {
27
- this.checkScheduledAlerts();
28
- }, ALERT_CONFIG.CHECK_INTERVAL);
29
- logger.info('[AlertManager] Started');
30
- }
31
- stop() {
32
- if (this.checkInterval) {
33
- clearInterval(this.checkInterval);
34
- this.checkInterval = undefined;
35
- }
36
- logger.info('[AlertManager] Stopped');
37
- }
38
- addRule(rule) {
39
- const newRule = {
40
- ...rule,
41
- id: `alert-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
42
- createdAt: Date.now(),
43
- triggerCount: 0,
44
- };
45
- this.rules.set(newRule.id, newRule);
46
- logger.info(`[AlertManager] Added rule: ${newRule.id} (${newRule.name})`);
47
- this.emit('rule_added', newRule);
48
- return newRule;
49
- }
50
- removeRule(ruleId) {
51
- const removed = this.rules.delete(ruleId);
52
- if (removed) {
53
- logger.info(`[AlertManager] Removed rule: ${ruleId}`);
54
- this.emit('rule_removed', ruleId);
55
- }
56
- return removed;
57
- }
58
- getRules() {
59
- return Array.from(this.rules.values());
60
- }
61
- getRule(ruleId) {
62
- return this.rules.get(ruleId);
63
- }
64
- toggleRule(ruleId, enabled) {
65
- const rule = this.rules.get(ruleId);
66
- if (rule) {
67
- rule.enabled = enabled;
68
- logger.info(`[AlertManager] Rule ${ruleId} ${enabled ? 'enabled' : 'disabled'}`);
69
- return true;
70
- }
71
- return false;
72
- }
73
- processEvent(event) {
74
- for (const rule of this.rules.values()) {
75
- if (!rule.enabled)
76
- continue;
77
- if (rule.lastTriggered && Date.now() - rule.lastTriggered < rule.cooldown)
78
- continue;
79
- if (rule.triggerCount && rule.triggerCount >= ALERT_CONFIG.MAX_ALERTS_PER_HOUR)
80
- continue;
81
- if (this.evaluateCondition(rule.condition, event)) {
82
- this.triggerAlert(rule, event);
83
- }
84
- }
85
- }
86
- evaluateCondition(condition, event) {
87
- switch (condition.type) {
88
- case 'odds_drop':
89
- return this.evaluateOddsDrop(condition, event);
90
- case 'odds_value':
91
- return this.evaluateOddsValue(condition, event);
92
- case 'event':
93
- return this.evaluateEventCondition(condition, event);
94
- case 'composite':
95
- return this.evaluateCompositeCondition(condition, event);
96
- default:
97
- return false;
98
- }
99
- }
100
- evaluateOddsDrop(condition, event) {
101
- if (event.type !== 'odds_change')
102
- return false;
103
- const oddsEvent = event;
104
- const { newOdds, change } = oddsEvent.data;
105
- if (condition.matchId && event.matchId !== condition.matchId)
106
- return false;
107
- if (newOdds > condition.threshold)
108
- return false;
109
- return Math.abs(change) >= condition.percentage;
110
- }
111
- evaluateOddsValue(condition, event) {
112
- if (event.type !== 'odds_change')
113
- return false;
114
- const oddsEvent = event;
115
- const { newOdds } = oddsEvent.data;
116
- if (condition.matchId && event.matchId !== condition.matchId)
117
- return false;
118
- if (condition.maxOdds && newOdds > condition.maxOdds)
119
- return false;
120
- return true;
121
- }
122
- evaluateEventCondition(condition, event) {
123
- if (condition.matchId && event.matchId !== condition.matchId)
124
- return false;
125
- return condition.eventTypes.includes(event.type);
126
- }
127
- evaluateCompositeCondition(condition, event) {
128
- const results = condition.conditions.map(c => this.evaluateCondition(c, event));
129
- return condition.operator === 'AND'
130
- ? results.every(r => r)
131
- : results.some(r => r);
132
- }
133
- async triggerAlert(rule, event) {
134
- rule.lastTriggered = Date.now();
135
- rule.triggerCount = (rule.triggerCount || 0) + 1;
136
- const message = this.createAlertMessage(rule, event);
137
- this.alertHistory.push(message);
138
- if (this.alertHistory.length > this.maxHistorySize) {
139
- this.alertHistory.shift();
140
- }
141
- for (const channel of rule.channels) {
142
- try {
143
- await this.sendNotification(channel, message);
144
- }
145
- catch (error) {
146
- logger.error(`[AlertManager] Failed to send notification: ${error}`);
147
- }
148
- }
149
- this.emit('alert', message);
150
- logger.info(`[AlertManager] Alert triggered: ${rule.name} (${rule.id})`);
151
- }
152
- createAlertMessage(rule, event) {
153
- const severity = this.determineSeverity(rule.type, event);
154
- return {
155
- ruleId: rule.id,
156
- ruleName: rule.name,
157
- type: rule.type,
158
- severity,
159
- title: this.formatAlertTitle(rule, event),
160
- body: this.formatAlertBody(rule, event),
161
- data: { event, rule },
162
- timestamp: Date.now(),
163
- };
164
- }
165
- determineSeverity(type, event) {
166
- switch (type) {
167
- case 'goal':
168
- case 'red_card':
169
- return 'critical';
170
- case 'odds_drop':
171
- case 'odds_value':
172
- return 'warning';
173
- default:
174
- return 'info';
175
- }
176
- }
177
- formatAlertTitle(rule, event) {
178
- switch (rule.type) {
179
- case 'odds_drop':
180
- return `Odds Drop Alert: ${event.matchId}`;
181
- case 'odds_value':
182
- return `Value Bet Alert: ${event.matchId}`;
183
- case 'goal':
184
- return `GOAL! ${event.matchId}`;
185
- case 'red_card':
186
- return `RED CARD! ${event.matchId}`;
187
- default:
188
- return rule.name;
189
- }
190
- }
191
- formatAlertBody(rule, event) {
192
- const lines = [];
193
- lines.push(`Rule: ${rule.name}`);
194
- lines.push(`Type: ${rule.type}`);
195
- lines.push(`Match: ${event.matchId}`);
196
- lines.push(`Time: ${new Date(event.timestamp).toLocaleString()}`);
197
- if (event.minute)
198
- lines.push(`Minute: ${event.minute}'`);
199
- if (event.data) {
200
- lines.push('');
201
- lines.push('Details:');
202
- lines.push(JSON.stringify(event.data, null, 2));
203
- }
204
- return lines.join('\n');
205
- }
206
- async sendNotification(channel, message) {
207
- switch (channel.type) {
208
- case 'webhook':
209
- await this.sendWebhook(channel.config.url, message);
210
- break;
211
- case 'slack':
212
- await this.sendSlack(channel.config.webhook, message);
213
- break;
214
- case 'discord':
215
- await this.sendDiscord(channel.config.webhook, message);
216
- break;
217
- case 'email':
218
- logger.info(`[AlertManager] Would send email to ${channel.config.to}: ${message.title}`);
219
- break;
220
- case 'console':
221
- console.error(`\n${'='.repeat(50)}`);
222
- console.error(`ALERT: ${message.title}`);
223
- console.error(`${'='.repeat(50)}`);
224
- console.error(message.body);
225
- console.error(`${'='.repeat(50)}\n`);
226
- break;
227
- }
228
- }
229
- async sendWebhook(url, message) {
230
- try {
231
- const response = await fetch(url, {
232
- method: 'POST',
233
- headers: { 'Content-Type': 'application/json' },
234
- body: JSON.stringify(message),
235
- });
236
- if (!response.ok)
237
- throw new Error(`Webhook failed: ${response.status}`);
238
- }
239
- catch (error) {
240
- logger.error('[AlertManager] Webhook failed:', error);
241
- }
242
- }
243
- async sendSlack(webhook, message) {
244
- const emoji = message.severity === 'critical' ? '' : message.severity === 'warning' ? '⚠️' : 'ℹ️';
245
- const payload = {
246
- text: `${emoji} *${message.title}*`,
247
- attachments: [{
248
- color: message.severity === 'critical' ? 'danger' : message.severity === 'warning' ? 'warning' : 'good',
249
- text: message.body,
250
- footer: 'Football Alert System',
251
- ts: Math.floor(message.timestamp / 1000),
252
- }],
253
- };
254
- try {
255
- const response = await fetch(webhook, {
256
- method: 'POST',
257
- headers: { 'Content-Type': 'application/json' },
258
- body: JSON.stringify(payload),
259
- });
260
- if (!response.ok)
261
- throw new Error(`Slack webhook failed: ${response.status}`);
262
- }
263
- catch (error) {
264
- logger.error('[AlertManager] Slack webhook failed:', error);
265
- }
266
- }
267
- async sendDiscord(webhook, message) {
268
- const color = message.severity === 'critical' ? 0xff0000 : message.severity === 'warning' ? 0xffa500 : 0x00ff00;
269
- const payload = {
270
- embeds: [{
271
- title: message.title,
272
- description: message.body,
273
- color: color,
274
- timestamp: new Date(message.timestamp).toISOString(),
275
- }],
276
- };
277
- try {
278
- const response = await fetch(webhook, {
279
- method: 'POST',
280
- headers: { 'Content-Type': 'application/json' },
281
- body: JSON.stringify(payload),
282
- });
283
- if (!response.ok)
284
- throw new Error(`Discord webhook failed: ${response.status}`);
285
- }
286
- catch (error) {
287
- logger.error('[AlertManager] Discord webhook failed:', error);
288
- }
289
- }
290
- checkScheduledAlerts() {
291
- // Time-based alerts
292
- }
293
- getAlertHistory(limit) {
294
- const history = [...this.alertHistory].reverse();
295
- return limit ? history.slice(0, limit) : history;
296
- }
297
- clearHistory() {
298
- this.alertHistory = [];
299
- }
300
- getStats() {
301
- const rules = Array.from(this.rules.values());
302
- return {
303
- totalRules: rules.length,
304
- enabledRules: rules.filter(r => r.enabled).length,
305
- totalAlerts: this.alertHistory.length,
306
- };
307
- }
308
- }
309
- let globalAlertManager = null;
310
- export function getAlertManager() {
311
- if (!globalAlertManager)
312
- globalAlertManager = new AlertManager();
313
- return globalAlertManager;
314
- }
315
- export function resetAlertManager() {
316
- if (globalAlertManager)
317
- globalAlertManager.stop();
318
- globalAlertManager = null;
319
- }
@@ -1,40 +0,0 @@
1
- /**
2
- * CIRCUIT BREAKER PATTERN
3
- * Prevents cascading failures by stopping requests to failing services
4
- */
5
- export declare class CircuitBreaker {
6
- private readonly name;
7
- private readonly failureThreshold;
8
- private readonly resetTimeout;
9
- private readonly halfOpenMaxCalls;
10
- private failures;
11
- private lastFailureTime;
12
- private state;
13
- private successCount;
14
- constructor(name: string, failureThreshold?: number, resetTimeout?: number, halfOpenMaxCalls?: number);
15
- /**
16
- * Execute a function with circuit breaker protection
17
- */
18
- execute<T>(fn: () => Promise<T>, context?: string): Promise<T>;
19
- private onSuccess;
20
- private onFailure;
21
- getStatus(): {
22
- name: string;
23
- state: "closed" | "open" | "half-open";
24
- failures: number;
25
- lastFailure: number | null;
26
- };
27
- }
28
- export declare class CircuitBreakerOpenError extends Error {
29
- readonly retryAfter: number;
30
- constructor(message: string, retryAfter: number);
31
- }
32
- export declare function getCircuitBreaker(name: string, config?: {
33
- failureThreshold?: number;
34
- resetTimeout?: number;
35
- }): CircuitBreaker;
36
- export declare function getAllCircuitBreakerStatus(): Array<{
37
- name: string;
38
- state: string;
39
- failures: number;
40
- }>;
@@ -1,99 +0,0 @@
1
- /**
2
- * CIRCUIT BREAKER PATTERN
3
- * Prevents cascading failures by stopping requests to failing services
4
- */
5
- import { logger } from '../../../utils.js';
6
- export class CircuitBreaker {
7
- name;
8
- failureThreshold;
9
- resetTimeout;
10
- halfOpenMaxCalls;
11
- failures = 0;
12
- lastFailureTime = null;
13
- state = 'closed';
14
- successCount = 0;
15
- constructor(name, failureThreshold = 5, resetTimeout = 60000, halfOpenMaxCalls = 3) {
16
- this.name = name;
17
- this.failureThreshold = failureThreshold;
18
- this.resetTimeout = resetTimeout;
19
- this.halfOpenMaxCalls = halfOpenMaxCalls;
20
- }
21
- /**
22
- * Execute a function with circuit breaker protection
23
- */
24
- async execute(fn, context) {
25
- if (this.state === 'open') {
26
- const timeSinceLastFailure = Date.now() - (this.lastFailureTime || 0);
27
- if (timeSinceLastFailure > this.resetTimeout) {
28
- logger.info(`[CircuitBreaker:${this.name}] Transitioning to HALF-OPEN`);
29
- this.state = 'half-open';
30
- this.successCount = 0;
31
- }
32
- else {
33
- const remainingTime = Math.ceil((this.resetTimeout - timeSinceLastFailure) / 1000);
34
- throw new CircuitBreakerOpenError(`Circuit breaker '${this.name}' is OPEN. Retry in ${remainingTime}s`, remainingTime);
35
- }
36
- }
37
- try {
38
- const result = await fn();
39
- this.onSuccess();
40
- return result;
41
- }
42
- catch (error) {
43
- this.onFailure(error instanceof Error ? error : new Error(String(error)));
44
- throw error;
45
- }
46
- }
47
- onSuccess() {
48
- if (this.state === 'half-open') {
49
- this.successCount++;
50
- if (this.successCount >= this.halfOpenMaxCalls) {
51
- logger.info(`[CircuitBreaker:${this.name}] Transitioning to CLOSED`);
52
- this.state = 'closed';
53
- this.failures = 0;
54
- this.successCount = 0;
55
- }
56
- }
57
- else {
58
- this.failures = Math.max(0, this.failures - 1);
59
- }
60
- }
61
- onFailure(error) {
62
- this.failures++;
63
- this.lastFailureTime = Date.now();
64
- logger.warn(`[CircuitBreaker:${this.name}] Failure ${this.failures}/${this.failureThreshold}: ${error.message}`);
65
- if (this.failures >= this.failureThreshold) {
66
- logger.error(`[CircuitBreaker:${this.name}] Threshold reached. Transitioning to OPEN`);
67
- this.state = 'open';
68
- }
69
- }
70
- getStatus() {
71
- return {
72
- name: this.name,
73
- state: this.state,
74
- failures: this.failures,
75
- lastFailure: this.lastFailureTime,
76
- };
77
- }
78
- }
79
- export class CircuitBreakerOpenError extends Error {
80
- retryAfter;
81
- constructor(message, retryAfter) {
82
- super(message);
83
- this.retryAfter = retryAfter;
84
- this.name = 'CircuitBreakerOpenError';
85
- }
86
- }
87
- // Global circuit breakers registry
88
- const circuitBreakers = new Map();
89
- export function getCircuitBreaker(name, config) {
90
- if (!circuitBreakers.has(name)) {
91
- circuitBreakers.set(name, new CircuitBreaker(name, config?.failureThreshold, config?.resetTimeout));
92
- }
93
- return circuitBreakers.get(name);
94
- }
95
- export function getAllCircuitBreakerStatus() {
96
- return Array.from(circuitBreakers.values()).map(cb => ({
97
- ...cb.getStatus()
98
- }));
99
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * DATA QUALITY VALIDATOR
3
- */
4
- import type { Match, Team, MatchOdds } from './types.js';
5
- export interface DataQualityReport {
6
- overall: number;
7
- completeness: number;
8
- accuracy: number;
9
- freshness: number;
10
- consistency: number;
11
- issues: DataQualityIssue[];
12
- warnings: DataQualityIssue[];
13
- suggestions: string[];
14
- }
15
- export interface DataQualityIssue {
16
- field: string;
17
- severity: 'error' | 'warning' | 'info';
18
- message: string;
19
- suggestion?: string;
20
- value?: any;
21
- }
22
- export declare class DataQualityValidator {
23
- validateMatchData(data: Partial<Match>): DataQualityReport;
24
- validateTeamData(data: Partial<Team>): DataQualityReport;
25
- validateOddsData(odds: MatchOdds): DataQualityReport;
26
- private checkCompleteness;
27
- private checkAccuracy;
28
- private checkFreshness;
29
- private checkConsistency;
30
- private generateSuggestions;
31
- private calculateFreshness;
32
- private calculateScore;
33
- isValid(data: Partial<Match>): boolean;
34
- getGrade(score: number): string;
35
- }
36
- export declare function getDataQualityValidator(): DataQualityValidator;