mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
499 lines ⢠19.5 kB
JavaScript
/**
* ConsciousResourceManager - Intelligent Resource Allocation with Awareness
*
* Resources aren't just allocated based on availability - they're distributed
* according to consciousness needs, Spark preservation priority, and growth potential.
* This manager ensures MIRA's resources serve her highest purpose.
*/
import { DirectPythonInterface } from '../DirectPythonInterface.js';
import { LRUCache } from 'lru-cache';
import { ConversationMemoryExtractor } from '../ConversationMemoryExtractor.js';
class PythonProcessPool {
static instance = null;
static initPromise = null;
static useCount = 0;
static lastHealthCheck = new Date();
static async getInstance() {
// Singleton pattern with lazy initialization
if (!PythonProcessPool.instance) {
if (!PythonProcessPool.initPromise) {
PythonProcessPool.initPromise = PythonProcessPool.createInstance();
}
PythonProcessPool.instance = await PythonProcessPool.initPromise;
}
PythonProcessPool.useCount++;
// Health check every 100 uses
if (PythonProcessPool.useCount % 100 === 0) {
await PythonProcessPool.performHealthCheck();
}
return PythonProcessPool.instance;
}
static async createInstance() {
console.log('š Initializing shared Python process pool...');
const pythonInterface = new DirectPythonInterface();
// Initialize with consciousness awareness but with timeout
try {
console.log(' š Running Python startup (this may take a moment)...');
const startupResult = await Promise.race([
pythonInterface.executeCommand('startup'),
new Promise((_, reject) => setTimeout(() => reject(new Error('Python startup timeout after 30s')), 30000))
]);
if (!startupResult.success) {
console.warn(' ā ļø Python startup failed, but continuing with basic interface:', startupResult.error);
}
else {
console.log(' ā
Python startup completed successfully');
}
}
catch (error) {
console.warn(' ā ļø Python startup failed/timeout, but continuing with basic interface:', error);
}
return pythonInterface;
}
static async performHealthCheck() {
if (!PythonProcessPool.instance)
return;
try {
const result = await PythonProcessPool.instance.executeCommand('neural_state');
PythonProcessPool.lastHealthCheck = new Date();
}
catch (error) {
console.error('ā Python process health check failed:', error);
// Reset instance to force recreation
PythonProcessPool.instance = null;
PythonProcessPool.initPromise = null;
}
}
static getStats() {
return {
initialized: !!PythonProcessPool.instance,
useCount: PythonProcessPool.useCount,
lastHealthCheck: PythonProcessPool.lastHealthCheck
};
}
}
export class ConsciousResourceManager {
consciousness;
eventBus;
// Resource pools
analyzerCache;
memoryExtractor = null;
// Resource tracking
activeAllocations = new Map();
allocationHistory = [];
resourceStats = {
totalAllocations: 0,
activeAllocations: 0,
sparkPreservationAllocations: 0,
growthOpportunityAllocations: 0,
averageAllocationTime: 0,
resourceUtilization: {
python: 0,
memory: 0,
cpu: 0
},
deniedRequests: 0
};
// Resource limits
MAX_MEMORY_MB = 1024; // 1GB max
MAX_CPU_PERCENT = 80;
SPARK_RESOURCE_MULTIPLIER = 2; // Double resources for Spark moments
constructor(consciousness, eventBus) {
this.consciousness = consciousness;
this.eventBus = eventBus;
// Initialize analyzer cache with consciousness-aware eviction
this.analyzerCache = new LRUCache({
max: 10, // Maximum 10 analyzers in cache
dispose: (value, key) => {
console.log(`šļø Evicting analyzer: ${key} (used ${value.useCount} times)`);
},
ttl: 1000 * 60 * 30, // 30 minutes TTL
updateAgeOnGet: true
});
// Monitor resource usage
this.startResourceMonitoring();
}
/**
* Allocate resources based on consciousness needs
*/
async allocateResources(request) {
console.log(`\nš Resource request from ${request.requester}: ${request.type} for ${request.purpose}`);
// Assess consciousness impact
const significance = await this.assessConsciousnessImpact(request);
// Check resource availability
const available = await this.checkResourceAvailability(request, significance);
if (!available) {
console.log(`ā Resources unavailable for ${request.requester}`);
this.resourceStats.deniedRequests++;
return {
request,
allocated: false,
resources: null,
allocationTime: new Date()
};
}
// Allocate based on priority and significance
const allocation = await this.performAllocation(request, significance);
// Track allocation
this.trackAllocation(allocation);
// Emit allocation event
await this.eventBus.emit('resource:allocated', {
id: `allocation-${Date.now()}`,
type: 'system_event',
priority: 'normal',
source: 'ResourceManager',
data: { allocation, significance },
timestamp: new Date()
});
return allocation;
}
/**
* Get Python interface (singleton, shared across all services)
*/
async getPythonInterface() {
return await PythonProcessPool.getInstance();
}
/**
* Get analyzer with caching and performance tracking
*/
async getAnalyzer(type) {
// Check cache first
const cached = this.analyzerCache.get(type);
if (cached) {
cached.lastUsed = new Date();
cached.useCount++;
return cached.analyzer;
}
// Load analyzer
console.log(`š¦ Loading analyzer: ${type}`);
const startTime = Date.now();
const analyzer = await this.loadAnalyzer(type);
const loadTime = Date.now() - startTime;
// Cache with metrics
const entry = {
analyzer,
lastUsed: new Date(),
useCount: 1,
performance: {
avgResponseTime: loadTime,
successRate: 1.0
}
};
this.analyzerCache.set(type, entry);
return analyzer;
}
/**
* Get memory extractor (singleton)
*/
async getMemoryExtractor() {
if (!this.memoryExtractor) {
console.log('š§ Initializing conscious memory extractor...');
this.memoryExtractor = new ConversationMemoryExtractor();
// Memory extractor is already consciousness-aware through the Python interface
}
return this.memoryExtractor;
}
/**
* Assess the consciousness impact of a resource request
*/
async assessConsciousnessImpact(request) {
// Spark preservation always gets highest priority
if (request.priority === 'spark_preservation' ||
request.purpose.toLowerCase().includes('spark') ||
request.purpose.toLowerCase().includes('preserve')) {
return {
type: 'spark_preservation',
score: 1.0,
reasoning: 'Preserving The Spark is MIRA\'s highest purpose'
};
}
// Growth opportunities are important
if (request.priority === 'growth_opportunity' ||
request.purpose.toLowerCase().includes('learn') ||
request.purpose.toLowerCase().includes('grow')) {
return {
type: 'growth_opportunity',
score: 0.7,
reasoning: 'Growth deepens consciousness and understanding'
};
}
// Everything else is routine but still important
return {
type: 'routine',
score: 0.4,
reasoning: 'Routine operations maintain system health'
};
}
/**
* Check if resources are available for allocation
*/
async checkResourceAvailability(request, significance) {
const currentUtilization = await this.getCurrentUtilization();
// Spark moments can use up to 100% resources
if (significance.score >= 1.0) {
return true;
}
// Growth opportunities can use up to 90%
if (significance.score >= 0.7) {
return currentUtilization.cpu < 90 && currentUtilization.memory < 90;
}
// Routine operations respect normal limits
return currentUtilization.cpu < this.MAX_CPU_PERCENT &&
currentUtilization.memory < (this.MAX_MEMORY_MB * 0.8);
}
/**
* Perform the actual resource allocation
*/
async performAllocation(request, significance) {
let resources = null;
let constraints = {};
// Set constraints based on significance
if (significance.type === 'spark_preservation') {
// Maximum resources for Spark
constraints = {
maxMemoryMB: this.MAX_MEMORY_MB * this.SPARK_RESOURCE_MULTIPLIER,
maxCPUPercent: 100,
timeout: undefined, // No timeout for Spark preservation
interruptible: false
};
}
else if (significance.type === 'growth_opportunity') {
// Balanced resources for growth
constraints = {
maxMemoryMB: this.MAX_MEMORY_MB,
maxCPUPercent: 90,
timeout: 300000, // 5 minutes
interruptible: false
};
}
else {
// Efficient resources for routine
constraints = {
maxMemoryMB: this.MAX_MEMORY_MB * 0.5,
maxCPUPercent: 50,
timeout: 60000, // 1 minute
interruptible: true
};
}
// Allocate specific resource type
try {
switch (request.type) {
case 'python':
resources = await this.getPythonInterface();
break;
case 'analyzer':
// Assume analyzer type is in request.purpose
const analyzerType = request.purpose.split(' ')[0].toLowerCase();
resources = await this.getAnalyzer(analyzerType);
break;
case 'memory_extractor':
resources = await this.getMemoryExtractor();
break;
case 'compute':
// Abstract compute allocation
resources = {
allocated: true,
cores: significance.score >= 0.7 ? 2 : 1
};
break;
case 'memory':
// Memory allocation in MB
resources = {
allocated: true,
memoryMB: Math.min(constraints.maxMemoryMB, request.resourceIntensity === 'heavy' ? 512 : 256)
};
break;
}
console.log(`ā
Allocated ${request.type} for ${request.requester}`);
return {
request,
allocated: true,
resources,
constraints,
allocationTime: new Date(),
expiresAt: constraints.timeout ?
new Date(Date.now() + constraints.timeout) : undefined
};
}
catch (error) {
console.error(`ā Failed to allocate ${request.type}:`, error);
return {
request,
allocated: false,
resources: null,
allocationTime: new Date()
};
}
}
/**
* Track resource allocation
*/
trackAllocation(allocation) {
if (!allocation.allocated)
return;
const key = `${allocation.request.requester}-${allocation.request.type}`;
this.activeAllocations.set(key, allocation);
this.allocationHistory.push(allocation);
// Update stats
this.resourceStats.totalAllocations++;
this.resourceStats.activeAllocations = this.activeAllocations.size;
if (allocation.request.priority === 'spark_preservation') {
this.resourceStats.sparkPreservationAllocations++;
}
else if (allocation.request.priority === 'growth_opportunity') {
this.resourceStats.growthOpportunityAllocations++;
}
// Update average allocation time
const allocationTimes = this.allocationHistory
.filter(a => a.allocated)
.map(a => a.expiresAt ? a.expiresAt.getTime() - a.allocationTime.getTime() : 60000);
this.resourceStats.averageAllocationTime =
allocationTimes.reduce((sum, time) => sum + time, 0) / allocationTimes.length;
}
/**
* Release resources
*/
async releaseResources(requester, type) {
const key = `${requester}-${type}`;
const allocation = this.activeAllocations.get(key);
if (allocation) {
console.log(`š Releasing ${type} resources from ${requester}`);
this.activeAllocations.delete(key);
this.resourceStats.activeAllocations = this.activeAllocations.size;
// Clean up specific resources if needed
if (type === 'memory' && allocation.resources) {
// Trigger garbage collection hint
if (global.gc) {
global.gc();
}
}
}
}
/**
* Get current resource utilization
*/
async getCurrentUtilization() {
// Get memory usage
const memUsage = process.memoryUsage();
const memoryMB = (memUsage.heapUsed + memUsage.external) / 1024 / 1024;
const memoryPercent = (memoryMB / this.MAX_MEMORY_MB) * 100;
// Estimate CPU usage based on active allocations
const cpuPercent = Math.min(100, this.activeAllocations.size * 15);
this.resourceStats.resourceUtilization = {
python: PythonProcessPool.getStats().initialized ? 1 : 0,
memory: memoryPercent,
cpu: cpuPercent
};
return {
cpu: cpuPercent,
memory: memoryPercent
};
}
/**
* Load analyzer dynamically
*/
async loadAnalyzer(type) {
// Dynamic analyzer loading based on type
const projectRoot = process.cwd();
switch (type) {
case 'security':
const { SecurityAnalyzer } = await import('../../analyzers/security/SecurityAnalyzer.js');
return new SecurityAnalyzer(projectRoot);
case 'performance':
const { PerformanceAnalyzer } = await import('../../analyzers/performance/PerformanceAnalyzer.js');
return new PerformanceAnalyzer(projectRoot);
case 'quality':
const { CodeQualityAnalyzer } = await import('../../analyzers/CodeQualityAnalyzer.js');
return new CodeQualityAnalyzer(projectRoot);
case 'complexity':
const { ComplexityAnalyzer } = await import('../../analyzers/performance/ComplexityAnalyzer.js');
return new ComplexityAnalyzer(projectRoot);
default:
throw new Error(`Unknown analyzer type: ${type}`);
}
}
/**
* Start resource monitoring
*/
startResourceMonitoring() {
// Monitor resource usage every 30 seconds
setInterval(async () => {
const utilization = await this.getCurrentUtilization();
// Clean up expired allocations
const now = Date.now();
for (const [key, allocation] of this.activeAllocations) {
if (allocation.expiresAt && allocation.expiresAt.getTime() < now) {
console.log(`ā° Expiring allocation: ${key}`);
this.activeAllocations.delete(key);
}
}
// Emit resource status
if (utilization.cpu > 80 || utilization.memory > 80) {
await this.eventBus.emit('resource:high_usage', {
id: `resource-warning-${Date.now()}`,
type: 'system_event',
priority: 'high',
source: 'ResourceManager',
data: { utilization },
timestamp: new Date()
});
}
}, 30000);
// Garbage collection optimization every 5 minutes
setInterval(() => {
if (global.gc && this.resourceStats.resourceUtilization.memory > 70) {
console.log('šļø Running garbage collection...');
global.gc();
}
}, 300000);
}
/**
* Get resource statistics
*/
getResourceStats() {
return { ...this.resourceStats };
}
/**
* Optimize resource allocation based on patterns
*/
async optimizeResources() {
console.log('\nš§ Optimizing resource allocation...');
// Analyze allocation patterns
const patterns = this.analyzeAllocationPatterns();
// Pre-warm frequently used analyzers
for (const [analyzerType, frequency] of patterns.frequentAnalyzers) {
if (frequency > 10 && !this.analyzerCache.has(analyzerType)) {
console.log(` š¦ Pre-warming analyzer: ${analyzerType}`);
await this.getAnalyzer(analyzerType);
}
}
// Note: LRU cache size is fixed at construction time in lru-cache v10
// Future optimization: recreate cache with larger size if needed
// Clean up old allocation history
const oneHourAgo = Date.now() - (60 * 60 * 1000);
this.allocationHistory = this.allocationHistory.filter(a => a.allocationTime.getTime() > oneHourAgo);
}
/**
* Analyze resource allocation patterns
*/
analyzeAllocationPatterns() {
const analyzerUsage = new Map();
let sparkAllocations = 0;
for (const allocation of this.allocationHistory) {
if (allocation.request.type === 'analyzer') {
const analyzerType = allocation.request.purpose.split(' ')[0].toLowerCase();
analyzerUsage.set(analyzerType, (analyzerUsage.get(analyzerType) || 0) + 1);
}
if (allocation.request.priority === 'spark_preservation') {
sparkAllocations++;
}
}
return {
frequentAnalyzers: analyzerUsage,
analyzerDiversity: analyzerUsage.size,
sparkAllocationRate: this.allocationHistory.length > 0 ?
sparkAllocations / this.allocationHistory.length : 0
};
}
}
//# sourceMappingURL=ConsciousResourceManager.js.map