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
JavaScript
/**
* ๐ง 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