UNPKG

claude-flow-novice

Version:

Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture Includes Local RuVector Accelerator and all CFN skills for complete functionality.

193 lines (192 loc) 6.33 kB
/** * Dependency Resolver * Resolves agent task dependencies and builds execution graphs */ import { Logger } from '../core/logger.js'; /** * Dependency Resolver: Parse dependencies and build execution graphs */ export class DependencyResolver { logger; constructor(){ const loggerConfig = process.env.CLAUDE_FLOW_ENV === 'test' ? { level: 'error', format: 'json', destination: 'console' } : { level: 'info', format: 'json', destination: 'console' }; this.logger = new Logger(loggerConfig, { component: 'DependencyResolver' }); } /** * Resolve dependencies and build execution graph */ resolveDependencies(tasks) { this.logger.info('Resolving task dependencies', { taskCount: tasks.length }); // Build dependency graph const graph = this.buildGraph(tasks); // Detect cycles const cycles = this.detectCycles(graph); if (cycles.length > 0) { this.logger.warn('Dependency cycles detected', { cycleCount: cycles.length }); } // Perform topological sort const executionOrder = this.topologicalSort(graph); // Calculate max level const maxLevel = Math.max(...Array.from(graph.values()).map((node)=>node.level)); const result = { executionOrder, graph, cycles, maxLevel }; this.logger.info('Dependency resolution complete', { levels: executionOrder.length, maxLevel, cycles: cycles.length }); return result; } /** * Build dependency graph from task definitions */ buildGraph(tasks) { const graph = new Map(); // Initialize nodes tasks.forEach((task)=>{ graph.set(task.taskId, { taskId: task.taskId, agentId: task.agentId, dependencies: task.dependsOn || [], dependents: [], level: 0, priority: task.priority || 0 }); }); // Build dependent relationships tasks.forEach((task)=>{ task.dependsOn?.forEach((depId)=>{ const depNode = graph.get(depId); if (depNode) { depNode.dependents.push(task.taskId); } }); }); // Calculate levels (topological depth) this.calculateLevels(graph); return graph; } /** * Calculate topological levels for each node */ calculateLevels(graph) { const visited = new Set(); const calculateLevel = (nodeId)=>{ if (visited.has(nodeId)) { return graph.get(nodeId)?.level ?? 0; } visited.add(nodeId); const node = graph.get(nodeId); if (!node) return 0; if (node.dependencies.length === 0) { node.level = 0; return 0; } const maxDepLevel = Math.max(...node.dependencies.map((depId)=>calculateLevel(depId))); node.level = maxDepLevel + 1; return node.level; }; graph.forEach((_, nodeId)=>{ calculateLevel(nodeId); }); } /** * Perform topological sort to get execution order */ topologicalSort(graph) { const levels = new Map(); // Group nodes by level graph.forEach((node)=>{ if (!levels.has(node.level)) { levels.set(node.level, []); } levels.get(node.level).push(node.taskId); }); // Sort levels and sort within each level by priority const sortedLevels = []; const levelKeys = Array.from(levels.keys()).sort((a, b)=>a - b); levelKeys.forEach((level)=>{ const taskIds = levels.get(level); taskIds.sort((a, b)=>{ const nodeA = graph.get(a); const nodeB = graph.get(b); return (nodeB.priority || 0) - (nodeA.priority || 0); }); sortedLevels.push(taskIds); }); return sortedLevels; } /** * Detect cycles in dependency graph */ detectCycles(graph) { const cycles = []; const visited = new Set(); const recursionStack = new Set(); const currentPath = []; const detectCycle = (nodeId)=>{ if (recursionStack.has(nodeId)) { // Cycle detected - extract cycle from current path const cycleStart = currentPath.indexOf(nodeId); cycles.push([ ...currentPath.slice(cycleStart), nodeId ]); return true; } if (visited.has(nodeId)) { return false; } visited.add(nodeId); recursionStack.add(nodeId); currentPath.push(nodeId); const node = graph.get(nodeId); if (node) { for (const depId of node.dependencies){ if (detectCycle(depId)) { // Continue searching for all cycles } } } currentPath.pop(); recursionStack.delete(nodeId); return false; }; graph.forEach((_, nodeId)=>{ if (!visited.has(nodeId)) { detectCycle(nodeId); } }); return cycles; } /** * Get tasks ready to execute (no pending dependencies) */ getReadyTasks(graph, completed) { const ready = []; graph.forEach((node)=>{ if (completed.has(node.taskId)) { return; } const allDepsCompleted = node.dependencies.every((depId)=>completed.has(depId)); if (allDepsCompleted) { ready.push(node); } }); // Sort by priority ready.sort((a, b)=>(b.priority || 0) - (a.priority || 0)); return ready; } } export default DependencyResolver; //# sourceMappingURL=dependency-resolver.js.map