UNPKG

universal-ai-brain

Version:

🧠 UNIVERSAL AI BRAIN 3.3 - The world's most advanced cognitive architecture with 24 specialized systems, MongoDB 8.1 $rankFusion hybrid search, latest Voyage 3.5 embeddings, and framework-agnostic design. Works with Mastra, Vercel AI, LangChain, OpenAI A

709 lines (645 loc) • 25 kB
/** * @file TemporalPlanningEngine.test.ts - Comprehensive tests for TemporalPlanningEngine * * Tests the TemporalPlanningEngine's ability to: * - Create and optimize temporal plans with time-series analysis * - Predict future states using predictive analytics * - Optimize plans using constraint satisfaction * - Analyze plan performance and generate insights * - Demonstrate MongoDB's time-series and predictive analytics capabilities */ import { MongoClient, Db } from 'mongodb'; import { TemporalPlanningEngine } from '../../intelligence/TemporalPlanningEngine'; import { TemporalPlanCollection } from '../../collections/TemporalPlanCollection'; describe('TemporalPlanningEngine - Real MongoDB Integration', () => { let client: MongoClient; let db: Db; let planningEngine: TemporalPlanningEngine; let planCollection: TemporalPlanCollection; beforeAll(async () => { // Connect to test MongoDB instance const uri = process.env.MONGODB_URI || 'mongodb://localhost:27017'; client = new MongoClient(uri); await client.connect(); // Use test database db = client.db('test_ai_brain_temporal_planning'); planningEngine = new TemporalPlanningEngine(db); planCollection = new TemporalPlanCollection(db); // Initialize the engine await planningEngine.initialize(); }); afterAll(async () => { // Clean up test data await planningEngine.cleanup(); await db.dropDatabase(); await client.close(); }); beforeEach(async () => { // Clear collections before each test await db.collection('agent_temporal_plans').deleteMany({}); }); describe('Temporal Plan Creation and Optimization', () => { it('should create and optimize a temporal plan', async () => { const agentId = 'test-agent-planning-001'; const startTime = new Date(); const endTime = new Date(startTime.getTime() + 8 * 60 * 60 * 1000); // 8 hours later const planningRequest = { agentId, sessionId: 'session-planning-123', planName: 'Data Processing Project', planType: 'sequential' as const, category: 'task_execution' as const, priority: 'high' as const, timeframe: { startTime, endTime, flexibility: 0.2, // 20% flexibility timezone: 'UTC' }, tasks: [ { id: 'task-001', name: 'Data Collection', type: 'atomic' as const, estimatedDuration: 2 * 60 * 60 * 1000, // 2 hours requirements: { skills: ['data_extraction', 'api_integration'], resources: [{ resourceId: 'database_access', quantity: 1 }], conditions: { internet_required: true } }, dependencies: [] }, { id: 'task-002', name: 'Data Processing', type: 'composite' as const, estimatedDuration: 4 * 60 * 60 * 1000, // 4 hours requirements: { skills: ['data_analysis', 'machine_learning'], resources: [{ resourceId: 'compute_cluster', quantity: 4 }], conditions: { high_memory_required: true } }, dependencies: [ { predecessorId: 'task-001', type: 'finish_to_start', lag: 0 } ] }, { id: 'task-003', name: 'Report Generation', type: 'atomic' as const, estimatedDuration: 1 * 60 * 60 * 1000, // 1 hour requirements: { skills: ['report_writing', 'data_visualization'], resources: [{ resourceId: 'reporting_tools', quantity: 1 }], conditions: { template_available: true } }, dependencies: [ { predecessorId: 'task-002', type: 'finish_to_start', lag: 30 * 60 * 1000 } // 30 min lag ] } ], constraints: { deadlines: [ { taskId: 'task-003', deadline: endTime, hardDeadline: true } ], resources: [ { resourceId: 'compute_cluster', maxCapacity: 8, availability: [] }, { resourceId: 'database_access', maxCapacity: 2, availability: [] } ], quality: { minimumLevel: 0.8, targetLevel: 0.95 } }, objectives: [ { name: 'duration', type: 'minimize' as const, weight: 0.4 }, { name: 'quality', type: 'maximize' as const, weight: 0.4, target: 0.95 }, { name: 'efficiency', type: 'maximize' as const, weight: 0.2, target: 0.85 } ] }; // Create the plan const planResult = await planningEngine.createPlan(planningRequest); expect(planResult.planId).toBeDefined(); expect(planResult.optimizedSchedule).toBeDefined(); expect(planResult.criticalPath).toBeInstanceOf(Array); expect(planResult.riskAssessment).toBeDefined(); expect(planResult.performancePredictions).toBeDefined(); // Verify the plan was recorded in MongoDB const recordedPlans = await planCollection.getAgentPlans(agentId); expect(recordedPlans).toHaveLength(1); const plan = recordedPlans[0]; expect(plan.agentId).toBe(agentId); expect(plan.plan.name).toBe('Data Processing Project'); expect(plan.plan.type).toBe('sequential'); expect(plan.structure.tasks).toHaveLength(3); expect(plan.temporal.timeframe.startTime).toEqual(startTime); expect(plan.temporal.timeframe.endTime).toEqual(endTime); // Verify optimization objectives expect(plan.prediction.optimization.objectives).toHaveLength(3); const durationObjective = plan.prediction.optimization.objectives.find(obj => obj.name === 'duration'); expect(durationObjective).toBeDefined(); expect(durationObjective!.type).toBe('minimize'); expect(durationObjective!.weight).toBe(0.4); }); it('should handle complex parallel task planning', async () => { const agentId = 'test-agent-parallel'; const startTime = new Date(); const endTime = new Date(startTime.getTime() + 6 * 60 * 60 * 1000); // 6 hours later const parallelPlanRequest = { agentId, planName: 'Parallel Processing Pipeline', planType: 'parallel' as const, category: 'optimization' as const, priority: 'critical' as const, timeframe: { startTime, endTime, flexibility: 0.1, // 10% flexibility timezone: 'UTC' }, tasks: [ { id: 'parallel-001', name: 'Data Stream A Processing', type: 'atomic' as const, estimatedDuration: 3 * 60 * 60 * 1000, // 3 hours requirements: { skills: ['stream_processing'], resources: [{ resourceId: 'stream_processor_a', quantity: 1 }], conditions: {} }, dependencies: [] }, { id: 'parallel-002', name: 'Data Stream B Processing', type: 'atomic' as const, estimatedDuration: 2.5 * 60 * 60 * 1000, // 2.5 hours requirements: { skills: ['stream_processing'], resources: [{ resourceId: 'stream_processor_b', quantity: 1 }], conditions: {} }, dependencies: [] }, { id: 'merge-001', name: 'Stream Merge and Analysis', type: 'composite' as const, estimatedDuration: 2 * 60 * 60 * 1000, // 2 hours requirements: { skills: ['data_merging', 'analysis'], resources: [{ resourceId: 'analysis_engine', quantity: 1 }], conditions: {} }, dependencies: [ { predecessorId: 'parallel-001', type: 'finish_to_start', lag: 0 }, { predecessorId: 'parallel-002', type: 'finish_to_start', lag: 0 } ] } ], constraints: { deadlines: [ { taskId: 'merge-001', deadline: endTime, hardDeadline: false } ], resources: [ { resourceId: 'stream_processor_a', maxCapacity: 1, availability: [] }, { resourceId: 'stream_processor_b', maxCapacity: 1, availability: [] }, { resourceId: 'analysis_engine', maxCapacity: 1, availability: [] } ], quality: { minimumLevel: 0.85, targetLevel: 0.95 } }, objectives: [ { name: 'duration', type: 'minimize' as const, weight: 0.6 }, { name: 'efficiency', type: 'maximize' as const, weight: 0.4 } ] }; const planResult = await planningEngine.createPlan(parallelPlanRequest); expect(planResult.planId).toBeDefined(); expect(planResult.optimizedSchedule.tasks).toHaveLength(3); expect(planResult.criticalPath).toContain('parallel-001'); // Longest duration task // Verify parallel execution optimization const plan = (await planCollection.getAgentPlans(agentId))[0]; expect(plan.plan.type).toBe('parallel'); expect(plan.structure.tasks.filter(t => t.dependencies.length === 0)).toHaveLength(2); // Two parallel tasks }); }); describe('Future State Prediction with Time-Series Analysis', () => { it('should predict future states using time-series analysis', async () => { const agentId = 'test-agent-prediction'; // Create a plan first const planResult = await planningEngine.createPlan({ agentId, planName: 'Prediction Test Plan', planType: 'sequential', category: 'learning', priority: 'medium', timeframe: { startTime: new Date(), endTime: new Date(Date.now() + 4 * 60 * 60 * 1000), flexibility: 0.3, timezone: 'UTC' }, tasks: [ { id: 'pred-task-001', name: 'Learning Phase', type: 'atomic', estimatedDuration: 2 * 60 * 60 * 1000, requirements: { skills: ['learning'], resources: [], conditions: {} }, dependencies: [] } ], constraints: { deadlines: [], resources: [], quality: { minimumLevel: 0.7, targetLevel: 0.9 } }, objectives: [ { name: 'quality', type: 'maximize', weight: 1.0 } ] }); // Predict future states const predictionRequest = { agentId, timeHorizon: 8, // 8 hours into the future scenarios: [ { name: 'optimal_conditions', probability: 0.3, conditions: { resource_availability: 'high', external_interference: 'low' } }, { name: 'normal_conditions', probability: 0.6, conditions: { resource_availability: 'medium', external_interference: 'medium' } }, { name: 'challenging_conditions', probability: 0.1, conditions: { resource_availability: 'low', external_interference: 'high' } } ], factors: ['resource_availability', 'task_complexity', 'agent_performance', 'external_dependencies'] }; const predictions = await planningEngine.predictFutureStates(predictionRequest); expect(predictions).toBeInstanceOf(Array); predictions.forEach(prediction => { expect(prediction.timestamp).toBeInstanceOf(Date); expect(prediction.state).toBeDefined(); expect(prediction.probability).toBeGreaterThanOrEqual(0); expect(prediction.probability).toBeLessThanOrEqual(1); expect(prediction.confidence).toBeGreaterThanOrEqual(0); expect(prediction.confidence).toBeLessThanOrEqual(1); expect(prediction.influencingFactors).toBeInstanceOf(Array); expect(prediction.influencingFactors).toEqual( expect.arrayContaining(predictionRequest.factors) ); }); // Verify predictions include scenario enhancements const enhancedPredictions = predictions.filter(p => Object.keys(p.state).some(key => key.startsWith('scenario_')) ); expect(enhancedPredictions.length).toBeGreaterThan(0); }); }); describe('Plan Optimization with Constraint Satisfaction', () => { it('should optimize existing plans using constraint satisfaction', async () => { const agentId = 'test-agent-optimization'; // Create a plan to optimize const planResult = await planningEngine.createPlan({ agentId, planName: 'Optimization Test Plan', planType: 'sequential', category: 'task_execution', priority: 'high', timeframe: { startTime: new Date(), endTime: new Date(Date.now() + 6 * 60 * 60 * 1000), flexibility: 0.2, timezone: 'UTC' }, tasks: [ { id: 'opt-task-001', name: 'Initial Task', type: 'atomic', estimatedDuration: 3 * 60 * 60 * 1000, requirements: { skills: ['processing'], resources: [], conditions: {} }, dependencies: [] }, { id: 'opt-task-002', name: 'Follow-up Task', type: 'atomic', estimatedDuration: 2 * 60 * 60 * 1000, requirements: { skills: ['analysis'], resources: [], conditions: {} }, dependencies: [{ predecessorId: 'opt-task-001', type: 'finish_to_start', lag: 0 }] } ], constraints: { deadlines: [], resources: [], quality: { minimumLevel: 0.8, targetLevel: 0.9 } }, objectives: [ { name: 'duration', type: 'minimize', weight: 0.5 }, { name: 'efficiency', type: 'maximize', weight: 0.5 } ] }); // Optimize the plan const optimizationRequest = { planId: planResult.planId, objectives: [ { name: 'duration', type: 'minimize' as const, weight: 0.6, currentValue: 5 * 60 * 60 * 1000, // 5 hours targetValue: 4 * 60 * 60 * 1000 // 4 hours }, { name: 'efficiency', type: 'maximize' as const, weight: 0.4, currentValue: 0.75, targetValue: 0.9 } ], constraints: [ { name: 'max_duration', type: 'hard' as const, expression: 'duration <= 4.5 * 60 * 60 * 1000', penalty: 1000 }, { name: 'min_efficiency', type: 'soft' as const, expression: 'efficiency >= 0.8', penalty: 100 } ], optimizationMethod: 'heuristic' as const }; const optimizationResult = await planningEngine.optimizePlan(optimizationRequest); expect(optimizationResult.optimizationId).toBeDefined(); expect(optimizationResult.improvedObjectives).toBeDefined(); expect(optimizationResult.constraintSatisfaction).toBeDefined(); expect(optimizationResult.optimizationScore).toBeGreaterThanOrEqual(0); expect(optimizationResult.optimizationScore).toBeLessThanOrEqual(1); expect(optimizationResult.recommendedChanges).toBeInstanceOf(Array); // Verify constraint satisfaction Object.values(optimizationResult.constraintSatisfaction).forEach(satisfied => { expect(typeof satisfied).toBe('boolean'); }); // Verify improvements Object.values(optimizationResult.improvedObjectives).forEach(improvement => { expect(typeof improvement).toBe('number'); }); }); }); describe('Plan Analysis and Performance Insights', () => { it('should analyze plan performance and generate comprehensive insights', async () => { const agentId = 'test-agent-analysis'; // Create a plan for analysis const planResult = await planningEngine.createPlan({ agentId, planName: 'Analysis Test Plan', planType: 'conditional', category: 'goal_achievement', priority: 'medium', timeframe: { startTime: new Date(), endTime: new Date(Date.now() + 5 * 60 * 60 * 1000), flexibility: 0.25, timezone: 'UTC' }, tasks: [ { id: 'analysis-task-001', name: 'Data Preparation', type: 'atomic', estimatedDuration: 1.5 * 60 * 60 * 1000, requirements: { skills: ['data_prep'], resources: [], conditions: {} }, dependencies: [] }, { id: 'analysis-task-002', name: 'Analysis Execution', type: 'composite', estimatedDuration: 2.5 * 60 * 60 * 1000, requirements: { skills: ['analysis'], resources: [], conditions: {} }, dependencies: [{ predecessorId: 'analysis-task-001', type: 'finish_to_start', lag: 0 }] } ], constraints: { deadlines: [], resources: [], quality: { minimumLevel: 0.85, targetLevel: 0.95 } }, objectives: [ { name: 'quality', type: 'maximize', weight: 0.7 }, { name: 'efficiency', type: 'maximize', weight: 0.3 } ] }); // Analyze the plan const analytics = await planningEngine.analyzePlan(planResult.planId); expect(analytics.performance).toEqual( expect.objectContaining({ efficiency: expect.any(Number), effectiveness: expect.any(Number), timeliness: expect.any(Number), quality: expect.any(Number) }) ); expect(analytics.predictions).toEqual( expect.objectContaining({ completionProbability: expect.any(Number), estimatedCompletionTime: expect.any(Date), riskFactors: expect.any(Array), successScenarios: expect.any(Array) }) ); expect(analytics.optimization).toEqual( expect.objectContaining({ currentScore: expect.any(Number), potentialImprovement: expect.any(Number), recommendedChanges: expect.any(Array), tradeoffs: expect.any(Array) }) ); expect(analytics.insights).toEqual( expect.objectContaining({ criticalPath: expect.any(Array), bottlenecks: expect.any(Array), resourceUtilization: expect.any(Object), learningOpportunities: expect.any(Array) }) ); // Verify risk factors have proper structure analytics.predictions.riskFactors.forEach(risk => { expect(risk).toEqual( expect.objectContaining({ factor: expect.any(String), impact: expect.any(Number), probability: expect.any(Number) }) ); }); }); }); describe('Plan Progress Tracking and Adaptation', () => { it('should update plan progress and recommend adaptations', async () => { const agentId = 'test-agent-progress'; // Create a plan const planResult = await planningEngine.createPlan({ agentId, planName: 'Progress Tracking Plan', planType: 'sequential', category: 'task_execution', priority: 'high', timeframe: { startTime: new Date(), endTime: new Date(Date.now() + 4 * 60 * 60 * 1000), flexibility: 0.15, timezone: 'UTC' }, tasks: [ { id: 'progress-task-001', name: 'Phase 1', type: 'atomic', estimatedDuration: 2 * 60 * 60 * 1000, requirements: { skills: ['phase1'], resources: [], conditions: {} }, dependencies: [] }, { id: 'progress-task-002', name: 'Phase 2', type: 'atomic', estimatedDuration: 2 * 60 * 60 * 1000, requirements: { skills: ['phase2'], resources: [], conditions: {} }, dependencies: [{ predecessorId: 'progress-task-001', type: 'finish_to_start', lag: 0 }] } ], constraints: { deadlines: [], resources: [], quality: { minimumLevel: 0.8, targetLevel: 0.9 } }, objectives: [ { name: 'duration', type: 'minimize', weight: 1.0 } ] }); // Update progress (simulating being behind schedule) const progressUpdate = { overall: 0.3, // 30% complete taskUpdates: [ { taskId: 'progress-task-001', status: 'in_progress', progress: 0.6, actualDuration: 2.5 * 60 * 60 * 1000 // Taking longer than expected } ], milestoneUpdates: [] }; const updateResult = await planningEngine.updatePlanProgress( planResult.planId, progressUpdate ); expect(updateResult.updated).toBe(true); expect(updateResult.adaptationsRequired).toBe(true); // Should detect being behind expect(updateResult.recommendedAdaptations).toBeInstanceOf(Array); expect(updateResult.recommendedAdaptations.length).toBeGreaterThan(0); expect(updateResult.newPredictions).toBeDefined(); // Verify progress was updated in database const updatedPlans = await planCollection.getAgentPlans(agentId); const updatedPlan = updatedPlans.find(p => p.plan.id === planResult.planId); expect(updatedPlan).toBeDefined(); expect(updatedPlan!.execution.progress.overall).toBe(0.3); }); it('should track active plans for an agent', async () => { const agentId = 'test-agent-active-plans'; // Create multiple plans const planTypes = ['sequential', 'parallel', 'adaptive']; const planIds = []; for (const planType of planTypes) { const result = await planningEngine.createPlan({ agentId, planName: `${planType} Plan`, planType: planType as any, category: 'task_execution', priority: 'medium', timeframe: { startTime: new Date(), endTime: new Date(Date.now() + 3 * 60 * 60 * 1000), flexibility: 0.2, timezone: 'UTC' }, tasks: [ { id: `${planType}-task-001`, name: `${planType} Task`, type: 'atomic', estimatedDuration: 2 * 60 * 60 * 1000, requirements: { skills: [planType], resources: [], conditions: {} }, dependencies: [] } ], constraints: { deadlines: [], resources: [], quality: { minimumLevel: 0.8, targetLevel: 0.9 } }, objectives: [ { name: 'efficiency', type: 'maximize', weight: 1.0 } ] }); planIds.push(result.planId); } // Get active plans const activePlans = await planningEngine.getActivePlans(agentId); expect(activePlans).toHaveLength(3); activePlans.forEach(plan => { expect(plan.planId).toBeDefined(); expect(plan.name).toBeDefined(); expect(plan.status).toBeDefined(); expect(plan.progress).toBeGreaterThanOrEqual(0); expect(plan.estimatedCompletion).toBeInstanceOf(Date); expect(plan.criticalTasks).toBeInstanceOf(Array); }); // Verify plan IDs match const returnedPlanIds = activePlans.map(p => p.planId); planIds.forEach(id => { expect(returnedPlanIds).toContain(id); }); }); }); describe('Error Handling and Edge Cases', () => { it('should handle uninitialized engine gracefully', async () => { const uninitializedEngine = new TemporalPlanningEngine(db); await expect(uninitializedEngine.createPlan({ agentId: 'test', planName: 'Test Plan', planType: 'sequential', category: 'task_execution', priority: 'medium', timeframe: { startTime: new Date(), endTime: new Date(Date.now() + 60 * 60 * 1000), flexibility: 0.1, timezone: 'UTC' }, tasks: [], constraints: { deadlines: [], resources: [], quality: { minimumLevel: 0.8, targetLevel: 0.9 } }, objectives: [] })).rejects.toThrow('TemporalPlanningEngine must be initialized first'); }); it('should handle invalid plan IDs gracefully', async () => { await expect(planningEngine.analyzePlan('non-existent-plan')).rejects.toThrow('Plan not found'); }); }); });