diff --git a/api/blade-tasks/task_20260418120501_a73eed.json b/api/blade-tasks/task_20260418120501_a73eed.json new file mode 100644 index 000000000..436775375 --- /dev/null +++ b/api/blade-tasks/task_20260418120501_a73eed.json @@ -0,0 +1,11 @@ +{ + "id": "task_20260418120501_a73eed", + "name": "Blade self-heal 14:05", + "type": "powershell", + "command": "\n# Blade self-heal\nWrite-Host \"Self-heal triggered $(Get-Date)\"\n$agentProc = Get-Process powershell | Where-Object { $_.CommandLine -match 'sentinel-agent' }\nif (!$agentProc) {\n Write-Host \"Agent not running, starting...\"\n Start-Process powershell -ArgumentList \"-ExecutionPolicy\",\"Bypass\",\"-File\",\"C:\\ProgramData\\WEVAL\\sentinel-agent.ps1\" -WindowStyle Hidden\n}\n# Clear stale tasks > 3 days locally\n$cutoff = (Get-Date).AddDays(-3)\nGet-ChildItem \"C:\\ProgramData\\WEVAL\\tasks\\*.json\" -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt $cutoff } | Move-Item -Destination \"C:\\ProgramData\\WEVAL\\tasks\\archived\\\" -Force -ErrorAction SilentlyContinue\nWrite-Host \"Self-heal complete\"\n", + "cmd": "\n# Blade self-heal\nWrite-Host \"Self-heal triggered $(Get-Date)\"\n$agentProc = Get-Process powershell | Where-Object { $_.CommandLine -match 'sentinel-agent' }\nif (!$agentProc) {\n Write-Host \"Agent not running, starting...\"\n Start-Process powershell -ArgumentList \"-ExecutionPolicy\",\"Bypass\",\"-File\",\"C:\\ProgramData\\WEVAL\\sentinel-agent.ps1\" -WindowStyle Hidden\n}\n# Clear stale tasks > 3 days locally\n$cutoff = (Get-Date).AddDays(-3)\nGet-ChildItem \"C:\\ProgramData\\WEVAL\\tasks\\*.json\" -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt $cutoff } | Move-Item -Destination \"C:\\ProgramData\\WEVAL\\tasks\\archived\\\" -Force -ErrorAction SilentlyContinue\nWrite-Host \"Self-heal complete\"\n", + "priority": "high", + "status": "pending", + "created": "2026-04-18T12:05:01+00:00", + "created_by": "blade-control-ui" +} \ No newline at end of file diff --git a/api/em-kpi-cache.json b/api/em-kpi-cache.json index c68d7ebf4..aada94287 100644 --- a/api/em-kpi-cache.json +++ b/api/em-kpi-cache.json @@ -1,281 +1,7 @@ -{ - "ts": "2026-04-18T12:00:01+00:00", - "server": "s204", - "s204": { - "load": 0.8, - "uptime": "2026-04-14 11:51:24", - "ram_total_mb": 31335, - "ram_used_mb": 5999, - "ram_free_mb": 25335, - "disk_total": "150G", - "disk_used": "114G", - "disk_free": "31G", - "disk_pct": "79%", - "fpm_workers": 100, - "docker_containers": 19, - "cpu_cores": 8 - }, - "s95": { - "load": 1.86, - "disk_pct": "88%", - "status": "UP", - "ram_total_mb": 15610, - "ram_free_mb": 11449 - }, - "pmta": [ - { - "name": "SER6", - "ip": "110.239.84.121", - "status": "DOWN" - }, - { - "name": "SER7", - "ip": "110.239.65.64", - "status": "DOWN" - }, - { - "name": "SER8", - "ip": "182.160.55.107", - "status": "DOWN" - }, - { - "name": "SER9", - "ip": "110.239.86.68", - "status": "DOWN" - } - ], - "assets": { - "html_pages": 241, - "php_apis": 626, - "wiki_entries": 1534, - "vault_doctrines": 58, - "vault_sessions": 14, - "vault_decisions": 12 - }, - "tools": { - "total": 617, - "registry_version": "?" - }, - "sovereign": { - "status": "UP", - "providers": [ - "Cerebras-fast", - "Cerebras-think", - "Groq", - "Cloudflare-AI", - "Gemini", - "SambaNova", - "NVIDIA-NIM", - "Mistral", - "Groq-OSS", - "HF-Space", - "HF-Router", - "OpenRouter", - "GitHub-Models" - ], - "active": 13, - "total": 13, - "primary": "Cerebras-fast", - "cost": "0€" - }, - "ethica": { - "total_hcps": 151709, - "with_email": 110210, - "with_phone": 145787, - "gap_email": 41499, - "pct_email": 72.6, - "pct_phone": 96.1, - "by_country": [ - { - "country": "DZ", - "hcps": 112324, - "with_email": 78181, - "with_tel": 110053, - "pct_email": 69.6, - "pct_tel": 98 - }, - { - "country": "MA", - "hcps": 19709, - "with_email": 15045, - "with_tel": 18717, - "pct_email": 76.3, - "pct_tel": 95 - }, - { - "country": "TN", - "hcps": 17797, - "with_email": 15105, - "with_tel": 17017, - "pct_email": 84.9, - "pct_tel": 95.6 - }, - { - "country": "INTL", - "hcps": 1879, - "with_email": 1879, - "with_tel": 0, - "pct_email": 100, - "pct_tel": 0 - } - ] - }, - "docker": [ - { - "name": "loki", - "status": "Up 2 days", - "ports": "" - }, - { - "name": "listmonk", - "status": "Up 2 days", - "ports": "" - }, - { - "name": "plausible-plausible-1", - "status": "Up 21 hours", - "ports": "" - }, - { - "name": "plausible-plausible-db-1", - "status": "Up 21 hours", - "ports": "" - }, - { - "name": "plausible-plausible-events-db-1", - "status": "Up 21 hours", - "ports": "" - }, - { - "name": "n8n-docker-n8n-1", - "status": "Up 2 days", - "ports": "" - }, - { - "name": "mattermost-docker-mm-db-1", - "status": "Up 2 days", - "ports": "" - }, - { - "name": "mattermost-docker-mattermost-1", - "status": "Up 2 days (healthy)", - "ports": "" - }, - { - "name": "twenty", - "status": "Up 2 days", - "ports": "" - }, - { - "name": "twenty-redis", - "status": "Up 2 days", - "ports": "" - }, - { - "name": "langfuse", - "status": "Up 2 days", - "ports": "" - }, - { - "name": "redis-weval", - "status": "Up 3 days", - "ports": "" - }, - { - "name": "gitea", - "status": "Up 3 days", - "ports": "" - }, - { - "name": "node-exporter", - "status": "Up 3 days", - "ports": "" - }, - { - "name": "prometheus", - "status": "Up 3 days", - "ports": "" - }, - { - "name": "searxng", - "status": "Up 3 days", - "ports": "" - }, - { - "name": "uptime-kuma", - "status": "Up 3 days (healthy)", - "ports": "" - }, - { - "name": "vaultwarden", - "status": "Up 3 days (healthy)", - "ports": "" - }, - { - "name": "qdrant", - "status": "Up 3 days", - "ports": "" - } - ], - "crons": { - "active": 14 - }, - "git": { - "head": "eee80eae AUTO-BACKUP 20260418-1400", - "dirty": 4, - "status": "DIRTY" - }, - "nonreg": { - "total": 153, - "passed": 153, - "score": "100%" - }, - "services": [ - { - "name": "DeerFlow", - "port": 3002, - "status": "UP" - }, - { - "name": "DeerFlow API", - "port": 8001, - "status": "UP" - }, - { - "name": "Qdrant", - "port": 6333, - "status": "UP" - }, - { - "name": "Ollama", - "port": 11434, - "status": "UP" - }, - { - "name": "Redis", - "port": 6379, - "status": "UP" - }, - { - "name": "Sovereign", - "port": 4000, - "status": "UP" - }, - { - "name": "SearXNG", - "port": 8080, - "status": "UP" - } - ], - "whisper": { - "binary": "COMPILED", - "model": "142MB" - }, - "grand_total": 3095, - "health": { - "score": 5, - "max": 6, - "pct": 83 - }, - "elapsed_ms": 9026 -} \ No newline at end of file + +500 Internal Server Error + +

