claude-flow-tbowman01
Version:
Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)
315 lines (261 loc) • 8.3 kB
text/typescript
/**
* Fixed orchestrator implementation for Claude-Flow
*/
import type { EventBus } from './event-bus.js';
import type { Logger } from './logger.js';
import type { ConfigManager } from './config.js';
import { JsonPersistenceManager } from './json-persistence.js';
export interface AgentInfo {
id: string;
type: string;
name: string;
status: string;
assignedTasks: string[];
createdAt: number;
}
export interface TaskInfo {
id: string;
type: string;
description: string;
status: string;
progress: number;
assignedAgent?: string;
error?: string;
}
export interface SessionInfo {
id: string;
type: string;
agentId: string;
}
export interface WorkflowStatus {
status: string;
progress: number;
error?: string;
}
export interface HealthCheckResult {
healthy: boolean;
memory: boolean;
terminalPool: boolean;
mcp: boolean;
}
export class Orchestrator {
private agents: Map<string, AgentInfo> = new Map();
private tasks: Map<string, TaskInfo> = new Map();
private sessions: Map<string, SessionInfo> = new Map();
private persistence: JsonPersistenceManager;
private workflows: Map<string, WorkflowStatus> = new Map();
private started = false;
constructor(
private config: ConfigManager,
private eventBus: EventBus,
private logger: Logger,
) {
this.persistence = new JsonPersistenceManager();
}
async start(): Promise<void> {
if (this.started) {
throw new Error('Orchestrator already started');
}
this.logger.info('Starting orchestrator...');
// Initialize persistence
await this.persistence.initialize();
// Load existing agents and tasks from database
await this.loadFromPersistence();
// Initialize components
this.eventBus.emit('system:ready', { timestamp: new Date() });
this.started = true;
this.logger.info('Orchestrator started successfully');
}
private async loadFromPersistence(): Promise<void> {
// Load agents
const persistedAgents = await this.persistence.getActiveAgents();
for (const agent of persistedAgents) {
this.agents.set(agent.id, {
id: agent.id,
type: agent.type,
name: agent.name,
status: agent.status,
assignedTasks: [],
createdAt: agent.createdAt,
});
}
// Load tasks
const persistedTasks = await this.persistence.getActiveTasks();
for (const task of persistedTasks) {
this.tasks.set(task.id, {
id: task.id,
type: task.type,
description: task.description,
status: task.status,
progress: task.progress,
assignedAgent: task.assignedAgent,
error: task.error,
});
}
this.logger.info(
`Loaded ${this.agents.size} agents and ${this.tasks.size} tasks from persistence`,
);
}
async stop(): Promise<void> {
if (!this.started) {
return;
}
this.logger.info('Stopping orchestrator...');
// Clean up resources
this.agents.clear();
this.tasks.clear();
this.sessions.clear();
this.workflows.clear();
// Close persistence
this.persistence.close();
this.started = false;
this.logger.info('Orchestrator stopped');
}
async spawnAgent(profile: {
type: string;
name: string;
capabilities: string[];
systemPrompt: string;
maxConcurrentTasks: number;
priority: number;
}): Promise<string> {
const agentId = `agent-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const agent: AgentInfo = {
id: agentId,
type: profile.type,
name: profile.name,
status: 'active',
assignedTasks: [],
createdAt: Date.now(),
};
// Save to persistence
await this.persistence.saveAgent({
id: agentId,
type: profile.type,
name: profile.name,
status: 'active',
capabilities: profile.capabilities,
systemPrompt: profile.systemPrompt,
maxConcurrentTasks: profile.maxConcurrentTasks,
priority: profile.priority,
createdAt: Date.now(),
});
this.agents.set(agentId, agent);
this.eventBus.emit('agent:spawned', { agentId, profile });
return agentId;
}
async terminateAgent(agentId: string): Promise<void> {
const agent = this.agents.get(agentId);
if (!agent) {
throw new Error(`Agent ${agentId} not found`);
}
// Update persistence
await this.persistence.updateAgentStatus(agentId, 'terminated');
this.agents.delete(agentId);
this.eventBus.emit('agent:terminated', { agentId, reason: 'User requested' });
}
getActiveAgents(): AgentInfo[] {
return Array.from(this.agents.values());
}
getAgentInfo(agentId: string): AgentInfo | undefined {
return this.agents.get(agentId);
}
async submitTask(task: {
type: string;
description: string;
priority: number;
dependencies: string[];
metadata: Record<string, unknown>;
}): Promise<string> {
const taskId = `task-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const taskInfo: TaskInfo = {
id: taskId,
type: task.type,
description: task.description,
status: 'pending',
progress: 0,
};
// Save to persistence
await this.persistence.saveTask({
id: taskId,
type: task.type,
description: task.description,
status: 'pending',
priority: task.priority,
dependencies: task.dependencies,
metadata: task.metadata,
progress: 0,
createdAt: Date.now(),
});
this.tasks.set(taskId, taskInfo);
this.eventBus.emit('task:created', { taskId, task });
// Simulate task assignment
const availableAgents = Array.from(this.agents.values()).filter((a) => a.status === 'active');
if (availableAgents.length > 0) {
const agent = availableAgents[0];
taskInfo.assignedAgent = agent.id;
taskInfo.status = 'assigned';
agent.assignedTasks.push(taskId);
this.eventBus.emit('task:assigned', { taskId, agentId: agent.id });
// Update persistence with assignment
await this.persistence.updateTaskStatus(taskId, 'assigned', agent.id);
}
return taskId;
}
getTaskQueue(): TaskInfo[] {
return Array.from(this.tasks.values());
}
getTaskStatus(taskId: string): TaskInfo | undefined {
return this.tasks.get(taskId);
}
async cancelTask(taskId: string): Promise<void> {
const task = this.tasks.get(taskId);
if (!task) {
throw new Error(`Task ${taskId} not found`);
}
task.status = 'cancelled';
this.eventBus.emit('task:cancelled', { taskId });
}
getActiveSessions(): SessionInfo[] {
return Array.from(this.sessions.values());
}
async terminateSession(sessionId: string): Promise<void> {
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Session ${sessionId} not found`);
}
this.sessions.delete(sessionId);
this.eventBus.emit('session:terminated', { sessionId });
}
async executeWorkflow(workflow: any): Promise<string> {
const workflowId = `workflow-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const status: WorkflowStatus = {
status: 'running',
progress: 0,
};
this.workflows.set(workflowId, status);
this.eventBus.emit('workflow:started', { workflowId, workflow });
// Simulate workflow execution
setTimeout(() => {
status.status = 'completed';
status.progress = 100;
this.eventBus.emit('workflow:completed', { workflowId });
}, 5000);
return workflowId;
}
async getWorkflowStatus(workflowId: string): Promise<WorkflowStatus> {
const status = this.workflows.get(workflowId);
if (!status) {
throw new Error(`Workflow ${workflowId} not found`);
}
return status;
}
async healthCheck(): Promise<HealthCheckResult> {
return {
healthy: this.started,
memory: true,
terminalPool: true,
mcp: this.started,
};
}
}