Spaces:
Paused
Paused
| /** | |
| * 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(); | |