UNPKG

claude-flow-tbowman01

Version:

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

422 lines (364 loc) 12.6 kB
/** * Hive Mind Orchestrator - Advanced task coordination with consensus */ import { EventEmitter } from 'events'; import { generateId } from '../utils/helpers.js'; export interface HiveTask { id: string; type: 'analysis' | 'design' | 'implementation' | 'testing' | 'documentation' | 'research'; description: string; priority: 'critical' | 'high' | 'medium' | 'low'; dependencies: string[]; assignedTo?: string; status: 'pending' | 'voting' | 'assigned' | 'executing' | 'reviewing' | 'completed' | 'failed'; votes: Map<string, { approve: boolean; confidence: number }>; result?: any; metrics?: { startTime: number; endTime?: number; attempts: number; quality?: number; }; } export interface HiveDecision { id: string; type: 'task_assignment' | 'quality_check' | 'architecture' | 'consensus'; proposal: any; votes: Map<string, boolean>; result: 'approved' | 'rejected' | 'pending'; timestamp: number; } export class HiveOrchestrator extends EventEmitter { private tasks: Map<string, HiveTask> = new Map(); private decisions: Map<string, HiveDecision> = new Map(); private agentCapabilities: Map<string, Set<string>> = new Map(); private consensusThreshold: number; private topology: string; constructor( options: { consensusThreshold?: number; topology?: 'hierarchical' | 'mesh' | 'ring' | 'star'; } = {}, ) { super(); this.consensusThreshold = options.consensusThreshold || 0.6; this.topology = options.topology || 'hierarchical'; } /** * Register agent capabilities for task matching */ registerAgentCapabilities(agentId: string, capabilities: string[]) { this.agentCapabilities.set(agentId, new Set(capabilities)); this.emit('agent:registered', { agentId, capabilities }); } /** * Decompose objective into coordinated tasks */ async decomposeObjective(objective: string): Promise<HiveTask[]> { const tasks: HiveTask[] = []; // Analyze objective to determine task types const needsResearch = objective.toLowerCase().includes('research') || objective.toLowerCase().includes('analyze'); const needsDesign = objective.toLowerCase().includes('build') || objective.toLowerCase().includes('create') || objective.toLowerCase().includes('develop'); const needsImplementation = needsDesign || objective.toLowerCase().includes('implement'); // Create task graph based on objective if (needsResearch) { tasks.push( this.createTask( 'research', `Research background and requirements for: ${objective}`, 'high', ), ); } const analysisTask = this.createTask( 'analysis', `Analyze requirements and constraints for: ${objective}`, 'critical', ); tasks.push(analysisTask); if (needsDesign) { const designTask = this.createTask( 'design', 'Design system architecture and components', 'high', [analysisTask.id], ); tasks.push(designTask); if (needsImplementation) { const implTask = this.createTask('implementation', 'Implement core functionality', 'high', [ designTask.id, ]); tasks.push(implTask); const testTask = this.createTask('testing', 'Test and validate implementation', 'high', [ implTask.id, ]); tasks.push(testTask); } } // Always include documentation const docTask = this.createTask( 'documentation', 'Document solution and decisions', 'medium', tasks.filter((t) => t.type !== 'documentation').map((t) => t.id), ); tasks.push(docTask); // Apply topology-specific ordering return this.applyTopologyOrdering(tasks); } /** * Create a new task */ private createTask( type: HiveTask['type'], description: string, priority: HiveTask['priority'], dependencies: string[] = [], ): HiveTask { const task: HiveTask = { id: generateId('task'), type, description, priority, dependencies, status: 'pending', votes: new Map(), metrics: { startTime: Date.now(), attempts: 0, }, }; this.tasks.set(task.id, task); this.emit('task:created', task); return task; } /** * Apply topology-specific task ordering */ private applyTopologyOrdering(tasks: HiveTask[]): HiveTask[] { switch (this.topology) { case 'hierarchical': // Priority-based ordering with dependency respect return tasks.sort((a, b) => { const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 }; return priorityOrder[a.priority] - priorityOrder[b.priority]; }); case 'ring': // Sequential ordering - each task depends on previous for (let i = 1; i < tasks.length; i++) { if (tasks[i].dependencies.length === 0) { tasks[i].dependencies.push(tasks[i - 1].id); } } return tasks; case 'mesh': // Parallel-friendly ordering - minimize dependencies return tasks.sort((a, b) => a.dependencies.length - b.dependencies.length); case 'star': // Central coordination - all tasks report to analysis const analysisTask = tasks.find((t) => t.type === 'analysis'); if (analysisTask) { tasks.forEach((t) => { if (t.id !== analysisTask.id && t.dependencies.length === 0) { t.dependencies.push(analysisTask.id); } }); } return tasks; default: return tasks; } } /** * Propose task assignment with voting */ async proposeTaskAssignment(taskId: string, agentId: string): Promise<HiveDecision> { const task = this.tasks.get(taskId); if (!task) throw new Error(`Task ${taskId} not found`); const decision: HiveDecision = { id: generateId('decision'), type: 'task_assignment', proposal: { taskId, agentId }, votes: new Map(), result: 'pending', timestamp: Date.now(), }; this.decisions.set(decision.id, decision); task.status = 'voting'; this.emit('decision:proposed', decision); return decision; } /** * Submit vote for a decision */ submitVote(decisionId: string, agentId: string, vote: boolean) { const decision = this.decisions.get(decisionId); if (!decision) throw new Error(`Decision ${decisionId} not found`); decision.votes.set(agentId, vote); // Check if we have enough votes const totalAgents = this.agentCapabilities.size; const votesReceived = decision.votes.size; if (votesReceived >= totalAgents * 0.8) { // 80% participation required this.evaluateDecision(decision); } } /** * Evaluate decision based on votes */ private evaluateDecision(decision: HiveDecision) { const approvals = Array.from(decision.votes.values()).filter((v) => v).length; const totalVotes = decision.votes.size; const approvalRate = approvals / totalVotes; decision.result = approvalRate >= this.consensusThreshold ? 'approved' : 'rejected'; if (decision.result === 'approved' && decision.type === 'task_assignment') { const { taskId, agentId } = decision.proposal; const task = this.tasks.get(taskId); if (task) { task.assignedTo = agentId; task.status = 'assigned'; this.emit('task:assigned', { task, agentId }); } } this.emit('decision:resolved', decision); } /** * Get optimal agent for task based on capabilities */ getOptimalAgent(taskId: string): string | null { const task = this.tasks.get(taskId); if (!task) return null; let bestAgent: string | null = null; let bestScore = 0; for (const [agentId, capabilities] of this.agentCapabilities) { const score = this.calculateAgentTaskScore(task, capabilities); if (score > bestScore) { bestScore = score; bestAgent = agentId; } } return bestAgent; } /** * Calculate how well agent capabilities match task */ private calculateAgentTaskScore(task: HiveTask, capabilities: Set<string>): number { let score = 0; // Type-specific scoring switch (task.type) { case 'research': if (capabilities.has('research')) score += 5; if (capabilities.has('analysis')) score += 3; if (capabilities.has('exploration')) score += 2; break; case 'design': if (capabilities.has('architecture')) score += 5; if (capabilities.has('design')) score += 4; if (capabilities.has('planning')) score += 3; break; case 'implementation': if (capabilities.has('coding')) score += 5; if (capabilities.has('implementation')) score += 4; if (capabilities.has('building')) score += 3; break; case 'testing': if (capabilities.has('testing')) score += 5; if (capabilities.has('validation')) score += 4; if (capabilities.has('quality')) score += 3; break; case 'documentation': if (capabilities.has('documentation')) score += 5; if (capabilities.has('writing')) score += 3; break; } // General capabilities bonus if (capabilities.has('analysis')) score += 1; if (capabilities.has('optimization')) score += 1; return score; } /** * Update task status */ updateTaskStatus(taskId: string, status: HiveTask['status'], result?: any) { const task = this.tasks.get(taskId); if (!task) throw new Error(`Task ${taskId} not found`); task.status = status; if (result) task.result = result; if (status === 'completed' && task.metrics) { task.metrics.endTime = Date.now(); } this.emit('task:updated', task); // Check if we can start dependent tasks if (status === 'completed') { this.checkDependentTasks(taskId); } } /** * Check and update dependent tasks */ private checkDependentTasks(completedTaskId: string) { for (const task of this.tasks.values()) { if (task.status === 'pending' && task.dependencies.includes(completedTaskId)) { // Check if all dependencies are completed const allDepsCompleted = task.dependencies.every((depId) => { const depTask = this.tasks.get(depId); return depTask && depTask.status === 'completed'; }); if (allDepsCompleted) { this.emit('task:ready', task); } } } } /** * Calculate swarm performance metrics */ getPerformanceMetrics() { const tasks = Array.from(this.tasks.values()); const completed = tasks.filter((t) => t.status === 'completed'); const failed = tasks.filter((t) => t.status === 'failed'); const avgExecutionTime = completed.length > 0 ? completed.reduce( (sum, t) => sum + (t.metrics?.endTime || 0) - (t.metrics?.startTime || 0), 0, ) / completed.length : 0; const decisions = Array.from(this.decisions.values()); const approvedDecisions = decisions.filter((d) => d.result === 'approved'); return { totalTasks: tasks.length, completedTasks: completed.length, failedTasks: failed.length, pendingTasks: tasks.filter((t) => t.status === 'pending').length, executingTasks: tasks.filter((t) => t.status === 'executing').length, avgExecutionTime, totalDecisions: decisions.length, approvedDecisions: approvedDecisions.length, consensusRate: decisions.length > 0 ? approvedDecisions.length / decisions.length : 0, topology: this.topology, }; } /** * Get task dependency graph */ getTaskGraph() { const nodes = Array.from(this.tasks.values()).map((task) => ({ id: task.id, type: task.type, status: task.status, assignedTo: task.assignedTo, })); const edges = []; for (const task of this.tasks.values()) { for (const dep of task.dependencies) { edges.push({ from: dep, to: task.id }); } } return { nodes, edges }; } }