UNPKG

claude-flow

Version:

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

521 lines (444 loc) 15.2 kB
/** * HiveMind Core Class * * Main orchestrator for the collective intelligence swarm system. * Manages agents, tasks, memory, and coordination. */ import { EventEmitter } from 'events'; import { v4 as uuidv4 } from 'uuid'; import { Queen } from './Queen.js'; import { Agent } from './Agent.js'; import { Memory } from './Memory.js'; import { Communication } from './Communication.js'; import { DatabaseManager } from './DatabaseManager.js'; import { SwarmOrchestrator } from '../integration/SwarmOrchestrator.js'; import { ConsensusEngine } from '../integration/ConsensusEngine.js'; import { HiveMindConfig, SwarmTopology, AgentType, Task, TaskPriority, TaskStrategy, SwarmStatus, AgentSpawnOptions, TaskSubmitOptions } from '../types.js'; export class HiveMind extends EventEmitter { private id: string; private config: HiveMindConfig; private queen: Queen; private agents: Map<string, Agent>; private memory: Memory; private communication: Communication; private orchestrator: SwarmOrchestrator; private consensus: ConsensusEngine; private db: DatabaseManager; private started: boolean = false; private startTime: number; constructor(config: HiveMindConfig) { super(); this.config = config; this.id = uuidv4(); this.agents = new Map(); this.startTime = Date.now(); } /** * Initialize the Hive Mind and all subsystems */ async initialize(): Promise<string> { try { // Initialize database this.db = await DatabaseManager.getInstance(); // Create swarm in database await this.db.createSwarm({ id: this.id, name: this.config.name, topology: this.config.topology, queenMode: this.config.queenMode, maxAgents: this.config.maxAgents, consensusThreshold: this.config.consensusThreshold, memoryTTL: this.config.memoryTTL, config: JSON.stringify(this.config) }); // Initialize Queen this.queen = new Queen({ swarmId: this.id, mode: this.config.queenMode, topology: this.config.topology }); // Initialize subsystems this.memory = new Memory(this.id); this.communication = new Communication(this.id); this.orchestrator = new SwarmOrchestrator(this); this.consensus = new ConsensusEngine(this.config.consensusThreshold); // Initialize subsystems await Promise.all([ this.queen.initialize(), this.memory.initialize(), this.communication.initialize(), this.orchestrator.initialize() ]); // Set as active swarm await this.db.setActiveSwarm(this.id); // Auto-spawn agents if configured if (this.config.autoSpawn) { await this.autoSpawnAgents(); } this.started = true; this.emit('initialized', { swarmId: this.id }); return this.id; } catch (error) { this.emit('error', error); throw error; } } /** * Load an existing Hive Mind from the database */ static async load(swarmId: string): Promise<HiveMind> { const db = await DatabaseManager.getInstance(); const swarmData = await db.getSwarm(swarmId); if (!swarmData) { throw new Error(`Swarm ${swarmId} not found`); } const config = JSON.parse(swarmData.config); const hiveMind = new HiveMind(config); hiveMind.id = swarmId; await hiveMind.initialize(); // Load existing agents const agents = await db.getAgents(swarmId); for (const agentData of agents) { const agent = new Agent({ id: agentData.id, name: agentData.name, type: agentData.type, swarmId: swarmId, capabilities: JSON.parse(agentData.capabilities) }); await agent.initialize(); hiveMind.agents.set(agent.id, agent); } return hiveMind; } /** * Auto-spawn initial agents based on topology */ async autoSpawnAgents(): Promise<Agent[]> { const topologyConfigs = { hierarchical: [ { type: 'coordinator', count: 1 }, { type: 'researcher', count: 2 }, { type: 'coder', count: 2 }, { type: 'analyst', count: 1 }, { type: 'tester', count: 1 } ], mesh: [ { type: 'coordinator', count: 2 }, { type: 'researcher', count: 2 }, { type: 'coder', count: 2 }, { type: 'specialist', count: 2 } ], ring: [ { type: 'coordinator', count: 1 }, { type: 'coder', count: 3 }, { type: 'reviewer', count: 2 } ], star: [ { type: 'coordinator', count: 1 }, { type: 'specialist', count: 4 } ] }; const config = topologyConfigs[this.config.topology]; const spawnedAgents: Agent[] = []; for (const agentConfig of config) { for (let i = 0; i < agentConfig.count; i++) { const agent = await this.spawnAgent({ type: agentConfig.type as AgentType, name: `${agentConfig.type}-${i + 1}` }); spawnedAgents.push(agent); } } return spawnedAgents; } /** * Spawn a new agent into the swarm */ async spawnAgent(options: AgentSpawnOptions): Promise<Agent> { if (this.agents.size >= this.config.maxAgents) { throw new Error('Maximum agent limit reached'); } const agent = new Agent({ name: options.name || `${options.type}-${Date.now()}`, type: options.type, swarmId: this.id, capabilities: options.capabilities || this.getDefaultCapabilities(options.type) }); await agent.initialize(); // Register with Queen await this.queen.registerAgent(agent); // Store in database await this.db.createAgent({ id: agent.id, swarmId: this.id, name: agent.name, type: agent.type, capabilities: JSON.stringify(agent.capabilities), status: 'idle' }); // Add to local map this.agents.set(agent.id, agent); // Setup communication channels this.communication.addAgent(agent); // Auto-assign to pending tasks if configured if (options.autoAssign) { await this.assignPendingTasksToAgent(agent); } this.emit('agentSpawned', { agent }); return agent; } /** * Submit a task to the Hive Mind */ async submitTask(options: TaskSubmitOptions): Promise<Task> { const task: Task = { id: uuidv4(), swarmId: this.id, description: options.description, priority: options.priority, strategy: options.strategy, status: 'pending', progress: 0, dependencies: options.dependencies || [], assignedAgents: [], requireConsensus: options.requireConsensus || false, maxAgents: options.maxAgents || 3, requiredCapabilities: options.requiredCapabilities || [], createdAt: new Date(), metadata: options.metadata || {} }; // Store in database await this.db.createTask({ ...task, dependencies: JSON.stringify(task.dependencies), assignedAgents: JSON.stringify(task.assignedAgents), requiredCapabilities: JSON.stringify(task.requiredCapabilities), metadata: JSON.stringify(task.metadata) }); // Submit to orchestrator await this.orchestrator.submitTask(task); // Notify Queen await this.queen.onTaskSubmitted(task); this.emit('taskSubmitted', { task }); return task; } /** * Get full status of the Hive Mind */ async getFullStatus(): Promise<SwarmStatus> { const agents = Array.from(this.agents.values()); const tasks = await this.db.getTasks(this.id); const memoryStats = await this.memory.getStats(); const communicationStats = await this.communication.getStats(); // Calculate agent statistics const agentsByType = agents.reduce((acc, agent) => { acc[agent.type] = (acc[agent.type] || 0) + 1; return acc; }, {} as Record<string, number>); // Calculate task statistics const taskStats = { total: tasks.length, pending: tasks.filter(t => t.status === 'pending').length, inProgress: tasks.filter(t => t.status === 'in_progress').length, completed: tasks.filter(t => t.status === 'completed').length, failed: tasks.filter(t => t.status === 'failed').length }; // Calculate performance metrics const performance = await this.calculatePerformanceMetrics(); // Determine health status const health = this.determineHealth(agents, tasks, performance); // Get any warnings const warnings = this.getSystemWarnings(agents, tasks, performance); return { swarmId: this.id, name: this.config.name, topology: this.config.topology, queenMode: this.config.queenMode, health, uptime: Date.now() - this.startTime, agents: agents.map(a => ({ id: a.id, name: a.name, type: a.type, status: a.status, currentTask: a.currentTask, messageCount: a.messageCount, createdAt: a.createdAt.getTime() })), agentsByType, tasks: tasks.map(t => ({ id: t.id, description: t.description, status: t.status, priority: t.priority, progress: t.progress, assignedAgent: t.assigned_agents ? JSON.parse(t.assigned_agents)[0] : null })), taskStats, memoryStats, communicationStats, performance, warnings }; } /** * Get basic statistics */ async getStats() { const agents = Array.from(this.agents.values()); const tasks = await this.db.getTasks(this.id); return { totalAgents: agents.length, activeAgents: agents.filter(a => a.status === 'busy').length, pendingTasks: tasks.filter(t => t.status === 'pending').length, availableCapacity: Math.round((1 - (agents.filter(a => a.status === 'busy').length / agents.length)) * 100) }; } /** * Get list of agents */ async getAgents(): Promise<Agent[]> { return Array.from(this.agents.values()); } /** * Get list of tasks */ async getTasks(): Promise<any[]> { return this.db.getTasks(this.id); } /** * Get specific task */ async getTask(taskId: string): Promise<any> { return this.db.getTask(taskId); } /** * Cancel a task */ async cancelTask(taskId: string): Promise<void> { await this.orchestrator.cancelTask(taskId); await this.db.updateTaskStatus(taskId, 'cancelled'); this.emit('taskCancelled', { taskId }); } /** * Retry a failed task */ async retryTask(taskId: string): Promise<Task> { const originalTask = await this.db.getTask(taskId); if (!originalTask) { throw new Error('Task not found'); } const newTask = await this.submitTask({ description: originalTask.description + ' (Retry)', priority: originalTask.priority, strategy: originalTask.strategy, dependencies: [], requireConsensus: originalTask.require_consensus, maxAgents: originalTask.max_agents, requiredCapabilities: JSON.parse(originalTask.required_capabilities || '[]'), metadata: { ...JSON.parse(originalTask.metadata || '{}'), retryOf: taskId } }); return newTask; } /** * Rebalance agents across tasks */ async rebalanceAgents(): Promise<void> { await this.orchestrator.rebalance(); this.emit('agentsRebalanced'); } /** * Shutdown the Hive Mind */ async shutdown(): Promise<void> { this.started = false; // Shutdown all agents for (const agent of this.agents.values()) { await agent.shutdown(); } // Shutdown subsystems await Promise.all([ this.queen.shutdown(), this.memory.shutdown(), this.communication.shutdown(), this.orchestrator.shutdown() ]); this.emit('shutdown'); } // Private helper methods private getDefaultCapabilities(type: AgentType): string[] { const capabilityMap: Record<AgentType, string[]> = { coordinator: ['task_management', 'resource_allocation', 'consensus_building'], researcher: ['information_gathering', 'pattern_recognition', 'knowledge_synthesis'], coder: ['code_generation', 'refactoring', 'debugging'], analyst: ['data_analysis', 'performance_metrics', 'bottleneck_detection'], architect: ['system_design', 'architecture_patterns', 'integration_planning'], tester: ['test_generation', 'quality_assurance', 'edge_case_detection'], reviewer: ['code_review', 'standards_enforcement', 'best_practices'], optimizer: ['performance_optimization', 'resource_optimization', 'algorithm_improvement'], documenter: ['documentation_generation', 'api_docs', 'user_guides'], monitor: ['system_monitoring', 'health_checks', 'alerting'], specialist: ['domain_expertise', 'custom_capabilities', 'problem_solving'] }; return capabilityMap[type] || []; } private async assignPendingTasksToAgent(agent: Agent): Promise<void> { const pendingTasks = await this.db.getPendingTasks(this.id); for (const task of pendingTasks) { const requiredCapabilities = JSON.parse(task.required_capabilities || '[]'); // Check if agent has required capabilities if (requiredCapabilities.every((cap: string) => agent.capabilities.includes(cap))) { await this.orchestrator.assignTaskToAgent(task.id, agent.id); break; // Only assign one task at a time } } } private async calculatePerformanceMetrics() { // This would calculate real metrics from the database return { avgTaskCompletion: 3500, messageThroughput: 120, consensusSuccessRate: 92, memoryHitRate: 85, agentUtilization: 78 }; } private determineHealth(agents: Agent[], tasks: any[], performance: any): string { if (agents.length === 0) return 'critical'; const busyAgents = agents.filter(a => a.status === 'busy').length; const utilization = busyAgents / agents.length; if (utilization > 0.9) return 'degraded'; if (performance.consensusSuccessRate < 50) return 'degraded'; if (agents.filter(a => a.status === 'error').length > agents.length * 0.2) return 'critical'; return 'healthy'; } private getSystemWarnings(agents: Agent[], tasks: any[], performance: any): string[] { const warnings: string[] = []; const utilization = agents.filter(a => a.status === 'busy').length / agents.length; if (utilization > 0.8) { warnings.push('High agent utilization - consider spawning more agents'); } const pendingTasks = tasks.filter(t => t.status === 'pending').length; if (pendingTasks > agents.length * 2) { warnings.push('Large task backlog - tasks may be delayed'); } if (performance.memoryHitRate < 60) { warnings.push('Low memory hit rate - consider optimizing memory usage'); } return warnings; } }