UNPKG

claude-flow

Version:

Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)

951 lines (832 loc) 27.7 kB
/** * MCP Tool Wrapper for Hive Mind System * Wraps all 87 MCP tools for coordinated swarm usage */ import { spawn } from 'child_process'; /** * MCP Tool categories and their methods */ const MCP_TOOLS = { swarm: [ 'swarm_init', 'agent_spawn', 'task_orchestrate', 'swarm_status', 'agent_list', 'agent_metrics', 'swarm_monitor', 'topology_optimize', 'load_balance', 'coordination_sync', 'swarm_scale', 'swarm_destroy' ], neural: [ 'neural_status', 'neural_train', 'neural_patterns', 'neural_predict', 'model_load', 'model_save', 'wasm_optimize', 'inference_run', 'pattern_recognize', 'cognitive_analyze', 'learning_adapt', 'neural_compress', 'ensemble_create', 'transfer_learn', 'neural_explain' ], memory: [ 'memory_usage', 'memory_search', 'memory_persist', 'memory_namespace', 'memory_backup', 'memory_restore', 'memory_compress', 'memory_sync', 'cache_manage', 'state_snapshot', 'context_restore', 'memory_analytics' ], performance: [ 'performance_report', 'bottleneck_analyze', 'token_usage', 'benchmark_run', 'metrics_collect', 'trend_analysis', 'cost_analysis', 'quality_assess', 'error_analysis', 'usage_stats', 'health_check' ], github: [ 'github_repo_analyze', 'github_pr_manage', 'github_issue_track', 'github_release_coord', 'github_workflow_auto', 'github_code_review', 'github_sync_coord', 'github_metrics' ], workflow: [ 'workflow_create', 'workflow_execute', 'workflow_export', 'automation_setup', 'pipeline_create', 'scheduler_manage', 'trigger_setup', 'workflow_template', 'batch_process', 'parallel_execute' ], daa: [ 'daa_agent_create', 'daa_capability_match', 'daa_resource_alloc', 'daa_lifecycle_manage', 'daa_communication', 'daa_consensus', 'daa_fault_tolerance', 'daa_optimization' ], system: [ 'terminal_execute', 'config_manage', 'features_detect', 'security_scan', 'backup_create', 'restore_system', 'log_analysis', 'diagnostic_run' ], sparc: ['sparc_mode'], task: ['task_status', 'task_results'] }; /** * MCPToolWrapper class for unified MCP tool access */ export class MCPToolWrapper { constructor(config = {}) { this.config = { parallel: true, timeout: 60000, retryCount: 3, ...config }; this.toolStats = new Map(); this.parallelQueue = []; this.executing = false; /** @type {import('better-sqlite3').Database | null} */ this.memoryDb = null; // Initialize real memory storage this.initializeMemoryStorage(); } /** * Initialize real memory storage using SQLite */ async initializeMemoryStorage() { try { const Database = (await import('better-sqlite3')).default; const path = await import('path'); const fs = await import('fs'); // Create .hive-mind directory if it doesn't exist const hiveMindDir = path.join(process.cwd(), '.hive-mind'); if (!fs.existsSync(hiveMindDir)) { fs.mkdirSync(hiveMindDir, { recursive: true }); } // Initialize SQLite database const dbPath = path.join(hiveMindDir, 'memory.db'); this.memoryDb = new Database(dbPath); // Create memories table this.memoryDb.exec(` CREATE TABLE IF NOT EXISTS memories ( id INTEGER PRIMARY KEY AUTOINCREMENT, namespace TEXT NOT NULL, key TEXT NOT NULL, value TEXT NOT NULL, type TEXT DEFAULT 'knowledge', timestamp INTEGER NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE(namespace, key) ) `); // Real memory storage initialized with SQLite } catch (error) { console.warn('Failed to initialize SQLite storage, falling back to in-memory:', error.message); this.memoryDb = null; this.memoryStore = new Map(); // Fallback to in-memory storage } } /** * Execute MCP tool with automatic retry and error handling */ async executeTool(toolName, params = {}) { const startTime = Date.now(); let lastError = null; for (let attempt = 1; attempt <= this.config.retryCount; attempt++) { try { const result = await this._executeToolInternal(toolName, params); // Track statistics this._trackToolUsage(toolName, Date.now() - startTime, true); return result; } catch (error) { lastError = error; console.error(`Attempt ${attempt} failed for ${toolName}:`, error.message); if (attempt < this.config.retryCount) { // Exponential backoff await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000)); } } } // Track failure this._trackToolUsage(toolName, Date.now() - startTime, false); throw new Error(`Failed to execute ${toolName} after ${this.config.retryCount} attempts: ${lastError.message}`); } /** * Execute multiple tools in parallel with optimized batching */ async executeParallel(toolCalls) { if (!this.config.parallel) { // Execute sequentially if parallel is disabled const results = []; for (const call of toolCalls) { results.push(await this.executeTool(call.tool, call.params)); } return results; } if (!Array.isArray(toolCalls) || toolCalls.length === 0) { return []; } const startTime = Date.now(); // Intelligent concurrency limit based on tool types const concurrencyLimit = this._calculateOptimalConcurrency(toolCalls); // Group tools by priority and dependency const toolGroups = this._groupToolsByPriority(toolCalls); const allResults = []; try { // Execute high-priority tools first for (const group of toolGroups) { const groupResults = []; for (let i = 0; i < group.length; i += concurrencyLimit) { const batch = group.slice(i, i + concurrencyLimit); // Execute batch with timeout and retry logic const batchPromises = batch.map(call => this._executeWithTimeout(call, this.config.timeout) ); const batchResults = await Promise.allSettled(batchPromises); // Process results and handle failures for (let j = 0; j < batchResults.length; j++) { const result = batchResults[j]; if (result.status === 'fulfilled') { groupResults.push(result.value); } else { console.warn(`Tool execution failed: ${batch[j].tool}`, result.reason); groupResults.push({ error: result.reason.message, tool: batch[j].tool }); } } } allResults.push(...groupResults); } // Track performance metrics const executionTime = Date.now() - startTime; this._trackBatchPerformance(toolCalls.length, executionTime, concurrencyLimit); return allResults; } catch (error) { console.error('Parallel execution failed:', error); throw error; } } /** * Calculate optimal concurrency based on tool types */ _calculateOptimalConcurrency(toolCalls) { const toolTypes = toolCalls.map(call => this._getToolCategory(call.tool)); const uniqueTypes = new Set(toolTypes); // Heavy operations (neural, github) need lower concurrency const heavyTypes = ['neural', 'github', 'workflow']; const hasHeavyOps = toolTypes.some(type => heavyTypes.includes(type)); if (hasHeavyOps) { return Math.min(3, Math.max(1, Math.floor(toolCalls.length / 2))); } // Light operations (memory, performance) can handle higher concurrency return Math.min(8, Math.max(2, Math.floor(toolCalls.length / 1.5))); } /** * Group tools by execution priority */ _groupToolsByPriority(toolCalls) { const priorities = { critical: [], // swarm_init, swarm_destroy high: [], // agent_spawn, memory operations medium: [], // task operations, monitoring low: [] // analytics, reporting }; toolCalls.forEach(call => { const category = this._getToolCategory(call.tool); const tool = call.tool; if (['swarm_init', 'swarm_destroy', 'memory_backup'].includes(tool)) { priorities.critical.push(call); } else if (['agent_spawn', 'memory_usage', 'neural_train'].includes(tool)) { priorities.high.push(call); } else if (category === 'performance' || tool.includes('report')) { priorities.low.push(call); } else { priorities.medium.push(call); } }); // Return groups in priority order, filtering empty groups return [priorities.critical, priorities.high, priorities.medium, priorities.low] .filter(group => group.length > 0); } /** * Execute tool with timeout wrapper */ async _executeWithTimeout(call, timeout) { return new Promise((resolve, reject) => { const timer = setTimeout(() => { reject(new Error(`Tool ${call.tool} timed out after ${timeout}ms`)); }, timeout); this.executeTool(call.tool, call.params) .then(result => { clearTimeout(timer); resolve(result); }) .catch(error => { clearTimeout(timer); reject(error); }); }); } /** * Track batch execution performance */ _trackBatchPerformance(toolCount, executionTime, concurrency) { if (!this.batchStats) { this.batchStats = { totalBatches: 0, totalTools: 0, totalTime: 0, avgConcurrency: 0, avgToolsPerBatch: 0, avgTimePerTool: 0 }; } this.batchStats.totalBatches++; this.batchStats.totalTools += toolCount; this.batchStats.totalTime += executionTime; this.batchStats.avgConcurrency = (this.batchStats.avgConcurrency * (this.batchStats.totalBatches - 1) + concurrency) / this.batchStats.totalBatches; this.batchStats.avgToolsPerBatch = this.batchStats.totalTools / this.batchStats.totalBatches; this.batchStats.avgTimePerTool = this.batchStats.totalTime / this.batchStats.totalTools; } /** * Internal tool execution */ async _executeToolInternal(toolName, params) { const toolCategory = this._getToolCategory(toolName); if (!toolCategory) { throw new Error(`Unknown MCP tool: ${toolName}`); } // Handle memory operations with real storage if (toolName === 'memory_usage') { if (params.action === 'store') { return await this.storeMemory(params.namespace, params.key, params.value, params.type); } else if (params.action === 'retrieve') { return await this.retrieveMemory(params.namespace, params.key); } } else if (toolName === 'memory_search') { return await this.searchMemory(params.namespace, params.pattern); } // For other tools, use mock responses console.log(`Executing MCP tool: mcp__claude-flow__${toolName} with params:`, params); // Simulate async execution for non-memory tools await new Promise(resolve => setTimeout(resolve, Math.random() * 500)); // Mock response based on tool type const mockResponse = this._getMockResponse(toolName, params); return mockResponse; } /** * Get tool category */ _getToolCategory(toolName) { for (const [category, tools] of Object.entries(MCP_TOOLS)) { if (tools.includes(toolName)) { return category; } } return null; } /** * Get mock response for demonstration */ _getMockResponse(toolName, params) { // Mock responses for different tool types const mockResponses = { swarm_init: { swarmId: `swarm-${Date.now()}`, topology: params.topology || 'hierarchical', status: 'initialized' }, agent_spawn: { agentId: `agent-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`, type: params.type, status: 'active' }, task_orchestrate: { taskId: `task-${Date.now()}`, status: 'orchestrated', strategy: params.strategy || 'parallel' }, memory_usage: { action: params.action, result: params.action === 'store' ? 'stored' : 'retrieved', data: params.value || null }, neural_status: { status: 'ready', models: 27, accuracy: 0.848 } }; return mockResponses[toolName] || { status: 'success', toolName }; } /** * Track tool usage statistics */ _trackToolUsage(toolName, duration, success) { if (!this.toolStats.has(toolName)) { this.toolStats.set(toolName, { calls: 0, successes: 0, failures: 0, totalDuration: 0, avgDuration: 0 }); } const stats = this.toolStats.get(toolName); stats.calls++; if (success) { stats.successes++; } else { stats.failures++; } stats.totalDuration += duration; stats.avgDuration = stats.totalDuration / stats.calls; } /** * Get comprehensive tool statistics */ getStatistics() { const toolStats = {}; this.toolStats.forEach((value, key) => { toolStats[key] = { ...value }; }); return { tools: toolStats, batch: this.batchStats || { totalBatches: 0, totalTools: 0, totalTime: 0, avgConcurrency: 0, avgToolsPerBatch: 0, avgTimePerTool: 0 }, spawn: this.spawnStats || { totalSpawns: 0, totalAgents: 0, totalTime: 0, avgTimePerAgent: 0, bestTime: 0, worstTime: 0 }, performance: { totalCalls: Array.from(this.toolStats.values()).reduce((sum, stat) => sum + stat.calls, 0), successRate: this._calculateOverallSuccessRate(), avgLatency: this._calculateAvgLatency(), throughput: this._calculateThroughput() } }; } /** * Calculate overall success rate */ _calculateOverallSuccessRate() { const total = Array.from(this.toolStats.values()) .reduce((sum, stat) => sum + stat.calls, 0); const successes = Array.from(this.toolStats.values()) .reduce((sum, stat) => sum + stat.successes, 0); return total > 0 ? (successes / total * 100).toFixed(2) : 100; } /** * Calculate average latency */ _calculateAvgLatency() { const stats = Array.from(this.toolStats.values()).filter(stat => stat.calls > 0); if (stats.length === 0) return 0; const totalLatency = stats.reduce((sum, stat) => sum + stat.avgDuration, 0); return (totalLatency / stats.length).toFixed(2); } /** * Calculate throughput (operations per second) */ _calculateThroughput() { const batchStats = this.batchStats; if (!batchStats || batchStats.totalTime === 0) return 0; return (batchStats.totalTools / (batchStats.totalTime / 1000)).toFixed(2); } /** * Create batch of tool calls for parallel execution */ createBatch(calls) { return calls.map(call => ({ tool: call.tool, params: call.params || {} })); } /** * Execute swarm initialization sequence with optimization */ async initializeSwarm(config) { const swarmId = config.swarmId || `swarm-${Date.now()}`; const startTime = Date.now(); try { // Phase 1: Critical initialization (sequential) const criticalOps = [ { tool: 'swarm_init', params: { topology: config.topology || 'hierarchical', maxAgents: config.maxAgents || 8, strategy: 'auto', swarmId }} ]; const [swarmInitResult] = await this.executeParallel(criticalOps); // Phase 2: Supporting services (parallel) const supportingOps = [ { tool: 'memory_namespace', params: { action: 'create', namespace: swarmId, maxSize: config.memorySize || 100 }}, { tool: 'neural_status', params: {} }, { tool: 'performance_report', params: { format: 'summary' } }, { tool: 'features_detect', params: { component: 'swarm' } } ]; const supportingResults = await this.executeParallel(supportingOps); // Store initialization metadata const initTime = Date.now() - startTime; await this.storeMemory(swarmId, 'init_performance', { initTime, topology: config.topology, maxAgents: config.maxAgents, timestamp: Date.now() }, 'metrics'); return [swarmInitResult, ...supportingResults]; } catch (error) { console.error('Swarm initialization failed:', error); throw error; } } /** * Spawn multiple agents in parallel with optimization */ async spawnAgents(types, swarmId) { if (!Array.isArray(types) || types.length === 0) { return []; } const startTime = Date.now(); // Optimize agent spawning by grouping similar types const groupedTypes = this._groupAgentTypes(types); const allResults = []; try { // Spawn each group in parallel for (const group of groupedTypes) { const batch = group.map(type => ({ tool: 'agent_spawn', params: { type, swarmId, timestamp: Date.now(), batchId: `batch-${Date.now()}-${Math.random().toString(36).substr(2, 9)}` } })); const groupResults = await this.executeParallel(batch); allResults.push(...groupResults); } // Track spawn performance const spawnTime = Date.now() - startTime; this._trackSpawnPerformance(types.length, spawnTime); return allResults; } catch (error) { console.error('Agent spawning failed:', error); throw error; } } /** * Group agent types for optimized spawning */ _groupAgentTypes(types) { // Group complementary agent types that work well together const groups = { development: ['coder', 'architect', 'reviewer'], analysis: ['researcher', 'analyst', 'optimizer'], quality: ['tester', 'documenter'], coordination: ['coordinator'] }; const result = []; const remaining = [...types]; // Create groups of complementary agents Object.values(groups).forEach(groupTypes => { const groupAgents = remaining.filter(type => groupTypes.includes(type)); if (groupAgents.length > 0) { result.push(groupAgents); groupAgents.forEach(type => { const index = remaining.indexOf(type); if (index > -1) remaining.splice(index, 1); }); } }); // Add remaining agents as individual groups remaining.forEach(type => result.push([type])); return result; } /** * Track agent spawn performance */ _trackSpawnPerformance(agentCount, spawnTime) { if (!this.spawnStats) { this.spawnStats = { totalSpawns: 0, totalAgents: 0, totalTime: 0, avgTimePerAgent: 0, bestTime: Infinity, worstTime: 0 }; } this.spawnStats.totalSpawns++; this.spawnStats.totalAgents += agentCount; this.spawnStats.totalTime += spawnTime; this.spawnStats.avgTimePerAgent = this.spawnStats.totalTime / this.spawnStats.totalAgents; this.spawnStats.bestTime = Math.min(this.spawnStats.bestTime, spawnTime); this.spawnStats.worstTime = Math.max(this.spawnStats.worstTime, spawnTime); } /** * Store data in collective memory (REAL IMPLEMENTATION) */ async storeMemory(swarmId, key, value, type = 'knowledge') { try { if (!this.memoryDb) { await this.initializeMemoryStorage(); } const timestamp = Date.now(); const valueStr = typeof value === 'string' ? value : JSON.stringify(value); if (this.memoryDb) { // SQLite storage const stmt = this.memoryDb.prepare(` INSERT OR REPLACE INTO memories (namespace, key, value, type, timestamp) VALUES (?, ?, ?, ?, ?) `); const result = stmt.run(swarmId, key, valueStr, type, timestamp); return { success: true, action: 'store', namespace: swarmId, key, type, timestamp, id: result.lastInsertRowid }; } else { // Fallback in-memory storage const memoryKey = `${swarmId}:${key}`; this.memoryStore.set(memoryKey, { namespace: swarmId, key, value: valueStr, type, timestamp }); return { success: true, action: 'store', namespace: swarmId, key, type, timestamp }; } } catch (error) { console.error('Error storing memory:', error); throw error; } } /** * Retrieve data from collective memory (REAL IMPLEMENTATION) */ async retrieveMemory(swarmId, key) { try { if (!this.memoryDb) { await this.initializeMemoryStorage(); } if (this.memoryDb) { // SQLite retrieval const stmt = this.memoryDb.prepare(` SELECT * FROM memories WHERE namespace = ? AND key = ? `); const row = stmt.get(swarmId, key); if (row) { try { return { ...row, value: JSON.parse(row.value) }; } catch { return row; } } } else { // Fallback in-memory retrieval const memoryKey = `${swarmId}:${key}`; const memory = this.memoryStore.get(memoryKey); if (memory) { try { return { ...memory, value: JSON.parse(memory.value) }; } catch { return memory; } } } return null; } catch (error) { console.error('Error retrieving memory:', error); throw error; } } /** * Search collective memory (REAL IMPLEMENTATION) */ async searchMemory(swarmId, pattern) { try { if (!this.memoryDb) { await this.initializeMemoryStorage(); } let results = []; if (this.memoryDb) { // SQLite search let query, params; if (pattern && pattern.trim()) { // Search with pattern query = ` SELECT * FROM memories WHERE namespace = ? AND (key LIKE ? OR value LIKE ? OR type LIKE ?) ORDER BY timestamp DESC LIMIT 50 `; const searchPattern = `%${pattern}%`; params = [swarmId, searchPattern, searchPattern, searchPattern]; } else { // Get all memories for namespace query = ` SELECT * FROM memories WHERE namespace = ? ORDER BY timestamp DESC LIMIT 50 `; params = [swarmId]; } const stmt = this.memoryDb.prepare(query); results = stmt.all(...params); // Parse JSON values where possible results = results.map(row => { try { return { ...row, value: JSON.parse(row.value) }; } catch { return row; } }); } else { // Fallback in-memory search for (const [memKey, memory] of this.memoryStore) { if (memory.namespace === swarmId) { if (!pattern || memory.key.includes(pattern) || memory.value.includes(pattern) || memory.type.includes(pattern)) { try { results.push({ ...memory, value: JSON.parse(memory.value) }); } catch { results.push(memory); } } } } // Sort by timestamp descending results.sort((a, b) => b.timestamp - a.timestamp); results = results.slice(0, 50); } return { success: true, namespace: swarmId, pattern: pattern || '', total: results.length, results: results }; } catch (error) { console.error('Error searching memory:', error); throw error; } } /** * Orchestrate task with monitoring and optimization */ async orchestrateTask(task, strategy = 'parallel', metadata = {}) { const taskId = metadata.taskId || `task-${Date.now()}`; const complexity = metadata.complexity || 'medium'; // Adjust monitoring frequency based on task complexity const monitoringInterval = { low: 10000, medium: 5000, high: 2000 }[complexity] || 5000; const batch = [ { tool: 'task_orchestrate', params: { task, strategy, taskId, priority: metadata.priority || 5, estimatedDuration: metadata.estimatedDuration || 30000 }}, { tool: 'swarm_monitor', params: { interval: monitoringInterval, taskId, metrics: ['performance', 'progress', 'bottlenecks'] }}, // Add performance tracking for high-priority tasks ...(metadata.priority > 7 ? [{ tool: 'performance_report', params: { format: 'detailed', taskId } }] : []) ]; return await this.executeParallel(batch); } /** * Analyze performance bottlenecks */ async analyzePerformance(swarmId) { const batch = [ { tool: 'bottleneck_analyze', params: { component: swarmId }}, { tool: 'performance_report', params: { format: 'detailed' }}, { tool: 'token_usage', params: { operation: swarmId }} ]; return await this.executeParallel(batch); } /** * GitHub integration for code operations */ async githubOperations(repo, operation, params = {}) { const githubTools = { analyze: 'github_repo_analyze', pr: 'github_pr_manage', issue: 'github_issue_track', review: 'github_code_review' }; const tool = githubTools[operation]; if (!tool) { throw new Error(`Unknown GitHub operation: ${operation}`); } return await this.executeTool(tool, { repo, ...params }); } /** * Neural network operations */ async neuralOperation(operation, params = {}) { const neuralTools = { train: 'neural_train', predict: 'neural_predict', analyze: 'neural_patterns', optimize: 'wasm_optimize' }; const tool = neuralTools[operation]; if (!tool) { throw new Error(`Unknown neural operation: ${operation}`); } return await this.executeTool(tool, params); } /** * Clean up and destroy swarm */ async destroySwarm(swarmId) { const batch = [ { tool: 'swarm_destroy', params: { swarmId }}, { tool: 'memory_namespace', params: { action: 'delete', namespace: swarmId }}, { tool: 'cache_manage', params: { action: 'clear', key: `swarm-${swarmId}` }} ]; return await this.executeParallel(batch); } } // Export tool categories for reference export { MCP_TOOLS };