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
114 lines โข 4.42 kB
JavaScript
/**
* Lazy Handler Wrapper
* Wraps handlers to load dependencies only when their tools are actually used
*/
import { BaseToolHandler } from './base-handler.js';
import { loadToolDependencies } from '../utils/lazy-dependencies.js';
import { requiresExternalDependencies, getToolMemoryEstimate } from '../utils/comprehensive-tool-dependencies.js';
export class LazyHandlerWrapper extends BaseToolHandler {
wrappedHandler;
loadedDependencies = new Map();
isLoadingDeps = new Map();
tools;
constructor(handler) {
super();
this.wrappedHandler = handler;
this.tools = handler.tools;
}
getTools() {
return this.tools;
}
async handle(toolName, args, sessions) {
// Check if tool requires external dependencies
if (requiresExternalDependencies(toolName)) {
// Check if already loading dependencies for this tool
const loadingPromise = this.isLoadingDeps.get(toolName);
if (loadingPromise) {
console.log(`โณ Waiting for ${toolName} dependencies to load...`);
await loadingPromise;
}
else if (!this.loadedDependencies.has(toolName)) {
// Start loading dependencies
const memoryEstimate = getToolMemoryEstimate(toolName);
console.log(`๐ฆ Loading dependencies for ${toolName} (estimated ${memoryEstimate}MB)...`);
const loadPromise = this.loadDependencies(toolName);
this.isLoadingDeps.set(toolName, loadPromise);
try {
await loadPromise;
}
finally {
this.isLoadingDeps.delete(toolName);
}
}
}
// Call the wrapped handler with loaded dependencies available
return this.wrappedHandler.handle(toolName, args, sessions);
}
async loadDependencies(toolName) {
const startTime = Date.now();
const startMemory = process.memoryUsage().heapUsed / 1024 / 1024;
try {
const deps = await loadToolDependencies(toolName);
this.loadedDependencies.set(toolName, deps);
const endMemory = process.memoryUsage().heapUsed / 1024 / 1024;
const memoryIncrease = Math.round(endMemory - startMemory);
const loadTime = Date.now() - startTime;
console.log(`โ
Loaded ${deps.size} dependencies for ${toolName} in ${loadTime}ms (+${memoryIncrease}MB)`);
// Make dependencies available globally if needed
if (deps.has('playwright') && !global.__playwright) {
global.__playwright = deps.get('playwright');
}
}
catch (error) {
console.error(`โ Failed to load dependencies for ${toolName}:`, error);
throw new Error(`Failed to load required dependencies for ${toolName}`);
}
}
/**
* Get loaded dependencies for a tool
*/
getLoadedDependencies(toolName) {
return this.loadedDependencies.get(toolName);
}
/**
* Cleanup loaded dependencies to free memory
*/
async cleanup() {
console.log(`๐งน Cleaning up ${this.loadedDependencies.size} loaded dependency sets`);
// Clean up browser instances if loaded
if (global.__playwright) {
const { cleanupLazyDependencies } = await import('../utils/lazy-dependencies.js');
await cleanupLazyDependencies();
delete global.__playwright;
}
this.loadedDependencies.clear();
// Force garbage collection if available
if (global.gc) {
global.gc();
}
}
/**
* Get memory usage stats
*/
getMemoryStats() {
const loadedTools = Array.from(this.loadedDependencies.keys());
let totalDeps = 0;
let estimatedMemory = 0;
for (const [tool, deps] of this.loadedDependencies) {
totalDeps += deps.size;
estimatedMemory += getToolMemoryEstimate(tool);
}
return {
loadedTools,
totalDependencies: totalDeps,
estimatedMemoryMB: estimatedMemory
};
}
}
/**
* Create a lazy-loaded version of a handler
*/
export function createLazyHandler(handler) {
return new LazyHandlerWrapper(handler);
}
//# sourceMappingURL=lazy-handler-wrapper.js.map