// Copyright 2025 Chris Bunting
// Brief: Project-specific knowledge base service for MCP Code Analysis & Quality Server
// Scope: Manages project-specific knowledge extraction, storage, and retrieval
import { EventEmitter } from 'events';
import {
AnalysisContext,
AnalysisResult,
UnifiedAnalysisResult,
LoggerInterface,
CacheInterface
} from '@mcp-code-analysis/shared-types';
export interface KnowledgeBaseConfig {
enableLearning: boolean;
enableKnowledgeSharing: boolean;
maxKnowledgeNodes: number;
confidenceThreshold: number;
learningRate: number;
knowledgeRetention: number;
enableInference: boolean;
enableValidation: boolean;
}
export interface KnowledgeNode {
id: string;
type: NodeType;
title: string;
description: string;
content: string;
confidence: number;
source: KnowledgeSource;
metadata: NodeMetadata;
relationships: Relationship[];
tags: string[];
createdAt: Date;
updatedAt: Date;
accessCount: number;
lastAccessed: Date;
}
export interface Relationship {
id: string;
type: RelationshipType;
sourceNodeId: string;
targetNodeId: string;
strength: number;
description: string;
metadata: RelationshipMetadata;
createdAt: Date;
}
export interface KnowledgeGraph {
id: string;
projectId: string;
name: string;
description: string;
nodes: Map<string, KnowledgeNode>;
relationships: Map<string, Relationship>;
metadata: GraphMetadata;
createdAt: Date;
updatedAt: Date;
}
export interface KnowledgeQuery {
query: string;
type: QueryType;
filters: QueryFilter[];
limit: number;
includeRelationships: boolean;
context: QueryContext;
}
export interface KnowledgeExtractionRequest {
projectId: string;
analysisResults: UnifiedAnalysisResult[];
context: AnalysisContext;
extractionType: ExtractionType;
options: ExtractionOptions;
}
export interface KnowledgeInferenceRequest {
projectId: string;
context: AnalysisContext;
inferenceType: InferenceType;
premises: string[];
options: InferenceOptions;
}
export interface KnowledgeValidationRequest {
knowledgeNodes: KnowledgeNode[];
validationType: ValidationType;
options: ValidationOptions;
}
export interface NodeMetadata {
language: string;
technologies: string[];
complexity: number;
importance: number;
businessImpact: number;
technicalImpact: number;
userImpact: number;
verificationStatus: VerificationStatus;
reviewStatus: ReviewStatus;
}
export interface RelationshipMetadata {
correlationStrength: number;
causalRelationship: boolean;
temporal: boolean;
spatial: boolean;
logical: boolean;
evidence: string[];
}
export interface GraphMetadata {
totalNodes: number;
totalRelationships: number;
averageConfidence: number;
lastExtraction: Date;
lastInference: Date;
lastValidation: Date;
knowledgeDomains: string[];
completeness: number;
}
export interface QueryContext {
projectId: string;
userContext: UserContext;
temporalContext: TemporalContext;
spatialContext: SpatialContext;
domainContext: DomainContext;
}
export interface UserContext {
expertise: ExpertiseLevel;
preferences: UserPreferences;
history: QueryHistory[];
}
export interface TemporalContext {
timeframe: Timeframe;
timeRange: {
start: Date;
end: Date;
};
}
export interface SpatialContext {
files: string[];
modules: string[];
components: string[];
}
export interface DomainContext {
businessDomain: string;
technicalDomain: string;
industry: string;
}
export interface QueryFilter {
field: string;
operator: FilterOperator;
value: any;
}
export interface ExtractionOptions {
includeCodeAnalysis: boolean;
includeDocumentation: boolean;
includeComments: boolean;
includeTests: boolean;
includeConfiguration: boolean;
maxNodesPerExtraction: number;
confidenceThreshold: number;
}
export interface InferenceOptions {
maxDepth: number;
confidenceThreshold: number;
includeExplanations: boolean;
includeAlternatives: boolean;
reasoningStrategy: ReasoningStrategy;
}
export interface ValidationOptions {
validationLevel: ValidationLevel;
crossReference: boolean;
consistencyCheck: boolean;
completenessCheck: boolean;
expertReview: boolean;
}
export interface QueryHistory {
query: string;
timestamp: Date;
results: number;
satisfaction: number;
}
export interface UserPreferences {
preferredLanguages: string[];
preferredTechnologies: string[];
detailLevel: DetailLevel;
visualizationPreference: VisualizationType;
}
export interface KnowledgeExtractionResult {
success: boolean;
extractedNodes: KnowledgeNode[];
extractedRelationships: Relationship[];
statistics: ExtractionStatistics;
errors: string[];
}
export interface KnowledgeInferenceResult {
success: boolean;
inferredNodes: KnowledgeNode[];
inferredRelationships: Relationship[];
reasoning: ReasoningChain[];
confidence: number;
alternatives: Alternative[];
errors: string[];
}
export interface KnowledgeValidationResult {
success: boolean;
validatedNodes: ValidatedNode[];
validationReport: ValidationReport;
recommendations: ValidationRecommendation[];
errors: string[];
}
export interface ExtractionStatistics {
totalNodes: number;
totalRelationships: number;
averageConfidence: number;
processingTime: number;
sources: ExtractionSource[];
}
export interface ExtractionSource {
type: SourceType;
count: number;
confidence: number;
}
export interface ReasoningChain {
id: string;
steps: ReasoningStep[];
conclusion: string;
confidence: number;
}
export interface ReasoningStep {
step: number;
premise: string;
inference: string;
confidence: number;
evidence: string[];
}
export interface Alternative {
id: string;
description: string;
confidence: number;
reasoning: string;
pros: string[];
cons: string[];
}
export interface ValidatedNode {
nodeId: string;
validationStatus: ValidationStatus;
confidence: number;
issues: ValidationIssue[];
recommendations: string[];
}
export interface ValidationReport {
totalNodes: number;
validNodes: number;
invalidNodes: number;
questionableNodes: number;
averageConfidence: number;
mainIssues: string[];
}
export interface ValidationRecommendation {
type: RecommendationType;
description: string;
priority: PriorityLevel;
effort: number;
expectedOutcome: string;
}
export interface ValidationIssue {
type: IssueType;
severity: SeverityLevel;
description: string;
location: string;
suggestion: string;
}
export enum NodeType {
CODE_PATTERN = 'code-pattern',
ARCHITECTURAL_PATTERN = 'architectural-pattern',
DESIGN_PRINCIPLE = 'design-principle',
BUSINESS_RULE = 'business-rule',
TECHNICAL_DECISION = 'technical-decision',
REQUIREMENT = 'requirement',
CONSTRAINT = 'constraint',
BEST_PRACTICE = 'best-practice',
ANTI_PATTERN = 'anti-pattern',
DOMAIN_CONCEPT = 'domain-concept',
TECHNOLOGY = 'technology',
FRAMEWORK = 'framework',
LIBRARY = 'library',
API = 'api',
DATA_MODEL = 'data-model',
ALGORITHM = 'algorithm',
PROCESS = 'process',
WORKFLOW = 'workflow'
}
export enum RelationshipType {
DEPENDS_ON = 'depends-on',
IMPLEMENTS = 'implements',
EXTENDS = 'extends',
USES = 'uses',
CONTAINS = 'contains',
REFERENCES = 'references',
VALIDATES = 'validates',
CONTRADICTS = 'contradicts',
SIMILAR_TO = 'similar-to',
RELATED_TO = 'related-to',
CAUSES = 'causes',
PREVENTS = 'prevents',
ENHANCES = 'enhances',
REDUCES = 'reduces',
ALTERNATIVE_TO = 'alternative-to'
}
export enum KnowledgeSource {
CODE_ANALYSIS = 'code-analysis',
DOCUMENTATION = 'documentation',
COMMENTS = 'comments',
TESTS = 'tests',
CONFIGURATION = 'configuration',
EXTERNAL_KNOWLEDGE = 'external-knowledge',
USER_INPUT = 'user-input',
INFERENCE = 'inference',
VALIDATION = 'validation'
}
export enum QueryType {
SEARCH = 'search',
EXPLORE = 'explore',
RECOMMEND = 'recommend',
VALIDATE = 'validate',
INFER = 'infer',
EXPLAIN = 'explain',
COMPARE = 'compare',
ANALYZE = 'analyze'
}
export enum ExtractionType {
CODE_PATTERNS = 'code-patterns',
ARCHITECTURE = 'architecture',
BUSINESS_LOGIC = 'business-logic',
DATA_MODELS = 'data-models',
API_CONTRACTS = 'api-contracts',
CONFIGURATION = 'configuration',
DEPENDENCIES = 'dependencies',
TEST_PATTERNS = 'test-patterns',
DOCUMENTATION = 'documentation'
}
export enum InferenceType {
DEDUCTIVE = 'deductive',
INDUCTIVE = 'inductive',
ABDUCTIVE = 'abductive',
ANALOGICAL = 'analogical',
CAUSAL = 'causal',
CORRELATIONAL = 'correlational'
}
export enum ValidationType {
CONSISTENCY = 'consistency',
COMPLETENESS = 'completeness',
ACCURACY = 'accuracy',
RELEVANCE = 'relevance',
TIMELINESS = 'timeliness',
CROSS_REFERENCE = 'cross-reference'
}
export enum VerificationStatus {
UNVERIFIED = 'unverified',
VERIFIED = 'verified',
DISPUTED = 'disputed',
OUTDATED = 'outdated'
}
export enum ReviewStatus {
UNREVIEWED = 'unreviewed',
REVIEWED = 'reviewed',
APPROVED = 'approved',
REJECTED = 'rejected'
}
export enum ExpertiseLevel {
BEGINNER = 'beginner',
INTERMEDIATE = 'intermediate',
ADVANCED = 'advanced',
EXPERT = 'expert'
}
export enum Timeframe {
HOUR = 'hour',
DAY = 'day',
WEEK = 'week',
MONTH = 'month',
QUARTER = 'quarter',
YEAR = 'year'
}
export enum FilterOperator {
EQUALS = 'equals',
NOT_EQUALS = 'not-equals',
CONTAINS = 'contains',
STARTS_WITH = 'starts-with',
ENDS_WITH = 'ends-with',
GREATER_THAN = 'greater-than',
LESS_THAN = 'less-than',
IN = 'in',
NOT_IN = 'not-in'
}
export enum DetailLevel {
BASIC = 'basic',
DETAILED = 'detailed',
COMPREHENSIVE = 'comprehensive'
}
export enum VisualizationType {
GRAPH = 'graph',
TREE = 'tree',
TABLE = 'table',
LIST = 'list'
}
export enum SourceType {
CODE_FILE = 'code-file',
DOCUMENTATION_FILE = 'documentation-file',
TEST_FILE = 'test-file',
CONFIGURATION_FILE = 'configuration-file',
COMMENT = 'comment',
EXTERNAL_API = 'external-api',
USER_INPUT = 'user-input'
}
export enum ReasoningStrategy {
FORWARD_CHAINING = 'forward-chaining',
BACKWARD_CHAINING = 'backward-chaining',
MIXED_CHAINING = 'mixed-chaining',
ANALOGICAL_REASONING = 'analogical-reasoning',
CASE_BASED = 'case-based'
}
export enum ValidationLevel {
BASIC = 'basic',
STANDARD = 'standard',
THOROUGH = 'thorough',
COMPREHENSIVE = 'comprehensive'
}
export enum ValidationStatus {
VALID = 'valid',
INVALID = 'invalid',
QUESTIONABLE = 'questionable',
PARTIAL = 'partial'
}
export enum RecommendationType {
ADD_EVIDENCE = 'add-evidence',
IMPROVE_CONFIDENCE = 'improve-confidence',
UPDATE_CONTENT = 'update-content',
REMOVE_NODE = 'remove-node',
ADD_RELATIONSHIP = 'add-relationship',
VERIFY_SOURCE = 'verify-source'
}
export enum IssueType {
INCONSISTENCY = 'inconsistency',
CONTRADICTION = 'contradiction',
INCOMPLETENESS = 'incompleteness',
INACCURACY = 'inaccuracy',
IRRELEVANCE = 'irrelevance',
OUTDATED = 'outdated'
}
export class KnowledgeBaseService extends EventEmitter {
private config: KnowledgeBaseConfig;
private cache: CacheInterface;
private logger: LoggerInterface;
private knowledgeGraphs: Map<string, KnowledgeGraph> = new Map();
private extractionEngines: Map<ExtractionType, ExtractionEngine> = new Map();
private inferenceEngines: Map<InferenceType, InferenceEngine> = new Map();
private validationEngines: Map<ValidationType, ValidationEngine> = new Map();
constructor(config: KnowledgeBaseConfig, cache: CacheInterface, logger: LoggerInterface) {
super();
this.config = config;
this.cache = cache;
this.logger = logger;
this.setupEventHandlers();
this.initializeEngines();
}
private setupEventHandlers(): void {
this.on('knowledge-extracted', this.handleKnowledgeExtracted.bind(this));
this.on('knowledge-inferred', this.handleKnowledgeInferred.bind(this));
this.on('knowledge-validated', this.handleKnowledgeValidated.bind(this));
this.on('knowledge-query', this.handleKnowledgeQuery.bind(this));
}
private initializeEngines(): void {
// Initialize extraction engines
this.extractionEngines.set(ExtractionType.CODE_PATTERNS, new CodePatternExtractionEngine());
this.extractionEngines.set(ExtractionType.ARCHITECTURE, new ArchitectureExtractionEngine());
this.extractionEngines.set(ExtractionType.BUSINESS_LOGIC, new BusinessLogicExtractionEngine());
this.extractionEngines.set(ExtractionType.DATA_MODELS, new DataModelExtractionEngine());
this.extractionEngines.set(ExtractionType.API_CONTRACTS, new ApiContractExtractionEngine());
this.extractionEngines.set(ExtractionType.CONFIGURATION, new ConfigurationExtractionEngine());
this.extractionEngines.set(ExtractionType.DEPENDENCIES, new DependencyExtractionEngine());
this.extractionEngines.set(ExtractionType.TEST_PATTERNS, new TestPatternExtractionEngine());
this.extractionEngines.set(ExtractionType.DOCUMENTATION, new DocumentationExtractionEngine());
// Initialize inference engines
this.inferenceEngines.set(InferenceType.DEDUCTIVE, new DeductiveInferenceEngine());
this.inferenceEngines.set(InferenceType.INDUCTIVE, new InductiveInferenceEngine());
this.inferenceEngines.set(InferenceType.ABDUCTIVE, new AbductiveInferenceEngine());
this.inferenceEngines.set(InferenceType.ANALOGICAL, new AnalogicalInferenceEngine());
this.inferenceEngines.set(InferenceType.CAUSAL, new CausalInferenceEngine());
this.inferenceEngines.set(InferenceType.CORRELATIONAL, new CorrelationalInferenceEngine());
// Initialize validation engines
this.validationEngines.set(ValidationType.CONSISTENCY, new ConsistencyValidationEngine());
this.validationEngines.set(ValidationType.COMPLETENESS, new CompletenessValidationEngine());
this.validationEngines.set(ValidationType.ACCURACY, new AccuracyValidationEngine());
this.validationEngines.set(ValidationType.RELEVANCE, new RelevanceValidationEngine());
this.validationEngines.set(ValidationType.TIMELINESS, new TimelinessValidationEngine());
this.validationEngines.set(ValidationType.CROSS_REFERENCE, new CrossReferenceValidationEngine());
}
async initialize(): Promise<void> {
this.logger.info('Initializing Knowledge Base Service');
// Load existing knowledge graphs from cache
await this.loadKnowledgeGraphs();
this.logger.info('Knowledge Base Service initialized successfully');
}
async createKnowledgeGraph(projectId: string, name: string, description: string): Promise<KnowledgeGraph> {
const graph: KnowledgeGraph = {
id: this.generateGraphId(),
projectId,
name,
description,
nodes: new Map(),
relationships: new Map(),
metadata: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
lastExtraction: new Date(),
lastInference: new Date(),
lastValidation: new Date(),
knowledgeDomains: [],
completeness: 0
},
createdAt: new Date(),
updatedAt: new Date()
};
this.knowledgeGraphs.set(projectId, graph);
await this.saveKnowledgeGraph(projectId);
this.emit('graph-created', graph);
this.logger.info(`Knowledge graph created for project: ${projectId}`);
return graph;
}
async extractKnowledge(request: KnowledgeExtractionRequest): Promise<KnowledgeExtractionResult> {
try {
this.logger.info(`Extracting knowledge for project: ${request.projectId}`);
const startTime = Date.now();
const graph = this.getOrCreateKnowledgeGraph(request.projectId);
const engine = this.extractionEngines.get(request.extractionType);
if (!engine) {
throw new Error(`No extraction engine found for type: ${request.extractionType}`);
}
const result = await engine.extract(request, graph);
if (result.success) {
// Add extracted nodes and relationships to graph
for (const node of result.extractedNodes) {
graph.nodes.set(node.id, node);
}
for (const relationship of result.extractedRelationships) {
graph.relationships.set(relationship.id, relationship);
}
// Update graph metadata
this.updateGraphMetadata(graph);
// Save updated graph
await this.saveKnowledgeGraph(request.projectId);
this.emit('knowledge-extracted', {
projectId: request.projectId,
extractionType: request.extractionType,
nodesCount: result.extractedNodes.length,
relationshipsCount: result.extractedRelationships.length
});
}
result.statistics.processingTime = Date.now() - startTime;
this.logger.info(`Knowledge extraction completed in ${result.statistics.processingTime}ms`);
return result;
} catch (error) {
this.logger.error('Failed to extract knowledge:', error);
return {
success: false,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: [error.message]
};
}
}
async inferKnowledge(request: KnowledgeInferenceRequest): Promise<KnowledgeInferenceResult> {
try {
this.logger.info(`Inferring knowledge for project: ${request.projectId}`);
const startTime = Date.now();
const graph = this.getKnowledgeGraph(request.projectId);
const engine = this.inferenceEngines.get(request.inferenceType);
if (!engine) {
throw new Error(`No inference engine found for type: ${request.inferenceType}`);
}
const result = await engine.infer(request, graph);
if (result.success) {
// Add inferred nodes and relationships to graph
for (const node of result.inferredNodes) {
if (node.confidence >= this.config.confidenceThreshold) {
graph.nodes.set(node.id, node);
}
}
for (const relationship of result.inferredRelationships) {
if (relationship.strength >= this.config.confidenceThreshold) {
graph.relationships.set(relationship.id, relationship);
}
}
// Update graph metadata
this.updateGraphMetadata(graph);
// Save updated graph
await this.saveKnowledgeGraph(request.projectId);
this.emit('knowledge-inferred', {
projectId: request.projectId,
inferenceType: request.inferenceType,
confidence: result.confidence,
nodesCount: result.inferredNodes.length,
relationshipsCount: result.inferredRelationships.length
});
}
this.logger.info(`Knowledge inference completed in ${Date.now() - startTime}ms`);
return result;
} catch (error) {
this.logger.error('Failed to infer knowledge:', error);
return {
success: false,
inferredNodes: [],
inferredRelationships: [],
reasoning: [],
confidence: 0,
alternatives: [],
errors: [error.message]
};
}
}
async validateKnowledge(request: KnowledgeValidationRequest): Promise<KnowledgeValidationResult> {
try {
this.logger.info('Validating knowledge');
const startTime = Date.now();
const engine = this.validationEngines.get(request.validationType);
if (!engine) {
throw new Error(`No validation engine found for type: ${request.validationType}`);
}
const result = await engine.validate(request);
if (result.success) {
// Update validation status of nodes
for (const validatedNode of result.validatedNodes) {
// Find and update the node in all graphs
for (const graph of this.knowledgeGraphs.values()) {
const node = graph.nodes.get(validatedNode.nodeId);
if (node) {
node.metadata.verificationStatus = this.mapValidationStatus(validatedNode.validationStatus);
node.confidence = Math.max(node.confidence, validatedNode.confidence);
node.updatedAt = new Date();
}
}
}
// Save all updated graphs
for (const projectId of this.knowledgeGraphs.keys()) {
await this.saveKnowledgeGraph(projectId);
}
this.emit('knowledge-validated', {
validationType: request.validationType,
totalNodes: request.knowledgeNodes.length,
validNodes: result.validationReport.validNodes,
invalidNodes: result.validationReport.invalidNodes
});
}
this.logger.info(`Knowledge validation completed in ${Date.now() - startTime}ms`);
return result;
} catch (error) {
this.logger.error('Failed to validate knowledge:', error);
return {
success: false,
validatedNodes: [],
validationReport: {
totalNodes: 0,
validNodes: 0,
invalidNodes: 0,
questionableNodes: 0,
averageConfidence: 0,
mainIssues: []
},
recommendations: [],
errors: [error.message]
};
}
}
async queryKnowledge(query: KnowledgeQuery): Promise<KnowledgeNode[]> {
try {
this.logger.info(`Querying knowledge: ${query.query}`);
const graph = this.getKnowledgeGraph(query.context.projectId);
const results: KnowledgeNode[] = [];
// Apply filters and search
for (const node of graph.nodes.values()) {
if (this.matchesQuery(node, query)) {
results.push(node);
// Update access statistics
node.accessCount++;
node.lastAccessed = new Date();
}
}
// Sort by relevance and confidence
results.sort((a, b) => {
const relevanceScore = this.calculateRelevanceScore(a, query);
const bRelevanceScore = this.calculateRelevanceScore(b, query);
return (bRelevanceScore + b.confidence) - (relevanceScore + a.confidence);
});
// Apply limit
const limitedResults = results.slice(0, query.limit);
// Include relationships if requested
if (query.includeRelationships) {
for (const node of limitedResults) {
node.relationships = this.getNodeRelationships(node.id, graph);
}
}
// Save updated graph
await this.saveKnowledgeGraph(query.context.projectId);
this.emit('knowledge-query', {
query: query.query,
results: limitedResults.length,
projectId: query.context.projectId
});
this.logger.info(`Knowledge query returned ${limitedResults.length} results`);
return limitedResults;
} catch (error) {
this.logger.error('Failed to query knowledge:', error);
return [];
}
}
async getKnowledgeGraph(projectId: string): Promise<KnowledgeGraph | null> {
return this.knowledgeGraphs.get(projectId) || null;
}
async getAllKnowledgeGraphs(): Promise<KnowledgeGraph[]> {
return Array.from(this.knowledgeGraphs.values());
}
async deleteKnowledgeGraph(projectId: string): Promise<boolean> {
try {
const deleted = this.knowledgeGraphs.delete(projectId);
if (deleted) {
await this.cache.delete(`knowledge-graph-${projectId}`);
this.emit('graph-deleted', { projectId });
this.logger.info(`Knowledge graph deleted for project: ${projectId}`);
}
return deleted;
} catch (error) {
this.logger.error('Failed to delete knowledge graph:', error);
return false;
}
}
async shareKnowledge(sourceProjectId: string, targetProjectId: string, nodeIds: string[]): Promise<boolean> {
try {
const sourceGraph = this.getKnowledgeGraph(sourceProjectId);
const targetGraph = this.getOrCreateKnowledgeGraph(targetProjectId);
if (!sourceGraph) {
throw new Error(`Source knowledge graph not found: ${sourceProjectId}`);
}
let sharedCount = 0;
for (const nodeId of nodeIds) {
const node = sourceGraph.nodes.get(nodeId);
if (node) {
// Create a copy of the node for the target graph
const sharedNode: KnowledgeNode = {
...node,
id: this.generateNodeId(),
source: KnowledgeSource.EXTERNAL_KNOWLEDGE,
createdAt: new Date(),
updatedAt: new Date(),
accessCount: 0,
lastAccessed: new Date()
};
targetGraph.nodes.set(sharedNode.id, sharedNode);
sharedCount++;
}
}
if (sharedCount > 0) {
this.updateGraphMetadata(targetGraph);
await this.saveKnowledgeGraph(targetProjectId);
this.emit('knowledge-shared', {
sourceProjectId,
targetProjectId,
sharedCount
});
this.logger.info(`Shared ${sharedCount} knowledge nodes from ${sourceProjectId} to ${targetProjectId}`);
}
return sharedCount > 0;
} catch (error) {
this.logger.error('Failed to share knowledge:', error);
return false;
}
}
private getOrCreateKnowledgeGraph(projectId: string): KnowledgeGraph {
let graph = this.knowledgeGraphs.get(projectId);
if (!graph) {
graph = {
id: this.generateGraphId(),
projectId,
name: `${projectId} Knowledge Graph`,
description: `Automatically generated knowledge graph for ${projectId}`,
nodes: new Map(),
relationships: new Map(),
metadata: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
lastExtraction: new Date(),
lastInference: new Date(),
lastValidation: new Date(),
knowledgeDomains: [],
completeness: 0
},
createdAt: new Date(),
updatedAt: new Date()
};
this.knowledgeGraphs.set(projectId, graph);
}
return graph;
}
private updateGraphMetadata(graph: KnowledgeGraph): void {
graph.metadata.totalNodes = graph.nodes.size;
graph.metadata.totalRelationships = graph.relationships.size;
// Calculate average confidence
const totalConfidence = Array.from(graph.nodes.values())
.reduce((sum, node) => sum + node.confidence, 0);
graph.metadata.averageConfidence = graph.nodes.size > 0
? totalConfidence / graph.nodes.size
: 0;
// Update knowledge domains
const domains = new Set<string>();
for (const node of graph.nodes.values()) {
domains.add(node.metadata.technicalImpact > 5 ? 'technical' : 'business');
}
graph.metadata.knowledgeDomains = Array.from(domains);
// Calculate completeness (simplified)
graph.metadata.completeness = Math.min(100, (graph.nodes.size / 100) * 100);
graph.updatedAt = new Date();
}
private matchesQuery(node: KnowledgeNode, query: KnowledgeQuery): boolean {
// Check if node matches query filters
for (const filter of query.filters) {
if (!this.matchesFilter(node, filter)) {
return false;
}
}
// Check if node content matches query string
if (query.query) {
const queryLower = query.query.toLowerCase();
const contentMatch =
node.title.toLowerCase().includes(queryLower) ||
node.description.toLowerCase().includes(queryLower) ||
node.content.toLowerCase().includes(queryLower) ||
node.tags.some(tag => tag.toLowerCase().includes(queryLower));
if (!contentMatch) {
return false;
}
}
return true;
}
private matchesFilter(node: KnowledgeNode, filter: QueryFilter): boolean {
const value = this.getNodeFieldValue(node, filter.field);
if (value === undefined) {
return false;
}
switch (filter.operator) {
case FilterOperator.EQUALS:
return value === filter.value;
case FilterOperator.NOT_EQUALS:
return value !== filter.value;
case FilterOperator.CONTAINS:
return String(value).toLowerCase().includes(String(filter.value).toLowerCase());
case FilterOperator.STARTS_WITH:
return String(value).toLowerCase().startsWith(String(filter.value).toLowerCase());
case FilterOperator.ENDS_WITH:
return String(value).toLowerCase().endsWith(String(filter.value).toLowerCase());
case FilterOperator.GREATER_THAN:
return Number(value) > Number(filter.value);
case FilterOperator.LESS_THAN:
return Number(value) < Number(filter.value);
case FilterOperator.IN:
return Array.isArray(filter.value) && filter.value.includes(value);
case FilterOperator.NOT_IN:
return Array.isArray(filter.value) && !filter.value.includes(value);
default:
return false;
}
}
private getNodeFieldValue(node: KnowledgeNode, field: string): any {
const fieldPath = field.split('.');
let value: any = node;
for (const part of fieldPath) {
if (value && typeof value === 'object') {
value = value[part];
} else {
return undefined;
}
}
return value;
}
private calculateRelevanceScore(node: KnowledgeNode, query: KnowledgeQuery): number {
let score = 0;
// Boost score based on user expertise
const expertiseMultiplier = {
[ExpertiseLevel.BEGINNER]: 1.2,
[ExpertiseLevel.INTERMEDIATE]: 1.0,
[ExpertiseLevel.ADVANCED]: 0.8,
[ExpertiseLevel.EXPERT]: 0.6
};
score *= expertiseMultiplier[query.context.userContext.expertise] || 1.0;
// Boost score based on recency
const daysSinceAccess = (Date.now() - node.lastAccessed.getTime()) / (1000 * 60 * 60 * 24);
if (daysSinceAccess < 7) {
score *= 1.2;
}
// Boost score based on access frequency
if (node.accessCount > 10) {
score *= 1.1;
}
return score;
}
private getNodeRelationships(nodeId: string, graph: KnowledgeGraph): Relationship[] {
return Array.from(graph.relationships.values()).filter(rel =>
rel.sourceNodeId === nodeId || rel.targetNodeId === nodeId
);
}
private mapValidationStatus(status: ValidationStatus): VerificationStatus {
const statusMap = {
[ValidationStatus.VALID]: VerificationStatus.VERIFIED,
[ValidationStatus.INVALID]: VerificationStatus.DISPUTED,
[ValidationStatus.QUESTIONABLE]: VerificationStatus.UNVERIFIED,
[ValidationStatus.PARTIAL]: VerificationStatus.UNVERIFIED
};
return statusMap[status] || VerificationStatus.UNVERIFIED;
}
private async loadKnowledgeGraphs(): Promise<void> {
try {
// Load knowledge graphs from cache
const cachedGraphs = await this.cache.get<Map<string, any>>('knowledge-graphs');
if (cachedGraphs) {
for (const [projectId, graphData] of Object.entries(cachedGraphs)) {
const graph: KnowledgeGraph = {
...graphData,
nodes: new Map(Object.entries(graphData.nodes)),
relationships: new Map(Object.entries(graphData.relationships))
};
this.knowledgeGraphs.set(projectId, graph);
}
this.logger.info(`Loaded ${this.knowledgeGraphs.size} knowledge graphs from cache`);
}
} catch (error) {
this.logger.warn('Failed to load knowledge graphs:', error);
}
}
private async saveKnowledgeGraph(projectId: string): Promise<void> {
try {
const graph = this.knowledgeGraphs.get(projectId);
if (graph) {
const graphData = {
...graph,
nodes: Object.fromEntries(graph.nodes),
relationships: Object.fromEntries(graph.relationships)
};
await this.cache.set(`knowledge-graph-${projectId}`, graphData, 3600);
// Also save to global graphs index
const graphsIndex: Record<string, any> = {};
for (const [pid, g] of this.knowledgeGraphs.entries()) {
graphsIndex[pid] = {
...g,
nodes: Object.fromEntries(g.nodes),
relationships: Object.fromEntries(g.relationships)
};
}
await this.cache.set('knowledge-graphs', graphsIndex, 3600);
}
} catch (error) {
this.logger.warn(`Failed to save knowledge graph for project ${projectId}:`, error);
}
}
// ID generation methods
private generateGraphId(): string {
return `graph_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
private generateNodeId(): string {
return `node_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
// Event handlers
private handleKnowledgeExtracted(data: any): void {
this.logger.debug(`Knowledge extracted event handled for project: ${data.projectId}`);
}
private handleKnowledgeInferred(data: any): void {
this.logger.debug(`Knowledge inferred event handled for project: ${data.projectId}`);
}
private handleKnowledgeValidated(data: any): void {
this.logger.debug(`Knowledge validated event handled`);
}
private handleKnowledgeQuery(data: any): void {
this.logger.debug(`Knowledge query event handled for project: ${data.projectId}`);
}
// Public API methods
async updateConfig(config: Partial<KnowledgeBaseConfig>): Promise<void> {
this.config = { ...this.config, ...config };
this.logger.info('Knowledge base configuration updated');
}
async getKnowledgeStats(): Promise<any> {
const totalNodes = Array.from(this.knowledgeGraphs.values())
.reduce((sum, graph) => sum + graph.metadata.totalNodes, 0);
const totalRelationships = Array.from(this.knowledgeGraphs.values())
.reduce((sum, graph) => sum + graph.metadata.totalRelationships, 0);
const averageConfidence = Array.from(this.knowledgeGraphs.values())
.reduce((sum, graph) => sum + graph.metadata.averageConfidence, 0) / this.knowledgeGraphs.size || 0;
return {
totalGraphs: this.knowledgeGraphs.size,
totalNodes,
totalRelationships,
averageConfidence,
learningEnabled: this.config.enableLearning,
knowledgeSharingEnabled: this.config.enableKnowledgeSharing,
extractionEngines: this.extractionEngines.size,
inferenceEngines: this.inferenceEngines.size,
validationEngines: this.validationEngines.size
};
}
async shutdown(): Promise<void> {
this.logger.info('Shutting down Knowledge Base Service');
// Save all knowledge graphs
for (const projectId of this.knowledgeGraphs.keys()) {
await this.saveKnowledgeGraph(projectId);
}
// Clear event listeners
this.removeAllListeners();
this.logger.info('Knowledge Base Service shutdown complete');
}
}
// Abstract base classes for engines
abstract class ExtractionEngine {
abstract extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult>;
}
abstract class InferenceEngine {
abstract infer(request: KnowledgeInferenceRequest, graph: KnowledgeGraph): Promise<KnowledgeInferenceResult>;
}
abstract class ValidationEngine {
abstract validate(request: KnowledgeValidationRequest): Promise<KnowledgeValidationResult>;
}
// Concrete engine implementations (simplified for brevity)
class CodePatternExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
// Implementation for code pattern extraction
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
class ArchitectureExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
// Implementation for architecture extraction
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
// Additional engine implementations would follow the same pattern...
class BusinessLogicExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
class DataModelExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
class ApiContractExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
class ConfigurationExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
class DependencyExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
class TestPatternExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
class DocumentationExtractionEngine extends ExtractionEngine {
async extract(request: KnowledgeExtractionRequest, graph: KnowledgeGraph): Promise<KnowledgeExtractionResult> {
return {
success: true,
extractedNodes: [],
extractedRelationships: [],
statistics: {
totalNodes: 0,
totalRelationships: 0,
averageConfidence: 0,
processingTime: 0,
sources: []
},
errors: []
};
}
}
class DeductiveInferenceEngine extends InferenceEngine {
async infer(request: KnowledgeInferenceRequest, graph: KnowledgeGraph): Promise<KnowledgeInferenceResult> {
return {
success: true,
inferredNodes: [],
inferredRelationships: [],
reasoning: [],
confidence: 0,
alternatives: [],
errors: []
};
}
}
class InductiveInferenceEngine extends InferenceEngine {
async infer(request: KnowledgeInferenceRequest, graph: KnowledgeGraph): Promise<KnowledgeInferenceResult> {
return {
success: true,
inferredNodes: [],
inferredRelationships: [],
reasoning: [],
confidence: 0,
alternatives: [],
errors: []
};
}
}
class AbductiveInferenceEngine extends InferenceEngine {
async infer(request: KnowledgeInferenceRequest, graph: KnowledgeGraph): Promise<KnowledgeInferenceResult> {
return {
success: true,
inferredNodes: [],
inferredRelationships: [],
reasoning: [],
confidence: 0,
alternatives: [],
errors: []
};
}
}
class AnalogicalInferenceEngine extends InferenceEngine {
async infer(request: KnowledgeInferenceRequest, graph: KnowledgeGraph): Promise<KnowledgeInferenceResult> {
return {
success: true,
inferredNodes: [],
inferredRelationships: [],
reasoning: [],
confidence: 0,
alternatives: [],
errors: []
};
}
}
class CausalInferenceEngine extends InferenceEngine {
async infer(request: KnowledgeInferenceRequest, graph: KnowledgeGraph): Promise<KnowledgeInferenceResult> {
return {
success: true,
inferredNodes: [],
inferredRelationships: [],
reasoning: [],
confidence: 0,
alternatives: [],
errors: []
};
}
}
class CorrelationalInferenceEngine extends InferenceEngine {
async infer(request: KnowledgeInferenceRequest, graph: KnowledgeGraph): Promise<KnowledgeInferenceResult> {
return {
success: true,
inferredNodes: [],
inferredRelationships: [],
reasoning: [],
confidence: 0,
alternatives: [],
errors: []
};
}
}
class ConsistencyValidationEngine extends ValidationEngine {
async validate(request: KnowledgeValidationRequest): Promise<KnowledgeValidationResult> {
return {
success: true,
validatedNodes: [],
validationReport: {
totalNodes: 0,
validNodes: 0,
invalidNodes: 0,
questionableNodes: 0,
averageConfidence: 0,
mainIssues: []
},
recommendations: [],
errors: []
};
}
}
class CompletenessValidationEngine extends ValidationEngine {
async validate(request: KnowledgeValidationRequest): Promise<KnowledgeValidationResult> {
return {
success: true,
validatedNodes: [],
validationReport: {
totalNodes: 0,
validNodes: 0,
invalidNodes: 0,
questionableNodes: 0,
averageConfidence: 0,
mainIssues: []
},
recommendations: [],
errors: []
};
}
}
class AccuracyValidationEngine extends ValidationEngine {
async validate(request: KnowledgeValidationRequest): Promise<KnowledgeValidationResult> {
return {
success: true,
validatedNodes: [],
validationReport: {
totalNodes: 0,
validNodes: 0,
invalidNodes: 0,
questionableNodes: 0,
averageConfidence: 0,
mainIssues: []
},
recommendations: [],
errors: []
};
}
}
class RelevanceValidationEngine extends ValidationEngine {
async validate(request: KnowledgeValidationRequest): Promise<KnowledgeValidationResult> {
return {
success: true,
validatedNodes: [],
validationReport: {
totalNodes: 0,
validNodes: 0,
invalidNodes: 0,
questionableNodes: 0,
averageConfidence: 0,
mainIssues: []
},
recommendations: [],
errors: []
};
}
}
class TimelinessValidationEngine extends ValidationEngine {
async validate(request: KnowledgeValidationRequest): Promise<KnowledgeValidationResult> {
return {
success: true,
validatedNodes: [],
validationReport: {
totalNodes: 0,
validNodes: 0,
invalidNodes: 0,
questionableNodes: 0,
averageConfidence: 0,
mainIssues: []
},
recommendations: [],
errors: []
};
}
}
class CrossReferenceValidationEngine extends ValidationEngine {
async validate(request: KnowledgeValidationRequest): Promise<KnowledgeValidationResult> {
return {
success: true,
validatedNodes: [],
validationReport: {
totalNodes: 0,
validNodes: 0,
invalidNodes: 0,
questionableNodes: 0,
averageConfidence: 0,
mainIssues: []
},
recommendations: [],
errors: []
};
}
}