235 lines
11 KiB
PHP
235 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* V78 — Capability Dispatcher
|
|
* WEVIA Master selects relevant agents based on task keywords.
|
|
* Usage: "dispatcher audit cyber" / "selective agents avatar" / "focus agents blade"
|
|
*
|
|
* Sélectionne les N agents pertinents, fire en parallèle, synthèse.
|
|
*/
|
|
|
|
if (!isset($_mam) && !isset($msg)) {
|
|
$_raw = file_get_contents('php://input');
|
|
$_j = json_decode($_raw, true);
|
|
$_mam = $_j['message'] ?? $_REQUEST['msg'] ?? $_REQUEST['message'] ?? '';
|
|
if (empty($_mam)) { header('Content-Type: application/json'); echo json_encode(['error'=>'V78 needs message']); return; }
|
|
}
|
|
$V78_MSG = $msg ?? $_mam;
|
|
$V78_LOW = mb_strtolower($V78_MSG);
|
|
|
|
/* V78 explicit triggers */
|
|
$V78_TRIGGERS = ['dispatcher','selective agents','focus agents','smart agents','agents selectif','agents pertinents','capability dispatcher','agents sur mesure'];
|
|
$V78_HIT = false;
|
|
foreach ($V78_TRIGGERS as $t) {
|
|
if (stripos($V78_LOW, $t) !== false) { $V78_HIT = true; break; }
|
|
}
|
|
if (!$V78_HIT) {
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['error'=>'V78 trigger not matched','triggers'=>$V78_TRIGGERS,'got'=>$V78_MSG]);
|
|
return;
|
|
}
|
|
|
|
/* Capability matrix: task keyword → agent(s) to fire */
|
|
$V78_MATRIX = [
|
|
/* Cyber / Security / Selenium */
|
|
'cyber' => ['v76_cyber_tips','v76_selenium_check','v76_chrome_blade','blade_pending','blade_scripts','token_keys'],
|
|
'selenium' => ['v76_selenium_check','v76_chrome_blade','v76_playwright_check','selenium_drv','chrome_procs_v77'],
|
|
'chrome' => ['v76_selenium_check','v76_chrome_blade','chrome_procs_v77','blade_scripts'],
|
|
'token' => ['token_keys','blade_pending','blade_scripts','v76_cyber_tips'],
|
|
'renouvel' => ['token_keys','blade_pending','blade_scripts'],
|
|
'office' => ['v76_cyber_tips','blade_pending','token_keys'],
|
|
'blade' => ['v76_chrome_blade','blade_pending','blade_scripts','token_keys'],
|
|
|
|
/* Visual / UX */
|
|
'avatar' => ['v76_avatar_audit','v76_registry_status'],
|
|
'visuel' => ['v76_avatar_audit','v76_playwright_check','pages_500'],
|
|
'ux' => ['pages_500','v76_playwright_check','hubs_count'],
|
|
'page' => ['pages_500','html_count','hubs_count','v76_pages_index'],
|
|
'orphelin' => ['v76_orphans_audit','v76_pages_index'],
|
|
'orphan' => ['v76_orphans_audit','v76_pages_index'],
|
|
'referentiel'=> ['v76_pages_index','v76_orphans_audit','v76_registry_status'],
|
|
'index' => ['v76_pages_index'],
|
|
'archi' => ['v76_pages_index','v76_orphans_audit','hubs_count','html_count'],
|
|
|
|
/* Quality / Six Sigma */
|
|
'qualite' => ['v76_six_sigma','nonreg_score','pages_500','v76_playwright_check'],
|
|
'sigma' => ['v76_six_sigma','v76_autonomy_score','nonreg_score'],
|
|
'nonreg' => ['nonreg_score','pages_500'],
|
|
'regression' => ['nonreg_score','v76_playwright_check','pages_500','git_dirty'],
|
|
'test' => ['v76_playwright_check','nonreg_score','pages_500'],
|
|
|
|
/* Infrastructure */
|
|
'infra' => ['load','disk','memory','fpm','nginx','postgres'],
|
|
'serveur' => ['load','disk','memory','ports_listen'],
|
|
'disque' => ['disk'],
|
|
'memoire' => ['memory'],
|
|
'ram' => ['memory'],
|
|
'ports' => ['ports_listen','sovereign_port','qdrant_port'],
|
|
|
|
/* Services */
|
|
'docker' => ['docker'],
|
|
'ollama' => ['ollama_procs'],
|
|
'ia' => ['ollama_procs','sovereign_port','qdrant_port','paperclip_api'],
|
|
'sovereign' => ['sovereign_port'],
|
|
'qdrant' => ['qdrant_port','truth_registry_kb'],
|
|
'paperclip' => ['paperclip_api'],
|
|
'deerflow' => ['deerflow_port'],
|
|
|
|
/* Autonomie / Source de vérité */
|
|
'autonomie' => ['v76_autonomy_score','truth_registry_kb','v76_six_sigma','intents_pending'],
|
|
'truth' => ['v76_autonomy_score','truth_registry_kb'],
|
|
'intent' => ['intents_pending'],
|
|
'doctrine' => ['v76_autonomy_score'],
|
|
|
|
/* Git / vault / wiki */
|
|
'git' => ['git_dirty','git_head'],
|
|
'commit' => ['git_dirty','git_head'],
|
|
'vault' => ['vault_count'],
|
|
'wiki' => ['wiki_count'],
|
|
'backup' => ['vault_count','git_head'],
|
|
|
|
/* CRM / Business */
|
|
'crm' => ['postgres','paperclip_api'],
|
|
'ethica' => ['postgres'],
|
|
|
|
/* Général */
|
|
'audit' => ['v76_avatar_audit','v76_six_sigma','nonreg_score','pages_500','git_dirty'],
|
|
'etat' => ['v76_autonomy_score','v76_six_sigma','nonreg_score','load','disk'],
|
|
'sante' => ['load','disk','memory','pages_500','docker','nonreg_score'],
|
|
];
|
|
|
|
/* Agent definitions (from V77) */
|
|
$V78_AGENT_DEFS = [
|
|
'v76_avatar_audit' => 'bash /var/www/html/api/v76-scripts/avatar-audit.sh',
|
|
'v76_selenium_check' => 'bash /var/www/html/api/v76-scripts/selenium-check.sh',
|
|
'v76_playwright_check' => 'bash /var/www/html/api/v76-scripts/playwright-check.sh',
|
|
'v76_registry_status' => 'bash /var/www/html/api/v76-scripts/registry-status.sh',
|
|
'v76_six_sigma' => 'bash /var/www/html/api/v76-scripts/six-sigma.sh',
|
|
'v76_chrome_blade' => 'bash /var/www/html/api/v76-scripts/chrome-blade.sh',
|
|
'v76_cyber_tips' => 'bash /var/www/html/api/v76-scripts/cyber-tips.sh',
|
|
'v76_autonomy_score' => 'bash /var/www/html/api/v76-scripts/autonomy-score.sh',
|
|
'v76_pages_index' => 'bash /var/www/html/api/v76-scripts/pages-index.sh',
|
|
'v76_orphans_audit' => 'bash /var/www/html/api/v76-scripts/orphans-audit.sh',
|
|
'load' => 'uptime | tr -s " " | cut -d, -f3- | head -c 60',
|
|
'disk' => 'df -h / | tail -1 | awk \'{print "use:"$5" free:"$4}\'',
|
|
'memory' => 'free -m | grep Mem | awk \'{print "used:"$3"M free:"$4"M"}\'',
|
|
'fpm' => 'pgrep -cf php-fpm | xargs -I{} echo "fpm:{}"',
|
|
'nginx' => 'pgrep -cf nginx | xargs -I{} echo "nginx:{}"',
|
|
'postgres' => 'pgrep -cf postgres | xargs -I{} echo "pg:{}"',
|
|
'html_count' => 'ls /var/www/html/*.html 2>/dev/null | wc -l | xargs -I{} echo "pages:{}"',
|
|
'hubs_count' => 'ls /var/www/html/*hub*.html /var/www/html/*dashboard*.html 2>/dev/null | wc -l | xargs -I{} echo "hubs:{}"',
|
|
'intents_pending' => 'ls /var/www/html/api/wired-pending/*.php 2>/dev/null | wc -l | xargs -I{} echo "intents:{}"',
|
|
'git_dirty' => 'cd /var/www/html && git status -s 2>/dev/null | wc -l | xargs -I{} echo "dirty:{}"',
|
|
'git_head' => 'cd /var/www/html && git log --format=%h -1 2>/dev/null',
|
|
'vault_count' => 'ls /opt/wevads/vault/ 2>/dev/null | wc -l | xargs -I{} echo "vault:{}"',
|
|
'wiki_count' => 'ls /var/www/html/wiki/ 2>/dev/null | wc -l | xargs -I{} echo "wiki:{}"',
|
|
'docker' => 'docker ps --format "{{.Names}}" 2>/dev/null | wc -l | xargs -I{} echo "containers:{}"',
|
|
'ollama_procs' => 'pgrep -cf ollama | xargs -I{} echo "ollama:{}"',
|
|
'chrome_procs_v77' => 'pgrep -cf chrome | xargs -I{} echo "chrome:{}"',
|
|
'ports_listen' => 'ss -tln 2>/dev/null | grep -c LISTEN | xargs -I{} echo "ports:{}"',
|
|
'nonreg_score' => 'cat /var/www/html/api/nonreg-latest.json 2>/dev/null | grep -oE \'"score":[0-9.]+\' | head -1',
|
|
'sovereign_port' => 'ss -tln 2>/dev/null | grep -c ":4000" | xargs -I{} echo "sov:{}"',
|
|
'qdrant_port' => 'ss -tln 2>/dev/null | grep -c ":6333" | xargs -I{} echo "qdrant:{}"',
|
|
'truth_registry_kb' => 'stat -c %s /var/www/html/api/wevia-truth-registry.json 2>/dev/null | awk \'{print "kb:"int($1/1024)}\'',
|
|
'blade_pending' => 'ls /var/www/html/api/blade-tasks/*.json 2>/dev/null | wc -l | xargs -I{} echo "tasks:{}"',
|
|
'blade_scripts' => 'ls /opt/weval-l99/wevia-blade-*.sh 2>/dev/null | wc -l | xargs -I{} echo "scripts:{}"',
|
|
'token_keys' => 'ls /var/www/html/api/blade-tasks/key_*.json 2>/dev/null | wc -l | xargs -I{} echo "keys:{}"',
|
|
'selenium_drv' => 'which chromedriver 2>/dev/null || echo MISSING',
|
|
'pages_500' => 'C=0; for p in index enterprise-model architecture sales-hub erp-launchpad agents-archi; do CODE=$(curl -sk --max-time 1 -o/dev/null -w "%{http_code}" http://127.0.0.1:5890/$p.html -H "Host: weval-consulting.com"); [ "$CODE" != "200" ] && [ "$CODE" != "302" ] && C=$((C+1)); done; echo "errs:$C"',
|
|
'paperclip_api' => 'curl -sk --max-time 2 http://127.0.0.1/api/paperclip-agents-api.php 2>/dev/null | grep -oE \'"agents":[0-9]+\' | head -1',
|
|
'deerflow_port' => 'ss -tln 2>/dev/null | grep -c ":3000" | xargs -I{} echo "deerflow:{}"',
|
|
];
|
|
|
|
/* Analyze message: which capability keywords match? */
|
|
$V78_MATCHED_KEYS = [];
|
|
foreach ($V78_MATRIX as $key => $agents) {
|
|
if (stripos($V78_LOW, $key) !== false) {
|
|
$V78_MATCHED_KEYS[$key] = $agents;
|
|
}
|
|
}
|
|
|
|
/* Collect unique agents to run */
|
|
$V78_AGENTS_TO_RUN = [];
|
|
foreach ($V78_MATCHED_KEYS as $key => $agents) {
|
|
foreach ($agents as $a) {
|
|
if (isset($V78_AGENT_DEFS[$a])) {
|
|
$V78_AGENTS_TO_RUN[$a] = $V78_AGENT_DEFS[$a];
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If nothing matched, default to health + truth */
|
|
if (empty($V78_AGENTS_TO_RUN)) {
|
|
foreach (['load','disk','memory','v76_autonomy_score','nonreg_score','git_head'] as $a) {
|
|
$V78_AGENTS_TO_RUN[$a] = $V78_AGENT_DEFS[$a];
|
|
}
|
|
$V78_MATCHED_KEYS['default'] = ['(santé globale)'];
|
|
}
|
|
|
|
/* Execute in parallel */
|
|
header('Content-Type: text/event-stream');
|
|
header('Cache-Control: no-cache');
|
|
header('X-Accel-Buffering: no');
|
|
|
|
function sse_v78($data) {
|
|
echo 'data: ' . json_encode($data) . "\n\n";
|
|
@ob_flush(); @flush();
|
|
}
|
|
|
|
sse_v78([
|
|
'type'=>'start',
|
|
'task'=>'V78 Capability Dispatcher',
|
|
'message'=>$V78_MSG,
|
|
'matched_keys'=>array_keys($V78_MATCHED_KEYS),
|
|
'agents_selected'=>count($V78_AGENTS_TO_RUN),
|
|
'agents_names'=>array_keys($V78_AGENTS_TO_RUN),
|
|
'ts'=>date('H:i:s')
|
|
]);
|
|
|
|
$V78_WORKDIR = '/tmp/v78_' . time() . '_' . bin2hex(random_bytes(3));
|
|
@mkdir($V78_WORKDIR, 0755, true);
|
|
$t_start = microtime(true);
|
|
$pids = [];
|
|
|
|
foreach ($V78_AGENTS_TO_RUN as $id => $cmd) {
|
|
$outfile = "{$V78_WORKDIR}/{$id}.out";
|
|
@shell_exec("timeout 3 bash -c " . escapeshellarg($cmd) . " > $outfile 2>&1 &");
|
|
$pids[$id] = $outfile;
|
|
}
|
|
|
|
$deadline = microtime(true) + 8;
|
|
$done = [];
|
|
while (microtime(true) < $deadline && count($done) < count($pids)) {
|
|
foreach ($pids as $id => $outfile) {
|
|
if (isset($done[$id])) continue;
|
|
if (!file_exists($outfile)) continue;
|
|
clearstatcache(true, $outfile);
|
|
$age_ms = (microtime(true) - filemtime($outfile)) * 1000;
|
|
if ($age_ms < 50) continue;
|
|
$out = @file_get_contents($outfile);
|
|
$done[$id] = trim($out) ?: '(empty)';
|
|
sse_v78(['type'=>'agent','id'=>$id,'result'=>substr($done[$id],0,400),'progress'=>round(count($done)/count($pids)*100)]);
|
|
}
|
|
usleep(80000);
|
|
}
|
|
|
|
foreach ($pids as $id => $outfile) {
|
|
if (!isset($done[$id])) {
|
|
$done[$id] = 'TIMEOUT';
|
|
sse_v78(['type'=>'agent','id'=>$id,'result'=>'TIMEOUT','progress'=>100]);
|
|
}
|
|
}
|
|
|
|
$elapsed_ms = round((microtime(true) - $t_start) * 1000);
|
|
$ok = count(array_filter($done, function($v){return $v !== 'TIMEOUT' && $v !== '(empty)';}));
|
|
|
|
sse_v78([
|
|
'type'=>'done',
|
|
'agents_selected'=>count($V78_AGENTS_TO_RUN),
|
|
'agents_ok'=>$ok,
|
|
'matched_capabilities'=>array_keys($V78_MATCHED_KEYS),
|
|
'elapsed_ms'=>$elapsed_ms,
|
|
'token_efficiency'=>'selective vs V77 full',
|
|
'note'=>"Dispatcher matched " . count($V78_MATCHED_KEYS) . " capability keywords → " . count($V78_AGENTS_TO_RUN) . " agents in " . $elapsed_ms . "ms"
|
|
]);
|
|
exit;
|