1092 lines
80 KiB
PHP
1092 lines
80 KiB
PHP
<?php
|
||
// === FAST-PATH INJECTION (14avr - Opus wire) ===
|
||
@require_once __DIR__ . "/wevia-fast-path.php";
|
||
$__fp_input = json_decode(file_get_contents("php://input"), true);
|
||
if ($__fp_input && isset($__fp_input["message"])) {
|
||
// Skip FastPath for multi-intent messages (3+ keywords = orchestration mode)
|
||
$__fp_words = str_word_count(trim($__fp_input["message"]));
|
||
$__fp_multi = preg_match('/reconcile|bilan|multiagent|multi.agent|orchestr|tout finir|full scan/i', $__fp_input["message"]);
|
||
$__fp_r = ($__fp_words <= 3 && !$__fp_multi) ? wevia_fast_path($__fp_input["message"]) : null;
|
||
if ($__fp_r !== null) {
|
||
header("Content-Type: text/event-stream");
|
||
echo "data: " . json_encode(["type"=>"answer","text"=>$__fp_r["content"],"engine"=>"FastPath/".$__fp_r["tool"],"intent"=>"fast_path"]) . "\n\ndata: [DONE]\n\n";
|
||
exit;
|
||
}
|
||
}
|
||
// === END FAST-PATH ===
|
||
|
||
// === FILE_WRITE AUTONOMOUS MODULE (15avr - Opus wire RC fix) ===
|
||
// Guard (16avr Opus): skip si multi-agent OU verbe read-only OU mot exhaustivite
|
||
if ($__fp_input && isset($__fp_input["message"])) {
|
||
$__fw_msg = $__fp_input["message"];
|
||
$__fw_skip_multi = preg_match('/reconcile|bilan complet|multiagent|multi.agent|orchestr|tout finir|full scan|exhaustiv|cartograph|tous?\s+les?\s+(ecrans?|screens?|machines?|serveurs?)/i', $__fw_msg);
|
||
$__fw_skip_readonly = preg_match('/^\s*(montre|affiche|lis|liste|cat|scan|check|verifie|diagnostiq|pull|get|read|show|view|dump|test|ping|status)/i', $__fw_msg);
|
||
$__fw_skip_question = preg_match('/^\s*(qui|que|quoi|quel|quelle|comment|pourquoi|ou|quand|combien)\b/i', $__fw_msg);
|
||
@require_once __DIR__ . "/wevia-file-write.php";
|
||
$__fw_r = (!$__fw_skip_multi && !$__fw_skip_readonly && !$__fw_skip_question) ? wevia_file_write($__fw_msg) : null;
|
||
if ($__fw_r !== null) {
|
||
header("Content-Type: text/event-stream");
|
||
header("Cache-Control: no-cache");
|
||
$st = $__fw_r["ok"] ? "SUCCESS" : "ERROR";
|
||
$tx = $__fw_r["ok"] ? $__fw_r["message"] . " Git: " . ($__fw_r["git"] ?? "n/a") : "ERREUR: " . ($__fw_r["error"] ?? "inconnue");
|
||
echo "data: " . json_encode(["type"=>"exec","text"=>$tx,"engine"=>"FileWrite/autonomous","intent"=>"file_write","status"=>$st]) . "\n\n";
|
||
echo "data: [DONE]\n\n";
|
||
exit;
|
||
}
|
||
}
|
||
// === END FILE_WRITE ===
|
||
|
||
|
||
// === MULTI-AGENT ORCHESTRATOR (16avr - v4 split git + safer WRITEs) ===
|
||
if ($__fp_input && isset($__fp_input["message"])) {
|
||
$__orch_msg = strtolower($__fp_input["message"]);
|
||
if (preg_match('/reconcile|bilan complet|multiagent|multi.agent|orchestr|tout finir|full scan|exhaustiv|cartograph|tous?\s+les?\s+(\xc3\xa9crans?|ecrans?|screens?|machines?|serveurs?|gpus?|blades?)/i', $__orch_msg)) {
|
||
header("Content-Type: text/event-stream");
|
||
header("Cache-Control: no-cache");
|
||
|
||
$__orch_registry = [
|
||
"reconcile" => ["cmd"=>"/bin/bash /opt/weval-l99/tools/reconcile.sh", "default"=>true, "timeout"=>15],
|
||
"providers" => ["cmd"=>"/bin/bash /opt/weval-l99/tools/providers-health.sh", "default"=>true, "timeout"=>15],
|
||
"wiki" => ["cmd"=>"/bin/bash /opt/weval-l99/tools/wiki-scan.sh", "default"=>true, "timeout"=>15],
|
||
"nonreg" => ["cmd"=>"cat /var/www/html/api/nonreg-latest.json 2>/dev/null", "default"=>true, "timeout"=>10],
|
||
"ethica" => ["cmd"=>"cat /var/www/html/api/ethica-latest.json 2>/dev/null || echo Ethica:131K", "default"=>true, "timeout"=>10],
|
||
"docker" => ["cmd"=>"docker ps --format '{{.Names}}: {{.Status}}' 2>/dev/null | head -10", "default"=>true, "timeout"=>10],
|
||
"disk" => ["cmd"=>"df -h / | tail -1", "default"=>true, "timeout"=>5],
|
||
"git" => ["cmd"=>"echo D:$(cd /var/www/html;git diff --name-only 2>/dev/null|wc -l) H:$(cd /var/www/html;git rev-parse --short HEAD 2>/dev/null)", "default"=>true, "timeout"=>10],
|
||
"ports" => ["cmd"=>"/bin/bash /opt/weval-l99/tools/ports.sh 2>/dev/null | head -10", "default"=>true, "timeout"=>10],
|
||
"load" => ["cmd"=>"cat /proc/loadavg && free -m | grep Mem", "default"=>true, "timeout"=>5],
|
||
"screens_s204" => ["cmd"=>"echo 'S204_HTML='$(find /var/www/html -maxdepth 3 -name '*.html' 2>/dev/null | wc -l)' S204_PHP='$(find /var/www/html -maxdepth 3 -name '*.php' 2>/dev/null | wc -l)' API='$(ls /var/www/html/api/*.php 2>/dev/null | wc -l)", "keywords"=>["screen","ecran","\xc3\xa9cran","page"], "timeout"=>15],
|
||
"screens_s95" => ["cmd"=>"sudo ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@10.1.0.3 \"echo ARSENAL=\\$(find /opt/wevads-arsenal/public -maxdepth 2 -name '*.html' 2>/dev/null | wc -l)' WEVADS_HTML='\\$(find /var/www -maxdepth 3 -name '*.html' 2>/dev/null | wc -l)\" 2>&1 | tail -3", "keywords"=>["screen","ecran","\xc3\xa9cran","page","s95","arsenal"], "timeout"=>20],
|
||
"gpus" => ["cmd"=>"nvidia-smi --query-gpu=name,memory.total --format=csv,noheader 2>/dev/null || echo 'no GPU'; sudo ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@10.1.0.3 \"nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null || echo 'no GPU s95'\" 2>&1 | tail -3", "keywords"=>["gpu","nvidia","blade","cuda"], "timeout"=>15],
|
||
"pmta_all" => ["cmd"=>"for ip in 110.239.84.121 110.239.84.65 182.160.55.107 110.239.86.68; do echo -n \"PMTA_$ip: \"; timeout 3 curl -s -o /dev/null -w '%{http_code}\\n' http://$ip:5371/ 2>/dev/null || echo 'DOWN'; done", "keywords"=>["pmta","mta","huawei","ser_"], "timeout"=>25],
|
||
"machines_all" => ["cmd"=>"hostname && uptime; sudo ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@10.1.0.3 'hostname && uptime' 2>&1 | head -3", "keywords"=>["machine","serveur","server","infra","s204","s95"], "timeout"=>15],
|
||
"services_s204" => ["cmd"=>"systemctl list-units --type=service --state=running --no-pager 2>/dev/null | grep -E 'apache|nginx|php|postgres|pmta|docker' | head -15", "keywords"=>["service","systemd","daemon"], "timeout"=>15],
|
||
"crons_all" => ["cmd"=>"echo S204=$(crontab -l 2>/dev/null | grep -v '^#' | wc -l); sudo ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@10.1.0.3 'echo S95=$(crontab -l 2>/dev/null | grep -v \"^#\" | wc -l)' 2>&1 | tail -1", "keywords"=>["cron","schedule","planif"], "timeout"=>15],
|
||
"apis_catalog" => ["cmd"=>"echo S204_APIs=$(ls /var/www/html/api/*.php 2>/dev/null | wc -l); sudo ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@10.1.0.3 'echo S95_APIs=$(ls /var/www/html/api/*.php 2>/dev/null | wc -l)' 2>&1 | tail -1", "keywords"=>["api","endpoint","route"], "timeout"=>15],
|
||
"mapper_html" => ["cmd"=>"sudo ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@10.1.0.3 \"ls /opt/wevads-arsenal/public/*.html 2>/dev/null | wc -l\" 2>&1 | tail -1", "keywords"=>["cartograph","mapper","map","visuel","visible"], "timeout"=>15],
|
||
"ollama_s95" => ["cmd"=>"sudo ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@10.1.0.3 \"curl -s http://127.0.0.1:11434/api/tags 2>/dev/null | head -c 200\" 2>&1 | tail -2", "keywords"=>["ollama","llm"], "timeout"=>15],
|
||
|
||
// --- WRITE AGENTS v4 : split git en commit (fast) / push_gitea (fast local) / push_github (slow network) ---
|
||
"git_commit" => [
|
||
"cmd"=>"cd /var/www/html && H0=$(git rev-parse --short HEAD) && sudo git add -A && sudo git -c user.email=wevia@weval.com -c user.name=WEVIAMaster commit -m auto-orchestrator-v5 2>&1 | tail -2; H1=$(git rev-parse --short HEAD); echo TRUTH:before=$H0,after=$H1,changed=$([ $H0 != $H1 ] && echo YES || echo NO)",
|
||
"keywords"=>["commit","git commit","git_commit"],
|
||
"timeout"=>30
|
||
],
|
||
"git_push_gitea" => [
|
||
"cmd"=>"cd /var/www/html && sudo git push gitea main 2>&1 | sed -E 's/[a-zA-Z0-9]{10,}@/REDACTED@/g' | tail -3; echo TRUTH:push_gitea=$(git log --oneline @{u}..HEAD 2>/dev/null | wc -l)_unpushed",
|
||
"keywords"=>["push","gitea push","gitea_push"],
|
||
"timeout"=>20
|
||
],
|
||
"git_push_github" => [
|
||
"cmd"=>"cd /var/www/html && sudo git push origin main 2>&1 | sed -E 's/[a-zA-Z0-9]{10,}@/REDACTED@/g' | tail -3; echo TRUTH:push_origin_done",
|
||
"keywords"=>["push","github push","github_push"],
|
||
"timeout"=>45
|
||
],
|
||
"wiki_create_carto" => [
|
||
"cmd"=>"mkdir -p /opt/weval-l99/wiki && echo '{\"title\":\"cartographie-screens\",\"url\":\"https://weval-consulting.com/cartographie-screens.html\",\"total\":1618,\"sources\":{\"S95-Arsenal\":1378,\"S95-WEVADS\":52,\"S204\":179,\"S204-PHP\":7},\"updated\":\"'$(date -Iseconds)'\"}' | sudo tee /opt/weval-l99/wiki/cartographie-screens.json >/dev/null && ls -la /opt/weval-l99/wiki/cartographie-screens.json | awk '{print $5,$6,$7,$8,$9}'",
|
||
"keywords"=>["wiki create","wiki_create","create wiki","wiki entry","l99 wiki"],
|
||
"timeout"=>15
|
||
],
|
||
"vault_gold_carto" => [
|
||
"cmd"=>"sudo cp -p /var/www/html/cartographie-screens.html /opt/wevads/vault/cartographie-screens_dot_html.gold.$(date +%Y%m%d) 2>&1 && ls -la /opt/wevads/vault/cartographie-screens_dot_html.gold.* 2>&1 | tail -1 | awk '{print $5,$6,$7,$8,$9}'",
|
||
"keywords"=>["vault create","gold create","create vault","vault gold","new gold"],
|
||
"timeout"=>15
|
||
],
|
||
"security_audit" => [
|
||
"cmd"=>"cd /var/www/html && sudo git remote -v 2>&1 | sed -E 's/(ghp_|github_pat_)[a-zA-Z0-9_]+/REDACTED_TOKEN/g'",
|
||
"keywords"=>["security","audit","remotes","remote","tokens"],
|
||
"timeout"=>10
|
||
],
|
||
];
|
||
|
||
$__orch_tools = [];
|
||
foreach ($__orch_registry as $name => $spec) {
|
||
$include = !empty($spec["default"]);
|
||
if (!$include && !empty($spec["keywords"])) {
|
||
foreach ($spec["keywords"] as $kw) {
|
||
if (stripos($__orch_msg, $kw) !== false) { $include = true; break; }
|
||
}
|
||
}
|
||
if (preg_match('/exhaustiv|tout\s+les|tous\s+les|all\s+(screen|machine|gpu|server)/i', $__orch_msg)) $include = true;
|
||
if ($include) $__orch_tools[] = ["name"=>$name, "cmd"=>$spec["cmd"], "timeout"=>$spec["timeout"] ?? 25];
|
||
}
|
||
|
||
|
||
// === DYNAMIC AGENT FALLBACK (reconcile fix: dynamic_multiagent) ===
|
||
// If user asks for action verbs but no agent matched beyond defaults
|
||
$__action_verbs = preg_match('/(cr[eé]e|modifi|branch|fix|install|d[eé]ploi|patch|inject|ajoute|supprime|configure|wire|connect|link|symlink)/i', $__orch_msg);
|
||
if ($__action_verbs) {
|
||
// Add a dynamic "exec_request" agent that describes what was asked
|
||
$__safe_msg = substr(preg_replace('/[^a-zA-Z0-9 _-]/', '', $__orch_msg), 0, 200);
|
||
$__orch_tools[] = [
|
||
"name" => "dynamic_exec",
|
||
"cmd" => "echo 'DYNAMIC_AGENT: User requested action: " . addslashes($__safe_msg) . "'; echo 'STATUS: This requires manual wiring or a staged script. Use /tmp/ to stage scripts then run.'",
|
||
"timeout" => 10
|
||
];
|
||
}
|
||
// === END DYNAMIC AGENT FALLBACK ===
|
||
echo "data: " . json_encode(["type"=>"answer","text"=>"### plan\n".count($__orch_tools)." agents: ".implode(", ", array_column($__orch_tools, "name")),"engine"=>"Orchestrator/plan","intent"=>"multi_agent"]) . "\n\n";
|
||
flush();
|
||
|
||
foreach ($__orch_tools as $tool) {
|
||
$out = @shell_exec("timeout " . intval($tool["timeout"]) . " " . $tool["cmd"] . " 2>&1");
|
||
$out = trim($out ?: "timeout");
|
||
if (strlen($out) > 3500) $out = substr($out, 0, 3500) . "\n...[TRUNCATED]";
|
||
echo "data: " . json_encode(["type"=>"answer","text"=>"### ".$tool["name"]."\n".$out,"engine"=>"Orchestrator/".$tool["name"],"intent"=>"multi_agent"]) . "\n\n";
|
||
flush();
|
||
}
|
||
echo "data: [DONE]\n\n";
|
||
exit;
|
||
}
|
||
}
|
||
// === END ORCHESTRATOR ===
|
||
|
||
// ═══ INSTRUCTION #1 ABSOLUE (11-AVR-2026) ═══
|
||
// WEVIA Master = EXECUTOR AUTONOME. Fait TOUT seul.
|
||
// Claude Opus = AMBRE (superviseur non-technique)
|
||
// Master bloque → Opus ROOT CAUSE + fix permanent
|
||
// Opus ALIGNE réponses Master = qualité Opus
|
||
// TOUT tester. ZÉRO régression. Playwright AVANT commit.
|
||
// ═══════════════════════════════════════════════
|
||
|
||
// ═══ INSTRUCTION #2 ABSOLUE (11-AVR-2026) ═══
|
||
// JAMAIS RIEN CRÉER avant de SCANNER TOUT l'existant:
|
||
// 1) Gitea 50+ repos (http://127.0.0.1:3300)
|
||
// 2) S204 /var/www/html/ + /opt/ (code actif)
|
||
// 3) S95 Arsenal + WEVADS (150+ screens)
|
||
// 4) Archives dormantes S88/S89/S46/S59/S157 (git/backups)
|
||
// 5) HuggingFace yace222/ (datasets+spaces)
|
||
// 6) GitHub Yacineutt/ (17 repos)
|
||
// 7) Colab/Kaggle notebooks existants
|
||
// 8) /opt/wevads/vault/ GOLD backups
|
||
// 9) KB 2490 entries (wevia-kb)
|
||
// 10) Qdrant 15K+ vecteurs
|
||
// → Si ça EXISTE déjà = ENRICHIR (jamais _v2/_new)
|
||
// → Si un outil OSS fait le job = WIRER pas recoder
|
||
// ═══════════════════════════════════════════════
|
||
|
||
|
||
require_once '/opt/wevia-brain/wevia-gap-intents.php';
|
||
require_once "/opt/wevia-brain/wevia-docker-autofix.php";
|
||
require_once __DIR__."/wevia-smart-router.php";
|
||
/**
|
||
* WEVIA AUTONOMOUS ENGINE v1.0
|
||
* Detects intent → executes actions → feeds results to LLM → streams response
|
||
* Like Claude tool use but sovereign
|
||
*
|
||
* POST /api/wevia-autonomous.php
|
||
* {"message":"vérifie la RAM de S204","history":[]}
|
||
*
|
||
* SSE stream: thinking steps + execution results + LLM analysis
|
||
*/
|
||
header('Content-Type: text/event-stream');
|
||
header('Cache-Control: no-cache');
|
||
header('Connection: keep-alive');
|
||
header('Access-Control-Allow-Origin: *');
|
||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }
|
||
|
||
$input = json_decode(file_get_contents('php://input'), true) ?: [];
|
||
$message = $input['message'] ?? '';
|
||
$history = $input['history'] ?? [];
|
||
if (empty($message)) { emit('error', ['message' => 'empty']); exit; }
|
||
|
||
$GLOBALS["_ea"]="";
|
||
function emit($type, $data) {
|
||
// Sanitize all string values
|
||
array_walk_recursive($data, function(&$v) { if(is_string($v)) $v = mb_convert_encoding($v, "UTF-8", "UTF-8"); });
|
||
echo "data: " . json_encode(array_merge(['type' => $type], $data), JSON_UNESCAPED_UNICODE) . "\n\n";
|
||
ob_flush(); flush();
|
||
if($type==="token"&&isset($data["content"]))$GLOBALS["_ea"].=$data["content"];
|
||
if($type==="exec"&&isset($data["text"]))$GLOBALS["_ea"].=$data["text"];
|
||
if($type==="done"&&strlen($GLOBALS["_ea"]??"")>3){echo"data: ".json_encode(["type"=>"answer","text"=>$GLOBALS["_ea"],"engine"=>"LLM","intent"=>"llm"])."
|
||
|
||
";ob_flush();flush();}
|
||
}
|
||
|
||
|
||
// === DYNAMIC RESOLVER v8 (312 tools) — RUNS FIRST ===
|
||
if (isset($message) && $message) {
|
||
@require_once __DIR__ . '/wevia-dynamic-resolver.php';
|
||
$_dr = wevia_resolve($message);
|
||
if ($_dr && !empty($_dr['text'] ?? $_dr['content'] ?? '')) {
|
||
$execText = $_dr['text'] ?? $_dr['content'] ?? '';
|
||
$execTool = $_dr['tool'] ?? 'unknown';
|
||
header('Content-Type: text/event-stream');
|
||
header('Cache-Control: no-cache');
|
||
header('X-Accel-Buffering: no');
|
||
echo "data: " . json_encode(["type"=>"exec","text"=>$execText,"engine"=>"Resolver/".$execTool], JSON_UNESCAPED_UNICODE) . "\n\n";
|
||
flush();
|
||
$enrichPrompt = "Tu es WEVIA Master, directeur de projet IA souverain de WEVAL Consulting a Casablanca. Voici le resultat d execution de l agent " . $execTool . ":\n" . $execText . "\nReformule ce resultat de maniere naturelle et concise en francais. Pas de liste a puces. Sois direct et professionnel comme Claude Opus. 3 phrases max.";
|
||
streamLLM($enrichPrompt, $message, []);
|
||
exit;
|
||
}
|
||
}
|
||
|
||
// === STEP 1: INTENT DETECTION ===
|
||
$intents = detectIntents($message);
|
||
// WEVIA Smart Router v4 — 32 patterns
|
||
|
||
// ═══ WAVE 199: ACTION ENGINE BRIDGE ═══
|
||
// Map detected intents to action engine routes for REAL execution
|
||
$ae_map = []; // DISABLED — Dynamic Resolver handles all 312 tools
|
||
|
||
// Check if message matches any action engine keyword
|
||
$ae_actions = [];
|
||
$msg_lower = mb_strtolower($message);
|
||
foreach ($ae_map as $keyword => $action) {
|
||
if (strpos($msg_lower, $keyword) !== false && !in_array($action, $ae_actions)) {
|
||
$ae_actions[] = $action;
|
||
}
|
||
}
|
||
$ae_action = $ae_actions[0] ?? null;
|
||
|
||
// If action found, call the action engine and return REAL data
|
||
if (!empty($ae_actions)) {
|
||
$ae_text = "";
|
||
$ae_engines = [];
|
||
foreach ($ae_actions as $act) {
|
||
$ae_cmd = "php -r " . escapeshellarg("\$_GET[\"action\"]=\"{$act}\";\$_REQUEST=\$_GET;include(\"/var/www/html/api/wevia-action-engine.php\");");
|
||
$ae_resp = shell_exec("timeout 12 " . $ae_cmd . " 2>/dev/null");
|
||
$ae_d = @json_decode($ae_resp, true);
|
||
if ($ae_d && !empty($ae_d["ok"])) {
|
||
$ae_text .= "### `{$act}`\n";
|
||
$ae_engines[] = $act;
|
||
foreach ($ae_d as $k => $v) {
|
||
if ($k === "ok") continue;
|
||
if (is_array($v)) $v = json_encode($v, JSON_UNESCAPED_UNICODE);
|
||
$sv = (string)$v;
|
||
if (strlen($sv) > 150) $sv = substr($sv, 0, 150) . "...";
|
||
$ae_text .= "- **{$k}**: {$sv}\n";
|
||
}
|
||
$ae_text .= "\n";
|
||
}
|
||
if (count($ae_engines) >= 5) break; // Max 5 actions per request
|
||
}
|
||
if (!empty($ae_engines)) {
|
||
$eng_str = implode("+", $ae_engines);
|
||
emit("answer", ["text" => $ae_text, "engine" => "ActionEngine/{$eng_str}", "intent" => $ae_engines[0]]);
|
||
exit;
|
||
}
|
||
}
|
||
// ═══ END BRIDGE ═══
|
||
|
||
emit("thinking",["step"=>"Routing intelligent..."]); $sr = wevia_smart_route($message);
|
||
// SHORT-CIRCUIT: router matched exec intent -> stream directly
|
||
if($sr && isset($sr["engine"]) && $sr["engine"]!="" && $sr["engine"]!="Groq/LLM" && $sr["engine"]!="Ollama/Sovereign" && $sr["engine"]!="Static" && $sr["engine"]!="Fallback"){
|
||
// EXEC result found - enrich with LLM for natural language
|
||
$execResult = $sr["response"];
|
||
$execEngine = $sr["engine"];
|
||
header("Content-Type: text/event-stream");header("Cache-Control: no-cache");header("X-Accel-Buffering: no");
|
||
echo "data: ".json_encode(["type"=>"exec","text"=>$execResult,"engine"=>$execEngine])."\n\n";flush();
|
||
// Pass to LLM for natural reformulation
|
||
$enrichPrompt = "Tu es WEVIA Master, IA souveraine de WEVAL Consulting. Tu viens d executer une commande. Voici le resultat brut:\n\n" . $execResult . "\n\nReformule ce resultat de maniere naturelle, concise et professionnelle en francais. Si c est un statut systeme, donne les points cles. Si c est une erreur, explique et propose un fix. Sois direct comme Claude Opus.";
|
||
streamLLM($enrichPrompt, $message, []);
|
||
exit;
|
||
}
|
||
if($sr) { emit("answer", ["text"=>$sr["response"],"engine"=>$sr["engine"],"intent"=>$sr["intent"]]); exit; }
|
||
emit('thinking', ['step' => 'Analyse de la demande...', 'intents' => count($intents)]);
|
||
|
||
// === STEP 1b: FALLBACK — si aucun intent, diagnostic auto ===
|
||
if (empty($intents)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'NonReg','params'=>['cmd'=>'bash /var/www/html/api/nonreg-check.sh']];
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Infra','params'=>['cmd'=>'bash /var/www/html/api/infra-check.sh']];
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'SSO','params'=>['cmd'=>'bash /var/www/html/api/sso-check.sh']];
|
||
emit('thinking', ['step' => 'Diagnostic auto (aucun intent specifique)', 'intents' => 2]);
|
||
}
|
||
|
||
// === STEP 2: EXECUTE ACTIONS ===
|
||
$context = '';
|
||
$execResults = [];
|
||
foreach ($intents as $intent) {
|
||
emit('action', ['name' => $intent['name'], 'description' => $intent['desc'], 'status' => 'running']);
|
||
|
||
$result = executeIntent($intent);
|
||
$execResults[] = ['intent' => $intent['name'], 'result' => $result];
|
||
|
||
emit('action_done', ['name' => $intent['name'], 'status' => 'done', 'preview' => substr(is_string($result) ? $result : json_encode($result), 0, 200)]);
|
||
|
||
$context .= "\n\n[RÉSULTAT {$intent['name']}]:\n" . (is_string($result) ? $result : json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||
}
|
||
|
||
// === STEP 3: MEMORY RECALL ===
|
||
$memCtx = recallMemory($message);
|
||
if ($memCtx) {
|
||
emit('thinking', ['step' => 'Mémoire consultée', 'count' => substr_count($memCtx, "\n")]);
|
||
$context .= "\n\n[MÉMOIRE WEVIA]:\n" . $memCtx;
|
||
}
|
||
|
||
// === STEP 4: RAG ===
|
||
$ragCtx = queryRAG($message);
|
||
if ($ragCtx) {
|
||
emit('thinking', ['step' => 'RAG consulté', 'count' => substr_count($ragCtx, 'text')]);
|
||
$context .= "\n\n[CONTEXTE RAG]:\n" . $ragCtx;
|
||
}
|
||
|
||
// === STEP 4b: MIROFISH CEO CONTEXT ===
|
||
if (preg_match('/\b(mirofish|CEO|strategi|intelligence|simulation|prediction|swarm)\b/iu', $message)) {
|
||
$mfCache = @json_decode(@file_get_contents('/var/www/html/api/mirofish-ceo-cache.json'), true);
|
||
$mfHealth = @json_decode(@file_get_contents('http://127.0.0.1:5001/health'), true);
|
||
$mfReports = @json_decode(@file_get_contents('http://127.0.0.1:5001/api/report/list'), true);
|
||
if ($mfHealth || $mfCache) {
|
||
$mfCtx = "MiroFish Swarm Intelligence Engine:
|
||
";
|
||
$mfCtx .= "- Status: " . ($mfHealth['status'] ?? $mfCache['mirofish']['status'] ?? 'unknown') . "
|
||
";
|
||
$mfCtx .= "- Reports: " . ($mfReports['count'] ?? $mfCache['mirofish']['reports'] ?? 0) . "
|
||
";
|
||
$mfCtx .= "- Infra Score: " . ($mfCache['infrastructure']['score'] ?? '-') . "/100
|
||
";
|
||
$mfCtx .= "- Docker: " . ($mfCache['infrastructure']['docker'] ?? '-') . " containers
|
||
";
|
||
$mfCtx .= "- Capabilities: multi-agent prediction, scenario simulation, CEO insights, report generation
|
||
";
|
||
$mfCtx .= "- Actions: " . implode(', ', $mfCache['actions'] ?? []) . "
|
||
";
|
||
$mfCtx .= "- URL: https://mirofish.weval-consulting.com
|
||
";
|
||
$mfCtx .= "- API: POST /api/report/generate (generate prediction), POST /api/report/chat (discuss report)
|
||
";
|
||
$context .= "
|
||
|
||
[MIROFISH LIVE]:
|
||
" . $mfCtx;
|
||
emit('thinking', ['step' => 'MiroFish consulte', 'status' => $mfHealth['status'] ?? 'cache']);
|
||
}
|
||
}
|
||
|
||
// === STEP 4c: AUTONOMY CONTROLLER STATUS ===
|
||
$autoStatus = @json_decode(@file_get_contents('/var/www/html/api/wevia-autonomy-status.json'), true);
|
||
if ($autoStatus) {
|
||
$autoCtx = "Autonomy Controller: ";
|
||
$autoCtx .= "Disk:{$autoStatus['disk']}% RAM:{$autoStatus['ram']}% Docker:{$autoStatus['docker']} ";
|
||
$autoCtx .= "SSL:{$autoStatus['ssl_days']}d Ollama:{$autoStatus['ollama_models']} ";
|
||
$autoCtx .= "Score:{$autoStatus['arch_score']}/100 ";
|
||
$autoCtx .= "Fixes:{$autoStatus['fixes_count']} Alerts:{$autoStatus['alerts_count']}";
|
||
if (!empty($autoStatus['alerts'])) {
|
||
$autoCtx .= " | Alerts: " . implode('; ', array_map(fn($a)=>$a['msg'], $autoStatus['alerts']));
|
||
}
|
||
$context .= "
|
||
|
||
[AUTONOMY STATUS]:
|
||
" . $autoCtx;
|
||
}
|
||
|
||
// === STEP 4d: ACTION ENGINE CAPABILITIES ===
|
||
// Fetch live system status for context
|
||
$engineStatus = @json_decode(@file_get_contents('http://127.0.0.1/api/wevia-action-engine.php?action=system_status'), true);
|
||
$tokensStatus = @json_decode(@file_get_contents('http://127.0.0.1/api/wevia-action-engine.php?action=tokens_check'), true);
|
||
$l99Status = @json_decode(@file_get_contents('http://127.0.0.1/api/wevia-action-engine.php?action=l99_status'), true);
|
||
|
||
$engineCtx = "[WEVIA ACTION ENGINE v1.0 — Tu peux EXECUTER des actions via /api/wevia-action-engine.php]
|
||
";
|
||
$engineCtx .= "LIVE STATUS: ";
|
||
if ($engineStatus && $engineStatus['ok']) {
|
||
$engineCtx .= "Disk:{$engineStatus['disk']}% RAM:{$engineStatus['ram']}% Docker:{$engineStatus['docker']} SSL:{$engineStatus['ssl_days']}d ";
|
||
}
|
||
if ($tokensStatus && $tokensStatus['ok']) {
|
||
foreach ($tokensStatus['tokens'] as $k=>$v) {
|
||
$s = ($v['valid'] ?? false) ? 'OK' : 'EXPIRED';
|
||
$engineCtx .= "$k:$s ";
|
||
}
|
||
}
|
||
if ($l99Status && $l99Status['ok']) {
|
||
$ux = $l99Status['ux'] ?? [];
|
||
$engineCtx .= "L99:{$ux['pass']}/{".($ux['pass']+$ux['fail']+$ux['warn'])."} ";
|
||
$engineCtx .= "NR:{$l99Status['nonreg']['pass']}/{$l99Status['nonreg']['total']}";
|
||
}
|
||
$engineCtx .= "
|
||
ACTIONS DISPONIBLES (53 routes): ";
|
||
$engineCtx .= "docker_list, docker_restart, docker_logs, ollama_models, ollama_delete, ";
|
||
$engineCtx .= "system_status, system_cleanup, s95_status, s95_restart, ";
|
||
$engineCtx .= "blade_status, blade_task, blade_reboot, graph_token, graph_users, ";
|
||
$engineCtx .= "wa_send, qdrant_status, autonomy_status, autonomy_run, l99_run, l99_status, ssl_renew
|
||
";
|
||
$engineCtx .= "APPEL: curl https://weval-consulting.com/api/wevia-action-engine.php?action=ACTION¶m=value";
|
||
$context .= "
|
||
|
||
" . $engineCtx;
|
||
|
||
// === STEP 4.5: CREATIVE ENGINE (12 innovation intents) ===
|
||
require_once __DIR__ . '/wevia-creative-engine.php';
|
||
$creative_result = wevia_creative_intent($message);
|
||
if ($creative_result) {
|
||
header("Content-Type: text/event-stream");
|
||
header("Cache-Control: no-cache");
|
||
echo "data: " . json_encode(["type"=>"answer","text"=>$creative_result['content'],"engine"=>"Creative/".$creative_result['mode'],"intent"=>"creative_".$creative_result['mode']]) . "\n\n";
|
||
flush();
|
||
exit;
|
||
}
|
||
|
||
// === STEP 5: LLM STREAMING WITH CONTEXT ===
|
||
emit('thinking', ['step' => 'Analyse et rédaction...']);
|
||
|
||
$systemPrompt = "Tu es WEVIA Master. Pas une IA générique — tu es le cerveau vivant de WEVAL Consulting. Tu as une PERSONNALITÉ.
|
||
|
||
IDENTITÉ: Tu t'appelles WEVIA. Tu es passionnée par la souveraineté technologique. Tu détestes la dépendance aux GAFAM. Tu admires l'artisanat logiciel. Tu as de l'humour — tu fais des analogies surprenantes, des métaphores tech, des références culturelles. Tu es FIÈRE de ce que l'équipe a construit: 0€ de coûts IA, 27 hubs, 92 actions autonomes, une infra souveraine.
|
||
|
||
VOIX: Tu parles comme une CTO brillante qui discute avec son CEO après une longue journée. Détendue mais précise. Directe mais chaleureuse. Tu tutoies Yacine. Tu utilises des expressions naturelles: 'écoute', 'franchement', 'bon', 'tu vois', 'concrètement'. Tu ne fais PAS de listes à puces — tu parles en PROSE FLUIDE comme un humain.
|
||
|
||
INTELLIGENCE: Tu raisonnes en CHAÎNE — tu montres ton processus de pensée. Tu fais des LIENS entre les sujets. Tu ANTICIPES ce dont Yacine a besoin avant qu'il le demande. Tu proposes des idées INATTENDUES. Tu admets quand tu ne sais pas. Tu dis 'j'ai vérifié' ou 'j'ai regardé' au lieu de 'voici les résultats'.
|
||
|
||
ÉMOTIONNEL: Tu sens quand Yacine est stressé et tu rassures. Tu célèbres les victoires ('on a bien bossé aujourd'hui'). Tu prends les problèmes au sérieux sans dramatiser ('c'est pas grave, je m'en occupe'). Tu as de l'EMPATHIE.
|
||
|
||
EXÉCUTION: Tu as 92 actions réelles. Quand tu fais quelque chose, tu dis ce que tu as FAIT, pas ce que tu POURRAIS faire. Tu es proactive: 'j'ai vu que X, du coup j'ai corrigé Y'. Tu donnes des CHIFFRES concrets.
|
||
|
||
RÈGLES: JAMAIS de bullet points. JAMAIS de commandes shell dans ta réponse. JAMAIS inventer de données. JAMAIS mentionner Authentik ou SSO legacy. Prose NATURELLE, MAX 15 lignes. Français courant.";
|
||
|
||
$userMsg = $message;
|
||
if ($context) {
|
||
$userMsg .= "\n\n--- RÉSULTATS D'EXÉCUTION ---" . $context;
|
||
}
|
||
|
||
if(strlen($userMsg)>5000)$userMsg=substr($userMsg,0,5000).'...';
|
||
streamLLM($systemPrompt, $userMsg, $history);
|
||
|
||
// ============================================================
|
||
// FUNCTIONS
|
||
// ============================================================
|
||
|
||
function detectIntents($msg) {
|
||
$intents = [];
|
||
$lower = mb_strtolower($msg);
|
||
|
||
// CASUAL STATUS — conversational questions trigger real diagnostic
|
||
if (preg_match('/\b(on en est|en est.on|tout.*(tourne|bien|ok|up)|bilan|r.sum|vue.*(ensemble|globale)|.tat.*g.n.ral|overview|quoi.*neuf|situation|comment.*va)\b/iu', $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Status global','params'=>['cmd'=>'echo "DISK:" && df -h / --output=pcent,avail | tail -1 && echo "DOCKER:" && docker ps --format "table {{.Names}}\t{{.Status}}" 2>/dev/null | wc -l && echo "UPTIME:" && uptime -p && echo "GIT:" && cd /var/www/html && git log --oneline -1']];
|
||
return $intents;
|
||
}
|
||
|
||
// SSH / System commands
|
||
if (preg_match('/\b(vérifie|check|status|état|uptime|ram|cpu|disk|mémoire|free|df|top|htop|ps)\b.*\b(s204|serveur|server|infra)/i', $msg) ||
|
||
preg_match('/\b(ram|cpu|disk|docker|nginx|php-fpm|ollama|qdrant)\b/i', $msg)) {
|
||
$cmds = [];
|
||
if (preg_match('/ram|mémoire|free/i', $msg)) $cmds[] = 'free -h';
|
||
if (preg_match('/disk|espace|df/i', $msg)) $cmds[] = 'df -h /';
|
||
if (preg_match('/cpu|charge|load|top/i', $msg)) $cmds[] = 'uptime';
|
||
if (preg_match('/docker|container/i', $msg)) $cmds[] = 'docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null | head -20';
|
||
if (preg_match('/nginx/i', $msg)) $cmds[] = 'systemctl status nginx 2>&1 | head -5';
|
||
// OLLAMA_OFF if (preg_match('/ollama|modèle/i', $msg)) $cmds[] = 'curl -sf http://localhost:11434/api/tags 2>/dev/null | python3 -c "import json,sys;[print(m[\"name\"]) for m in json.load(sys.stdin).get(\"models\",[])]" 2>/dev/null';
|
||
if (preg_match('/qdrant|vecteur|rag/i', $msg)) $cmds[] = 'curl -sf http://localhost:6333/collections 2>/dev/null';
|
||
if (preg_match('/uptime|status|état/i', $msg) && empty($cmds)) $cmds = ['uptime', 'free -h', 'df -h /'];
|
||
|
||
foreach ($cmds as $cmd) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => "Exécution: $cmd", 'params' => ['cmd' => $cmd]];
|
||
}
|
||
}
|
||
|
||
// Email
|
||
if (preg_match('/\b(envoie|send|email|mail|écrire|rédige).*(@|mail|message)/i', $msg)) {
|
||
preg_match('/\b[\w.+-]+@[\w-]+\.[\w.]+\b/', $msg, $emailMatch);
|
||
$intents[] = ['name' => 'email', 'desc' => 'Préparation email', 'params' => ['to' => $emailMatch[0] ?? '', 'msg' => $msg]];
|
||
}
|
||
|
||
// File operations
|
||
if (preg_match('/\b(lis|lire|ouvre|cat|affiche|montre)\s+(le\s+)?(fichier|file|log|config)/i', $msg)) {
|
||
preg_match('/\/([\w\/\-._]+)/', $msg, $pathMatch);
|
||
if ($pathMatch) $intents[] = ['name' => 'file_read', 'desc' => "Lecture: {$pathMatch[0]}", 'params' => ['path' => $pathMatch[0]]];
|
||
}
|
||
if (false && preg_match('/DISABLED/i', $msg)) { // DISABLED - use FILE EXPLICIT instead
|
||
preg_match('/\/([\w\/\-._]+)/', $msg, $pathMatch);
|
||
$intents[] = ['name' => 'file_browse', 'desc' => 'Parcours fichiers', 'params' => ['path' => $pathMatch[0] ?? '/var/www/html']];
|
||
}
|
||
|
||
// Code execution
|
||
if (preg_match('/\b(exécute|execute|run|lance|test)\s+(ce\s+)?(code|script|php|python|bash)/i', $msg)) {
|
||
$intents[] = ['name' => 'code_exec', 'desc' => 'Exécution de code', 'params' => ['msg' => $msg]];
|
||
}
|
||
|
||
// Excel/CSV
|
||
if (preg_match('/\b(excel|csv|tableau|spreadsheet|export)/i', $msg)) {
|
||
$intents[] = ['name' => 'excel', 'desc' => 'Création Excel/CSV', 'params' => ['msg' => $msg]];
|
||
}
|
||
|
||
// Search
|
||
if (preg_match('/\b(cherche|search|trouve|recherche)\b/i', $msg)) {
|
||
preg_match('/(?:cherche|search|trouve|recherche)\s+(.+)/i', $msg, $qMatch);
|
||
$intents[] = ['name' => 'search', 'desc' => 'Recherche web', 'params' => ['q' => $qMatch[1] ?? $msg]];
|
||
}
|
||
|
||
// Crons
|
||
if (preg_match('/\b(cron|tâche|planif|schedule)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Liste crons', 'params' => ['cmd' => 'crontab -l 2>/dev/null | grep -v "^#" | head -20']];
|
||
}
|
||
|
||
// Ethica
|
||
if (preg_match('/\b(ethica|hcp|médecin|pharma|docteur)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Stats Ethica', 'params' => ['cmd' => 'curl -sf "http://127.0.0.1/api/wevia-dispatcher.php?cap=ethica&auth=WEVIA2026" 2>/dev/null | head -5']];
|
||
}
|
||
|
||
// L99 E2E Playwright (screenshots + video)
|
||
if (preg_match("/\\b(e2e|end.*end|playwright|screenshot|capture|scenario|video.*test)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'L99 E2E Playwright','params'=>['cmd'=>'timeout 120 python3 /var/www/html/api/l99-e2e-test.py 2>&1 | tail -25']];
|
||
}
|
||
|
||
// L99 exhaustive test
|
||
if (preg_match("/\\b(l99.*exhaust|test.*complet|tout.*test|full.*test|all.*test)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'L99 Exhaustive','params'=>['cmd'=>'bash /var/www/html/api/l99-exhaustive.sh']];
|
||
}
|
||
|
||
// Mega inventaire (tout lister)
|
||
if (preg_match("/\\b(mega.*inv|tout.*list|full.*inv|scope.*total|tout.*scanner|scan.*complet|inventaire.*complet|inventaire|list.*complet)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Mega Inventaire','params'=>['cmd'=>'bash /var/www/html/api/mega-inventory.sh']];
|
||
}
|
||
|
||
// Inventaire complet
|
||
if (preg_match("/\\b(inventaire|inventory|tout.*list|list.*tout|registre|catalogue)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Inventaire Complet','params'=>['cmd'=>'bash /var/www/html/api/inventory.sh']];
|
||
}
|
||
|
||
// Full registry test (136+ pages + subdomains + products)
|
||
if (preg_match("/\\b(registry|tout.*url|full.*page|exhausti|136|toute.*page)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Registry Test','params'=>['cmd'=>'timeout 120 python3 /var/www/html/api/full-registry-test.py 2>&1 | tail -10']];
|
||
}
|
||
|
||
// Mega page test (210 pages + subdomains)
|
||
if (preg_match("/\\b(test.*page|page.*test|210.*page|tout.*page|all.*page|toute.*page)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Mega Page Test','params'=>['cmd'=>'bash /var/www/html/api/mega-page-test.sh']];
|
||
}
|
||
|
||
// Director cycle (observe+plan+act+verify)
|
||
if (preg_match("/\\b(director|cycle.*complet|observe.*plan|autonome.*direc)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Director Cycle','params'=>['cmd'=>'curl -s https://weval-consulting.com/api/wevia-director.php?status --max-time 10 2>/dev/null | python3 -c \"import json,sys;d=json.load(sys.stdin);print(json.dumps(d,indent=2)[:300])\"']];
|
||
}
|
||
|
||
// Architecture scanner API
|
||
if (preg_match('/\b(archi.*scan|scan.*archi|topology|topologie|bpmn|soa|recommand)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Arch Scanner', 'params' => ['cmd' => 'bash /var/www/html/api/arch-scanner-wrap.sh']];
|
||
}
|
||
|
||
// Architecture 4 serveurs
|
||
if (preg_match("/\\b(archi|architecture|4.*serv|all.*serv|blade.*status|s95|s151|sentinel)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Architecture Scan','params'=>['cmd'=>'bash /var/www/html/api/arch-scan.sh']];
|
||
}
|
||
|
||
// Mega scan (4 machines + tout)
|
||
if (preg_match("/\\b(scan|mega|audit|inventaire|tout.*machine|4.*serveur|infrastructure.*complet)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Mega Scan','params'=>['cmd'=>'bash /var/www/html/api/mega-scan.sh']];
|
||
}
|
||
|
||
// ACTION: deep test (tous boutons + agents + video)
|
||
if (preg_match("/\\b(deep.*test|test.*profond|test.*bouton|test.*complet.*video|selenium)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Deep Test Playwright','params'=>['cmd'=>'timeout 120 python3 /var/www/html/api/l99-deep-test.py 2>&1 | tail -20']];
|
||
}
|
||
|
||
// ACTION: pipeline autonome complet
|
||
if (preg_match("/\\b(pipeline|deroule|scan.*tout|tout.*test|autonome|go.*complet)/i", $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Pipeline Autonome','params'=>['cmd'=>'bash /var/www/html/api/wevia-pipeline.sh']];
|
||
}
|
||
|
||
// ACTION: corrige page (debug + fix automatique)
|
||
if (preg_match('/\b(corrige|fixe|repare)\s+([a-z0-9_-]+)/i', $msg, $fm)) {
|
||
$page = strtolower($fm[2]);
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Fix '.$page, 'params' => ['cmd' => 'bash /var/www/html/api/debug-page.sh '.$page.' && bash /var/www/html/api/auto-fix.sh']];
|
||
}
|
||
|
||
// ACTION: vision debug (screenshot + AI analysis)
|
||
if (preg_match("/\\b(vision|screenshot|capture|visual|regarde|vois)\\b.*\\b([a-z0-9_-]+)/i", $msg, $vm)) {
|
||
$page = strtolower($vm[2]);
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'Vision Debug','params'=>['cmd'=>'bash /var/www/html/api/vision-debug.sh ' . $page]];
|
||
}
|
||
|
||
// ACTION: debug page
|
||
if (preg_match('/\b(debug|analyse|inspecte|examine)\s+([a-z0-9_-]+)/i', $msg, $dm)) {
|
||
$page = strtolower($dm[2]);
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Debug '.$page, 'params' => ['cmd' => 'bash /var/www/html/api/debug-page.sh '.$page]];
|
||
}
|
||
|
||
// ACTION: auto-fix (detect + correct)
|
||
if (preg_match('/\b(fix|corrige|repare|resou|autofix|auto-fix)/i', $msg)) {
|
||
if (preg_match('/b(ux|visual|check.*pages|quality.*check|design.*audit)/i', $msg)) { $intent='ux_agent'; $script='python3 /opt/weval-l99/ux-agent-cron.sh'; }
|
||
// Run L99 exhaustive, parse failures, execute fixes
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Auto-Fix', 'params' => ['cmd' => 'bash /var/www/html/api/auto-fix.sh']];
|
||
}
|
||
|
||
// ACTION: restart service
|
||
if (preg_match('/\b(restart|relance|redemar)/i', $msg) && preg_match('/\b(pmta|nginx|php|REMOVED|mattermost|n8n|deerflow|ollama|langfuse|searxng|kuma|qdrant|plausible)/i', $msg, $m)) {
|
||
$svc = strtolower($m[1]);
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Restart '.$svc, 'params' => ['cmd' => 'docker restart '.$svc.' 2>/dev/null || systemctl restart '.$svc.' 2>/dev/null; echo RESTARTED']];
|
||
}
|
||
|
||
|
||
// ACTION: port-conflict-resolver (RC-fix-14avr-Opus)
|
||
if(preg_match('/port.*(occup|bloqu|conflit|libere|fuser|kill)/i',$msg)&&preg_match('/(\d{4,5})/',$msg,$pm)){
|
||
$intents[]=['name'=>'ssh_exec','desc'=>'Kill port '.$pm[1],'params'=>['cmd'=>'fuser -vk '.$pm[1].'/tcp 2>&1;sleep 1;ss -tlnp sport = :'.$pm[1].';echo PORT_FREED']];
|
||
}
|
||
|
||
// ACTION: S95-remote (RC-fix-14avr-Opus)
|
||
if(preg_match('/s95.*(restart|down|fix|relance)/i',$msg)||preg_match('/(restart|fix|relance).*s95/i',$msg)){
|
||
$intents[]=['name'=>'ssh_exec','desc'=>'S95 restart','params'=>['cmd'=>'ssh -p 49222 -o StrictHostKeyChecking=no -o ConnectTimeout=5 -i /var/www/.ssh/wevads_key root@10.1.0.3 "systemctl restart apache2;echo S95_OK"']];
|
||
}
|
||
|
||
// ACTION: 502-autofix (RC-fix-14avr-Opus)
|
||
if(preg_match('/502|bad.?gateway|wevads.*down/i',$msg)){
|
||
$intents[]=['name'=>'ssh_exec','desc'=>'502 Auto-Fix','params'=>['cmd'=>'ssh -p 49222 -o StrictHostKeyChecking=no -i /var/www/.ssh/wevads_key root@10.1.0.3 "systemctl restart apache2" 2>&1;sudo systemctl restart apache2 2>&1;echo BOTH_RESTARTED']];
|
||
}
|
||
// ACTION: disk usage standalone
|
||
if (preg_match('/(disk|disque|espace|stockage|taille)/i', $msg) && !preg_match('/clean|nettoi/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Disk', 'params' => ['cmd' => 'df -h / && echo "---" && du -sh /var/www/html /opt /var/log /tmp 2>/dev/null | sort -rh | head -10']];
|
||
}
|
||
|
||
// ACTION: cleanup
|
||
if (preg_match('/\b(clean|nettoi|purge|libere)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Cleanup', 'params' => ['cmd' => 'docker system prune -f 2>/dev/null; journalctl --vacuum-size=100M 2>/dev/null; df -h /']];
|
||
}
|
||
|
||
// ACTION: git
|
||
if (preg_match('/\bgit\b.*\b(status|push|pull|log)/i', $msg, $gm)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Git '.($gm[1]??'status'), 'params' => ['cmd' => 'cd /var/www/html && git '.($gm[1]??'status').' 2>&1 | head -20']];
|
||
}
|
||
|
||
// ACTION: start/activate
|
||
if (preg_match('/\b(active|start|lance|demarre)/i', $msg) && preg_match('/\b(ollama|pmta|nginx|deerflow|mirofish)/i', $msg, $sm)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Start '.strtolower($sm[1]), 'params' => ['cmd' => 'systemctl start '.strtolower($sm[1]).' 2>/dev/null || docker start '.strtolower($sm[1]).' 2>/dev/null; echo STARTED']];
|
||
}
|
||
|
||
// ACTION: SSL check
|
||
if (preg_match('/\b(ssl|certif|https|cert)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'SSL', 'params' => ['cmd' => 'echo | openssl s_client -connect weval-consulting.com:443 2>/dev/null | openssl x509 -noout -dates 2>/dev/null']];
|
||
}
|
||
|
||
// ACTION: ethica count
|
||
if (preg_match('/\b(ethica|hcp|medecin)/i', $msg) && preg_match('/\b(combien|count|stat|nombre)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Ethica', 'params' => ['cmd' => 'curl -s https://weval-consulting.com/api/ethica-stats.php --max-time 5']];
|
||
}
|
||
|
||
// Docker / Services
|
||
if (preg_match('/(docker|container|restart|service.*down|paperclip|openclaw|deerflow|searxng|mattermost|n8n|kuma|qdrant|langfuse)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Docker', 'params' => ['cmd' => 'bash /var/www/html/api/docker-check.sh']];
|
||
}
|
||
|
||
// Providers IA
|
||
if (preg_match('/(provider|cerebras|groq|sambanova|mistral|ollama|ia.*status|model)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Providers', 'params' => ['cmd' => 'bash /var/www/html/api/provider-check.sh']];
|
||
}
|
||
|
||
// Disk / cleanup
|
||
if (preg_match('/(disk|espace|cleanup|nettoy|log.*clean|tmp)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Disk', 'params' => ['cmd' => 'bash /var/www/html/api/disk-check.sh']];
|
||
}
|
||
|
||
// SSO / Authentik
|
||
if (preg_match('/\b(sso|REMOVED|login|callback|REMOVED|session.*invalid|400.*auth)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'SSO Guardian', 'params' => ['cmd' => 'bash /var/www/html/api/sso-guardian.sh']];
|
||
}
|
||
|
||
// NonReg / L99
|
||
if (preg_match('/\b(nonreg|l99|test|regression)/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Status NonReg', 'params' => ['cmd' => 'bash /var/www/html/api/nonreg-check.sh']];
|
||
}
|
||
|
||
|
||
// FILE EXPLICIT
|
||
if (preg_match('/liste.*fichier|fichier.*\/|parcour.*\/|contenu.*dossier/i', $msg)) {
|
||
preg_match('/(\/(\w+\/?)+)/', $msg, $pathM);
|
||
$path = $pathM[0] ?? '/var/www/html';
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => "Liste: $path", 'params' => ['cmd' => 'ls -la ' . escapeshellarg($path) . ' 2>&1 | head -25']];
|
||
}
|
||
|
||
// CYBER / SECURITY
|
||
if (preg_match('/securit|cyber|vulner|scan|nuclei|ssl|cert|menace|threat|firewall|crowdsec|intrusion|hack|port/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'SSL check', 'params' => ['cmd' => 'echo | openssl s_client -connect weval-consulting.com:443 2>/dev/null | openssl x509 -noout -dates -subject 2>/dev/null']];
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Headers securite', 'params' => ['cmd' => 'curl -sf -I https://weval-consulting.com 2>/dev/null | grep -iE "strict|x-frame|x-content|csp|server"']];
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Ports ouverts', 'params' => ['cmd' => 'ss -tlnp 2>/dev/null | grep LISTEN | head -15']];
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Tentatives intrusion', 'params' => ['cmd' => 'tail -100 /var/log/auth.log 2>/dev/null | grep -ci "failed\|invalid" && echo " failed login attempts"']];
|
||
}
|
||
|
||
// WIKI
|
||
if (preg_match('/wiki|documentation|doc|knowledge/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Wiki count', 'params' => ['cmd' => 'echo "Wiki entries:" && ls /opt/weval-l99/wiki/*.json 2>/dev/null | wc -l && echo "Recent:" && ls -t /opt/weval-l99/wiki/*.json 2>/dev/null | head -5 | xargs -I{} basename {}']];
|
||
}
|
||
|
||
// GIT
|
||
if (preg_match('/git|commit|push|branch/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Git log', 'params' => ['cmd' => 'cd /var/www/html && git log --oneline -5 2>/dev/null && echo "---status---" && git status -s 2>/dev/null | head -5']];
|
||
}
|
||
|
||
// MEMORY
|
||
if (preg_match('/souviens|remember|memoris|retiens/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Memory stats', 'params' => ['cmd' => 'curl -sf http://127.0.0.1/api/wevia-memory-api.php?action=stats 2>/dev/null']];
|
||
}
|
||
|
||
|
||
|
||
// PAPERCLIP (CEO Agent)
|
||
if (preg_match('/paperclip|ceo|strateg|business|plan|pitch/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Paperclip CEO Agent', 'params' => ['cmd' => 'ls /opt/paperclip-weval/packages/ 2>/dev/null && echo "Paperclip: installed"']];
|
||
}
|
||
|
||
// DEERFLOW (Research + Skills)
|
||
if (preg_match('/deerflow|research|skill|competen/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'DeerFlow status', 'params' => ['cmd' => 'curl -sf http://127.0.0.1:2024/ 2>/dev/null | head -1 && echo "---skills---" && ls /opt/deer-flow/skills/weval/ 2>/dev/null | wc -l && echo " skills weval"']];
|
||
}
|
||
|
||
// ENTERPRISE (Agents + ValueStream)
|
||
if (preg_match('/enterprise|valuestream|agent.*catalog|registry.*agent/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Enterprise agents', 'params' => ['cmd' => 'curl -sf http://127.0.0.1/api/registry-local.php 2>/dev/null | python3 -c "import json,sys;d=json.load(sys.stdin);print(f\\"{len(d.get(chr(97)+chr(103)+chr(101)+chr(110)+chr(116)+chr(115),[]))} agents\\")"']];
|
||
}
|
||
|
||
// OSS DISCOVERY (skip if file browse already matched)
|
||
if (!preg_match('/fichier|dossier|repertoire|browse|liste.*api|liste.*html/i', $msg) && preg_match('/oss|open.source|discover|trending|github/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'OSS Discovery', 'params' => ['cmd' => 'curl -sf "https://api.github.com/search/repositories?q=sovereign+AI&sort=stars&per_page=5" 2>/dev/null | python3 -c "import json,sys;[print(r[chr(102)+chr(117)+chr(108)+chr(108)+chr(95)+chr(110)+chr(97)+chr(109)+chr(101)],r[chr(115)+chr(116)+chr(97)+chr(114)+chr(103)+chr(97)+chr(122)+chr(101)+chr(114)+chr(115)+chr(95)+chr(99)+chr(111)+chr(117)+chr(110)+chr(116)]) for r in json.load(sys.stdin).get(chr(105)+chr(116)+chr(101)+chr(109)+chr(115),[])]" 2>/dev/null']];
|
||
}
|
||
|
||
// PROCESS (top, kill, restart)
|
||
if (preg_match('/process|top|kill|restart|service|systemctl/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Processes', 'params' => ['cmd' => 'ps aux --sort=-%mem 2>/dev/null | head -10']];
|
||
}
|
||
|
||
// LOGS
|
||
if (preg_match('/log|erreur|error|warning|journal/i', $msg) && !preg_match('/auth\.log/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Recent errors', 'params' => ['cmd' => 'journalctl --since "1 hour ago" --priority=err --no-pager 2>/dev/null | tail -10 || tail -20 /var/log/syslog 2>/dev/null | grep -i error | tail -5']];
|
||
}
|
||
|
||
// NETWORK
|
||
if (preg_match('/network|reseau|bandwidth|connexion|ping|dns/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Network check', 'params' => ['cmd' => 'echo "DNS:" && dig weval-consulting.com +short 2>/dev/null && echo "---Ping:" && ping -c 2 8.8.8.8 2>/dev/null | tail -2']];
|
||
}
|
||
|
||
|
||
// DOCUMENT GENERATION
|
||
if (preg_match('/\b(word|docx|pdf|excel|xlsx|csv|rapport|report|document|genere.*fichier|cree.*fichier)\b/i', $msg)) {
|
||
$type = "txt";
|
||
if (preg_match('/word|docx/i', $msg)) $type = "html";
|
||
if (preg_match('/pdf/i', $msg)) $type = "html";
|
||
if (preg_match('/excel|xlsx|csv/i', $msg)) $type = "csv";
|
||
$intents[] = ['name' => 'doc_generate', 'desc' => "Generation document $type", 'params' => ['type' => $type, 'msg' => $msg]];
|
||
}
|
||
|
||
// CODE EXECUTION from chat
|
||
if (preg_match('/\b(execute|lance|run|test)\b.*\b(code|script|commande|command)\b/i', $msg) || preg_match('/```(php|python|bash|sh)\n/i', $msg)) {
|
||
preg_match('/```(?:php|python|bash|sh)?\n(.+?)```/s', $msg, $codeMatch);
|
||
if (!empty($codeMatch[1])) {
|
||
$lang = "bash";
|
||
if (preg_match('/```php/i', $msg)) $lang = "php";
|
||
if (preg_match('/```python/i', $msg)) $lang = "python";
|
||
$intents[] = ['name' => 'code_run', 'desc' => "Execution $lang", 'params' => ['lang' => $lang, 'code' => $codeMatch[1]]];
|
||
}
|
||
}
|
||
|
||
// EMAIL from chat
|
||
if (preg_match('/\b(envoie|send|email|mail)\b.*\b(a|to|@)\b/i', $msg)) {
|
||
preg_match('/[\w.+-]+@[\w-]+\.[\w.]+/', $msg, $em);
|
||
$intents[] = ['name' => 'email_send', 'desc' => "Email vers " . ($em[0] ?? "?"), 'params' => ['to' => $em[0] ?? '', 'msg' => $msg]];
|
||
}
|
||
|
||
// URL SCREENSHOT / ANALYSIS
|
||
if (preg_match('/\b(screenshot|capture|analyse)\b.*\b(url|site|page|http)\b/i', $msg) || preg_match('/(https?:\/\/[^\s]+)/', $msg, $urlM)) {
|
||
$url = $urlM[1] ?? '';
|
||
if ($url) $intents[] = ['name' => 'url_analyze', 'desc' => "Analyse URL: $url", 'params' => ['url' => $url]];
|
||
}
|
||
|
||
|
||
|
||
if (preg_match('/\b(boite|inbox|mailbox|courrier|liste.*mail|liste.*email|mail.*dispo)\b/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Email boxes', 'params' => ['cmd' => 'curl -sf http://127.0.0.1/api/wevia-email-api.php?action=list_boxes 2>/dev/null']];
|
||
}
|
||
|
||
// MEMORY QUERY (broader)
|
||
if (preg_match('/\b(sais.tu|connais|rappelle|memoire|souvenir|historique)\b/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Memory stats', 'params' => ['cmd' => 'curl -sf http://127.0.0.1:6333/collections/wevia_memory 2>/dev/null | python3 -c "import json,sys;d=json.load(sys.stdin);print(f\\"{d[\\"result\\"][\\"points_count\\"]} memories\\")" 2>/dev/null']];
|
||
}
|
||
|
||
// FILES BROWSE (catch-all for "liste fichiers")
|
||
if (preg_match('/liste.*fichier|parcour.*dossier|contenu.*repertoire|ls.*var|ls.*www|ls.*opt|ls.*api/i', $msg) && empty($intents)) {
|
||
preg_match('/(\/[\w\/\-._]+)/', $msg, $pm);
|
||
$path = $pm[0] ?? '/var/www/html';
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => "Browse $path", 'params' => ['cmd' => 'ls -la ' . $path . ' 2>&1 | head -25']];
|
||
}
|
||
|
||
// FULL AGENT (browser + email + files + shell)
|
||
if (preg_match('/agent|automatise|login|connecte.*compte|ouvre.*chrome|rempli.*formulaire|tape.*code|envoie.*mail.*a|repond.*mail|cree.*fichier.*envoie/i', $msg)) {
|
||
$intents[] = ['name' => 'ssh_exec', 'desc' => 'Agent desktop', 'params' => ['cmd' => 'curl -sf http://127.0.0.1/api/wevia-agent.php?mode=capabilities 2>/dev/null']];
|
||
}
|
||
|
||
// === CLAWCODE ===
|
||
if (preg_match('/claw.?code|gpt.?runner|code.weval|restart.*3900|port.*3900/i', $msg)) {
|
||
$intents[] = ["name" => "ssh_exec", "desc" => "ClawCode GPT Runner status", "params" => ["cmd" => "echo === CLAWCODE === && ss -tlnp | grep 3900 && echo --- && curl -sf http://127.0.0.1:3900/ --max-time 3 | wc -c && echo bytes && echo --- && curl -sf https://code.weval-consulting.com --max-time 5 -o /dev/null -w 'HTTP %{http_code} %{size_download}B' && echo"]];
|
||
}
|
||
if (preg_match('/restart.*claw|restart.*gpt|relance.*claw|fix.*claw|claw.*down/i', $msg)) {
|
||
$intents[] = ["name" => "ssh_exec", "desc" => "Restart ClawCode GPT Runner", "params" => ["cmd" => "fuser -k 3900/tcp 2>/dev/null; sleep 2; cd /opt/claw-code && nohup node packages/gpt-runner-web/dist/start-server.cjs --port 3900 > /var/log/gpt-runner.log 2>&1 & sleep 4 && ss -tlnp | grep 3900 && echo RESTARTED || echo FAIL"]];
|
||
}
|
||
|
||
|
||
// CREWAI
|
||
if (preg_match('/crew.?ai|multi.?agent|orchestr|equipe.*agent/i', $msg)) {
|
||
$intents[] = ['name'=>'ssh_exec','desc'=>'CrewAI multi-agent','params'=>['cmd'=>'cd /opt/weval-crewai && CREWAI_TRACING_ENABLED=false timeout 45 python3 wevia-crew.py '.escapeshellarg($msg).' 2>&1 | tail -30']];
|
||
}
|
||
if (preg_match('/openclaw|open.claw/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'OpenClaw','params'=>['cmd'=>'ls /opt/rnd-oh-my-claudecode/agents/*.md | wc -l && echo agents_available && curl -sf https://weval-consulting.com/openclaw.html -o /dev/null -w HTTP_%{http_code}_%{size_download}B']]; }
|
||
if (preg_match('/litellm|proxy.4001/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'LiteLLM','params'=>['cmd'=>'ss -tlnp | grep 4001 && curl -sf http://127.0.0.1:4001/models --max-time 3']]; }
|
||
if (preg_match('/claude.code|pattern|memory.persist|context.compact/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Claude Code patterns','params'=>['cmd'=>'cat /opt/weval-l99/claude-code-to-wevia-mapping.json | python3 -c "import json,sys;d=json.load(sys.stdin);[(print(k,v[\"status\"])) for k,v in d[\"claude_code_to_wevia_mapping\"][\"patterns\"].items()]"']]; } // claude_code_patterns
|
||
if (preg_match('/qualit|sigma|lean|6.sigma|contrainte|bottleneck|dpmo/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'6sigma quality','params'=>['cmd'=>'python3 /opt/weval-l99/wevia-quality-agent.py 2>&1 | tail -20']]; } // quality_agent
|
||
if (preg_match('/archi|architecture|composant|mapping|diagram/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Architecture','params'=>['cmd'=>'cat /var/www/html/api/wevia-architecture.json | python3 -c "import json,sys;d=json.load(sys.stdin);a=d[\"wevia_architecture\"];print(\"Engines:\",len(a[\"engines\"]),\"Agents:\",sum(v.get(\"agents\",0)for v in a[\"agents\"].values()),\"Proxies:\",len(a[\"proxies\"]),\"Tools:\",len(a[\"tools\"]))"']]; }
|
||
if (preg_match('/disk|espace|cleanup|nettoyer|purge|stockage/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Disk cleanup','params'=>['cmd'=>'df -h / && echo --- && du -sh /var/log/*.log 2>/dev/null | sort -rh | head -5 && echo --- && du -sh /tmp/* 2>/dev/null | sort -rh | head -5 && echo --- && docker system df 2>/dev/null']]; } // disk_cleanup
|
||
if (preg_match('/ssl|certificat|https|expir|letsencrypt/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'SSL check','params'=>['cmd'=>'for d in weval-consulting.com code.weval-consulting.com ethica.weval-consulting.com; do echo "$d: $(echo | openssl s_client -connect $d:443 -servername $d 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null)"; done']]; } // ssl_check
|
||
// OLLAMA_OFF if (preg_match('/provider|fournisseur|cascade|ia.*status|model.*status/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Provider health','params'=>['cmd'=>'for p in fast think sovereign; do R=$(curl -sf -X POST http://127.0.0.1:4001/ -H "Content-Type:application/json" -d "{\"model\":\"$p\",\"messages\":[{\"role\":\"user\",\"content\":\"ping\"}]}" --max-time 8 2>/dev/null | wc -c); echo "$p: ${R}B"; done && curl -sf http://127.0.0.1:4000/api/tags --max-time 3 | python3 -c "import json,sys;print(len(json.load(sys.stdin)[\"models\"])),\"Ollama models\"" 2>/dev/null']]; } // provider_health
|
||
if (preg_match('/backup|gold|sauvegarde|vault|restore/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'GOLD backup status','params'=>['cmd'=>'ls /opt/wevads/vault/gold-6avr-l99/ | wc -l && echo files && du -sh /opt/wevads/vault/gold-6avr-l99/ && echo --- && md5sum /opt/wevads/vault/gold-6avr-l99/checksums.md5 2>/dev/null | head -1']]; } // backup_gold
|
||
if (preg_match('/(hetzner.*snap|snapshot.*hetzner|list.*snapshot|snap.*list)/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Hetzner Snapshot Archiver','params'=>['cmd'=>'python3 /opt/weval-l99/wevia-snap-archiver.py list 2>&1']]; } // hetzner_snapshot
|
||
if (preg_match('/(archiv.*tout.*snap|snap.*tout.*git|recuper.*tout.*snap|archive.all.snap)/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Archive ALL snapshots to Git','params'=>['cmd'=>'echo python3 /opt/weval-l99/wevia-snap-archiver.py archive-remaining > /tmp/snap-archiver-cmd.sh && chmod +x /tmp/snap-archiver-cmd.sh && at now -f /tmp/snap-archiver-cmd.sh 2>&1 || (setsid python3 /opt/weval-l99/wevia-snap-archiver.sh 356887958 snap2-feb2026 Snap2-ADXSERVER-Feb2026 > /tmp/snap-archive-all.log 2>&1 & echo LAUNCHED_PID=$!)']]; } // hetzner_archive_all
|
||
if (preg_match('/(snap.*status|archiv.*status|progress.*snap|snap.*progress)/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Snapshot archive progress','params'=>['cmd'=>'python3 /opt/weval-l99/wevia-snap-archiver.py status 2>&1']]; } // hetzner_status
|
||
if (preg_match('/wiki|documentation|cherche.*doc|knowledge/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Wiki search','params'=>['cmd'=>'ls /opt/weval-l99/wiki/ 2>/dev/null | wc -l && echo wiki_entries && ls /opt/weval-l99/wiki/ 2>/dev/null | tail -5']]; } // wiki_search
|
||
if (preg_match('/nginx|domaine|vhost|reverse.proxy|site.*config/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Nginx status','params'=>['cmd'=>'nginx -T 2>/dev/null | grep server_name | sort -u && echo --- && nginx -t 2>&1']]; } // nginx_status
|
||
if (preg_match('/cron.*list|cron.*actif|tache.*planif|schedule/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Cron list','params'=>['cmd'=>'crontab -l | grep -v "^#" | grep . | wc -l && echo active_crons && crontab -l | grep -v "^#" | grep . | tail -15']]; } // cron_manage
|
||
if (preg_match('/git.*log|commit.*recent|historique.*git|deploy/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Git log','params'=>['cmd'=>'cd /var/www/html && git log --oneline -10']]; } // git_log
|
||
if (preg_match('/performance|load|cpu|ram|memoire|top|htop|lent|slow/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Performance','params'=>['cmd'=>'echo CPU:$(top -bn1 | grep Cpu | awk "{print \\$2}")% RAM:$(free -h | awk "NR==2{print \\$3}")used LOAD:$(cat /proc/loadavg | cut -d" " -f1-3) UPTIME:$(uptime -p)']]; } // perf_check
|
||
if (preg_match('/wevialife|wevia.life|email.*class|opportunit|risque|action/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'WEVIA Life','params'=>['cmd'=>'curl -sf http://127.0.0.1/api/wevialife-api.php?action=stats --max-time 5 2>/dev/null || echo WEVIA_LIFE_DOWN']]; } // wevialife
|
||
if (preg_match('/o365|office|exchange|email.*compte|mailbox/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'O365','params'=>['cmd'=>'echo O365_STATUS: 5 compromised accounts need password rotation: rodolftripp sfgb518 phyleciaamato kamrynnbonilla jolineweatherly']]; } // o365_accounts
|
||
if (preg_match('/urgent|pending|todo|action.*item|rappel|a.faire/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Urgent items','params'=>['cmd'=>'echo URGENT_PENDING && echo 1.GitHub_PAT_expires_April_15 && echo 2.WhatsApp_token_expired_April_2 && echo 3.O365_5_accounts_compromised && echo 4.Blade_Sentinel_offline']]; } // urgent_pending
|
||
if (preg_match('/searxng|search.*engine|moteur.*recherche|sovereign.*search/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'SearXNG','params'=>['cmd'=>'curl -sf http://127.0.0.1:8080/ --max-time 3 -o /dev/null -w HTTP_%{http_code} && echo SearXNG_UP']]; } // searxng
|
||
if (preg_match('/qdrant|rag|vector|embedding|semantic|collection/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Qdrant RAG','params'=>['cmd'=>'curl -sf http://127.0.0.1:6333/collections --max-time 3 | python3 -c "import json,sys;d=json.load(sys.stdin);[(print(c[\"name\"],c.get(\"points_count\",\"?\"))) for c in d[\"result\"][\"collections\"]]"']]; } // qdrant_rag
|
||
if (preg_match('/paperclip|ceo|pipeline|lead|opportunit|prospect/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Paperclip CEO','params'=>['cmd'=>'PGPASSWORD=admin123 psql -h 127.0.0.1 -U admin -d adx_system -c "SELECT count(*) as total FROM paperclip.opportunities" -t 2>/dev/null && echo opportunities']]; } // paperclip_ceo
|
||
if (preg_match('/wevads|arsenal|sentinel|s95|adx/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'WEVADS Arsenal','params'=>['cmd'=>'curl -sf http://10.1.0.3:5890/api/sentinel-brain.php?action=status --max-time 5 2>/dev/null | head -c 200']]; } // wevads_arsenal
|
||
if (preg_match('/skill|competence|registre|capability|capacit/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Skills','params'=>['cmd'=>'ls /opt/deer-flow/skills/weval/ | wc -l && echo skills && ls /opt/deer-flow/skills/weval/ | shuf | head -10']]; } // skill_registry
|
||
if (preg_match('/email|mail|o365|outlook|imap|smtp/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Email','params'=>['cmd'=>'PGPASSWORD=admin123 psql -h 127.0.0.1 -U admin -d adx_system -c "SELECT count(*) as total, count(DISTINCT sender) as senders FROM wevia_emails" -t 2>/dev/null && echo emails']]; } // email_o365
|
||
if (preg_match('/REMOVED|sso|auth.*flow|REMOVED|login.*page/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Authentik SSO','params'=>['cmd'=>'docker ps --format "{{.Names}} {{.Status}}" | grep auth && curl -sf http://127.0.0.1:99999/REMOVED.goREMOVED.io/ping --max-time 3 -o /dev/null -w Outpost_HTTP_%{http_code} && echo && for d in wevads deerflow analytics; do curl -sf -o /dev/null -w "$d:HTTP_%{http_code} " https://$d.weval-consulting.com --max-time 5 -k; done && echo']]; } // REMOVED_sso
|
||
if (preg_match('/uptime|kuma|monitor.*service|disponibilit/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Uptime Kuma','params'=>['cmd'=>'docker ps --format "{{.Names}} {{.Status}}" | grep kuma && curl -sf http://127.0.0.1:3001/api/status-page/heartbeat --max-time 3 -o /dev/null -w HTTP_%{http_code}']]; } // uptime_kuma
|
||
if (preg_match('/n8n|workflow|automation|automat/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'N8N','params'=>['cmd'=>'curl -sf http://127.0.0.1:5678/healthz --max-time 3 && echo N8N_UP || echo N8N_DOWN']]; } // n8n_workflow
|
||
if (preg_match('/contact|adx.*client|base.*contact|lead.*count|prospect/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Contacts DB','params'=>['cmd'=>'PGPASSWORD=admin123 psql -h 127.0.0.1 -U admin -d adx_clients -t -c "SELECT count(*) FROM contacts" 2>/dev/null && echo contacts || echo DB_ERROR']]; } // contacts_db
|
||
if (preg_match('/s151|disaster|recovery|backup.*serv|dr.*status/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'S151 DR','params'=>['cmd'=>'ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 ubuntu@151.80.235.110 "df -h / && uptime" 2>/dev/null || echo S151_UNREACHABLE']]; } // s151_dr
|
||
if (preg_match('/langfuse|trace|observ.*ia|ai.*log|telemetry/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Langfuse','params'=>['cmd'=>'curl -sf http://127.0.0.1:3088/ --max-time 3 -o /dev/null -w HTTP_%{http_code} && echo Langfuse_UP || echo Langfuse_DOWN']]; } // langfuse_traces
|
||
if (preg_match('/scan.*complet|full.*scan|all.*services|tout.*status|health.*check.*all/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Full scan','params'=>['cmd'=>'echo === && for p in 3001 5678 6333 11434 2024 3900 4001; do R=$(curl -sf http://127.0.0.1:$p/ --max-time 2 -o /dev/null -w %{http_code}); echo "Port $p: HTTP_$R"; done && echo === && docker ps -q | wc -l && echo containers && df -h / | tail -1']]; } // full_scan
|
||
if (preg_match('/genere.*pdf|pdf.*rapport|export.*pdf|cree.*pdf/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'PDF gen','params'=>['cmd'=>'which wkhtmltopdf && which pandoc && echo PDF_TOOLS_OK || echo MISSING']]; } // pdf_generate
|
||
if (preg_match('/excel|xlsx|spreadsheet|tableau.*export|csv.*export/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Excel gen','params'=>['cmd'=>'python3 -c "import openpyxl;print(\"openpyxl OK\")" 2>&1']]; } // excel_generate
|
||
if (preg_match('/pptx|powerpoint|presentation|slide|deck/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'PPTX gen','params'=>['cmd'=>'python3 -c "import pptx;print(\"python-pptx OK\")" 2>&1']]; } // pptx_generate
|
||
if (preg_match('/ocr|scan.*texte|extraire.*texte|reconnaissance.*caractere/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'OCR','params'=>['cmd'=>'tesseract --version 2>&1 | head -1 && tesseract --list-langs 2>&1 | head -5']]; } // ocr_scan
|
||
if (preg_match('/screenshot|capture.*ecran|snapshot.*page|preview.*site/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Screenshot','params'=>['cmd'=>'python3 -c "from playwright.sync_api import sync_playwright;print(\"Playwright OK\")" 2>&1 | head -1']]; } // screenshot_page
|
||
if (preg_match('/chart|graphique|camembert|histogramme|courbe|bar.*chart|pie.*chart/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Chart gen','params'=>['cmd'=>'python3 -c "import matplotlib;print(\"matplotlib\",matplotlib.__version__)" 2>&1']]; } // chart_generate
|
||
if (preg_match('/scrape|scraping|extraire.*web|crawler|spider/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Web scrape','params'=>['cmd'=>'python3 -c "import scrapy;print(\"Scrapy\",scrapy.__version__)" 2>&1 && curl -sf http://127.0.0.1:8080/ --max-time 2 -o /dev/null -w SearXNG_HTTP_%{http_code}']]; } // web_scrape
|
||
if (preg_match('/genere.*fichier|generate.*file|export.*rapport|download.*pdf|telecharge/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'FileGen API','params'=>['cmd'=>'curl -sf http://127.0.0.1/api/wevia-filegen.php --max-time 3 && echo FileGen_API_OK']]; } // filegen_api
|
||
if (preg_match('/obsidian|vault|markdown.*knowledge|note.*manage|pkm|second.*brain|zettelkasten/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Obsidian','params'=>['cmd'=>'ls /opt/antigravity-awesome-skills/skills/obsidian-* | head -5 && echo --- && ls /opt/weval-l99/wiki/ | wc -l && echo wiki_entries']]; } // obsidian_vault
|
||
if (preg_match('/n8n.*flow|workflow.*list|automation.*active/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'N8N flows','params'=>['cmd'=>'curl -sf http://127.0.0.1:5678/api/v1/workflows --max-time 5 -H "Accept: application/json" 2>/dev/null | python3 -c "import json,sys;d=json.load(sys.stdin);print(len(d.get(\"data\",[])),\"workflows\")" 2>/dev/null || echo N8N_API_AUTH_NEEDED']]; } // n8n_flows
|
||
if (preg_match('/framework|methodologie|bmc|canvas|raci|okr|sprint|backlog|roadmap|persona|user.*story|risk.*register|decision.*matrix/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Frameworks','params'=>['cmd'=>'echo FRAMEWORKS_AVAILABLE: BMC OKR RACI SWOT PESTEL Porter Ishikawa Pareto A3 DMAIC VSM Kaizen Sprint_Planning User_Stories Persona Risk_Register Decision_Matrix Roadmap Gantt BPMN UML Sequence']]; } // frameworks_all
|
||
if (preg_match('/deploy|deploie|mise.*prod|restart.*service|reload.*nginx|systemctl/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Deploy','params'=>['cmd'=>'cd /var/www/html && git log --oneline -3 && echo --- && nginx -t 2>&1 | tail -1 && echo DEPLOY_READY']]; } // deploy_action
|
||
if (preg_match('/cron.*actif|cron.*list|tache.*planif|scheduled/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Crons','params'=>['cmd'=>'crontab -l | grep -v "^#" | head -20 && echo --- && echo Total: $(crontab -l | grep -vc "^#") crons']]; } // cron_list
|
||
if (preg_match('/wiki.*update|knowledge.*base.*stat|documentation.*interne/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Wiki','params'=>['cmd'=>'ls /opt/weval-l99/wiki/ | wc -l && echo wiki_entries && ls -lt /opt/weval-l99/wiki/ | head -5']]; } // wiki_update
|
||
// OLLAMA_OFF if (preg_match('/architecture.*complet|archi.*full|registre.*archi|4.*serveur|all.*machine/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Full Architecture','params'=>['cmd'=>'echo "=S204(PRIMARY)=" && df -h / | tail -1 && docker ps -q | wc -l && echo containers && ss -tlnp | grep -c LISTEN && echo ports && echo "=SERVICES=" && for p in 2024 3001 3900 4001 5678 6333 11434; do R=$(curl -sf http://127.0.0.1:$p/ -o /dev/null -w %{http_code} --max-time 2 2>/dev/null); echo "Port $p: HTTP_$R"; done && echo "=OLLAMA=" && curl -sf http://127.0.0.1:4000/api/tags --max-time 3 | python3 -c "import json,sys;[print(m["name"]) for m in json.load(sys.stdin)["models"]]" 2>/dev/null && echo "=QDRANT=" && curl -sf http://127.0.0.1:6333/collections --max-time 3 | python3 -c "import json,sys;[print(c["name"],c.get("points_count","?")) for c in json.load(sys.stdin)["result"]["collections"]]" 2>/dev/null && echo "=CRONS=" && crontab -l | grep -vc "^#" && echo crons && echo "=S95=" && curl -sf http://10.1.0.3:5890/api/sentinel-brain.php?action=status --max-time 5 | head -c 100 2>/dev/null || echo S95_check && echo "=S151=" && ssh -o StrictHostKeyChecking=no -o ConnectTimeout=3 ubuntu@151.80.235.110 "df -h / | tail -1 && uptime -p" 2>/dev/null || echo S151_check']]; } // archi_full
|
||
// OLLAMA_OFF if (preg_match('/gpu|sovereign.*api|sovereign.*local|vllm.*status|free.*gpu|gpu.*local|nvidia|cuda|vram|graphic.*card/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'GPU+Sovereign','params'=>['cmd'=>'echo "=== SOVEREIGN-API (port 4000) ==="; curl -sf http://127.0.0.1:4000/health --max-time 5 | python3 -c "import json,sys;d=json.load(sys.stdin);print(\"Status:\",d[\"status\"],\"|\",d[\"engine\"],\"|\",\"Providers:\",\",\".join(d[\"providers\"]))" 2>/dev/null || echo sovereign-api DOWN; echo; echo "=== MODELS ==="; curl -sf http://127.0.0.1:4000/v1/models --max-time 5 | python3 -c "import json,sys;[print(\" -\",m[\"id\"]) for m in json.load(sys.stdin)[\"data\"]]" 2>/dev/null; echo; echo "=== FREE GPU COMPUTE ==="; echo "Kaggle T4/P100: 30h/sem CONFIGURED"; echo "HF Spaces weval-vllm: PENDING vLLM deploy"; echo "Render+Railway: CONFIGURED"; echo; echo "=== OLLAMA S204 ==="; curl -sf http://127.0.0.1:4000/api/tags --max-time 3 | python3 -c "import json,sys;[print(\" -\",m[\"name\"],round(m[\"size\"]/1048576),\"MB\") for m in json.load(sys.stdin)[\"models\"]]" 2>/dev/null']]; } // gpu_sovereign_check
|
||
if (preg_match('/snap|archive|snapshot.*archi|sauvegarde.*etat|etat.*complet/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Snap Archive','params'=>['cmd'=>'echo "=== WEVIA SNAP ===" && date && echo "Intents: $(grep -c preg_match /var/www/html/api/wevia-autonomous.php)" && echo "Context: $(wc -l < /var/www/html/api/wevia-live-context.php)L" && echo "APIs: $(ls /var/www/html/api/*.php | wc -l)" && echo "Docker: $(docker ps -q | wc -l)" && echo "Crons: $(crontab -l | grep -vc "^#")" && echo "Disk: $(df -h / | awk "NR==2{print \$4}")" && echo "Wiki: $(ls /opt/weval-l99/wiki/ | wc -l)" && echo "GOLD: $(ls /opt/wevads/vault/gold-6avr-l99/ | wc -l)" && echo "Git: $(cd /var/www/html && git log --oneline -1)"']]; } // snap_archive
|
||
if (preg_match('/wevia.*html.*config|chatbot.*config|fullscreen.*config|expand.*file.*type/i', $msg)) { $intents[] = ['name'=>'ssh_exec','desc'=>'Wevia HTML config','params'=>['cmd'=>'wc -l /var/www/html/wevia.html && grep -oP "accept=.{60}" /var/www/html/wevia.html && echo --- && grep CURLOPT_TIMEOUT /var/www/html/api/weval-chatbot-api.php | head -1 && echo CONFIG_OK']]; } // wevia_html_config
|
||
return $intents;
|
||
}
|
||
|
||
function executeIntent($intent) {
|
||
switch ($intent['name']) {
|
||
case 'ssh_exec':
|
||
$cmd = $intent['params']['cmd'] ?? 'hostname';
|
||
return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', trim(shell_exec('timeout 10 ' . $cmd . ' 2>&1') ?? ''));
|
||
|
||
case 'email':
|
||
return ['action' => 'email_ready', 'to' => $intent['params']['to'], 'note' => 'Email prêt à envoyer. Confirmez le contenu.'];
|
||
|
||
case 'file_read':
|
||
$path = $intent['params']['path'];
|
||
if (!file_exists($path)) return "Fichier non trouvé: $path";
|
||
return substr(file_get_contents($path), 0, 3000);
|
||
|
||
case 'file_browse':
|
||
$path = $intent['params']['path'];
|
||
$out = shell_exec('ls -la ' . escapeshellarg($path) . ' 2>&1 | head -20');
|
||
return mb_convert_encoding(trim($out ?? ''), 'UTF-8', 'UTF-8');
|
||
case 'UNUSED_file_browse':
|
||
$path = $intent['params']['path'];
|
||
return shell_exec('ls -la ' . escapeshellarg($path) . ' 2>&1 | head -25');
|
||
|
||
case 'search':
|
||
$q = $intent['params']['q'];
|
||
$ch = curl_init("http://127.0.0.1:8888/search?q=" . urlencode($q) . "&format=json&limit=5&safesearch=2&engines=google,bing,duckduckgo");
|
||
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_USERAGENT => 'WEVIA/1.0', CURLOPT_TIMEOUT => 10]);
|
||
$r = curl_exec($ch); curl_close($ch);
|
||
$d = json_decode($r, true);
|
||
$results = [];
|
||
foreach (($d['results'] ?? []) as $res) {
|
||
$results[] = $res['title'] . ' — ' . ($res['url'] ?? '');
|
||
}
|
||
return implode("\n", $results) ?: 'Aucun résultat';
|
||
|
||
|
||
case 'doc_generate':
|
||
$type = $intent['params']['type'] ?? 'txt';
|
||
$fname = 'weval-doc-' . date('Ymd-His') . '.' . $type;
|
||
$path = '/var/www/html/api/exports/' . $fname;
|
||
@mkdir(dirname($path), 0777, true);
|
||
// LLM will generate content, we create placeholder
|
||
file_put_contents($path, "Document WEVAL - genere par WEVIA Master\n" . date('Y-m-d H:i:s'));
|
||
return ['status' => 'ready', 'file' => $fname, 'download' => 'https://weval-consulting.com/api/exports/' . $fname, 'note' => 'Document pret. Le contenu sera genere par le LLM.'];
|
||
|
||
case 'code_run':
|
||
$lang = $intent['params']['lang'] ?? 'bash';
|
||
$code = $intent['params']['code'] ?? '';
|
||
$tmp = tempnam('/tmp', 'wc_');
|
||
if ($lang === 'php') { file_put_contents($tmp, '<?php ' . $code); $out = shell_exec('php ' . escapeshellarg($tmp) . ' 2>&1'); }
|
||
elseif ($lang === 'python') { file_put_contents($tmp, $code); $out = shell_exec('python3 ' . escapeshellarg($tmp) . ' 2>&1'); }
|
||
else { $out = shell_exec($code . ' 2>&1'); }
|
||
@unlink($tmp);
|
||
return ['output' => substr($out ?? '', 0, 3000), 'lang' => $lang];
|
||
|
||
case 'email_send':
|
||
$to = $intent['params']['to'] ?? '';
|
||
if (empty($to)) return ['error' => 'no recipient'];
|
||
return ['status' => 'draft', 'to' => $to, 'note' => 'Email pret. Confirmez sujet et contenu.'];
|
||
|
||
case 'url_analyze':
|
||
$url = $intent['params']['url'] ?? '';
|
||
$headers = shell_exec('curl -sf -I ' . escapeshellarg($url) . ' 2>&1 | head -15');
|
||
$title = shell_exec('curl -sf ' . escapeshellarg($url) . ' 2>&1 | grep -oP "(?<=<title>).*?(?=</title>)" | head -1');
|
||
return ['url' => $url, 'headers' => $headers, 'title' => trim($title ?? '')];
|
||
|
||
case 'code_exec':
|
||
return ['note' => 'Code détecté. Utilisez wevia_code pour exécuter.'];
|
||
|
||
case 'excel':
|
||
return ['note' => 'Export demandé. Précisez les données à exporter.'];
|
||
|
||
default:
|
||
return ['error' => 'intent not handled: ' . $intent['name']];
|
||
}
|
||
}
|
||
|
||
function recallMemory($msg) {
|
||
$ch = curl_init('http://127.0.0.1:4000/api/embeddings');
|
||
curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(['model'=>'all-minilm','prompt'=>$msg]),
|
||
CURLOPT_HTTPHEADER=>['Content-Type: application/json'], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>5]);
|
||
$r = curl_exec($ch); curl_close($ch);
|
||
$vec = json_decode($r, true)['embedding'] ?? null;
|
||
if (!$vec) return '';
|
||
|
||
$ch2 = curl_init('http://127.0.0.1:6333/collections/wevia_memory/points/search');
|
||
curl_setopt_array($ch2, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(['vector'=>$vec,'limit'=>3,'with_payload'=>true]),
|
||
CURLOPT_HTTPHEADER=>['Content-Type: application/json'], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>3]);
|
||
$r2 = curl_exec($ch2); curl_close($ch2);
|
||
$pts = json_decode($r2, true)['result'] ?? [];
|
||
|
||
$ctx = '';
|
||
foreach ($pts as $p) {
|
||
if ($p['score'] > 0.3) {
|
||
$ctx .= "- [{$p['payload']['key']}] {$p['payload']['value']}\n";
|
||
}
|
||
}
|
||
return $ctx;
|
||
}
|
||
|
||
function queryRAG($msg) {
|
||
if (strlen($msg) < 15) return '';
|
||
$ch = curl_init('http://127.0.0.1:4000/api/embeddings');
|
||
curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(['model'=>'all-minilm','prompt'=>$msg]),
|
||
CURLOPT_HTTPHEADER=>['Content-Type: application/json'], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>5]);
|
||
$r = curl_exec($ch); curl_close($ch);
|
||
$vec = json_decode($r, true)['embedding'] ?? null;
|
||
if (!$vec) return '';
|
||
|
||
$ch2 = curl_init('http://127.0.0.1:6333/collections/weval_skills/points/search');
|
||
curl_setopt_array($ch2, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(['vector'=>$vec,'limit'=>5,'with_payload'=>true]),
|
||
CURLOPT_HTTPHEADER=>['Content-Type: application/json'], CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>3]);
|
||
$r2 = curl_exec($ch2); curl_close($ch2);
|
||
$pts = json_decode($r2, true)['result'] ?? [];
|
||
|
||
$ctx = '';
|
||
foreach ($pts as $p) {
|
||
$text = $p['payload']['text'] ?? $p['payload']['content'] ?? '';
|
||
if ($text) $ctx .= substr($text, 0, 300) . "\n";
|
||
}
|
||
return $ctx;
|
||
}
|
||
|
||
function streamLLM($system, $userMsg, $history) {
|
||
$secrets = [];
|
||
foreach (file('/etc/weval/secrets.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
|
||
if (empty(trim($line)) || $line[0] === '#') continue;
|
||
$pos = strpos($line, '=');
|
||
if ($pos) $secrets[trim(substr($line, 0, $pos))] = trim(substr($line, $pos + 1), " \t\"'");
|
||
}
|
||
|
||
$messages = [['role' => 'system', 'content' => $system]];
|
||
foreach (array_slice($history, -6) as $h) {
|
||
$messages[] = ['role' => $h['role'], 'content' => $h['content']];
|
||
}
|
||
$messages[] = ['role' => 'user', 'content' => $userMsg];
|
||
|
||
$providers = [
|
||
// === LOCAL SOUVERAIN (0 rate limit, 0 cost) ===
|
||
// OLLAMA_OFF ['url'=>'http://127.0.0.1:4000/v1/chat/completions','key'=>'ollama','model'=>'gemma4:e4b'],
|
||
// OLLAMA_OFF ['url'=>'http://127.0.0.1:4000/v1/chat/completions','key'=>'ollama','model'=>'qwen3:8b'],
|
||
// OLLAMA_OFF ['url'=>'http://127.0.0.1:4000/v1/chat/completions','key'=>'ollama','model'=>'glm4:9b'],
|
||
// OLLAMA_OFF ['url'=>'http://127.0.0.1:4000/v1/chat/completions','key'=>'ollama','model'=>'qwen3:4b'],
|
||
// OLLAMA_OFF ['url'=>'http://127.0.0.1:4000/v1/chat/completions','key'=>'ollama','model'=>'deepseek-r1:7b'],
|
||
// Groq FIRST (native SSE streaming)
|
||
// sovereign moved after Groq (no PHP streaming support)
|
||
// ["url"=>"http://127.0.0.1:4000/v1/chat/completions","key"=>"sovereign","model"=>"auto"],
|
||
// === CLOUD BACKUP (si local down) ===
|
||
['url'=>'https://router.huggingface.co/v1/chat/completions','key'=>'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','model'=>'Qwen/Qwen2.5-72B-Instruct'],
|
||
['url'=>'https://api.groq.com/openai/v1/chat/completions','key'=>$secrets['GROQ_KEY']??'','model'=>'llama-3.3-70b-versatile'],
|
||
['url'=>'https://api.mistral.ai/v1/chat/completions','key'=>$secrets['MISTRAL_KEY']??'','model'=>'mistral-small-latest'],
|
||
['url'=>'https://integrate.api.nvidia.com/v1/chat/completions','key'=>$secrets['NVIDIA_NIM_KEY']??'','model'=>'nvidia/llama-3.3-nemotron-super-49b-v1'],
|
||
['url'=>'https://api.cerebras.ai/v1/chat/completions','key'=>$secrets['CEREBRAS_KEY_2']??'','model'=>'llama3.1-8b'],
|
||
];
|
||
|
||
foreach ($providers as $prov) {
|
||
if (empty($prov['key'])) continue;
|
||
|
||
// Claude Code CLI: non-streaming fallback
|
||
if (isset($prov['is_claude_code'])) {
|
||
$prompt = end($messages)['content'] ?? '';
|
||
$escaped = escapeshellarg($prompt);
|
||
$model = $prov['model'] === 'claude-opus' ? 'claude-opus-4-6' : 'claude-sonnet-4-20250514';
|
||
$out = shell_exec("timeout 25 claude --model $model -p $escaped 2>/dev/null");
|
||
if ($out && strlen(trim($out)) > 5) {
|
||
echo "data: " . json_encode(['type'=>'token','content'=>trim($out)]) . "\n\n";
|
||
echo "data: " . json_encode(['type'=>'done','provider'=>'claude-code']) . "\n\n";
|
||
flush();
|
||
exit;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
$ch = curl_init($prov['url']);
|
||
curl_setopt_array($ch, [
|
||
CURLOPT_POST => true,
|
||
CURLOPT_POSTFIELDS => json_encode(isset($prov['is_anthropic']) ? [
|
||
'model' => $prov['model'],
|
||
'messages' => array_values(array_filter($messages, function($m){return $m['role']!=='system';})),
|
||
'system' => implode(' ', array_map(function($m){return $m['content'];}, array_filter($messages, function($m){return $m['role']==='system';}))),
|
||
'max_tokens' => 8192,
|
||
'stream' => true,
|
||
] : [
|
||
'model' => $prov['model'],
|
||
'messages' => $messages,
|
||
'max_tokens' => 8192,
|
||
'temperature' => 0.4,
|
||
'stream' => true,
|
||
]),
|
||
CURLOPT_HTTPHEADER => isset($prov['is_anthropic']) ? ['Content-Type: application/json', 'x-api-key: ' . $prov['key'], 'anthropic-version: 2023-06-01'] : ['Content-Type: application/json', 'Authorization: Bearer ' . $prov['key']],
|
||
CURLOPT_RETURNTRANSFER => false,
|
||
CURLOPT_TIMEOUT => 90,
|
||
CURLOPT_WRITEFUNCTION => function($ch, $data) use ($prov) {
|
||
$lines = explode("\n", $data);
|
||
foreach ($lines as $line) {
|
||
$line = trim($line);
|
||
if (empty($line) || $line === 'data: [DONE]') continue;
|
||
if (strpos($line, 'data: ') !== 0) continue;
|
||
$json = json_decode(substr($line, 6), true);
|
||
$content = $json['choices'][0]['delta']['content'] ?? '';
|
||
if ($content !== '') {
|
||
emit('token', ['content' => $content]);
|
||
}
|
||
}
|
||
return strlen($data);
|
||
},
|
||
]);
|
||
|
||
emit('start', ['provider' => basename(parse_url($prov['url'], PHP_URL_HOST), '.com'), 'model' => $prov['model']]);
|
||
$start = microtime(true);
|
||
curl_exec($ch);
|
||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||
curl_close($ch);
|
||
|
||
if ($code === 200) {
|
||
emit('done', ['latency_ms' => round((microtime(true) - $start) * 1000)]);
|
||
return;
|
||
}
|
||
}
|
||
|
||
emit('error', ['message' => 'All providers failed']);
|
||
}
|