UNPKG

@versatil/sdlc-framework

Version:

🚀 AI-Native SDLC framework with 11-MCP ecosystem, RAG memory, OPERA orchestration, and 6 specialized agents achieving ZERO CONTEXT LOSS. Features complete CI/CD pipeline with 7 GitHub workflows (MCP testing, security scanning, performance benchmarking),

603 lines • 22 kB
/** * VERSATIL SDLC Framework - Enhanced OPERA Integration * Integrates RAG memory and Opera orchestration with existing OPERA agents */ import { EventEmitter } from 'events'; import { AgentRegistry } from '../agents/agent-registry.js'; import { VERSATILLogger } from '../utils/logger.js'; import { vectorMemoryStore } from '../rag/vector-memory-store.js'; import { OperaOrchestrator } from '../opera/opera-orchestrator.js'; import { SDLCOrchestrator } from '../flywheel/sdlc-orchestrator.js'; import { AgentIntelligenceManager } from '../intelligence/agent-intelligence.js'; /** * Enhanced OPERA Coordinator - Integrates all autonomous capabilities */ export class EnhancedOPERACoordinator extends EventEmitter { constructor(config = {}) { super(); this.contexts = new Map(); this.enhancedAgents = new Map(); this.logger = new VERSATILLogger(); this.config = { ragEnabled: true, operaEnabled: true, autonomousMode: true, memoryDepth: 10, contextWindowSize: 5, learningRate: 0.1, ...config }; this.initialize(); } async initialize() { // Initialize core components this.agentRegistry = new AgentRegistry(); this.intelligenceManager = new AgentIntelligenceManager(); this.sdlcOrchestrator = new SDLCOrchestrator(); if (this.config.operaEnabled) { this.operaOrchestrator = new OperaOrchestrator(this.agentRegistry); this.setupOperaIntegration(); } // Enhance all agents with RAG and autonomous capabilities await this.enhanceAgents(); this.logger.info('Enhanced OPERA Coordinator initialized', this.config, 'opera-enhanced'); } /** * Enhance all OPERA agents with RAG and autonomous capabilities */ async enhanceAgents() { const agents = this.agentRegistry.getAllAgents(); for (const agent of agents) { const agentId = agent.id; const enhancedAgent = this.createEnhancedAgent(agent); this.enhancedAgents.set(agentId, enhancedAgent); // Replace in registry this.agentRegistry.registerAgent(agentId, enhancedAgent); } } /** * Create an enhanced version of an agent with RAG and autonomous capabilities */ createEnhancedAgent(originalAgent) { const coordinator = this; const agentId = originalAgent['id']; // Create enhanced proxy return new Proxy(originalAgent, { get(target, prop, receiver) { if (prop === 'activate') { return async (context) => { // Enhanced activation with RAG and context return coordinator.enhancedAgentActivation(target, context); }; } return Reflect.get(target, prop, receiver); } }); } /** * Enhanced agent activation with RAG memory and autonomous capabilities */ async enhancedAgentActivation(agent, context) { const agentId = agent['id']; const startTime = Date.now(); this.logger.info(`Enhanced activation for ${agentId}`, { context }, 'opera-enhanced'); // 1. Query relevant memories if RAG is enabled let relevantMemories = []; if (this.config.ragEnabled && context.filePath) { relevantMemories = await this.queryAgentMemory(agentId, context); // Enrich context with memories context = { ...context, memories: relevantMemories }; } // 2. Get original agent response const originalResponse = await agent.activate(context); // 3. Enhance response with memories and learnings const enhancedResponse = { ...originalResponse, memories: relevantMemories, learnings: [], autonomousActions: [] }; // 4. Store this interaction in memory if (this.config.ragEnabled) { await this.storeAgentInteraction(agentId, context, enhancedResponse); } // 5. Check for autonomous actions if (this.config.autonomousMode && this.config.operaEnabled) { const autonomousActions = await this.checkAutonomousActions(agentId, context, enhancedResponse); if (autonomousActions.length > 0) { enhancedResponse.autonomousActions = autonomousActions; // Queue autonomous goals for (const action of autonomousActions) { await this.queueAutonomousGoal(action, agentId); } } } // 6. Learn from this interaction const learnings = await this.learnFromInteraction(agentId, context, enhancedResponse, Date.now() - startTime); enhancedResponse.learnings = learnings; // 7. Emit enhanced activation event this.emit('enhanced_activation', { agentId, context, response: enhancedResponse, executionTime: Date.now() - startTime }); return enhancedResponse; } /** * Query agent-specific memories using RAG */ async queryAgentMemory(agentId, context) { // Build query from context let queryText = ''; if (context.filePath) { queryText += `file:${context.filePath} `; } if (context.errorMessage) { queryText += `error:"${context.errorMessage}" `; } if (context.userRequest) { queryText += context.userRequest; } // Query memories const query = { query: queryText.trim(), agentId, topK: this.config.memoryDepth, filters: { tags: [] } }; // Add file type filter if (context.filePath) { const fileType = this.getFileType(context.filePath); if (fileType) { query.filters.fileTypes = [fileType]; } } const results = await vectorMemoryStore.queryMemories(arguments[0]); // Parse and return relevant memories return results.documents.map(doc => { try { const memory = JSON.parse(doc.content); return { ...memory, relevanceScore: doc.metadata.relevanceScore }; } catch { return { content: doc.content, relevanceScore: doc.metadata.relevanceScore }; } }); } /** * Store agent interaction in vector memory */ async storeAgentInteraction(agentId, context, response) { const interaction = { agentId, timestamp: Date.now(), context: { filePath: context.filePath, errorMessage: context.errorMessage, userRequest: context.userRequest, contextClarity: context.contextClarity, urgency: context.urgency }, response: { message: response.message, priority: response.priority, suggestionCount: response.suggestions.length, handoffAgents: response.handoffTo } }; // Determine tags const tags = [agentId, 'interaction']; if (context.filePath) { const fileType = this.getFileType(context.filePath); if (fileType) tags.push(fileType); } if (response.priority === 'critical' || response.priority === 'high') { tags.push('important'); } if (context.emergency) { tags.push('emergency'); } // Store in vector memory await vectorMemoryStore.storeMemory({ content: JSON.stringify(interaction), metadata: { agentId, timestamp: Date.now(), fileType: context.filePath ? this.getFileType(context.filePath) : undefined, tags } }); } /** * Check for autonomous actions based on agent response */ async checkAutonomousActions(agentId, context, response) { const autonomousActions = []; // Check for critical issues requiring immediate action if (response.priority === 'critical' || context.emergency) { autonomousActions.push({ type: 'emergency_response', reason: 'Critical issue detected', suggestedAction: 'Immediate investigation and resolution', agents: [agentId, ...response.handoffTo] }); } // Check for handoff requests if (response.handoffTo.length > 0) { autonomousActions.push({ type: 'agent_coordination', reason: 'Multi-agent collaboration needed', suggestedAction: 'Coordinate with recommended agents', agents: response.handoffTo }); } // Check for patterns requiring proactive action const patterns = await this.detectActionablePatterns(agentId, context, response); for (const pattern of patterns) { autonomousActions.push({ type: 'pattern_response', reason: pattern.description, suggestedAction: pattern.action, confidence: pattern.confidence }); } return autonomousActions; } /** * Queue autonomous goal for Opera execution */ async queueAutonomousGoal(action, agentId) { if (!this.operaOrchestrator) return; const goal = { id: this.generateId('goal'), type: this.mapActionToGoalType(action.type), description: `${action.reason}: ${action.suggestedAction}`, priority: this.determinePriority(action), status: 'pending', constraints: [], successCriteria: [`${action.type} completed successfully`] }; await this.operaOrchestrator.addGoal(goal); this.logger.info('Autonomous goal queued', { goal, action, agentId }, 'opera-enhanced'); } /** * Learn from interaction and update agent behavior */ async learnFromInteraction(agentId, context, response, executionTime) { const learnings = []; // Track execution time patterns if (executionTime > 5000) { // Slow execution learnings.push({ type: 'performance', observation: 'Slow execution detected', recommendation: 'Optimize query or cache results', metric: executionTime }); } // Track memory effectiveness if (response.memories && response.memories.length > 0) { const avgRelevance = response.memories.reduce((sum, m) => sum + (m.relevanceScore || 0), 0) / response.memories.length; if (avgRelevance < 0.5) { learnings.push({ type: 'memory_quality', observation: 'Low relevance memories retrieved', recommendation: 'Improve memory tagging or embedding quality', metric: avgRelevance }); } } // Track suggestion patterns if (response.suggestions.length > 5) { learnings.push({ type: 'suggestion_overload', observation: 'Many suggestions provided', recommendation: 'Prioritize and filter suggestions', count: response.suggestions.length }); } // Store learnings if (learnings.length > 0) { await vectorMemoryStore.storeMemory({ content: JSON.stringify({ agentId, learnings, context, response }), metadata: { agentId: 'opera-enhanced', timestamp: Date.now(), tags: ['learning', agentId, 'performance'] } }); } return learnings; } /** * Detect actionable patterns from agent interactions */ async detectActionablePatterns(agentId, context, response) { const patterns = []; // Query recent similar interactions const query = { query: `${agentId} ${context.filePath || ''} pattern`, topK: 5, filters: { timeRange: { start: Date.now() - (24 * 60 * 60 * 1000), // Last 24 hours end: Date.now() } } }; const recentInteractions = await vectorMemoryStore.queryMemories(arguments[0]); // Simple pattern detection - repeated issues if (recentInteractions.documents.length >= 3) { const commonIssues = this.findCommonIssues(recentInteractions.documents); for (const issue of commonIssues) { patterns.push({ description: `Recurring issue: ${issue.type}`, action: 'Implement permanent fix or automation', confidence: issue.frequency / recentInteractions.documents.length }); } } return patterns; } /** * Find common issues in memories */ findCommonIssues(memories) { const issueMap = new Map(); for (const memory of memories) { try { const content = JSON.parse(memory.content); if (content.context?.errorMessage) { const key = this.normalizeError(content.context.errorMessage); issueMap.set(key, (issueMap.get(key) || 0) + 1); } } catch { // Ignore parsing errors } } return Array.from(issueMap.entries()) .filter(([_, count]) => count >= 2) .map(([type, frequency]) => ({ type, frequency })); } /** * Setup Opera integration */ setupOperaIntegration() { // Listen to Opera events this.operaOrchestrator.on('goal_completed', ({ goal, decision }) => { this.logger.info('Opera goal completed', { goal, decision }, 'opera-enhanced'); this.emit('autonomous_goal_completed', { goal, decision }); }); this.operaOrchestrator.on('goal_failed', ({ goal, decision }) => { this.logger.warn('Opera goal failed', { goal, decision }, 'opera-enhanced'); this.emit('autonomous_goal_failed', { goal, decision }); }); this.operaOrchestrator.on('human_intervention_required', ({ step, error }) => { this.logger.warn('Human intervention required', { step, error }, 'opera-enhanced'); this.emit('human_intervention_required', { step, error }); }); } /** * Create a new OPERA context for a project */ async createContext(projectId) { const context = { projectId, phase: 'initialization', activeAgents: [], memory: [], goals: [], decisions: [] }; this.contexts.set(projectId, context); // Initialize project memory await vectorMemoryStore.storeMemory({ content: JSON.stringify({ projectId, action: 'context_created' }), metadata: { agentId: 'opera-enhanced', timestamp: Date.now(), projectContext: projectId, tags: ['project', 'initialization'] } }); this.emit('context_created', context); return context; } /** * Get or create context for a project */ async getContext(projectId) { let context = this.contexts.get(projectId); if (!context) { context = await this.createContext(projectId); } return context; } /** * Update context phase */ async updateContextPhase(projectId, phase) { const context = await this.getContext(projectId); context.phase = phase; // Store phase transition await vectorMemoryStore.storeMemory({ content: JSON.stringify({ projectId, phase, previousPhase: context.phase }), metadata: { agentId: 'opera-enhanced', timestamp: Date.now(), projectContext: projectId, tags: ['project', 'phase-transition', phase] } }); this.emit('phase_updated', { projectId, phase }); } /** * Execute OPERA workflow for a project */ async executeOPERAWorkflow(projectId, requirements) { const context = await this.getContext(projectId); // Create initial goal const goal = { id: this.generateId('workflow'), type: 'feature', description: requirements, priority: 'high', status: 'pending', constraints: ['Follow OPERA methodology', 'Maintain zero context loss'], successCriteria: [ 'Requirements analyzed', 'Architecture designed', 'Implementation completed', 'Tests passing', 'Documentation updated' ], }; context.goals.push(goal); // Queue for autonomous execution if (this.operaOrchestrator) { await this.operaOrchestrator.addGoal(goal); } this.emit('workflow_started', { projectId, goal }); } /** * Helper methods */ getFileType(filePath) { const extension = filePath.split('.').pop()?.toLowerCase(); const typeMap = { 'js': 'javascript', 'jsx': 'react', 'ts': 'typescript', 'tsx': 'react', 'py': 'python', 'java': 'java', 'css': 'css', 'scss': 'scss', 'html': 'html', 'json': 'json', 'yml': 'yaml', 'yaml': 'yaml', 'md': 'markdown' }; return typeMap[extension || ''] || 'unknown'; } normalizeError(error) { // Simple error normalization return error.toLowerCase() .replace(/line \d+/g, 'line X') .replace(/column \d+/g, 'column X') .replace(/\d+/g, 'N') .trim(); } mapActionToGoalType(actionType) { const mapping = { 'emergency_response': 'bug_fix', 'agent_coordination': 'feature', 'pattern_response': 'optimization' }; return mapping[actionType] || 'feature'; } determinePriority(action) { if (action.type === 'emergency_response') return 'critical'; if (action.confidence && action.confidence > 0.8) return 'high'; return 'medium'; } generateId(prefix) { return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } /** * Public API */ /** * Get enhanced agent by ID */ getEnhancedAgent(agentId) { return this.enhancedAgents.get(agentId); } /** * Enable/disable RAG */ setRAGEnabled(enabled) { this.config.ragEnabled = enabled; this.emit('config_updated', { ragEnabled: enabled }); } /** * Enable/disable autonomous mode */ setAutonomousMode(enabled) { this.config.autonomousMode = enabled; if (this.operaOrchestrator) { if (enabled) { this.operaOrchestrator.resumeAutonomous(); } else { this.operaOrchestrator.pauseAutonomous(); } } this.emit('config_updated', { autonomousMode: enabled }); } /** * Get performance metrics */ async getPerformanceMetrics() { const metrics = { contexts: this.contexts.size, enhancedAgents: this.enhancedAgents.size, ragEnabled: this.config.ragEnabled, operaEnabled: this.config.operaEnabled, autonomousMode: this.config.autonomousMode }; if (this.operaOrchestrator) { const operaState = await this.operaOrchestrator.getState(); metrics['operaMetrics'] = { activeGoals: operaState.currentGoals.length, activeDecisions: operaState.activeDecisions.length, queuedSteps: operaState.executionQueue.length, performance: operaState.performance }; } // Query memory statistics const memoryStats = await this.getMemoryStatistics(); metrics['memoryStats'] = memoryStats; return metrics; } /** * Get memory statistics */ async getMemoryStatistics() { // Query total memories per agent const agentStats = {}; for (const agentId of this.enhancedAgents.keys()) { const query = { query: '', agentId, topK: 1000 // Get count }; const results = await vectorMemoryStore.queryMemories(arguments[0]); agentStats[agentId] = results.documents.length; } return { totalMemories: Object.values(agentStats).reduce((sum, count) => sum + count, 0), agentBreakdown: agentStats }; } } // Export singleton instance export const enhancedOPERA = new EnhancedOPERACoordinator(); //# sourceMappingURL=enhanced-opera-coordinator.js.map