enhanced-manager.ts•18.4 kB
/**
* Enhanced Memory Manager with Learning and Knowledge Graph Integration
* Combines Issues #47 and #48 for intelligent memory management
*/
import { MemoryManager } from "./manager.js";
import { MemoryEntry } from "./storage.js";
import IncrementalLearningSystem, {
ProjectFeatures,
LearningInsight,
} from "./learning.js";
import KnowledgeGraph, { RecommendationPath } from "./knowledge-graph.js";
export interface EnhancedRecommendation {
baseRecommendation: any;
learningEnhanced: any;
graphBased: RecommendationPath[];
insights: LearningInsight[];
confidence: number;
reasoning: string[];
metadata: {
usedLearning: boolean;
usedKnowledgeGraph: boolean;
patternsFound: number;
similarProjects: number;
};
}
export interface IntelligentAnalysis {
analysis: any;
patterns: string[];
predictions: Array<{
type: "success_rate" | "optimal_ssg" | "potential_issues";
prediction: string;
confidence: number;
}>;
recommendations: string[];
learningData: {
similarProjects: number;
confidenceLevel: number;
dataQuality: "low" | "medium" | "high";
};
}
export class EnhancedMemoryManager extends MemoryManager {
private learningSystem: IncrementalLearningSystem;
private knowledgeGraph: KnowledgeGraph;
private initialized: boolean = false;
constructor(storageDir?: string) {
super(storageDir);
this.learningSystem = new IncrementalLearningSystem(this);
this.knowledgeGraph = new KnowledgeGraph(this);
}
async initialize(): Promise<void> {
await super.initialize();
if (!this.initialized) {
await this.learningSystem.initialize();
await this.knowledgeGraph.initialize();
this.initialized = true;
// Set up automatic learning from new memories
this.on("memory-created", this.handleNewMemory.bind(this));
}
}
/**
* Enhanced recommendation that combines base analysis with learning and graph intelligence
*/
async getEnhancedRecommendation(
projectPath: string,
baseRecommendation: any,
projectFeatures: ProjectFeatures,
): Promise<EnhancedRecommendation> {
await this.initialize();
// Get learning-enhanced recommendation
const learningResult = await this.learningSystem.getImprovedRecommendation(
projectFeatures,
baseRecommendation,
);
// Get knowledge graph-based recommendations
const candidateSSGs = this.extractCandidateSSGs(baseRecommendation);
const graphRecommendations =
await this.knowledgeGraph.getGraphBasedRecommendation(
projectFeatures,
candidateSSGs,
);
// Combine insights and reasoning
const allInsights = [...learningResult.insights];
const reasoning: string[] = [];
// Add graph-based reasoning
if (graphRecommendations.length > 0) {
const topRecommendation = graphRecommendations[0];
reasoning.push(...topRecommendation.reasoning);
allInsights.push({
type: "recommendation",
message: `Knowledge graph analysis suggests ${topRecommendation.to.label} based on similar successful projects`,
confidence: topRecommendation.confidence,
actionable: true,
data: { graphPath: topRecommendation.path },
});
}
// Calculate combined confidence
const combinedConfidence = this.calculateCombinedConfidence(
baseRecommendation.confidence,
learningResult.confidence,
graphRecommendations[0]?.confidence || 0,
);
// Determine final recommendation
const finalRecommendation = learningResult.recommendation;
if (
graphRecommendations.length > 0 &&
graphRecommendations[0].confidence > 0.8
) {
const graphChoice = graphRecommendations[0].to.label;
if (graphChoice !== finalRecommendation.recommended) {
finalRecommendation.graphSuggestion = graphChoice;
finalRecommendation.conflictDetected = true;
reasoning.push(
`Knowledge graph suggests ${graphChoice} while learning system suggests ${finalRecommendation.recommended}`,
);
}
}
return {
baseRecommendation,
learningEnhanced: learningResult.recommendation,
graphBased: graphRecommendations,
insights: allInsights,
confidence: combinedConfidence,
reasoning,
metadata: {
usedLearning: learningResult.insights.length > 0,
usedKnowledgeGraph: graphRecommendations.length > 0,
patternsFound: await this.countRelevantPatterns(projectFeatures),
similarProjects: graphRecommendations.length,
},
};
}
/**
* Enhanced analysis that provides intelligent insights
*/
async getIntelligentAnalysis(
projectPath: string,
baseAnalysis: any,
): Promise<IntelligentAnalysis> {
await this.initialize();
const projectFeatures = this.extractProjectFeatures(baseAnalysis);
// Find patterns from similar projects
const patterns = await this.findProjectPatterns(projectFeatures);
// Generate predictions
const predictions = await this.generatePredictions(
projectFeatures,
patterns,
);
// Generate recommendations
const recommendations = await this.generateIntelligentRecommendations(
projectFeatures,
patterns,
predictions,
);
// Assess learning data quality
const learningData = await this.assessLearningData(projectFeatures);
return {
analysis: baseAnalysis,
patterns: patterns.map((p) => p.description),
predictions,
recommendations,
learningData,
};
}
/**
* Learn from new memory entries automatically
*/
private async handleNewMemory(memory: MemoryEntry): Promise<void> {
try {
// Determine outcome for learning
const outcome = this.inferOutcome(memory);
if (outcome) {
await this.learningSystem.learn(memory, outcome);
}
// Update knowledge graph
await this.knowledgeGraph.buildFromMemories();
// Periodically save graph to persistent storage
if (Math.random() < 0.1) {
// 10% chance to save
await this.knowledgeGraph.saveToMemory();
}
} catch (error) {
console.error("Error in automatic learning:", error);
}
}
/**
* Extract project features from analysis data
*/
private extractProjectFeatures(analysis: any): ProjectFeatures {
return {
language: analysis.language?.primary || "unknown",
framework: analysis.framework?.name,
size: this.categorizeProjectSize(analysis.stats?.files || 0),
complexity: this.categorizeProjectComplexity(analysis),
hasTests: Boolean(analysis.testing?.hasTests),
hasCI: Boolean(analysis.ci?.hasCI),
hasDocs: Boolean(analysis.documentation?.exists),
teamSize: analysis.team?.size,
isOpenSource: Boolean(analysis.repository?.isPublic),
};
}
private categorizeProjectSize(
fileCount: number,
): "small" | "medium" | "large" {
if (fileCount < 50) return "small";
if (fileCount < 200) return "medium";
return "large";
}
private categorizeProjectComplexity(
analysis: any,
): "simple" | "moderate" | "complex" {
let complexity = 0;
if (analysis.dependencies?.count > 20) complexity++;
if (analysis.framework?.name) complexity++;
if (analysis.testing?.frameworks?.length > 1) complexity++;
if (analysis.ci?.workflows?.length > 2) complexity++;
if (analysis.architecture?.patterns?.length > 3) complexity++;
if (complexity <= 1) return "simple";
if (complexity <= 3) return "moderate";
return "complex";
}
/**
* Extract candidate SSGs from base recommendation
*/
private extractCandidateSSGs(baseRecommendation: any): string[] {
const candidates = [baseRecommendation.recommended];
if (baseRecommendation.alternatives) {
candidates.push(
...baseRecommendation.alternatives.map((alt: any) => alt.name || alt),
);
}
return [...new Set(candidates)].filter(Boolean);
}
/**
* Calculate combined confidence from multiple sources
*/
private calculateCombinedConfidence(
baseConfidence: number,
learningConfidence: number,
graphConfidence: number,
): number {
// Weighted average with emphasis on learning and graph data when available
const weights = {
base: 0.4,
learning: learningConfidence > 0 ? 0.4 : 0,
graph: graphConfidence > 0 ? 0.2 : 0,
};
// Redistribute weights if some sources are unavailable
const totalWeight = weights.base + weights.learning + weights.graph;
const normalizedWeights = {
base: weights.base / totalWeight,
learning: weights.learning / totalWeight,
graph: weights.graph / totalWeight,
};
return (
baseConfidence * normalizedWeights.base +
learningConfidence * normalizedWeights.learning +
graphConfidence * normalizedWeights.graph
);
}
/**
* Count patterns relevant to project features
*/
private async countRelevantPatterns(
features: ProjectFeatures,
): Promise<number> {
const tags = [features.language, features.framework, features.size].filter(
(tag): tag is string => Boolean(tag),
);
const memories = await this.search({
tags,
});
return memories.length;
}
/**
* Find patterns from similar projects
*/
private async findProjectPatterns(features: ProjectFeatures): Promise<
Array<{
type: string;
description: string;
confidence: number;
frequency: number;
}>
> {
const patterns: Array<{
type: string;
description: string;
confidence: number;
frequency: number;
}> = [];
// Find similar projects based on features
const similarMemories = await this.search({
tags: [features.language],
});
if (similarMemories.length >= 3) {
// Pattern: Most common SSG for this language
const ssgCounts = new Map<string, number>();
for (const memory of similarMemories) {
if (memory.metadata.ssg) {
ssgCounts.set(
memory.metadata.ssg,
(ssgCounts.get(memory.metadata.ssg) || 0) + 1,
);
}
}
if (ssgCounts.size > 0) {
const topSSG = Array.from(ssgCounts.entries()).sort(
([, a], [, b]) => b - a,
)[0];
patterns.push({
type: "ssg_preference",
description: `${topSSG[0]} is commonly used with ${features.language} (${topSSG[1]}/${similarMemories.length} projects)`,
confidence: topSSG[1] / similarMemories.length,
frequency: topSSG[1],
});
}
// Pattern: Success rate analysis
const deploymentMemories = similarMemories.filter(
(m) => m.type === "deployment",
);
if (deploymentMemories.length >= 2) {
const successRate =
deploymentMemories.filter((m) => m.data.status === "success").length /
deploymentMemories.length;
patterns.push({
type: "success_rate",
description: `Similar ${features.language} projects have ${(
successRate * 100
).toFixed(0)}% deployment success rate`,
confidence: Math.min(deploymentMemories.length / 10, 1.0),
frequency: deploymentMemories.length,
});
}
}
return patterns;
}
/**
* Generate predictions based on patterns and features
*/
private async generatePredictions(
features: ProjectFeatures,
patterns: Array<{ type: string; description: string; confidence: number }>,
): Promise<
Array<{
type: "success_rate" | "optimal_ssg" | "potential_issues";
prediction: string;
confidence: number;
}>
> {
const predictions: Array<{
type: "success_rate" | "optimal_ssg" | "potential_issues";
prediction: string;
confidence: number;
}> = [];
// Predict success rate
const successPattern = patterns.find((p) => p.type === "success_rate");
if (successPattern) {
predictions.push({
type: "success_rate",
prediction: `Expected deployment success rate: ${
successPattern.description.match(/(\d+)%/)?.[1] || "unknown"
}%`,
confidence: successPattern.confidence,
});
}
// Predict optimal SSG
const ssgPattern = patterns.find((p) => p.type === "ssg_preference");
if (ssgPattern) {
const ssg = ssgPattern.description.split(" ")[0];
predictions.push({
type: "optimal_ssg",
prediction: `${ssg} is likely the optimal choice based on similar projects`,
confidence: ssgPattern.confidence,
});
}
// Predict potential issues
if (!features.hasTests && features.size !== "small") {
predictions.push({
type: "potential_issues",
prediction:
"Deployment issues likely due to lack of tests in medium/large project",
confidence: 0.7,
});
}
if (!features.hasCI && features.complexity === "complex") {
predictions.push({
type: "potential_issues",
prediction:
"Complex project without CI/CD may face integration challenges",
confidence: 0.6,
});
}
return predictions;
}
/**
* Generate intelligent recommendations
*/
private async generateIntelligentRecommendations(
features: ProjectFeatures,
patterns: Array<{ type: string; description: string; confidence: number }>,
predictions: Array<{
type: string;
prediction: string;
confidence: number;
}>,
): Promise<string[]> {
const recommendations: string[] = [];
// Recommendations based on patterns
const ssgPattern = patterns.find((p) => p.type === "ssg_preference");
if (ssgPattern && ssgPattern.confidence > 0.7) {
const ssg = ssgPattern.description.split(" ")[0];
recommendations.push(
`Consider ${ssg} - it's proven successful for similar ${features.language} projects`,
);
}
// Recommendations based on predictions
const issuesPrediction = predictions.find(
(p) => p.type === "potential_issues",
);
if (issuesPrediction && issuesPrediction.confidence > 0.6) {
if (issuesPrediction.prediction.includes("tests")) {
recommendations.push(
"Set up automated testing before deployment to improve success rate",
);
}
if (issuesPrediction.prediction.includes("CI/CD")) {
recommendations.push(
"Implement CI/CD pipeline to handle project complexity",
);
}
}
// Recommendations based on features
if (features.complexity === "complex" && !features.hasDocs) {
recommendations.push(
"Invest in comprehensive documentation for this complex project",
);
}
if (features.isOpenSource && features.size === "large") {
recommendations.push(
"Consider community-friendly documentation tools for large open-source project",
);
}
return recommendations;
}
/**
* Assess quality of learning data
*/
private async assessLearningData(features: ProjectFeatures): Promise<{
similarProjects: number;
confidenceLevel: number;
dataQuality: "low" | "medium" | "high";
}> {
const tags = [features.language, features.framework].filter(
(tag): tag is string => Boolean(tag),
);
const similarMemories = await this.search({
tags,
});
const similarProjects = similarMemories.length;
let confidenceLevel = 0;
if (similarProjects >= 10) {
confidenceLevel = 0.9;
} else if (similarProjects >= 5) {
confidenceLevel = 0.7;
} else if (similarProjects >= 2) {
confidenceLevel = 0.5;
} else {
confidenceLevel = 0.2;
}
let dataQuality: "low" | "medium" | "high";
if (similarProjects >= 8 && confidenceLevel >= 0.8) {
dataQuality = "high";
} else if (similarProjects >= 3 && confidenceLevel >= 0.5) {
dataQuality = "medium";
} else {
dataQuality = "low";
}
return {
similarProjects,
confidenceLevel,
dataQuality,
};
}
/**
* Infer outcome from memory entry
*/
private inferOutcome(
memory: MemoryEntry,
): "success" | "failure" | "neutral" | null {
if (memory.type === "deployment") {
if (memory.data.status === "success") return "success";
if (memory.data.status === "failed") return "failure";
}
if (memory.type === "recommendation" && memory.data.feedback) {
const rating = memory.data.feedback.rating || memory.data.feedback.score;
if (rating > 3) return "success";
if (rating < 3) return "failure";
}
return "neutral";
}
/**
* Get comprehensive learning statistics
*/
async getLearningStatistics(): Promise<{
learning: any;
knowledgeGraph: any;
combined: {
totalMemories: number;
enhancedRecommendations: number;
accuracyImprovement: number;
systemMaturity: "nascent" | "developing" | "mature";
};
}> {
const learningStats = await this.learningSystem.getStatistics();
const graphStats = this.knowledgeGraph.getStatistics();
const totalMemories = (await this.search("")).length;
const graphStatsResult = await graphStats;
const enhancedRecommendations =
learningStats.totalPatterns + graphStatsResult.nodeCount;
// Estimate accuracy improvement based on data volume
let accuracyImprovement = 0;
if (totalMemories >= 50) {
accuracyImprovement = Math.min(0.3, totalMemories / 200);
}
// Determine system maturity
let systemMaturity: "nascent" | "developing" | "mature";
if (totalMemories >= 100 && learningStats.totalPatterns >= 20) {
systemMaturity = "mature";
} else if (totalMemories >= 20 && learningStats.totalPatterns >= 5) {
systemMaturity = "developing";
} else {
systemMaturity = "nascent";
}
return {
learning: learningStats,
knowledgeGraph: graphStats,
combined: {
totalMemories,
enhancedRecommendations,
accuracyImprovement,
systemMaturity,
},
};
}
/**
* Close and cleanup
*/
async close(): Promise<void> {
await this.knowledgeGraph.saveToMemory();
await super.close();
}
}
export default EnhancedMemoryManager;