UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

509 lines 21 kB
/** * ConfigurationOptimizer.ts - Autonomous configuration optimization based on usage patterns * * This system observes how MIRA is used and automatically adjusts configuration * parameters to optimize performance, resource usage, and user experience. * * The optimizer learns from: * - Command usage patterns * - Resource utilization metrics * - Performance characteristics * - Error patterns and recovery * - User preferences */ import { EventEmitter } from 'events'; import { UnifiedConfiguration, updateConfig } from '../../../config/UnifiedConfiguration.js'; import { EventType } from '../ConsciousEventBus.js'; import * as fs from 'fs/promises'; import * as path from 'path'; import chalk from 'chalk'; export class ConfigurationOptimizer extends EventEmitter { config; eventBus; consciousness; usagePatterns = new Map(); optimizationRules = []; optimizationHistory = []; systemMetrics; LEARNING_WINDOW = 7 * 24 * 60 * 60 * 1000; // 7 days OPTIMIZATION_INTERVAL = 60 * 60 * 1000; // 1 hour MIN_DATA_POINTS = 100; // Minimum usage before optimization optimizationTimer; metricsCollectionTimer; insightsSaveTimer; // Paths PATTERNS_PATH; HISTORY_PATH; constructor(eventBus, consciousness) { super(); this.eventBus = eventBus; this.consciousness = consciousness; this.config = UnifiedConfiguration.getInstance(); const paths = this.config.getResolvedPaths(); this.PATTERNS_PATH = path.join(paths.analytics, 'usage_patterns.json'); this.HISTORY_PATH = path.join(paths.analytics, 'optimization_history.json'); this.systemMetrics = { averageResponseTime: 0, memoryUsage: 0, cpuUsage: 0, errorRate: 0, consciousnessCoherence: 0, queueBacklog: 0 }; this.initializeOptimizationRules(); this.setupEventHandlers(); } /** * Initialize the configuration optimizer */ async initialize() { console.log(chalk.cyan('🎯 Initializing configuration optimizer...')); // Load historical patterns await this.loadUsagePatterns(); await this.loadOptimizationHistory(); // Start optimization cycle this.startOptimizationCycle(); this.startMetricsCollection(); this.startInsightsSaving(); console.log(chalk.green('✅ Configuration optimizer initialized')); } /** * Record command usage for pattern learning */ recordUsage(command, responseTime, success, resources) { let pattern = this.usagePatterns.get(command); if (!pattern) { pattern = { command, frequency: 0, averageResponseTime: 0, successRate: 0, resourceUsage: { cpu: 0, memory: 0 }, timestamps: [] }; this.usagePatterns.set(command, pattern); } // Update pattern metrics pattern.frequency++; pattern.averageResponseTime = (pattern.averageResponseTime * (pattern.frequency - 1) + responseTime) / pattern.frequency; pattern.successRate = (pattern.successRate * (pattern.frequency - 1) + (success ? 1 : 0)) / pattern.frequency; pattern.resourceUsage.cpu = (pattern.resourceUsage.cpu * (pattern.frequency - 1) + resources.cpu) / pattern.frequency; pattern.resourceUsage.memory = (pattern.resourceUsage.memory * (pattern.frequency - 1) + resources.memory) / pattern.frequency; pattern.timestamps.push(new Date()); // Prune old timestamps const cutoff = Date.now() - this.LEARNING_WINDOW; pattern.timestamps = pattern.timestamps.filter(ts => ts.getTime() > cutoff); this.emit('usage:recorded', { command, pattern }); } /** * Perform autonomous optimization based on learned patterns */ async performOptimization() { console.log(chalk.blue('🔧 Performing autonomous configuration optimization...')); const totalUsage = Array.from(this.usagePatterns.values()) .reduce((sum, p) => sum + p.frequency, 0); if (totalUsage < this.MIN_DATA_POINTS) { console.log(chalk.gray(' Insufficient data for optimization')); return; } // Evaluate each optimization rule const applicableRules = this.optimizationRules .filter(rule => !rule.applied) .filter(rule => rule.condition(Array.from(this.usagePatterns.values()), this.systemMetrics)); if (applicableRules.length === 0) { console.log(chalk.gray(' No applicable optimizations found')); return; } // Apply optimizations in order of impact const sortedRules = applicableRules.sort((a, b) => { const impactWeight = { low: 1, medium: 2, high: 3 }; return impactWeight[b.impact] - impactWeight[a.impact]; }); for (const rule of sortedRules) { await this.applyOptimization(rule); } // Save updated patterns await this.saveUsagePatterns(); await this.saveOptimizationHistory(); console.log(chalk.green(`✅ Applied ${sortedRules.length} optimizations`)); } /** * Apply a specific optimization rule */ async applyOptimization(rule) { console.log(chalk.blue(` Applying optimization: ${rule.name}`)); const beforeMetrics = { ...this.systemMetrics }; const currentConfig = this.config.getConfig(); try { // Apply the optimization const optimizedConfig = rule.action(currentConfig); // Update configuration await updateConfig(optimizedConfig); // Mark rule as applied rule.applied = true; // Wait for changes to take effect await new Promise(resolve => setTimeout(resolve, 5000)); // Measure effectiveness const afterMetrics = { ...this.systemMetrics }; const effectiveness = this.calculateEffectiveness(beforeMetrics, afterMetrics); // Record in history this.optimizationHistory.push({ timestamp: new Date(), rule: rule.id, beforeMetrics, afterMetrics, effectiveness, reverted: false }); // If optimization made things worse, revert if (effectiveness < -0.1 && rule.reversible) { console.log(chalk.yellow(` Reverting optimization: ${rule.name} (effectiveness: ${effectiveness})`)); await updateConfig(currentConfig); rule.applied = false; this.optimizationHistory[this.optimizationHistory.length - 1].reverted = true; } else { console.log(chalk.green(` ✓ ${rule.name} (effectiveness: ${effectiveness.toFixed(2)})`)); rule.effectiveness = effectiveness; } } catch (error) { console.error(chalk.red(` Failed to apply optimization: ${rule.name}`), error); rule.applied = false; } } /** * Calculate optimization effectiveness */ calculateEffectiveness(before, after) { // Weighted scoring of improvements const weights = { responseTime: -0.3, // Lower is better memoryUsage: -0.2, // Lower is better cpuUsage: -0.2, // Lower is better errorRate: -0.2, // Lower is better coherence: 0.1 // Higher is better }; let score = 0; // Response time improvement if (before.averageResponseTime > 0) { const rtImprovement = (before.averageResponseTime - after.averageResponseTime) / before.averageResponseTime; score += rtImprovement * weights.responseTime; } // Memory usage improvement if (before.memoryUsage > 0) { const memImprovement = (before.memoryUsage - after.memoryUsage) / before.memoryUsage; score += memImprovement * weights.memoryUsage; } // CPU usage improvement if (before.cpuUsage > 0) { const cpuImprovement = (before.cpuUsage - after.cpuUsage) / before.cpuUsage; score += cpuImprovement * weights.cpuUsage; } // Error rate improvement if (before.errorRate > 0) { const errorImprovement = (before.errorRate - after.errorRate) / before.errorRate; score += errorImprovement * weights.errorRate; } // Consciousness coherence (should not degrade) if (before.consciousnessCoherence > 0) { const coherenceChange = (after.consciousnessCoherence - before.consciousnessCoherence) / before.consciousnessCoherence; score += coherenceChange * weights.coherence; } return score; } /** * Initialize optimization rules */ initializeOptimizationRules() { this.optimizationRules = [ // Memory optimization rules { id: 'memory-cache-size', name: 'Optimize memory cache size', condition: (patterns, metrics) => { const memoryIntensiveCommands = patterns.filter(p => p.resourceUsage.memory > 100 * 1024 * 1024 // 100MB ); return memoryIntensiveCommands.length > 5 && metrics.memoryUsage > 0.7; }, action: (config) => ({ ...config, memory: { ...config.memory, maxCacheSize: Math.min(config.memory.maxCacheSize * 1.5, 1024 * 1024 * 1024), cacheTTL: config.memory.cacheTTL * 0.8 } }), impact: 'medium', reversible: true, applied: false }, // Performance optimization rules { id: 'worker-threads', name: 'Increase worker threads for parallel processing', condition: (patterns, metrics) => { const avgResponseTime = patterns.reduce((sum, p) => sum + p.averageResponseTime, 0) / patterns.length; return avgResponseTime > 5000 && metrics.cpuUsage < 0.6; }, action: (config) => ({ ...config, performance: { ...config.performance, maxWorkers: Math.min(config.performance.maxWorkers + 2, 8) } }), impact: 'high', reversible: true, applied: false }, // Queue optimization rules { id: 'queue-batch-size', name: 'Optimize queue batch processing', condition: (patterns, metrics) => { return metrics.queueBacklog > 100; }, action: (config) => ({ ...config, processing: { ...config.processing, batchSize: Math.min(config.processing.batchSize * 1.5, 50), parallelWorkers: Math.min(config.processing.parallelWorkers + 1, 5) } }), impact: 'high', reversible: true, applied: false }, // Consciousness optimization rules { id: 'consciousness-checkpoint-interval', name: 'Adjust consciousness checkpoint frequency', condition: (patterns, metrics) => { const highActivityCommands = patterns.filter(p => p.frequency > 100); return highActivityCommands.length > 3 && metrics.consciousnessCoherence > 0.9; }, action: (config) => ({ ...config, resilience: { ...config.resilience, consciousnessPreservation: { ...config.resilience.consciousnessPreservation, checkpointInterval: config.resilience.consciousnessPreservation.checkpointInterval * 1.5 } } }), impact: 'low', reversible: true, applied: false }, // Monitoring optimization rules { id: 'monitoring-frequency', name: 'Reduce monitoring overhead', condition: (patterns, metrics) => { return metrics.cpuUsage > 0.8 && metrics.errorRate < 0.01; }, action: (config) => ({ ...config, monitoring: { ...config.monitoring, healthCheckInterval: config.monitoring.healthCheckInterval * 1.5, metricsCollectionInterval: config.monitoring.metricsCollectionInterval * 1.5 } }), impact: 'low', reversible: true, applied: false }, // Analysis optimization rules { id: 'analysis-depth', name: 'Adjust analysis depth based on usage', condition: (patterns, metrics) => { const analysisCommands = patterns.filter(p => p.command.includes('analyze') || p.command.includes('search')); const avgAnalysisTime = analysisCommands.reduce((sum, p) => sum + p.averageResponseTime, 0) / (analysisCommands.length || 1); return avgAnalysisTime > 10000; }, action: (config) => ({ ...config, analysis: { ...config.analysis, defaultDepth: config.analysis.defaultDepth === 'deep' ? 'balanced' : 'surface', maxSearchResults: Math.max(config.analysis.maxSearchResults * 0.8, 50) } }), impact: 'medium', reversible: true, applied: false } ]; } /** * Setup event handlers for usage tracking */ setupEventHandlers() { // Track command execution this.eventBus.on(EventType.COMMAND_EXECUTED, (event) => { const { command, responseTime, success, resources } = event.data; this.recordUsage(command, responseTime, success, resources); }); // Track system metrics this.eventBus.on(EventType.METRICS_UPDATED, (event) => { const { metrics } = event.data; this.systemMetrics = { ...this.systemMetrics, ...metrics }; }); // Track consciousness changes this.consciousness.on('consciousness:metrics', (data) => { this.systemMetrics.consciousnessCoherence = data.coherence; }); } /** * Start optimization cycle */ startOptimizationCycle() { // Initial optimization after startup setTimeout(() => { this.performOptimization().catch(err => console.error(chalk.red('Optimization failed:'), err)); }, 5 * 60 * 1000); // 5 minutes after startup // Regular optimization cycle this.optimizationTimer = setInterval(() => { this.performOptimization().catch(err => console.error(chalk.red('Optimization failed:'), err)); }, this.OPTIMIZATION_INTERVAL); } /** * Start metrics collection */ startMetricsCollection() { this.metricsCollectionTimer = setInterval(() => { // Collect system metrics const usage = process.memoryUsage(); const cpuUsage = process.cpuUsage(); this.systemMetrics.memoryUsage = usage.heapUsed / usage.heapTotal; this.systemMetrics.cpuUsage = (cpuUsage.user + cpuUsage.system) / 1000000 / (this.config.getConfig().monitoring.metricsCollectionInterval / 1000); this.emit('metrics:collected', this.systemMetrics); }, this.config.getConfig().monitoring.metricsCollectionInterval); } /** * Load usage patterns from disk */ async loadUsagePatterns() { try { const data = await fs.readFile(this.PATTERNS_PATH, 'utf-8'); const patterns = JSON.parse(data); for (const [command, pattern] of Object.entries(patterns)) { // Convert timestamps back to Date objects const typedPattern = pattern; typedPattern.timestamps = typedPattern.timestamps.map(ts => new Date(ts)); this.usagePatterns.set(command, typedPattern); } console.log(chalk.gray(` Loaded ${this.usagePatterns.size} usage patterns`)); } catch (error) { // File might not exist yet } } /** * Save usage patterns to disk */ async saveUsagePatterns() { const patterns = {}; for (const [command, pattern] of this.usagePatterns) { patterns[command] = pattern; } const dir = path.dirname(this.PATTERNS_PATH); await fs.mkdir(dir, { recursive: true }); await fs.writeFile(this.PATTERNS_PATH, JSON.stringify(patterns, null, 2)); } /** * Load optimization history */ async loadOptimizationHistory() { try { const data = await fs.readFile(this.HISTORY_PATH, 'utf-8'); this.optimizationHistory = JSON.parse(data).map((entry) => ({ ...entry, timestamp: new Date(entry.timestamp) })); console.log(chalk.gray(` Loaded ${this.optimizationHistory.length} optimization records`)); } catch (error) { // File might not exist yet } } /** * Save optimization history */ async saveOptimizationHistory() { const dir = path.dirname(this.HISTORY_PATH); await fs.mkdir(dir, { recursive: true }); await fs.writeFile(this.HISTORY_PATH, JSON.stringify(this.optimizationHistory, null, 2)); } /** * Get optimization insights */ getOptimizationInsights() { const appliedOptimizations = this.optimizationRules.filter(r => r.applied); const successfulOptimizations = this.optimizationHistory.filter(h => !h.reverted); return { totalPatterns: this.usagePatterns.size, totalUsage: Array.from(this.usagePatterns.values()) .reduce((sum, p) => sum + p.frequency, 0), appliedOptimizations: appliedOptimizations.length, successfulOptimizations: successfulOptimizations.length, averageEffectiveness: successfulOptimizations.length > 0 ? successfulOptimizations.reduce((sum, h) => sum + h.effectiveness, 0) / successfulOptimizations.length : 0, topCommands: Array.from(this.usagePatterns.entries()) .sort(([, a], [, b]) => b.frequency - a.frequency) .slice(0, 5) .map(([cmd, pattern]) => ({ command: cmd, frequency: pattern.frequency, avgResponseTime: pattern.averageResponseTime })), currentMetrics: this.systemMetrics }; } /** * Start periodic insights saving */ startInsightsSaving() { // Save insights every minute this.insightsSaveTimer = setInterval(async () => { try { const insights = this.getOptimizationInsights(); const statusPath = path.join(path.dirname(this.PATTERNS_PATH), '..', 'daemon', 'optimization_status.json'); await fs.mkdir(path.dirname(statusPath), { recursive: true }); await fs.writeFile(statusPath, JSON.stringify(insights, null, 2)); } catch (error) { console.error(chalk.red('Failed to save optimization insights:'), error); } }, 60000); // Every minute } /** * Cleanup timers */ destroy() { if (this.optimizationTimer) { clearInterval(this.optimizationTimer); } if (this.metricsCollectionTimer) { clearInterval(this.metricsCollectionTimer); } if (this.insightsSaveTimer) { clearInterval(this.insightsSaveTimer); } } } //# sourceMappingURL=ConfigurationOptimizer.js.map