UNPKG

mushcode-mcp-server

Version:

A specialized Model Context Protocol server for MUSHCODE development assistance. Provides AI-powered code generation, validation, optimization, and examples for MUD development.

215 lines 7.81 kB
/** * Persistence layer for knowledge base data */ import { promises as fs } from 'fs'; import { join } from 'path'; import { MushcodeKnowledgeBase } from './base.js'; /** * Persistence manager for knowledge base */ export class KnowledgeBasePersistence { dataDir; constructor(dataDir = 'data/knowledge') { this.dataDir = dataDir; } /** * Save knowledge base to JSON files */ async save(knowledgeBase) { console.log('💾 Saving knowledge base to JSON files...'); // Ensure data directory exists await this.ensureDataDirectory(); const stats = knowledgeBase.getStats(); // Convert Maps to arrays for serialization const data = { patterns: Array.from(knowledgeBase.patterns.values()), dialects: Array.from(knowledgeBase.dialects.values()), securityRules: Array.from(knowledgeBase.securityRules.values()), examples: Array.from(knowledgeBase.examples.values()), learningPaths: Array.from(knowledgeBase.learningPaths.values()), metadata: { version: stats.version, lastUpdated: stats.lastUpdated.toISOString(), sources: knowledgeBase.sources, totalFiles: stats.patterns + stats.examples } }; // Save individual files for better organization await Promise.all([ this.saveJsonFile('patterns.json', data.patterns), this.saveJsonFile('dialects.json', data.dialects), this.saveJsonFile('security-rules.json', data.securityRules), this.saveJsonFile('examples.json', data.examples), this.saveJsonFile('learning-paths.json', data.learningPaths), this.saveJsonFile('metadata.json', data.metadata) ]); // Also save a complete combined file await this.saveJsonFile('knowledge-base.json', data); console.log('✅ Knowledge base saved successfully!'); console.log(`📁 Data directory: ${this.dataDir}`); console.log(`📊 Saved ${data.patterns.length} patterns, ${data.examples.length} examples`); } /** * Load knowledge base from JSON files */ async load() { console.log('📂 Loading knowledge base from JSON files...'); const knowledgeBase = new MushcodeKnowledgeBase(); try { // Try to load from individual files first const [patterns, dialects, securityRules, examples, learningPaths, metadata] = await Promise.all([ this.loadJsonFile('patterns.json'), this.loadJsonFile('dialects.json'), this.loadJsonFile('security-rules.json'), this.loadJsonFile('examples.json'), this.loadJsonFile('learning-paths.json'), this.loadJsonFile('metadata.json') ]); // Populate the knowledge base patterns.forEach(pattern => knowledgeBase.addPattern(pattern)); dialects.forEach(dialect => knowledgeBase.addDialect(dialect)); securityRules.forEach(rule => knowledgeBase.addSecurityRule(rule)); examples.forEach(example => knowledgeBase.addExample(example)); learningPaths.forEach(path => knowledgeBase.addLearningPath(path)); // Update metadata knowledgeBase.version = metadata.version; knowledgeBase.lastUpdated = new Date(metadata.lastUpdated); knowledgeBase.sources = metadata.sources; console.log('✅ Knowledge base loaded successfully!'); console.log(`📊 Loaded ${patterns.length} patterns, ${examples.length} examples`); } catch (error) { // Fallback to combined file console.log('⚠️ Individual files not found, trying combined file...'); try { const data = await this.loadJsonFile('knowledge-base.json'); data.patterns.forEach(pattern => knowledgeBase.addPattern(pattern)); data.dialects.forEach(dialect => knowledgeBase.addDialect(dialect)); data.securityRules.forEach(rule => knowledgeBase.addSecurityRule(rule)); data.examples.forEach(example => knowledgeBase.addExample(example)); data.learningPaths.forEach(path => knowledgeBase.addLearningPath(path)); knowledgeBase.version = data.metadata.version; knowledgeBase.lastUpdated = new Date(data.metadata.lastUpdated); knowledgeBase.sources = data.metadata.sources; console.log('✅ Knowledge base loaded from combined file!'); } catch (combinedError) { console.log('⚠️ No existing knowledge base found, starting with empty base'); } } return knowledgeBase; } /** * Check if knowledge base files exist */ async exists() { try { await fs.access(join(this.dataDir, 'knowledge-base.json')); return true; } catch { return false; } } /** * Get information about saved knowledge base */ async getInfo() { try { return await this.loadJsonFile('metadata.json'); } catch { try { const data = await this.loadJsonFile('knowledge-base.json'); return data.metadata; } catch { return null; } } } /** * Export knowledge base to a specific directory */ async exportTo(targetDir, knowledgeBase) { const originalDataDir = this.dataDir; this.dataDir = targetDir; try { await this.save(knowledgeBase); } finally { this.dataDir = originalDataDir; } } /** * Import knowledge base from a specific directory */ async importFrom(sourceDir) { const originalDataDir = this.dataDir; this.dataDir = sourceDir; try { return await this.load(); } finally { this.dataDir = originalDataDir; } } /** * Ensure data directory exists */ async ensureDataDirectory() { try { await fs.mkdir(this.dataDir, { recursive: true }); } catch (error) { console.error('Failed to create data directory:', error); throw error; } } /** * Save data to JSON file */ async saveJsonFile(filename, data) { const filePath = join(this.dataDir, filename); const jsonData = JSON.stringify(data, null, 2); await fs.writeFile(filePath, jsonData, 'utf8'); } /** * Load data from JSON file */ async loadJsonFile(filename) { const filePath = join(this.dataDir, filename); const jsonData = await fs.readFile(filePath, 'utf8'); return JSON.parse(jsonData); } /** * List all saved knowledge base files */ async listFiles() { try { const files = await fs.readdir(this.dataDir); return files.filter(file => file.endsWith('.json')); } catch { return []; } } /** * Get file sizes for saved knowledge base */ async getFileSizes() { const files = await this.listFiles(); const sizes = {}; for (const file of files) { try { const stats = await fs.stat(join(this.dataDir, file)); sizes[file] = stats.size; } catch { sizes[file] = 0; } } return sizes; } } //# sourceMappingURL=persistence.js.map