UNPKG

claude-flow

Version:

Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration

326 lines 11.9 kB
/** * V3 Task Lifecycle Hooks * * Provides pre-task and post-task hooks for task execution lifecycle. * Integrates with ReasoningBank for learning and pattern recognition. * * @module v3/shared/hooks/task-hooks */ import { HookEvent, HookPriority, } from './types.js'; /** * Task Hooks Manager * * Manages pre-task and post-task hooks with ReasoningBank integration. */ export class TaskHooksManager { registry; activeTasks = new Map(); taskPatterns = new Map(); constructor(registry) { this.registry = registry; this.registerDefaultHooks(); } /** * Register default task hooks */ registerDefaultHooks() { // Pre-task hook for agent suggestion this.registry.register(HookEvent.PreTaskExecute, this.handlePreTask.bind(this), HookPriority.Normal, { name: 'task-hooks:pre-task' }); // Post-task hook for learning this.registry.register(HookEvent.PostTaskExecute, this.handlePostTask.bind(this), HookPriority.Normal, { name: 'task-hooks:post-task' }); } /** * Handle pre-task execution */ async handlePreTask(context) { const task = context.task; if (!task) { return { success: false, error: new Error('No task in context') }; } // Store task for tracking const taskStore = { taskId: task.id, description: task.description, startTime: Date.now(), metadata: task.metadata, }; // Analyze task and suggest agents const analysis = await this.analyzeTask(task); taskStore.suggestedAgents = analysis.suggestedAgents; this.activeTasks.set(task.id, taskStore); // Store patterns for this task if (analysis.patterns.length > 0) { this.taskPatterns.set(task.id, analysis.patterns); } return { success: true, suggestedAgents: analysis.suggestedAgents, complexity: analysis.complexity, estimatedDuration: analysis.estimatedDuration, patterns: analysis.patterns, risks: analysis.risks, recommendations: analysis.recommendations, data: { task: { ...task, metadata: { ...task.metadata, suggestedAgents: analysis.suggestedAgents.map(a => a.type), complexity: analysis.complexity, }, }, }, }; } /** * Handle post-task execution */ async handlePostTask(context) { const task = context.task; if (!task) { return { success: false, error: new Error('No task in context') }; } const taskStore = this.activeTasks.get(task.id); const patterns = this.taskPatterns.get(task.id); // Calculate duration const duration = taskStore ? Date.now() - taskStore.startTime : 0; // Extract outcome from context metadata const success = context.metadata?.success !== false; const quality = context.metadata?.quality; const error = context.metadata?.error; const agent = context.metadata?.agent; const outcome = { success, duration, quality, error, agent, artifacts: context.metadata?.artifacts, }; // Record learning trajectory const learningUpdates = await this.recordLearning(task, outcome, patterns); // Clean up this.activeTasks.delete(task.id); this.taskPatterns.delete(task.id); return { success: true, outcome, learningUpdates, patternId: learningUpdates.newPatterns > 0 ? `pattern-${task.id}` : undefined, trajectoryId: `trajectory-${task.id}-${Date.now()}`, }; } /** * Analyze task for agent suggestions and patterns */ async analyzeTask(task) { const description = task.description.toLowerCase(); // Pattern-based agent suggestion const suggestedAgents = []; const patterns = []; const risks = []; const recommendations = []; // Analyze task keywords for agent routing const agentPatterns = [ { keywords: ['implement', 'code', 'create', 'build', 'develop', 'write'], agent: 'coder', capabilities: ['code-generation', 'implementation', 'debugging'], }, { keywords: ['test', 'spec', 'coverage', 'unit', 'integration'], agent: 'tester', capabilities: ['unit-testing', 'integration-testing', 'coverage-analysis'], }, { keywords: ['review', 'check', 'audit', 'analyze'], agent: 'reviewer', capabilities: ['code-review', 'quality-analysis', 'best-practices'], }, { keywords: ['research', 'investigate', 'explore', 'study'], agent: 'researcher', capabilities: ['research', 'analysis', 'documentation'], }, { keywords: ['security', 'vulnerability', 'cve', 'threat'], agent: 'security-architect', capabilities: ['security-analysis', 'vulnerability-detection', 'threat-modeling'], }, { keywords: ['performance', 'optimize', 'speed', 'memory'], agent: 'performance-engineer', capabilities: ['performance-optimization', 'profiling', 'benchmarking'], }, { keywords: ['architect', 'design', 'structure', 'pattern'], agent: 'core-architect', capabilities: ['architecture-design', 'pattern-application', 'system-design'], }, { keywords: ['memory', 'storage', 'database', 'cache'], agent: 'memory-specialist', capabilities: ['memory-management', 'data-persistence', 'caching'], }, { keywords: ['swarm', 'coordinate', 'orchestrate', 'agent'], agent: 'swarm-specialist', capabilities: ['swarm-coordination', 'agent-orchestration', 'distributed-systems'], }, ]; // Score each agent based on keyword matches for (const pattern of agentPatterns) { let matchCount = 0; for (const keyword of pattern.keywords) { if (description.includes(keyword)) { matchCount++; } } if (matchCount > 0) { const confidence = Math.min(0.3 + matchCount * 0.2, 0.95); suggestedAgents.push({ type: pattern.agent, confidence, reason: `Matched keywords: ${pattern.keywords.filter(k => description.includes(k)).join(', ')}`, capabilities: pattern.capabilities, }); } } // Sort by confidence suggestedAgents.sort((a, b) => b.confidence - a.confidence); // If no matches, default to coder if (suggestedAgents.length === 0) { suggestedAgents.push({ type: 'coder', confidence: 0.5, reason: 'Default agent for unclassified tasks', capabilities: ['code-generation', 'implementation'], }); } // Estimate complexity based on description length and keywords let complexity = 'medium'; const complexityKeywords = ['complex', 'large', 'multiple', 'refactor', 'redesign', 'critical']; const simpleKeywords = ['simple', 'small', 'quick', 'fix', 'minor', 'typo']; const hasComplexKeywords = complexityKeywords.some(k => description.includes(k)); const hasSimpleKeywords = simpleKeywords.some(k => description.includes(k)); if (hasComplexKeywords) { complexity = 'high'; } else if (hasSimpleKeywords) { complexity = 'low'; } else if (description.length > 200) { complexity = 'high'; } else if (description.length < 50) { complexity = 'low'; } // Estimate duration based on complexity const durationMap = { low: 5 * 60 * 1000, // 5 minutes medium: 30 * 60 * 1000, // 30 minutes high: 2 * 60 * 60 * 1000, // 2 hours }; const estimatedDuration = durationMap[complexity]; // Detect risks if (description.includes('production') || description.includes('live')) { risks.push('Task involves production environment'); } if (description.includes('delete') || description.includes('remove')) { risks.push('Task involves destructive operations'); } if (description.includes('security') || description.includes('auth')) { risks.push('Task involves security-sensitive operations'); } if (description.includes('database') || description.includes('migration')) { risks.push('Task involves database changes'); } // Add recommendations if (complexity === 'high') { recommendations.push('Consider breaking this task into smaller subtasks'); } if (suggestedAgents.length > 1) { recommendations.push('Consider using multiple agents for better coverage'); } if (risks.length > 0) { recommendations.push('Review risks before proceeding'); } return { suggestedAgents, complexity, estimatedDuration, patterns, risks, recommendations, }; } /** * Record learning trajectory */ async recordLearning(task, outcome, patterns) { // In a real implementation, this would integrate with ReasoningBank // For now, we track basic statistics const learningUpdate = { patternsUpdated: patterns?.length || 0, newPatterns: outcome.success ? 1 : 0, confidenceAdjusted: patterns?.length || 0, trajectoriesRecorded: 1, }; return learningUpdate; } /** * Execute pre-task hook manually */ async executePreTask(taskId, description, metadata) { const context = { event: HookEvent.PreTaskExecute, timestamp: new Date(), task: { id: taskId, description, metadata, }, }; return this.handlePreTask(context); } /** * Execute post-task hook manually */ async executePostTask(taskId, success, metadata) { const taskStore = this.activeTasks.get(taskId); const context = { event: HookEvent.PostTaskExecute, timestamp: new Date(), task: { id: taskId, description: taskStore?.description || 'Unknown task', metadata: taskStore?.metadata, }, metadata: { ...metadata, success, }, }; return this.handlePostTask(context); } /** * Get active tasks */ getActiveTasks() { return new Map(this.activeTasks); } /** * Clear all active tasks */ clearActiveTasks() { this.activeTasks.clear(); this.taskPatterns.clear(); } } /** * Create task hooks manager */ export function createTaskHooksManager(registry) { return new TaskHooksManager(registry); } //# sourceMappingURL=task-hooks.js.map