false, 'error'=>'message required']); exit; } $msg_lower = mb_strtolower($msg); $t_start = microtime(true); // === STEP 1: try opus4 stub trigger match === $stubs = @glob('/var/www/html/api/wired-pending/intent-opus4-*.php') ?: []; foreach ($stubs as $s) { $info = @include $s; if (!is_array($info) || empty($info['triggers'])) continue; $status = $info['status'] ?? ''; if (!in_array($status, ['EXECUTED', 'PENDING_APPROVAL'])) continue; foreach ($info['triggers'] as $trg) { $trg = trim($trg); if ($trg === '') continue; if (stripos($msg_lower, mb_strtolower($trg)) !== false) { $cmd = $info['cmd'] ?? ''; // Safety whitelist $safe = false; foreach (['/var/www/html/', 'echo ', 'curl ', 'php8.4 ', 'grep ', 'psql '] as $p) { if (stripos($cmd, $p) === 0 || stripos($cmd, " $p") !== false) { $safe = true; break; } } if (!$safe) continue; $out = @shell_exec('timeout 15 ' . $cmd . ' 2>&1'); $ms = round((microtime(true) - $t_start) * 1000); log_task([ 'ts' => date('c'), 'session' => $session, 'user' => $in['user'] ?? 'yacine', 'type' => 'dispatch', 'intent' => $info['name'], 'provider' => 'opus5-dispatch-proxy', 'trigger_matched' => $trg, 'message' => substr($msg, 0, 500), 'response' => substr(trim((string)$out), 0, 500), 'ms' => $ms, 'status' => 'ok' ]); http_response_code(200); echo json_encode([ 'response' => "Intent '{$info['name']}' executed (trigger: $trg)\n" . trim((string)$out), 'executed' => true, 'provider' => 'opus5-dispatch-proxy', 'intent' => $info['name'], 'trigger_matched' => $trg, 'ms' => $ms, 'session' => $session, 'output' => trim((string)$out) ], JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE); exit; } } } // === STEP 2: proxy to wevia-master-api === $ch = curl_init('http://127.0.0.1/api/wevia-master-api.php'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $raw, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 60 ]); $resp = curl_exec($ch); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $ms = round((microtime(true) - $t_start) * 1000); $decoded = @json_decode($resp, true); log_task([ 'ts' => date('c'), 'session' => $session, 'user' => $in['user'] ?? 'yacine', 'type' => 'proxy', 'intent' => $decoded['intent'] ?? $decoded['tool'] ?? null, 'provider' => $decoded['provider'] ?? 'master-api', 'message' => substr($msg, 0, 500), 'response' => substr((string)($decoded['content'] ?? $decoded['response'] ?? ''), 0, 500), 'ms' => $ms, 'status' => ($http === 200 ? 'ok' : 'upstream_error'), 'http' => $http ]); http_response_code(200); echo $resp ?: json_encode(['success'=>false, 'error'=>'upstream_error', 'http'=>$http, 'ms'=>$ms]);