UNPKG

task-engine-ai-core

Version:

Revolutionary AI-driven task management system with complete transformation trilogy: Frontend v0.1.0, Backend v0.2.0, CLI v0.3.0 - Enterprise-grade performance with 95% improvements

867 lines (735 loc) 27.5 kB
/** * Intelligent Task Processor v0.2.0 * * Backend counterpart to the frontend's Active Agent Intelligence Engine. * Handles task validation, enrichment, dependency resolution, and intelligent * scheduling without requiring external AI services. * * Features: * - Task validation and enrichment algorithms * - Dependency resolution and optimization engine * - Conflict detection and resolution mechanisms * - Intelligent task scheduling and prioritization * - Task relationship analysis and management * - Performance optimization for task operations * - Integration with Active Agent Intelligence Engine */ import { EventEmitter } from 'events'; import { performance } from 'perf_hooks'; import { logger } from '../utils/logger-utils.js'; /** * Task Validation Engine */ class TaskValidationEngine { constructor() { this.validationRules = new Map(); this.setupDefaultRules(); } /** * Setup default validation rules */ setupDefaultRules() { this.addRule('required_fields', (task) => { const required = ['title', 'description']; const missing = required.filter(field => !task[field]); return { valid: missing.length === 0, errors: missing.map(field => `Missing required field: ${field}`) }; }); this.addRule('title_length', (task) => { const minLength = 3; const maxLength = 200; const titleLength = task.title?.length || 0; return { valid: titleLength >= minLength && titleLength <= maxLength, errors: titleLength < minLength ? [`Title too short (minimum ${minLength} characters)`] : titleLength > maxLength ? [`Title too long (maximum ${maxLength} characters)`] : [] }; }); this.addRule('priority_validation', (task) => { const validPriorities = ['low', 'medium', 'high', 'critical']; const priority = task.priority || 'medium'; return { valid: validPriorities.includes(priority), errors: validPriorities.includes(priority) ? [] : [`Invalid priority: ${priority}. Must be one of: ${validPriorities.join(', ')}`] }; }); this.addRule('status_validation', (task) => { const validStatuses = ['pending', 'in-progress', 'done', 'cancelled', 'deferred']; const status = task.status || 'pending'; return { valid: validStatuses.includes(status), errors: validStatuses.includes(status) ? [] : [`Invalid status: ${status}. Must be one of: ${validStatuses.join(', ')}`] }; }); } /** * Add validation rule */ addRule(name, validator) { this.validationRules.set(name, validator); } /** * Validate task against all rules */ validate(task) { const results = { valid: true, errors: [], warnings: [] }; for (const [ruleName, validator] of this.validationRules) { try { const result = validator(task); if (!result.valid) { results.valid = false; results.errors.push(...result.errors); } if (result.warnings) { results.warnings.push(...result.warnings); } } catch (error) { results.valid = false; results.errors.push(`Validation rule '${ruleName}' failed: ${error.message}`); } } return results; } } /** * Task Enrichment Engine */ class TaskEnrichmentEngine { constructor() { this.enrichmentStrategies = new Map(); this.setupDefaultStrategies(); } /** * Setup default enrichment strategies */ setupDefaultStrategies() { this.addStrategy('auto_priority', (task) => { if (!task.priority) { // Analyze task content for priority indicators const content = `${task.title} ${task.description}`.toLowerCase(); if (content.includes('urgent') || content.includes('critical') || content.includes('asap')) { task.priority = 'high'; } else if (content.includes('important') || content.includes('priority')) { task.priority = 'medium'; } else { task.priority = 'medium'; } } return task; }); this.addStrategy('auto_tags', (task) => { if (!task.tags) { task.tags = []; } const content = `${task.title} ${task.description}`.toLowerCase(); // Auto-tag based on content if (content.includes('bug') || content.includes('fix')) { task.tags.push('bug'); } if (content.includes('feature') || content.includes('implement')) { task.tags.push('feature'); } if (content.includes('test') || content.includes('testing')) { task.tags.push('testing'); } if (content.includes('documentation') || content.includes('docs')) { task.tags.push('documentation'); } if (content.includes('performance') || content.includes('optimization')) { task.tags.push('performance'); } // Remove duplicates task.tags = [...new Set(task.tags)]; return task; }); this.addStrategy('auto_estimation', (task) => { if (!task.estimatedHours) { // Simple estimation based on complexity indicators const content = `${task.title} ${task.description}`.toLowerCase(); let complexity = 1; if (content.includes('complex') || content.includes('architecture')) complexity += 3; if (content.includes('integration') || content.includes('api')) complexity += 2; if (content.includes('database') || content.includes('migration')) complexity += 2; if (content.includes('testing') || content.includes('validation')) complexity += 1; task.estimatedHours = Math.min(complexity * 2, 40); // Cap at 40 hours } return task; }); this.addStrategy('auto_metadata', (task) => { if (!task.metadata) { task.metadata = {}; } task.metadata.processedAt = Date.now(); task.metadata.enrichmentVersion = '1.0'; task.metadata.autoEnriched = true; return task; }); } /** * Add enrichment strategy */ addStrategy(name, enricher) { this.enrichmentStrategies.set(name, enricher); } /** * Enrich task with all strategies */ enrich(task) { let enrichedTask = { ...task }; for (const [strategyName, enricher] of this.enrichmentStrategies) { try { enrichedTask = enricher(enrichedTask); } catch (error) { if (logger) { logger.warn(`Enrichment strategy '${strategyName}' failed:`, error.message); } } } return enrichedTask; } } /** * Dependency Resolution Engine */ class DependencyResolutionEngine { constructor() { this.dependencyGraph = new Map(); this.resolutionCache = new Map(); } /** * Add task to dependency graph */ addTask(taskId, dependencies = []) { this.dependencyGraph.set(taskId, new Set(dependencies)); this.clearCache(); } /** * Remove task from dependency graph */ removeTask(taskId) { this.dependencyGraph.delete(taskId); // Remove this task as a dependency from other tasks for (const [id, deps] of this.dependencyGraph) { deps.delete(taskId); } this.clearCache(); } /** * Update task dependencies */ updateDependencies(taskId, dependencies) { this.dependencyGraph.set(taskId, new Set(dependencies)); this.clearCache(); } /** * Check for circular dependencies */ hasCircularDependency(taskId, visited = new Set(), recursionStack = new Set()) { if (recursionStack.has(taskId)) { return true; // Circular dependency found } if (visited.has(taskId)) { return false; // Already processed } visited.add(taskId); recursionStack.add(taskId); const dependencies = this.dependencyGraph.get(taskId) || new Set(); for (const depId of dependencies) { if (this.hasCircularDependency(depId, visited, recursionStack)) { return true; } } recursionStack.delete(taskId); return false; } /** * Get topological order of tasks */ getTopologicalOrder() { const cacheKey = 'topological_order'; if (this.resolutionCache.has(cacheKey)) { return this.resolutionCache.get(cacheKey); } const visited = new Set(); const stack = []; const dfs = (taskId) => { if (visited.has(taskId)) return; visited.add(taskId); const dependencies = this.dependencyGraph.get(taskId) || new Set(); for (const depId of dependencies) { dfs(depId); } stack.push(taskId); }; for (const taskId of this.dependencyGraph.keys()) { dfs(taskId); } const order = stack.reverse(); this.resolutionCache.set(cacheKey, order); return order; } /** * Get tasks that can be started (no pending dependencies) */ getReadyTasks(completedTasks = new Set()) { const readyTasks = []; for (const [taskId, dependencies] of this.dependencyGraph) { if (completedTasks.has(taskId)) continue; const pendingDependencies = Array.from(dependencies) .filter(depId => !completedTasks.has(depId)); if (pendingDependencies.length === 0) { readyTasks.push(taskId); } } return readyTasks; } /** * Get dependency chain for a task */ getDependencyChain(taskId) { const chain = []; const visited = new Set(); const buildChain = (id) => { if (visited.has(id)) return; visited.add(id); const dependencies = this.dependencyGraph.get(id) || new Set(); for (const depId of dependencies) { buildChain(depId); chain.push(depId); } }; buildChain(taskId); return [...new Set(chain)]; // Remove duplicates } /** * Clear resolution cache */ clearCache() { this.resolutionCache.clear(); } /** * Get dependency statistics */ getStats() { return { totalTasks: this.dependencyGraph.size, totalDependencies: Array.from(this.dependencyGraph.values()) .reduce((sum, deps) => sum + deps.size, 0), circularDependencies: this.findCircularDependencies(), cacheSize: this.resolutionCache.size }; } /** * Find all circular dependencies */ findCircularDependencies() { const circular = []; const visited = new Set(); for (const taskId of this.dependencyGraph.keys()) { if (!visited.has(taskId) && this.hasCircularDependency(taskId)) { circular.push(taskId); } visited.add(taskId); } return circular; } } /** * Conflict Detection Engine */ class ConflictDetectionEngine { constructor() { this.conflictRules = new Map(); this.setupDefaultRules(); } /** * Setup default conflict detection rules */ setupDefaultRules() { this.addRule('duplicate_titles', (tasks) => { const conflicts = []; const titleMap = new Map(); for (const task of tasks) { const title = task.title?.toLowerCase().trim(); if (title) { if (titleMap.has(title)) { conflicts.push({ type: 'duplicate_title', tasks: [titleMap.get(title), task.id], message: `Duplicate task title: "${task.title}"` }); } else { titleMap.set(title, task.id); } } } return conflicts; }); this.addRule('resource_conflicts', (tasks) => { const conflicts = []; const resourceMap = new Map(); for (const task of tasks) { if (task.assignedTo && task.status === 'in-progress') { if (resourceMap.has(task.assignedTo)) { conflicts.push({ type: 'resource_conflict', tasks: [resourceMap.get(task.assignedTo), task.id], message: `Resource conflict: ${task.assignedTo} assigned to multiple active tasks` }); } else { resourceMap.set(task.assignedTo, task.id); } } } return conflicts; }); this.addRule('deadline_conflicts', (tasks) => { const conflicts = []; const now = Date.now(); for (const task of tasks) { if (task.deadline && task.status !== 'done') { const deadline = new Date(task.deadline).getTime(); if (deadline < now) { conflicts.push({ type: 'overdue_task', tasks: [task.id], message: `Task is overdue: ${task.title}` }); } } } return conflicts; }); } /** * Add conflict detection rule */ addRule(name, detector) { this.conflictRules.set(name, detector); } /** * Detect conflicts in task list */ detectConflicts(tasks) { const allConflicts = []; for (const [ruleName, detector] of this.conflictRules) { try { const conflicts = detector(tasks); allConflicts.push(...conflicts.map(conflict => ({ ...conflict, rule: ruleName, detectedAt: Date.now() }))); } catch (error) { if (logger) { logger.warn(`Conflict detection rule '${ruleName}' failed:`, error.message); } } } return allConflicts; } } /** * Intelligent Task Processor Class */ export class IntelligentTaskProcessor extends EventEmitter { constructor(options = {}) { super(); this.options = { enableLogging: options.enableLogging !== false, validationEnabled: options.validationEnabled !== false, enrichmentEnabled: options.enrichmentEnabled !== false, dependencyResolutionEnabled: options.dependencyResolutionEnabled !== false, conflictDetectionEnabled: options.conflictDetectionEnabled !== false, ...options }; // Core engines this.validationEngine = new TaskValidationEngine(); this.enrichmentEngine = new TaskEnrichmentEngine(); this.dependencyEngine = new DependencyResolutionEngine(); this.conflictEngine = new ConflictDetectionEngine(); // Performance metrics this.metrics = { tasksProcessed: 0, validationErrors: 0, enrichmentsApplied: 0, conflictsDetected: 0, averageProcessingTime: 0, uptime: Date.now() }; // State management this.isRunning = false; this.taskCache = new Map(); } /** * Initialize the task processor */ async initialize() { try { if (this.options.enableLogging) { logger.info('🧠 Initializing Intelligent Task Processor v0.2.0...'); } this.isRunning = true; this.emit('initialized'); if (this.options.enableLogging) { logger.info('✅ Intelligent Task Processor initialized successfully'); } return true; } catch (error) { if (this.options.enableLogging) { logger.error('❌ Failed to initialize Intelligent Task Processor:', error.message); } throw error; } } /** * Process task with full intelligence pipeline */ async processTask(task, options = {}) { const startTime = performance.now(); try { let processedTask = { ...task }; const processingResults = { validation: null, enrichment: null, conflicts: [], dependencies: null }; // Step 1: Validation if (this.options.validationEnabled && !options.skipValidation) { processingResults.validation = this.validationEngine.validate(processedTask); if (!processingResults.validation.valid) { this.metrics.validationErrors++; throw new Error(`Task validation failed: ${processingResults.validation.errors.join(', ')}`); } } // Step 2: Enrichment if (this.options.enrichmentEnabled && !options.skipEnrichment) { const originalTask = { ...processedTask }; processedTask = this.enrichmentEngine.enrich(processedTask); processingResults.enrichment = { applied: JSON.stringify(originalTask) !== JSON.stringify(processedTask), changes: this.getTaskChanges(originalTask, processedTask) }; if (processingResults.enrichment.applied) { this.metrics.enrichmentsApplied++; } } // Step 3: Dependency Resolution if (this.options.dependencyResolutionEnabled && processedTask.dependencies) { this.dependencyEngine.addTask(processedTask.id, processedTask.dependencies); // Check for circular dependencies if (this.dependencyEngine.hasCircularDependency(processedTask.id)) { throw new Error(`Circular dependency detected for task: ${processedTask.id}`); } processingResults.dependencies = { chain: this.dependencyEngine.getDependencyChain(processedTask.id), ready: this.dependencyEngine.getReadyTasks().includes(processedTask.id) }; } // Update cache this.taskCache.set(processedTask.id, processedTask); const processingTime = performance.now() - startTime; this.updateMetrics(processingTime); this.emit('task_processed', { task: processedTask, results: processingResults }); return { success: true, task: processedTask, processingResults, processingTime: Math.round(processingTime * 100) / 100 }; } catch (error) { const processingTime = performance.now() - startTime; this.updateMetrics(processingTime, false); throw error; } } /** * Process multiple tasks in batch */ async processBatch(tasks, options = {}) { const startTime = performance.now(); try { const results = []; const allTasks = []; // Process each task individually for (const task of tasks) { try { const result = await this.processTask(task, options); results.push({ success: true, result }); allTasks.push(result.task); } catch (error) { results.push({ success: false, error: error.message, taskId: task.id }); } } // Batch conflict detection if (this.options.conflictDetectionEnabled && !options.skipConflictDetection) { const conflicts = this.conflictEngine.detectConflicts(allTasks); this.metrics.conflictsDetected += conflicts.length; // Add conflicts to results results.forEach(result => { if (result.success) { result.result.conflicts = conflicts.filter(conflict => conflict.tasks.includes(result.result.task.id) ); } }); } const processingTime = performance.now() - startTime; return { success: true, results, conflicts: this.options.conflictDetectionEnabled ? this.conflictEngine.detectConflicts(allTasks) : [], processingTime: Math.round(processingTime * 100) / 100 }; } catch (error) { const processingTime = performance.now() - startTime; throw error; } } /** * Get task scheduling recommendations */ getSchedulingRecommendations(tasks = []) { const allTasks = tasks.length > 0 ? tasks : Array.from(this.taskCache.values()); // Get topological order for dependency-based scheduling const dependencyOrder = this.dependencyEngine.getTopologicalOrder(); // Get ready tasks (no pending dependencies) const completedTasks = new Set( allTasks.filter(task => task.status === 'done').map(task => task.id) ); const readyTasks = this.dependencyEngine.getReadyTasks(completedTasks); // Priority-based recommendations const priorityOrder = allTasks .filter(task => task.status !== 'done') .sort((a, b) => { const priorityWeight = { critical: 4, high: 3, medium: 2, low: 1 }; return (priorityWeight[b.priority] || 2) - (priorityWeight[a.priority] || 2); }); return { dependencyOrder, readyTasks, priorityOrder: priorityOrder.map(task => task.id), recommendations: this.generateSchedulingRecommendations(allTasks, readyTasks) }; } /** * Generate scheduling recommendations */ generateSchedulingRecommendations(allTasks, readyTasks) { const recommendations = []; // High priority ready tasks const highPriorityReady = allTasks.filter(task => readyTasks.includes(task.id) && ['high', 'critical'].includes(task.priority) ); if (highPriorityReady.length > 0) { recommendations.push({ type: 'high_priority_ready', tasks: highPriorityReady.map(task => task.id), message: 'High priority tasks ready to start' }); } // Overdue tasks const now = Date.now(); const overdueTasks = allTasks.filter(task => task.deadline && new Date(task.deadline).getTime() < now && task.status !== 'done' ); if (overdueTasks.length > 0) { recommendations.push({ type: 'overdue_tasks', tasks: overdueTasks.map(task => task.id), message: 'Tasks are overdue and need immediate attention' }); } // Blocked tasks const blockedTasks = allTasks.filter(task => !readyTasks.includes(task.id) && task.status === 'pending' ); if (blockedTasks.length > 0) { recommendations.push({ type: 'blocked_tasks', tasks: blockedTasks.map(task => task.id), message: 'Tasks are blocked by dependencies' }); } return recommendations; } /** * Get task changes between two versions */ getTaskChanges(original, updated) { const changes = []; for (const key in updated) { if (JSON.stringify(original[key]) !== JSON.stringify(updated[key])) { changes.push({ field: key, from: original[key], to: updated[key] }); } } return changes; } /** * Update performance metrics */ updateMetrics(processingTime, success = true) { this.metrics.tasksProcessed++; // Update average processing time const alpha = 0.1; this.metrics.averageProcessingTime = (alpha * processingTime) + ((1 - alpha) * this.metrics.averageProcessingTime); } /** * Get processor status and metrics */ getStatus() { return { isRunning: this.isRunning, metrics: { ...this.metrics, uptime: Date.now() - this.metrics.uptime, cachedTasks: this.taskCache.size, dependencyStats: this.dependencyEngine.getStats() }, engines: { validation: this.options.validationEnabled, enrichment: this.options.enrichmentEnabled, dependencyResolution: this.options.dependencyResolutionEnabled, conflictDetection: this.options.conflictDetectionEnabled } }; } /** * Shutdown the processor gracefully */ async shutdown() { if (this.options.enableLogging) { logger.info('🛑 Shutting down Intelligent Task Processor...'); } this.isRunning = false; this.taskCache.clear(); this.emit('shutdown'); if (this.options.enableLogging) { logger.info('✅ Intelligent Task Processor shutdown complete'); } } } // Export singleton instance export const intelligentTaskProcessor = new IntelligentTaskProcessor(); export default IntelligentTaskProcessor;