mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
509 lines • 21 kB
JavaScript
/**
* 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