500 Internal Server Error

+
nginx/1.24.0 (Ubuntu)
+ + diff --git a/api/v83-business-kpi-latest.json b/api/v83-business-kpi-latest.json index 79bc4e104..3566862d8 100644 --- a/api/v83-business-kpi-latest.json +++ b/api/v83-business-kpi-latest.json @@ -1,7 +1,7 @@ { "ok": true, "version": "V83-business-kpi", - "ts": "2026-04-18T12:00:17+00:00", + "ts": "2026-04-18T12:03:22+00:00", "summary": { "total_categories": 7, "total_kpis": 56, diff --git a/api/wevia-dynamic-resolver.php b/api/wevia-dynamic-resolver.php index 078ffef62..517758520 100644 --- a/api/wevia-dynamic-resolver.php +++ b/api/wevia-dynamic-resolver.php @@ -24,7 +24,7 @@ function wevia_resolve($msg) { if (@preg_match('/' . $tool['kw'] . '/i', $msg_lower)) { $score = 10; } else { - $keywords = preg_split('/[|.*()]+/', $tool['kw']); + $keywords = preg_split('/[|.*()]+/', $tool['kw']); $keywords = array_unique(array_filter(array_map(function($k){ return trim(mb_strtolower($k)); }, $keywords))); /* V84_DEDUPE_FUZZY */ $matched_keywords = 0; foreach ($keywords as $kw) { $kw = trim($kw); diff --git a/api/wevia-dynamic-resolver.php.GOLD-20260418-140228-pre-v84-dedupe b/api/wevia-dynamic-resolver.php.GOLD-20260418-140228-pre-v84-dedupe new file mode 100644 index 000000000..078ffef62 --- /dev/null +++ b/api/wevia-dynamic-resolver.php.GOLD-20260418-140228-pre-v84-dedupe @@ -0,0 +1,91 @@ + 0 && mb_strlen($msg_lower) > 60 && preg_match("/reconcil|diagnostic|bilan|test_global/", $tool["id"] ?? "")) $score += 1; + + if ($score > $best_score || ($score == $best_score && !empty($tool["cmd"]) && empty($best["cmd"]))) { + $second_best_score = $best_score; + $best_score = $score; + $best = $tool; + } elseif ($score > $second_best_score) { + $second_best_score = $score; + } + } + + // HARDENING: seuil relevé de 3 à 6 (exige regex exact score=10 OU 3 keywords matches score=6) + // Évite fuzzy-match abusif type "plus" → ports.sh + if (!$best || $best_score < 6) { + // Retourner suggestion au lieu de null si score "moyen" (3-5) + if ($best && $best_score >= 3) { + return [ + 'provider' => 'dynamic-resolver', + 'content' => "Je n'ai pas bien compris votre demande. Vous vouliez peut-être :\n • " . ($best['id'] ?? 'unknown') . " (demandez : \"" . ($best['kw'] ?? '') . "\")\n\nSi ce n'est pas ça, essayez :\n • \"candidats dashboard\" — stats recrutement\n • \"facturation mission\" — missions & TJM\n • \"etat du systeme\" — vue globale\n • \"andons actifs\" — alertes en cours", + 'tool' => 'disambiguation' + ]; + } + return null; + } + + // HARDENING: si 2 tools ont scores très proches (diff <= 1) ET regex non-exact, demander clarification + if ($best_score < 10 && $second_best_score >= $best_score - 1 && $second_best_score >= 4) { + return [ + 'provider' => 'dynamic-resolver', + 'content' => "Votre demande est ambiguë (plusieurs interprétations possibles). Précisez svp :\n • Pour la situation business → \"etat du systeme\", \"candidats dashboard\", \"facturation mission\"\n • Pour l'infra → \"etat global\", \"andons actifs\", \"verify l99\"", + 'tool' => 'ambiguous' + ]; + } + + $result = ''; + if (!empty($best['cmd'])) { + $result = shell_exec('sudo timeout 15 bash -c ' . escapeshellarg($best['cmd']) . ' 2>&1') ?? ''; + if (trim($result) === '') $result = '[timeout 15s] Commande lente. Essayez plus ciblé.'; + } elseif (strpos($best['api'] ?? '', 'GET:') === 0) { + $ctx = stream_context_create(['http' => ['timeout' => 4]]); + $result = @file_get_contents('http://127.0.0.1' . substr($best['api'], 4), false, $ctx) ?? ''; + } elseif (strpos($best['api'] ?? '', 'POST:') === 0) { + $ctx = stream_context_create(['http' => ['method' => 'POST', 'timeout' => 4]]); + $result = @file_get_contents('http://127.0.0.1' . substr($best['api'], 5), false, $ctx) ?? ''; + } + if (!$result) return ["provider"=>"dynamic-resolver","content"=>"[" . ($best["id"] ?? "tool") . "] pas de reponse (timeout ou service down)","tool"=>$best["id"]??"unknown"]; + return ['provider' => 'dynamic-resolver', 'content' => trim($result), 'tool' => $best['id'] ?? 'unknown']; +} +function wevia_dynamic_resolve($msg) { return wevia_resolve($msg); } \ No newline at end of file diff --git a/api/wevia-dynamic-resolver.php.GOLD-20260418-140305-pre-v84-dedupe b/api/wevia-dynamic-resolver.php.GOLD-20260418-140305-pre-v84-dedupe new file mode 100644 index 000000000..078ffef62 --- /dev/null +++ b/api/wevia-dynamic-resolver.php.GOLD-20260418-140305-pre-v84-dedupe @@ -0,0 +1,91 @@ + 0 && mb_strlen($msg_lower) > 60 && preg_match("/reconcil|diagnostic|bilan|test_global/", $tool["id"] ?? "")) $score += 1; + + if ($score > $best_score || ($score == $best_score && !empty($tool["cmd"]) && empty($best["cmd"]))) { + $second_best_score = $best_score; + $best_score = $score; + $best = $tool; + } elseif ($score > $second_best_score) { + $second_best_score = $score; + } + } + + // HARDENING: seuil relevé de 3 à 6 (exige regex exact score=10 OU 3 keywords matches score=6) + // Évite fuzzy-match abusif type "plus" → ports.sh + if (!$best || $best_score < 6) { + // Retourner suggestion au lieu de null si score "moyen" (3-5) + if ($best && $best_score >= 3) { + return [ + 'provider' => 'dynamic-resolver', + 'content' => "Je n'ai pas bien compris votre demande. Vous vouliez peut-être :\n • " . ($best['id'] ?? 'unknown') . " (demandez : \"" . ($best['kw'] ?? '') . "\")\n\nSi ce n'est pas ça, essayez :\n • \"candidats dashboard\" — stats recrutement\n • \"facturation mission\" — missions & TJM\n • \"etat du systeme\" — vue globale\n • \"andons actifs\" — alertes en cours", + 'tool' => 'disambiguation' + ]; + } + return null; + } + + // HARDENING: si 2 tools ont scores très proches (diff <= 1) ET regex non-exact, demander clarification + if ($best_score < 10 && $second_best_score >= $best_score - 1 && $second_best_score >= 4) { + return [ + 'provider' => 'dynamic-resolver', + 'content' => "Votre demande est ambiguë (plusieurs interprétations possibles). Précisez svp :\n • Pour la situation business → \"etat du systeme\", \"candidats dashboard\", \"facturation mission\"\n • Pour l'infra → \"etat global\", \"andons actifs\", \"verify l99\"", + 'tool' => 'ambiguous' + ]; + } + + $result = ''; + if (!empty($best['cmd'])) { + $result = shell_exec('sudo timeout 15 bash -c ' . escapeshellarg($best['cmd']) . ' 2>&1') ?? ''; + if (trim($result) === '') $result = '[timeout 15s] Commande lente. Essayez plus ciblé.'; + } elseif (strpos($best['api'] ?? '', 'GET:') === 0) { + $ctx = stream_context_create(['http' => ['timeout' => 4]]); + $result = @file_get_contents('http://127.0.0.1' . substr($best['api'], 4), false, $ctx) ?? ''; + } elseif (strpos($best['api'] ?? '', 'POST:') === 0) { + $ctx = stream_context_create(['http' => ['method' => 'POST', 'timeout' => 4]]); + $result = @file_get_contents('http://127.0.0.1' . substr($best['api'], 5), false, $ctx) ?? ''; + } + if (!$result) return ["provider"=>"dynamic-resolver","content"=>"[" . ($best["id"] ?? "tool") . "] pas de reponse (timeout ou service down)","tool"=>$best["id"]??"unknown"]; + return ['provider' => 'dynamic-resolver', 'content' => trim($result), 'tool' => $best['id'] ?? 'unknown']; +} +function wevia_dynamic_resolve($msg) { return wevia_resolve($msg); } \ No newline at end of file diff --git a/oss-discovery.html b/oss-discovery.html index c05d20ab6..1589d2cfe 100644 --- a/oss-discovery.html +++ b/oss-discovery.html @@ -164,7 +164,7 @@ function render(d,tools,sk){
🧩 All Injected Skills
${sk.total||0}
${(sk.path||"skills")+"/"}
-
${Array.isArray(sk.skills)?sk.skills.map(s=>`
${s.slug||s.name||s}
`).join(''):(sk.total>0||sk.skills)?`
📁 ${sk.total||(sk.skills&&sk.skills.total)||0} skills disponibles dans /skills/ — parcourir
`:'
Chargement...
'}
+
${Array.isArray(sk.skills)?sk.skills.map(s=>`
${s.slug||s.name||s}
`).join(''):(sk.total>0||sk.skills)?`
📁 ${sk.total||(sk.skills&&sk.skills.total)||0} skills disponibles dans /skills/ — parcourir
`:`
📁 ${(sk&&sk.total)||0} skills disponibles dans /skills/ — parcourir
`}
`; diff --git a/oss-discovery.html.GOLD-20260418-140415-pre-v84-defensive b/oss-discovery.html.GOLD-20260418-140415-pre-v84-defensive new file mode 100644 index 000000000..c05d20ab6 --- /dev/null +++ b/oss-discovery.html.GOLD-20260418-140415-pre-v84-defensive @@ -0,0 +1,300 @@ + + + + + +WEVAL — OSS Discovery + + + + +
#9889; 669 Agents
#127970; 22 Depts
#128051; 20 Docker
#129302; 10 Ollama
#128200; 153/153
#128274; SSO OK
+
+
+ +

OSS Discovery

Sovereign Skill Learning Engine v2.0
+
+
+ + + ● Live +
+
+

Chargement...

+ + + +