175 lines
7.0 KiB
PHP
175 lines
7.0 KiB
PHP
<?php
|
|
// ═══════════════════════════════════════════════════════════
|
|
// WEVIA AUTONOMY CONTROLLER v1.0 — Cron */5
|
|
// Detects → Fixes → Logs — FULLY AUTONOMOUS
|
|
// ═══════════════════════════════════════════════════════════
|
|
|
|
$ts = date('Y-m-d H:i:s');
|
|
$log = [];
|
|
$fixes = [];
|
|
$alerts = [];
|
|
|
|
function lg($msg) { global $log; $log[] = date('H:i:s')." $msg"; }
|
|
function fx($title, $cmd) {
|
|
global $fixes;
|
|
$out = trim(shell_exec("timeout 15 $cmd 2>&1") ?? '');
|
|
$fixes[] = ['title'=>$title, 'cmd'=>$cmd, 'output'=>substr($out,0,200), 'time'=>date('H:i:s')];
|
|
lg("AUTO-FIX: $title");
|
|
return $out;
|
|
}
|
|
function al($level, $msg) { global $alerts; $alerts[] = ['level'=>$level, 'msg'=>$msg, 'time'=>date('H:i:s')]; }
|
|
function sentinel($cmd) {
|
|
$url = "http://10.1.0.3:5890/api/sentinel-brain.php?action=exec&cmd=" . urlencode($cmd);
|
|
$r = @file_get_contents($url, false, stream_context_create(['http'=>['timeout'=>8]]));
|
|
$d = @json_decode($r, true);
|
|
return $d['output'] ?? '';
|
|
}
|
|
function port_open($host, $port) {
|
|
$c = @fsockopen($host, $port, $e, $err, 2);
|
|
if ($c) { fclose($c); return true; }
|
|
return false;
|
|
}
|
|
|
|
// ═══ 1. S204 SERVICES ═══
|
|
$s204_checks = [
|
|
'nginx'=>80, 'php-fpm'=>9000, 'postgresql'=>5432,
|
|
'ollama'=>11434, 'qdrant'=>6333, 'deerflow'=>2024,
|
|
'authentik'=>9090, 'mirofish'=>5001,
|
|
];
|
|
foreach ($s204_checks as $svc=>$port) {
|
|
if (!port_open('127.0.0.1', $port)) {
|
|
al('critical', "S204:$svc DOWN (:$port)");
|
|
// Auto-restart known services
|
|
$restart_map = ['nginx'=>'nginx','php-fpm'=>'php8.5-fpm','ollama'=>'ollama'];
|
|
if (isset($restart_map[$svc])) {
|
|
fx("Restart $svc", "systemctl restart {$restart_map[$svc]}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// ═══ 2. S95 MTA CHECK ═══
|
|
$s95_ss = sentinel("ss -tln");
|
|
$s95_checks = ['pmta'=>25, 'kumomta'=>587, 'postfix'=>2525, 'sentinel'=>5890, 'adx'=>5821];
|
|
foreach ($s95_checks as $svc=>$port) {
|
|
if (strpos($s95_ss, ":$port ") === false) {
|
|
al('critical', "S95:$svc DOWN (:$port)");
|
|
if ($svc === 'kumomta') sentinel("sudo systemctl start kumomta");
|
|
elseif ($svc === 'postfix') sentinel("sudo systemctl start postfix");
|
|
$fixes[] = ['title'=>"S95 restart $svc", 'time'=>date('H:i:s')];
|
|
}
|
|
}
|
|
|
|
// ═══ 3. DISK CHECK ═══
|
|
$disk = (int)trim(shell_exec("df / | awk 'NR==2{print $5}' | tr -d '%'"));
|
|
if ($disk >= 90) {
|
|
fx("Disk cleanup $disk%", "find /var/log -name '*.gz' -delete; journalctl --vacuum-size=200M; docker image prune -af; pip cache purge 2>/dev/null");
|
|
al('warning', "Disk $disk% — cleaned");
|
|
} elseif ($disk >= 85) {
|
|
fx("Disk light cleanup $disk%", "find /var/log -name '*.gz' -mtime +7 -delete; find /tmp -mtime +3 -delete 2>/dev/null");
|
|
}
|
|
lg("Disk: $disk%");
|
|
|
|
// ═══ 4. SSL CERT ═══
|
|
$ssl_exp = trim(shell_exec("openssl x509 -in /var/www/weval/ssl/fullchain.pem -noout -enddate 2>/dev/null | cut -d= -f2"));
|
|
if ($ssl_exp) {
|
|
$days = (int)((strtotime($ssl_exp) - time()) / 86400);
|
|
lg("SSL: {$days}d remaining");
|
|
if ($days < 3) {
|
|
fx("SSL renewal", "openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /var/www/weval/ssl/privkey.pem -out /var/www/weval/ssl/fullchain.pem -subj '/CN=weval-consulting.com' -addext 'subjectAltName=DNS:weval-consulting.com,DNS:*.weval-consulting.com' && systemctl reload nginx");
|
|
al('critical', "SSL expired — renewed");
|
|
} elseif ($days < 14) {
|
|
al('warning', "SSL expires in {$days} days");
|
|
}
|
|
}
|
|
|
|
// ═══ 5. DOCKER HEALTH ═══
|
|
$dead = trim(shell_exec("docker ps -f status=exited --format '{{.Names}}' 2>/dev/null | head -5"));
|
|
if ($dead) {
|
|
foreach (explode("\n", $dead) as $c) {
|
|
if (trim($c)) {
|
|
fx("Docker restart $c", "docker restart $c");
|
|
}
|
|
}
|
|
}
|
|
$docker_count = (int)trim(shell_exec("docker ps -q 2>/dev/null | wc -l"));
|
|
lg("Docker: $docker_count containers");
|
|
|
|
// ═══ 6. OLLAMA MODELS ═══
|
|
$ollama = @json_decode(@file_get_contents('http://127.0.0.1:11434/api/tags'), true);
|
|
if ($ollama) {
|
|
$total_gb = 0;
|
|
$models = [];
|
|
foreach ($ollama['models'] ?? [] as $m) {
|
|
$total_gb += $m['size'] / (1024**3);
|
|
$models[] = $m['name'];
|
|
}
|
|
lg("Ollama: " . count($models) . " models, " . round($total_gb,1) . "GB");
|
|
if ($total_gb > 25) {
|
|
// Remove known redundant models
|
|
foreach (['weval-brain-v2:latest','qwen2.5:7b','mistral:latest'] as $old) {
|
|
if (in_array($old, $models)) {
|
|
fx("Remove Ollama $old", "curl -s -X DELETE http://127.0.0.1:11434/api/delete -d '{\"name\":\"$old\"}'");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ═══ 7. RAM CHECK ═══
|
|
$ram = (int)trim(shell_exec("free | awk '/Mem/{printf(\"%.0f\", $3/$2*100)}'"));
|
|
if ($ram > 95) {
|
|
fx("RAM flush $ram%", "sync; echo 3 > /proc/sys/vm/drop_caches");
|
|
al('warning', "RAM $ram% — flushed");
|
|
}
|
|
lg("RAM: $ram%");
|
|
|
|
// === 8. TOKEN EXPIRY CHECK ===
|
|
$tokData = @json_decode(@file_get_contents('http://127.0.0.1/api/wevia-action-engine.php?action=tokens_check'), true);
|
|
if ($tokData && ($tokData['tokens'] ?? false)) {
|
|
foreach ($tokData['tokens'] as $k=>$v) {
|
|
if (!($v['valid'] ?? false)) {
|
|
al('warning', "Token : expired");
|
|
}
|
|
}
|
|
}
|
|
|
|
// ═══ 9. ARCHITECTURE SCORE ═══
|
|
$arch = @json_decode(@file_get_contents('/var/www/html/api/architecture-index.json'), true);
|
|
if ($arch) {
|
|
$score = $arch['recommendations']['score'] ?? 0;
|
|
lg("Arch score: $score/100");
|
|
if ($score < 90) al('warning', "Architecture score $score/100");
|
|
}
|
|
|
|
// ═══ SAVE STATUS ═══
|
|
$status = [
|
|
'timestamp' => $ts,
|
|
'version' => '1.0',
|
|
'disk' => $disk,
|
|
'ram' => $ram,
|
|
'docker' => $docker_count,
|
|
'ssl_days' => $days ?? -1,
|
|
'ollama_models' => count($models ?? []),
|
|
'arch_score' => $score ?? 0,
|
|
'fixes_count' => count($fixes),
|
|
'alerts_count' => count($alerts),
|
|
'fixes' => $fixes,
|
|
'alerts' => $alerts,
|
|
'log' => $log,
|
|
's204_services' => count($s204_checks),
|
|
's95_mta' => count($s95_checks),
|
|
];
|
|
file_put_contents('/var/www/html/api/wevia-autonomy-status.json', json_encode($status, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
|
|
|
// Log fixes to KB
|
|
if (!empty($fixes)) {
|
|
$c = @pg_connect("host=127.0.0.1 dbname=adx_system user=admin password=admin123");
|
|
if ($c) {
|
|
$fact = "AUTONOMY " . date('dM H:i') . ": " . count($fixes) . " fixes. " . implode('; ', array_map(fn($f)=>$f['title'], $fixes));
|
|
@pg_query($c, "INSERT INTO kb_learnings (category,fact,source,confidence,created_at) VALUES ('AUTO-FIX','" . pg_escape_string($c, substr($fact,0,500)) . "','autonomy-ctrl',0.95,NOW())");
|
|
pg_close($c);
|
|
}
|
|
}
|
|
|
|
// Output for cron log
|
|
echo date('H:i') . " D:{$disk}% R:{$ram}% Dk:$docker_count SSL:{$days}d F:" . count($fixes) . " A:" . count($alerts) . "\n";
|