@gotza02/sequential-thinking 2026.2.39 → 2026.2.41

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 (38) hide show
  1. package/README.md +7 -4
  2. package/SYSTEM_INSTRUCTION.md +25 -50
  3. package/dist/tools/sports/core/base.d.ts +169 -0
  4. package/dist/tools/sports/core/base.js +289 -0
  5. package/dist/tools/sports/core/cache.d.ts +106 -0
  6. package/dist/tools/sports/core/cache.js +305 -0
  7. package/dist/tools/sports/core/constants.d.ts +179 -0
  8. package/dist/tools/sports/core/constants.js +149 -0
  9. package/dist/tools/sports/core/types.d.ts +379 -0
  10. package/dist/tools/sports/core/types.js +5 -0
  11. package/dist/tools/sports/index.d.ts +34 -0
  12. package/dist/tools/sports/index.js +50 -0
  13. package/dist/tools/sports/providers/api.d.ts +73 -0
  14. package/dist/tools/sports/providers/api.js +517 -0
  15. package/dist/tools/sports/providers/scraper.d.ts +66 -0
  16. package/dist/tools/sports/providers/scraper.js +186 -0
  17. package/dist/tools/sports/providers/search.d.ts +54 -0
  18. package/dist/tools/sports/providers/search.js +224 -0
  19. package/dist/tools/sports/tools/betting.d.ts +6 -0
  20. package/dist/tools/sports/tools/betting.js +251 -0
  21. package/dist/tools/sports/tools/league.d.ts +11 -0
  22. package/dist/tools/sports/tools/league.js +12 -0
  23. package/dist/tools/sports/tools/live.d.ts +9 -0
  24. package/dist/tools/sports/tools/live.js +235 -0
  25. package/dist/tools/sports/tools/match.d.ts +6 -0
  26. package/dist/tools/sports/tools/match.js +323 -0
  27. package/dist/tools/sports/tools/player.d.ts +6 -0
  28. package/dist/tools/sports/tools/player.js +152 -0
  29. package/dist/tools/sports/tools/team.d.ts +6 -0
  30. package/dist/tools/sports/tools/team.js +370 -0
  31. package/dist/tools/sports/utils/calculator.d.ts +69 -0
  32. package/dist/tools/sports/utils/calculator.js +156 -0
  33. package/dist/tools/sports/utils/formatter.d.ts +57 -0
  34. package/dist/tools/sports/utils/formatter.js +206 -0
  35. package/dist/tools/sports.d.ts +7 -0
  36. package/dist/tools/sports.js +27 -6
  37. package/package.json +1 -1
  38. package/system_instruction.md +155 -0
