claude-flow
Version:
Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)
521 lines (444 loc) • 15.2 kB
text/typescript
/**
* 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;
}
}