UNPKG

ai-debug-local-mcp

Version:

๐ŸŽฏ ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh

294 lines โ€ข 8.78 kB
/** * ๐Ÿง  Intelligent Caching System for AI-Debug * * Caches expensive operations and system information to improve performance * Uses smart invalidation and memory management */ import { EventEmitter } from 'events'; export class IntelligentCache extends EventEmitter { cache = new Map(); options; totalSize = 0; constructor(options = {}) { super(); this.options = { ttl: 5 * 60 * 1000, // 5 minutes default maxSize: 50 * 1024 * 1024, // 50MB default maxEntries: 1000, onEvict: () => { }, ...options }; // Periodic cleanup setInterval(() => this.cleanup(), 30000); // Every 30 seconds } /** * Get value from cache with automatic validation */ get(key) { const entry = this.cache.get(key); if (!entry) { return null; } // Check TTL if (Date.now() - entry.timestamp > entry.ttl) { this.delete(key); return null; } // Update access statistics entry.hits++; entry.lastAccess = Date.now(); return entry.value; } /** * Set value in cache with intelligent eviction */ set(key, value, options = {}) { const ttl = options.ttl || this.options.ttl; const size = this.estimateSize(value); // Check if we need to make space while ((this.cache.size >= this.options.maxEntries) || (this.totalSize + size > this.options.maxSize)) { this.evictLeastUsed(); } // Remove existing entry if updating if (this.cache.has(key)) { this.delete(key); } const entry = { value, timestamp: Date.now(), ttl, hits: 0, lastAccess: Date.now(), size }; this.cache.set(key, entry); this.totalSize += size; this.emit('set', key, value); } /** * Get or compute value with caching */ async getOrCompute(key, compute, options = {}) { const cached = this.get(key); if (cached !== null) { return cached; } const value = await compute(); this.set(key, value, options); return value; } /** * Delete entry from cache */ delete(key) { const entry = this.cache.get(key); if (!entry) { return false; } this.cache.delete(key); this.totalSize -= entry.size; this.options.onEvict(key, entry.value); this.emit('delete', key); return true; } /** * Clear all entries */ clear() { this.cache.clear(); this.totalSize = 0; this.emit('clear'); } /** * Get cache statistics */ getStats() { const entries = this.cache.size; const now = Date.now(); let totalHits = 0; let totalAccesses = 0; let totalAge = 0; for (const entry of this.cache.values()) { totalHits += entry.hits; totalAccesses += entry.hits + 1; // +1 for initial set totalAge += now - entry.timestamp; } return { entries, totalSize: this.totalSize, hitRate: totalAccesses > 0 ? totalHits / totalAccesses : 0, averageAge: entries > 0 ? totalAge / entries : 0, memoryUsage: `${(this.totalSize / 1024 / 1024).toFixed(2)} MB` }; } /** * Cleanup expired entries */ cleanup() { const now = Date.now(); const toDelete = []; for (const [key, entry] of this.cache) { if (now - entry.timestamp > entry.ttl) { toDelete.push(key); } } for (const key of toDelete) { this.delete(key); } if (toDelete.length > 0) { console.log(`๐Ÿงน Cache cleanup: removed ${toDelete.length} expired entries`); } } /** * Evict least recently used entry */ evictLeastUsed() { let lruKey = null; let lruScore = Infinity; for (const [key, entry] of this.cache) { // Score based on hits and recency (lower = less valuable) const score = entry.hits * Math.log(Date.now() - entry.lastAccess + 1); if (score < lruScore) { lruScore = score; lruKey = key; } } if (lruKey) { console.log(`๐Ÿ—‘๏ธ Cache eviction: removing least used entry ${lruKey}`); this.delete(lruKey); } } /** * Estimate memory size of value */ estimateSize(value) { if (typeof value === 'string') { return value.length * 2; // UTF-16 } if (typeof value === 'number') { return 8; } if (typeof value === 'boolean') { return 4; } if (Buffer.isBuffer(value)) { return value.length; } if (typeof value === 'object' && value !== null) { return JSON.stringify(value).length * 2; // Rough estimate } return 100; // Default estimate } } /** * System Information Cache - Caches expensive system queries */ export class SystemInfoCache { windowsCache = new IntelligentCache({ ttl: 10000 }); // 10 seconds processCache = new IntelligentCache({ ttl: 5000 }); // 5 seconds screenCache = new IntelligentCache({ ttl: 1000 }); // 1 second /** * Cache window information */ async getWindowInfo(appName) { return this.windowsCache.getOrCompute(`window:${appName}`, async () => { // Expensive window discovery operation return await this.discoverWindows(appName); }, { ttl: 10000 }); } /** * Cache process information */ async getProcessInfo(pid) { return this.processCache.getOrCompute(`process:${pid}`, async () => { // Expensive process info query return await this.queryProcessInfo(pid); }); } /** * Cache screen information */ async getScreenInfo() { return this.screenCache.getOrCompute('screen:info', async () => { // Screen resolution, bounds, etc. return await this.queryScreenInfo(); }); } /** * Invalidate cache for specific app when windows change */ invalidateWindowCache(appName) { if (appName) { this.windowsCache.delete(`window:${appName}`); } else { this.windowsCache.clear(); } } async discoverWindows(appName) { // Simulate expensive window discovery console.log(`๐Ÿ” Discovering windows for: ${appName}`); // Implementation would use native APIs here return { appName, windows: [] }; } async queryProcessInfo(pid) { console.log(`๐Ÿ” Querying process info for PID: ${pid}`); // Implementation would query system process info return { pid, status: 'running' }; } async queryScreenInfo() { console.log('๐Ÿ” Querying screen information'); // Implementation would get screen bounds, resolution, etc. return { width: 1920, height: 1080 }; } /** * Get combined cache statistics */ getStats() { return { windows: this.windowsCache.getStats(), processes: this.processCache.getStats(), screen: this.screenCache.getStats() }; } } /** * Global system cache instance */ export const systemCache = new SystemInfoCache(); /** * Performance-optimized file system cache */ export class FileSystemCache extends IntelligentCache { constructor() { super({ ttl: 30000, // 30 seconds for file contents maxSize: 100 * 1024 * 1024, // 100MB maxEntries: 500 }); } /** * Cache file contents with hash-based invalidation */ async getFileContents(filePath) { const { promises: fs } = await import('fs'); try { // Check if file exists and get stats const stats = await fs.stat(filePath); const fileKey = `file:${filePath}:${stats.mtime.getTime()}`; return await this.getOrCompute(fileKey, async () => { console.log(`๐Ÿ“ Reading file: ${filePath}`); return await fs.readFile(filePath, 'utf-8'); }); } catch (error) { return null; } } } /** * Global file system cache */ export const fileCache = new FileSystemCache(); //# sourceMappingURL=intelligent-caching-system.js.map