Files
html/api/wevia-autonomy-controller.php
2026-04-16 02:28:32 +02:00

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";