UNPKG

@mrtkrcm/acp-claude-code

Version:

ACP (Agent Client Protocol) bridge for Claude Code

263 lines 10.5 kB
/** * Enhanced Agent Integration Module * * This module provides integration points for the new MCP optimization features * without modifying the existing agent.ts file directly. */ import { ClaudeACPAgent } from './agent.js'; import { globalMcpManager } from './mcp-connection-manager.js'; import { globalToolBatcher } from './mcp-tool-batcher.js'; import { ContextOptimizer } from './context-optimizer.js'; import { ContextMonitor } from './context-monitor.js'; import { createLogger } from './logger.js'; /** * Enhanced Claude ACP Agent with MCP optimizations */ export class EnhancedClaudeACPAgent extends ClaudeACPAgent { contextOptimizer; logger; options; constructor(client, options = {}) { super(client); this.logger = createLogger('Enhanced-Agent'); this.options = { enableMcpOptimization: true, enableToolBatching: true, enableContextOptimization: true, mcpConnectionPoolSize: 3, toolBatchingStrategy: 'dependency-aware', contextOptimizationStrategy: 'balanced', ...options }; // Initialize context optimizer with the existing context monitor this.contextOptimizer = new ContextOptimizer(new ContextMonitor()); this.initializeEnhancements(); } async initializeEnhancements() { this.logger.info('Initializing MCP enhancements', this.options); if (this.options.enableMcpOptimization) { await this.initializeMcpOptimization(); } if (this.options.enableToolBatching) { this.initializeToolBatching(); } if (this.options.enableContextOptimization) { this.initializeContextOptimization(); } } async initializeMcpOptimization() { // Register default MCP servers that would typically be configured // These would come from Claude Code SDK configuration in a real implementation const defaultServers = [ { name: 'filesystem', type: 'stdio', config: { command: 'mcp-filesystem', args: [] }, maxConnections: this.options.mcpConnectionPoolSize, }, { name: 'web-search', type: 'stdio', config: { command: 'mcp-web-search', args: [] }, maxConnections: this.options.mcpConnectionPoolSize, }, { name: 'terminal', type: 'stdio', config: { command: 'mcp-terminal', args: [] }, maxConnections: this.options.mcpConnectionPoolSize, } ]; for (const server of defaultServers) { try { await globalMcpManager.registerServer(server); this.logger.info(`Registered MCP server: ${server.name}`); } catch (error) { this.logger.warn(`Failed to register MCP server ${server.name}: ${error}`); } } } initializeToolBatching() { this.logger.info(`Tool batching enabled with ${this.options.toolBatchingStrategy} strategy`); // Tool batching integration happens at the message processing level } initializeContextOptimization() { this.logger.info(`Context optimization enabled with ${this.options.contextOptimizationStrategy} strategy`); // Context optimization integration happens at the prompt processing level } /** * Enhanced prompt processing with context optimization */ async processPromptWithOptimization(sessionId, promptText) { if (!this.options.enableContextOptimization) { return { optimizedPrompt: promptText, optimizationStats: null }; } // Add current prompt as context chunk this.contextOptimizer.addContextChunk(sessionId, { id: `prompt_${Date.now()}`, content: promptText, type: 'user', timestamp: Date.now(), importance: 1.0, // User prompts are always important tokenCount: Math.ceil(promptText.length / 4), }); // Analyze context health const healthAnalysis = this.contextOptimizer.analyzeContextHealth(sessionId); if (healthAnalysis.status !== 'healthy') { this.logger.info(`Context health: ${healthAnalysis.status}`, { sessionId, recommendations: healthAnalysis.recommendations, stats: healthAnalysis.stats }); // Optimize context if needed const optimization = this.contextOptimizer.optimizeContext(sessionId, this.options.contextOptimizationStrategy); this.logger.info(`Context optimized for session ${sessionId}`, optimization.stats); return { optimizedPrompt: optimization.optimizedContext, optimizationStats: optimization.stats }; } return { optimizedPrompt: promptText, optimizationStats: null }; } /** * Enhanced tool call processing with batching */ async processToolCallsWithBatching(sessionId, toolCalls) { if (!this.options.enableToolBatching || toolCalls.length <= 1) { // Fall back to individual execution for single tools return this.processToolCallsIndividually(toolCalls); } const batchId = `batch_${sessionId}_${Date.now()}`; // Convert to batchable format and analyze dependencies const batchableCalls = toolCalls.map((call, index) => ({ id: call.id, serverName: this.mapToolToMcpServer(call.name), toolName: call.name, args: call.input, priority: index, // Simple priority based on order dependencies: this.analyzeDependencies(call, toolCalls), timeout: 30000, })); // Add to batch globalToolBatcher.addToBatch(batchId, batchableCalls); // Execute batch with configured strategy const results = await globalToolBatcher.executeBatch(batchId, { strategy: this.options.toolBatchingStrategy, maxConcurrency: 5, batchTimeout: 120000, // 2 minutes }); this.logger.info(`Batch execution completed`, { batchId, totalTools: toolCalls.length, successCount: results.filter(r => r.success).length, strategy: this.options.toolBatchingStrategy }); return results; } async processToolCallsIndividually(toolCalls) { const results = []; for (const call of toolCalls) { try { const serverName = this.mapToolToMcpServer(call.name); const result = await globalMcpManager.executeToolWithPooling(serverName, call.name, call.input); results.push({ id: call.id, success: true, result, }); } catch (error) { results.push({ id: call.id, success: false, error: error instanceof Error ? error.message : String(error), }); } } return results; } mapToolToMcpServer(toolName) { // Map Claude Code tools to MCP servers const toolServerMap = { 'Bash': 'terminal', 'BashOutput': 'terminal', 'FileRead': 'filesystem', 'FileWrite': 'filesystem', 'FileEdit': 'filesystem', 'Glob': 'filesystem', 'Grep': 'filesystem', 'WebFetch': 'web-search', 'WebSearch': 'web-search', 'ListMcpResources': 'filesystem', 'ReadMcpResource': 'filesystem', 'Mcp': 'filesystem', // Default fallback }; return toolServerMap[toolName] || 'filesystem'; } analyzeDependencies(currentTool, allTools) { const dependencies = []; const currentIndex = allTools.findIndex(t => t.id === currentTool.id); // Simple dependency analysis based on tool types for (let i = 0; i < currentIndex; i++) { const previousTool = allTools[i]; // File operations depend on previous file operations on the same file if (this.isFileOperation(currentTool.name) && this.isFileOperation(previousTool.name)) { const currentFile = this.extractFilePath(currentTool.input); const previousFile = this.extractFilePath(previousTool.input); if (currentFile && previousFile && currentFile === previousFile) { dependencies.push(previousTool.id); } } // Web operations can depend on previous Bash operations (e.g., setup) if (currentTool.name === 'WebSearch' && previousTool.name === 'Bash') { dependencies.push(previousTool.id); } } return dependencies; } isFileOperation(toolName) { return ['FileRead', 'FileWrite', 'FileEdit', 'Glob', 'Grep'].includes(toolName); } extractFilePath(input) { return (input.file_path || input.path || input.file); } /** * Get comprehensive health and performance metrics */ getEnhancedHealthStatus() { return { baseHealth: this.getHealthStatus(), mcpStats: globalMcpManager.getStats(), batchStats: globalToolBatcher.getBatchStats(), contextStats: this.contextOptimizer.getOptimizationStats(), }; } /** * Cleanup enhanced components */ async destroy() { this.logger.info('Destroying enhanced agent components'); // Clear tool batches globalToolBatcher.clearPendingBatches(); // Clear context optimizations // (Context optimizer cleanup would be implemented here) // Call parent destroy if it exists if (super.destroy && typeof super.destroy === 'function') { await super.destroy(); } } } /** * Factory function to create enhanced agent */ export function createEnhancedAgent(client, options) { return new EnhancedClaudeACPAgent(client, options); } //# sourceMappingURL=enhanced-agent-integration.js.map