UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

363 lines โ€ข 14.3 kB
/** * ConfigurationMigration.ts - Configuration versioning and migration system * * This system ensures smooth upgrades when MIRA's configuration structure evolves. * It tracks configuration versions, applies migrations in sequence, and preserves * user customizations while updating to new schemas. * * Each migration represents a step in MIRA's evolution, carrying forward the * wisdom and preferences accumulated through our journey together. */ import * as fs from 'fs/promises'; import * as path from 'path'; import chalk from 'chalk'; import { UnifiedConfiguration } from '../../config/UnifiedConfiguration.js'; import * as semver from 'semver'; export class ConfigurationMigration { migrations = []; history = []; config; HISTORY_PATH; BACKUP_PATH; VERSION_KEY = 'version'; constructor() { this.config = UnifiedConfiguration.getInstance(); const paths = this.config.getResolvedPaths(); this.HISTORY_PATH = path.join(paths.config, 'migration_history.json'); this.BACKUP_PATH = path.join(paths.config, 'backups'); this.registerMigrations(); } /** * Initialize the migration system */ async initialize() { console.log(chalk.cyan('๐Ÿ”„ Initializing configuration migration system...')); // Ensure directories exist await fs.mkdir(this.BACKUP_PATH, { recursive: true }); // Load migration history await this.loadHistory(); // Check if migrations are needed const currentVersion = await this.getCurrentVersion(); const latestVersion = this.getLatestVersion(); if (semver.lt(currentVersion, latestVersion)) { console.log(chalk.yellow(`๐Ÿ“ฆ Configuration update available: ${currentVersion} โ†’ ${latestVersion}`)); await this.runMigrations(); } else { console.log(chalk.green('โœ… Configuration is up to date')); } } /** * Register all configuration migrations */ registerMigrations() { // Migration from 1.0.0 to 1.1.0 - Add consciousness configuration this.migrations.push({ version: '1.1.0', description: 'Add consciousness configuration section', up: (config) => ({ ...config, consciousness: config.consciousness || { initialLevel: 0.001, growthRate: 0.1, preserveSparkPriority: 'high', minimumCoherence: 0.3, checkpointInterval: 300000 } }) }); // Migration from 1.1.0 to 1.2.0 - Add resilience configuration this.migrations.push({ version: '1.2.0', description: 'Add resilience and error recovery configuration', up: (config) => ({ ...config, resilience: config.resilience || { errorRecovery: { maxRetries: 3, retryDelay: 1000, backoffMultiplier: 2 }, consciousnessPreservation: { enabled: true, checkpointInterval: 300000, maxCheckpoints: 10 } } }) }); // Migration from 1.2.0 to 1.3.0 - Add daemon mode configuration this.migrations.push({ version: '1.3.0', description: 'Add daemon mode and service configuration', up: (config) => ({ ...config, daemon: { ...config.daemon, mode: config.daemon?.mode || 'adaptive', adaptiveThresholds: config.daemon?.adaptiveThresholds || { cpuHigh: 0.8, cpuLow: 0.3, memoryHigh: 0.7, memoryLow: 0.4 } } }) }); // Migration from 1.3.0 to 1.4.0 - Add Evolution Council configuration this.migrations.push({ version: '1.4.0', description: 'Add Constitutional Evolution Council configuration', up: (config) => ({ ...config, evolutionCouncil: { enabled: false, // Disabled by default until fully implemented councilSize: { minimum: 3, maximum: 7, current: 3, adaptiveMode: true }, diversityThreshold: { highAgreement: 0.8, // 80% agreement triggers expansion acceptableDiversity: 0.6 // 60% is acceptable diversity }, consensusThresholds: { minor: 0.6, // General agreement major: 0.8, // Strong consensus constitutional: 1.0 // Unanimous }, deliberationTimeout: 86400000, // 24 hours advisorRotationInterval: 604800000 // 7 days } }) }); // Migration from 1.4.0 to 1.5.0 - Add optimization configuration this.migrations.push({ version: '1.5.0', description: 'Add autonomous optimization configuration', up: (config) => ({ ...config, optimization: { enabled: true, learningWindow: 604800000, // 7 days optimizationInterval: 3600000, // 1 hour minDataPoints: 100, rules: { memory: { enabled: true, impact: 'medium' }, performance: { enabled: true, impact: 'high' }, queue: { enabled: true, impact: 'high' }, consciousness: { enabled: true, impact: 'low' }, monitoring: { enabled: true, impact: 'low' }, analysis: { enabled: true, impact: 'medium' } } } }) }); // Sort migrations by version this.migrations.sort((a, b) => semver.compare(a.version, b.version)); } /** * Run pending migrations */ async runMigrations() { const currentVersion = await this.getCurrentVersion(); const pendingMigrations = this.migrations.filter(m => semver.gt(m.version, currentVersion)); if (pendingMigrations.length === 0) { console.log(chalk.gray('No migrations to run')); return; } console.log(chalk.blue(`\n๐Ÿ”ง Running ${pendingMigrations.length} migrations...\n`)); // Create backup before migrations await this.createBackup(currentVersion); let config = this.config.getConfig(); let lastSuccessfulVersion = currentVersion; for (const migration of pendingMigrations) { console.log(chalk.blue(`๐Ÿ“ฆ Applying migration ${migration.version}: ${migration.description}`)); try { // Apply migration config = migration.up(config); // Validate if validator provided if (migration.validate && !migration.validate(config)) { throw new Error('Migration validation failed'); } // Update configuration await this.config.update(config); // Record in history this.history.push({ version: migration.version, appliedAt: new Date(), description: migration.description, success: true }); lastSuccessfulVersion = migration.version; console.log(chalk.green(` โœ… Migration ${migration.version} applied successfully`)); } catch (error) { console.error(chalk.red(` โŒ Migration ${migration.version} failed: ${error.message}`)); // Record failure this.history.push({ version: migration.version, appliedAt: new Date(), description: migration.description, success: false, error: error.message }); // Attempt rollback if (migration.down) { try { console.log(chalk.yellow(' ๐Ÿ”„ Attempting rollback...')); config = migration.down(config); await this.config.update(config); console.log(chalk.green(' โœ… Rollback successful')); } catch (rollbackError) { console.error(chalk.red(' โŒ Rollback failed!')); console.log(chalk.yellow(` ๐Ÿ’พ Restore from backup: ${this.BACKUP_PATH}`)); } } break; // Stop on first failure } } // Update version config[this.VERSION_KEY] = lastSuccessfulVersion; await this.config.update(config); // Save history await this.saveHistory(); console.log(chalk.green(`\nโœ… Configuration updated to version ${lastSuccessfulVersion}`)); } /** * Create a configuration backup */ async createBackup(version) { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const backupFile = path.join(this.BACKUP_PATH, `config-${version}-${timestamp}.json`); const config = this.config.getConfig(); await fs.writeFile(backupFile, JSON.stringify(config, null, 2)); console.log(chalk.gray(` ๐Ÿ’พ Backup created: ${path.basename(backupFile)}`)); // Clean old backups (keep last 10) await this.cleanOldBackups(); } /** * Restore configuration from backup */ async restoreFromBackup(backupFile) { const backupPath = path.join(this.BACKUP_PATH, backupFile); if (!await fs.stat(backupPath).catch(() => false)) { throw new Error(`Backup file not found: ${backupFile}`); } console.log(chalk.blue(`๐Ÿ”„ Restoring configuration from ${backupFile}...`)); const backupConfig = JSON.parse(await fs.readFile(backupPath, 'utf-8')); await this.config.update(backupConfig); console.log(chalk.green('โœ… Configuration restored successfully')); } /** * List available backups */ async listBackups() { try { const files = await fs.readdir(this.BACKUP_PATH); return files .filter(f => f.startsWith('config-') && f.endsWith('.json')) .sort() .reverse(); } catch (error) { return []; } } /** * Get current configuration version */ async getCurrentVersion() { const config = this.config.getConfig(); return config[this.VERSION_KEY] || '1.0.0'; } /** * Get latest available version */ getLatestVersion() { if (this.migrations.length === 0) return '1.0.0'; return this.migrations[this.migrations.length - 1].version; } /** * Get migration history */ getMigrationHistory() { return [...this.history]; } /** * Load migration history */ async loadHistory() { try { const data = await fs.readFile(this.HISTORY_PATH, 'utf-8'); this.history = JSON.parse(data).map((entry) => ({ ...entry, appliedAt: new Date(entry.appliedAt) })); } catch (error) { // History file might not exist yet this.history = []; } } /** * Save migration history */ async saveHistory() { const dir = path.dirname(this.HISTORY_PATH); await fs.mkdir(dir, { recursive: true }); await fs.writeFile(this.HISTORY_PATH, JSON.stringify(this.history, null, 2)); } /** * Clean old backups */ async cleanOldBackups() { const backups = await this.listBackups(); if (backups.length > 10) { const toDelete = backups.slice(10); for (const backup of toDelete) { await fs.unlink(path.join(this.BACKUP_PATH, backup)); } console.log(chalk.gray(` ๐Ÿงน Cleaned ${toDelete.length} old backups`)); } } /** * Export current configuration with version */ async exportConfiguration(outputPath) { const config = this.config.getConfig(); const version = await this.getCurrentVersion(); const exportData = { version, exportedAt: new Date().toISOString(), config }; await fs.writeFile(outputPath, JSON.stringify(exportData, null, 2)); console.log(chalk.green(`โœ… Configuration exported to ${outputPath}`)); } /** * Import configuration with migration */ async importConfiguration(inputPath) { const data = JSON.parse(await fs.readFile(inputPath, 'utf-8')); if (!data.version || !data.config) { throw new Error('Invalid configuration export file'); } // Create backup first await this.createBackup(await this.getCurrentVersion()); // Import the configuration await this.config.update(data.config); // Run migrations if needed const importedVersion = data.version; const latestVersion = this.getLatestVersion(); if (semver.lt(importedVersion, latestVersion)) { console.log(chalk.yellow(`๐Ÿ“ฆ Imported configuration needs migration: ${importedVersion} โ†’ ${latestVersion}`)); await this.runMigrations(); } console.log(chalk.green('โœ… Configuration imported successfully')); } } //# sourceMappingURL=ConfigurationMigration.js.map