@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),
389 lines • 16.6 kB
JavaScript
/**
* VERSATIL SDLC Framework - RAG-Enabled Agent Base Class
*
* Extends BaseAgent with direct RAG capabilities, allowing each agent to:
* - Retrieve domain-specific context from vector memory
* - Store successful patterns for future learning
* - Generate context-aware prompts with historical knowledge
*/
import { BaseAgent } from './base-agent.js';
export class RAGEnabledAgent extends BaseAgent {
constructor(vectorStore) {
super();
this.vectorStore = vectorStore;
this.ragConfig = this.getDefaultRAGConfig();
}
/**
* Main analysis method with RAG enhancement
*/
async activate(context) {
// Level 1: Standard pattern analysis
const patternAnalysis = await this.runPatternAnalysis(context);
// Level 2: RAG enhancement (if vector store available)
let ragContext;
if (this.vectorStore) {
ragContext = await this.retrieveRelevantContext(context, patternAnalysis);
}
// Level 3: Generate enhanced response
const enhancedResponse = await this.generateRAGEnhancedResponse(context, patternAnalysis, ragContext);
// Level 4: Store successful patterns for learning
if (this.vectorStore && this.ragConfig.enableLearning) {
await this.storeNewPatterns(context, patternAnalysis, enhancedResponse);
}
return enhancedResponse;
}
/**
* Retrieve relevant context from vector memory
*/
async retrieveRelevantContext(context, analysis) {
if (!this.vectorStore) {
return this.getEmptyRAGContext();
}
const retrievals = {
similarCode: [],
previousSolutions: {},
projectStandards: [],
agentExpertise: []
};
try {
// 1. Find similar code patterns for this agent's domain
retrievals.similarCode = await this.retrieveSimilarCodePatterns(context);
// 2. Find previous solutions for similar issues
retrievals.previousSolutions = await this.retrievePreviousSolutions(analysis);
// 3. Get project-specific standards for this domain
retrievals.projectStandards = await this.retrieveProjectStandards(context);
// 4. Get agent-specific expertise
retrievals.agentExpertise = await this.retrieveAgentExpertise(context);
}
catch (error) {
console.warn(`RAG retrieval failed for ${this.id}:`, error.message);
}
return retrievals;
}
/**
* Retrieve similar code patterns based on content and domain
*/
async retrieveSimilarCodePatterns(context) {
if (!this.vectorStore)
return [];
const query = {
query: this.createSemanticQuery(context.content, context.filePath),
queryType: 'semantic',
agentId: this.id,
topK: this.ragConfig.maxExamples,
filters: {
tags: [this.ragConfig.agentDomain, 'pattern', this.detectLanguage(context.filePath)],
contentTypes: ['code']
}
};
const result = await this.vectorStore.queryMemories(query);
return result.documents || [];
}
/**
* Retrieve previous solutions for similar issues
*/
async retrievePreviousSolutions(analysis) {
if (!this.vectorStore)
return {};
const solutions = {};
for (const issue of analysis.patterns) {
const query = {
query: `${issue.type} ${issue.message}`,
queryType: 'semantic',
agentId: this.id,
topK: 2,
filters: {
tags: [issue.type, 'solution', this.ragConfig.agentDomain],
contentTypes: ['text', 'code']
}
};
try {
const result = await this.vectorStore.queryMemories(query);
solutions[issue.type] = result.documents || [];
}
catch (error) {
console.warn(`Failed to retrieve solutions for ${issue.type}:`, error.message);
solutions[issue.type] = [];
}
}
return solutions;
}
/**
* Retrieve project standards specific to this agent's domain
*/
async retrieveProjectStandards(context) {
if (!this.vectorStore)
return [];
const query = {
query: `${context.filePath} ${this.ragConfig.agentDomain} standards conventions`,
queryType: 'semantic',
agentId: this.id,
topK: 3,
filters: {
tags: [this.ragConfig.agentDomain, 'standard', 'convention'],
contentTypes: ['text']
}
};
const result = await this.vectorStore.queryMemories(query);
return result.documents || [];
}
/**
* Retrieve agent-specific expertise and insights
*/
async retrieveAgentExpertise(context) {
if (!this.vectorStore)
return [];
const query = {
query: this.createSemanticQuery(context.content, context.filePath),
queryType: 'semantic',
agentId: this.id,
topK: 3,
filters: {
tags: [this.id, 'expertise', this.ragConfig.agentDomain],
contentTypes: ['text', 'code']
}
};
const result = await this.vectorStore.queryMemories(query);
return result.documents || [];
}
/**
* Generate enhanced response with RAG context
*/
async generateRAGEnhancedResponse(context, analysis, ragContext) {
// Convert analysis to suggestions
const suggestions = analysis.patterns.map(p => ({
type: p.type,
description: p.message,
location: `${context.filePath}:${p.line}`,
priority: p.severity,
action: p.suggestion
}));
// Enhance suggestions with RAG context
if (ragContext) {
this.enhanceSuggestionsWithRAG(suggestions, ragContext);
}
// Generate domain-specific handoffs
const handoffTo = this.generateDomainHandoffs(analysis);
// Create enhanced message with RAG insights
const message = this.generateEnhancedMessage(analysis, ragContext);
return {
agentId: this.id,
message,
suggestions,
priority: this.calculatePriorityWithRAG(analysis, ragContext),
handoffTo,
context: {
analysisScore: analysis.score,
totalIssues: analysis.patterns.length,
criticalIssues: analysis.patterns.filter(p => p.severity === 'critical').length,
ragEnhanced: !!ragContext,
ragInsights: ragContext ? this.summarizeRAGInsights(ragContext) : undefined,
generatedPrompt: this.generateRAGEnhancedPrompt(context, analysis, ragContext),
recommendations: analysis.recommendations,
summary: analysis.summary
}
};
}
/**
* Generate RAG-enhanced prompt with retrieved context
*/
generateRAGEnhancedPrompt(context, analysis, ragContext) {
let prompt = this.getBasePromptTemplate();
if (ragContext) {
prompt += '\n## Retrieved Context\n\n';
// Similar Code Patterns
if (ragContext.similarCode.length > 0) {
prompt += '### Similar Code Patterns From This Project:\n';
ragContext.similarCode.forEach((pattern, index) => {
const tags = pattern.metadata?.tags?.join(', ') || 'N/A';
const score = Math.round((pattern.metadata?.relevanceScore || 0) * 100);
prompt += `Example ${index + 1} (${score}% relevance, tags: ${tags}):\n`;
prompt += '```\n' + pattern.content.slice(0, 200) + '...\n```\n\n';
});
}
// Previous Solutions
const solutionEntries = Object.entries(ragContext.previousSolutions).filter(([_, solutions]) => solutions.length > 0);
if (solutionEntries.length > 0) {
prompt += '### Previous Solutions for Similar Issues:\n';
solutionEntries.forEach(([issueType, solutions]) => {
prompt += `For ${issueType}:\n`;
solutions.forEach(solution => {
prompt += `- ${solution.content.slice(0, 150)}...\n`;
});
prompt += '\n';
});
}
// Project Standards
if (ragContext.projectStandards.length > 0) {
prompt += '### Project Standards:\n';
ragContext.projectStandards.forEach(standard => {
prompt += `- ${standard.content.slice(0, 100)}...\n`;
});
prompt += '\n';
}
}
// Current context
prompt += '## Current Context\n';
prompt += `File: ${context.filePath}\n`;
prompt += `Issues Found: ${JSON.stringify(analysis.patterns.map(p => ({ type: p.type, severity: p.severity, message: p.message })), null, 2)}\n\n`;
// Code to analyze
prompt += `## Code to Analyze\n`;
prompt += '```' + this.detectLanguage(context.filePath) + '\n';
prompt += context.content + '\n';
prompt += '```\n\n';
prompt += 'Using the retrieved context above as reference, provide your analysis and recommendations.\n';
return prompt;
}
/**
* Store successful patterns for future learning
*/
async storeNewPatterns(context, analysis, response) {
if (!this.vectorStore)
return;
try {
const language = this.detectLanguage(context.filePath);
// Store high-quality code patterns (score >= 80)
if (analysis.score >= 80) {
const patternDoc = {
id: `pattern_${this.id}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
content: context.content,
contentType: 'code',
metadata: {
agentId: this.id,
timestamp: Date.now(),
fileType: context.filePath.split('.').pop() || '',
projectContext: 'VERSATIL Framework',
tags: [language, this.ragConfig.agentDomain, 'pattern', 'high-quality'],
relevanceScore: analysis.score / 100,
language,
framework: this.detectFramework(context.content)
}
};
await this.vectorStore.storeMemory(patternDoc);
}
// Store successful solutions for detected issues
for (const suggestion of response.suggestions) {
if (suggestion.priority !== 'low') {
const solutionDoc = {
id: `solution_${this.id}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
content: suggestion.action,
contentType: 'text',
metadata: {
agentId: this.id,
timestamp: Date.now(),
projectContext: 'VERSATIL Framework',
tags: [language, this.ragConfig.agentDomain, suggestion.type, 'solution'],
relevanceScore: suggestion.priority === 'critical' ? 1.0 : suggestion.priority === 'high' ? 0.8 : 0.6,
language
}
};
await this.vectorStore.storeMemory(solutionDoc);
}
}
}
catch (error) {
console.warn(`Failed to store patterns for ${this.id}:`, error.message);
}
}
// Helper methods
getEmptyRAGContext() {
return {
similarCode: [],
previousSolutions: {},
projectStandards: [],
agentExpertise: []
};
}
createSemanticQuery(content, filePath) {
// Extract key concepts and create semantic query
const lines = content.split('\n');
const keywords = [];
// Extract function/class names
const functionMatches = content.match(/(?:function|class|const|let|var)\s+(\w+)/g);
if (functionMatches) {
keywords.push(...functionMatches.map(match => match.split(/\s+/)[1]));
}
// Add file path context
const pathParts = filePath.split('/').filter(part => part && !part.includes('.'));
keywords.push(...pathParts);
// Create concise semantic query
const uniqueKeywords = [...new Set(keywords)].filter(k => k && k.length > 2).slice(0, 8);
return uniqueKeywords.join(' ') || content.slice(0, 150);
}
detectLanguage(filePath) {
const ext = filePath.split('.').pop()?.toLowerCase() || '';
const langMap = {
'js': 'javascript', 'jsx': 'javascriptreact',
'ts': 'typescript', 'tsx': 'typescriptreact',
'py': 'python', 'vue': 'vue', 'svelte': 'svelte'
};
return langMap[ext] || 'plaintext';
}
detectFramework(content) {
if (content.includes('react') || content.includes('useState'))
return 'react';
if (content.includes('vue') || content.includes('Vue'))
return 'vue';
if (content.includes('angular'))
return 'angular';
if (content.includes('express') || content.includes('app.get'))
return 'express';
return '';
}
enhanceSuggestionsWithRAG(suggestions, ragContext) {
// Add RAG-derived suggestions
if (ragContext.similarCode.length > 0) {
suggestions.push({
type: 'rag-pattern',
description: `Found ${ragContext.similarCode.length} similar patterns in project history`,
location: 'RAG Context',
priority: 'info',
action: 'Review similar implementations for consistency and best practices'
});
}
}
generateEnhancedMessage(analysis, ragContext) {
let message = `${this.ragConfig.agentDomain} Analysis Complete: Score ${analysis.score}/100. ${analysis.patterns.length} issues found.`;
if (ragContext) {
const ragInsights = [];
if (ragContext.similarCode.length > 0)
ragInsights.push(`${ragContext.similarCode.length} similar patterns`);
if (Object.keys(ragContext.previousSolutions).length > 0)
ragInsights.push(`solutions for ${Object.keys(ragContext.previousSolutions).length} issue types`);
if (ragContext.projectStandards.length > 0)
ragInsights.push(`${ragContext.projectStandards.length} project standards`);
if (ragInsights.length > 0) {
message += ` RAG-Enhanced: ${ragInsights.join(', ')}.`;
}
}
return message;
}
summarizeRAGInsights(ragContext) {
return {
similarPatterns: ragContext.similarCode.length,
solutionTypes: Object.keys(ragContext.previousSolutions).length,
projectStandards: ragContext.projectStandards.length,
expertise: ragContext.agentExpertise.length
};
}
calculatePriorityWithRAG(analysis, ragContext) {
// Check for critical severity issues first
const hasCritical = analysis.patterns.some(p => p.severity === 'critical');
if (hasCritical)
return 'critical';
const hasHigh = analysis.patterns.some(p => p.severity === 'high');
if (hasHigh)
return 'high';
// Fall back to score-based priority
let basePriority = analysis.score < 60 ? 'high' : analysis.score < 80 ? 'medium' : 'low';
// Boost priority if RAG context shows this is a recurring issue
if (ragContext && Object.keys(ragContext.previousSolutions).length > 2) {
if (basePriority === 'low')
basePriority = 'medium';
if (basePriority === 'medium')
basePriority = 'high';
}
return basePriority;
}
}
//# sourceMappingURL=rag-enabled-agent.js.map