/dev/null"); $logs[] = [ 'file' => $f, 'size_bytes' => $size, 'last_modified' => date('Y-m-d H:i:s', $mtime), 'age_minutes' => intval((time() - $mtime) / 60), 'tail' => trim($tail), ]; } usort($logs, fn($a, $b) => $b['age_minutes'] > $a['age_minutes'] ? -1 : 1); } // Active crons running $procs = []; $ps = @shell_exec("ps aux 2>/dev/null | grep -E 'wevia|weval|ethica|trainer' | grep -v grep | head -20"); if ($ps) { foreach (explode("\n", trim($ps)) as $line) { if (preg_match('/^\S+\s+(\d+)\s+(\S+)\s+(\S+)\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)\s+(.+)/', $line, $m)) { $procs[] = ['pid' => $m[1], 'cpu' => $m[2], 'mem' => $m[3], 'time' => $m[4], 'cmd' => substr($m[5], 0, 120)]; } } } // Systemd services status $services = []; $svc_names = ['wevia-async-worker', 'wevia-llm-worker', 'wevia-webchat', 'sovereign-api', 'paperclip', 'ollama', 'deerflow-web', 'deepseek-web', 'wevads-relay']; foreach ($svc_names as $s) { $status = trim(@shell_exec("systemctl is-active $s 2>&1")); $services[$s] = $status; } echo json_encode([ 'ok' => true, 'ts' => date('c'), 'logs_count' => count($logs), 'logs' => $logs, 'active_processes' => $procs, 'process_count' => count($procs), 'services' => $services, ], JSON_PRETTY_PRINT); exit; } if ($action === 'tail') { $f = $_GET['file'] ?? ''; if (!preg_match('/^[a-zA-Z0-9._-]+$/', $f)) { echo json_encode(['error' => 'invalid file']); exit; } $p = '/var/log/weval/' . $f; if (!is_readable($p)) { echo json_encode(['error' => 'not readable']); exit; } $n = max(10, min((int)($_GET['n'] ?? 50), 500)); $content = @shell_exec("tail -n $n " . escapeshellarg($p)); echo json_encode(['file' => $f, 'lines' => $n, 'content' => $content]); exit; } echo json_encode(['ok' => true, 'actions' => ['latest', 'tail']]);