"auth"]); exit; } $goal = $_REQUEST["goal"] ?? ""; $max_steps = intval($_REQUEST["max_steps"] ?? 15); $mode = $_REQUEST["mode"] ?? "auto"; // auto, plan_only, execute if (!$goal) { echo json_encode(["error" => "no goal"]); exit; } // === AI PROVIDERS === function callAI($system, $messages, $timeout = 15) { global $secrets; /* OPUS3-BLADE-SCOPE-FIX */ // OPUS3-SOVEREIGN-FIRST: route via local cascade (auto-retry multi-provider) array_unshift($providers, ["url" => "http://127.0.0.1:4000/v1/chat/completions", "key" => "none", "model" => "auto"]); $providers = [ ["url" => "https://api.cerebras.ai/v1/chat/completions", "key" => ($secrets["CEREBRAS_API_KEY"] ?? "csk-4wrrhkpr568ry9xx49k9mcynwdx483nx53dd62yh5xedfckh"), "model" => "qwen-3-235b-a22b-instruct-2507" /* OPUS3-BLADE-PROVIDERS-FIX */], ["url" => "https://api.groq.com/openai/v1/chat/completions", "key" => ($secrets["GROQ_KEY"]??""), "model" => "qwen-3-235b-a22b-instruct-2507-versatile"], ["url" => "https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions", "key" => "sk-34db1ad3152443cd86563d1bfc576c30", "model" => "qwen-plus"], ]; $allMessages = array_merge([["role" => "system", "content" => $system]], $messages); foreach ($providers as $p) { $ch = curl_init($p["url"]); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_TIMEOUT => $timeout, CURLOPT_HTTPHEADER => ["Content-Type: application/json", "Authorization: Bearer " . $p["key"]], CURLOPT_POSTFIELDS => json_encode([ "model" => $p["model"], "messages" => $allMessages, "max_tokens" => 2048, "temperature" => 0.3 ]) ]); $r = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($code === 200) { $d = json_decode($r, true); return $d["choices"][0]["message"]["content"] ?? ""; } } return ""; } // === EXECUTE COMMAND === function execCommand($cmd, $type = "powershell") { $BLADE_API = "https://weval-consulting.com/api/blade-api.php?k=BLADE2026"; // Push task and wait for result $taskId = "agent_" . uniqid(); $pushUrl = "$BLADE_API&action=push&type=$type&priority=10&label=" . urlencode("Agent: " . substr($cmd, 0, 50)); $pushUrl .= "&cmd=" . urlencode($cmd); $ch = curl_init($pushUrl); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10]); $r = json_decode(curl_exec($ch), true); curl_close($ch); $pushedId = $r["task"]["id"] ?? ""; if (!$pushedId) return ["error" => "push_failed", "detail" => $r]; // Poll for result (max 60s) for ($i = 0; $i < 12; $i++) { sleep(5); $ch = curl_init("$BLADE_API&action=list"); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5]); $list = json_decode(curl_exec($ch), true); curl_close($ch); foreach ($list["tasks"] ?? [] as $t) { if ($t["id"] === $pushedId) { if ($t["status"] === "done") { return ["ok" => true, "result" => $t["result"] ?? "", "status" => "done"]; } if ($t["status"] === "failed") { return ["ok" => false, "error" => $t["error"] ?? "", "status" => "failed"]; } } } } return ["ok" => false, "error" => "timeout_60s", "status" => "timeout"]; } // === EXECUTE ON SERVER (via CX/SSH) === function execServer($server, $cmd) { if ($server === "s204") { $sentinel = "sudo ssh -p 49222 -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i /root/.ssh/wevads_key root@10.1.0.2 " . $cmd; $url = "http://10.1.0.3:5890/api/sentinel-brain.php?action=exec&cmd=" . urlencode($sentinel); } elseif ($server === "s95") { $url = "http://10.1.0.3:5890/api/sentinel-brain.php?action=exec&cmd=" . urlencode($cmd); } elseif ($server === "s151") { $sentinel = "sudo ssh -o StrictHostKeyChecking=no ubuntu@151.80.235.110 " . $cmd; $url = "http://10.1.0.3:5890/api/sentinel-brain.php?action=exec&cmd=" . urlencode($sentinel); } else { return ["error" => "unknown server"]; } // Route through CX $cxCmd = "curl -s \"$url\""; $encoded = base64_encode($cxCmd); $ch = curl_init("https://weval-consulting.com/api/cx"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_TIMEOUT => 30, CURLOPT_POSTFIELDS => "k=WEVADS2026&c=$encoded" ]); $r = json_decode(curl_exec($ch), true); curl_close($ch); return ["ok" => true, "result" => $r["output"] ?? ""]; } // === AGENT SYSTEM PROMPT === $AGENT_SYSTEM = << "user", "content" => "OBJECTIF: $goal"]]; $steps = []; $done = false; for ($step = 0; $step < $max_steps && !$done; $step++) { // Ask AI for next action $response = callAI($AGENT_SYSTEM, $messages); if (!$response) { $steps[] = ["step" => $step + 1, "error" => "AI provider failed"]; break; } // Parse JSON action — robust extraction $action = null; // Try to find JSON in response $start = strpos($response, '{'); if ($start !== false) { $depth = 0; $end = $start; for ($j = $start; $j < strlen($response); $j++) { if ($response[$j] === '{') $depth++; if ($response[$j] === '}') { $depth--; if ($depth === 0) { $end = $j; break; } } } $jsonStr = substr($response, $start, $end - $start + 1); // Fix common AI escaping issues $jsonStr = str_replace(["\\'", '\\"', '\\n'], ["'", '"', "\n"], $jsonStr); $action = json_decode($jsonStr, true); if (!$action) { // Try cleaning more aggressively $jsonStr = preg_replace('/\\{2,}/', '\\', $jsonStr); $action = json_decode($jsonStr, true); } } if (!$action || !isset($action["action"])) { // AI returned text instead of JSON — add to context and retry $messages[] = ["role" => "assistant", "content" => $response]; $messages[] = ["role" => "user", "content" => "Réponds en JSON strict: {\"action\":\"...\",\"cmd\":\"...\"}"]; $steps[] = ["step" => $step + 1, "type" => "retry", "raw" => substr($response, 0, 200)]; continue; } $stepResult = ["step" => $step + 1, "action" => $action["action"]]; switch ($action["action"]) { case "exec_blade": $result = execCommand($action["cmd"] ?? "", $action["type"] ?? "powershell"); $stepResult["cmd"] = $action["cmd"]; $stepResult["result"] = $result; $messages[] = ["role" => "assistant", "content" => $response]; $messages[] = ["role" => "user", "content" => "Résultat: " . json_encode($result) . "\nQuelle est la prochaine étape?"]; break; case "exec_server": $result = execServer($action["server"] ?? "s204", $action["cmd"] ?? ""); $stepResult["server"] = $action["server"]; $stepResult["cmd"] = $action["cmd"]; $stepResult["result"] = $result; $messages[] = ["role" => "assistant", "content" => $response]; $messages[] = ["role" => "user", "content" => "Résultat: " . json_encode($result) . "\nQuelle est la prochaine étape?"]; break; case "think": $stepResult["thought"] = $action["thought"] ?? ""; $messages[] = ["role" => "assistant", "content" => $response]; $messages[] = ["role" => "user", "content" => "OK, exécute la prochaine action."]; break; case "done": $stepResult["summary"] = $action["summary"] ?? ""; $done = true; break; default: $stepResult["error"] = "unknown action: " . $action["action"]; $messages[] = ["role" => "assistant", "content" => $response]; $messages[] = ["role" => "user", "content" => "Action inconnue. Utilise exec_blade, exec_server, think, ou done."]; } $steps[] = $stepResult; } // Output echo json_encode([ "ok" => $done, "goal" => $goal, "steps" => count($steps), "max_steps" => $max_steps, "log" => $steps, "completed" => $done ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);