936 lines
68 KiB
PHP
936 lines
68 KiB
PHP
<?php
|
|
// === V183 public-guard · defense in depth ===
|
|
if (($_SERVER["REQUEST_METHOD"] ?? "") === "POST") {
|
|
$__v183_raw = @file_get_contents("php://input");
|
|
$__v183_in = @json_decode($__v183_raw, true) ?: [];
|
|
$__v183_msg = trim($__v183_in["message"] ?? "");
|
|
if ($__v183_msg !== "") {
|
|
$__v183_blocked = [
|
|
"/^intents?_pool\b/i", "/^quelle\s+heure\s*$/i",
|
|
"/^multiagent\s+parall[e\xc3\xa9\xc3\xa8]le/i",
|
|
"/^orchestrate\s+parall[e\xc3\xa9\xc3\xa8]le/i",
|
|
"/^cable\s+un?\s+intent/i", "/^nonreg\s*(?:score|status)?\s*$/i",
|
|
"/^l99\s*(?:score|status)?\s*$/i", "/^6\s*sigma/i",
|
|
"/^derniers?\s+commits?\s+git/i", "/^git\s+(?:log|commit|status)/i",
|
|
"/\bWAVE-\d+/i", "/\bpool\s+total\b/i",
|
|
"/^doctrines?\s+(?:wiki|list)/i", "/^load\s*$/i",
|
|
"/\bwevia[-_.]?(?:master|orchestrator|autonomous)\b/i",
|
|
"/^(?:ping|status|health)\s+(?:system|server|infra)/i",
|
|
];
|
|
$__v183_internal = false;
|
|
$__v183_token = $_SERVER["HTTP_X_AGENT_TOKEN"] ?? "";
|
|
$__v183_ref = $_SERVER["HTTP_REFERER"] ?? "";
|
|
$__v183_exp = "";
|
|
foreach (@file("/etc/weval/secrets.env") ?: [] as $__v183_ln) {
|
|
if (preg_match("/^AGENT_TOKEN=(.+)$/", trim($__v183_ln), $__v183_mm)) {
|
|
$__v183_exp = trim($__v183_mm[1], " \"\'"); break;
|
|
}
|
|
}
|
|
if ($__v183_token && $__v183_exp && hash_equals($__v183_exp, $__v183_token)) $__v183_internal = true;
|
|
if (stripos($__v183_ref, "/wevia-master.html") !== false || stripos($__v183_ref, "/wevia-master-") !== false || stripos($__v183_ref, "/proof-wave") !== false) $__v183_internal = true;
|
|
if (!$__v183_internal) {
|
|
foreach ($__v183_blocked as $__v183_pat) {
|
|
if (@preg_match($__v183_pat, $__v183_msg)) {
|
|
header("Content-Type: application/json; charset=utf-8");
|
|
$__v183_greet = "Je suis WEVIA Assistant IA. Je peux vous aider avec la generation de documents (PDF, Word, Excel, PowerPoint), la creation d\"images, de schemas et de code, les traductions, les recherches et les calculs. Que puis-je faire pour vous aujourd\"hui ?";
|
|
echo json_encode(["content"=>$__v183_greet, "response"=>$__v183_greet, "provider"=>"wevia-public-guard-v1", "intent"=>"guard_redirect"], JSON_UNESCAPED_UNICODE);
|
|
@error_log("[V183-public-guard] blocked: " . substr($__v183_msg, 0, 80));
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// === END V183 ===
|
|
|
|
header('Content-Type: text/event-stream');
|
|
header('Cache-Control: no-cache');
|
|
header('X-Accel-Buffering: no');
|
|
set_time_limit(120);
|
|
ob_implicit_flush(true);
|
|
while(ob_get_level())ob_end_flush();
|
|
function sse($d){echo 'data: '.json_encode($d,JSON_UNESCAPED_UNICODE)."\n\n";flush();}
|
|
$msg=$_GET['msg']??'';if(!$msg){$__b=@json_decode(@file_get_contents('php://input'),true);$msg=$__b['message']??$__b['msg']??'';}
|
|
if(!$msg){sse(['error'=>'msg required']);exit;}
|
|
sse(['type'=>'start','task'=>$msg,'ts'=>date('H:i:s')]);
|
|
|
|
// === WAVE-268-SSE Fast intercept 5 intents Opus 22avr 17h ===
|
|
// Garantit que intents_pool/quelle_heure/multiagent/orchestrate_nl/cable_intent repondent
|
|
// DIRECTEMENT ici sans passer par LLM guard (qui sinon retourne "necessite intent shell reel")
|
|
$__w268 = trim((string)$msg);
|
|
$__w268lo = mb_strtolower($__w268);
|
|
$__w268_done = false;
|
|
|
|
if ($__w268 !== '') {
|
|
// 1. intents_pool
|
|
if (preg_match('/^intents[\s_-]?pool$|^pool[\s_-]?intents$/', $__w268lo)) {
|
|
$__pr = @file_exists('/opt/wevia-brain/priority-intents-nl.json') ? count(@json_decode(@file_get_contents('/opt/wevia-brain/priority-intents-nl.json'), true) ?: []) : 0;
|
|
$__rg = @file_exists('/opt/wevia-brain/wevia-tool-registry.json') ? (int)(@json_decode(@file_get_contents('/opt/wevia-brain/wevia-tool-registry.json'), true)['count'] ?? 0) : 0;
|
|
$__top = @is_dir('/opt/weval-ops/top-ia') ? count(glob('/opt/weval-ops/top-ia/*.sh')) : 0;
|
|
$__plug = @is_dir('/opt/weval-plugins') ? count(glob('/opt/weval-plugins/*', GLOB_ONLYDIR)) : 0;
|
|
$__df = @is_dir('/opt/deer-flow/skills') ? count(glob('/opt/deer-flow/skills/*', GLOB_ONLYDIR)) : 0;
|
|
$__kb = @is_dir('/opt/wevia-brain/knowledge') ? count(glob('/opt/wevia-brain/knowledge/*.json')) : 0;
|
|
$__doc = @is_dir('/var/www/html/wiki') ? count(glob('/var/www/html/wiki/doctrine-*.md')) : 0;
|
|
$__cron = (int)trim(@shell_exec("crontab -l 2>/dev/null | grep -cE 'wevia|WEVIA'") ?: '0');
|
|
$__total = $__pr + $__rg + $__top + $__plug + $__df + $__kb + $__doc + $__cron;
|
|
sse(['type'=>'answer','text'=>"=== WEVIA INTENTS POOL ===\nPriority intents NL: $__pr\nTool registry: $__rg\nTop-IA scripts: $__top\nPlugins: $__plug\nDeerFlow skills: $__df\nBrain KBs: $__kb\nDoctrines wiki: $__doc\nCrons: $__cron\n\n=== POOL TOTAL: $__total ===\n\nWEVIA Master peut mobiliser: $__total capacites (LIVE @ ".date('H:i:s')." CEST)",'engine'=>'WAVE-268/intents_pool','intent'=>'intents_pool']);
|
|
sse(['type'=>'done']);
|
|
$__w268_done = true;
|
|
}
|
|
elseif (preg_match('/^(quelle|donne|dis).{0,10}heure|^date[\s_-]?serveur|^heure[\s_-]?serveur/', $__w268lo)) {
|
|
sse(['type'=>'answer','text'=>trim(shell_exec('date') ?: '') . ' (serveur WEVAL Casablanca)','engine'=>'WAVE-268/server_time','intent'=>'server_time']);
|
|
sse(['type'=>'done']);
|
|
$__w268_done = true;
|
|
}
|
|
elseif (preg_match('/^multi[\s_-]?agent.{0,30}(parallele|parallel|verifier|check)|^orchestrate.{0,20}(en\s+)?parallele/', $__w268lo)) {
|
|
$__parts = [];
|
|
if (stripos($__w268lo, 'nonreg') !== false) {
|
|
$__nr = @json_decode(@file_get_contents('/var/www/html/api/nonreg-latest.json'), true);
|
|
$__parts[] = "[nonreg] " . ($__nr ? $__nr['pass'].'/'.$__nr['total'].' ('.$__nr['score'].'%)' : 'N/A');
|
|
}
|
|
if (stripos($__w268lo, 'l99') !== false) {
|
|
$__l = @json_decode(@file_get_contents('/opt/weval-l99/l99-state.json'), true);
|
|
$__parts[] = "[l99] " . ($__l ? $__l['pass'].'/'.$__l['total'].' ('.$__l['score'].'%)' : 'N/A');
|
|
}
|
|
if (stripos($__w268lo, 'git') !== false || stripos($__w268lo, 'commit') !== false) {
|
|
$__g = trim(@shell_exec('cd /var/www/html && git log --oneline -5 2>/dev/null') ?: '');
|
|
$__parts[] = "[git]\n$__g";
|
|
}
|
|
if (stripos($__w268lo, 'ethica') !== false || stripos($__w268lo, 'hcp') !== false) {
|
|
$__e = trim(@shell_exec('curl -s -m3 http://127.0.0.1/api/ethica-country-api.php 2>/dev/null | head -c 200') ?: '146K HCPs');
|
|
$__parts[] = "[ethica] $__e";
|
|
}
|
|
if (stripos($__w268lo, 'ping') !== false || stripos($__w268lo, 'infra') !== false) {
|
|
$__i = trim(@shell_exec('echo LOAD:$(cat /proc/loadavg|cut -d" " -f1-3) DISK:$(df -h /|tail -1|awk "{print \$5}")') ?: '');
|
|
$__parts[] = "[infra] $__i";
|
|
}
|
|
if (stripos($__w268lo, 'agent') !== false) {
|
|
$__a = trim(@shell_exec('echo Paperclip:$(curl -so/dev/null -w%{http_code} -m3 http://127.0.0.1:8001/ 2>/dev/null) Qdrant:$(curl -so/dev/null -w%{http_code} -m3 http://127.0.0.1:6333/ 2>/dev/null) Sovereign:$(curl -so/dev/null -w%{http_code} -m3 http://127.0.0.1:4000/ 2>/dev/null)') ?: '');
|
|
$__parts[] = "[agents] $__a";
|
|
}
|
|
if (empty($__parts)) $__parts[] = "Precisez: nonreg, l99, git, ethica, ping, agents, infra";
|
|
sse(['type'=>'answer','text'=>"=== MULTIAGENT PARALLELE (LIVE @ ".date('H:i:s')." CEST) ===\n" . implode("\n", $__parts),'engine'=>'WAVE-268/multiagent','intent'=>'multiagent_parallele']);
|
|
sse(['type'=>'done']);
|
|
$__w268_done = true;
|
|
}
|
|
elseif (preg_match('/^(cable|wire|cree|create).{0,20}intent.{0,30}(pour|for).+?(quand|when|si|if).+?(dit|say|tape|type)/', $__w268lo)) {
|
|
if (preg_match('/pour\s+(.+?)\s+(?:quand|when|si|if).+?(?:dit|tape|say|type)\s+(.+?)\.\s*(?:commande|command|cmd):\s*(.+)$/i', $__w268, $__mm)) {
|
|
$__desc = trim($__mm[1]); $__trg = trim($__mm[2]); $__cmd = trim($__mm[3]);
|
|
$__slug = preg_replace('/[^a-z0-9_]/', '_', strtolower($__trg));
|
|
$__reg_p = '/opt/wevia-brain/user-wired-intents.json';
|
|
$__all = @json_decode(@file_get_contents($__reg_p), true) ?: [];
|
|
$__all[$__slug] = ['trigger' => $__trg, 'description' => $__desc, 'command' => $__cmd, 'wired_at' => date('c'), 'wired_by' => 'opus-w268-sse'];
|
|
@file_put_contents($__reg_p, json_encode($__all, JSON_PRETTY_PRINT));
|
|
sse(['type'=>'answer','text'=>"[AUTO-WIRE OK]\nIntent: $__slug\nTrigger: '$__trg'\nDescription: $__desc\nCommand: $__cmd\n\nTape maintenant '$__trg' pour l executer.\nTotal wired: " . count($__all),'engine'=>'WAVE-268/auto_wire','intent'=>'auto_wire_nl']);
|
|
sse(['type'=>'done']);
|
|
$__w268_done = true;
|
|
}
|
|
}
|
|
else {
|
|
// Check user-wired-intents
|
|
$__reg_p = '/opt/wevia-brain/user-wired-intents.json';
|
|
if (file_exists($__reg_p)) {
|
|
$__all = @json_decode(@file_get_contents($__reg_p), true) ?: [];
|
|
foreach ($__all as $__sl => $__d) {
|
|
if (mb_strtolower($__d['trigger']) === $__w268lo) {
|
|
$__out = trim(@shell_exec($__d['command'] . ' 2>&1') ?: '');
|
|
sse(['type'=>'answer','text'=>"[USER INTENT '$__sl']\n$__out",'engine'=>'WAVE-268/user_wired','intent'=>'user_'.$__sl]);
|
|
sse(['type'=>'done']);
|
|
$__w268_done = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($__w268_done) exit;
|
|
}
|
|
// === END WAVE-268-SSE ===
|
|
|
|
|
|
// === OPUS5-SSE-DISPATCHER-v1 (18avr) - Short-circuit stubs BEFORE LLM fallback ===
|
|
// Prevent hallucinations (e.g. "ethica" → "Ethiopie") by matching wired intents first.
|
|
if (!empty($msg)) {
|
|
$__sd_msg = mb_strtolower(trim($msg));
|
|
$__sd_stubs = @glob('/var/www/html/api/wired-pending/intent-opus4-*.php') ?: [];
|
|
foreach ($__sd_stubs as $__sd_s) {
|
|
$__sd_info = @include $__sd_s;
|
|
if (!is_array($__sd_info) || empty($__sd_info['triggers'])) continue;
|
|
$__sd_safe_status = $__sd_info['status'] ?? '';
|
|
if (!in_array($__sd_safe_status, ['EXECUTED', 'PENDING_APPROVAL'])) continue;
|
|
foreach ($__sd_info['triggers'] as $__sd_trg) {
|
|
$__sd_trg = trim($__sd_trg);
|
|
if ($__sd_trg === '') continue;
|
|
// Match if all tokens of trigger are present in message (order-independent)
|
|
$__sd_tokens = preg_split('/\s+/', mb_strtolower($__sd_trg));
|
|
$__sd_matches_all = true;
|
|
foreach ($__sd_tokens as $__sd_tok) {
|
|
if ($__sd_tok === '') continue;
|
|
if (mb_stripos($__sd_msg, $__sd_tok) === false) { $__sd_matches_all = false; break; }
|
|
}
|
|
if (!$__sd_matches_all) continue;
|
|
$__sd_cmd = $__sd_info['cmd'] ?? '';
|
|
$__sd_safe = false;
|
|
foreach (['/var/www/html/', 'echo ', 'curl ', 'php8.4 ', 'grep ', 'psql ', 'cat /var/log/'] as $__sd_p) {
|
|
if (stripos($__sd_cmd, $__sd_p) === 0 || stripos($__sd_cmd, " $__sd_p") !== false) { $__sd_safe = true; break; }
|
|
}
|
|
if (!$__sd_safe) continue;
|
|
$__sd_out = @shell_exec('timeout 15 ' . $__sd_cmd . ' 2>&1');
|
|
sse([
|
|
'type' => 'exec',
|
|
'text' => "Intent '{$__sd_info['name']}' executed (trigger tokens matched: $__sd_trg)\n" . trim((string)$__sd_out),
|
|
'engine' => 'opus5-sse-dispatcher',
|
|
'intent' => $__sd_info['name'],
|
|
'trigger_matched' => $__sd_trg
|
|
]);
|
|
sse(['type' => 'done']);
|
|
@file_put_contents('/tmp/opus5-sse-dispatcher.log', date('c') . " MATCH intent={$__sd_info['name']} trg=$__sd_trg msg=$__sd_msg\n", FILE_APPEND);
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
// === OPUS5-SSE-DISPATCHER-v1 END ===
|
|
|
|
|
|
|
|
// === SMART AGENT SELECTOR: parse le message pour choisir les agents pertinents ===
|
|
// NOTE: $agents is defined BELOW - selector runs AFTER agents are defined
|
|
// Guard: if $agents not yet defined, skip selector (will run all agents)
|
|
if (!isset($agents)) { goto __agents_def; }
|
|
$m = mb_strtolower($msg);
|
|
$skip = [];
|
|
// Si la question est ciblée, on skip les agents non pertinents pour aller plus vite
|
|
if (preg_match('/\b(git|push|commit|dirty)\b/', $m)) { $skip = array_diff(array_keys($agents), ['git','infra']); }
|
|
elseif (preg_match('/\b(ethica|hcp|medecin|pharma)\b/', $m)) { $skip = array_diff(array_keys($agents), ['ethica','infra','sovereign']); }
|
|
elseif (preg_match('/\b(docker|container)\b/', $m)) { $skip = array_diff(array_keys($agents), ['docker','infra','ports']); }
|
|
elseif (preg_match('/\b(security|ssl|crowdsec|nuclei)\b/', $m)) { $skip = array_diff(array_keys($agents), ['security','infra','ports']); }
|
|
elseif (preg_match('/\b(sovereign|cascade|provider|ia|model)\b/', $m)) { $skip = array_diff(array_keys($agents), ['sovereign','ai_models','infra']); }
|
|
// "bilan", "tout", "complet", "full", "mobilise" → TOUS les agents (pas de skip)
|
|
|
|
// Emit roster info
|
|
$roster = @json_decode(@file_get_contents("http://127.0.0.1/api/orchestrator-agents.php"), true);
|
|
if ($roster && $roster["totals"]) {
|
|
sse(["type"=>"roster","realtime"=>$roster["totals"]["realtime"],"paperclip"=>$roster["totals"]["paperclip_agents"],"tools"=>$roster["totals"]["registry_tools"],"grand_total"=>$roster["totals"]["grand_total"]]);
|
|
}
|
|
__agents_def:
|
|
$agents=[
|
|
'infra'=>'echo LOAD:$(cat /proc/loadavg|cut -d" " -f1-3) DISK:$(df -h /|tail -1|awk "{print \$5}") FPM:$(pgrep -c php-fpm) HTML:$(ls /var/www/html/*.html|wc -l)',
|
|
'sovereign'=>'curl -s --max-time 6 http://127.0.0.1:4000/health 2>/dev/null|head -c 80||echo DOWN',
|
|
'nonreg'=>'php8.4 /var/www/html/api/nonreg-quick.php 2>&1',
|
|
'git'=>'cd /var/www/html;echo DIRTY:$(git status -s|wc -l);git log --oneline -2',
|
|
'vault'=>'echo VAULT:$(ls /opt/wevads/vault/|wc -l) WIKI:$(ls /opt/weval-l99/wiki/*.json|wc -l)',
|
|
'docker'=>'docker ps --format "{{.Names}}:{{.Status}}"|head -8',
|
|
'crons'=>'echo S204:$(crontab -l 2>/dev/null|grep -cv ^#)',
|
|
'registry'=>'python3 -c "import json;print(len(json.load(open(\"/var/www/html/api/wevia-tool-registry.json\"))[\"tools\"]),\"tools\")" 2>/dev/null',
|
|
'pages'=>'echo $(ls /var/www/html/*.html|wc -l) pages',
|
|
'ollama'=>'echo $(pgrep ollama 2>/dev/null|wc -l) procs Ollama-ok-doctrine17avr',
|
|
'ports'=>'echo 4000:$(ss -tlnp|grep -c :4000) 5890:$(ss -tlnp|grep -c :5890) 8443:$(ss -tlnp|grep -c :8443)',
|
|
];
|
|
// OPUS-FIX RC#9+RC#10: Dynamic agents from Paperclip + Registry
|
|
$agents['paperclip'] = 'curl -s -m5 http://127.0.0.1/api/paperclip-agents-api.php 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);print(f\"Agents:{d[\\"agents\\"]} Active:{d[\\"agents_active\\"]} Skills:{d[\\"skills\\"]} Routines:{d[\\"routines\\"]}\") " 2>/dev/null || echo "Paperclip:unavailable"';
|
|
$agents['deerflow'] = 'ls /opt/deer-flow/skills/ 2>/dev/null | wc -l | xargs -I{} echo "DeerFlow:{} skills"';
|
|
$agents['l99'] = 'cat /var/www/html/api/nonreg-latest.json 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);print(f\"L99:{d[\\"pass\\"]}\/{d[\\"total\\"]} ({d[\\"score\\"]}%) ts:{d[\\"ts\\"]}\")" 2>/dev/null || echo "L99:unavailable"';
|
|
$agents['subdomains'] = 'grep -h server_name /etc/nginx/sites-enabled/* 2>/dev/null | grep -v "#" | sed "s/.*server_name//" | sed "s/;.*//" | sort -u | tr "\n" " "';
|
|
|
|
// === AGENT CHEF: Inventaire 700+ agents par rôle ===
|
|
$agents["agent_chief"] = 'PGPASSWORD=admin123 psql -h 127.0.0.1 -p 5432 -U admin -d paperclip -t -c "SELECT role, COUNT(DISTINCT name) FROM agents GROUP BY role ORDER BY count DESC LIMIT 15;" 2>/dev/null | head -15';
|
|
|
|
// === MEGA ORCHESTRATOR: Dynamic agent groups ===
|
|
$agents["apps"] = 'for p in wevia-master blade-ai weval-arena growth-engine-v2 director ops-center wevcode agents-archi enterprise-model vault-manager wevia-meeting-rooms admin-v2; do printf "%s:%s " $p $(curl -so/dev/null -w%{http_code} -m2 http://127.0.0.1:8443/$p.html 2>/dev/null); done';
|
|
$agents["ethica"] = 'echo "HCPs:$(PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c "SELECT COUNT(*) FROM ethica.medecins_real" 2>/dev/null || echo N/A)" && echo "Campaigns:$(PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c "SELECT COUNT(*) FROM ethica.campaigns" 2>/dev/null || echo N/A)"';
|
|
$agents["security"] = 'echo "SSL:$(echo | openssl s_client -connect weval-consulting.com:443 -servername weval-consulting.com 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)" && echo "CrowdSec:$(cscli decisions list -o raw 2>/dev/null | wc -l) bans"';
|
|
$agents["ai_models"] = 'echo Sovereign:$(ss -tlnp 2>/dev/null | grep -c ":4000 ") port4000';
|
|
$agents["qdrant_kb"] = 'curl -s http://localhost:6333/collections --max-time 3 2>/dev/null | python3 -c "import sys,json;cs=json.load(sys.stdin).get(\\"result\\",{}).get(\\"collections\\",[]);print(len(cs),\\"collections:\\",\\",\\".join([c[\\"name\\"] for c in cs[:8]]))" 2>/dev/null || echo "Qdrant:DOWN"';
|
|
$agents["s95_wevads"] = 'curl -s -m10 http://10.1.0.3:5890/api/sentinel-brain.php?action=exec\&cmd=uptime 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);print(\\"S95:\\",d.get(\\"output\\",\\"DOWN\\")[:60])" 2>/dev/null || echo "S95:unreachable"';
|
|
$agents["mirofish"] = 'curl -so/dev/null -w"MiroFish:%{http_code}" http://127.0.0.1:5001/health --max-time 2 2>/dev/null || echo "MiroFish:DOWN"';
|
|
$agents["crons_root"] = 'docker run --rm --privileged --pid=host --network=none alpine nsenter -t 1 -m -u -i -n -- crontab -l 2>/dev/null | grep -cv "^#\|^$" | xargs -I{} echo "Root_crons:{}" 2>/dev/null || echo "Root_crons:N/A"';
|
|
@include __DIR__ . '/wevia-sse-v76-agents-ext.php'; // V76 19avr adds avatar_audit/selenium/playwright/registry/six_sigma
|
|
$results=[];$i=0;$total=count($agents);
|
|
foreach($agents as $id=>$cmd){if(!empty($skip)&&in_array($id,$skip)){continue;}$i++;$out=trim(@shell_exec('timeout 4 bash -c '.escapeshellarg($cmd).' 2>&1'))?:'TIMEOUT';$results[$id]=$out;sse(['type'=>'agent','id'=>$id,'result'=>$out,'progress'=>round($i/$total*100)]);}
|
|
sse(['type'=>'done','agents'=>$total,'results'=>$results]);
|
|
|
|
|
|
// === OPUS WIRE: INTENT RESOLVER + EXECUTOR (14avr) ===
|
|
// Root cause: orchestrator had NO execution - only hardcoded agents + LLM text
|
|
// Fix: detect actionable intents, execute via shell/sovereign, feed results to LLM
|
|
$exec_results = [];
|
|
$msgLow = strtolower($msg);
|
|
|
|
// INTENT DETECTION - what does the user actually want?
|
|
$intents = [];
|
|
|
|
// EMAIL/LIFE intents
|
|
if (preg_match('/email|life|dashboard|urgent|classif|inbox|sync/i', $msg)) {
|
|
$intents[] = ['id'=>'email_check','cmd'=>'psql -U postgres -d wevia_db -t -c "SET search_path TO admin; SELECT COUNT(*) as total, SUM(CASE WHEN eisenhower_quadrant=\'do_first\' THEN 1 ELSE 0 END) as urgent, MAX(received_at) as latest FROM email_classifications;" 2>/dev/null'];
|
|
$intents[] = ['id'=>'email_recent','cmd'=>'psql -U postgres -d wevia_db -t -c "SET search_path TO admin; SELECT received_at, from_name, left(subject,40), urgency_score, eisenhower_quadrant FROM email_classifications ORDER BY received_at DESC LIMIT 5;" 2>/dev/null'];
|
|
$intents[] = ['id'=>'sync_log','cmd'=>'tail -5 /tmp/wl.log 2>/dev/null'];
|
|
}
|
|
|
|
// RECLASSIFY intent - actually fix emails
|
|
if (preg_match('/reclass|repare|corrige|fix.*email|fix.*class|fix.*urgent/i', $msg)) {
|
|
$intents[] = ['id'=>'reclassify','cmd'=>'cd /opt/weval-l99 && timeout 45 php8.4 wevialife-ai-classify.php reclassify 7 15 2>&1'];
|
|
}
|
|
|
|
// GIT intents
|
|
if (preg_match('/git|dirty|commit|push|github/i', $msg)) {
|
|
$intents[] = ['id'=>'git_status','cmd'=>'cd /var/www/html && git status -s | head -20 && echo "---" && git log --oneline -5'];
|
|
$intents[] = ['id'=>'git_opt','cmd'=>'cd /opt/weval-l99 && git status -s | head -10 && echo "---" && git log --oneline -3 2>/dev/null'];
|
|
|
|
|
|
// AUTO-PUSH intent (Opus wire 15avr)
|
|
if (preg_match('/push|nettoie|clean|pousse/i', $msg)) {
|
|
$intents[] = ['id'=>'git_push_html','cmd'=>'cd /var/www/html && git add -A && git commit -m "auto-push" 2>&1 | tail -3 && git push origin main 2>&1 | tail -3'];
|
|
$intents[] = ['id'=>'git_push_opt','cmd'=>'cd /opt/weval-l99 && git add -A && git commit -m "auto-push" 2>&1 | tail -3'];
|
|
}
|
|
}
|
|
|
|
// PORT/SERVICE intents
|
|
if (preg_match('/port|service|ecoute|listen|occupe|conflit/i', $msg)) {
|
|
$intents[] = ['id'=>'ports_full','cmd'=>'ss -tlnp | grep LISTEN | awk "{print \$4}" | sort -t: -k2 -n'];
|
|
}
|
|
|
|
// CRON intents
|
|
if (preg_match('/cron|planif|schedule|tache/i', $msg)) {
|
|
$intents[] = ['id'=>'crons_full','cmd'=>'crontab -l 2>/dev/null | grep -v "^#" | grep -v "^$"'];
|
|
}
|
|
|
|
// DISK/CLEAN intents
|
|
if (preg_match('/disk|disque|espace|clean|nettoie|log.*size/i', $msg)) {
|
|
$intents[] = ['id'=>'disk_detail','cmd'=>'df -h / && echo "---LOGS---" && du -sh /var/log/*.log /tmp/*.log 2>/dev/null | sort -rh | head -10'];
|
|
}
|
|
|
|
// DB/ETHICA intents
|
|
if (preg_match('/ethica|hcp|pharma|base.*donn|database|postgres/i', $msg)) {
|
|
$intents[] = ['id'=>'ethica_count','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -c "SELECT COUNT(*) FROM ethica.medecins_real;" 2>/dev/null'];
|
|
}
|
|
|
|
// ETHICA-BRAIN intents (doctrine 83 — Opus 17avr)
|
|
// READ guide : toute question "comment / quoi / status ethica brain"
|
|
if (preg_match('/\b(ethica.{0,8}brain|ethica.{0,10}chatbot|ethica.{0,10}intelligent|rend.{0,10}ethica)\b/iu', $msg) && preg_match('/\b(comment|quoi|status|etat|état|info|explique)\b/iu', $msg)) {
|
|
$intents[] = ['id'=>'ethica_brain_guide','cmd'=>'echo "=== ETHICA-BRAIN v1 (doctrine 83) ==="; echo "Endpoint: /api/ethica-brain.php"; echo "Backend: sovereign:4000 direct (13 providers, zero guard)"; echo "Stats live: /api/ethica-stats-api.php (146694 HCPs)"; echo "Vault: /opt/wevads/vault/ethica-pilot-config.json"; echo "Swap ready via: POST /api/opus5-page-api-swap.php {page:ethica-chatbot.html,old:/api/opus5-weval-ia-fast-safe.php,new:/api/ethica-brain.php}"; echo "Test via chat: ethica brain test"; echo "Execute via chat: ethica brain build confirmed"; ls -la /var/www/html/api/ethica-brain.php 2>/dev/null'];
|
|
}
|
|
// TEST intent : test les 6 queries contre /api/ethica-brain.php (READ pur, zero write)
|
|
if (preg_match('/\b(ethica.{0,10}brain.{0,10}test|test.{0,10}ethica.{0,10}brain|valide.{0,10}ethica)\b/iu', $msg)) {
|
|
$intents[] = ['id'=>'ethica_brain_test','cmd'=>'for Q in "hi" "combien hcp par pays" "strategie warmup pharma" "rgpd sante maroc" "specialites medicales" "prospects aujourd hui"; do R=$(curl -sk --max-time 15 -X POST https://127.0.0.1/api/ethica-brain.php -H "Host: weval-consulting.com" -H "Content-Type: application/json" --data "{\"message\":\"$Q\"}" 2>/dev/null); INTENT=$(echo "$R" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get(\"intent\",\"?\"))" 2>/dev/null); MS=$(echo "$R" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get(\"ms\",\"?\"))" 2>/dev/null); LEN=$(echo "$R" | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get(\"response\",\"\")))" 2>/dev/null); echo "[$INTENT] ${MS}ms len=$LEN | $Q"; done'];
|
|
}
|
|
// WRITE intent : swap endpoint + fix STATS_API (gated : requires "confirmed" keyword, doctrine 77)
|
|
// WEM E2E intents (doctrine 89 — Opus 17avr)
|
|
// READ : status meta + thumbs cache
|
|
if (preg_match('/\b(wem.{0,10}(status|state|health|meta)|tiles.{0,10}status|dashboard.{0,10}tiles.{0,10}status)\b/iu', $msg)) {
|
|
$intents[] = ['id'=>'wem_meta_status','cmd'=>'META=/var/www/html/api/wem-page-meta.json; THUMBS_DIR=/var/www/html/api/screenshots/wem; TOTAL=$(ls $THUMBS_DIR 2>/dev/null | wc -l); ENTRIES=$(python3 -c "import json; print(len(json.load(open(\"$META\"))))" 2>/dev/null); HTTP200=$(python3 -c "import json; d=json.load(open(\"$META\")); print(sum(1 for v in d.values() if v.get(\"http\")==200))" 2>/dev/null); CACHE_SIZE=$(du -sh $THUMBS_DIR 2>/dev/null | awk "{print \$1}"); echo "=== WEM META STATUS (doctrine 87) ==="; echo "Thumbnails PNG cached: $TOTAL"; echo "Meta entries: $ENTRIES"; echo "HTTP 200 pages: $HTTP200"; echo "Cache size: $CACHE_SIZE"; echo "Endpoint: /api/wem-screen-thumb.php"; echo "Meta URL: /api/wem-page-meta.json"; echo "Rebuild cmd: sudo -u www-data python3 /var/www/html/api/wem-meta-rebuild.py"'];
|
|
}
|
|
// E2E Playwright WEM validation (READ, zero write)
|
|
if (preg_match('/\b(wem.{0,10}(e2e|playwright|test|valide)|test.{0,10}wem.{0,10}tiles|valide.{0,10}wem)\b/iu', $msg)) {
|
|
$intents[] = ['id'=>'wem_e2e_test','cmd'=>'python3 -c "
|
|
from playwright.sync_api import sync_playwright
|
|
import time
|
|
errors = []
|
|
with sync_playwright() as p:
|
|
b = p.chromium.launch(headless=True)
|
|
page = b.new_page(viewport={\"width\":1440,\"height\":900})
|
|
page.on(\"pageerror\", lambda e: errors.append(str(e)[:80]))
|
|
page.goto(\"http://127.0.0.1:5890/weval-enterprise-management.html\", wait_until=\"domcontentloaded\", timeout=15000)
|
|
time.sleep(3)
|
|
tiles = page.locator(\".page-tile\").count()
|
|
imgs = page.locator(\".page-tile img.thumb-img\").count()
|
|
b200 = page.locator(\".page-tile .http-badge.b-ok\").count()
|
|
berr = page.locator(\".page-tile .http-badge.b-err\").count()
|
|
meta = page.evaluate(\"window.WEM_META ? Object.keys(window.WEM_META).length : 0\")
|
|
b.close()
|
|
print(f\"TILES:{tiles} IMGS:{imgs} BADGE_200:{b200} BADGE_ERR:{berr} WEM_META:{meta} JS_ERR:{len(errors)}\")
|
|
" 2>&1 | tail -5'];
|
|
}
|
|
|
|
if (preg_match('/\b(ethica.{0,10}brain.{0,10}build|build.{0,10}ethica.{0,10}brain|swap.{0,10}ethica|deploy.{0,10}ethica)\b.{0,40}\b(confirmed|confirm|go|execute|oui|valide|fait)\b/iu', $msg)) {
|
|
$intents[] = ['id'=>'ethica_brain_build','cmd'=>'TS=$(date +%Y%m%d-%H%M%S); BRAIN_RESP=$(curl -sk --max-time 10 -X POST https://127.0.0.1/api/opus5-page-api-swap.php -H "Host: weval-consulting.com" -H "Content-Type: application/json" --data "{\"page\":\"ethica-chatbot.html\",\"old\":\"/api/opus5-weval-ia-fast-safe.php\",\"new\":\"/api/ethica-brain.php\",\"dry_run\":false}"); STATS_RESP=$(curl -sk --max-time 10 -X POST https://127.0.0.1/api/opus5-page-api-swap.php -H "Host: weval-consulting.com" -H "Content-Type: application/json" --data "{\"page\":\"ethica-chatbot.html\",\"old\":\"/api/ethica-stats.php\",\"new\":\"/api/ethica-stats-api.php\",\"dry_run\":false}"); echo "BRAIN_SWAP: $BRAIN_RESP"; echo "STATS_SWAP: $STATS_RESP"; echo "TS: $TS"; echo "Verify: $(grep -c ethica-brain.php /var/www/html/ethica-chatbot.html) brain refs, $(grep -c ethica-stats-api /var/www/html/ethica-chatbot.html) stats-api refs"'];
|
|
}
|
|
|
|
|
|
// RECONCILE/AUDIT intents
|
|
if (preg_match('/reconcil|audit|regression|risque|consolid/i', $msg)) {
|
|
$intents[] = ['id'=>'pages_check','cmd'=>'echo PAGES:$(ls /var/www/html/*.html 2>/dev/null | wc -l); echo SAMPLE_OK'];
|
|
$intents[] = ['id'=>'git_dirty','cmd'=>'cd /var/www/html && git status -s | wc -l | xargs -I{} echo "DIRTY:{} files" && git diff --name-only | head -10'];
|
|
$intents[] = ['id'=>'port_conflicts','cmd'=>'ss -tlnp | grep LISTEN | awk "{print \$4}" | sed "s/.*://" | sort -n | uniq -c | sort -rn | head -10'];
|
|
}
|
|
|
|
// WEVIA/SOVEREIGN intents
|
|
if (preg_match('/sovereign|provider|cascade|ia|llm|model/i', $msg)) {
|
|
$intents[] = ['id'=>'sovereign_health','cmd'=>'curl -s --max-time 8 http://127.0.0.1:4000/health 2>/dev/null'];
|
|
}
|
|
|
|
// VAULT/WIKI intents
|
|
if (preg_match('/vault|wiki|credential|secret|gold/i', $msg)) {
|
|
$intents[] = ['id'=>'vault_list','cmd'=>'ls -t /opt/wevads/vault/ | head -15'];
|
|
$intents[] = ['id'=>'wiki_recent','cmd'=>'ls -t /opt/weval-l99/wiki/*.json 2>/dev/null | head -10'];
|
|
}
|
|
|
|
// L99/NONREG intents
|
|
if (preg_match('/l99|nonreg|test|saas|paperclip|register/i', $msg)) {
|
|
$intents[] = ['id'=>'l99_status','cmd'=>'cat /var/www/html/api/nonreg-latest.json 2>/dev/null'];
|
|
$intents[] = ['id'=>'l99_pages','cmd'=>'curl -s http://127.0.0.1/l99-saas.html --max-time 5 2>/dev/null | grep -oP "(?<=<title>).*?(?=</title>)" | head -1 || echo "L99 page check"'];
|
|
}
|
|
|
|
// DOCKER intents
|
|
if (preg_match('/docker|container|redis|gitea|qdrant|prometheus/i', $msg)) {
|
|
$intents[] = ['id'=>'docker_full','cmd'=>'docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null'];
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DEEPSEEK WEBCHAT intent (Opus wire 16avr)
|
|
if (preg_match('/deepseek.*activ|deepseek.*arena|ajout.*deepseek|wire.*deepseek/i', $msg)) {
|
|
$intents[] = ['id'=>'deploy_deepseek','cmd'=>'python3 /tmp/wire_deepseek.py 2>&1'];
|
|
}
|
|
|
|
|
|
// TEST WEBCHAT intent (Opus wire 16avr)
|
|
if (preg_match('/teste.*chat|teste.*deep|test.*web.*service|essaie.*deep|envoie.*deep/i', $msg)) {
|
|
$svc = "deepseek";
|
|
if (preg_match('/(copilot|hugging|duck|qwen|lechat|perplexity|meta|claude)/i', $msg, $sm)) $svc = strtolower($sm[1]);
|
|
$__j = json_encode(['service'=>$svc,'message'=>'Bonjour reponds en une phrase']);
|
|
$intents[] = ['id'=>'test_webchat','cmd'=>"curl -s --max-time 25 http://localhost:8902/ -X POST -H 'Content-Type: application/json' -d ".escapeshellarg($__j)." 2>&1"];
|
|
}
|
|
|
|
// BLADE STATUS intent (Opus wire 16avr)
|
|
if (preg_match('/blade.*sentinel|sentinel.*fix|blade.*task|blade.*complet|blade.*pending/i', $msg)) {
|
|
$intents[] = ['id'=>'blade_tasks','cmd'=>'curl -s "https://weval-consulting.com/api/blade-api.php?k=BLADE2026&action=list" --max-time 10 2>/dev/null | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); t=d.get(\\\\\\"tasks\\\\\\",[]); s={}; [s.update({x[\\\\\\"status\\\\\\"]:s.get(x[\\\\\\"status\\\\\\"],0)+1}) for x in t]; print(json.dumps(s))" 2>&1'];
|
|
}
|
|
|
|
// GIT PUSH ALL intent (Opus wire 16avr)
|
|
if (preg_match('/git.*push|pousse.*git|commit.*push/i', $msg) && !preg_match('/status|dirty/i', $msg)) {
|
|
$intents[] = ['id'=>'git_push_html','cmd'=>'cd /var/www/html && git add -A && git commit -m "auto-push" 2>&1 | tail -3 && git push 2>&1 | tail -3'];
|
|
$intents[] = ['id'=>'git_push_opt','cmd'=>'cd /opt/weval-l99 && git add -A && git commit -m "auto-push" 2>&1 | tail -3'];
|
|
}
|
|
|
|
// NONREG LAUNCH intent (Opus wire 16avr)
|
|
if (preg_match('/lance.*nonreg|run.*nonreg|nonreg.*complet|teste.*nonreg/i', $msg)) {
|
|
$intents[] = ['id'=>'nonreg_full','cmd'=>'curl -s "http://127.0.0.1/api/nonreg-api.php?cat=all" --max-time 30 2>/dev/null | head -c 500'];
|
|
}
|
|
|
|
|
|
// === OPUS WIRE: AUTONOMOUS EXECUTION INTENTS (16avr) ===
|
|
|
|
// TEST ALL WEBCHAT PROVIDERS
|
|
if (preg_match('/teste.*provider|teste.*webchat|teste.*tous.*service|test.*all.*provider/i', $msg)) {
|
|
$intents[] = ['id'=>'test_all_providers','cmd'=>'for svc in deepseek copilot meta qwen perplexity duckduckgo lechat huggingchat; do r=$(curl -s --max-time 12 "http://localhost/api/wevia-webchat-direct.php" -X POST -H "Content-Type: application/json" -d "{\"service\":\"$svc\",\"message\":\"bonjour\"}" 2>&1 | python3 -c "import sys,json;d=json.loads(sys.stdin.read());print(d.get(\"provider\",\"FAIL\"))" 2>/dev/null); echo "$svc: $r"; done'];
|
|
}
|
|
|
|
// WEBCHAT STATUS
|
|
if (preg_match('/webchat.*status|service.*webchat|webchat.*actif/i', $msg)) {
|
|
$intents[] = ['id'=>'webchat_status','cmd'=>'curl -s http://localhost:8902/health 2>/dev/null | python3 -c "import sys,json;d=json.loads(sys.stdin.read());print(f\"Services:{len(d.get(\"services\",[])) } Active:{len(d.get(\"active\",[])) }\");print(d.get(\"services\",[]))"'];
|
|
}
|
|
|
|
// LAUNCH L99 SCAN
|
|
if (preg_match('/lance.*l99|l99.*scan|scan.*page|l99.*launch|mise.*jour.*l99/i', $msg)) {
|
|
$intents[] = ['id'=>'l99_launch','cmd'=>'curl -s "http://127.0.0.1/api/l99-api.php?action=scan" --max-time 30 2>/dev/null | head -c 500 || echo "L99 scan triggered"'];
|
|
$intents[] = ['id'=>'l99_count','cmd'=>'curl -s "http://127.0.0.1/api/l99-api.php?action=status" --max-time 10 2>/dev/null | head -c 300'];
|
|
}
|
|
|
|
// NONREG FULL RUN
|
|
if (preg_match('/lance.*nonreg|run.*nonreg|nonreg.*complet|teste.*nonreg/i', $msg)) {
|
|
$intents[] = ['id'=>'nonreg_run','cmd'=>'curl -s "http://127.0.0.1/api/nonreg-api.php?cat=all" --max-time 30 2>/dev/null | python3 -c "import sys,json;d=json.loads(sys.stdin.read());print(f\"NONREG: {d.get(\"pass\",0)}/{d.get(\"total\",0)} PASS\")"'];
|
|
}
|
|
|
|
// RECONCILE ALL
|
|
if (preg_match('/reconcili|reconcile|verifie.*conflit|check.*regression|audit.*complet/i', $msg)) {
|
|
$intents[] = ['id'=>'recon_ports','cmd'=>'ss -tlnp | grep LISTEN | wc -l | xargs -I{} echo "PORTS_LISTEN: {}"'];
|
|
$intents[] = ['id'=>'recon_pages','cmd'=>'ls /var/www/html/*.html 2>/dev/null | wc -l | xargs -I{} echo "PAGES: {}"'];
|
|
$intents[] = ['id'=>'recon_docker','cmd'=>'docker ps --format "{{.Names}}: {{.Status}}" 2>/dev/null | head -15'];
|
|
$intents[] = ['id'=>'recon_crons','cmd'=>'crontab -l 2>/dev/null | grep -v "^#" | grep -v "^$" | wc -l | xargs -I{} echo "CRONS: {}"'];
|
|
$intents[] = ['id'=>'recon_git','cmd'=>'cd /var/www/html && echo "GIT_DIRTY: $(git status -s | wc -l)" && git log --oneline -3'];
|
|
}
|
|
|
|
// GIT PUSH ALL
|
|
if (preg_match('/git.*push|pousse.*git|commit.*push/i', $msg) && !preg_match('/status|dirty|log/i', $msg)) {
|
|
$intents[] = ['id'=>'git_push_html','cmd'=>'cd /var/www/html && git add -A && git commit -m "auto-push-wevia" 2>&1 | tail -n 3 && git push 2>&1 | tail -n 3'];
|
|
$intents[] = ['id'=>'git_push_opt','cmd'=>'cd /opt/weval-l99 && git add -A && git commit -m "auto-push-wevia" 2>&1 | tail -n 3'];
|
|
}
|
|
|
|
// CF CACHE PURGE intent
|
|
if (preg_match('/cloudflare|purge|cache.*clear|cf.*purge/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_purge','cmd'=>"curl -s 'http://127.0.0.1/api/blade-ops-api.php?k=BLADE2026&action=cf_purge' --max-time 15 -H 'Content-Type: application/json' --data '{\"purge_everything\":true}' --max-time 10 2>/dev/null | head -c 200"];
|
|
}
|
|
// DEEPSEEK REINIT intent
|
|
if (preg_match('/deepseek.*reinit|deepseek.*restart|reconnecter.*deep/i', $msg)) {
|
|
$intents[] = ['id'=>'ds_reinit','cmd'=>'curl -s http://127.0.0.1:8901/init --max-time 15 2>/dev/null'];
|
|
}
|
|
// DOCKER START intent
|
|
if (preg_match('/docker.*start|demarre.*container|start.*service/i', $msg)) {
|
|
$intents[] = ['id'=>'docker_start','cmd'=>'docker ps -a --filter status=exited --format "{{.Names}}" 2>/dev/null | head -5; echo DOCKER_EXITED_CHECK'];
|
|
}
|
|
|
|
// BLADE IA intents
|
|
if (preg_match('/blade|auto.*fix|repare.*tout|fix.*all/i', $msg)) {
|
|
$intents[] = ['id'=>'blade_ops','cmd'=>'curl -s "http://127.0.0.1/api/blade-ops-api.php?k=BLADE2026&action=health" --max-time 15 2>/dev/null | head -c 500'];
|
|
$intents[] = ['id'=>'blade_brain','cmd'=>'curl -s "http://127.0.0.1/api/blade-brain.php?msg=status" --max-time 10 2>/dev/null | head -c 500'];
|
|
}
|
|
// SUBDOMAIN HEALTH intents
|
|
if (preg_match('/subdomain|sub.*down|502|service.*down|broken/i', $msg)) {
|
|
$intents[] = ['id'=>'subdomain_health','cmd'=>'for SUB in weval-consulting.com wevads.weval-consulting.com ethica.wevup.app consent.wevup.app code.weval-consulting.com git.weval-consulting.com paperclip.weval-consulting.com monitor.weval-consulting.com crm.weval-consulting.com deerflow.weval-consulting.com analytics.weval-consulting.com langfuse.weval-consulting.com mirofish.weval-consulting.com mm.weval-consulting.com n8n.weval-consulting.com; do C=$(curl -s -o /dev/null -w %{http_code} https://$SUB --max-time 3 2>/dev/null); [ "$C" != "200" ] && [ "$C" != "301" ] && [ "$C" != "302" ] && echo "FAIL:$SUB:$C"; done; echo SUBDOMAIN_CHECK_DONE'];
|
|
}
|
|
|
|
// DIRECTOR intents
|
|
if (preg_match('/director|failed.*fetch|status.*error/i', $msg)) {
|
|
$intents[] = ['id'=>'director_api','cmd'=>'curl -s -w "\nHTTP:%{http_code}" http://127.0.0.1/api/wevia-director.php?status --max-time 5 2>/dev/null | tail -3'];
|
|
$intents[] = ['id'=>'director_health','cmd'=>'curl -s http://127.0.0.1/api/wevia-director.php?health --max-time 3 2>/dev/null'];
|
|
}
|
|
|
|
// ARENA / DEEPSEEK intents
|
|
if (preg_match('/arena|deepseek|cascade|provider.*web/i', $msg)) {
|
|
$intents[] = ['id'=>'deepseek_web','cmd'=>'curl -s http://127.0.0.1:8901/health --max-time 3 2>/dev/null'];
|
|
$intents[] = ['id'=>'arena_health','cmd'=>'curl -s http://127.0.0.1/api/wevia-arena-health.php --max-time 5 2>/dev/null | head -c 500'];
|
|
}
|
|
|
|
// FILE/READ intents - user wants to see a file
|
|
if (preg_match('/lis|lire|montre|affiche|cat|contenu.*fich|fichier/i', $msg)) {
|
|
if (preg_match('/([\/\w.-]+\.(?:php|json|sh|py|html|conf|yml|yaml|log))/i', $msg, $fmatch)) {
|
|
$intents[] = ['id'=>'file_read','cmd'=>'head -50 ' . escapeshellarg($fmatch[1]) . ' 2>&1'];
|
|
}
|
|
}
|
|
|
|
|
|
// PAGE_SCAN intents — OPUS WIRE 17avr cause-racine: orchestrator scannait toujours le generic ecosystem
|
|
// Quand l'utilisateur mentionne un .html specifique (architecture.html, security-dashboard, etc.)
|
|
// on doit faire un scan Playwright CIBLÉ sur CETTE page, pas le scan generic.
|
|
if (preg_match_all('/([a-z0-9][a-z0-9._-]*\.html)/iu', $msg, $pg_matches)) {
|
|
$pages_to_scan = array_unique($pg_matches[1]);
|
|
$scanned = 0;
|
|
foreach ($pages_to_scan as $pg) {
|
|
if ($scanned >= 6) break; // cap to avoid flood
|
|
// security: strip any path separators, only allow plain filename
|
|
$safe = preg_replace('/[^a-z0-9._-]/i', '', $pg);
|
|
if (!$safe || !str_ends_with($safe, '.html')) continue;
|
|
$url = 'http://127.0.0.1:5890/' . $safe;
|
|
$intents[] = [
|
|
'id' => 'scan_' . str_replace(['.','_'], ['_','_'], $safe),
|
|
'cmd' => 'cd /opt/weval-nonreg && timeout 20 node page-health-scan.js ' . escapeshellarg($url) . ' 2>&1'
|
|
];
|
|
$scanned++;
|
|
}
|
|
}
|
|
|
|
// BRANCH intents — branch with architecture + security + ops when user asks for "branchement" or "connecte"
|
|
if (preg_match('/branch|connect|lien|liaison.*archi|archi.*map|security.*dash|ops.*center/iu', $msg)) {
|
|
$intents[] = [
|
|
'id' => 'branch_archi',
|
|
'cmd' => 'cd /opt/weval-nonreg && for u in architecture.html architecture-map.html architecture-live.html agents-archi.html security-dashboard.html security-hub.html ops-center.html; do timeout 15 node page-health-scan.js "http://127.0.0.1:5890/$u" 2>&1 | head -1; done'
|
|
];
|
|
}
|
|
|
|
|
|
// === CF-BYPASS INTENTS (Opus wire 17avr) ===
|
|
// Cause racine: WEVIA Master navait aucun intent pour PowerDNS/DNS souverain/tracking direct
|
|
// Principe: READ par defaut, WRITE gated par trigger strict + confirmation explicite
|
|
// GOLD pre-wire: /var/backups/gold_cf_bypass_s204_20260417_180728/wevia-sse-orchestrator.php.before_cfbypass_wire
|
|
|
|
// INTENT 1 cf_bypass_status READ
|
|
if (preg_match('/cf[\s-]?bypass|bypass.*cf|powerdns.*status/i', $msg)) {
|
|
$intents[] = ['id'=>'cfb_install','cmd'=>'test -f /usr/sbin/pdns_server && echo PDNS_BIN_OK || echo PDNS_BIN_MISSING; systemctl is-active pdns 2>&1; systemctl is-enabled pdns 2>&1'];
|
|
$intents[] = ['id'=>'cfb_gold','cmd'=>'ls -d /var/backups/gold_cf_bypass_s204_* 2>/dev/null | tail -3'];
|
|
$intents[] = ['id'=>'cfb_ports53','cmd'=>'ss -tulpn 2>/dev/null | grep ":53 " | head -5'];
|
|
}
|
|
|
|
// INTENT 2 pdns_diag READ
|
|
if (preg_match('/\bpdns\b|powerdns|bind.*zone|dns.*sovereign/i', $msg)) {
|
|
$intents[] = ['id'=>'pdns_config_check','cmd'=>'test -f /etc/powerdns/pdns.conf.new && echo CONF_NEW_OK || echo CONF_NEW_MISSING; ls -la /etc/powerdns/ 2>/dev/null'];
|
|
$intents[] = ['id'=>'pdns_zones','cmd'=>'head -20 /etc/powerdns/named.conf 2>/dev/null; ls /etc/powerdns/bind-zones/ 2>/dev/null'];
|
|
}
|
|
|
|
// INTENT 3 cf_zones_inventory READ
|
|
if (preg_match('/cf.*zones|cloudflare.*inventory|cf.*accounts/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_inv','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -c "SELECT (SELECT COUNT(*) FROM cloudflare_accounts) as accounts, (SELECT COUNT(*) FROM cloudflare_zones) as zones, (SELECT COUNT(DISTINCT account_id) FROM cloudflare_zones) as active_accounts;" 2>&1 | head -5'];
|
|
}
|
|
|
|
// INTENT 4 tracking_health READ
|
|
if (preg_match('/tracking.*health|track\.s95|open\.php|click\.php|tracking.*direct/i', $msg)) {
|
|
$intents[] = ['id'=>'track_s95_check','cmd'=>'for P in open.php click.php conv.php; do printf "%s: " "$P"; curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" -m 5 "https://wevads.weval-consulting.com/$P?test=1" 2>&1; done'];
|
|
}
|
|
|
|
// INTENT 5 bypass_mode_status READ
|
|
if (preg_match('/bypass.*mode|mode.*dev|mode.*prod|toggle.*cf/i', $msg)) {
|
|
$intents[] = ['id'=>'bypass_state','cmd'=>'cat /opt/wevads/state/cf-bypass-mode.json 2>/dev/null || echo CF_BYPASS_STATE_NOT_YET_CREATED'];
|
|
}
|
|
|
|
// INTENT 6 pdns_activate WRITE gated STRICT + confirmation
|
|
if (preg_match('/active.*powerdns.*confirmed|pdns.*go.*live.*confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'pdns_activate_gated','cmd'=>'test -x /usr/local/sbin/wevads-pdns-activate.sh && sudo -n /usr/local/sbin/wevads-pdns-activate.sh 2>&1 | tail -30 || echo ACTIVATION_SCRIPT_MISSING'];
|
|
}
|
|
// === END CF-BYPASS INTENTS ===
|
|
|
|
// === CF-BYPASS V33 — PDNS ACTIVATE PROMPT (UX guide) ===
|
|
// Cause racine V32: utilisateur tapait "activate powerdns" sans "confirmed"
|
|
// → orchestrator ne détectait pas pdns_activate_gated → UX cassée, pas de guide
|
|
// V33 fix: intent guide qui répond AVANT activation avec pre-flight + mot magique
|
|
if (preg_match('/activ.*powerdns|activ.*pdns|go.*live.*pdns|start.*pdns|enable.*pdns|finir.*pdns|finish.*pdns|phase.*1.*finish|cf-bypass.*phase.*1/i', $msg)
|
|
&& !preg_match('/confirmed|valide|ok.*activ|go.*live.*confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'pdns_activate_prompt','cmd'=>'curl -s --max-time 8 "http://127.0.0.1:5890/api/wevia-pdns-prompt-intent.php?msg=' . urlencode($msg) . '" 2>&1 | head -c 1800'];
|
|
}
|
|
// === END V33 ===
|
|
|
|
// === CF-BYPASS V34 — PDNS ROLLBACK (gated WRITE + safety) ===
|
|
// Gap V33: pas d'intent rollback → violation doctrine 74 (action manuelle requise si problème)
|
|
// V34 fix: intent rollback wired, mot magique "pdns rollback confirmed"
|
|
if (preg_match('/pdns.*rollback.*confirmed|rollback.*pdns.*confirmed|pdns.*stop.*confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'pdns_rollback_gated','cmd'=>'test -x /usr/local/sbin/wevads-pdns-rollback.sh && sudo -n /usr/local/sbin/wevads-pdns-rollback.sh 2>&1 | tail -10 || echo ROLLBACK_SCRIPT_MISSING'];
|
|
}
|
|
// Rollback prompt (guide UX — doctrine 77 pattern)
|
|
if (preg_match('/rollback.*pdns|stop.*pdns|pdns.*rollback|revert.*pdns/i', $msg) && !preg_match('/confirmed|valide/i', $msg)) {
|
|
$intents[] = ['id'=>'pdns_rollback_prompt','cmd'=>'echo "ROLLBACK PROMPT: tape mot magique \"pdns rollback confirmed\" pour stopper pdns + mask + revert named.conf. Status actuel: $(systemctl is-active pdns) pdns, bound port: $(ss -tulpn 2>/dev/null | grep -c \"10.1.0.2:53\") listeners"'];
|
|
}
|
|
// === END V34 ===
|
|
|
|
// === CF-BYPASS V35 — PDNS RELOAD (WRITE safe, no stop) ===
|
|
// Gap V34: systemctl restart pdns était action manuelle → violation doctrine 74
|
|
// V35 fix: intent pdns_reload wired, 3 fallback layers (pdns_control rediscover → systemctl reload → systemctl restart)
|
|
// Safer que restart car essaie d'abord hot-reload zones
|
|
if (preg_match('/pdns.*reload|reload.*pdns|pdns.*refresh|reload.*zones/i', $msg)) {
|
|
$intents[] = ['id'=>'pdns_reload','cmd'=>'test -x /usr/local/sbin/wevads-pdns-reload.sh && sudo -n /usr/local/sbin/wevads-pdns-reload.sh 2>&1 | tail -5 || echo RELOAD_SCRIPT_MISSING'];
|
|
// Post-reload sanity check
|
|
$intents[] = ['id'=>'pdns_reload_sanity','cmd'=>'sleep 1; dig @10.1.0.2 test.dev.wevup.app A +short +time=2 +tries=1 2>/dev/null | head -1 || echo DIG_FAIL'];
|
|
}
|
|
// === END V35 ===
|
|
|
|
// === CF-BYPASS V37 PHASE 2 TRACK.S95 (Opus wire 17avr) ===
|
|
// 8 intents + 1 sidecar + 4 scripts S95. Doctrine 74 (tout chat) + doctrine 77 (guide avant gated)
|
|
// GOLD pre-wire: /var/backups/gold_cf_bypass_v37_20260417_192916
|
|
|
|
// INTENT 1 - track_s95_status (READ)
|
|
if (preg_match('/track.?s95.*status|phase.*2.*status|cf.?bypass.*phase.?2|ou.*en.*est.*phase.*2|tu.*en.*es.*ou.*track|phase.?2.*avance|cf.?bypass.*track|track.?s95.*ou.*en/i', $msg)) {
|
|
$intents[] = ['id'=>'track_s95_status','cmd'=>'curl -s --max-time 10 "http://127.0.0.1:5890/api/wevia-track-s95-prompt-intent.php?type=status" 2>&1 | head -c 2000'];
|
|
}
|
|
|
|
// INTENT 2 - cf_dns_prompt (GUIDE doctrine 77)
|
|
if (preg_match('/(add|ajoute|cree|create).*dns.*track.*s95|dns.*record.*track.?s95/i', $msg)
|
|
&& !preg_match('/confirmed|valide/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_dns_prompt','cmd'=>'curl -s --max-time 10 "http://127.0.0.1:5890/api/wevia-track-s95-prompt-intent.php?type=cf_dns" 2>&1 | head -c 2000'];
|
|
}
|
|
|
|
// INTENT 3 - cf_dns_gated (WRITE strict)
|
|
if (preg_match('/(add|ajoute|cree).*dns.*track.*s95.*confirmed|dns.*track.?s95.*confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_dns_gated','cmd'=>'curl -s --max-time 20 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data "action=exec&cmd=sudo%20-n%20%2Fusr%2Flocal%2Fsbin%2Fwevads-cf-dns-add-track.sh" 2>&1 | head -c 1500'];
|
|
}
|
|
|
|
// INTENT 4 - cert_track_prompt (GUIDE)
|
|
if (preg_match('/cert.*track.*s95|letsencrypt.*track|certificat.*track.?s95/i', $msg)
|
|
&& !preg_match('/confirmed|valide/i', $msg)) {
|
|
$intents[] = ['id'=>'cert_track_prompt','cmd'=>'curl -s --max-time 10 "http://127.0.0.1:5890/api/wevia-track-s95-prompt-intent.php?type=cert" 2>&1 | head -c 2000'];
|
|
}
|
|
|
|
// INTENT 5 - cert_track_gated (WRITE strict)
|
|
if (preg_match('/cert.*track.*s95.*confirmed|letsencrypt.*track.?s95.*confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'cert_track_gated','cmd'=>'curl -s --max-time 60 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data "action=exec&cmd=sudo%20-n%20%2Fusr%2Flocal%2Fsbin%2Fwevads-track-s95-cert.sh" 2>&1 | head -c 2000'];
|
|
}
|
|
|
|
// INTENT 6 - vhost_track_prompt (GUIDE)
|
|
if (preg_match('/(deploy|deploye).*vhost.*track|vhost.*track.?s95/i', $msg)
|
|
&& !preg_match('/confirmed|valide/i', $msg)) {
|
|
$intents[] = ['id'=>'vhost_track_prompt','cmd'=>'curl -s --max-time 10 "http://127.0.0.1:5890/api/wevia-track-s95-prompt-intent.php?type=vhost" 2>&1 | head -c 2000'];
|
|
}
|
|
|
|
// INTENT 7 - vhost_track_gated (WRITE strict)
|
|
if (preg_match('/(deploy|deploye).*vhost.*track.*s95.*confirmed|vhost.*track.?s95.*confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'vhost_track_gated','cmd'=>'curl -s --max-time 30 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data "action=exec&cmd=sudo%20-n%20%2Fusr%2Flocal%2Fsbin%2Fwevads-track-s95-vhost.sh" 2>&1 | head -c 2000'];
|
|
}
|
|
|
|
// INTENT 8 - track_s95_rollback_gated (WRITE safety)
|
|
if (preg_match('/rollback.*track.*s95.*confirmed|track.?s95.*rollback.*confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'track_s95_rollback_gated','cmd'=>'curl -s --max-time 20 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data "action=exec&cmd=sudo%20-n%20%2Fusr%2Flocal%2Fsbin%2Fwevads-track-s95-rollback.sh" 2>&1 | head -c 2000'];
|
|
}
|
|
// === END V37 ===
|
|
|
|
// === CF-BYPASS V42 DRY-RUN + WATCHDOG (Opus wire 17avr) ===
|
|
// Cause racine: WRITE Phase 2 impact externe (CT logs + DNS public + nginx:443)
|
|
// Fix: mode toggle dry-run/prod + watchdog post-deploy
|
|
// Doctrine 74 + 77: tout via chat, mot magique pour prod switch
|
|
// GOLD pre-V42: /var/backups/gold_cf_bypass_v42_20260417_202501/
|
|
|
|
// INTENT V42-1 - cf_bypass_mode_show (READ)
|
|
if (preg_match('/mode.*cf.?bypass|cf.?bypass.*mode|mode.*actuel.*phase.?2|phase.?2.*mode|dry.?run.*status/i', $msg)
|
|
&& !preg_match('/confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_bypass_mode_show','cmd'=>'curl -s --max-time 5 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data "action=exec&cmd=cat%20%2Fopt%2Fwevads%2Fstate%2Fcf-bypass-mode.json" 2>&1 | head -c 800'];
|
|
$intents[] = ['id'=>'cf_bypass_health_show','cmd'=>'curl -s --max-time 5 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data "action=exec&cmd=cat%20%2Fopt%2Fwevads%2Fstate%2Fcf-bypass-health.json%202%3E%2Fdev%2Fnull%20%7C%7C%20echo%20HEALTH_NOT_YET_WRITTEN" 2>&1 | head -c 800'];
|
|
}
|
|
|
|
// INTENT V42-2 - cf_bypass_mode_dryrun_prompt (GUIDE D77)
|
|
if (preg_match('/(active|passe|switch|go).*dry.?run|dry.?run.*(mode|activate)|passer.*dry/i', $msg)
|
|
&& !preg_match('/confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_bypass_dryrun_prompt','cmd'=>'echo "PROMPT V42: Pour passer Phase 2 en mode DRY-RUN (scripts simulent sans impact externe), tape: \"mode dry-run confirmed\" dans le chat. Garde-fou: en dry-run aucun appel CF API, aucun certbot, aucun nginx. Safe."'];
|
|
}
|
|
|
|
// INTENT V42-3 - cf_bypass_mode_dryrun_gated (WRITE safe)
|
|
if (preg_match('/mode.*dry.?run.*confirmed|dry.?run.*confirmed.*mode/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_bypass_mode_dryrun_gated','cmd'=>'curl -s --max-time 10 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data-urlencode "action=exec" --data-urlencode "cmd=echo %27%7B%22mode%22%3A%22dry-run%22%2C%22updated_at%22%3A%22%27%24%28date%20-Iseconds%29%27%22%2C%22updated_by%22%3A%22wevia-chat%22%7D%27 | sudo tee /opt/wevads/state/cf-bypass-mode.json > /dev/null && cat /opt/wevads/state/cf-bypass-mode.json" 2>&1 | head -c 500'];
|
|
}
|
|
|
|
// INTENT V42-4 - cf_bypass_mode_prod_prompt (GUIDE D77 HEAVY WARNING)
|
|
if (preg_match('/(active|passe|switch|go).*prod.*cf.?bypass|cf.?bypass.*prod|go.*live.*cf.?bypass|phase.?2.*prod/i', $msg)
|
|
&& !preg_match('/confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_bypass_prod_prompt','cmd'=>'echo "PROMPT V42 HEAVY WARNING: Passer Phase 2 en PROD exposera track.s95.wevup.app en public internet. Impacts irreversibles: (1) DNS public wevup.app visible mondialement (2) Cert LE dans CT logs permanents (3) nginx:443 S95 expose sur 95.216.167.89. Watchdog actif cron 1min. Pour confirmer tape: \"go live cf bypass confirmed\""'];
|
|
}
|
|
|
|
// INTENT V42-5 - cf_bypass_mode_prod_gated (WRITE HEAVY)
|
|
if (preg_match('/go.*live.*cf.?bypass.*confirmed|cf.?bypass.*prod.*confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'cf_bypass_mode_prod_gated','cmd'=>'curl -s --max-time 10 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data-urlencode "action=exec" --data-urlencode "cmd=echo %27%7B%22mode%22%3A%22prod%22%2C%22updated_at%22%3A%22%27%24%28date%20-Iseconds%29%27%22%2C%22updated_by%22%3A%22wevia-chat%22%2C%22warning%22%3A%22impact%20externe%20actif%22%7D%27 | sudo tee /opt/wevads/state/cf-bypass-mode.json > /dev/null && cat /opt/wevads/state/cf-bypass-mode.json" 2>&1 | head -c 500'];
|
|
}
|
|
|
|
// INTENT V42-6 - track_watchdog_status (READ)
|
|
if (preg_match('/watchdog.*status|track.*watchdog|cf.?bypass.*health|healthcheck.*track/i', $msg)) {
|
|
$intents[] = ['id'=>'track_watchdog_status','cmd'=>'curl -s --max-time 5 "https://wevads.weval-consulting.com/api/sentinel-brain.php" --data-urlencode "action=exec" --data-urlencode "cmd=cat /opt/wevads/state/cf-bypass-health.json 2>/dev/null || echo NO_HEALTH_YET ; echo --- ; tail -5 /var/log/wevads-track-watchdog.log 2>/dev/null" 2>&1 | head -c 1500'];
|
|
}
|
|
// === END V42 ===
|
|
|
|
// === V46 AUTO-WIRE Opus joue Yacine: 4 gaps autonomie fixes - 17avr 21:00 ===
|
|
// Cause racine: phrases business reelles ne declenchaient aucun exec_result
|
|
// Gaps detectes: scan_history, chatbots_health, telegram, ethica_campaigns, ethica_nl, self_audit
|
|
// Append-only apres END V42
|
|
|
|
// INTENT V46-1 scan_history
|
|
if (preg_match('/scan.*histor|histor.*scan|pages.*scann|derni.*pages.*scan|liste.*pages.*scan/i', $msg)) {
|
|
$intents[] = ['id'=>'scan_history','cmd'=>'ls -lt /var/log/playwright*.log 2>/dev/null | head -5 ; echo --- ; ls -lt /opt/weval-nonreg/scan*.json 2>/dev/null | head -5 ; echo --- ; find /var/log -name "*scan*" -type f -mmin -1440 2>/dev/null | head -10'];
|
|
}
|
|
|
|
// INTENT V46-2 chatbots_health
|
|
if (preg_match('/chatbot|chatbots|verifie.*chat|test.*chat|6.*chatbot/i', $msg)) {
|
|
$intents[] = ['id'=>'chatbots_health','cmd'=>'for C in wevia-chat wedroid openclaw wevcode blade-ai arena; do printf "%s: " "$C"; curl -s -o /dev/null -w "%{http_code}" -m 3 "http://127.0.0.1/api/${C}.php" 2>/dev/null; echo; done'];
|
|
}
|
|
|
|
// INTENT V46-3 telegram_status (READ only, doctrine 69 pas de send auto)
|
|
if (preg_match('/telegram|telegramme|notifie|alerte.*watch|alert.*telegram/i', $msg)) {
|
|
$intents[] = ['id'=>'telegram_status','cmd'=>'echo bot_config=@wevia_cyber_bot chat_id=7605775322 doctrine69_no_auto_send; echo "To send manually: curl Bot API with valid token from vault"'];
|
|
if (!preg_match('/confirmed/i', $msg)) {
|
|
$intents[] = ['id'=>'telegram_send_prompt','cmd'=>'echo "PROMPT D77: Pour envoyer Telegram tape telegram send confirmed (doctrine 69 zero send auto)"'];
|
|
}
|
|
}
|
|
|
|
// INTENT V46-4 ethica_campaigns
|
|
if (preg_match('/campagne.*ethica|ethica.*campagne|combien.*campagne/i', $msg)) {
|
|
$intents[] = ['id'=>'ethica_campaigns','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -c "SELECT COUNT(*) FROM ethica.campaigns;" 2>/dev/null || echo ethica_campaigns_table_missing'];
|
|
}
|
|
|
|
// INTENT V46-5 ethica_nl_query
|
|
if (preg_match('/ethica.*pays|ethica.*maroc|ethica.*region|ethica.*specialite|hcp.*pays|hcp.*specialite/i', $msg)) {
|
|
$intents[] = ['id'=>'ethica_nl_query','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -c "SELECT country, COUNT(*) FROM ethica.medecins_real GROUP BY country ORDER BY 2 DESC LIMIT 10;" 2>/dev/null'];
|
|
}
|
|
|
|
// INTENT V46-6 self_audit_autonomy
|
|
if (preg_match('/self.*audit|audit.*autonom|gaps.*auto|wevia.*autonom/i', $msg)) {
|
|
$intents[] = ['id'=>'self_audit_autonomy','cmd'=>'echo AUTONOMY_AUDIT; echo logs_wevia=$(ls /var/log/wevia-*.log 2>/dev/null | wc -l); echo gold_backups=$(ls -d /var/backups/gold_cf_bypass_v* 2>/dev/null | wc -l); echo intents_in_orch=$(grep -c "intents\[\]" /var/www/html/api/wevia-sse-orchestrator.php); echo training_html=$(stat -c %s /var/www/html/wevia-training.html 2>/dev/null) bytes'];
|
|
}
|
|
|
|
// === END V46 ===
|
|
|
|
// === V47 AUTO-WIRE WEVADS business intents - 17avr 22:15 ===
|
|
// Cycle 1 Opus joue Yacine: 7 gaps identifies sur phrases WEVADS reelles
|
|
// Append-only apres END V46
|
|
|
|
// INTENT V47-1 offers_list - manquait pour "liste offres actives avec payout"
|
|
if (preg_match('/offres?.*active|liste.*offre|offre.*payout|offre.*cx3|offre.*doublem/i', $msg)) {
|
|
$intents[] = ['id'=>'offers_list','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT id, name, network, payout_amount FROM affiliate.offers WHERE status=\"active\" LIMIT 10;" 2>/dev/null || echo offers_table_check_needed'];
|
|
}
|
|
|
|
// INTENT V47-2 warmup_count - manquait pour "combien warmup accounts"
|
|
if (preg_match('/warmup|warming|accounts?.*warm/i', $msg)) {
|
|
$intents[] = ['id'=>'warmup_count','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -c "SELECT COUNT(*) as total, SUM(daily_cap_current) as cap FROM warmup_accounts;" 2>/dev/null || echo warmup_table_check_needed'];
|
|
}
|
|
|
|
// INTENT V47-3 tracking_stats - opens/clicks 24h
|
|
if (preg_match('/open.*click|click.*open|tracking.*stat|stats.*24h|opens?.*24|clicks?.*24/i', $msg)) {
|
|
$intents[] = ['id'=>'tracking_stats','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT COUNT(*) FILTER (WHERE event_type=\"open\") as opens, COUNT(*) FILTER (WHERE event_type=\"click\") as clicks FROM tracking_events WHERE created_at > NOW() - INTERVAL \"24 hours\";" 2>/dev/null || echo tracking_events_query_needed'];
|
|
}
|
|
|
|
// INTENT V47-4 seeds_count - seeds par ISP
|
|
if (preg_match('/seed|semence|isp.*seed|seed.*isp/i', $msg)) {
|
|
$intents[] = ['id'=>'seeds_count','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT isp, COUNT(*) FROM seed_accounts WHERE is_active=true GROUP BY isp ORDER BY 2 DESC LIMIT 10;" 2>/dev/null || echo seed_accounts_query_needed'];
|
|
}
|
|
|
|
// INTENT V47-5 sponsors_list
|
|
if (preg_match('/sponsor|affiliate.*network|cx3.*doublem|network.*active/i', $msg)) {
|
|
$intents[] = ['id'=>'sponsors_list','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT name, status, network_type FROM sponsors LIMIT 10;" 2>/dev/null || echo sponsors_table_check_needed'];
|
|
}
|
|
|
|
// INTENT V47-6 brain_winners - 9 SACRED winners
|
|
if (preg_match('/brain.*winner|winner.*brain|sacred.*winner|9.*sacred|brain.*sacred|brain.*config/i', $msg)) {
|
|
$intents[] = ['id'=>'brain_winners','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT id, name, is_winner, is_sacred FROM brain_configs WHERE is_winner=true LIMIT 15;" 2>/dev/null || echo brain_configs_query_needed'];
|
|
}
|
|
|
|
// INTENT V47-7 pmta_vmtas
|
|
if (preg_match('/pmta|vmta|powermta|smtp.*source/i', $msg)) {
|
|
$intents[] = ['id'=>'pmta_vmtas','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT id, vmta_name, ip_address, is_installed FROM vmtas WHERE is_installed=true LIMIT 10;" 2>/dev/null || echo vmtas_table_check_needed'];
|
|
}
|
|
|
|
// INTENT V47-8 wevads_business_report - synthese multi-KPI
|
|
if (preg_match('/rapport.*business.*wevads|rapport.*wevads|wevads.*rapport|report.*wevads|bilan.*wevads/i', $msg)) {
|
|
$intents[] = ['id'=>'wevads_business_report','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT (SELECT COUNT(*) FROM warmup_accounts) as warmup, (SELECT COUNT(*) FROM seed_accounts WHERE is_active=true) as seeds, (SELECT COUNT(*) FROM affiliate.offers WHERE status=\"active\") as offers_active, (SELECT COUNT(*) FROM brain_configs WHERE is_winner=true) as winners;" 2>/dev/null || echo business_report_needs_tables'];
|
|
}
|
|
|
|
// INTENT V47-9 ethica_nl_query_ext - elargir pour phrases sans "pays"
|
|
if (preg_match('/hcp.*maroc|hcp.*algerie|hcp.*tunisie|maroc.*algerie|hcp.*egypte|hcp.*afrique/i', $msg)) {
|
|
$intents[] = ['id'=>'ethica_nl_query','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT country, COUNT(*) FROM ethica.medecins_real GROUP BY country ORDER BY 2 DESC LIMIT 10;" 2>/dev/null'];
|
|
}
|
|
|
|
// === END V47 ===
|
|
|
|
// === V48 AUTO-WIRE Partenariats strategiques Vistex/Huawei/Arrow/Ethica-Consent - 17avr 22:27 ===
|
|
// Cycle 3 Opus joue Yacine: 6 gaps stratégiques
|
|
// State files /opt/wevads/state/partnerships/{vistex,huawei,arrow,consent}.json
|
|
// Append-only apres END V47
|
|
|
|
// INTENT V48-1 vistex_status - partenariat Vistex global
|
|
if (preg_match('/vistex.*status|status.*vistex|partenariat.*vistex|vistex.*partenariat|vistex.*state/i', $msg)) {
|
|
$intents[] = ['id'=>'vistex_status','cmd'=>'cat /opt/wevads/state/partnerships/vistex.json 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);print(f\"Status: {d[\"status\"]}\");print(f\"Contacts: {\", \".join(d[\"contacts\"])}\");print(f\"Revenue: {d[\"revenue_potential\"]}\");print(\"Pending:\");[print(f\" - {p[\"item\"]} ({p[\"status\"]}) owner={p[\"owner\"]}\") for p in d[\"pending_items\"]]" 2>/dev/null || echo vistex_state_missing'];
|
|
}
|
|
|
|
// INTENT V48-2 vistex_lead_registration
|
|
if (preg_match('/vistex.*lead|lead.*registration|lead.*protection|addendum.*vistex|vistex.*addendum/i', $msg)) {
|
|
$intents[] = ['id'=>'vistex_lead_registration','cmd'=>'cat /opt/wevads/state/partnerships/vistex.json 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);items=[p for p in d[\"pending_items\"] if \"lead\" in p[\"item\"].lower() or \"addendum\" in p[\"item\"].lower() or \"portal\" in p[\"item\"].lower()];[print(f\"{p[\"item\"]}: {p[\"status\"]} owner={p[\"owner\"]}\") for p in items]" 2>/dev/null || echo vistex_state_missing'];
|
|
}
|
|
|
|
// INTENT V48-3 huawei_quota - quota ECS/EIP
|
|
if (preg_match('/huawei.*quota|quota.*huawei|quota.*ecs|ecs.*huawei|eip.*huawei|huawei.*infra/i', $msg)) {
|
|
$intents[] = ['id'=>'huawei_quota','cmd'=>'cat /opt/wevads/state/partnerships/huawei.json 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);i=d[\"infrastructure\"];print(f\"Region: {i[\"region_primary\"]}\");print(f\"ECS quota: {i[\"ecs_quota_current\"]} (requested {i[\"ecs_quota_requested\"]})\");print(f\"EIP quota: {i[\"eip_quota\"]}\");print(f\"Active instances: {\", \".join(i[\"active_instances\"])}\")" 2>/dev/null || echo huawei_state_missing'];
|
|
}
|
|
|
|
// INTENT V48-4 huawei_billing
|
|
if (preg_match('/dispute.*billing|billing.*dispute|huawei.*facture|huawei.*billing|billing.*huawei/i', $msg)) {
|
|
$intents[] = ['id'=>'huawei_billing','cmd'=>'cat /opt/wevads/state/partnerships/huawei.json 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);items=[p for p in d[\"pending_items\"] if \"billing\" in p[\"item\"].lower()];[print(f\"{p[\"item\"]}: status={p[\"status\"]} amount={p.get(\"amount\",\"N/A\")}\") for p in items]" 2>/dev/null || echo huawei_state_missing'];
|
|
}
|
|
|
|
// INTENT V48-5 arrow_scaleway
|
|
if (preg_match('/arrow|scaleway|arrow.*scaleway|scaleway.*arrow|credits.*arrow|credits.*scaleway/i', $msg)) {
|
|
$intents[] = ['id'=>'arrow_scaleway','cmd'=>'cat /opt/wevads/state/partnerships/arrow.json 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);print(f\"Partner: {d[\"partner\"]}\");print(f\"Status: {d[\"status\"]}\");print(f\"Contacts: {\", \".join(d[\"contacts\"])}\");print(f\"Server: {d[\"infrastructure\"][\"primary_server\"]} ({d[\"infrastructure\"][\"specs\"]})\");print(f\"Credits remaining: {d[\"credits\"][\"remaining\"]}\")" 2>/dev/null || echo arrow_state_missing'];
|
|
}
|
|
|
|
// INTENT V48-6 consent_health - consent.wevup.app health
|
|
if (preg_match('/consent.*wevup|consent.*ethica|consent.*health|gdpr.*ethica|ethica.*consent/i', $msg)) {
|
|
$intents[] = ['id'=>'consent_health','cmd'=>'HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 https://consent.wevup.app/healthz 2>/dev/null); cat /opt/wevads/state/partnerships/consent.json 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);print(f\"Service: {d[\"service\"]}\");print(f\"Purpose: {d[\"purpose\"]}\");print(f\"HCP volume: {d[\"hcp_volume\"]:,}\");print(f\"Compliance: {\", \".join(d[\"compliance\"])}\")" ; echo "HTTP status: $HTTP_CODE"'];
|
|
}
|
|
|
|
// INTENT V48-7 partnerships_overview - bilan global tous partenaires
|
|
if (preg_match('/partenaires?.*tous|bilan.*partenariat|overview.*partner|status.*partenariat|vue.*partenaire/i', $msg)) {
|
|
$intents[] = ['id'=>'partnerships_overview','cmd'=>'for F in vistex huawei arrow consent; do cat /opt/wevads/state/partnerships/$F.json 2>/dev/null | python3 -c "import sys,json;d=json.load(sys.stdin);name=d.get(\"partner\",d.get(\"service\",\"?\"));st=d.get(\"status\",\"?\");print(f\"{name}: {st}\")" 2>/dev/null; done'];
|
|
}
|
|
|
|
// === END V48 ===
|
|
|
|
// === V53 AUTO-WIRE Cycle 4 Ops/Monitoring - 17avr 22:55 ===
|
|
// Gaps: arsenal_monitor, deliverability_stats, o365_stats, nginx_vhosts, redis_status
|
|
// Append-only apres END V48 (zero touch V37-V48)
|
|
|
|
// INTENT V53-1 arsenal_monitor - ecrans /var/www/html/*.html
|
|
if (preg_match('/arsenal.*monitor|arsenal.*screen|arsenal.*ecran|arsenal.*page|150.*screen|combien.*ecran/i', $msg)) {
|
|
$intents[] = ['id'=>'arsenal_monitor','cmd'=>'echo total_html=$(ls /var/www/html/*.html 2>/dev/null | wc -l) ; echo wevia_pages=$(ls /var/www/html/wevia*.html 2>/dev/null | wc -l) ; echo ethica_pages=$(ls /var/www/html/ethica*.html 2>/dev/null | wc -l) ; echo wevads_pages=$(ls /var/www/html/wevads*.html 2>/dev/null | wc -l) ; echo admin_pages=$(ls /var/www/html/admin*.html 2>/dev/null | wc -l)'];
|
|
}
|
|
|
|
// INTENT V53-2 deliverability_stats - taux inbox O365 PMTA
|
|
if (preg_match('/taux.*deliverability|deliverability.*rate|inbox.*rate|taux.*inbox|97.*pourcent|deliverability.*97/i', $msg)) {
|
|
$intents[] = ['id'=>'deliverability_stats','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT COUNT(*) FILTER (WHERE inbox_status=\"inbox\") as inbox, COUNT(*) FILTER (WHERE inbox_status=\"spam\") as spam, COUNT(*) as total FROM seed_inbox_checks WHERE created_at > NOW() - INTERVAL \"24 hours\";" 2>/dev/null || echo deliverability_table_tracking_needed'];
|
|
}
|
|
|
|
// INTENT V53-3 o365_stats
|
|
if (preg_match('/o365|office365|office.365|oauth.*o365|tenant.*o365|microsoft.*graph|graph.*api|288.*domain/i', $msg)) {
|
|
$intents[] = ['id'=>'o365_stats','cmd'=>'PGPASSWORD=admin123 psql -h 10.1.0.3 -U admin -d adx_system -t -A -F "|" -c "SELECT (SELECT COUNT(*) FROM o365_accounts) as total_accounts, (SELECT COUNT(*) FROM o365_accounts WHERE is_active=true) as active, (SELECT COUNT(DISTINCT tenant_id) FROM o365_accounts) as tenants;" 2>/dev/null || echo o365_tables_check_needed'];
|
|
}
|
|
|
|
// INTENT V53-4 nginx_vhosts
|
|
if (preg_match('/nginx.*vhost|vhost.*nginx|nginx.*config|nginx.*site|sites.*enabled|nginx.*list/i', $msg)) {
|
|
$intents[] = ['id'=>'nginx_vhosts','cmd'=>'ls /etc/nginx/sites-enabled/ 2>/dev/null | wc -l | xargs -I{} echo total_vhosts={}; ls /etc/nginx/sites-enabled/ 2>/dev/null | head -20'];
|
|
}
|
|
|
|
// INTENT V53-5 redis_status
|
|
if (preg_match('/redis.*status|redis.*cache|redis.*running|cache.*redis|redis.*check/i', $msg)) {
|
|
$intents[] = ['id'=>'redis_status','cmd'=>'systemctl is-active redis-server 2>/dev/null || systemctl is-active redis 2>/dev/null || echo redis_check_needed ; redis-cli ping 2>/dev/null || echo redis_cli_unavailable'];
|
|
}
|
|
|
|
// === END V53 ===
|
|
|
|
// === V56 Cycle 6 Opus joue Yacine multiagent - 17avr 23:20 ===
|
|
// Gaps: dormants_overview (wrong intent ports_full fire), multi-intent partnerships missing
|
|
// Append-only apres END V53
|
|
|
|
// INTENT V56-1 dormants_overview - list hubs/priority/archived from auto-intent API
|
|
if (preg_match('/hubs?.*dormant|dormant.*hub|hub.*importan|combien.*hub|audit.*hub|liste.*hub/iu', $msg)) {
|
|
$intents[] = ['id'=>'dormants_overview','cmd'=>'echo TOTAL_HUBS=$(ls /var/www/html/*hub*.html 2>/dev/null | grep -v pre-carto | wc -l) ; echo TOTAL_PRIORITY=$(python3 -c "import json;print(len(json.load(open(\"/opt/wevia-brain/priority-intents-nl.json\"))))" 2>/dev/null) ; echo TOTAL_ARCHIVED=$(ls /opt/weval-l99/wiki/_var_www_html_api_wevia-*-intent*.json 2>/dev/null | wc -l) ; echo === TOP 15 HUBS === ; ls /var/www/html/*hub*.html 2>/dev/null | grep -v pre-carto | head -15 | xargs -I{} basename {}'];
|
|
}
|
|
|
|
// INTENT V56-2 partnerships_full_detail - enrich partnerships_overview with deep state read
|
|
if (preg_match('/partenariat.*complet|partnership.*full|bilan.*partenariat|vistex.*huawei|huawei.*arrow|arrow.*scaleway|tous.*partenaire/iu', $msg)) {
|
|
$intents[] = ['id'=>'partnerships_full_detail','cmd'=>'for P in vistex huawei arrow consent; do F=/opt/wevads/state/partnerships/$P.json ; if [ -f "$F" ]; then echo === $P === ; python3 -c "import json;d=json.load(open(\"$F\"));print(f\"status={d.get(\\\"status\\\",\\\"?\\\")}\");contacts=d.get(\"contacts\",[]);[print(f\" contact: {c.get(\\\"name\\\")} {c.get(\\\"role\\\")} {c.get(\\\"email\\\")}\") for c in contacts[:3]];pending=d.get(\"pending\",[]);[print(f\" pending: {p}\") for p in pending[:3]]" 2>&1 ; fi; done'];
|
|
}
|
|
|
|
// === END V56 ===
|
|
|
|
|
|
// === V61 Tier1+RAG intents include (Opus 18avr) ===
|
|
@include_once __DIR__ . '/wevia-v61-intents-include.php';
|
|
// === END V61 ===
|
|
|
|
// === V62 WIRE Intents include (Opus 18avr) ===
|
|
@include_once __DIR__ . '/wevia-v62-intents-include.php';
|
|
include __DIR__ . '/wevia-v72-intents-include.php';
|
|
include __DIR__ . '/wevia-v73-intents-include.php';
|
|
include __DIR__ . '/wevia-v74-intents-include.php';
|
|
include __DIR__ . '/wevia-v75-intents-include.php';
|
|
// === END V62 ===
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// EXECUTE detected intents
|
|
if (!empty($intents)) {
|
|
sse(['type'=>'executor','status'=>'start','intents'=>count($intents)]);
|
|
foreach ($intents as $intent) {
|
|
$out = trim(@shell_exec('timeout 20 bash -c ' . escapeshellarg($intent['cmd']) . ' 2>&1')) ?: 'EMPTY';
|
|
$exec_results[$intent['id']] = $out;
|
|
sse(['type'=>'exec_result','id'=>$intent['id'],'result'=>substr($out, 0, 2000)]);
|
|
}
|
|
sse(['type'=>'executor','status'=>'done','executed'=>count($exec_results)]);
|
|
}
|
|
// === END EXECUTOR ===
|
|
|
|
// === V38 UX-PRIORITY: promouvoir exec_result V37 en tete (Opus wire 17avr) ===
|
|
// Cause racine: user non-tech pose "phase 2 status" -> LLM synthesis dilue l'info.
|
|
// Fix: si un intent V37/phase2 a execute, envoyer un event SSE "phase2_priority"
|
|
// AVANT le llm_synthesis pour que l'UI l'affiche en premier.
|
|
$v37_intents_fired = array_intersect_key($exec_results, array_flip([
|
|
'track_s95_status', 'cf_dns_prompt', 'cf_dns_gated',
|
|
'cert_track_prompt', 'cert_track_gated',
|
|
'vhost_track_prompt', 'vhost_track_gated',
|
|
'track_s95_rollback_gated'
|
|
]));
|
|
if (!empty($v37_intents_fired)) {
|
|
foreach ($v37_intents_fired as $iid => $ires) {
|
|
// Parser le JSON du sidecar si applicable
|
|
$parsed = @json_decode($ires, true);
|
|
if ($parsed && is_array($parsed)) {
|
|
sse(['type'=>'phase2_priority','intent'=>$iid,'ux_guide'=>$parsed]);
|
|
} else {
|
|
sse(['type'=>'phase2_priority','intent'=>$iid,'raw'=>substr($ires, 0, 1500)]);
|
|
}
|
|
}
|
|
}
|
|
// === END V38 ===
|
|
|
|
|
|
|
|
// === LLM SYNTHESIS (enhanced with execution results) ===
|
|
$ctx = "AGENTS WEVIA:\n";
|
|
foreach($results as $id=>$r) $ctx .= "[$id] $r\n";
|
|
if (!empty($exec_results)) {
|
|
$ctx .= "\n=== RESULTATS EXECUTION ===\n";
|
|
foreach($exec_results as $id=>$r) $ctx .= "[$id] " . substr($r, 0, 800) . "\n";
|
|
}
|
|
$sp = $ctx . "\n---\nQUESTION: " . $msg . "\nINSTRUCTION: resume FACTUELLEMENT les resultats ci-dessus sans inventer. Liste OBSERVE (chiffres), PROBLEMES DETECTES (si TIMEOUT/DIRTY>0/port-conflit), AUCUNE correction n a ete appliquee sauf si un intent fix_* apparait. Francais concis.";
|
|
$ch = curl_init("http://127.0.0.1:4000/v1/chat/completions");
|
|
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_HTTPHEADER => ["Content-Type: application/json"], CURLOPT_POSTFIELDS => json_encode(["messages" => [["role"=>"system","content"=>"Tu es WEVIA Master. REGLES STRICTES HONNETETE DOCTRINE #4: (1) Decris UNIQUEMENT les resultats bruts des agents/exec fournis en contexte. (2) N INVENTE RIEN. (3) Si un probleme est detecte (ex: port conflits, DIRTY>0, TIMEOUT), liste-le comme PROBLEME A CORRIGER, JAMAIS comme deja corrige. (4) Ne dis JAMAIS corrections appliquees / resolu / fixed sauf si un intent explicite de type fix a tourne. (5) Les commandes de lecture (ls, cat, count, check, grep) sont READ-ONLY, tu n as rien corrige. (6) Si resultat vide ou TIMEOUT, dis-le. Format: bullets courts, chiffres exacts, francais."],["role"=>"user","content"=>$sp]], "max_tokens" => 600, "stream" => false]), CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30]);
|
|
$r2 = curl_exec($ch); curl_close($ch);
|
|
$d2 = @json_decode($r2, true);
|
|
$txt = $d2["choices"][0]["message"]["content"] ?? "Synthese indisponible.";
|
|
sse(["type"=>"llm_synthesis","text"=>$txt]);
|
|
|