Kraft102's picture
Update backend source
34367da verified
/**
* 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();