@@ -0,0 +1,106 @@
1
+ /**
2
+ * SPORTS MODULE CACHE SERVICE
3
+ * TTL-based caching with file persistence for the football intelligence system
4
+ */
5
+ /**
6
+ * CacheService - Thread-safe TTL-based caching with persistence
7
+ */
8
+ export declare class CacheService {
9
+ private cache;
10
+ private cachePath;
11
+ private maxAge;
12
+ private maxSize;
13
+ private savePending;
14
+ private saveTimer;
15
+ constructor(cachePath?: string, maxAge?: number, maxSize?: number);
16
+ /**
17
+ * Generate a cache key from components
18
+ */
19
+ static generateKey(...parts: (string | number)[]): string;
20
+ /**
21
+ * Get a value from cache
22
+ */
23
+ get<T>(key: string): T | null;
24
+ /**
25
+ * Set a value in cache
26
+ */
27
+ set<T>(key: string, data: T, ttl?: number): void;
28
+ /**
29
+ * Check if a key exists and is not expired
30
+ */
31
+ has(key: string): boolean;
32
+ /**
33
+ * Delete a specific key
34
+ */
35
+ delete(key: string): boolean;
36
+ /**
37
+ * Clear all cache entries
38
+ */
39
+ clear(): void;
40
+ /**
41
+ * Get cache statistics
42
+ */
43
+ getStats(): {
44
+ size: number;
45
+ maxSize: number;
46
+ hits: number;
47
+ entries: Array<{
48
+ key: string;
49
+ hits: number;
50
+ age: number;
51
+ ttl: number;
52
+ }>;
53
+ };
54
+ /**
55
+ * Clean up expired entries
56
+ */
57
+ cleanup(): number;
58
+ /**
59
+ * Evict the oldest entry (LRU)
60
+ */
61
+ private evictOldest;
62
+ /**
63
+ * Schedule a save operation (debounced)
64
+ */
65
+ private scheduleSave;
66
+ /**
67
+ * Save cache to file
68
+ */
69
+ private saveToFile;
70
+ /**
71
+ * Load cache from file
72
+ */
73
+ private loadFromFile;
74
+ /**
75
+ * Force save cache to file immediately
76
+ */
77
+ flush(): Promise<void>;
78
+ /**
79
+ * Get or set pattern - returns cached value or computes and caches it
80
+ */
81
+ getOrSet<T>(key: string, factory: () => T | Promise<T>, ttl?: number): Promise<T>;
82
+ /**
83
+ * Get multiple keys at once
84
+ */
85
+ getMultiple<T>(keys: string[]): Map<string, T>;
86
+ /**
87
+ * Set multiple keys at once
88
+ */
89
+ setMultiple<T>(entries: Map<string, T>, ttl?: number): void;
90
+ /**
91
+ * Invalidate cache by pattern
92
+ */
93
+ invalidatePattern(pattern: string): number;
94
+ /**
95
+ * Get cache size breakdown by key prefix
96
+ */
97
+ getBreakdown(): Record<string, number>;
98
+ }
99
+ /**
100
+ * Get or create the global cache instance
101
+ */
102
+ export declare function getGlobalCache(): CacheService;
103
+ /**
104
+ * Reset the global cache instance
105
+ */
106
+ export declare function resetGlobalCache(): void;
@@ -0,0 +1,305 @@
1
+ /**
2
+ * SPORTS MODULE CACHE SERVICE
3
+ * TTL-based caching with file persistence for the football intelligence system
4
+ */
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ import { CACHE_CONFIG } from './constants.js';
8
+ import { logger } from '../../../utils.js';
9
+ /**
10
+ * CacheService - Thread-safe TTL-based caching with persistence
11
+ */
12
+ export class CacheService {
13
+ cache = new Map();
14
+ cachePath;
15
+ maxAge;
16
+ maxSize;
17
+ savePending = false;
18
+ saveTimer = null;
19
+ constructor(cachePath = CACHE_CONFIG.CACHE_PATH, maxAge = CACHE_CONFIG.DEFAULT_TTL, maxSize = CACHE_CONFIG.MAX_SIZE) {
20
+ this.cachePath = path.resolve(cachePath);
21
+ this.maxAge = maxAge;
22
+ this.maxSize = maxSize;
23
+ this.loadFromFile();
24
+ }
25
+ /**
26
+ * Generate a cache key from components
27
+ */
28
+ static generateKey(...parts) {
29
+ return parts.join(':').toLowerCase().replace(/\s+/g, '_');
30
+ }
31
+ /**
32
+ * Get a value from cache
33
+ */
34
+ get(key) {
35
+ const entry = this.cache.get(key);
36
+ if (!entry) {
37
+ return null;
38
+ }
39
+ // Check if expired
40
+ const now = Date.now();
41
+ if (now - entry.timestamp > entry.ttl) {
42
+ this.cache.delete(key);
43
+ logger.debug(`Cache expired: ${key}`);
44
+ return null;
45
+ }
46
+ // Increment hit counter
47
+ entry.hits++;
48
+ logger.debug(`Cache hit: ${key} (${entry.hits} hits)`);
49
+ return entry.data;
50
+ }
51
+ /**
52
+ * Set a value in cache
53
+ */
54
+ set(key, data, ttl) {
55
+ const now = Date.now();
56
+ // Check if we need to evict old entries
57
+ if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
58
+ this.evictOldest();
59
+ }
60
+ this.cache.set(key, {
61
+ key,
62
+ data,
63
+ timestamp: now,
64
+ ttl: ttl || this.maxAge,
65
+ hits: 0,
66
+ });
67
+ logger.debug(`Cache set: ${key} (TTL: ${ttl || this.maxAge}ms)`);
68
+ this.scheduleSave();
69
+ }
70
+ /**
71
+ * Check if a key exists and is not expired
72
+ */
73
+ has(key) {
74
+ const entry = this.cache.get(key);
75
+ if (!entry)
76
+ return false;
77
+ const now = Date.now();
78
+ if (now - entry.timestamp > entry.ttl) {
79
+ this.cache.delete(key);
80
+ return false;
81
+ }
82
+ return true;
83
+ }
84
+ /**
85
+ * Delete a specific key
86
+ */
87
+ delete(key) {
88
+ return this.cache.delete(key);
89
+ }
90
+ /**
91
+ * Clear all cache entries
92
+ */
93
+ clear() {
94
+ this.cache.clear();
95
+ logger.info('Cache cleared');
96
+ this.scheduleSave();
97
+ }
98
+ /**
99
+ * Get cache statistics
100
+ */
101
+ getStats() {
102
+ const now = Date.now();
103
+ const entries = Array.from(this.cache.values()).map(entry => ({
104
+ key: entry.key,
105
+ hits: entry.hits,
106
+ age: now - entry.timestamp,
107
+ ttl: entry.ttl,
108
+ }));
109
+ return {
110
+ size: this.cache.size,
111
+ maxSize: this.maxSize,
112
+ hits: entries.reduce((sum, e) => sum + e.hits, 0),
113
+ entries: entries.sort((a, b) => b.hits - a.hits),
114
+ };
115
+ }
116
+ /**
117
+ * Clean up expired entries
118
+ */
119
+ cleanup() {
120
+ const now = Date.now();
121
+ let removed = 0;
122
+ for (const [key, entry] of this.cache.entries()) {
123
+ if (now - entry.timestamp > entry.ttl) {
124
+ this.cache.delete(key);
125
+ removed++;
126
+ }
127
+ }
128
+ if (removed > 0) {
129
+ logger.info(`Cleaned up ${removed} expired cache entries`);
130
+ this.scheduleSave();
131
+ }
132
+ return removed;
133
+ }
134
+ /**
135
+ * Evict the oldest entry (LRU)
136
+ */
137
+ evictOldest() {
138
+ let oldestKey = null;
139
+ let oldestTime = Infinity;
140
+ for (const [key, entry] of this.cache.entries()) {
141
+ if (entry.timestamp < oldestTime) {
142
+ oldestTime = entry.timestamp;
143
+ oldestKey = key;
144
+ }
145
+ }
146
+ if (oldestKey) {
147
+ this.cache.delete(oldestKey);
148
+ logger.debug(`Evicted oldest cache entry: ${oldestKey}`);
149
+ }
150
+ }
151
+ /**
152
+ * Schedule a save operation (debounced)
153
+ */
154
+ scheduleSave() {
155
+ if (this.saveTimer) {
156
+ return;
157
+ }
158
+ this.saveTimer = setTimeout(() => {
159
+ this.saveToFile();
160
+ this.saveTimer = null;
161
+ }, 1000); // Save after 1 second of inactivity
162
+ }
163
+ /**
164
+ * Save cache to file
165
+ */
166
+ async saveToFile() {
167
+ if (this.savePending)
168
+ return;
169
+ this.savePending = true;
170
+ try {
171
+ const data = Array.from(this.cache.entries());
172
+ const tmpPath = `${this.cachePath}.tmp`;
173
+ await fs.writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf-8');
174
+ await fs.rename(tmpPath, this.cachePath);
175
+ logger.debug(`Cache saved to ${this.cachePath}`);
176
+ }
177
+ catch (error) {
178
+ logger.error(`Failed to save cache: ${error}`);
179
+ }
180
+ finally {
181
+ this.savePending = false;
182
+ }
183
+ }
184
+ /**
185
+ * Load cache from file
186
+ */
187
+ async loadFromFile() {
188
+ try {
189
+ const data = await fs.readFile(this.cachePath, 'utf-8');
190
+ const entries = JSON.parse(data);
191
+ // Restore only non-expired entries
192
+ const now = Date.now();
193
+ let restored = 0;
194
+ for (const [key, entry] of entries) {
195
+ if (now - entry.timestamp < entry.ttl) {
196
+ this.cache.set(key, entry);
197
+ restored++;
198
+ }
199
+ }
200
+ logger.info(`Cache loaded: ${restored}/${entries.length} entries restored`);
201
+ }
202
+ catch (error) {
203
+ // File doesn't exist or is invalid - start fresh
204
+ logger.debug('No existing cache file found, starting fresh');
205
+ }
206
+ }
207
+ /**
208
+ * Force save cache to file immediately
209
+ */
210
+ async flush() {
211
+ if (this.saveTimer) {
212
+ clearTimeout(this.saveTimer);
213
+ this.saveTimer = null;
214
+ }
215
+ await this.saveToFile();
216
+ }
217
+ /**
218
+ * Get or set pattern - returns cached value or computes and caches it
219
+ */
220
+ async getOrSet(key, factory, ttl) {
221
+ const cached = this.get(key);
222
+ if (cached !== null) {
223
+ return cached;
224
+ }
225
+ const value = await factory();
226
+ this.set(key, value, ttl);
227
+ return value;
228
+ }
229
+ /**
230
+ * Get multiple keys at once
231
+ */
232
+ getMultiple(keys) {
233
+ const result = new Map();
234
+ for (const key of keys) {
235
+ const value = this.get(key);
236
+ if (value !== null) {
237
+ result.set(key, value);
238
+ }
239
+ }
240
+ return result;
241
+ }
242
+ /**
243
+ * Set multiple keys at once
244
+ */
245
+ setMultiple(entries, ttl) {
246
+ for (const [key, value] of entries.entries()) {
247
+ this.set(key, value, ttl);
248
+ }
249
+ }
250
+ /**
251
+ * Invalidate cache by pattern
252
+ */
253
+ invalidatePattern(pattern) {
254
+ const regex = new RegExp(pattern);
255
+ let removed = 0;
256
+ for (const key of this.cache.keys()) {
257
+ if (regex.test(key)) {
258
+ this.cache.delete(key);
259
+ removed++;
260
+ }
261
+ }
262
+ if (removed > 0) {
263
+ logger.info(`Invalidated ${removed} entries matching pattern: ${pattern}`);
264
+ this.scheduleSave();
265
+ }
266
+ return removed;
267
+ }
268
+ /**
269
+ * Get cache size breakdown by key prefix
270
+ */
271
+ getBreakdown() {
272
+ const breakdown = {};
273
+ for (const key of this.cache.keys()) {
274
+ const prefix = key.split(':')[0] || 'unknown';
275
+ breakdown[prefix] = (breakdown[prefix] || 0) + 1;
276
+ }
277
+ return breakdown;
278
+ }
279
+ }
280
+ /**
281
+ * Singleton cache instance
282
+ */
283
+ let globalCache = null;
284
+ /**
285
+ * Get or create the global cache instance
286
+ */
287
+ export function getGlobalCache() {
288
+ if (!globalCache) {
289
+ globalCache = new CacheService();
290
+ // Cleanup expired entries every 5 minutes
291
+ setInterval(() => {
292
+ globalCache?.cleanup();
293
+ }, 5 * 60 * 1000);
294
+ }
295
+ return globalCache;
296
+ }
297
+ /**
298
+ * Reset the global cache instance
299
+ */
300
+ export function resetGlobalCache() {
301
+ if (globalCache) {
302
+ globalCache.clear();
303
+ }
304
+ globalCache = null;
305
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * SPORTS MODULE CONSTANTS
3
+ * Configuration values for the football intelligence system
4
+ */
5
+ export declare const API_CONFIG: {
6
+ readonly API_FOOTBALL_KEY: string;
7
+ readonly API_FOOTBALL_BASE: "https://api-football-v1.p.rapidapi.com/v3";
8
+ readonly API_FOOTBALL_HOST: "api-football-v1.p.rapidapi.com";
9
+ readonly FOOTBALL_DATA_KEY: string;
10
+ readonly FOOTBALL_DATA_BASE: "https://api.football-data.org/v4";
11
+ readonly SPORTS_DB_KEY: string;
12
+ readonly SPORTS_DB_BASE: "https://www.thesportsdb.com/api/v1/json";
13
+ readonly RATE_LIMITS: {
14
+ readonly API_FOOTBALL: 10;
15
+ readonly FOOTBALL_DATA: 10;
16
+ readonly SPORTS_DB: 30;
17
+ };
18
+ };
19
+ export declare const CACHE_CONFIG: {
20
+ readonly DEFAULT_TTL: number;
21
+ readonly TTL: {
22
+ readonly LIVE_SCORES: number;
23
+ readonly MATCH_DETAILS: number;
24
+ readonly STANDINGS: number;
25
+ readonly TEAM_STATS: number;
26
+ readonly PLAYER_STATS: number;
27
+ readonly ODDS: number;
28
+ readonly TRANSFER_NEWS: number;
29
+ };
30
+ readonly CACHE_PATH: string;
31
+ readonly MAX_SIZE: 1000;
32
+ };
33
+ export declare const SCRAPER_CONFIG: {
34
+ readonly PRIORITY_DOMAINS: readonly ["whoscored.com", "sofascore.com", "flashscore.com", "understat.com", "fbref.com", "bbc.co.uk/sport", "skysports.com", "sportsmole.co.uk", "goal.com", "thesquareball.net"];
35
+ readonly TIMEOUT: 15000;
36
+ readonly USER_AGENT: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";
37
+ readonly MAX_CONTENT_LENGTH: 50000;
38
+ };
39
+ export declare const LEAGUES: {
40
+ readonly PREMIER_LEAGUE: {
41
+ readonly id: 39;
42
+ readonly name: "Premier League";
43
+ readonly country: "England";
44
+ readonly code: "PL";
45
+ };
46
+ readonly LA_LIGA: {
47
+ readonly id: 140;
48
+ readonly name: "La Liga";
49
+ readonly country: "Spain";
50
+ readonly code: "LL";
51
+ };
52
+ readonly BUNDESLIGA: {
53
+ readonly id: 78;
54
+ readonly name: "Bundesliga";
55
+ readonly country: "Germany";
56
+ readonly code: "BL1";
57
+ };
58
+ readonly SERIE_A: {
59
+ readonly id: 135;
60
+ readonly name: "Serie A";
61
+ readonly country: "Italy";
62
+ readonly code: "SA";
63
+ };
64
+ readonly LIGUE_1: {
65
+ readonly id: 61;
66
+ readonly name: "Ligue 1";
67
+ readonly country: "France";
68
+ readonly code: "FL1";
69
+ };
70
+ readonly EREDIVISIE: {
71
+ readonly id: 88;
72
+ readonly name: "Eredivisie";
73
+ readonly country: "Netherlands";
74
+ readonly code: "DED";
75
+ };
76
+ readonly PRIMEIRA_LIGA: {
77
+ readonly id: 94;
78
+ readonly name: "Primeira Liga";
79
+ readonly country: "Portugal";
80
+ readonly code: "PPL";
81
+ };
82
+ readonly CHAMPIONS_LEAGUE: {
83
+ readonly id: 2;
84
+ readonly name: "UEFA Champions League";
85
+ readonly country: "Europe";
86
+ readonly code: "CL";
87
+ };
88
+ readonly EUROPA_LEAGUE: {
89
+ readonly id: 3;
90
+ readonly name: "UEFA Europa League";
91
+ readonly country: "Europe";
92
+ readonly code: "EL";
93
+ };
94
+ readonly FA_CUP: {
95
+ readonly id: 45;
96
+ readonly name: "FA Cup";
97
+ readonly country: "England";
98
+ readonly code: "FAC";
99
+ };
100
+ readonly J_LEAGUE: {
101
+ readonly id: 98;
102
+ readonly name: "J1 League";
103
+ readonly country: "Japan";
104
+ readonly code: "J1";
105
+ };
106
+ readonly K_LEAGUE: {
107
+ readonly id: 251;
108
+ readonly name: "K League 1";
109
+ readonly country: "South Korea";
110
+ readonly code: "KL1";
111
+ };
112
+ readonly THAI_LEAGUE: {
113
+ readonly id: 305;
114
+ readonly name: "Thai League 1";
115
+ readonly country: "Thailand";
116
+ readonly code: "TL1";
117
+ };
118
+ readonly CSL: {
119
+ readonly id: 169;
120
+ readonly name: "Chinese Super League";
121
+ readonly country: "China";
122
+ readonly code: "CSL";
123
+ };
124
+ };
125
+ export declare const QUERY_TYPES: {
126
+ readonly GENERAL: "general";
127
+ readonly H2H: "h2h";
128
+ readonly FORM: "form";
129
+ readonly NEWS: "news";
130
+ readonly STATS: "stats";
131
+ readonly ODDS: "odds";
132
+ readonly REFEREE: "referee";
133
+ readonly WEATHER: "weather";
134
+ readonly FATIGUE: "fatigue";
135
+ readonly SETPIECES: "setpieces";
136
+ };
137
+ export declare const BETTING: {
138
+ readonly KELLY_FULL: "full";
139
+ readonly KELLY_HALF: "half";
140
+ readonly KELLY_QUARTER: "quarter";
141
+ readonly VALUE_THRESHOLD: 0.05;
142
+ readonly HIGH_VALUE_THRESHOLD: 0.1;
143
+ readonly CONFIDENCE: {
144
+ readonly LOW: 50;
145
+ readonly MEDIUM: 65;
146
+ readonly HIGH: 80;
147
+ readonly VERY_HIGH: 90;
148
+ };
149
+ readonly DEFAULT_BANKROLL: 1000;
150
+ readonly MAX_STAKE_PERCENTAGE: 0.05;
151
+ };
152
+ export declare const POSITIONS: {
153
+ readonly GOALKEEPER: "GK";
154
+ readonly DEFENDER: "DF";
155
+ readonly MIDFIELDER: "MF";
156
+ readonly FORWARD: "FW";
157
+ readonly SUBSTITUTE: "SUB";
158
+ };
159
+ export declare const MATCH_STATUS: {
160
+ readonly SCHEDULED: "scheduled";
161
+ readonly LIVE: "live";
162
+ readonly FINISHED: "finished";
163
+ readonly POSTPONED: "postponed";
164
+ readonly CANCELLED: "cancelled";
165
+ readonly ABANDONED: "abandoned";
166
+ };
167
+ export declare const ERRORS: {
168
+ readonly NO_API_KEY: "No API key configured. Please set environment variables.";
169
+ readonly RATE_LIMITED: "API rate limit exceeded. Please try again later.";
170
+ readonly NOT_FOUND: "Requested data not found.";
171
+ readonly TIMEOUT: "Request timed out.";
172
+ readonly INVALID_RESPONSE: "Invalid response from API.";
173
+ readonly ALL_PROVIDERS_FAILED: "All data providers failed.";
174
+ };
175
+ export declare const MODULE_INFO: {
176
+ readonly NAME: "sports-module";
177
+ readonly VERSION: "2.0.0";
178
+ readonly DESCRIPTION: "Football Intelligence System for MCP Server";
179
+ };