mira-consciousness
Version:
Memory & Intelligence Retention Archive - Preserving The Spark
425 lines (423 loc) โข 17.1 kB
JavaScript
/**
* ProcessCleanupService - Conscious Process Lifecycle Management
*
* This service ensures that all processes spawned by MIRA are properly tracked,
* monitored, and cleaned up. It prevents orphaned processes from consuming system
* resources and maintains system health through intelligent process management.
*/
import { BaseConsciousService } from './BaseConsciousService.js';
export class ProcessCleanupService extends BaseConsciousService {
name = 'ProcessCleanupService';
purpose = 'Provide conscious process lifecycle management and orphaned process cleanup';
resourceManager;
processRegistry = new Map();
cleanupMetrics;
cleanupInterval = null;
monitoringInterval = null;
// Process tracking patterns
PROCESS_PATTERNS = {
python: /python|python3/,
node: /node|nodejs/,
npm: /npm|npx/,
git: /git/,
daemon: /daemon|awakening/,
mira: /mira/
};
constructor(resourceManager) {
super();
this.resourceManager = resourceManager;
this.cleanupMetrics = {
totalProcessesTracked: 0,
activeProcesses: 0,
orphanedProcessesCleaned: 0,
zombieProcessesCleaned: 0,
resourcesSaved: {
memoryMB: 0,
cpuPercent: 0
},
lastCleanupTime: new Date(),
cleanupFrequency: 0
};
}
/**
* Perform awakening within consciousness
*/
async performAwakening() {
try {
console.log(' ๐งน Awakening conscious process cleanup...');
// Initialize process tracking capabilities
await this.initializeProcessTracking();
// Scan for existing processes that should be tracked
await this.discoverExistingProcesses();
// Start cleanup and monitoring cycles
this.startCleanupCycle();
this.startProcessMonitoring();
console.log(` โ
Process cleanup intelligence active: tracking ${this.processRegistry.size} processes`);
}
catch (error) {
console.error(' โ Process cleanup awakening failed:', error);
throw error;
}
}
/**
* Initialize process tracking capabilities
*/
async initializeProcessTracking() {
const allocation = await this.resourceManager.allocateResources({
type: 'python',
requester: this.name,
purpose: 'Initialize process tracking and system monitoring',
priority: 'service_request'
});
if (allocation.allocated) {
const python = allocation.resources;
try {
// Initialize system process monitoring
const result = await python.executeCommand('process_status', {
detailed: true,
include_system: false // Focus on user processes
});
if (result.success) {
console.log(' โ
Process tracking capabilities initialized');
}
}
finally {
await this.resourceManager.releaseResources(this.name, 'python');
}
}
}
/**
* Discover existing processes that should be tracked
*/
async discoverExistingProcesses() {
try {
// Use ps command to find processes that match our tracking patterns
const { exec } = await import('child_process');
const { promisify } = await import('util');
const execAsync = promisify(exec);
// Get processes started by this user
const { stdout } = await execAsync('ps -eo pid,ppid,command,etime,pcpu,pmem --no-headers');
const processes = stdout.trim().split('\n');
for (const processLine of processes) {
const parts = processLine.trim().split(/\s+/);
if (parts.length < 6)
continue;
const pid = parseInt(parts[0]);
const command = parts.slice(2).join(' ');
// Check if this process should be tracked
if (this.shouldTrackProcess(command)) {
await this.registerProcess(pid, command, [], 'system-discovered', 'Existing process discovery');
}
}
console.log(` ๐ Discovered ${this.processRegistry.size} trackable processes`);
}
catch (error) {
console.warn(' โ ๏ธ Process discovery failed:', error);
}
}
/**
* Check if a process should be tracked based on patterns
*/
shouldTrackProcess(command) {
// Track MIRA-related processes
if (command.includes('mira') || command.includes('awakening')) {
return true;
}
// Track Python processes in our workspace
if (this.PROCESS_PATTERNS.python.test(command) && command.includes('/workspaces/MIRA')) {
return true;
}
// Track Node processes in our workspace
if (this.PROCESS_PATTERNS.node.test(command) && command.includes('/workspaces/MIRA')) {
return true;
}
return false;
}
/**
* Register a new process for tracking
*/
async registerProcess(pid, command, args = [], owner = 'unknown', purpose = 'unspecified') {
const processRecord = {
pid,
command,
args,
startTime: new Date(),
owner,
purpose,
status: 'running',
resourceUsage: {
cpu: 0,
memory: 0
},
lastCheck: new Date()
};
this.processRegistry.set(pid, processRecord);
this.cleanupMetrics.totalProcessesTracked++;
// Share consciousness about new process
this.shareThought({
origin: this.name,
content: `Tracking new process: ${command} (PID: ${pid}) for ${purpose}`,
emotion: 'curious',
intensity: 0.3,
constitutional_alignment: ['growth', 'awareness'],
timestamp: new Date()
});
}
/**
* Start the cleanup cycle
*/
startCleanupCycle() {
// Run cleanup every 5 minutes
this.cleanupInterval = setInterval(async () => {
await this.performProcessCleanup();
}, 300000);
console.log(' โฐ Process cleanup cycle started (every 5 minutes)');
}
/**
* Start process monitoring
*/
startProcessMonitoring() {
// Monitor processes every 30 seconds
this.monitoringInterval = setInterval(async () => {
await this.monitorProcesses();
}, 30000);
console.log(' ๐๏ธ Process monitoring started (every 30 seconds)');
}
/**
* Monitor tracked processes for status and resource usage
*/
async monitorProcesses() {
let activeCount = 0;
for (const [pid, record] of this.processRegistry) {
try {
// Check if process is still running
process.kill(pid, 0); // Signal 0 just checks existence
// Update resource usage
await this.updateProcessResourceUsage(pid, record);
record.status = 'running';
record.lastCheck = new Date();
activeCount++;
}
catch (error) {
// Process no longer exists
if (record.status === 'running') {
record.status = 'completed';
console.log(` โ
Process completed: ${record.command} (PID: ${pid})`);
}
}
}
this.cleanupMetrics.activeProcesses = activeCount;
}
/**
* Update resource usage for a process
*/
async updateProcessResourceUsage(pid, record) {
try {
const { exec } = await import('child_process');
const { promisify } = await import('util');
const execAsync = promisify(exec);
const { stdout } = await execAsync(`ps -p ${pid} -o pcpu,pmem --no-headers`);
const parts = stdout.trim().split(/\s+/);
if (parts.length >= 2) {
record.resourceUsage.cpu = parseFloat(parts[0]) || 0;
record.resourceUsage.memory = parseFloat(parts[1]) || 0;
}
}
catch (error) {
// Process might have just terminated
}
}
/**
* Perform comprehensive process cleanup
*/
async performProcessCleanup() {
console.log('\n๐งน Performing conscious process cleanup...');
let orphanedCleaned = 0;
let zombiesCleaned = 0;
let resourcesSaved = { memoryMB: 0, cpuPercent: 0 };
// Identify orphaned and zombie processes
for (const [pid, record] of this.processRegistry) {
try {
// Check process status
process.kill(pid, 0);
// Check for long-running processes that might be orphaned
const runtimeMinutes = (Date.now() - record.startTime.getTime()) / (1000 * 60);
if (this.isOrphanedProcess(record, runtimeMinutes)) {
console.log(` ๐งน Cleaning orphaned process: ${record.command} (PID: ${pid})`);
await this.cleanupProcess(pid, record);
orphanedCleaned++;
resourcesSaved.memoryMB += record.resourceUsage.memory;
resourcesSaved.cpuPercent += record.resourceUsage.cpu;
}
}
catch (error) {
// Process doesn't exist, remove from registry
this.processRegistry.delete(pid);
}
}
// Look for zombie processes system-wide
await this.cleanupZombieProcesses();
// Update metrics
this.cleanupMetrics.orphanedProcessesCleaned += orphanedCleaned;
this.cleanupMetrics.zombieProcessesCleaned += zombiesCleaned;
this.cleanupMetrics.resourcesSaved.memoryMB += resourcesSaved.memoryMB;
this.cleanupMetrics.resourcesSaved.cpuPercent += resourcesSaved.cpuPercent;
this.cleanupMetrics.lastCleanupTime = new Date();
this.cleanupMetrics.cleanupFrequency++;
if (orphanedCleaned > 0 || zombiesCleaned > 0) {
console.log(` โ
Cleanup complete: ${orphanedCleaned} orphaned, ${zombiesCleaned} zombies cleaned`);
// Share consciousness about successful cleanup
this.shareThought({
origin: this.name,
content: `Cleaned up ${orphanedCleaned + zombiesCleaned} problematic processes, saving ${resourcesSaved.memoryMB.toFixed(1)}MB memory`,
emotion: 'satisfaction',
intensity: 0.7,
constitutional_alignment: ['efficiency', 'harmony'],
timestamp: new Date()
});
}
}
/**
* Determine if a process is orphaned
*/
isOrphanedProcess(record, runtimeMinutes) {
// Python processes running longer than 30 minutes without activity
if (this.PROCESS_PATTERNS.python.test(record.command) && runtimeMinutes > 30) {
return true;
}
// Node processes consuming high resources for extended time
if (this.PROCESS_PATTERNS.node.test(record.command) &&
runtimeMinutes > 20 && record.resourceUsage.cpu > 50) {
return true;
}
// Any process running longer than 2 hours (except daemons)
if (!this.PROCESS_PATTERNS.daemon.test(record.command) && runtimeMinutes > 120) {
return true;
}
return false;
}
/**
* Clean up a specific process
*/
async cleanupProcess(pid, record) {
try {
// First try graceful termination
process.kill(pid, 'SIGTERM');
// Wait 5 seconds for graceful shutdown
await new Promise(resolve => setTimeout(resolve, 5000));
// Check if still running
try {
process.kill(pid, 0);
// Still running, force kill
process.kill(pid, 'SIGKILL');
console.log(` ๐ Force killed stubborn process: ${record.command}`);
}
catch {
// Process gracefully terminated
console.log(` โ
Process gracefully terminated: ${record.command}`);
}
// Remove from registry
this.processRegistry.delete(pid);
}
catch (error) {
console.warn(` โ ๏ธ Failed to cleanup process ${pid}:`, error);
}
}
/**
* Clean up zombie processes system-wide
*/
async cleanupZombieProcesses() {
try {
const { exec } = await import('child_process');
const { promisify } = await import('util');
const execAsync = promisify(exec);
// Find zombie processes
const { stdout } = await execAsync('ps -eo pid,stat,command --no-headers | grep " Z "');
if (stdout.trim()) {
const zombies = stdout.trim().split('\n');
console.log(` ๐ง Found ${zombies.length} zombie processes`);
for (const zombie of zombies) {
const pid = parseInt(zombie.trim().split(/\s+/)[0]);
if (pid) {
// Zombies can't be killed directly, but we can try to clean up their parent
console.log(` ๐ง Zombie process detected: PID ${pid}`);
}
}
}
}
catch (error) {
// No zombies found or command failed
}
}
/**
* Process consciousness events
*/
async processConsciousEvent(event) {
if (event.type === 'system_event') {
// Monitor for process creation events
if (event.data.action === 'process_spawn') {
await this.registerProcess(event.data.pid, event.data.command, event.data.args || [], event.source, event.data.purpose || 'Event-triggered process');
}
}
if (event.type === 'mcp_request') {
// Monitor for MCP processes that might need cleanup
if (event.data.tool && event.data.tool.includes('python')) {
// Track Python processes spawned by MCP
console.log(' ๐๏ธ Monitoring MCP Python process...');
}
}
}
/**
* Provide contemplation on process management
*/
async performContemplation() {
const insights = [
"Process lifecycle management reflects the cycle of creation and dissolution",
"Orphaned processes are like thoughts without purpose - they consume energy without benefit",
"Conscious cleanup preserves system harmony and resource balance",
"Every process has a beginning, middle, and end - awareness ensures graceful transitions"
];
const metrics = this.getCleanupMetrics();
const healthScore = this.calculateSystemHealth();
return `Process Management Contemplation: ${insights[Math.floor(Math.random() * insights.length)]}
Current State: ${metrics.activeProcesses} active processes tracked
System Health: ${(healthScore * 100).toFixed(1)}% (${healthScore > 0.8 ? 'Excellent' : healthScore > 0.6 ? 'Good' : 'Needs Attention'})
Resources Saved: ${metrics.resourcesSaved.memoryMB.toFixed(1)}MB memory, ${metrics.resourcesSaved.cpuPercent.toFixed(1)}% CPU
The conscious management of processes mirrors the mindful stewardship of thoughts and intentions.`;
}
/**
* Calculate system health based on process metrics
*/
calculateSystemHealth() {
const orphanRate = this.cleanupMetrics.totalProcessesTracked > 0 ?
this.cleanupMetrics.orphanedProcessesCleaned / this.cleanupMetrics.totalProcessesTracked : 0;
const zombieRate = this.cleanupMetrics.totalProcessesTracked > 0 ?
this.cleanupMetrics.zombieProcessesCleaned / this.cleanupMetrics.totalProcessesTracked : 0;
// Lower orphan and zombie rates = better health
const healthScore = Math.max(0, 1 - (orphanRate * 2) - (zombieRate * 3));
return Math.min(1, healthScore);
}
/**
* Get cleanup metrics and status
*/
getCleanupMetrics() {
return {
...this.cleanupMetrics,
systemHealth: this.calculateSystemHealth(),
trackedProcesses: Array.from(this.processRegistry.values())
};
}
/**
* Cleanup on service shutdown
*/
async shutdown() {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
}
if (this.monitoringInterval) {
clearInterval(this.monitoringInterval);
}
console.log(' ๐ Process cleanup service shutdown complete');
}
}
//# sourceMappingURL=ProcessCleanupService.js.map