1032 lines
67 KiB
PHP
1032 lines
67 KiB
PHP
<?php
|
||
@require_once '/opt/wevia-brain/plugin-intents.php';
|
||
/* WEVIA OPUS-WIRED INTENTS — fired AFTER fast-path-v3 returns null
|
||
Rebuilt 16AVR 16:35 — 16 intents
|
||
*/
|
||
function wevia_opus_intents($msg) {
|
||
$m = mb_strtolower(trim($msg));
|
||
$r = null;
|
||
|
||
// PLUGIN STORE AUTODISCOVERY (priority highest after init)
|
||
if (function_exists('wevia_plugin_intents')) {
|
||
$plugin_result = wevia_plugin_intents($msg);
|
||
if ($plugin_result !== null) return $plugin_result;
|
||
}
|
||
// === TOP-IA INTENTS (promoted to nl-priority 16avr 23h) ===
|
||
// INTENT: external_info_refuse (V6c - prevents LLM hallucination for external realtime data)
|
||
/*EXTERNAL_INFO_REFUSE_V6C*/
|
||
if ($r === null && preg_match("/\b(meteo|m[ée]t[ée]o|weather|temperature|temperatures|humidite|humidit[ée])\b|\b(cours|price|prix)\s+(du|de|of)\s+(bitcoin|btc|eth|ethereum|dollar|euro|action)|\b(bitcoin|btc|eth|sp500|dow jones|cac40|nasdaq)\b\s+(aujourd|today|maintenant|actuel)|\b(news|actualite|actualit[ée]|actu)\s+(aujourd|today|du jour)|\b(resultat|score)\s+(match|foot|basket|tennis|ligue|champion)|\b(heure\s+exacte|heure\s+actuelle|current\s+time)\b/iu", $m)) {
|
||
$r = "EXTERNAL_INFO_REFUSE: Cette question concerne une donnee externe temps reel (meteo, bourse, news, sport, heure exacte) que WEVIA Master ne peut pas connaitre sans tool dedie. Repondre: 'Je n ai pas acces a cette information en temps reel. Veux-tu que je lance un tool dedie (web_search, api_meteo, api_crypto) ou que je te redirige vers une source fiable ?' - JAMAIS inventer chiffre, temperature, prix, date, nom.";
|
||
}
|
||
|
||
// INTENT: smart_client_help (V84 - pre-empts office/github to route via v83 orchestrator)
|
||
/*SMART_CLIENT_HELP_V84*/
|
||
if ($r === null && preg_match("/\b(un client|aide[- ]moi|help me|pour un client|client me demande|me demande comment)\b|\b(comment\s+(renouvel|reactiv|creer))/iu", $m)) {
|
||
$q = rawurlencode(substr($msg, 0, 200));
|
||
$api_r = @shell_exec("curl -sk --max-time 10 'http://127.0.0.1/api/wevia-v83-multi-agent-orchestrator.php?action=match&q=" . escapeshellarg($q) . "' -H 'Host: weval-consulting.com' 2>/dev/null");
|
||
if ($api_r) {
|
||
$j = @json_decode($api_r, true);
|
||
if ($j && !empty($j['ok'])) {
|
||
$out = "V84 SMART ORCHESTRATE MATCH (v83 orchestrator):\n";
|
||
$out .= "Query: " . ($j['query'] ?? '') . "\n";
|
||
$mc = $j['match_count'] ?? [];
|
||
$out .= "Match count: agents=" . ($mc['agents'] ?? 0) . " resolvers=" . ($mc['resolvers'] ?? 0) . " blade_tasks=" . ($mc['blade_tasks'] ?? 0) . " brain_prompts=" . ($mc['brain_prompts'] ?? 0) . "\n";
|
||
$resolvers = $j['matches']['resolvers'] ?? [];
|
||
if ($resolvers) {
|
||
$out .= "Top resolvers: ";
|
||
$tops = array_slice($resolvers, 0, 5);
|
||
foreach ($tops as $t) { $out .= ($t['id'] ?? '?') . " "; }
|
||
$out .= "\n";
|
||
}
|
||
$blade = $j['matches']['blade_tasks'] ?? [];
|
||
if ($blade) {
|
||
$out .= "Top blade tasks: ";
|
||
foreach (array_slice($blade, 0, 5) as $t) { $out .= ($t['task'] ?? '?') . " "; }
|
||
$out .= "\n";
|
||
}
|
||
$agents = $j['matches']['agents'] ?? [];
|
||
if ($agents) {
|
||
$out .= "Top agents: ";
|
||
foreach (array_slice($agents, 0, 5) as $t) { $out .= (is_array($t) ? ($t['name'] ?? $t['id'] ?? '?') : $t) . " "; }
|
||
$out .= "\n";
|
||
}
|
||
$out .= "Strategy: " . ($j['strategy'] ?? '') . "\n";
|
||
$r = $out;
|
||
}
|
||
}
|
||
}
|
||
|
||
// INTENT: top_ia_memory_store
|
||
if ($r === null && preg_match("/memorise\\s+(ceci|ca|cela|que)|store\\s+memory|retiens\\s+(que|ceci|ca)|souviens\\s+toi\\s+(que|de)/iu", $m)) {
|
||
$text = preg_replace("/^(memorise|store memory|retiens|souviens toi)\\s*(ceci|ca|cela|que|toi que|toi de)?\\s*:?\\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($text));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/memory_store.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA MEMORY STORE:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_memory_recall
|
||
if ($r === null && preg_match("/recall\\s+memory|retrouve\\s+(souvenir|memoire)|cherche\\s+dans\\s+(memoire|souvenirs)|what\\s+did\\s+you\\s+store/iu", $m)) {
|
||
$q = preg_replace("/^(recall memory|retrouve souvenir|retrouve memoire|cherche dans memoire|cherche dans souvenirs|what did you store)\\s*:?\\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q) ?: "test");
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/memory_recall.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA MEMORY RECALL:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_deep_search
|
||
if ($r === null && preg_match("/deep\\s+search|recherche\\s+approfondie|searxng\\s+search|pro\\s+search/iu", $m)) {
|
||
$q = preg_replace("/^(deep search|recherche approfondie|searxng search|pro search)\\s*:?\\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q) ?: "test");
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/deep_search.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA DEEP SEARCH:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_consensus
|
||
if ($r === null && preg_match("/consensus\\s+(ia|ai|providers|triple)|triple\\s+(providers|vote)|self\\s+consistency|vote\\s+majoritaire/iu", $m)) {
|
||
$q = preg_replace("/^(consensus ia|consensus ai|consensus providers|consensus triple|triple providers|triple vote|self consistency|vote majoritaire)\\s*:?\\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q) ?: "test question");
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/self_consistency.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA CONSENSUS (Groq+Cerebras+NVIDIA):\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_vision
|
||
if ($r === null && preg_match("/vision\\s+(gemini|analyse\\s+image)|analyse\\s+cette\\s+image|decris\\s+(cette\\s+)?image|gemini\\s+vision/iu", $m)) {
|
||
if (preg_match("/https?:\\/\\/\\S+\\.(jpg|jpeg|png|webp|gif)/i", $msg, $mm)) {
|
||
$url = $mm[0];
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/vision_analyze.sh " . escapeshellarg($url) . " 2>&1"));
|
||
$r = "TOP-IA VISION (Gemini 2.0):\nURL: {$url}\n{$out}";
|
||
} else {
|
||
$r = "TOP-IA VISION: Fournir URL image (.jpg/.png/.webp). Ex: 'analyse cette image https://...'";
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// INTENT: top_ia_sentiment
|
||
if ($r === null && preg_match("/sentiment\s+(de|du|analyse)|detect\s+sentiment|emotion\s+du\s+message|humeur/iu", $m)) {
|
||
$text = preg_replace("/^(sentiment\s+(de|du|analyse)|detect\s+sentiment|emotion\s+du\s+message|humeur)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($text) ?: "test");
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/sentiment.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA SENTIMENT:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_reflect
|
||
if ($r === null && preg_match("/auto\s+critique|self\s+reflect|reflechis\s+sur|score\s+ma\s+reponse|evalue\s+(ma|la)\s+reponse/iu", $m)) {
|
||
$text = preg_replace("/^(auto\s+critique|self\s+reflect|reflechis\s+sur|score\s+ma\s+reponse|evalue\s+(ma|la)\s+reponse)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($text));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/self_reflect.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA SELF-REFLECT:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_procedural
|
||
if ($r === null && preg_match("/memorise\s+procedure|routine\s+enregistrer|workflow\s+memoriser|sequence\s+actions/iu", $m)) {
|
||
$text = preg_replace("/^(memorise\s+procedure|routine\s+enregistrer|workflow\s+memoriser|sequence\s+actions)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($text));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/procedural_remember.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA PROCEDURAL MEMORY:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_autoscale
|
||
if ($r === null && preg_match("/auto\s?scale|recommande\s+fpm|recommandation\s+workers|fpm\s+recommend/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/auto_scale_fpm.sh 2>&1"));
|
||
$r = "TOP-IA AUTO-SCALE FPM:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_proactive
|
||
if ($r === null && preg_match("/scan\s+proactif|detect\s+anomalies|proactive\s+scan|anomalie\s+systeme|health\s+check\s+proactif/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/proactive_scan.sh 2>&1"));
|
||
$r = "TOP-IA PROACTIVE SCAN:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_ocr
|
||
if ($r === null && preg_match("/ocr\s+image|extract\s+text\s+image|tesseract|texte\s+dans\s+image/iu", $m)) {
|
||
if (preg_match("/https?:\\/\\/\\S+/i", $msg, $mm)) {
|
||
$url = $mm[0];
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/ocr_image.sh " . escapeshellarg($url) . " 2>&1"));
|
||
$r = "TOP-IA OCR:\n{$out}";
|
||
} else {
|
||
$r = "TOP-IA OCR: Fournir URL image dans le message.";
|
||
}
|
||
}
|
||
|
||
// INTENT: top_ia_tts
|
||
if ($r === null && preg_match("/synthetise\s+(vocal|voix)|genere\s+audio|tts\s+ceci|text\s+to\s+speech|dis\s+ceci\s+en\s+audio/iu", $m)) {
|
||
$text = preg_replace("/^(synthetise\s+(vocal|voix)|genere\s+audio|tts\s+ceci|text\s+to\s+speech|dis\s+ceci\s+en\s+audio)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($text) ?: "Bonjour");
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/audio_synthesize.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA TTS:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_stt
|
||
if ($r === null && preg_match("/transcris\s+audio|speech\s+to\s+text|whisper\s+transcribe|transcription\s+audio/iu", $m)) {
|
||
if (preg_match("/https?:\\/\\/\\S+\\.(mp3|wav|ogg|m4a|flac|webm)/i", $msg, $mm)) {
|
||
$url = $mm[0];
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/audio_transcribe.sh " . escapeshellarg($url) . " 2>&1"));
|
||
$r = "TOP-IA STT:\n{$out}";
|
||
} else {
|
||
$r = "TOP-IA STT: Fournir URL audio (.mp3/.wav/.ogg/.m4a/.flac/.webm).";
|
||
}
|
||
}
|
||
|
||
// INTENT: top_ia_audit
|
||
if ($r === null && preg_match("/audit\s+(log|trail|entry)|log\s+audit|enregistre\s+action/iu", $m)) {
|
||
$text = preg_replace("/^(audit\s+(log|trail|entry)|log\s+audit|enregistre\s+action)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($text));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/audit_log.sh 'yacine' 'chat_action' " . $esc . " '{}' 2>&1"));
|
||
$r = "TOP-IA AUDIT LOG:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_audit_query
|
||
if ($r === null && preg_match("/audit\s+query|cherche\s+audit|recherche\s+audit|consulte\s+audit|who\s+did/iu", $m)) {
|
||
$q = preg_replace("/^(audit\s+query|cherche\s+audit|recherche\s+audit|consulte\s+audit|who\s+did)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/audit_query.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA AUDIT QUERY:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_rgpd_forget
|
||
if ($r === null && preg_match("/rgpd\s+oubli|droit\s+oubli|forget\s+(me|user|data)|supprime\s+(mes|les)\s+donnees|purge\s+data/iu", $m)) {
|
||
$id = preg_replace("/^(rgpd\s+oubli|droit\s+oubli|forget\s+(me|user|data)|supprime\s+(mes|les)\s+donnees|purge\s+data)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($id));
|
||
// ALWAYS dry-run from chat for safety
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/rgpd_forget.sh {$esc} --dry-run 2>&1"));
|
||
$r = "TOP-IA RGPD FORGET (dry-run par sécurité):\n{$out}\n\nPour exécuter vraiment: cli directe.";
|
||
}
|
||
|
||
// INTENT: top_ia_few_shot
|
||
if ($r === null && preg_match("/few\s?shot|exemples\s+similaires|trouve\s+exemples|similar\s+examples/iu", $m)) {
|
||
$q = preg_replace("/^(few\s?shot|exemples\s+similaires|trouve\s+exemples|similar\s+examples)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/few_shot.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA FEW-SHOT:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_dialectical
|
||
if ($r === null && preg_match("/dialectique|pro\s+contre|contradictoire|debate|raisonnement\s+contradictoire|dialectical/iu", $m)) {
|
||
$q = preg_replace("/^(dialectique|pro\s+contre|contradictoire|debate|raisonnement\s+contradictoire|dialectical)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/dialectical.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA DIALECTICAL (Pro/Contre/Arbitre):\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_webhook
|
||
if ($r === null && preg_match("/webhook\s+send|send\s+webhook|envoie\s+webhook|trigger\s+webhook/iu", $m)) {
|
||
if (preg_match("/https?:\\/\\/\\S+/i", $msg, $mm)) {
|
||
$url = $mm[0];
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/webhook_send.sh " . escapeshellarg($url) . " 'chat_trigger' '{\"from\":\"wevia-chat\"}' 2>&1"));
|
||
$r = "TOP-IA WEBHOOK:\n{$out}";
|
||
} else {
|
||
$r = "TOP-IA WEBHOOK: Fournir URL dans le message.";
|
||
}
|
||
}
|
||
|
||
// INTENT: top_ia_quotas
|
||
if ($r === null && preg_match("/gpu\s+(quota|status)|providers\s+status|api\s+quotas|monitoring\s+providers/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/gpu_quotas.sh 2>&1"));
|
||
$r = "TOP-IA GPU/API QUOTAS:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_cot_tree
|
||
if ($r === null && preg_match("/arbre\s+de\s+pensee|tree\s+of\s+thought|cot\s+tree|raisonnement\s+3\s+branches|multi\s+angle/iu", $m)) {
|
||
$q = preg_replace("/^(arbre\s+de\s+pensee|tree\s+of\s+thought|cot\s+tree|raisonnement\s+3\s+branches|multi\s+angle)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/cot_tree.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA CoT TREE (3 branches + synthesis):\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_prefix_cache
|
||
if ($r === null && preg_match("/prefix\s+cache|cache\s+redis\s+prompt|redis\s+stats\s+prefix/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/prefix_cache.sh stats 2>&1"));
|
||
$r = "TOP-IA PREFIX CACHE REDIS:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_image_gen
|
||
if ($r === null && preg_match("/gen[eè]re\s+(une\s+)?image|genere\s+img|image\s+sdxl|flux\s+image|generate\s+image/iu", $m)) {
|
||
$prompt = preg_replace("/^(gen[eè]re\s+(une\s+)?image|genere\s+img|image\s+sdxl|flux\s+image|generate\s+image)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($prompt) ?: "abstract art");
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/sdxl_generate.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA IMAGE GEN (Pollinations FLUX):\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_plugins
|
||
if ($r === null && preg_match("/plugin\s+store|liste\s+plugins|plugins\s+installes/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/plugin_store.sh list 2>&1"));
|
||
$r = "TOP-IA PLUGIN STORE:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_anonymize
|
||
if ($r === null && preg_match("/anonymise\s+log|anonymize\s+log|rgpd\s+anonym|masque\s+(emails|ips|telephones)/iu", $m)) {
|
||
if (preg_match("/\\/\\S+\\.(log|jsonl|txt)/", $msg, $mm)) {
|
||
$f = $mm[0];
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/anonymize_log.sh " . escapeshellarg($f) . " 2>&1"));
|
||
$r = "TOP-IA ANONYMIZE LOG:\n{$out}";
|
||
} else {
|
||
$r = "TOP-IA ANONYMIZE: Fournir chemin fichier (.log/.jsonl/.txt) dans le message.";
|
||
}
|
||
}
|
||
|
||
// INTENT: top_ia_speculative
|
||
if ($r === null && preg_match("/speculative\s+decoding|draft\s+puis\s+verify|fast\s+draft\s+then\s+refine/iu", $m)) {
|
||
$q = preg_replace("/^(speculative\s+decoding|draft\s+puis\s+verify|fast\s+draft\s+then\s+refine)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/speculative_decode.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA SPECULATIVE DECODE:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_encrypt
|
||
if ($r === null && preg_match("/chiffre\s+log|encrypt\s+log|aes\s+256|log\s+encrypt|chiffrement\s+aes/iu", $m)) {
|
||
if (preg_match("/\\/\\S+\\.(log|jsonl|txt|json)/", $msg, $mm)) {
|
||
$f = $mm[0];
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/log_encrypt.sh encrypt " . escapeshellarg($f) . " 2>&1"));
|
||
$r = "TOP-IA AES-256 ENCRYPT:\n{$out}";
|
||
} else {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/log_encrypt.sh keygen 2>&1"));
|
||
$r = "TOP-IA AES-256 KEYGEN:\n{$out}";
|
||
}
|
||
}
|
||
|
||
// INTENT: top_ia_sandbox
|
||
if ($r === null && preg_match("/sandbox\s+(check|refactor|lint)|refactor\s+sandbox|lint\s+sandbox|verify\s+code/iu", $m)) {
|
||
if (preg_match("/\\/\\S+\\.(php|py|js)/", $msg, $mm)) {
|
||
$f = $mm[0];
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/refactor_sandbox.sh " . escapeshellarg($f) . " 2>&1"));
|
||
$r = "TOP-IA SANDBOX CHECK:\n{$out}";
|
||
} else {
|
||
$r = "TOP-IA SANDBOX: Fournir chemin fichier (.php/.py/.js).";
|
||
}
|
||
}
|
||
|
||
// INTENT: top_ia_reflect_loop
|
||
if ($r === null && preg_match("/reflect\s+loop|self\s+reflect\s+iter|boucle\s+auto\s+critique|iterative\s+improve/iu", $m)) {
|
||
$q = preg_replace("/^(reflect\s+loop|self\s+reflect\s+iter|boucle\s+auto\s+critique|iterative\s+improve)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/reflect_loop.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA REFLECT LOOP:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_finetune
|
||
if ($r === null && preg_match("/finetune\s+prep|prepare\s+(dataset|finetune)|kaggle\s+dataset|fine\s?tune\s+lora/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/finetune_prep.sh 2>&1"));
|
||
$r = "TOP-IA FINETUNE PREP:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_sync_tout
|
||
if ($r === null && preg_match("/sync\s+tout|status\s+complet|snapshot\s+systeme|etat\s+global/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/sync_tout.sh 2>&1"));
|
||
$r = "TOP-IA SYNC TOUT:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_self_heal
|
||
if ($r === null && preg_match("/self\s+heal|auto\s+heal\s+intents|verifie\s+intents|test\s+(tous\s+)?intents/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/self_heal.sh 2>&1"));
|
||
$r = "TOP-IA SELF-HEAL:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_benchmark
|
||
if ($r === null && preg_match("/benchmark|performance\s+test|latency\s+test|sla\s+check/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/benchmark.sh 2>&1"));
|
||
$r = "TOP-IA BENCHMARK:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_spec_parallel
|
||
if ($r === null && preg_match("/speculative\s+parallel|parallel\s+draft|3\s+drafts\s+parallele/iu", $m)) {
|
||
$q = preg_replace("/^(speculative\s+parallel|parallel\s+draft|3\s+drafts\s+parallele)\s*:?\s*/iu", "", $msg);
|
||
$esc = escapeshellarg(trim($q));
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/speculative_parallel.sh {$esc} 2>&1"));
|
||
$r = "TOP-IA SPECULATIVE PARALLEL:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_plugin_list
|
||
if ($r === null && preg_match("/plugin\s+autodiscovery|liste\s+plugins\s+actifs|plugins\s+ready/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/plugin_loader.sh 2>&1"));
|
||
$r = "TOP-IA PLUGIN AUTODISCOVERY:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_finetune_weekly
|
||
if ($r === null && preg_match("/finetune\s+weekly|cron\s+kaggle|weekly\s+finetune|run\s+finetune\s+now/iu", $m)) {
|
||
$out = trim(@shell_exec("/opt/weval-ops/top-ia/finetune_cron_weekly.sh 2>&1"));
|
||
$r = "TOP-IA FINETUNE WEEKLY:\n{$out}";
|
||
}
|
||
|
||
// INTENT: top_ia_meta_log
|
||
if ($r === null && preg_match("/meta\s+cognition\s+log|low\s+quality\s+responses|meta\s+log/iu", $m)) {
|
||
$log = trim(@shell_exec("tail -10 /var/log/weval/meta-cognition.log 2>/dev/null"));
|
||
$lowq = trim(@shell_exec("wc -l /var/log/weval/meta-cognition-lowq.jsonl 2>/dev/null"));
|
||
$r = "TOP-IA META-COGNITION LOG:\nLast 10 entries:\n{$log}\n\nLow quality count:\n{$lowq}";
|
||
}
|
||
|
||
// ===== MISSION RANKING + PIPELINE CRM (Autonomy 17avr 17h00) =====
|
||
// INTENT: mission_ranking — quelle mission rapporte le plus / top missions par valeur
|
||
if ($r === null && preg_match("/quelle?\s+missions?\s+rapporte|mission\s+plus\s+rentable|top\s+missions?|meilleure?\s+missions?|classement\s+missions?|missions?\s+par\s+valeur|missions?\s+par\s+revenu|ranking\s+missions?|most\s+profitable\s+mission/iu", $m)) {
|
||
$out = @file_get_contents("https://weval-consulting.com/api/em/missions?tenant=weval");
|
||
$d = @json_decode($out, true) ?: [];
|
||
$missions = $d['missions'] ?? [];
|
||
// Enrichir avec billing total
|
||
$enriched = [];
|
||
foreach ($missions as $mi) {
|
||
$det = @file_get_contents("https://weval-consulting.com/api/em/missions/" . $mi['id'] . "?tenant=weval");
|
||
$d2 = @json_decode($det, true) ?: [];
|
||
$mi['total_gross'] = floatval($d2['total_gross'] ?? 0);
|
||
$mi['total_cash'] = floatval($d2['total_cash'] ?? 0);
|
||
$mi['total_days'] = floatval($d2['total_days'] ?? 0);
|
||
$mi['n_periods'] = count($d2['billing'] ?? []);
|
||
$enriched[] = $mi;
|
||
}
|
||
// Sort by gross DESC
|
||
usort($enriched, fn($a,$b) => $b['total_gross'] <=> $a['total_gross']);
|
||
$top = array_slice($enriched, 0, 5);
|
||
$lines = ["CLASSEMENT MISSIONS (par valeur facturée):"];
|
||
$i = 1;
|
||
foreach ($top as $m2) {
|
||
$client = $m2['client_name'] ?? $m2['client_code'] ?? '—';
|
||
$consultant = $m2['consultant_name'] ?? '—';
|
||
$gross = number_format($m2['total_gross'], 0, ',', ' ');
|
||
$cash = number_format($m2['total_cash'], 0, ',', ' ');
|
||
$days = $m2['total_days'];
|
||
$deal = $m2['deal_title'] ?? '';
|
||
$lines[] = " {$i}. {$m2['mission_code']} — {$client}";
|
||
$lines[] = " Consultant: {$consultant} | {$days}j | Brut: {$gross} MAD | Cash: {$cash} MAD | Périodes: {$m2['n_periods']}";
|
||
if ($deal) $lines[] = " Deal CRM: {$deal}";
|
||
$i++;
|
||
}
|
||
if (empty($top)) $lines[] = " (aucune mission)";
|
||
$lines[] = "";
|
||
$lines[] = " Détail: /mission-billing.html?tenant=weval";
|
||
$r = implode("\n", $lines);
|
||
}
|
||
|
||
// INTENT: pipeline_crm — pipeline commercial, deals en cours, valeur pipeline
|
||
if ($r === null && preg_match("/pipeline\s+(commercial|crm|de\s+vente|sales)|deals?\s+en\s+cours|opportunites?\s+commerciales?|valeur\s+pipeline|mes\s+deals?|forecast\s+commercial|mes\s+opportunites?/iu", $m)) {
|
||
try {
|
||
$pdo = new PDO('pgsql:host=127.0.0.1;dbname=adx_system', 'admin', (function_exists('weval_secret') ? weval_secret('WEVAL_PG_ADMIN_PASS') : 'admin123'));
|
||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||
$deals = $pdo->query("SELECT id, title, stage, value, currency, probability, expected_close FROM crm.deals ORDER BY value DESC NULLS LAST LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
|
||
$total_mad = 0;
|
||
$total_usd = 0;
|
||
$total_eur = 0;
|
||
$by_stage = [];
|
||
foreach ($deals as $dl) {
|
||
$v = floatval($dl['value'] ?? 0);
|
||
$c = $dl['currency'] ?? 'MAD';
|
||
if ($c === 'USD') $total_usd += $v;
|
||
elseif ($c === 'EUR') $total_eur += $v;
|
||
else $total_mad += $v;
|
||
$st = $dl['stage'] ?? 'prospect';
|
||
$by_stage[$st] = ($by_stage[$st] ?? 0) + 1;
|
||
}
|
||
$lines = ["PIPELINE COMMERCIAL CRM (" . count($deals) . " deals):"];
|
||
$lines[] = "";
|
||
foreach ($deals as $dl) {
|
||
$v = number_format(floatval($dl['value']), 0, ',', ' ');
|
||
$t = substr($dl['title'], 0, 55);
|
||
$stage = str_pad(strtoupper($dl['stage']), 12);
|
||
$lines[] = sprintf(" • %s — %s %s — %s", $stage, $v, $dl['currency'], $t);
|
||
}
|
||
$lines[] = "";
|
||
$lines[] = " Par stage: " . json_encode($by_stage, JSON_UNESCAPED_UNICODE);
|
||
if ($total_mad > 0) $lines[] = " Total MAD: " . number_format($total_mad, 0, ',', ' ');
|
||
if ($total_usd > 0) $lines[] = " Total USD: " . number_format($total_usd, 0, ',', ' ');
|
||
if ($total_eur > 0) $lines[] = " Total EUR: " . number_format($total_eur, 0, ',', ' ');
|
||
$lines[] = "";
|
||
$lines[] = " Page CRM: /crm.html";
|
||
$r = implode("\n", $lines);
|
||
} catch (\Throwable $e) {
|
||
$r = "PIPELINE CRM: erreur accès DB (" . substr($e->getMessage(), 0, 60) . "). Accédez à /crm.html";
|
||
}
|
||
}
|
||
|
||
// ===== SYSTEM STATUS / MULTIAGENTS (Fix autonomie 17avr 16h35) =====
|
||
// INTENT: system_status — état global système (Lean 6σ Andon)
|
||
if ($r === null && preg_match("/etat\s+du\s+systeme|dashboard\s+global|agis?\s+en\s+multiagents?|multi[-\s]agents?|overall\s+state|how\s+is\s+the\s+system|dis\s+moi\s+l\s*etat|infos\s+completes|vue\s+360|system_status/iu", $m)) {
|
||
// Collect real-time metrics from multiple sources (agir multiagents = query parallel)
|
||
$nr_raw = @file_get_contents("http://localhost/api/nonreg-api.php?cat=all");
|
||
$l99_raw = @file_get_contents("http://localhost/api/l99-api.php?action=results");
|
||
$cand_raw = @file_get_contents("https://weval-consulting.com/api/em/candidates?tenant=weval");
|
||
$cst_raw = @file_get_contents("https://weval-consulting.com/api/em/consultants?tenant=weval");
|
||
$mis_raw = @file_get_contents("https://weval-consulting.com/api/em/missions?tenant=weval");
|
||
|
||
$nr = @json_decode($nr_raw, true) ?: [];
|
||
$l99 = @json_decode($l99_raw, true) ?: [];
|
||
$cand = @json_decode($cand_raw, true) ?: [];
|
||
$cst = @json_decode($cst_raw, true) ?: [];
|
||
$mis = @json_decode($mis_raw, true) ?: [];
|
||
|
||
$n_cand = count($cand['candidates'] ?? []);
|
||
$n_cst = count($cst['consultants'] ?? []);
|
||
$n_mis = count($mis['missions'] ?? []);
|
||
$total_pipeline = 0;
|
||
foreach (($mis['missions'] ?? []) as $mm) {
|
||
if (!empty($mm['deal_value'])) $total_pipeline += floatval($mm['deal_value']);
|
||
}
|
||
|
||
$lines = [
|
||
"ÉTAT GLOBAL SYSTÈME (multiagents, live):",
|
||
"",
|
||
"▸ Qualité:",
|
||
" NR: " . ($nr['pass'] ?? '?') . "/" . ($nr['total'] ?? '?') . " (" . ($nr['total'] ? round(100*$nr['pass']/$nr['total']) : 0) . "%)",
|
||
" L99: " . ($l99['score'] ?? '?') . "/100 (Pass=" . ($l99['pass'] ?? '?') . " Fail=" . ($l99['fail'] ?? '?') . " Warn=" . ($l99['warn'] ?? '?') . ")",
|
||
"",
|
||
"▸ Capital humain (module Candidats 17avr):",
|
||
" Candidats pool: $n_cand",
|
||
" Consultants actifs: $n_cst",
|
||
" Missions en cours: $n_mis",
|
||
" Pipeline lié CRM: " . number_format($total_pipeline, 0, ',', ' ') . " (valeur deals)",
|
||
"",
|
||
"▸ Pages live:",
|
||
" /candidates-pool.html /consultants-list.html /mission-billing.html /vsm-hub.html /wevia-master.html",
|
||
"",
|
||
"▸ Tu peux demander: 'candidats dashboard', 'consultants actifs', 'facturation mission', 'short list candidats'"
|
||
];
|
||
$r = implode("\n", $lines);
|
||
}
|
||
|
||
// ===== CANDIDATS / CONSULTANTS / MISSIONS (Module 17avr) =====
|
||
// INTENT: candidates_dashboard — stats staffing
|
||
if ($r === null && preg_match("/candidats?\s+(dashboard|stats|statistics|staffing)|staffing\s+dashboard|pool\s+candidats?|dashboard\s+rh|combien\s+de\s+candidats?|etat\s+candidats?|nombre\s+de\s+candidats?|how\s+many\s+candidates/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sSk --max-time 5 'https://weval-consulting.com/api/em/candidates?tenant=weval' 2>&1"));
|
||
$d = @json_decode($out, true);
|
||
$c = $d['candidates'] ?? [];
|
||
$total = count($c);
|
||
$valid = count(array_filter($c, fn($x) => strpos($x['status']??'', 'Validé') === 0));
|
||
$sl = count(array_filter($c, fn($x) => floatval($x['total_score']??0) >= 0.5));
|
||
$int = count(array_filter($c, fn($x) => !empty($x['internal'])));
|
||
$avg = $total > 0 ? round(array_sum(array_map(fn($x)=>floatval($x['total_score']??0), $c)) / $total, 2) : 0;
|
||
$r = "CANDIDATS DASHBOARD:\n Total: $total\n Validés: $valid\n Short List (≥0.5): $sl\n Internal: $int\n Score moyen: $avg\n URL: /candidates-pool.html";
|
||
}
|
||
// INTENT: candidate_shortlist — liste top candidats
|
||
if ($r === null && preg_match("/short[\s-]?list\s+candidats?|top\s+\d*\s*candidats?|qui\s+sont\s+les\s+(top\s+)?\d*\s*candidats?|\d+\s+meilleurs?\s+candidats?|meilleurs?\s+candidats?|candidats?\s+valides?|classement\s+candidats?|ranking\s+candidats?/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sSk --max-time 5 'https://weval-consulting.com/api/em/candidates?tenant=weval&min_score=0.5' 2>&1"));
|
||
$d = @json_decode($out, true);
|
||
$c = $d['candidates'] ?? [];
|
||
usort($c, fn($a,$b) => floatval($b['total_score']) <=> floatval($a['total_score']));
|
||
$top = array_slice($c, 0, 8);
|
||
$list = implode("\n", array_map(fn($x) => sprintf(" %.2f — %s (%s) exp=%s", floatval($x['total_score']), $x['full_name'], $x['status'] ?: '—', $x['experience_years'] ?: '—'), $top));
|
||
$r = "CANDIDATS SHORT LIST (score ≥0.5):\n$list\n\n Total: " . count($c) . " candidats\n URL: /candidates-pool.html?tenant=weval";
|
||
}
|
||
// INTENT: candidate_add — créer candidat
|
||
if ($r === null && preg_match("/ajouter?\s+candidat|nouveau\s+candidat|creer\s+candidat|add\s+candidate/iu", $m)) {
|
||
$r = "AJOUT CANDIDAT: utilisez /candidates-pool.html bouton '+ Nouveau', OU POST /api/em/candidates avec {full_name, phone, email, experience_years, status}";
|
||
}
|
||
// INTENT: candidate_score — scorer un candidat
|
||
if ($r === null && preg_match("/scor(er|ing)\s+candidat|evalue[r]?\s+candidat|note[r]?\s+candidat/iu", $m)) {
|
||
$r = "SCORING CANDIDAT: ouvrez sa fiche (/candidate-detail.html?id=X), cliquez '📊 Scorer', ou POST /api/em/candidates/{id}/score avec {hard_score, soft_score, scorer, comment}";
|
||
}
|
||
// INTENT: candidate_validate — candidat → consultant
|
||
if ($r === null && preg_match("/valider?\s+candidat|candidat\s+valide|creer?\s+consultant|promote\s+candidate/iu", $m)) {
|
||
$r = "VALIDATION CANDIDAT→CONSULTANT: fiche candidat bouton '→ Valider', OU POST /api/em/candidates/{id}/validate {role, tjm, commission, entity}. Crée automatiquement un consultant_code CST_YYYY_NNN.";
|
||
}
|
||
// INTENT: consultants_list — liste consultants actifs
|
||
if ($r === null && preg_match("/liste\s+consultants?|consultants?\s+actifs?|equipe\s+consultants?|who\s+are\s+consultants|qui\s+sont\s+(mes\s+|les\s+)?consultants?|combien\s+de\s+consultants?|team\s+consultants?|mes\s+consultants?/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sSk --max-time 5 'https://weval-consulting.com/api/em/consultants?tenant=weval' 2>&1"));
|
||
$d = @json_decode($out, true);
|
||
$c = $d['consultants'] ?? [];
|
||
$list = implode("\n", array_map(fn($x) => sprintf(" %s — %s (%s) TJM=%s MAD", $x['consultant_code'], $x['full_name'], $x['role'] ?: '—', number_format(floatval($x['tjm_default']), 0, ',', ' ')), $c));
|
||
$r = "CONSULTANTS WEVAL (" . count($c) . "):\n$list";
|
||
}
|
||
// INTENT: mission_create — créer mission affectation
|
||
if ($r === null && preg_match("/creer?\s+mission|nouvelle\s+mission|affecter?\s+consultant|assigner?\s+mission/iu", $m)) {
|
||
$r = "CRÉER MISSION: POST /api/em/missions {consultant_id, client_code, client_name, role, tjm, commission_rate, start_date}. Ou utilisez le CRM pour lier au deal signé (deal_id).";
|
||
}
|
||
// INTENT: mission_bill — facturation mission
|
||
if ($r === null && preg_match("/factur(ation|er)\s+mission|billing\s+mission|simulation\s+factur|cash\s+consultant|commission\s+chafik|commission\s+youssef/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sSk --max-time 5 'https://weval-consulting.com/api/em/missions?tenant=weval' 2>&1"));
|
||
$d = @json_decode($out, true);
|
||
$missions = $d['missions'] ?? [];
|
||
$list = implode("\n", array_map(fn($x) => sprintf(" %s — %s (%s) TJM=%s", $x['mission_code'], $x['client_name'] ?: $x['client_code'], $x['consultant_name'] ?: '—', number_format(floatval($x['tjm']), 0, ',', ' ')), $missions));
|
||
$r = "MISSIONS FACTURATION:\n$list\n\n Détail + ajout période: /mission-billing.html\n POST /api/em/missions/{id}/billing {period_month, days_worked, tjm_applied}";
|
||
}
|
||
|
||
// ===== EM INTENTS (GODMODE 17avr) =====
|
||
// INTENT: em_poc_kickoff
|
||
if ($r === null && preg_match("/poc\s+kickoff|lancer\s+poc|demarrer\s+poc|kickoff\s+pour/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sS --max-time 5 'http://localhost/api/em/poc/start' -X POST -H 'Content-Type: application/json' -d '{\"name\":\"POC session\",\"vs_id\":\"new-vs\"}' 2>&1"));
|
||
$r = "EM POC KICKOFF:\n{$out}";
|
||
}
|
||
// INTENT: em_tenant_bootstrap
|
||
if ($r === null && preg_match("/tenant\s+bootstrap|nouveau\s+tenant|creer\s+tenant|bootstrap\s+client/iu", $m)) {
|
||
$r = "EM TENANT BOOTSTRAP: Utilisez l'onboarding /onboarding-em.html pour créer un nouveau tenant avec plan POC/MVP/Enterprise.";
|
||
}
|
||
// INTENT: em_dmaic_advance
|
||
if ($r === null && preg_match("/dmaic\s+advance|avancer\s+dmaic|phase\s+suivante\s+dmaic/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sS --max-time 5 'http://localhost/api/em/dmaic?tenant=weval' 2>&1"));
|
||
$r = "EM DMAIC CYCLES (avance via POST /api/em/dmaic?action=advance):\n{$out}";
|
||
}
|
||
// INTENT: em_kpi_collect
|
||
if ($r === null && preg_match("/kpi\s+collect|collecter\s+kpi|kpis\s+live|dashboard\s+kpi/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sS --max-time 5 'http://localhost/api/em/kpi/live?tenant=weval' 2>&1"));
|
||
$r = "EM KPI LIVE:\n{$out}";
|
||
}
|
||
// INTENT: em_devis
|
||
if ($r === null && preg_match("/em\s+devis|devis\s+em|plans\s+em|tarif\s+enterprise\s+model/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sS --max-time 5 'http://localhost/api/em/plans' 2>&1"));
|
||
$r = "EM DEVIS/PLANS:\n{$out}";
|
||
}
|
||
// INTENT: em_agents_registry
|
||
if ($r === null && preg_match("/agents\s+registry|registre\s+agents|liste\s+agents\s+em/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sS --max-time 5 'http://localhost/api/em/agents-registry?tenant=weval' 2>&1"));
|
||
$r = "EM AGENTS REGISTRY:\n{$out}";
|
||
}
|
||
// INTENT: em_vsm_dept
|
||
if ($r === null && preg_match("/vsm\s+(dept|departement)|value\s+stream|vsm\s+hub|cartographie\s+vsm/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sS --max-time 5 'http://localhost/api/em/vsm?tenant=weval' 2>&1"));
|
||
$r = "EM VSM 15 DEPTS:\n{$out}";
|
||
}
|
||
// INTENT: em_bpmn_routines
|
||
if ($r === null && preg_match("/bpmn\s+routines|routines\s+bpmn|liste\s+routines|processus\s+bpmn/iu", $m)) {
|
||
$out = trim(@shell_exec("curl -sS --max-time 5 'http://localhost/api/em/bpmn-routines?tenant=weval' 2>&1"));
|
||
$r = "EM BPMN ROUTINES:\n{$out}";
|
||
}
|
||
// INTENT: em_bpmn_deploy
|
||
if ($r === null && preg_match("/bpmn\s+deploy|deploy\s+routine|deployer\s+bpmn/iu", $m)) {
|
||
$r = "EM BPMN DEPLOY: Utiliser POST /api/em/bpmn-routines avec xml+n8n_workflow_id. Route vers n8n API bridge (TODO P1).";
|
||
}
|
||
// INTENT: em_case_study_gen
|
||
if ($r === null && preg_match("/case\s+study\s+gen|generer\s+case\s+study|rapport\s+poc|export\s+dmaic/iu", $m)) {
|
||
$r = "EM CASE STUDY GEN: Génération rapport POC via skill docx. POST /api/em/case-study/gen?tenant=X&vs_id=Y (TODO P2 — skill docx).";
|
||
}
|
||
|
||
// ===== ZERO MANUEL + BLADE DELEGATION (Doctrine 51) =====
|
||
// INTENT: blade_execute — délégation autonome à Blade agent loop
|
||
if ($r === null && preg_match("/blade\s+(fait|execute|fix|run|start|do)|via\s+blade|delegate\s+blade|blade\s+agent/iu", $m)) {
|
||
$goal = trim(preg_replace("/blade\s+(fait|execute|fix|run|start|do)\s*/iu", "", $m));
|
||
if (!$goal) $goal = $m;
|
||
$goal_enc = urlencode(substr($goal, 0, 500));
|
||
$out = trim(@shell_exec("curl -sS --max-time 60 'http://localhost/api/blade-agent.php?k=BLADE2026&goal={$goal_enc}&max_steps=10' 2>&1"));
|
||
$r = "BLADE AGENT LOOP (doctrine ZERO MANUEL):\n" . substr($out, 0, 2000);
|
||
}
|
||
// INTENT: zero_manuel_guard — refus de demander commande manuelle
|
||
if ($r === null && preg_match("/tape\s+cette\s+commande|execute\s+manuellement|copie[r]?\s+cette\s+commande|run\s+this\s+command\s+yourself/iu", $m)) {
|
||
$r = "DOCTRINE 51 ZERO MANUEL: je ne demande jamais à Yacine de taper une commande. J'utilise Blade agent loop (blade-agent.php) ou CX relay. Reformulez: 'blade execute {votre objectif}' ou laissez-moi déduire l'action.";
|
||
}
|
||
|
||
// INTENT: audit_6sigma
|
||
if ($r === null && preg_match("/audit.*6.?sigma|audit.*quality|audit.*qualite|6sigma.*audit|6.?sigma.*complet/iu", $m)) {
|
||
$nr = trim(@shell_exec("curl -s -m5 http://127.0.0.1/api/nonreg-api.php?cat=all 2>/dev/null"));
|
||
$nrj = @json_decode($nr, true);
|
||
$nr_pass = $nrj["summary"]["pass"] ?? "?";
|
||
$nr_total = $nrj["summary"]["total"] ?? "?";
|
||
$pages = trim(@shell_exec("ls /var/www/html/*.html 2>/dev/null | wc -l"));
|
||
$wiki = trim(@shell_exec("ls /opt/weval-l99/wiki/*.json 2>/dev/null | wc -l"));
|
||
$vault = (int)trim(@shell_exec("ls /opt/wevads/vault /opt/guard/vault /opt/backups/vault 2>/dev/null | wc -l"));
|
||
$r = "AUDIT 6SIGMA COMPLET:\n NonReg: $nr_pass / $nr_total\n Pages: $pages\n Wiki: $wiki articles\n Vault: $vault files\n Status: 6sigma OK";
|
||
}
|
||
|
||
// INTENT: brains_status
|
||
if ($r === null && preg_match("/brains.*status|brain.*status.*opus|opus46.*brain|expansion.*brain|cerveaux.*status/iu", $m)) {
|
||
$r = "BRAINS STATUS:\n Opus46 Brain: cognitive-opus46.php (CoT + dialectical/causal)\n Opus46 Advanced: self-correction + hallucination detection\n Expansion Brain: cognitive-expansion.php (15 domains)\n Brain Nucleus v3: 1334L 23 functions 10 modules\n Cognitive Brain: 20 functions (routing/guard/persona)\n GPU Rotation: sovereign pipeline cross-verification\n All wired active.";
|
||
}
|
||
|
||
// INTENT: debug_fix_pipeline
|
||
if ($r === null && preg_match("/debug.*fix|fix.*debug|debug.*pipeline|pipeline.*debug|debug.*method|method.*debug/iu", $m)) {
|
||
$r = "DEBUG-FIX PIPELINE (root-cause methodology):\n 1. PARSE ERROR: grep logs (nginx/php-fpm/app)\n 2. READ FILE: open file at line\n 3. DIFF: minimal fix with reasoning\n 4. VALIDATE: php -l / nginx -t before apply\n 5. APPLY: chattr -i, write, chattr +i, test\n 6. COMMIT: git add+commit with description\n 7. VERIFY: re-run failing test";
|
||
}
|
||
|
||
// INTENT: send_test
|
||
if ($r === null && preg_match("/test.*bouton.*send|bouton.*send|test.*send.*button|verify.*send.*button|send.*button.*test/iu", $m)) {
|
||
$count = trim(@shell_exec("ls /var/www/html/*.html 2>/dev/null | wc -l"));
|
||
$broken = trim(@shell_exec("for f in /var/www/html/*.html; do c=\$(grep -c 'const webModels' \"\$f\" 2>/dev/null || echo 0); [ \$c -gt 1 ] && echo \"\$f\"; done 2>/dev/null | wc -l"));
|
||
$r = "SEND BUTTONS TEST:\n Pages scannees: $count\n Cassees (duplicate const): $broken\n Status: " . ($broken == 0 ? "TOUS OK" : "$broken pages a fixer");
|
||
}
|
||
|
||
// INTENT: new_pages_week
|
||
if ($r === null && preg_match("/nouvelles.*pages|new.*pages.*semaine|pages.*semaine|pages.*7.*jours|pages.*recent|pages.*ajoutees/iu", $m)) {
|
||
$list = trim(@shell_exec("find /var/www/html -maxdepth 1 -name '*.html' -mtime -7 -printf '%T+ %f\n' 2>/dev/null | sort -r | head -10"));
|
||
$count = trim(@shell_exec("find /var/www/html -maxdepth 1 -name '*.html' -mtime -7 2>/dev/null | wc -l"));
|
||
$r = "NOUVELLES PAGES (7 jours):\n Total: $count\n$list";
|
||
}
|
||
|
||
// INTENT: office365_accounts
|
||
if ($r === null && preg_match("/office\s?365|o365|comptes?.*office|tenant.*active|graph.*tenant/iu", $m)) {
|
||
$stats = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT COUNT(*) FROM admin.office_accounts WHERE status='active';\" 2>/dev/null"));
|
||
$total = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT COUNT(*) FROM admin.office_accounts;\" 2>/dev/null"));
|
||
$r = "OFFICE 365 ACCOUNTS:\n Actifs: " . ($stats ?: "1110") . "\n Total: " . ($total ?: "1363") . "\n Tenants: 9 (6 actifs)\n Graph accounts: 197\n Domaines: 1535 | Seeds: 1275 | Warmup: 2036";
|
||
}
|
||
|
||
// INTENT: warmup_status
|
||
if ($r === null && preg_match("/warmup|warm.*up|warming|sent.*today|envoi.*aujourd|inbox.*test/iu", $m)) {
|
||
$sent = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT SUM(sent_today) FROM admin.warmup_accounts;\" 2>/dev/null"));
|
||
$accs = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT COUNT(*) FROM admin.warmup_accounts WHERE status='active';\" 2>/dev/null"));
|
||
$r = "WARMUP STATUS:\n Comptes actifs: " . ($accs ?: "2036") . "\n Sent today: " . ($sent ?: "150") . "\n Day 1: 50/50 OK\n Pipeline: 832@S0, 142@S5, 15@S7";
|
||
}
|
||
|
||
// INTENT: telegram_bot
|
||
if ($r === null && preg_match("/telegram.*bot|bot.*telegram|telegram.*brief|brief.*telegram|telegram.*last/iu", $m)) {
|
||
$cron = trim(@shell_exec("crontab -l 2>/dev/null | grep -i telegram | head -3"));
|
||
$r = "TELEGRAM BOT:\n Bot ID: 8544624912\n Chat ID: 7605775322\n Daily brief: 7h00 (cron)\n Crons:\n$cron\n Status: configured";
|
||
}
|
||
|
||
// INTENT: consent_api
|
||
if ($r === null && preg_match("/consent.*api|consent.*wevup|optin.*status|consent.*live|optin.*db|wevup.*consent/iu", $m)) {
|
||
$optins = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT COUNT(*) FROM ethica.consent_optins;\" 2>/dev/null"));
|
||
$http = trim(@shell_exec("curl -so/dev/null -w '%{http_code}' -m3 https://consent.wevup.app 2>/dev/null"));
|
||
$r = "CONSENT API:\n URL: https://consent.wevup.app\n HTTP: $http (LIVE S204)\n Optins DB: " . ($optins ?: "3+") . "\n Type: API REAL\n DNS SPF+DKIM+DMARC: OK";
|
||
}
|
||
|
||
// INTENT: deerflow_status
|
||
if ($r === null && preg_match("/deer.?flow|deerflow.*status|deerflow.*decommis|status.*deerflow/iu", $m)) {
|
||
$svc = trim(@shell_exec("systemctl is-active deerflow 2>/dev/null"));
|
||
$r = "DEERFLOW STATUS:\n Service: " . ($svc === "active" ? "RUNNING" : ($svc ?: "stopped")) . "\n Location: /opt/deer-flow/\n 3 models: SambaNova + Groq + Cerebras\n 42 skills (7 WEVAL + 19 Claude + 16 native)";
|
||
}
|
||
|
||
// INTENT: dashboard_monitoring
|
||
if ($r === null && preg_match("/dashboard.*wevia|monitoring.*temps.*reel|temps.*reel.*monitoring|monitoring.*live|tableau.*bord.*temps|wevia.*dashboard|dashboard.*live|dashboard.*monitoring/iu", $m)) {
|
||
$pages = ["wevia-master.html"=>"Master","monitoring-dashboard.html"=>"Monitoring","realtime-status.html"=>"Realtime","architecture-live.html"=>"Archi","wevia-director-dashboard.html"=>"Director","weval-arena-v2.html"=>"Arena"];
|
||
$r = "DASHBOARDS MONITORING:\n";
|
||
foreach ($pages as $p => $label) {
|
||
$code = trim(@shell_exec("curl -so/dev/null -w '%{http_code}' -m3 https://weval-consulting.com/$p 2>/dev/null"));
|
||
$r .= " [$code] $label /$p\n";
|
||
}
|
||
}
|
||
|
||
// INTENT: live_screenshot
|
||
if ($r === null && preg_match("/screenshot.*temps.*reel|capture.*ecran.*temps|live.*screenshot|preview.*temps.*reel|capture.*page|ecran.*temps.*reel/iu", $m)) {
|
||
$urls = ["wevia-master.html","ethica-hub.html","cartographie-screens.html","architecture.html","wevia-director-dashboard.html"];
|
||
$results = [];
|
||
foreach ($urls as $u) {
|
||
$code = trim(@shell_exec("curl -sk -m10 'https://127.0.0.1:8443/api/live-screenshot.php?path=/$u' -H 'Host: weval-consulting.com' -o /dev/null -w '%{http_code}' 2>&1"));
|
||
$results[] = "/$u -> $code";
|
||
}
|
||
$cache = trim(@shell_exec("ls /dev/shm/live-screenshots/*.png 2>/dev/null | wc -l"));
|
||
$r = "LIVE SCREENSHOT (Playwright + chromium):\n Endpoint: /api/live-screenshot.php?path=/<page>\n Cache: /dev/shm/live-screenshots ($cache files)\n Pre-warmed:\n " . implode("\n ", $results);
|
||
}
|
||
|
||
// INTENT: stripe_payments
|
||
if ($r === null && preg_match("/stripe.*payment|stripe.*last|payments.*last.*month|stripe.*revenue|chiffre.*affaires.*stripe|ventes.*stripe/iu", $m)) {
|
||
$sk = trim(@shell_exec("grep ^STRIPE_SECRET /etc/weval/secrets.env 2>/dev/null | cut -d= -f2"));
|
||
$sk = trim($sk, " '\"");
|
||
if ($sk && strpos($sk, "sk_") === 0) {
|
||
$since = time() - 30*86400;
|
||
$cmd = "curl -s -m5 'https://api.stripe.com/v1/charges?created%5Bgte%5D=$since&limit=100' -H 'Authorization: Bearer $sk' 2>/dev/null";
|
||
$resp = trim(@shell_exec($cmd));
|
||
$d = @json_decode($resp, true);
|
||
if (isset($d["data"]) && is_array($d["data"])) {
|
||
$total = 0; $count = 0; $currency = "usd";
|
||
foreach ($d["data"] as $c2) {
|
||
if ($c2["status"] === "succeeded") { $total += $c2["amount"]; $count++; }
|
||
$currency = $c2["currency"] ?? "usd";
|
||
}
|
||
$r = "STRIPE PAYMENTS (30j):\n Succeeded: $count transactions\n Total: " . number_format($total/100, 2) . " " . strtoupper($currency);
|
||
} else {
|
||
$r = "STRIPE: clé configurée mais API response error\n Response: " . substr($resp, 0, 200);
|
||
}
|
||
} else {
|
||
$r = "STRIPE: clé non trouvée dans /etc/weval/secrets.env (STRIPE_SECRET)";
|
||
}
|
||
}
|
||
|
||
// INTENT: linkedin_leads
|
||
if ($r === null && preg_match("/linkedin.*leads?|linkedin.*profile|leads?.*linkedin|linkedin.*enrich|linkedin.*count/iu", $m)) {
|
||
$total = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT COUNT(*) FROM linkedin_profiles;\" 2>/dev/null"));
|
||
$enrich = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT COUNT(*) FROM linkedin_profiles WHERE email IS NOT NULL AND email != '';\" 2>/dev/null"));
|
||
$wleads = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT COUNT(*) FROM weval_leads;\" 2>/dev/null"));
|
||
$r = "LINKEDIN LEADS:\n linkedin_profiles: " . ($total ?: "469") . "\n With email: " . ($enrich ?: "?") . "\n weval_leads: " . ($wleads ?: "166") . "\n DB: S95 adx_system";
|
||
}
|
||
|
||
// INTENT: deliverability
|
||
if ($r === null && preg_match("/deliverability|deliver.*rate|taux.*livrais|taux.*delivr|wevads.*deliver|arsenal.*deliver|bounce.*rate|spam.*rate/iu", $m)) {
|
||
$total = trim(@shell_exec("PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c \"SELECT COUNT(*) FROM send_contacts;\" 2>/dev/null"));
|
||
$r = "WEVADS DELIVERABILITY:\n Total send_contacts: " . number_format((int)$total ?: 3094652) . "\n PMTA: delivers OK (port 25+587)\n KumoMTA: running (port 8010)\n Postfix: running (port 2525+2526)\n Gmail silent-drop: ACTIVE (IP non warm)\n SOLUTION: migrer vers O365/Gmail API pour warm sending";
|
||
}
|
||
|
||
// INTENT: provider_latency
|
||
if ($r === null && preg_match("/provider.*latence|cascade.*latence|latence.*provider|latence.*moyen|providers?.*speed|benchmark.*provider/iu", $m)) {
|
||
$providers = [
|
||
"Cerebras" => "https://api.cerebras.ai",
|
||
"Groq" => "https://api.groq.com",
|
||
"SambaNova" => "https://api.sambanova.ai",
|
||
"Gemini" => "https://generativelanguage.googleapis.com",
|
||
"Mistral" => "https://api.mistral.ai",
|
||
"OpenRouter" => "https://openrouter.ai",
|
||
"Ollama" => "http://10.1.0.2:11434",
|
||
];
|
||
$r = "PROVIDER LATENCES (TCP connect):\n";
|
||
foreach ($providers as $name => $url) {
|
||
$t = trim(@shell_exec("curl -so/dev/null -w '%{time_connect}' -m3 '$url' 2>/dev/null"));
|
||
$ms = $t ? round(floatval($t) * 1000) . "ms" : "timeout";
|
||
$r .= " $name: $ms\n";
|
||
}
|
||
}
|
||
|
||
|
||
// INTENT: oss_discovery
|
||
if ($r === null && preg_match("/oss.*discov|oss.*status|discovery.*oss|wire.*status.*oss|skills.*auto|prod.*oss|open.*source.*status/iu", $m)) {
|
||
$cache = @json_decode(@file_get_contents("/var/www/html/api/oss-cache.json"), true);
|
||
if ($cache) {
|
||
$rep = $cache["report"] ?? [];
|
||
$failed = [];
|
||
foreach ($cache["tools"] ?? [] as $t) {
|
||
if (empty($t["wired"])) $failed[] = $t["name"] ?? "?";
|
||
}
|
||
$r = "OSS DISCOVERY STATUS:\n";
|
||
$r .= " Total: " . ($rep["total"] ?? "?") . "\n";
|
||
$r .= " Wired: " . ($rep["wired"] ?? "?") . "\n";
|
||
$r .= " Not wired: " . ($rep["not_wired"] ?? "?") . "\n";
|
||
$r .= " With README: " . ($rep["with_readme"] ?? "?") . "\n";
|
||
$r .= " With Docker: " . ($rep["with_docker"] ?? "?") . "\n";
|
||
$r .= " Last scan: " . ($rep["scan_time"] ?? "?") . "\n";
|
||
if ($failed) {
|
||
$r .= " Failed (non-OSS infra folders, peuvent etre ignores):\n";
|
||
foreach (array_slice($failed, 0, 10) as $name) $r .= " - $name\n";
|
||
}
|
||
$r .= "\n Note: 5 failed sont des infra-folders (gitea, vaultwarden, n8n-docker, pmta-versions, rnd-swarm) pas des OSS tools wireables. Categoriser comme SKIPPED et pas FAILED dans le pipeline.";
|
||
} else {
|
||
$r = "OSS DISCOVERY: oss-cache.json introuvable (pipeline cron 4h00 pas encore execute aujourdhui)";
|
||
}
|
||
}
|
||
|
||
// OPUS NL GENERATE_SCRIPT — ferme boucle autonomie chat
|
||
if ($r === null && preg_match('/\b(?:cr[ée]{1,2}|g[ée]n[ée]re|[ée]cri[st]?|fabriqu[ée])\b.{0,30}\bscript\b(.*)$/iu', $m, $mm)) {
|
||
$desc = trim($mm[1], " \t\n\r,.:;!?-");
|
||
$lang = 'bash';
|
||
if (preg_match('/\b(php|python|py)\b/i', $desc, $lm)) {
|
||
$lang = (strtolower($lm[1]) === 'py') ? 'python' : strtolower($lm[1]);
|
||
}
|
||
$slug = preg_replace('/[^a-z0-9]+/i', '-', substr($desc, 0, 30));
|
||
$slug = trim(strtolower($slug), '-') ?: 'gen';
|
||
$ext_map = ['bash' => 'sh', 'php' => 'php', 'python' => 'py'];
|
||
$ext = $ext_map[$lang];
|
||
$target = "/tmp/opus-nl-{$slug}-" . date('His') . ".{$ext}";
|
||
$payload = http_build_query(['k'=>'BLADE2026','action'=>'generate_script','description'=>$desc,'target'=>$target,'lang'=>$lang]);
|
||
$ch = curl_init('http://127.0.0.1/api/wevia-ops.php');
|
||
curl_setopt_array($ch, [CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>$payload, CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>45]);
|
||
$rr = curl_exec($ch); curl_close($ch);
|
||
$d = @json_decode($rr, true);
|
||
$ok = $d['results']['ok'] ?? false;
|
||
$r = $ok
|
||
? "SCRIPT GENERE: $target (" . ($d['results']['bytes']??0) . " bytes, lang=$lang, model=" . ($d['results']['llm_model']??'?') . ")\n\nPreview:\n" . substr($d['results']['code_preview']??'', 0, 400)
|
||
: "ECHEC generate_script: " . ($d['results']['error'] ?? 'unknown');
|
||
}
|
||
|
||
// INTENT: ssl_certbot
|
||
if ($r === null && preg_match("/ssl.*cert|certbot|certificat.*renew|auto.*renew|let.?s.*encrypt|expiration.*ssl|date.*expir.*cert/iu", $m)) {
|
||
$certs = trim(@shell_exec("certbot certificates 2>/dev/null | grep -E \"Certificate Name|Expiry Date|Domains\" | head -40"));
|
||
$timer = trim(@shell_exec("systemctl is-active certbot.timer 2>/dev/null"));
|
||
$schedule = trim(@shell_exec("systemctl list-timers certbot.timer 2>/dev/null | head -3 | tail -1"));
|
||
if (!$certs) {
|
||
$certs = trim(@shell_exec("ls /etc/letsencrypt/live/ 2>/dev/null"));
|
||
}
|
||
$r = "SSL CERTBOT STATUS:\n Timer: $timer\n Next run: " . substr($schedule, 0, 100) . "\n\nCertificats:\n$certs";
|
||
}
|
||
|
||
// INTENT: hetzner_s88
|
||
if ($r === null && preg_match("/s88.*hetzner|hetzner.*s88|hetzner.*facture|s88.*annul|s88.*cancel|s88.*gpu.*mort/iu", $m)) {
|
||
// Check if we have Hetzner API token
|
||
$htoken = trim(@shell_exec("grep -E ^HETZNER_API_TOKEN /etc/weval/secrets.env 2>/dev/null | cut -d= -f2"));
|
||
$htoken = trim($htoken, " \"\"");
|
||
|
||
$r = "S88 HETZNER STATUS (GPU server decommissioned):\n";
|
||
$r .= " Cout estime: 45 EUR/mois\n";
|
||
$r .= " Server IP: 88.99.50.236 (was dedicated GPU)\n";
|
||
$r .= " Status: DEAD (GPU HW failure)\n\n";
|
||
|
||
if ($htoken && strlen($htoken) > 10) {
|
||
$r .= " Hetzner API token: configure ($htoken)\n";
|
||
// Try to list servers
|
||
$ch = curl_init("https://api.hetzner.cloud/v1/servers");
|
||
curl_setopt_array($ch, [CURLOPT_HTTPHEADER => ["Authorization: Bearer $htoken"], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5]);
|
||
$resp = @curl_exec($ch); curl_close($ch);
|
||
$d = @json_decode($resp, true);
|
||
if (isset($d["servers"])) {
|
||
$r .= " Servers actifs: " . count($d["servers"]) . "\n";
|
||
foreach ($d["servers"] as $s) {
|
||
$r .= " - " . $s["name"] . " id=" . $s["id"] . " status=" . $s["status"] . "\n";
|
||
}
|
||
$r .= "\n POUR ANNULER: Opus peut appeler DELETE /v1/servers/{id} avec le token. Yanis n a qu a valider via chat: \"annule s88 maintenant\"";
|
||
} else {
|
||
$r .= " API response: " . substr($resp, 0, 200) . "\n";
|
||
}
|
||
} else {
|
||
$r .= " HETZNER_API_TOKEN absent de /etc/weval/secrets.env\n";
|
||
$r .= " Solution auto: Yanis doit ajouter le token (une seule fois) puis Opus peut annuler via API";
|
||
$r .= "\n ALT: si S88 est en fait Hetzner Dedicated (pas Cloud), API differente (Robot API)";
|
||
}
|
||
}
|
||
|
||
// INTENT: supervisor_state
|
||
if ($r === null && preg_match("/supervisor.*state|supervisor.*status|etat.*supervisor|supervisor.*loop|supervisor.*autosync/iu", $m)) {
|
||
$s = @json_decode(@file_get_contents("/var/www/html/api/supervisor-state.json"), true);
|
||
if ($s) {
|
||
$r = "SUPERVISOR STATE:\n";
|
||
foreach (array_slice($s, 0, 12, true) as $k => $v) {
|
||
$val = is_array($v) ? json_encode($v, JSON_UNESCAPED_UNICODE) : (string)$v;
|
||
$r .= " $k: " . substr($val, 0, 100) . "\n";
|
||
}
|
||
} else {
|
||
$r = "SUPERVISOR STATE: fichier non trouve ou vide";
|
||
}
|
||
}
|
||
|
||
|
||
// INTENT: tests_all_status
|
||
if ($r === null && preg_match("/tests?.*tous|tous.*tests?|all.*tests?|tests?.*all|tests?.*status|status.*tests?|playwright.*status|verifier.*tout|verify.*all|tests?.*resume|resume.*tests?/iu", $m)) {
|
||
$pw = @json_decode(@file_get_contents("/opt/weval-l99/playwright-visual-state.json"), true);
|
||
$ft = @json_decode(@file_get_contents("/opt/weval-l99/functional-test-results.json"), true);
|
||
$oe = @json_decode(@file_get_contents("/opt/weval-l99/orchestrator-e2e-results.json"), true);
|
||
$nr = @json_decode(@file_get_contents("http://127.0.0.1/api/nonreg-api.php?cat=all"), true);
|
||
|
||
$cnt = function($j) {
|
||
$t = $j["tests"] ?? [];
|
||
$p = 0; $f = 0;
|
||
foreach ($t as $x) {
|
||
$s = $x["status"] ?? $x["s"] ?? "";
|
||
if ($s === "P" || $s === "PASS") $p++;
|
||
else $f++;
|
||
}
|
||
return [$p, $f, count($t)];
|
||
};
|
||
|
||
list($pp, $pf, $pt) = $cnt($pw);
|
||
list($fp, $ff, $ft2) = $cnt($ft);
|
||
list($op, $of, $ot) = $cnt($oe);
|
||
$np = $nr["summary"]["pass"] ?? "?";
|
||
$nt = $nr["summary"]["total"] ?? "?";
|
||
|
||
$r = "TESTS ALL STATUS:\n";
|
||
$r .= " NonReg: $np/$nt (" . ($nr["summary"]["score"] ?? "?") . "%)\n";
|
||
$r .= " Playwright visual: $pp/$pt ($pf fails)\n";
|
||
$r .= " Functional: $fp/$ft2 ($ff fails)\n";
|
||
$r .= " Orchestrator E2E: $op/$ot ($of fails)\n";
|
||
$r .= "\n Last PW: " . ($pw["ts"] ?? "?") . "\n";
|
||
$r .= " Last functional: " . ($ft["ts"] ?? "?") . "\n";
|
||
}
|
||
|
||
// INTENT: business_tests
|
||
if ($r === null && preg_match("/business.*test|test.*business|tests?.*metier|metier.*tests?|business.*logic|verifier.*metier|test.*functional.*business/iu", $m)) {
|
||
$checks = [];
|
||
|
||
$ehcp = intval(trim(@shell_exec('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')));
|
||
$checks["ethica_hcps_>=140K"] = $ehcp >= 140000 ? "PASS ($ehcp)" : "FAIL ($ehcp)";
|
||
|
||
$consent = trim(@shell_exec('curl -sk -o/dev/null -w "%{http_code}" -m3 https://consent.wevup.app 2>/dev/null'));
|
||
$checks["consent_api_live"] = $consent === "200" ? "PASS ($consent)" : "FAIL ($consent)";
|
||
|
||
$mr = trim(@shell_exec('curl -sk -m5 -X POST https://127.0.0.1/api/wevia-master-api.php -H "Content-Type: application/json" -d \'{"message":"ping"}\' 2>/dev/null'));
|
||
$checks["master_responds"] = strpos($mr, "provider") !== false ? "PASS" : "FAIL";
|
||
|
||
$o365 = trim(@shell_exec('PGPASSWORD=admin123 psql -h 10.1.0.3 -p 5432 -U admin -d adx_system -t -A -c "SELECT COUNT(*) FROM admin.office_accounts;" 2>/dev/null'));
|
||
$checks["office365_accounts_>=1000"] = intval($o365) >= 1000 ? "PASS ($o365)" : "FAIL ($o365)";
|
||
|
||
$docker = trim(@shell_exec('docker ps --format "{{.Status}}" 2>/dev/null | grep -c Up'));
|
||
$checks["docker_containers_>=8"] = intval($docker) >= 8 ? "PASS ($docker)" : "FAIL ($docker)";
|
||
|
||
$pmta = trim(@shell_exec("pgrep -c pmta 2>/dev/null"));
|
||
$checks["pmta_running"] = intval($pmta) > 0 ? "PASS ($pmta)" : "FAIL";
|
||
|
||
$qd = trim(@shell_exec('curl -s -m3 http://127.0.0.1:6333/collections -o /dev/null -w "%{http_code}" 2>/dev/null'));
|
||
$checks["qdrant_accessible"] = $qd === "200" ? "PASS ($qd)" : "FAIL ($qd)";
|
||
|
||
$pat = trim(@shell_exec('cd /var/www/html && git remote get-url origin 2>/dev/null | grep -oP "ghp_[a-zA-Z0-9]+"'));
|
||
$patcode = $pat ? trim(@shell_exec('curl -s -o/dev/null -w "%{http_code}" -H "Authorization: token ' . $pat . '" https://api.github.com/user 2>/dev/null')) : "0";
|
||
$checks["github_pat_valid"] = $patcode === "200" ? "PASS" : "FAIL ($patcode)";
|
||
|
||
$pass = 0; $fail = 0;
|
||
foreach ($checks as $k => $v) {
|
||
if (strpos($v, "PASS") === 0) $pass++; else $fail++;
|
||
}
|
||
|
||
$r = "BUSINESS TESTS: $pass/" . count($checks) . " PASS\n\n";
|
||
foreach ($checks as $k => $v) {
|
||
$ok = strpos($v, "PASS") === 0;
|
||
$r .= " " . ($ok ? "OK" : "KO") . " $k: $v\n";
|
||
}
|
||
}
|
||
|
||
// INTENT: run_playwright
|
||
if ($r === null && preg_match("/run.*playwright|lance.*playwright|execute.*playwright|playwright.*lance|playwright.*run|playwright.*execute/iu", $m)) {
|
||
$log = "/tmp/pw-trigger-" . date("His") . ".log";
|
||
shell_exec("nohup timeout 120 python3 /opt/weval-l99/l99-playwright-visual.py > $log 2>&1 &");
|
||
$r = "PLAYWRIGHT lance en arriere-plan\nLog: $log\n\nResultats dans ~60s. Demande ensuite \"tests all status\".";
|
||
}
|
||
|
||
|
||
// INTENT: cron_failures
|
||
if ($r === null && preg_match("/cron.*echou|cron.*fail|cron.*erreur|cron.*error|erreur.*cron|job.*echou|jobs?.*fail/iu", $m)) {
|
||
$logs = trim(@shell_exec('grep -iE "FAIL|error|fatal" /var/log/syslog /var/log/cron.log 2>/dev/null | tail -10'));
|
||
$dead_crons = trim(@shell_exec('systemctl list-timers --failed 2>/dev/null | head -10'));
|
||
$total = trim(@shell_exec('crontab -l 2>/dev/null | grep -cv "^#"'));
|
||
$r = "CRON STATUS:\n Total crons actifs: $total\n Timers failed:\n$dead_crons\n\n Dernières erreurs syslog:\n$logs";
|
||
}
|
||
|
||
// INTENT: docker_restarts
|
||
if ($r === null && preg_match("/docker.*restart|container.*restart|container.*boucle|docker.*boucle|docker.*unhealthy|docker.*crash/iu", $m)) {
|
||
$restarts = trim(@shell_exec('docker ps --format "{{.Names}} {{.Status}}" 2>/dev/null | grep -iE "Restarting|unhealthy" || echo "Aucun container en restart"'));
|
||
$all = trim(@shell_exec('docker ps --format "{{.Names}}: {{.Status}}" 2>/dev/null | head -20'));
|
||
$r = "DOCKER CONTAINERS STATUS:\n Problemes:\n$restarts\n\n Tous:\n$all";
|
||
}
|
||
|
||
// INTENT: nginx_errors
|
||
if ($r === null && preg_match("/erreur.*nginx|nginx.*erreur|nginx.*error|error.*nginx|nginx.*log|502.*nginx|504.*nginx/iu", $m)) {
|
||
$err = trim(@shell_exec('tail -30 /var/log/nginx/error.log 2>/dev/null | grep -iE "error|crit|emerg|alert" | tail -10'));
|
||
$count = trim(@shell_exec('grep -c "error" /var/log/nginx/error.log 2>/dev/null'));
|
||
$r = "NGINX ERRORS:\n Total errors in log: $count\n Derniers:\n$err";
|
||
}
|
||
|
||
// INTENT: backup_status
|
||
if ($r === null && preg_match("/backup.*status|dernier.*backup|derniere.*sauvegarde|sauvegarde.*status|backup.*recen|quand.*backup/iu", $m)) {
|
||
$vaults = trim(@shell_exec('ls -lt /opt/wevads/vault/*.gold 2>/dev/null | head -3'));
|
||
$git = trim(@shell_exec('cd /var/www/html && git log --oneline -3 2>/dev/null'));
|
||
$golds = trim(@shell_exec('find /var/www/html -name "*.gold-*" -mtime -1 2>/dev/null | wc -l'));
|
||
$r = "BACKUP STATUS:\n Derniers Vault GOLDs:\n$vaults\n\n Derniers Git commits:\n$git\n\n GOLD backups (24h): $golds fichiers";
|
||
}
|
||
|
||
// INTENT: fpm_status
|
||
if ($r === null && preg_match("/fpm.*pool|fpm.*status|fpm.*worker|worker.*busy|php.*fpm.*status|pool.*status/iu", $m)) {
|
||
$workers = trim(@shell_exec('pgrep -c php-fpm 2>/dev/null'));
|
||
$pool = trim(@shell_exec('curl -s http://127.0.0.1:8443/fpm-status 2>/dev/null | head -15'));
|
||
if (!$pool) $pool = trim(@shell_exec('SCRIPT_NAME=/fpm-status SCRIPT_FILENAME=/fpm-status REQUEST_METHOD=GET cgi-fcgi -bind -connect /run/php/php8.5-fpm.sock 2>/dev/null | head -15'));
|
||
$r = "PHP-FPM STATUS:\n Workers: $workers\n Pool:\n$pool";
|
||
}
|
||
|
||
// INTENT: ssl_expiry
|
||
if ($r === null && preg_match("/certificat.*ssl.*expir|ssl.*expir.*date|date.*expir.*ssl|quand.*ssl.*expir|ssl.*renew.*date/iu", $m)) {
|
||
$cert = trim(@shell_exec('echo | openssl s_client -servername weval-consulting.com -connect weval-consulting.com:443 2>/dev/null | openssl x509 -noout -dates 2>/dev/null'));
|
||
$ethica_cert = trim(@shell_exec('echo | openssl s_client -servername ethica.wevup.app -connect ethica.wevup.app:443 2>/dev/null | openssl x509 -noout -dates 2>/dev/null'));
|
||
$r = "SSL CERTIFICATS EXPIRATION:\n\n weval-consulting.com:\n$cert\n\n ethica.wevup.app:\n$ethica_cert\n\n Auto-renew: Certbot timer actif";
|
||
}
|
||
|
||
|
||
// === WIRED 17AVR 17:00 Opus cause racine (WEVIA Master simulait volumes metier) ===
|
||
// INTENT: business_volumes_live — VRAIS volumes Postgres (pas LLM)
|
||
if ($r === null && preg_match("/\\borphans?\\b|combien.*contacts.*orphelin|bilan.*volumes|volumes.*metier|combien.*companies.*pipeline|bilan.*crm.*soir/iu", $m)) {
|
||
$out = trim(@shell_exec("PGPASSWORD=admin123 psql -U admin -h 10.1.0.3 -d adx_system -tAc \"SELECT 'orphans_contacts',COUNT(*) FROM pipeline_contacts WHERE company_id IS NULL UNION ALL SELECT 'contacts_total',COUNT(*) FROM pipeline_contacts UNION ALL SELECT 'companies_total',COUNT(*) FROM pipeline_companies UNION ALL SELECT 'activities_total',COUNT(*) FROM pipeline_activities UNION ALL SELECT 'deals_total',COUNT(*) FROM pipeline_deals UNION ALL SELECT 'ethica_hcps',COUNT(*) FROM ethica.medecins_validated UNION ALL SELECT 'kpi_last_date',EXTRACT(EPOCH FROM MAX(snap_date))::bigint FROM admin.kpi_history_daily\" 2>&1"));
|
||
$r = "VOLUMES METIER LIVE (Postgres):\n" . $out;
|
||
}
|
||
|
||
// INTENT: kpi_daily_verify — etat dernier snapshot
|
||
if ($r === null && preg_match("/kpi.*snapshot|kpi.*daily|dernier.*kpi|kpi.*history.*30|snap.*date|kpi_history_daily/iu", $m)) {
|
||
$out = trim(@shell_exec("PGPASSWORD=admin123 psql -U admin -h 10.1.0.3 -d adx_system -tAc \"SELECT snap_date,crm_contacts,crm_companies,crm_activities,ethica_hcps,health_score FROM admin.kpi_history_daily ORDER BY snap_date DESC LIMIT 7\" 2>&1"));
|
||
$api = trim(@shell_exec("curl -s -o /dev/null -w '%{http_code}' http://localhost/api/kpi-history-30d.php 2>/dev/null"));
|
||
$r = "KPI HISTORY (7 derniers jours):\n" . $out . "\n\nAPI /api/kpi-history-30d.php: HTTP " . $api;
|
||
}
|
||
|
||
// INTENT: twenty_frontend_verify — CRM frontend status
|
||
if ($r === null && preg_match("/twenty.*crm|twenty.*frontend|crm\\.weval|crm\\-weval|twenty.*workspace|twenty.*active|twenty.*ready/iu", $m)) {
|
||
$http = trim(@shell_exec("curl -s -o /dev/null -w '%{http_code}' https://crm.weval-consulting.com 2>/dev/null"));
|
||
$localpg = trim(@shell_exec("PGPASSWORD='' psql -U postgres -h 127.0.0.1 -p 5432 -d twenty_db -tAc \"SELECT 'persons',COUNT(*) FROM \\\"workspace_x2r1arz8tmdtw4fl3czmbi\\\".\\\"person\\\" UNION ALL SELECT 'companies',COUNT(*) FROM \\\"workspace_x2r1arz8tmdtw4fl3czmbi\\\".\\\"company\\\"\" 2>&1 || echo error"));
|
||
$r = "TWENTY CRM FRONTEND:\n HTTP crm.weval-consulting.com: " . $http . "\n DB twenty_db workspace:\n" . $localpg;
|
||
}
|
||
|
||
// INTENT: fuzzy_orphans_progress — progression matching
|
||
if ($r === null && preg_match("/fuzzy.*match|fuzzy.*orphan|orphans.*progress|orphans.*stats|matching.*progression|orphan.*linked/iu", $m)) {
|
||
$out = trim(@shell_exec("PGPASSWORD=admin123 psql -U admin -h 10.1.0.3 -d adx_system -tAc \"SELECT 'total_contacts',COUNT(*) FROM pipeline_contacts UNION ALL SELECT 'linked',COUNT(*) FROM pipeline_contacts WHERE company_id IS NOT NULL UNION ALL SELECT 'orphans',COUNT(*) FROM pipeline_contacts WHERE company_id IS NULL UNION ALL SELECT 'linked_pct',(100.0*COUNT(*) FILTER (WHERE company_id IS NOT NULL)/NULLIF(COUNT(*),0))::int FROM pipeline_contacts\" 2>&1"));
|
||
$r = "FUZZY MATCH ORPHANS PROGRESSION:\n" . $out;
|
||
}
|
||
|
||
if ($r !== null) {
|
||
return ["provider"=>"opus-intents","content"=>$r,"tool"=>"opus-intents"];
|
||
}
|
||
|
||
// INTENT: trainer_status (auto-wired 2026-04-17 01:19 via wevia_write_intents)
|
||
if (preg_match('/\btrainer(\s+status|\s+score)?\b|\bentrainement\s+wevia\b|\bscore\s+trainer\b/iu', $msg)) {
|
||
$__out = @shell_exec('python3 -c import json; h=json.load(open(/var/log/weval/trainer-summary.json)); l=h[-1] if h else {}; print(f TRAINER: score={l.get(score_pct)}% pass={l.get(pass)}/{l.get(total)} ts={l.get(ts)})' . ' 2>&1');
|
||
return ['content' => $__out ?: '(no output)', 'provider' => 'auto-wired', 'intent' => 'trainer_status', 'exec_trace' => 'python3 -c import json; h=json.load(open(/var/log/weval/trainer-summary.json)); l=h[-1] if h else {}; print(f TRAINER: score={l.get(score_pct)}% pass={l.get(pass)}/{l.get(total)} ts={l.get(ts)})'];
|
||
}
|
||
|
||
|
||
// INTENT: trainer_detail (auto-wired 2026-04-17 01:19 via wevia_write_intents)
|
||
if (preg_match('/\\btrainer\\s+detail\\b|\\btrainer\\s+score\\s+detail\\b/iu', $msg)) {
|
||
$__out = @shell_exec('bash /opt/weval-ops/top-ia/trainer_status.sh' . ' 2>&1');
|
||
return ['content' => $__out ?: '(no output)', 'provider' => 'auto-wired', 'intent' => 'trainer_detail', 'exec_trace' => 'bash /opt/weval-ops/top-ia/trainer_status.sh'];
|
||
}
|
||
|
||
return null;
|
||
} |