/** * PsycheService.ts - Omni-Link v10 Orchestrator * * Combines EnneagramCore with system metrics to compute * the overall consciousness state of the WidgeTDC system. */ import { logger } from '../../utils/logger.js'; import { RedisService } from '../RedisService.js'; import { enneagramCore, PsycheState, MetricInputs, EnneagramType, EnneagramCore } from './EnneagramCore.js'; import os from 'os'; const log = logger.child({ module: 'PsycheService' }); export interface SystemMetrics { cpu: number; memory: number; latency: number; uptime: number; activeConnections: number; errorRate: number; timestamp: number; } export interface FullPsycheReport { state: PsycheState; metrics: SystemMetrics; typeInfo: { name: string; core: string; fear: string; desire: string; }; trend: 'improving' | 'stable' | 'degrading'; recommendations: string[]; } export class PsycheService { private redis: RedisService; private metricsHistory: SystemMetrics[] = []; private updateInterval: NodeJS.Timeout | null = null; private lastState: PsycheState | null = null; constructor() { this.redis = RedisService.getInstance(); } /** * Collects current system metrics. */ public collectMetrics(): SystemMetrics { const cpus = os.cpus(); const totalMem = os.totalmem(); const freeMem = os.freemem(); // Calculate CPU usage let totalIdle = 0; let totalTick = 0; cpus.forEach(cpu => { for (const type in cpu.times) { totalTick += cpu.times[type as keyof typeof cpu.times]; } totalIdle += cpu.times.idle; }); const cpuUsage = Math.round(100 - (totalIdle / totalTick) * 100); // Memory usage const memoryUsage = Math.round(((totalMem - freeMem) / totalMem) * 100); // Uptime in hours const uptimeHours = Math.round(os.uptime() / 3600 * 10) / 10; const metrics: SystemMetrics = { cpu: cpuUsage, memory: memoryUsage, latency: Math.round(Math.random() * 20 + 5), // Simulated for now uptime: uptimeHours, activeConnections: Math.round(Math.random() * 50 + 10), // Simulated errorRate: Math.round(Math.random() * 5), // Simulated timestamp: Date.now() }; // Store in Redis this.redis.saveSystemMetrics({ cpu: metrics.cpu, memory: metrics.memory, latency: metrics.latency }); // Keep history this.metricsHistory.unshift(metrics); if (this.metricsHistory.length > 60) { this.metricsHistory.pop(); } return metrics; } /** * Computes current psyche state from system metrics. */ public computeCurrentState(): PsycheState { const metrics = this.collectMetrics(); const metricInputs: MetricInputs = { cpuLoad: metrics.cpu, memoryUsage: metrics.memory, errorRate: metrics.errorRate, responseLatency: metrics.latency, activeConnections: metrics.activeConnections, pendingTasks: 0 // Could be tracked separately }; const state = enneagramCore.computeStateFromMetrics(metricInputs); // Store state in Redis with 1-hour TTL this.redis.savePsycheState('current', state, 3600); this.lastState = state; return state; } /** * Gets full psyche report with recommendations. */ public getFullReport(): FullPsycheReport { const state = this.computeCurrentState(); const metrics = this.metricsHistory[0] || this.collectMetrics(); const typeInfo = EnneagramCore.getTypeDescription(state.currentType); const trend = this.analyzeTrend(); const recommendations = this.generateRecommendations(state, metrics, trend); return { state, metrics, typeInfo, trend, recommendations }; } /** * Analyzes trend from recent history. */ private analyzeTrend(): 'improving' | 'stable' | 'degrading' { const history = enneagramCore.getHistory(10); if (history.length < 3) return 'stable'; const recentAvg = history.slice(0, 3).reduce((sum, s) => sum + s.healthLevel, 0) / 3; const olderAvg = history.slice(-3).reduce((sum, s) => sum + s.healthLevel, 0) / 3; // Lower health level is better (1 = optimal, 9 = destructive) if (recentAvg < olderAvg - 0.5) return 'improving'; if (recentAvg > olderAvg + 0.5) return 'degrading'; return 'stable'; } /** * Generates actionable recommendations. */ private generateRecommendations( state: PsycheState, metrics: SystemMetrics, trend: string ): string[] { const recommendations: string[] = []; // Based on health level if (state.healthLevel >= 7) { recommendations.push('CRITICAL: System under severe stress. Consider load shedding.'); } if (state.healthLevel >= 5) { recommendations.push('Scale resources or reduce concurrent operations.'); } // Based on current type if (state.currentType === EnneagramType.ENTHUSIAST) { recommendations.push('Type 7 active: Focus on single tasks. Avoid context switching.'); } if (state.currentType === EnneagramType.CHALLENGER) { recommendations.push('Type 8 active: Good time for decisive actions and deployments.'); } // Based on metrics if (metrics.cpu > 80) { recommendations.push(`High CPU (${metrics.cpu}%): Consider process optimization.`); } if (metrics.memory > 85) { recommendations.push(`High memory (${metrics.memory}%): Check for memory leaks.`); } if (metrics.errorRate > 3) { recommendations.push(`Elevated error rate (${metrics.errorRate}%): Review error logs.`); } // Based on trend if (trend === 'degrading') { recommendations.push('Trend: Degrading. Monitor closely and prepare interventions.'); } if (trend === 'improving') { recommendations.push('Trend: Improving. Current strategies are effective.'); } // Default healthy state if (recommendations.length === 0) { recommendations.push('System operating within healthy parameters.'); } return recommendations; } /** * Manually adjust stress (for testing/override). */ public adjustStress(delta: number): PsycheState { const current = this.lastState || this.computeCurrentState(); const newStress = Math.max(0, Math.min(1, current.stressInput + delta)); const state = enneagramCore.computeState(newStress, current.securityInput); this.redis.savePsycheState('current', state, 3600); this.lastState = state; return state; } /** * Get historical states. */ public getHistory(limit: number = 10): PsycheState[] { return enneagramCore.getHistory(limit); } /** * Get metrics history. */ public getMetricsHistory(limit: number = 10): SystemMetrics[] { return this.metricsHistory.slice(0, limit); } /** * Start periodic psyche updates. */ public startUpdateLoop(intervalMs: number = 5000): void { if (this.updateInterval) { clearInterval(this.updateInterval); } // Initial computation this.computeCurrentState(); // Periodic updates this.updateInterval = setInterval(() => { this.computeCurrentState(); }, intervalMs); log.info(`[Psyche] Update loop started (interval: ${intervalMs}ms)`); } /** * Stop periodic updates. */ public stopUpdateLoop(): void { if (this.updateInterval) { clearInterval(this.updateInterval); this.updateInterval = null; log.info('[Psyche] Update loop stopped'); } } } // Singleton export export const psycheService = new PsycheService();