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
225 lines • 6.84 kB
JavaScript
// Lazy Handler Registry - Performance Optimization
// Implements on-demand handler loading for 30% startup improvement
/**
* LazyHandlerRegistry - Implements lazy loading for MCP handlers
* Target: 30% startup time improvement through on-demand loading
*/
export class LazyHandlerRegistry {
lazyHandlers = new Map();
loadedHandlers = new Map();
loadingErrors = [];
fallbackConfig = {
retryAttempts: 1,
fallbackToEager: false,
notifyOnFailure: true
};
/**
* Register a handler for lazy loading
*/
registerLazyHandler(name, constructor, config = {}) {
this.lazyHandlers.set(name, {
constructor,
config: {
priority: 'medium',
loadOnDemand: true,
...config
},
loaded: false
});
}
/**
* Check if a handler is loaded
*/
isHandlerLoaded(name) {
return this.loadedHandlers.has(name);
}
/**
* Get count of loaded handlers
*/
getLoadedHandlerCount() {
return this.loadedHandlers.size;
}
/**
* Get total registered handler count
*/
getTotalHandlerCount() {
return this.lazyHandlers.size;
}
/**
* Load a specific handler on demand
*/
async loadHandler(name) {
// Return if already loaded
if (this.loadedHandlers.has(name)) {
return this.loadedHandlers.get(name);
}
const lazyHandler = this.lazyHandlers.get(name);
if (!lazyHandler) {
return null;
}
try {
// Attempt to load with retry logic
let lastError = null;
for (let attempt = 0; attempt < this.fallbackConfig.retryAttempts + 1; attempt++) {
try {
const instance = lazyHandler.constructor();
// Mark as loaded
lazyHandler.loaded = true;
lazyHandler.instance = instance;
this.loadedHandlers.set(name, instance);
return instance;
}
catch (error) {
lastError = error;
if (attempt < this.fallbackConfig.retryAttempts) {
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 100));
}
}
}
// All attempts failed
if (lastError) {
this.recordLoadingError(name, lastError);
}
return null;
}
catch (error) {
this.recordLoadingError(name, error);
return null;
}
}
/**
* Get all available tools from loaded and lazy handlers
*/
async getAllAvailableTools() {
const tools = [];
// Load all handlers to get their tools
for (const handlerName of this.lazyHandlers.keys()) {
const handler = await this.loadHandler(handlerName);
if (handler && handler.tools) {
tools.push(...handler.tools);
}
}
return tools;
}
/**
* Get available tool names without loading handlers (fast discovery)
*/
getAvailableToolNames() {
const toolNames = [];
for (const [, handlerInfo] of this.lazyHandlers) {
if (handlerInfo.config.toolNames) {
toolNames.push(...handlerInfo.config.toolNames);
}
}
return toolNames;
}
/**
* Execute a tool from a specific handler (loads handler if needed)
*/
async executeToolFromHandler(handlerName, toolName, args) {
const handler = await this.loadHandler(handlerName);
if (!handler) {
throw new Error(`Handler ${handlerName} could not be loaded`);
}
if (typeof handler.handle === 'function') {
return await handler.handle(toolName, args, new Map());
}
throw new Error(`Handler ${handlerName} does not implement handle method`);
}
/**
* Configure fallback behavior
*/
configureFallback(config) {
this.fallbackConfig = { ...this.fallbackConfig, ...config };
}
/**
* Get loading errors
*/
getLoadingErrors() {
return [...this.loadingErrors];
}
/**
* Get failure notifications
*/
getFailureNotifications() {
return this.loadingErrors
.filter(error => this.fallbackConfig.notifyOnFailure)
.map(error => ({
handlerName: error.handlerName,
message: error.error.message,
timestamp: error.timestamp
}));
}
/**
* Clear all handlers and reset registry
*/
clear() {
this.lazyHandlers.clear();
this.loadedHandlers.clear();
this.loadingErrors.length = 0;
}
/**
* Get handler categories
*/
getHandlersByCategory(category) {
const handlers = [];
for (const [name, info] of this.lazyHandlers) {
if (info.config.category === category) {
handlers.push(name);
}
}
return handlers;
}
/**
* Load handlers by priority
*/
async loadHandlersByPriority(priority) {
const loadedHandlers = [];
for (const [name, info] of this.lazyHandlers) {
if (info.config.priority === priority) {
const handler = await this.loadHandler(name);
if (handler) {
loadedHandlers.push(name);
}
}
}
return loadedHandlers;
}
/**
* Get performance metrics
*/
getPerformanceMetrics() {
const totalRegistered = this.lazyHandlers.size;
const totalLoaded = this.loadedHandlers.size;
const totalErrors = this.loadingErrors.length;
return {
totalRegistered,
totalLoaded,
loadingEfficiency: totalRegistered > 0 ? (totalLoaded / totalRegistered) : 0,
failureRate: totalRegistered > 0 ? (totalErrors / totalRegistered) : 0
};
}
/**
* Record loading error
*/
recordLoadingError(handlerName, error) {
const existingError = this.loadingErrors.find(e => e.handlerName === handlerName);
if (existingError) {
existingError.retryCount++;
}
else {
this.loadingErrors.push({
handlerName,
error,
timestamp: new Date(),
retryCount: 0
});
}
}
}
/**
* Global lazy handler registry instance
*/
export const globalLazyHandlerRegistry = new LazyHandlerRegistry();
//# sourceMappingURL=lazy-handler-registry.js.map