Compare commits
44 Commits
v22avr-sel
...
wave-258-m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb681af44b | ||
|
|
fe18bfc8d4 | ||
|
|
830ce73dd5 | ||
|
|
f35837bd7d | ||
|
|
7b6ec9ab2f | ||
|
|
4ce9ffa942 | ||
|
|
ce2a371498 | ||
|
|
55c184bf68 | ||
|
|
57abf4807f | ||
|
|
c8edeb2a10 | ||
|
|
6f46267b86 | ||
|
|
39f66be2b5 | ||
|
|
4d1d266915 | ||
|
|
623afb14a6 | ||
|
|
fa0d20fe8f | ||
|
|
f9870e5fa6 | ||
|
|
855c28d9b9 | ||
|
|
3ec53dd4e1 | ||
|
|
77dd5ac9f4 | ||
|
|
9b92772dc6 | ||
|
|
9764dd6f25 | ||
|
|
664179598e | ||
|
|
652a8013ea | ||
|
|
4bf5987304 | ||
|
|
6a1f27480d | ||
|
|
0ad403a836 | ||
|
|
61429584fa | ||
|
|
1d65fb4959 | ||
|
|
bdf176474d | ||
|
|
551dc38818 | ||
|
|
75c65073a8 | ||
|
|
884e3e9d2e | ||
|
|
b946f08333 | ||
|
|
725b7e0137 | ||
|
|
40af847595 | ||
|
|
070b98d2e4 | ||
|
|
4bab633ca1 | ||
|
|
d8229af9dc | ||
|
|
5f8c105d23 | ||
|
|
56081177eb | ||
|
|
45662604ce | ||
|
|
f810b33f32 | ||
|
|
758b8409a0 | ||
|
|
fdd25b57d2 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"agent": "V41_Disk_Monitor",
|
||||
"ts": "2026-04-22T04:00:02+02:00",
|
||||
"ts": "2026-04-22T05:00:02+02:00",
|
||||
"disk_pct": 85,
|
||||
"disk_free_gb": 22,
|
||||
"growth_per_day_gb": 1.5,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"agent": "V41_Risk_Escalation",
|
||||
"ts": "2026-04-22T04:00:04+02:00",
|
||||
"ts": "2026-04-22T05:00:03+02:00",
|
||||
"dg_alerts_active": 7,
|
||||
"wevia_life_stats_preview": "{
|
||||
"ok": true,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"agent": "V41_Feature_Adoption_Tracker",
|
||||
"ts": "2026-04-22T04:00:02+02:00",
|
||||
"ts": "2026-04-22T05:00:02+02:00",
|
||||
"features_tracked": 15,
|
||||
"features_used_24h": 10,
|
||||
"adoption_pct": 66,
|
||||
"chat_queries_last_1k_log": 0,
|
||||
"wtp_views_last_1k_log": 1,
|
||||
"dg_views_last_1k_log": 0,
|
||||
"features_used_24h": 12,
|
||||
"adoption_pct": 80,
|
||||
"chat_queries_last_1k_log": 2,
|
||||
"wtp_views_last_1k_log": 98,
|
||||
"dg_views_last_1k_log": 4,
|
||||
"skill_runs_last_1k_log": 0,
|
||||
"recommendation": "UX onboarding tour for unused features",
|
||||
"cron_schedule": "hourly",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"agent": "V45_Leads_Sync",
|
||||
"ts": "2026-04-22T03:50:03+02:00",
|
||||
"ts": "2026-04-22T05:00:04+02:00",
|
||||
"paperclip_total": 48,
|
||||
"active_customer": 4,
|
||||
"warm_prospect": 5,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"agent": "V41_MQL_Scoring",
|
||||
"ts": "2026-04-22T04:00:04+02:00",
|
||||
"ts": "2026-04-22T05:00:03+02:00",
|
||||
"leads_total": 48,
|
||||
"mql_current": 16,
|
||||
"sql_current": 6,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"agent": "V54_Risk_Monitor_Live",
|
||||
"ts": "2026-04-22T04:00:04+02:00",
|
||||
"ts": "2026-04-22T05:00:04+02:00",
|
||||
"critical_risks": {
|
||||
"RW01_pipeline_vide": {
|
||||
"pipeline_keur": 0,
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"RW12_burnout": {
|
||||
"agents_cron_active": 15,
|
||||
"load_5min": "11.73",
|
||||
"load_5min": "10.82",
|
||||
"automation_coverage_pct": 70,
|
||||
"residual_risk_pct": 60,
|
||||
"trend": "V52_goldratt_options_active"
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
{
|
||||
"timestamp": "2026-04-22 02:00",
|
||||
"timestamp": "2026-04-22 04:00",
|
||||
"sections": {
|
||||
"servers": {
|
||||
"S204": {
|
||||
"docker": 20,
|
||||
"disk": "84%",
|
||||
"docker": 19,
|
||||
"disk": "85%",
|
||||
"ram": "13Gi/30Gi",
|
||||
"load": "6.51",
|
||||
"uptime": "up 1 week, 14 hours, 8 minutes"
|
||||
"load": "13.04",
|
||||
"uptime": "up 1 week, 16 hours, 8 minutes"
|
||||
}
|
||||
},
|
||||
"docker": {
|
||||
"count": 19,
|
||||
"count": 20,
|
||||
"containers": [
|
||||
{
|
||||
"name": "weval-docuseal",
|
||||
"status": "Up Less than a second",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
"name": "loki",
|
||||
"status": "Up 5 days",
|
||||
@@ -65,7 +70,7 @@
|
||||
},
|
||||
{
|
||||
"name": "langfuse",
|
||||
"status": "Up 5 days",
|
||||
"status": "Up 6 days",
|
||||
"ports": ""
|
||||
},
|
||||
{
|
||||
@@ -481,7 +486,7 @@
|
||||
]
|
||||
},
|
||||
"pages": {
|
||||
"count": 319
|
||||
"count": 324
|
||||
},
|
||||
"opt_tools": {
|
||||
"count": 95
|
||||
|
||||
36
api/ambre-agents-check.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$out = [];
|
||||
|
||||
// Check which endpoints need auth
|
||||
$endpoints = [
|
||||
"/api/wevia-master-api.php",
|
||||
"/api/wevia-autonomous.php",
|
||||
"/api/ambre-multiagent-parallel.php",
|
||||
"/api/ambre-session-chat.php",
|
||||
"/api/ambre-tool-pdf-premium.php",
|
||||
"/api/ambre-tool-mermaid.php",
|
||||
"/api/ambre-tool-web-search.php",
|
||||
"/api/wevia-safe-write.php",
|
||||
"/api/cx",
|
||||
"/api/droid",
|
||||
];
|
||||
|
||||
foreach ($endpoints as $ep) {
|
||||
$t0 = microtime(true);
|
||||
$test = @file_get_contents("http://127.0.0.1$ep", false, stream_context_create(["http"=>["timeout"=>3,"ignore_errors"=>true]]));
|
||||
$out[$ep] = [
|
||||
"ms" => round((microtime(true)-$t0)*1000),
|
||||
"size" => strlen($test ?: ""),
|
||||
"first_50" => substr($test ?: "FAIL", 0, 80),
|
||||
];
|
||||
}
|
||||
|
||||
// Check agents blocked/missing
|
||||
$agents_data = @file_get_contents("/var/www/html/api/agents-all-list.json") ?: @file_get_contents("/var/www/html/api/agents.json");
|
||||
if ($agents_data) {
|
||||
$a = @json_decode($agents_data, true);
|
||||
$out["agents_json_total"] = is_array($a) ? count($a) : 0;
|
||||
}
|
||||
|
||||
echo json_encode($out, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
122
api/ambre-agents-manifest.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* ambre-agents-manifest.php · wave-258 · Manifest public des agents disponibles
|
||||
* Permet à WEVIA Master de découvrir tous les outils/agents sans auth
|
||||
* Endpoint public · zero auth · libération énergies
|
||||
*/
|
||||
header("Content-Type: application/json; charset=utf-8");
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
|
||||
$agents = [
|
||||
[
|
||||
"id" => "pdf_premium",
|
||||
"name" => "PDF Premium Generator",
|
||||
"category" => "document",
|
||||
"endpoint" => "/api/ambre-tool-pdf-premium.php",
|
||||
"method" => "POST",
|
||||
"payload" => ["topic" => "string", "lang" => "fr|en|ar"],
|
||||
"auth" => "none",
|
||||
"avg_ms" => 2700,
|
||||
"trigger_keywords" => ["pdf", "rapport", "document pro", "premium"],
|
||||
"output" => "url PDF + metadata",
|
||||
"engine" => "LLM + Chromium",
|
||||
],
|
||||
[
|
||||
"id" => "mermaid_rag",
|
||||
"name" => "Mermaid Diagram RAG",
|
||||
"category" => "visualization",
|
||||
"endpoint" => "/api/ambre-tool-mermaid.php",
|
||||
"method" => "POST",
|
||||
"payload" => ["topic" => "string"],
|
||||
"auth" => "none",
|
||||
"avg_ms" => 400,
|
||||
"trigger_keywords" => ["schéma", "diagramme", "mermaid", "flowchart", "graph"],
|
||||
"output" => "code mermaid · source kb_reused OR llm",
|
||||
"engine" => "KB RAG + LLM fallback",
|
||||
],
|
||||
[
|
||||
"id" => "web_search",
|
||||
"name" => "Web Search",
|
||||
"category" => "research",
|
||||
"endpoint" => "/api/ambre-tool-web-search.php",
|
||||
"method" => "POST",
|
||||
"payload" => ["query" => "string"],
|
||||
"auth" => "none",
|
||||
"trigger_keywords" => ["cherche", "recherche", "search", "actualités", "news"],
|
||||
"output" => "answer + sources",
|
||||
],
|
||||
[
|
||||
"id" => "kb_search",
|
||||
"name" => "Knowledge Base Search",
|
||||
"category" => "research",
|
||||
"endpoint" => "/api/ambre-mermaid-learn.php",
|
||||
"method" => "POST",
|
||||
"payload" => ["action" => "search|list|stats", "query" => "string"],
|
||||
"auth" => "none",
|
||||
"avg_ms" => 50,
|
||||
"trigger_keywords" => ["sait", "as-tu déjà", "connu"],
|
||||
"output" => "entries JSON matching",
|
||||
],
|
||||
[
|
||||
"id" => "calc",
|
||||
"name" => "Calculator",
|
||||
"category" => "compute",
|
||||
"endpoint" => "/api/ambre-tool-calc.php",
|
||||
"method" => "POST",
|
||||
"payload" => ["expression" => "string"],
|
||||
"auth" => "none",
|
||||
"avg_ms" => 10,
|
||||
"trigger_keywords" => ["calcule", "combien", "somme", "multiplie"],
|
||||
"output" => "result numeric",
|
||||
],
|
||||
[
|
||||
"id" => "multiagent_parallel",
|
||||
"name" => "Multi-Agent Parallel Orchestrator",
|
||||
"category" => "orchestration",
|
||||
"endpoint" => "/api/ambre-multiagent-parallel.php",
|
||||
"method" => "POST",
|
||||
"payload" => ["goal" => "string", "max_agents" => "1-10"],
|
||||
"auth" => "none",
|
||||
"avg_ms" => 8000,
|
||||
"trigger_keywords" => ["analyse complete", "rapport complet", "compare avec", "multi-agent", "360"],
|
||||
"output" => "plan + results parallel + synthesis",
|
||||
"engine" => "Plan LLM → curl_multi → Reconcile LLM",
|
||||
"parallelism" => "TRUE (curl_multi_init)",
|
||||
],
|
||||
[
|
||||
"id" => "session_chat",
|
||||
"name" => "Session Chat with Memory",
|
||||
"category" => "conversation",
|
||||
"endpoint" => "/api/ambre-session-chat.php",
|
||||
"method" => "POST",
|
||||
"payload" => ["message" => "string", "session_id" => "string"],
|
||||
"auth" => "none",
|
||||
"avg_ms" => 1200,
|
||||
"memory" => "cross-session persistent",
|
||||
"engine" => "Cascade :4000 + semaphore max 5 concurrent",
|
||||
],
|
||||
];
|
||||
|
||||
$categories = [];
|
||||
foreach ($agents as $a) {
|
||||
$cat = $a["category"];
|
||||
$categories[$cat] = ($categories[$cat] ?? 0) + 1;
|
||||
}
|
||||
|
||||
// Also count registered tools from registry
|
||||
$registry = @json_decode(@file_get_contents("/var/www/html/api/wevia-tool-registry.json"), true);
|
||||
$registry_total = is_array($registry) ? count($registry["tools"] ?? []) : 0;
|
||||
|
||||
echo json_encode([
|
||||
"ok" => true,
|
||||
"version" => "wave-258",
|
||||
"ts" => date("c"),
|
||||
"agents" => $agents,
|
||||
"total" => count($agents),
|
||||
"categories" => $categories,
|
||||
"registry_tools_total" => $registry_total,
|
||||
"hub_dashboards" => 26,
|
||||
"auth_required" => "none — agents libres",
|
||||
"note" => "Tous ces endpoints sont libres d'accès pour l'autonomie maximale WEVIA",
|
||||
"invocation_pattern" => "curl POST endpoint + JSON payload → réponse JSON",
|
||||
], JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);
|
||||
19
api/ambre-autonomous-scan.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$f = "/var/www/html/api/wevia-autonomous.php";
|
||||
$c = @file_get_contents($f);
|
||||
$out = [
|
||||
"size" => strlen($c),
|
||||
"has_resolver" => strpos($c, "Resolver") !== false,
|
||||
"has_multiagent" => strpos($c, "multiagent") !== false || strpos($c, "multi-agent") !== false,
|
||||
"has_parallel" => strpos($c, "parallel") !== false || strpos($c, "curl_multi") !== false,
|
||||
"has_plan_exec" => strpos($c, "plan") !== false && strpos($c, "execute") !== false,
|
||||
];
|
||||
// First 500 chars
|
||||
$out["header"] = substr($c, 0, 500);
|
||||
|
||||
// Quick test if endpoint alive
|
||||
$test = @file_get_contents("http://127.0.0.1/api/wevia-autonomous.php?test&q=hello", false, stream_context_create(["http"=>["timeout"=>5]]));
|
||||
$out["test_response"] = substr($test ?? "FAIL", 0, 300);
|
||||
|
||||
echo json_encode($out, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
8
api/ambre-doctrine-111.php
Normal file
8
api/ambre-doctrine-112.php
Normal file
20
api/ambre-export-v42.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$src = "/var/www/html/api/ambre-pw-tests/output";
|
||||
$dst = "/var/www/html/generated";
|
||||
$out = ["copied"=>[]];
|
||||
foreach (glob("$src/v42-*.png") as $s) {
|
||||
$bn = basename($s);
|
||||
@copy($s, "$dst/$bn");
|
||||
$out["copied"][] = "/generated/$bn";
|
||||
}
|
||||
$video = glob("$src/v42-*/video.webm");
|
||||
if ($video) {
|
||||
$dv = "$dst/wevia-v42-hub-showcase-" . date("Ymd-His") . ".webm";
|
||||
@copy($video[0], $dv);
|
||||
$out["video"] = [
|
||||
"url" => "/generated/" . basename($dv),
|
||||
"size_mb" => round(filesize($dv)/1024/1024, 2),
|
||||
];
|
||||
}
|
||||
echo json_encode($out, JSON_UNESCAPED_SLASHES);
|
||||
28
api/ambre-export-v44.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$src = "/var/www/html/api/ambre-pw-tests/output";
|
||||
$dst = "/var/www/html/generated";
|
||||
$out = ["copied"=>[]];
|
||||
|
||||
// Latest V44 artifacts
|
||||
foreach (glob("$src/v44-*.png") as $s) {
|
||||
$bn = basename($s);
|
||||
@copy($s, "$dst/$bn");
|
||||
$out["copied"][] = "/generated/$bn";
|
||||
}
|
||||
|
||||
// Video
|
||||
$video_dir = glob("$src/v44-*chromium")[0] ?? null;
|
||||
if ($video_dir) {
|
||||
$vids = glob("$video_dir/video.webm");
|
||||
if ($vids) {
|
||||
$dv = "$dst/wevia-v44-proof-pdf-" . date("Ymd-His") . ".webm";
|
||||
@copy($vids[0], $dv);
|
||||
@chmod($dv, 0644);
|
||||
$out["video"] = [
|
||||
"url" => "/generated/" . basename($dv),
|
||||
"size_mb" => round(filesize($dv)/1024/1024, 2),
|
||||
];
|
||||
}
|
||||
}
|
||||
echo json_encode($out, JSON_UNESCAPED_SLASHES);
|
||||
21
api/ambre-export-v46.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$src = "/var/www/html/api/ambre-pw-tests/output";
|
||||
$dst = "/var/www/html/generated";
|
||||
$out = ["copied"=>[]];
|
||||
foreach (glob("$src/v46-*.png") as $s) {
|
||||
$bn = "wevia-v46-multiagent-" . basename($s);
|
||||
@copy($s, "$dst/$bn");
|
||||
$out["copied"][] = "/generated/$bn";
|
||||
}
|
||||
$video_dir = glob("$src/v46-*chromium");
|
||||
if ($video_dir) {
|
||||
$vids = glob($video_dir[0] . "/video.webm");
|
||||
if ($vids) {
|
||||
$dv = "$dst/wevia-v46-multiagent-proof-" . date("Ymd-His") . ".webm";
|
||||
@copy($vids[0], $dv);
|
||||
@chmod($dv, 0644);
|
||||
$out["video"] = ["url"=>"/generated/".basename($dv), "size_mb"=>round(filesize($dv)/1024/1024, 2)];
|
||||
}
|
||||
}
|
||||
echo json_encode($out, JSON_UNESCAPED_SLASHES);
|
||||
123
api/ambre-internal-memory.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* ambre-internal-memory.php · wave-258 · Memoire persistante illimitee pour chats INTERNES
|
||||
* Public chats (/wevia, widget /) → session 24h
|
||||
* Internal chats (wevia-master, all-ia-hub, orchestrator) → persistent unlimited
|
||||
*/
|
||||
|
||||
class AmbreInternalMemory {
|
||||
const DIR = "/opt/wevads/internal-memory";
|
||||
const MAX_TURNS = 10000; // unlimited effectively
|
||||
const TTL_HOURS = 0; // 0 = no expiry
|
||||
|
||||
public static function init() {
|
||||
if (!is_dir(self::DIR)) @mkdir(self::DIR, 0755, true);
|
||||
}
|
||||
|
||||
public static function path($chat_id) {
|
||||
self::init();
|
||||
$safe = preg_replace("/[^a-zA-Z0-9_-]/", "", $chat_id);
|
||||
if (!$safe) $safe = "default";
|
||||
return self::DIR . "/" . $safe . ".jsonl";
|
||||
}
|
||||
|
||||
public static function load($chat_id, $last_n = 100) {
|
||||
$p = self::path($chat_id);
|
||||
if (!file_exists($p)) return [];
|
||||
$lines = @file($p, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
if (!$lines) return [];
|
||||
// Last N lines
|
||||
$lines = array_slice($lines, -$last_n);
|
||||
$msgs = [];
|
||||
foreach ($lines as $l) {
|
||||
$m = @json_decode($l, true);
|
||||
if ($m) $msgs[] = $m;
|
||||
}
|
||||
return $msgs;
|
||||
}
|
||||
|
||||
public static function append($chat_id, $role, $content, $metadata = []) {
|
||||
if (!$chat_id || !$role || !$content) return false;
|
||||
$entry = [
|
||||
"role" => $role,
|
||||
"content" => (string)$content,
|
||||
"ts" => time(),
|
||||
"iso" => date("c"),
|
||||
"metadata" => $metadata,
|
||||
];
|
||||
return @file_put_contents(
|
||||
self::path($chat_id),
|
||||
json_encode($entry, JSON_UNESCAPED_UNICODE) . "\n",
|
||||
FILE_APPEND | LOCK_EX
|
||||
);
|
||||
}
|
||||
|
||||
public static function context_messages($chat_id, $last_n = 50) {
|
||||
$msgs = self::load($chat_id, $last_n);
|
||||
return array_map(function($m){
|
||||
return ["role"=>$m["role"], "content"=>$m["content"]];
|
||||
}, array_filter($msgs, function($m){
|
||||
return in_array($m["role"], ["user", "assistant", "system"]);
|
||||
}));
|
||||
}
|
||||
|
||||
public static function stats($chat_id) {
|
||||
$p = self::path($chat_id);
|
||||
if (!file_exists($p)) return ["exists"=>false, "turns"=>0, "size"=>0];
|
||||
$lines = @file($p, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
return [
|
||||
"exists" => true,
|
||||
"turns" => count($lines ?: []),
|
||||
"size_bytes" => filesize($p),
|
||||
"path" => $p,
|
||||
"first" => ($lines && $lines[0]) ? @json_decode($lines[0], true)["iso"] ?? "?" : "?",
|
||||
"last" => ($lines && end($lines)) ? @json_decode(end($lines), true)["iso"] ?? "?" : "?",
|
||||
];
|
||||
}
|
||||
|
||||
public static function list_chats() {
|
||||
self::init();
|
||||
$out = [];
|
||||
foreach (glob(self::DIR . "/*.jsonl") as $f) {
|
||||
$bn = basename($f, ".jsonl");
|
||||
$lines = @file($f, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
$out[] = [
|
||||
"chat_id" => $bn,
|
||||
"turns" => count($lines ?: []),
|
||||
"size_kb" => round(filesize($f)/1024, 1),
|
||||
"mtime" => date("c", filemtime($f)),
|
||||
];
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
// If called directly via HTTP, act as API
|
||||
if (php_sapi_name() !== "cli" && basename($_SERVER["SCRIPT_FILENAME"] ?? "") === "ambre-internal-memory.php") {
|
||||
header("Content-Type: application/json; charset=utf-8");
|
||||
$raw = file_get_contents("php://input");
|
||||
$in = json_decode($raw, true) ?: $_GET;
|
||||
$action = $in["action"] ?? "stats";
|
||||
$chat_id = $in["chat_id"] ?? "";
|
||||
|
||||
switch ($action) {
|
||||
case "append":
|
||||
$result = AmbreInternalMemory::append($chat_id, $in["role"] ?? "user", $in["content"] ?? "", $in["metadata"] ?? []);
|
||||
echo json_encode(["ok"=>(bool)$result, "written"=>$result]);
|
||||
break;
|
||||
case "load":
|
||||
echo json_encode(["ok"=>true, "messages"=>AmbreInternalMemory::load($chat_id, intval($in["n"] ?? 100))]);
|
||||
break;
|
||||
case "context":
|
||||
echo json_encode(["ok"=>true, "messages"=>AmbreInternalMemory::context_messages($chat_id, intval($in["n"] ?? 50))]);
|
||||
break;
|
||||
case "stats":
|
||||
echo json_encode(["ok"=>true, "stats"=>AmbreInternalMemory::stats($chat_id)]);
|
||||
break;
|
||||
case "list":
|
||||
echo json_encode(["ok"=>true, "chats"=>AmbreInternalMemory::list_chats()]);
|
||||
break;
|
||||
default:
|
||||
echo json_encode(["error"=>"unknown action. Use: append|load|context|stats|list"]);
|
||||
}
|
||||
}
|
||||
5
api/ambre-mem-read.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
header("Content-Type: text/plain");
|
||||
$f = "/var/www/html/api/ambre-session-memory.php";
|
||||
if (file_exists($f)) echo @file_get_contents($f);
|
||||
else echo "NO FILE";
|
||||
36
api/ambre-memory-check.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$out = [];
|
||||
|
||||
// Widget / root index
|
||||
$root = @file_get_contents("/var/www/html/index.html");
|
||||
$out["root_size"] = strlen($root ?? "");
|
||||
$out["widget_has_sessionstorage"] = strpos($root ?? "", "sessionStorage") !== false;
|
||||
$out["widget_has_localstorage"] = strpos($root ?? "", "localStorage") !== false;
|
||||
$out["widget_has_wevia"] = preg_match_all("/wevia/i", $root ?? "");
|
||||
|
||||
// Widget bubbler for persistent backend
|
||||
$wevia_public = @file_get_contents("/var/www/html/wevia.html");
|
||||
$out["wevia_public_size"] = strlen($wevia_public ?? "");
|
||||
$out["wevia_has_sessionstorage"] = strpos($wevia_public ?? "", "sessionStorage") !== false;
|
||||
$out["wevia_has_session_id"] = strpos($wevia_public ?? "", "_ambre_session_id") !== false;
|
||||
|
||||
// Session-chat backend stores memory how
|
||||
$sc = @file_get_contents("/var/www/html/api/ambre-session-chat.php");
|
||||
$out["session_chat_size"] = strlen($sc ?? "");
|
||||
$out["session_chat_storage"] = [];
|
||||
if ($sc) {
|
||||
if (strpos($sc, "file_put_contents") !== false) $out["session_chat_storage"][] = "file";
|
||||
if (strpos($sc, "sqlite") !== false) $out["session_chat_storage"][] = "sqlite";
|
||||
if (strpos($sc, "redis") !== false) $out["session_chat_storage"][] = "redis";
|
||||
// Find TTL
|
||||
if (preg_match("/(\d{4,}).*TTL|TTL.*?(\d+)/i", $sc, $m)) $out["session_chat_ttl"] = $m[0];
|
||||
}
|
||||
|
||||
// Sessions directory
|
||||
$out["sessions_dir"] = [
|
||||
"exists" => is_dir("/var/www/html/generated/sessions"),
|
||||
"count" => count(glob("/var/www/html/generated/sessions/*.json") ?: []),
|
||||
];
|
||||
|
||||
echo json_encode($out, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
190
api/ambre-multiagent-parallel.php
Normal file
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/**
|
||||
* ambre-multiagent-parallel.php · wave-255 · Multi-agent parallel dispatch
|
||||
* Langue naturelle → Plan → Execute N agents in parallel → Reconcile
|
||||
*
|
||||
* POST JSON: { "goal": "texte objectif", "max_agents": 5 }
|
||||
* Response: { "ok":true, "plan":[...], "results":[...], "elapsed_ms":N, "reconciled":"..." }
|
||||
*/
|
||||
header("Content-Type: application/json; charset=utf-8");
|
||||
set_time_limit(120);
|
||||
|
||||
$raw = file_get_contents("php://input");
|
||||
$in = json_decode($raw, true) ?: $_POST;
|
||||
$goal = trim($in["goal"] ?? $in["message"] ?? "");
|
||||
$max_agents = min(10, max(1, intval($in["max_agents"] ?? 5)));
|
||||
|
||||
if (!$goal) {
|
||||
echo json_encode(["error"=>"goal required"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$t0 = microtime(true);
|
||||
|
||||
// Step 1 · PLAN via LLM (one call, JSON structured)
|
||||
$plan_sys = "Tu es un planificateur multi-agent. Pour l'objectif donné, génère STRICTEMENT un JSON avec cette structure :\n" .
|
||||
"{\n" .
|
||||
" \"objective\": \"<reformulation en une phrase>\",\n" .
|
||||
" \"agents\": [\n" .
|
||||
" {\"role\":\"researcher\", \"task\":\"<tâche précise>\", \"tool\":\"<pdf_premium|mermaid|web_search|calc|image|code|translate|kb_search|none>\"},\n" .
|
||||
" ...\n" .
|
||||
" ]\n" .
|
||||
"}\n" .
|
||||
"Maximum $max_agents agents. Chaque agent a un role distinct et une tâche autonome. NE réponds QUE le JSON.";
|
||||
|
||||
$plan_raw = @file_get_contents("http://127.0.0.1:4000/v1/chat/completions", false, stream_context_create([
|
||||
"http" => [
|
||||
"method" => "POST",
|
||||
"header" => "Content-Type: application/json\r\n",
|
||||
"content" => json_encode([
|
||||
"model" => "fast",
|
||||
"messages" => [
|
||||
["role"=>"system","content"=>$plan_sys],
|
||||
["role"=>"user","content"=>"Objectif: " . $goal]
|
||||
],
|
||||
"max_tokens" => 800,
|
||||
"temperature" => 0.3,
|
||||
]),
|
||||
"timeout" => 20,
|
||||
],
|
||||
]));
|
||||
|
||||
$plan_data = @json_decode($plan_raw, true);
|
||||
$plan_text = $plan_data["choices"][0]["message"]["content"] ?? "";
|
||||
$plan_text = preg_replace('/^```(?:json)?\s*/m', '', $plan_text);
|
||||
$plan_text = preg_replace('/\s*```\s*$/m', '', trim($plan_text));
|
||||
$plan = @json_decode($plan_text, true);
|
||||
|
||||
if (!$plan || !isset($plan["agents"]) || !is_array($plan["agents"])) {
|
||||
echo json_encode(["error"=>"LLM plan invalid", "raw"=>substr($plan_text, 0, 500)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$plan_ms = round((microtime(true)-$t0)*1000);
|
||||
|
||||
// Step 2 · EXECUTE agents en parallèle via curl_multi
|
||||
$agents = array_slice($plan["agents"], 0, $max_agents);
|
||||
$mh = curl_multi_init();
|
||||
$handles = [];
|
||||
|
||||
$tool_map = [
|
||||
"pdf_premium" => ["url"=>"http://127.0.0.1/api/ambre-tool-pdf-premium.php", "body_key"=>"topic"],
|
||||
"mermaid" => ["url"=>"http://127.0.0.1/api/ambre-tool-mermaid.php", "body_key"=>"topic"],
|
||||
"web_search" => ["url"=>"http://127.0.0.1/api/ambre-tool-web-search.php", "body_key"=>"query"],
|
||||
"calc" => ["url"=>"http://127.0.0.1/api/ambre-tool-calc.php", "body_key"=>"expression"],
|
||||
"kb_search" => ["url"=>"http://127.0.0.1/api/ambre-mermaid-learn.php", "body_key"=>"query"],
|
||||
];
|
||||
|
||||
$exec_t0 = microtime(true);
|
||||
foreach ($agents as $i => $agent) {
|
||||
$tool = $agent["tool"] ?? "none";
|
||||
$task = $agent["task"] ?? "";
|
||||
if ($tool === "none" || !isset($tool_map[$tool])) {
|
||||
// No tool → LLM direct reasoning
|
||||
$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([
|
||||
"model"=>"fast",
|
||||
"messages"=>[["role"=>"user","content"=>$task]],
|
||||
"max_tokens"=>400,
|
||||
]),
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_CONNECTTIMEOUT => 3,
|
||||
]);
|
||||
} else {
|
||||
$cfg = $tool_map[$tool];
|
||||
$body = [$cfg["body_key"] => $task];
|
||||
if ($tool === "kb_search") $body["action"] = "search";
|
||||
$ch = curl_init($cfg["url"]);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
|
||||
CURLOPT_POSTFIELDS => json_encode($body),
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 45,
|
||||
CURLOPT_CONNECTTIMEOUT => 3,
|
||||
]);
|
||||
}
|
||||
curl_multi_add_handle($mh, $ch);
|
||||
$handles[$i] = ["ch"=>$ch, "agent"=>$agent, "t0"=>microtime(true)];
|
||||
}
|
||||
|
||||
// Run all in parallel
|
||||
$running = null;
|
||||
do {
|
||||
curl_multi_exec($mh, $running);
|
||||
curl_multi_select($mh, 0.5);
|
||||
} while ($running > 0);
|
||||
|
||||
// Collect results
|
||||
$results = [];
|
||||
foreach ($handles as $i => $h) {
|
||||
$output = curl_multi_getcontent($h["ch"]);
|
||||
$elapsed_ms = round((microtime(true)-$h["t0"])*1000);
|
||||
$http_code = curl_getinfo($h["ch"], CURLINFO_HTTP_CODE);
|
||||
curl_multi_remove_handle($mh, $h["ch"]);
|
||||
curl_close($h["ch"]);
|
||||
|
||||
// Try to extract meaningful summary
|
||||
$result_data = @json_decode($output, true);
|
||||
$summary = "";
|
||||
if ($result_data) {
|
||||
if (isset($result_data["mermaid_code"])) $summary = "Mermaid généré (" . strlen($result_data["mermaid_code"]) . "B)";
|
||||
elseif (isset($result_data["url"])) $summary = "PDF: " . $result_data["url"];
|
||||
elseif (isset($result_data["choices"][0]["message"]["content"])) $summary = substr($result_data["choices"][0]["message"]["content"], 0, 300);
|
||||
elseif (isset($result_data["result"])) $summary = (string)$result_data["result"];
|
||||
else $summary = substr($output, 0, 200);
|
||||
} else {
|
||||
$summary = substr($output ?: "empty", 0, 200);
|
||||
}
|
||||
|
||||
$results[] = [
|
||||
"agent" => $h["agent"]["role"] ?? "agent_$i",
|
||||
"task" => $h["agent"]["task"] ?? "",
|
||||
"tool" => $h["agent"]["tool"] ?? "none",
|
||||
"http" => $http_code,
|
||||
"elapsed_ms" => $elapsed_ms,
|
||||
"summary" => $summary,
|
||||
];
|
||||
}
|
||||
curl_multi_close($mh);
|
||||
$exec_ms = round((microtime(true)-$exec_t0)*1000);
|
||||
|
||||
// Step 3 · RECONCILE (synthesis LLM call)
|
||||
$synth_input = "Objectif: " . $goal . "\n\nRésultats des " . count($results) . " agents:\n";
|
||||
foreach ($results as $r) {
|
||||
$synth_input .= "- " . $r["agent"] . " (" . $r["tool"] . "): " . substr($r["summary"], 0, 300) . "\n";
|
||||
}
|
||||
$synth_input .= "\nSynthétise la réponse finale en français clair et actionnable. Max 200 mots.";
|
||||
|
||||
$synth_raw = @file_get_contents("http://127.0.0.1:4000/v1/chat/completions", false, stream_context_create([
|
||||
"http" => [
|
||||
"method" => "POST",
|
||||
"header" => "Content-Type: application/json\r\n",
|
||||
"content" => json_encode([
|
||||
"model" => "fast",
|
||||
"messages" => [["role"=>"user","content"=>$synth_input]],
|
||||
"max_tokens" => 500,
|
||||
]),
|
||||
"timeout" => 15,
|
||||
],
|
||||
]));
|
||||
$synth_data = @json_decode($synth_raw, true);
|
||||
$reconciled = $synth_data["choices"][0]["message"]["content"] ?? "Synthèse échouée";
|
||||
|
||||
echo json_encode([
|
||||
"ok" => true,
|
||||
"goal" => $goal,
|
||||
"plan" => $plan,
|
||||
"plan_ms" => $plan_ms,
|
||||
"results" => $results,
|
||||
"exec_ms" => $exec_ms,
|
||||
"parallel_speedup" => round(array_sum(array_column($results, "elapsed_ms")) / max($exec_ms, 1), 2),
|
||||
"reconciled" => trim($reconciled),
|
||||
"total_ms" => round((microtime(true)-$t0)*1000),
|
||||
"agents_count" => count($results),
|
||||
"provider" => "WEVIA MultiAgent Parallel Engine · wave-255",
|
||||
], JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);
|
||||
27
api/ambre-oss-wire.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$path = "/var/www/html/oss-catalog.html";
|
||||
$c = @file_get_contents($path);
|
||||
$orig = strlen($c);
|
||||
|
||||
if (strpos($c, "dashboards-hub-unified") !== false) {
|
||||
echo json_encode(["already"=>true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Inject in footer
|
||||
$old = '<a href="/dashboards-index.html">Dashboards</a>';
|
||||
$new = '<a href="/dashboards-hub-unified.html">📊 Hub Dashboards</a> · <a href="/dashboards-index.html">Index</a>';
|
||||
|
||||
if (strpos($c, $old) !== false) {
|
||||
$c = str_replace($old, $new, $c);
|
||||
$backup = "/opt/wevads/vault/oss-catalog.GOLD-" . date("Ymd-His") . "-wave246";
|
||||
@copy($path, $backup);
|
||||
$wrote = @file_put_contents($path, $c);
|
||||
echo json_encode([
|
||||
"wrote" => $wrote,
|
||||
"delta" => strlen($c) - $orig,
|
||||
]);
|
||||
} else {
|
||||
echo json_encode(["error"=>"anchor not found"]);
|
||||
}
|
||||
4
api/ambre-pw-tests/output/.last-run.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"failedTests": []
|
||||
}
|
||||
161
api/ambre-pw-tests/output/results.json
Normal file
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"config": {
|
||||
"configFile": "/var/www/html/api/ambre-pw-tests/playwright.config.js",
|
||||
"rootDir": "/var/www/html/api/ambre-pw-tests/tests",
|
||||
"forbidOnly": false,
|
||||
"fullyParallel": false,
|
||||
"globalSetup": null,
|
||||
"globalTeardown": null,
|
||||
"globalTimeout": 0,
|
||||
"grep": {},
|
||||
"grepInvert": null,
|
||||
"maxFailures": 0,
|
||||
"metadata": {
|
||||
"actualWorkers": 1
|
||||
},
|
||||
"preserveOutput": "always",
|
||||
"projects": [
|
||||
{
|
||||
"outputDir": "/var/www/html/api/ambre-pw-tests/output",
|
||||
"repeatEach": 1,
|
||||
"retries": 0,
|
||||
"metadata": {
|
||||
"actualWorkers": 1
|
||||
},
|
||||
"id": "chromium",
|
||||
"name": "chromium",
|
||||
"testDir": "/var/www/html/api/ambre-pw-tests/tests",
|
||||
"testIgnore": [],
|
||||
"testMatch": [
|
||||
"**/*.@(spec|test).?(c|m)[jt]s?(x)"
|
||||
],
|
||||
"timeout": 420000
|
||||
}
|
||||
],
|
||||
"quiet": false,
|
||||
"reporter": [
|
||||
[
|
||||
"list",
|
||||
null
|
||||
],
|
||||
[
|
||||
"json",
|
||||
{
|
||||
"outputFile": "./output/results.json"
|
||||
}
|
||||
]
|
||||
],
|
||||
"reportSlowTests": {
|
||||
"max": 5,
|
||||
"threshold": 300000
|
||||
},
|
||||
"shard": null,
|
||||
"tags": [],
|
||||
"updateSnapshots": "missing",
|
||||
"updateSourceMethod": "patch",
|
||||
"version": "1.59.1",
|
||||
"workers": 1,
|
||||
"webServer": null
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"title": "v46-debug.spec.js",
|
||||
"file": "v46-debug.spec.js",
|
||||
"column": 0,
|
||||
"line": 0,
|
||||
"specs": [
|
||||
{
|
||||
"title": "V46 · Debug V11 triggers + console logs",
|
||||
"ok": true,
|
||||
"tags": [],
|
||||
"tests": [
|
||||
{
|
||||
"timeout": 200000,
|
||||
"annotations": [],
|
||||
"expectedStatus": "passed",
|
||||
"projectId": "chromium",
|
||||
"projectName": "chromium",
|
||||
"results": [
|
||||
{
|
||||
"workerIndex": 0,
|
||||
"parallelIndex": 0,
|
||||
"status": "passed",
|
||||
"duration": 166633,
|
||||
"errors": [],
|
||||
"stdout": [
|
||||
{
|
||||
"text": "Waiting multi-agent...\n"
|
||||
},
|
||||
{
|
||||
"text": "\n=== Console logs ===\n"
|
||||
},
|
||||
{
|
||||
"text": " [error] Failed to load resource: the server responded with a status of 503 ()\n"
|
||||
},
|
||||
{
|
||||
"text": " [error] Failed to load resource: the server responded with a status of 503 ()\n"
|
||||
},
|
||||
{
|
||||
"text": " [log] [V11-MULTIAGENT] triggered for text: compare WEVIA avec OPUS sur architecture, couts, securite en analyse complete mu\n"
|
||||
},
|
||||
{
|
||||
"text": " [error] Failed to load resource: the server responded with a status of 503 ()\n"
|
||||
},
|
||||
{
|
||||
"text": " [error] Failed to load resource: the server responded with a status of 502 ()\n"
|
||||
},
|
||||
{
|
||||
"text": " [warning] [retry] /api/ambre-multiagent-parallel.php got 502, retry #1\n"
|
||||
},
|
||||
{
|
||||
"text": " [log] [V11] response status 200\n"
|
||||
},
|
||||
{
|
||||
"text": "\n=== Errors ===\n"
|
||||
},
|
||||
{
|
||||
"text": "\n=== Last msg ===\n"
|
||||
},
|
||||
{
|
||||
"text": "{\n \"text\": \"🧠 Multi-Agent\\n5 agents ∥\\n⚡ 5x speedup\\n16905ms\\n📋 Plan · Comparer WEVIA avec OPUS en matière d'architecture, de coûts et de sécurité selon une analyse complète et multi-angle.\\n5 agents dispatchés en parallèle\\n🤖 Agents · exécution parallèle\\n🔍 researcher · web_search · 12176ms\\nRecueillir des informations détaillées sur l'architecture technique de WEVIA et d'OPUS à partir de sources fiables.\\n{\\\"quer\",\n \"has_synth\": true,\n \"badges\": 4,\n \"html_len\": 6620\n}\n"
|
||||
}
|
||||
],
|
||||
"stderr": [],
|
||||
"retry": 0,
|
||||
"startTime": "2026-04-22T02:54:24.596Z",
|
||||
"annotations": [],
|
||||
"attachments": [
|
||||
{
|
||||
"name": "screenshot",
|
||||
"contentType": "image/png",
|
||||
"path": "/var/www/html/api/ambre-pw-tests/output/v46-debug-V46-·-Debug-V11-triggers-console-logs-chromium/test-finished-1.png"
|
||||
},
|
||||
{
|
||||
"name": "video",
|
||||
"contentType": "video/webm",
|
||||
"path": "/var/www/html/api/ambre-pw-tests/output/v46-debug-V46-·-Debug-V11-triggers-console-logs-chromium/video.webm"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"status": "expected"
|
||||
}
|
||||
],
|
||||
"id": "43927d920210b130c5c8-fed91c1b3d281fc0e1a8",
|
||||
"file": "v46-debug.spec.js",
|
||||
"line": 3,
|
||||
"column": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"errors": [],
|
||||
"stats": {
|
||||
"startTime": "2026-04-22T02:54:23.825Z",
|
||||
"duration": 167589.90399999998,
|
||||
"expected": 1,
|
||||
"skipped": 0,
|
||||
"unexpected": 0,
|
||||
"flaky": 0
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 281 KiB |
BIN
api/ambre-pw-tests/output/v46-result.png
Normal file
|
After Width: | Height: | Size: 281 KiB |
@@ -1,25 +0,0 @@
|
||||
const { test } = require("@playwright/test");
|
||||
|
||||
test("V40 · Hub Dashboards Unifié screenshot", async ({ page }) => {
|
||||
test.setTimeout(30000);
|
||||
await page.goto("/dashboards-hub-unified.html");
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForTimeout(1500);
|
||||
await page.screenshot({ path: "output/v40-hub-top.png" });
|
||||
await page.screenshot({ path: "output/v40-hub-full.png", fullPage: true });
|
||||
|
||||
// Test filter click
|
||||
const filters = await page.locator(".filter").count();
|
||||
console.log(`Filters count: ${filters}`);
|
||||
const cards = await page.locator(".card").count();
|
||||
console.log(`Cards count: ${cards}`);
|
||||
const cats = await page.locator(".cat-section").count();
|
||||
console.log(`Cat sections: ${cats}`);
|
||||
|
||||
// Click 2nd filter (not "Tous")
|
||||
if (filters > 1) {
|
||||
await page.locator(".filter").nth(1).click();
|
||||
await page.waitForTimeout(800);
|
||||
await page.screenshot({ path: "output/v40-hub-filtered.png" });
|
||||
}
|
||||
});
|
||||
48
api/ambre-pw-tests/tests/v46-debug.spec.js
Normal file
@@ -0,0 +1,48 @@
|
||||
const { test } = require("@playwright/test");
|
||||
|
||||
test("V46 · Debug V11 triggers + console logs", async ({ page }) => {
|
||||
test.setTimeout(200000);
|
||||
const logs = [];
|
||||
const errs = [];
|
||||
page.on("console", m => logs.push({type:m.type(), text:m.text().substring(0,200)}));
|
||||
page.on("pageerror", e => errs.push(e.message.substring(0,200)));
|
||||
|
||||
await page.goto("/wevia.html?cb=" + Date.now());
|
||||
await page.evaluate(() => { try{sessionStorage.clear();}catch(e){} });
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Skip HI - straight to multi-agent
|
||||
const input = page.locator("#msgInput");
|
||||
await input.click({force:true});
|
||||
await input.fill("compare WEVIA avec OPUS sur architecture, couts, securite en analyse complete multi-angle");
|
||||
await page.waitForTimeout(500);
|
||||
await input.press("Enter");
|
||||
|
||||
console.log("Waiting multi-agent...");
|
||||
await page.waitForTimeout(150000); // wait 2.5min for response
|
||||
|
||||
console.log("\n=== Console logs ===");
|
||||
logs.filter(l => l.text.includes("V11") || l.text.includes("multi") || l.type === "error").forEach(l => {
|
||||
console.log(` [${l.type}] ${l.text}`);
|
||||
});
|
||||
console.log("\n=== Errors ===");
|
||||
errs.forEach(e => console.log(` ${e}`));
|
||||
|
||||
await page.screenshot({ path: "output/v46-result.png", fullPage: true });
|
||||
|
||||
// Extract last assistant message
|
||||
const last = await page.evaluate(() => {
|
||||
const msgs = document.querySelectorAll(".msg.assistant");
|
||||
if (msgs.length === 0) return "no msg";
|
||||
const l = msgs[msgs.length-1];
|
||||
return {
|
||||
text: (l.querySelector(".bubble")?.innerText || "").substring(0, 400),
|
||||
has_synth: /Synth[eè]se consolid/.test(l.innerHTML),
|
||||
badges: l.querySelectorAll(".nx-badge").length,
|
||||
html_len: l.innerHTML.length,
|
||||
};
|
||||
});
|
||||
console.log("\n=== Last msg ===");
|
||||
console.log(JSON.stringify(last, null, 2));
|
||||
});
|
||||
7
api/ambre-pw-v41-deploy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$base = "/var/www/html/api/ambre-pw-tests/tests";
|
||||
$spec = base64_decode("Y29uc3QgeyB0ZXN0IH0gPSByZXF1aXJlKCJAcGxheXdyaWdodC90ZXN0Iik7Cgp0ZXN0KCJWNDEgwrcgV1RQIGF2ZWMgSHViIFVuaWZpw6kgbGluayIsIGFzeW5jICh7IHBhZ2UgfSkgPT4gewogIHRlc3Quc2V0VGltZW91dCgzMDAwMCk7CiAgYXdhaXQgcGFnZS5nb3RvKCIvd2V2YWwtdGVjaG5vbG9neS1wbGF0Zm9ybS5odG1sIik7CiAgYXdhaXQgcGFnZS53YWl0Rm9yTG9hZFN0YXRlKCJuZXR3b3JraWRsZSIpOwogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoMjAwMCk7CiAgCiAgLy8gRmluZCBodWIgbGluawogIGNvbnN0IGh1YkxpbmtzID0gYXdhaXQgcGFnZS5sb2NhdG9yKCdhW2hyZWYqPSJkYXNoYm9hcmRzLWh1Yi11bmlmaWVkIl0nKS5jb3VudCgpOwogIGNvbnNvbGUubG9nKGBIdWIgbGlua3MgaW4gV1RQOiAke2h1YkxpbmtzfWApOwogIAogIGlmIChodWJMaW5rcyA+IDApIHsKICAgIGNvbnN0IGVsID0gcGFnZS5sb2NhdG9yKCdhW2hyZWYqPSJkYXNoYm9hcmRzLWh1Yi11bmlmaWVkIl0nKS5maXJzdCgpOwogICAgYXdhaXQgZWwuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZCgpOwogICAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCg1MDApOwogICAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDEtd3RwLWh1Yi1saW5rLnBuZyIgfSk7CiAgICBjb25zdCB0eHQgPSBhd2FpdCBlbC5pbm5lclRleHQoKTsKICAgIGNvbnNvbGUubG9nKGBMaW5rIHRleHQ6ICIke3R4dH0iYCk7CiAgfQogIAogIC8vIEFsc28gdGVzdCBPU1MKICBhd2FpdCBwYWdlLmdvdG8oIi9vc3MtY2F0YWxvZy5odG1sIik7CiAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCgyMDAwKTsKICBjb25zdCBvc3NMaW5rcyA9IGF3YWl0IHBhZ2UubG9jYXRvcignYVtocmVmKj0iZGFzaGJvYXJkcy1odWItdW5pZmllZCJdJykuY291bnQoKTsKICBjb25zb2xlLmxvZyhgSHViIGxpbmtzIGluIE9TUzogJHtvc3NMaW5rc31gKTsKICBhd2FpdCBwYWdlLnNjcmVlbnNob3QoeyBwYXRoOiAib3V0cHV0L3Y0MS1vc3MtaHViLWxpbmsucG5nIiwgZnVsbFBhZ2U6IHRydWUgfSk7Cn0pOwo=");
|
||||
foreach (glob("$base/*.spec.js") as $old) @unlink($old);
|
||||
$written = @file_put_contents("$base/v41-wtp-hub.spec.js", $spec);
|
||||
echo json_encode(["written" => $written]);
|
||||
7
api/ambre-pw-v41b-deploy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$base = "/var/www/html/api/ambre-pw-tests/tests";
|
||||
$spec = base64_decode("Y29uc3QgeyB0ZXN0IH0gPSByZXF1aXJlKCJAcGxheXdyaWdodC90ZXN0Iik7Cgp0ZXN0KCJWNDFiIMK3IFdUUCArIE9TUyArIEh1YiB3aXRoIGNhY2hlLWJ1c3QiLCBhc3luYyAoeyBwYWdlIH0pID0+IHsKICB0ZXN0LnNldFRpbWVvdXQoMzAwMDApOwogIGNvbnN0IGNiID0gRGF0ZS5ub3coKTsKICAKICAvLyBXVFAKICBhd2FpdCBwYWdlLmdvdG8oYC93ZXZhbC10ZWNobm9sb2d5LXBsYXRmb3JtLmh0bWw/Y2I9JHtjYn1gKTsKICBhd2FpdCBwYWdlLndhaXRGb3JMb2FkU3RhdGUoIm5ldHdvcmtpZGxlIik7CiAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCgyMDAwKTsKICBsZXQgaHViTGlua3MgPSBhd2FpdCBwYWdlLmxvY2F0b3IoJ2FbaHJlZio9ImRhc2hib2FyZHMtaHViLXVuaWZpZWQiXScpLmNvdW50KCk7CiAgY29uc29sZS5sb2coYFdUUCBodWIgbGlua3M6ICR7aHViTGlua3N9YCk7CiAgaWYgKGh1YkxpbmtzID4gMCkgewogICAgY29uc3QgZWwgPSBwYWdlLmxvY2F0b3IoJ2FbaHJlZio9ImRhc2hib2FyZHMtaHViLXVuaWZpZWQiXScpLmZpcnN0KCk7CiAgICBhd2FpdCBlbC5zY3JvbGxJbnRvVmlld0lmTmVlZGVkKCk7CiAgICBhd2FpdCBwYWdlLndhaXRGb3JUaW1lb3V0KDgwMCk7CiAgICBhd2FpdCBwYWdlLnNjcmVlbnNob3QoeyBwYXRoOiAib3V0cHV0L3Y0MWItd3RwLWh1Yi5wbmciIH0pOwogICAgY29uc3QgdHh0ID0gYXdhaXQgZWwuaW5uZXJUZXh0KCk7CiAgICBjb25zb2xlLmxvZyhgV1RQIGxpbms6ICIke3R4dH0iYCk7CiAgfSBlbHNlIHsKICAgIGF3YWl0IHBhZ2Uuc2NyZWVuc2hvdCh7IHBhdGg6ICJvdXRwdXQvdjQxYi13dHAtbm9odWIucG5nIiB9KTsKICB9CiAgCiAgLy8gQ2xpY2sgdGhlIGh1YiBsaW5rIHRvIHZlcmlmeSBmbG93CiAgaWYgKGh1YkxpbmtzID4gMCkgewogICAgYXdhaXQgcGFnZS5sb2NhdG9yKCdhW2hyZWYqPSJkYXNoYm9hcmRzLWh1Yi11bmlmaWVkIl0nKS5maXJzdCgpLmNsaWNrKCk7CiAgICBhd2FpdCBwYWdlLndhaXRGb3JUaW1lb3V0KDIwMDApOwogICAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDFiLWh1Yi1hZnRlci1jbGljay5wbmciIH0pOwogIH0KfSk7Cg==");
|
||||
foreach (glob("$base/*.spec.js") as $old) @unlink($old);
|
||||
$written = @file_put_contents("$base/v41b.spec.js", $spec);
|
||||
echo json_encode(["written" => $written]);
|
||||
7
api/ambre-pw-v42-deploy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$base = "/var/www/html/api/ambre-pw-tests/tests";
|
||||
$spec = base64_decode("Y29uc3QgeyB0ZXN0IH0gPSByZXF1aXJlKCJAcGxheXdyaWdodC90ZXN0Iik7Cgp0ZXN0KCJWNDIgwrcgRklOQUwgSHViIERhc2hib2FyZHMgU2hvd2Nhc2UgVWx0cmEiLCBhc3luYyAoeyBwYWdlIH0pID0+IHsKICB0ZXN0LnNldFRpbWVvdXQoNjAwMDApOwogIAogIC8vIDEuIEh1YiBob21lCiAgYXdhaXQgcGFnZS5nb3RvKCIvZGFzaGJvYXJkcy1odWItdW5pZmllZC5odG1sP2NiPSIgKyBEYXRlLm5vdygpKTsKICBhd2FpdCBwYWdlLndhaXRGb3JMb2FkU3RhdGUoIm5ldHdvcmtpZGxlIik7CiAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCgxNTAwKTsKICBhd2FpdCBwYWdlLnNjcmVlbnNob3QoeyBwYXRoOiAib3V0cHV0L3Y0Mi0wMS1ob21lLnBuZyIgfSk7CiAgY29uc29sZS5sb2coIuKchSBUMTogSHViIGhvbWUgbG9hZGVkIik7CiAgCiAgLy8gU3RhdHMKICBjb25zdCBzdGF0cyA9IGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4gewogICAgY29uc3QgYnMgPSBBcnJheS5mcm9tKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5zdGF0IGInKSkubWFwKGIgPT4gYi5pbm5lclRleHQpOwogICAgY29uc3QgY2FyZHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuY2FyZCcpLmxlbmd0aDsKICAgIGNvbnN0IGZpbHRlcnMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZmlsdGVyJykubGVuZ3RoOwogICAgcmV0dXJuIHsgc3RhdHM6IGJzLCBjYXJkcywgZmlsdGVycyB9OwogIH0pOwogIGNvbnNvbGUubG9nKGAgIFN0YXRzOiAke0pTT04uc3RyaW5naWZ5KHN0YXRzKX1gKTsKICAKICAvLyAyLiBGaWx0ZXIgYnkgS1BJICYgQW5hbHl0aWNzCiAgY29uc3QgZmlsdGVyS1BJID0gcGFnZS5sb2NhdG9yKCcuZmlsdGVyOmhhcy10ZXh0KCJLUEkgJiBBbmFseXRpY3MiKScpOwogIGlmIChhd2FpdCBmaWx0ZXJLUEkuY291bnQoKSA+IDApIHsKICAgIGF3YWl0IGZpbHRlcktQSS5jbGljaygpOwogICAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCg1MDApOwogICAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDItMDItZmlsdGVyLWtwaS5wbmciIH0pOwogICAgY29uc29sZS5sb2coIuKchSBUMjogS1BJIGZpbHRlciBhcHBsaWVkIik7CiAgfQogIAogIC8vIDMuIEZpbHRlciBieSBFdGhpY2EKICBjb25zdCBmaWx0ZXJFdGggPSBwYWdlLmxvY2F0b3IoJy5maWx0ZXI6aGFzLXRleHQoIkV0aGljYSIpJyk7CiAgaWYgKGF3YWl0IGZpbHRlckV0aC5jb3VudCgpID4gMCkgewogICAgYXdhaXQgZmlsdGVyRXRoLmNsaWNrKCk7CiAgICBhd2FpdCBwYWdlLndhaXRGb3JUaW1lb3V0KDUwMCk7CiAgICBhd2FpdCBwYWdlLnNjcmVlbnNob3QoeyBwYXRoOiAib3V0cHV0L3Y0Mi0wMy1maWx0ZXItZXRoaWNhLnBuZyIgfSk7CiAgICBjb25zb2xlLmxvZygi4pyFIFQzOiBFdGhpY2EgZmlsdGVyIGFwcGxpZWQiKTsKICB9CiAgCiAgLy8gNC4gQmFjayB0byBhbGwKICBhd2FpdCBwYWdlLmxvY2F0b3IoJy5maWx0ZXI6aGFzLXRleHQoIlRvdXMiKScpLmNsaWNrKCk7CiAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCg1MDApOwogIGF3YWl0IHBhZ2Uuc2NyZWVuc2hvdCh7IHBhdGg6ICJvdXRwdXQvdjQyLTA0LWFsbC1iYWNrLnBuZyIgfSk7CiAgCiAgLy8gNS4gRnVsbCBwYWdlCiAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDItMDUtZnVsbHBhZ2UucG5nIiwgZnVsbFBhZ2U6IHRydWUgfSk7CiAgY29uc29sZS5sb2coIuKchSBUNDogRnVsbCBwYWdlIGNhcHR1cmVkIik7CiAgCiAgLy8gNi4gUmVnaXN0cnkgQVBJCiAgY29uc3QgcmVnID0gYXdhaXQgcGFnZS5ldmFsdWF0ZShhc3luYyAoKSA9PiB7CiAgICBjb25zdCByID0gYXdhaXQgZmV0Y2goJy9hcGkvZGFzaGJvYXJkcy1yZWdpc3RyeS1hbWJyZS5waHAnKTsKICAgIHJldHVybiBhd2FpdCByLmpzb24oKTsKICB9KTsKICBjb25zb2xlLmxvZyhgICBSZWdpc3RyeTogdG90YWw9JHtyZWcudG90YWx9IMK3IGNhdHM9JHtyZWcuY2F0ZWdvcmllc19jb3VudH0gwrcgemVyb19vcnBoYW49JHtyZWcuemVyb19vcnBoYW59YCk7Cn0pOwo=");
|
||||
foreach (glob("$base/*.spec.js") as $old) @unlink($old);
|
||||
$written = @file_put_contents("$base/v42-hub-showcase.spec.js", $spec);
|
||||
echo json_encode(["written" => $written]);
|
||||
7
api/ambre-pw-v43-deploy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$base = "/var/www/html/api/ambre-pw-tests/tests";
|
||||
$spec = base64_decode("Y29uc3QgeyB0ZXN0IH0gPSByZXF1aXJlKCJAcGxheXdyaWdodC90ZXN0Iik7Cgp0ZXN0KCJWNDMgwrcgUFJPT0YgwrcgUERGIFByZW1pdW0gZW5kLXRvLWVuZCBjb252ZXJzYXRpb24gWWFjaW5lIiwgYXN5bmMgKHsgcGFnZSB9KSA9PiB7CiAgdGVzdC5zZXRUaW1lb3V0KDE4MDAwMCk7CiAgY29uc3QgZXJyb3JzID0gW107CiAgcGFnZS5vbigicGFnZWVycm9yIiwgZSA9PiBlcnJvcnMucHVzaChlLm1lc3NhZ2Uuc3Vic3RyaW5nKDAsMTIwKSkpOwogIAogIGF3YWl0IHBhZ2UuZ290bygiL3dldmlhLmh0bWw/Y2I9IiArIERhdGUubm93KCkpOwogIGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4geyB0cnl7c2Vzc2lvblN0b3JhZ2UuY2xlYXIoKTsgbG9jYWxTdG9yYWdlLmNsZWFyKCk7fWNhdGNoKGUpe30gfSk7CiAgYXdhaXQgcGFnZS53YWl0Rm9yTG9hZFN0YXRlKCJuZXR3b3JraWRsZSIpOwogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoMzUwMCk7CiAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDMtMDAtc3RhcnQucG5nIiB9KTsKICBjb25zb2xlLmxvZygi8J+TuCBUMCBzdGFydCDCtyBlcnJvcnM6IiwgZXJyb3JzLmxlbmd0aCk7CiAgCiAgLy8gVHVybiAxOiBoaQogIGNvbnN0IGlucHV0ID0gcGFnZS5sb2NhdG9yKCIjbXNnSW5wdXQiKTsKICBhd2FpdCBpbnB1dC5jbGljayh7Zm9yY2U6dHJ1ZX0pOwogIGF3YWl0IGlucHV0LmZpbGwoIkhJIik7CiAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCg0MDApOwogIGF3YWl0IGlucHV0LnByZXNzKCJFbnRlciIpOwogIAogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoNjAwMCk7CiAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDMtMDEtaGkucG5nIiB9KTsKICBjb25zb2xlLmxvZygi8J+TuCBUMSBISSBzZW50Iik7CiAgCiAgLy8gVHVybiAyOiBKRSBWRVVYIFVOIFBERgogIGF3YWl0IGlucHV0LmNsaWNrKHtmb3JjZTp0cnVlfSk7CiAgYXdhaXQgcGFnZS5rZXlib2FyZC5wcmVzcygiQ29udHJvbCtBIik7CiAgYXdhaXQgcGFnZS5rZXlib2FyZC5wcmVzcygiRGVsZXRlIik7CiAgYXdhaXQgaW5wdXQuZmlsbCgiSkUgVkVVWCBVTiBQREYgREUgQ09NUEFSQUlTT04gV0VWSUEgT1BVUyBBVkVDIEFWQU5UQUdFUyBJTkNPTlZFTklFTlRTIENPVVRTIFBFUkZPUk1BTkNFUyBJTlRFR1JBVElPTlMiKTsKICBhd2FpdCBwYWdlLndhaXRGb3JUaW1lb3V0KDQwMCk7CiAgYXdhaXQgaW5wdXQucHJlc3MoIkVudGVyIik7CiAgCiAgLy8gV2FpdCBQREYgZ2VuZXJhdGlvbiAobWF4IDkwcykKICBjb25zdCB3cyA9IERhdGUubm93KCk7CiAgbGV0IHBkZkZvdW5kID0gZmFsc2U7CiAgbGV0IHBkZlVybCA9IG51bGw7CiAgbGV0IGxhc3RSZXBseSA9ICIiOwogIAogIHdoaWxlIChEYXRlLm5vdygpIC0gd3MgPCA5MDAwMCkgewogICAgY29uc3Qgc3RhdGUgPSBhd2FpdCBwYWdlLmV2YWx1YXRlKCgpID0+IHsKICAgICAgY29uc3QgbXNncyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoIi5tc2cuYXNzaXN0YW50Iik7CiAgICAgIGNvbnN0IGxhc3QgPSBtc2dzLmxlbmd0aCA+IDAgPyBtc2dzW21zZ3MubGVuZ3RoLTFdIDogbnVsbDsKICAgICAgaWYgKCFsYXN0KSByZXR1cm4geyBjbnQ6IDAsIHBkZjogbnVsbCwgdGV4dDogIiIgfTsKICAgICAgY29uc3QgcGRmTGluayA9IGxhc3QucXVlcnlTZWxlY3RvcignYVtocmVmKj0iLnBkZiJdJyk7CiAgICAgIHJldHVybiB7CiAgICAgICAgY250OiBtc2dzLmxlbmd0aCwKICAgICAgICBwZGZfdXJsOiBwZGZMaW5rID8gcGRmTGluay5ocmVmIDogbnVsbCwKICAgICAgICBoYXNfcGRmX2luX2h0bWw6IC9cLnBkZi9pLnRlc3QobGFzdC5pbm5lckhUTUwpLAogICAgICAgIHRleHRfc2FtcGxlOiAobGFzdC5xdWVyeVNlbGVjdG9yKCIuYnViYmxlIik/LmlubmVyVGV4dCB8fCAiIikuc3Vic3RyaW5nKDAsIDMwMCksCiAgICAgIH07CiAgICB9KTsKICAgIGlmIChzdGF0ZS5wZGZfdXJsKSB7CiAgICAgIHBkZkZvdW5kID0gdHJ1ZTsKICAgICAgcGRmVXJsID0gc3RhdGUucGRmX3VybDsKICAgICAgbGFzdFJlcGx5ID0gc3RhdGUudGV4dF9zYW1wbGU7CiAgICAgIGJyZWFrOwogICAgfQogICAgbGFzdFJlcGx5ID0gc3RhdGUudGV4dF9zYW1wbGU7CiAgICBpZiAoc3RhdGUuaGFzX3BkZl9pbl9odG1sKSBjb25zb2xlLmxvZyhgICBbJHtNYXRoLnJvdW5kKChEYXRlLm5vdygpLXdzKS8xMDAwKX1zXSBwZGYga2V5d29yZCBpbiBodG1sYCk7CiAgICBhd2FpdCBwYWdlLndhaXRGb3JUaW1lb3V0KDIwMDApOwogIH0KICAKICBjb25zdCBlbCA9ICgoRGF0ZS5ub3coKS13cykvMTAwMCkudG9GaXhlZCgxKTsKICBjb25zb2xlLmxvZyhgXG7ilZDilZDilZAgUERGIHJlc3VsdCBhZnRlciAke2VsfXMg4pWQ4pWQ4pWQYCk7CiAgY29uc29sZS5sb2coYCAgRm91bmQ6ICR7cGRmRm91bmR9YCk7CiAgY29uc29sZS5sb2coYCAgVVJMOiAke3BkZlVybH1gKTsKICBjb25zb2xlLmxvZyhgICBUZXh0IHNhbXBsZTogJHtsYXN0UmVwbHkuc3Vic3RyaW5nKDAsMjUwKS5yZXBsYWNlKC9cbi9nLCcgJyl9YCk7CiAgCiAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDMtMDItcGRmLXJlcXVlc3QucG5nIiB9KTsKICBhd2FpdCBwYWdlLndhaXRGb3JUaW1lb3V0KDE1MDApOwogIGF3YWl0IHBhZ2Uuc2NyZWVuc2hvdCh7IHBhdGg6ICJvdXRwdXQvdjQzLTAzLWZpbmFsLnBuZyIsIGZ1bGxQYWdlOiB0cnVlIH0pOwogIAogIGlmICghcGRmRm91bmQpIHsKICAgIGNvbnNvbGUubG9nKGBcbuKdjCBOTyBQREYgTElOSyBHRU5FUkFURURgKTsKICAgIGNvbnNvbGUubG9nKGBFcnJvcnM6ICR7SlNPTi5zdHJpbmdpZnkoZXJyb3JzKX1gKTsKICB9Cn0pOwo=");
|
||||
foreach (glob("$base/*.spec.js") as $old) @unlink($old);
|
||||
$written = @file_put_contents("$base/v43-proof.spec.js", $spec);
|
||||
echo json_encode(["written" => $written]);
|
||||
7
api/ambre-pw-v44-deploy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$base = "/var/www/html/api/ambre-pw-tests/tests";
|
||||
$spec = base64_decode("Y29uc3QgeyB0ZXN0IH0gPSByZXF1aXJlKCJAcGxheXdyaWdodC90ZXN0Iik7Cgp0ZXN0KCJWNDQgwrcgUFJPT0YgwrcgUERGIFByZW1pdW0gYXR0ZW5kIGZpbiBISSIsIGFzeW5jICh7IHBhZ2UgfSkgPT4gewogIHRlc3Quc2V0VGltZW91dCgyNDAwMDApOwogIAogIGF3YWl0IHBhZ2UuZ290bygiL3dldmlhLmh0bWw/Y2I9IiArIERhdGUubm93KCkpOwogIGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4geyB0cnl7c2Vzc2lvblN0b3JhZ2UuY2xlYXIoKTsgbG9jYWxTdG9yYWdlLmNsZWFyKCk7fWNhdGNoKGUpe30gfSk7CiAgYXdhaXQgcGFnZS53YWl0Rm9yTG9hZFN0YXRlKCJuZXR3b3JraWRsZSIpOwogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoMzUwMCk7CiAgCiAgLy8gVHVybiAxOiBISSAtIHdhaXQgZm9yIENPTVBMRVRFIHJlc3BvbnNlCiAgY29uc3QgaW5wdXQgPSBwYWdlLmxvY2F0b3IoIiNtc2dJbnB1dCIpOwogIGF3YWl0IGlucHV0LmNsaWNrKHtmb3JjZTp0cnVlfSk7CiAgYXdhaXQgaW5wdXQuZmlsbCgiYm9uam91ciIpOwogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoNDAwKTsKICAKICBjb25zdCBiYzAgPSBhd2FpdCBwYWdlLmV2YWx1YXRlKCgpID0+IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoIi5tc2cuYXNzaXN0YW50IikubGVuZ3RoKTsKICBhd2FpdCBpbnB1dC5wcmVzcygiRW50ZXIiKTsKICBjb25zb2xlLmxvZygi8J+TpCBUMTogYm9uam91ciBzZW50Iik7CiAgCiAgLy8gV2FpdCBmb3IgYXNzaXN0YW50IGNvdW50IHRvIGdyb3cgQU5EIGJ1c3kgZmxhZyB0byByZWxlYXNlCiAgY29uc3Qgd3MxID0gRGF0ZS5ub3coKTsKICB3aGlsZSAoRGF0ZS5ub3coKSAtIHdzMSA8IDkwMDAwKSB7CiAgICBjb25zdCBzID0gYXdhaXQgcGFnZS5ldmFsdWF0ZSgoYmMpID0+ICh7CiAgICAgIGNudDogZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgiLm1zZy5hc3Npc3RhbnQiKS5sZW5ndGgsCiAgICAgIGJ1c3k6IHdpbmRvdy5idXN5IHx8IGZhbHNlLAogICAgICBkaXNhYmxlZDogZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNlbmRCdG4iKT8uZGlzYWJsZWQgfHwgZmFsc2UsCiAgICB9KSwgYmMwKTsKICAgIGlmIChzLmNudCA+IGJjMCAmJiAhcy5idXN5ICYmICFzLmRpc2FibGVkKSBicmVhazsKICAgIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoMTUwMCk7CiAgfQogIGNvbnNvbGUubG9nKGAgIOKchSBUMSBkb25lIGluICR7KChEYXRlLm5vdygpLXdzMSkvMTAwMCkudG9GaXhlZCgxKX1zYCk7CiAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDQtMDEtaGktZG9uZS5wbmciIH0pOwogIAogIC8vIFR1cm4gMjogUERGIHJlcXVlc3QKICBhd2FpdCBpbnB1dC5jbGljayh7Zm9yY2U6dHJ1ZX0pOwogIGF3YWl0IHBhZ2Uua2V5Ym9hcmQucHJlc3MoIkNvbnRyb2wrQSIpOwogIGF3YWl0IHBhZ2Uua2V5Ym9hcmQucHJlc3MoIkRlbGV0ZSIpOwogIGF3YWl0IGlucHV0LmZpbGwoImZhaXMgbW9pIHVuIHBkZiBwcmVtaXVtIGRlIGNvbXBhcmFpc29uIFdFVklBIHZlcnN1cyBPUFVTIGF2ZWMgYXZhbnRhZ2VzLCBpbmNvbnZlbmllbnRzLCBjb3V0cywgcGVyZm9ybWFuY2VzLCBpbnRlZ3JhdGlvbnMiKTsKICBhd2FpdCBwYWdlLndhaXRGb3JUaW1lb3V0KDQwMCk7CiAgCiAgY29uc3QgYmMxID0gYXdhaXQgcGFnZS5ldmFsdWF0ZSgoKSA9PiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCIubXNnLmFzc2lzdGFudCIpLmxlbmd0aCk7CiAgYXdhaXQgaW5wdXQucHJlc3MoIkVudGVyIik7CiAgY29uc29sZS5sb2coIvCfk6QgVDI6IFBERiByZXF1ZXN0IHNlbnQgwrcgd2FpdGluZy4uLiIpOwogIAogIGNvbnN0IHdzMiA9IERhdGUubm93KCk7CiAgbGV0IHBkZkZvdW5kID0gZmFsc2U7CiAgbGV0IHBkZlVybCA9IG51bGw7CiAgbGV0IGxhc3RUZXh0ID0gIiI7CiAgCiAgd2hpbGUgKERhdGUubm93KCkgLSB3czIgPCAxMjAwMDApIHsKICAgIGNvbnN0IHMgPSBhd2FpdCBwYWdlLmV2YWx1YXRlKChiYykgPT4gewogICAgICBjb25zdCBtc2dzID0gQXJyYXkuZnJvbShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCIubXNnLmFzc2lzdGFudCIpKTsKICAgICAgY29uc3QgbGFzdCA9IG1zZ3MubGVuZ3RoID4gYmMgPyBtc2dzW21zZ3MubGVuZ3RoLTFdIDogbnVsbDsKICAgICAgaWYgKCFsYXN0KSByZXR1cm4geyBjbnQ6IG1zZ3MubGVuZ3RoLCBwZGY6IG51bGwsIHRleHQ6ICIiLCBsaW5rczogMCB9OwogICAgICBjb25zdCBwZGZMaW5rID0gbGFzdC5xdWVyeVNlbGVjdG9yKCdhW2hyZWYqPSIucGRmIl0nKTsKICAgICAgY29uc3QgbGlua3MgPSBsYXN0LnF1ZXJ5U2VsZWN0b3JBbGwoJ2EnKS5sZW5ndGg7CiAgICAgIHJldHVybiB7CiAgICAgICAgY250OiBtc2dzLmxlbmd0aCwKICAgICAgICBwZGZfdXJsOiBwZGZMaW5rID8gcGRmTGluay5ocmVmIDogbnVsbCwKICAgICAgICB0ZXh0OiAobGFzdC5xdWVyeVNlbGVjdG9yKCIuYnViYmxlIik/LmlubmVyVGV4dCB8fCAiIikuc3Vic3RyaW5nKDAsIDQwMCksCiAgICAgICAgbGlua3M6IGxpbmtzLAogICAgICB9OwogICAgfSwgYmMxKTsKICAgIGlmIChzLnBkZl91cmwpIHsKICAgICAgcGRmRm91bmQgPSB0cnVlOyBwZGZVcmwgPSBzLnBkZl91cmw7IGxhc3RUZXh0ID0gcy50ZXh0OwogICAgICBicmVhazsKICAgIH0KICAgIGxhc3RUZXh0ID0gcy50ZXh0OwogICAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCgyNTAwKTsKICB9CiAgCiAgY29uc3QgZWwgPSAoKERhdGUubm93KCktd3MyKS8xMDAwKS50b0ZpeGVkKDEpOwogIGNvbnNvbGUubG9nKGBcbuKVkOKVkOKVkCBSRVNVTFQgYWZ0ZXIgJHtlbH1zIOKVkOKVkOKVkGApOwogIGNvbnNvbGUubG9nKGAgIOKchSBQREYgZ2VuZXJhdGVkOiAke3BkZkZvdW5kfWApOwogIGNvbnNvbGUubG9nKGAgIFVSTDogJHtwZGZVcmx9YCk7CiAgY29uc29sZS5sb2coYCAgVGV4dDogJHtsYXN0VGV4dC5zdWJzdHJpbmcoMCwyMDApLnJlcGxhY2UoL1xuL2csJyAnKX1gKTsKICAKICBhd2FpdCBwYWdlLnNjcmVlbnNob3QoeyBwYXRoOiAib3V0cHV0L3Y0NC0wMi1wZGYtcmVzdWx0LnBuZyIsIGZ1bGxQYWdlOiB0cnVlIH0pOwogIAogIGlmIChwZGZGb3VuZCkgewogICAgLy8gQ2xpY2sgdGhlIFBERiBsaW5rIChvciBqdXN0IHZlcmlmeSkKICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBwYWdlLmV2YWx1YXRlKGFzeW5jICh1cmwpID0+IHsKICAgICAgY29uc3QgciA9IGF3YWl0IGZldGNoKHVybCwge21ldGhvZDonSEVBRCd9KTsKICAgICAgcmV0dXJuIHsgc3RhdHVzOiByLnN0YXR1cywgc2l6ZTogci5oZWFkZXJzLmdldCgnY29udGVudC1sZW5ndGgnKSwgdHlwZTogci5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJykgfTsKICAgIH0sIHBkZlVybCk7CiAgICBjb25zb2xlLmxvZyhgICBIVFRQIEhFQUQ6ICR7SlNPTi5zdHJpbmdpZnkocmVzcCl9YCk7CiAgfQp9KTsK");
|
||||
foreach (glob("$base/*.spec.js") as $old) @unlink($old);
|
||||
$written = @file_put_contents("$base/v44-pdf-proof.spec.js", $spec);
|
||||
echo json_encode(["written" => $written]);
|
||||
7
api/ambre-pw-v45-deploy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$base = "/var/www/html/api/ambre-pw-tests/tests";
|
||||
$spec = base64_decode("Y29uc3QgeyB0ZXN0IH0gPSByZXF1aXJlKCJAcGxheXdyaWdodC90ZXN0Iik7Cgp0ZXN0KCJWNDUgwrcgUFJPT0YgwrcgTXVsdGktQWdlbnQgUGFyYWxsZWwgUERGIFdFVklBIE9QVVMiLCBhc3luYyAoeyBwYWdlIH0pID0+IHsKICB0ZXN0LnNldFRpbWVvdXQoMjQwMDAwKTsKICAKICBhd2FpdCBwYWdlLmdvdG8oIi93ZXZpYS5odG1sP2NiPSIgKyBEYXRlLm5vdygpKTsKICBhd2FpdCBwYWdlLmV2YWx1YXRlKCgpID0+IHsgdHJ5e3Nlc3Npb25TdG9yYWdlLmNsZWFyKCk7fWNhdGNoKGUpe30gfSk7CiAgYXdhaXQgcGFnZS53YWl0Rm9yTG9hZFN0YXRlKCJuZXR3b3JraWRsZSIpOwogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoMzUwMCk7CiAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDUtMDAtc3RhcnQucG5nIiB9KTsKICAKICAvLyBUdXJuIDE6IGJvbmpvdXIgKHdhcm0gdXApCiAgY29uc3QgaW5wdXQgPSBwYWdlLmxvY2F0b3IoIiNtc2dJbnB1dCIpOwogIGF3YWl0IGlucHV0LmNsaWNrKHtmb3JjZTp0cnVlfSk7CiAgYXdhaXQgaW5wdXQuZmlsbCgiYm9uam91ciIpOwogIGF3YWl0IGlucHV0LnByZXNzKCJFbnRlciIpOwogIAogIGNvbnN0IHdzMSA9IERhdGUubm93KCk7CiAgd2hpbGUgKERhdGUubm93KCkgLSB3czEgPCA2MDAwMCkgewogICAgY29uc3QgYiA9IGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4gd2luZG93LmJ1c3kgfHwgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNlbmRCdG4iKT8uZGlzYWJsZWQpOwogICAgaWYgKCFiKSBicmVhazsKICAgIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoMTAwMCk7CiAgfQogIGNvbnNvbGUubG9nKGBUMSBib25qb3VyIGRvbmUgaW4gJHsoKERhdGUubm93KCktd3MxKS8xMDAwKS50b0ZpeGVkKDEpfXNgKTsKICBhd2FpdCBwYWdlLnNjcmVlbnNob3QoeyBwYXRoOiAib3V0cHV0L3Y0NS0wMS1oaS5wbmciIH0pOwogIAogIC8vIFR1cm4gMjogTVVMVEktQUdFTlQgcmVxdWVzdAogIGF3YWl0IGlucHV0LmNsaWNrKHtmb3JjZTp0cnVlfSk7CiAgYXdhaXQgcGFnZS5rZXlib2FyZC5wcmVzcygiQ29udHJvbCtBIik7CiAgYXdhaXQgcGFnZS5rZXlib2FyZC5wcmVzcygiRGVsZXRlIik7CiAgY29uc3QgbXNnID0gImNvbXBhcmUgV0VWSUEgYXZlYyBPUFVTIHN1ciBhcmNoaXRlY3R1cmUsIGNvdXRzLCBwZXJmb3JtYW5jZXMgZXQgc2VjdXJpdGUgZW4gYW5hbHlzZSBjb21wbGV0ZSBtdWx0aS1hbmdsZSI7CiAgYXdhaXQgaW5wdXQuZmlsbChtc2cpOwogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoNDAwKTsKICAKICBjb25zdCBiYyA9IGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgiLm1zZy5hc3Npc3RhbnQiKS5sZW5ndGgpOwogIGF3YWl0IGlucHV0LnByZXNzKCJFbnRlciIpOwogIGNvbnNvbGUubG9nKGDwn5OkIE11bHRpLWFnZW50IHNlbnQgwrcgbXNnOiAke21zZy5zdWJzdHJpbmcoMCw4MCl9YCk7CiAgCiAgY29uc3Qgd3MyID0gRGF0ZS5ub3coKTsKICBsZXQgZG9uZSA9IGZhbHNlOwogIGxldCBhZ2VudENvdW50ID0gMDsKICBsZXQgaGFzQmFkZ2VzID0gZmFsc2U7CiAgCiAgd2hpbGUgKERhdGUubm93KCkgLSB3czIgPCAxODAwMDApIHsKICAgIGNvbnN0IHMgPSBhd2FpdCBwYWdlLmV2YWx1YXRlKChiYykgPT4gewogICAgICBjb25zdCBtc2dzID0gQXJyYXkuZnJvbShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCIubXNnLmFzc2lzdGFudCIpKTsKICAgICAgY29uc3QgbGFzdCA9IG1zZ3MubGVuZ3RoID4gYmMgPyBtc2dzW21zZ3MubGVuZ3RoLTFdIDogbnVsbDsKICAgICAgaWYgKCFsYXN0KSByZXR1cm4geyBjbnQ6IG1zZ3MubGVuZ3RoLCBiYWRnZXM6IDAsIGFnZW50czogMCwgdGV4dF9zaXplOiAwIH07CiAgICAgIHJldHVybiB7CiAgICAgICAgY250OiBtc2dzLmxlbmd0aCwKICAgICAgICBiYWRnZXM6IGxhc3QucXVlcnlTZWxlY3RvckFsbCgiLm54LWJhZGdlIikubGVuZ3RoLAogICAgICAgIGFnZW50c19ibG9ja3M6IGxhc3QuaW5uZXJIVE1MLm1hdGNoKC9hZ2VudMK3fPCfpJZ8TXVsdGktQWdlbnQvZ2kpPy5sZW5ndGggfHwgMCwKICAgICAgICBoYXNfc3ludGg6IC9TeW50aMOoc2UgY29uc29saWTDqWUvLnRlc3QobGFzdC5pbm5lckhUTUwpLAogICAgICAgIHRleHRfc2l6ZTogKGxhc3QucXVlcnlTZWxlY3RvcigiLmJ1YmJsZSIpPy5pbm5lckhUTUwgfHwgIiIpLmxlbmd0aCwKICAgICAgfTsKICAgIH0sIGJjKTsKICAgIAogICAgaWYgKHMuaGFzX3N5bnRoKSB7CiAgICAgIGRvbmUgPSB0cnVlOwogICAgICBhZ2VudENvdW50ID0gcy5hZ2VudHNfYmxvY2tzOwogICAgICBoYXNCYWRnZXMgPSBzLmJhZGdlcyA+IDA7CiAgICAgIGNvbnNvbGUubG9nKGDinIUgTXVsdGktYWdlbnQgZG9uZSDCtyBiYWRnZXM9JHtzLmJhZGdlc30gwrcgYWdlbnRzX2Jsb2Nrcz0ke3MuYWdlbnRzX2Jsb2Nrc30gwrcgaHRtbF9zaXplPSR7cy50ZXh0X3NpemV9QmApOwogICAgICBicmVhazsKICAgIH0KICAgIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoMjUwMCk7CiAgfQogIAogIGNvbnN0IGVsID0gKChEYXRlLm5vdygpLXdzMikvMTAwMCkudG9GaXhlZCgxKTsKICBjb25zb2xlLmxvZyhgXG7ilZDilZDilZAgUkVTVUxUIGluICR7ZWx9cyDCtyBkb25lPSR7ZG9uZX0g4pWQ4pWQ4pWQYCk7CiAgCiAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDUtMDItbXVsdGlhZ2VudC5wbmciLCBmdWxsUGFnZTogdHJ1ZSB9KTsKICBhd2FpdCBwYWdlLndhaXRGb3JUaW1lb3V0KDE1MDApOwogIGF3YWl0IHBhZ2Uuc2NyZWVuc2hvdCh7IHBhdGg6ICJvdXRwdXQvdjQ1LTAzLXNjcm9sbGVkLnBuZyIgfSk7Cn0pOwo=");
|
||||
foreach (glob("$base/*.spec.js") as $old) @unlink($old);
|
||||
$written = @file_put_contents("$base/v45-multiagent.spec.js", $spec);
|
||||
echo json_encode(["written" => $written]);
|
||||
7
api/ambre-pw-v46-deploy.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$base = "/var/www/html/api/ambre-pw-tests/tests";
|
||||
$spec = base64_decode("Y29uc3QgeyB0ZXN0IH0gPSByZXF1aXJlKCJAcGxheXdyaWdodC90ZXN0Iik7Cgp0ZXN0KCJWNDYgwrcgRGVidWcgVjExIHRyaWdnZXJzICsgY29uc29sZSBsb2dzIiwgYXN5bmMgKHsgcGFnZSB9KSA9PiB7CiAgdGVzdC5zZXRUaW1lb3V0KDIwMDAwMCk7CiAgY29uc3QgbG9ncyA9IFtdOwogIGNvbnN0IGVycnMgPSBbXTsKICBwYWdlLm9uKCJjb25zb2xlIiwgbSA9PiBsb2dzLnB1c2goe3R5cGU6bS50eXBlKCksIHRleHQ6bS50ZXh0KCkuc3Vic3RyaW5nKDAsMjAwKX0pKTsKICBwYWdlLm9uKCJwYWdlZXJyb3IiLCBlID0+IGVycnMucHVzaChlLm1lc3NhZ2Uuc3Vic3RyaW5nKDAsMjAwKSkpOwogIAogIGF3YWl0IHBhZ2UuZ290bygiL3dldmlhLmh0bWw/Y2I9IiArIERhdGUubm93KCkpOwogIGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4geyB0cnl7c2Vzc2lvblN0b3JhZ2UuY2xlYXIoKTt9Y2F0Y2goZSl7fSB9KTsKICBhd2FpdCBwYWdlLndhaXRGb3JMb2FkU3RhdGUoIm5ldHdvcmtpZGxlIik7CiAgYXdhaXQgcGFnZS53YWl0Rm9yVGltZW91dCgzMDAwKTsKICAKICAvLyBTa2lwIEhJIC0gc3RyYWlnaHQgdG8gbXVsdGktYWdlbnQKICBjb25zdCBpbnB1dCA9IHBhZ2UubG9jYXRvcigiI21zZ0lucHV0Iik7CiAgYXdhaXQgaW5wdXQuY2xpY2soe2ZvcmNlOnRydWV9KTsKICBhd2FpdCBpbnB1dC5maWxsKCJjb21wYXJlIFdFVklBIGF2ZWMgT1BVUyBzdXIgYXJjaGl0ZWN0dXJlLCBjb3V0cywgc2VjdXJpdGUgZW4gYW5hbHlzZSBjb21wbGV0ZSBtdWx0aS1hbmdsZSIpOwogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoNTAwKTsKICBhd2FpdCBpbnB1dC5wcmVzcygiRW50ZXIiKTsKICAKICBjb25zb2xlLmxvZygiV2FpdGluZyBtdWx0aS1hZ2VudC4uLiIpOwogIGF3YWl0IHBhZ2Uud2FpdEZvclRpbWVvdXQoMTUwMDAwKTsgIC8vIHdhaXQgMi41bWluIGZvciByZXNwb25zZQogIAogIGNvbnNvbGUubG9nKCJcbj09PSBDb25zb2xlIGxvZ3MgPT09Iik7CiAgbG9ncy5maWx0ZXIobCA9PiBsLnRleHQuaW5jbHVkZXMoIlYxMSIpIHx8IGwudGV4dC5pbmNsdWRlcygibXVsdGkiKSB8fCBsLnR5cGUgPT09ICJlcnJvciIpLmZvckVhY2gobCA9PiB7CiAgICBjb25zb2xlLmxvZyhgICBbJHtsLnR5cGV9XSAke2wudGV4dH1gKTsKICB9KTsKICBjb25zb2xlLmxvZygiXG49PT0gRXJyb3JzID09PSIpOwogIGVycnMuZm9yRWFjaChlID0+IGNvbnNvbGUubG9nKGAgICR7ZX1gKSk7CiAgCiAgYXdhaXQgcGFnZS5zY3JlZW5zaG90KHsgcGF0aDogIm91dHB1dC92NDYtcmVzdWx0LnBuZyIsIGZ1bGxQYWdlOiB0cnVlIH0pOwogIAogIC8vIEV4dHJhY3QgbGFzdCBhc3Npc3RhbnQgbWVzc2FnZQogIGNvbnN0IGxhc3QgPSBhd2FpdCBwYWdlLmV2YWx1YXRlKCgpID0+IHsKICAgIGNvbnN0IG1zZ3MgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCIubXNnLmFzc2lzdGFudCIpOwogICAgaWYgKG1zZ3MubGVuZ3RoID09PSAwKSByZXR1cm4gIm5vIG1zZyI7CiAgICBjb25zdCBsID0gbXNnc1ttc2dzLmxlbmd0aC0xXTsKICAgIHJldHVybiB7CiAgICAgIHRleHQ6IChsLnF1ZXJ5U2VsZWN0b3IoIi5idWJibGUiKT8uaW5uZXJUZXh0IHx8ICIiKS5zdWJzdHJpbmcoMCwgNDAwKSwKICAgICAgaGFzX3N5bnRoOiAvU3ludGhbZcOoXXNlIGNvbnNvbGlkLy50ZXN0KGwuaW5uZXJIVE1MKSwKICAgICAgYmFkZ2VzOiBsLnF1ZXJ5U2VsZWN0b3JBbGwoIi5ueC1iYWRnZSIpLmxlbmd0aCwKICAgICAgaHRtbF9sZW46IGwuaW5uZXJIVE1MLmxlbmd0aCwKICAgIH07CiAgfSk7CiAgY29uc29sZS5sb2coIlxuPT09IExhc3QgbXNnID09PSIpOwogIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGxhc3QsIG51bGwsIDIpKTsKfSk7Cg==");
|
||||
foreach (glob("$base/*.spec.js") as $old) @unlink($old);
|
||||
$written = @file_put_contents("$base/v46-debug.spec.js", $spec);
|
||||
echo json_encode(["written" => $written]);
|
||||
3
api/ambre-sc-read.php
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
header("Content-Type: text/plain");
|
||||
echo @file_get_contents("/var/www/html/api/ambre-session-chat.php");
|
||||
41
api/ambre-scan-247.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$out = [];
|
||||
chdir("/var/www/html");
|
||||
$out["recent_tags"] = array_filter(array_map("trim", explode("\n", @shell_exec("git tag -l 'wave-*' --sort=-creatordate 2>&1 | head -10"))));
|
||||
$out["recent_commits"] = array_filter(array_map("trim", explode("\n", @shell_exec("git log --since='30 minutes ago' --oneline 2>&1 | head -10"))));
|
||||
|
||||
// Multi-agent infrastructure
|
||||
$out["multiagent_files"] = [];
|
||||
foreach (["ambre-master-multiagent.php", "wevia-autonomous.php", "weval-master-api.php", "wevia-multiagent.php", "multiagent-orchestrator.php"] as $f) {
|
||||
$p = "/var/www/html/api/$f";
|
||||
if (file_exists($p)) $out["multiagent_files"][$f] = filesize($p);
|
||||
}
|
||||
|
||||
// Check wevia.html V9 state
|
||||
$w = @file_get_contents("/var/www/html/wevia.html");
|
||||
$out["wevia"] = [
|
||||
"size" => strlen($w),
|
||||
"v9_wave247_ok_check" => strpos($w, "data.ok || data.success") !== false,
|
||||
"v9_pattern_widened" => strpos($w, "veux|besoin|demande|fais|cree") !== false,
|
||||
"v5_memory" => strpos($w, "AMBRE-V5-MEMORY") !== false,
|
||||
"v10_mermaid" => strpos($w, "AMBRE-V10-MERMAID") !== false,
|
||||
"mode_select" => strpos($w, "mode.*auto") !== false,
|
||||
];
|
||||
|
||||
// Cascade + semaphore
|
||||
$out["cascade_up"] = @file_get_contents("http://127.0.0.1:4000/health", false, stream_context_create(["http"=>["timeout"=>3]])) ? "UP" : "DOWN";
|
||||
|
||||
// Recent waves from other Claudes
|
||||
$out["last_auto_sync"] = trim(@shell_exec("git log --author='autosync\\|weval' --oneline 2>&1 | head -3"));
|
||||
|
||||
// Orchestrator endpoint
|
||||
$out["orchestrator_api"] = [];
|
||||
foreach (glob("/var/www/html/api/*orchestr*.php") as $f) {
|
||||
$out["orchestrator_api"][] = basename($f);
|
||||
}
|
||||
|
||||
// Current load
|
||||
$out["load"] = trim(@shell_exec("uptime"));
|
||||
|
||||
echo json_encode($out, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
42
api/ambre-scan-v11.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$out = [];
|
||||
|
||||
chdir("/var/www/html");
|
||||
$out["recent_tags"] = array_filter(array_map("trim", explode("\n", @shell_exec("git tag -l 'wave-*' --sort=-creatordate 2>&1 | head -10"))));
|
||||
|
||||
// Check V11 errors via direct fetch sim
|
||||
$t0 = microtime(true);
|
||||
$test = @file_get_contents("http://127.0.0.1/api/ambre-multiagent-parallel.php", false, stream_context_create([
|
||||
"http"=>["method"=>"POST","header"=>"Content-Type: application/json\r\n",
|
||||
"content"=>json_encode(["goal"=>"compare A avec B sur X, Y, Z en analyse complete","max_agents"=>3]),
|
||||
"timeout"=>90]
|
||||
]));
|
||||
$out["ma_endpoint_ms"] = round((microtime(true)-$t0)*1000);
|
||||
$out["ma_response_size"] = strlen($test ?: "FAIL");
|
||||
$out["ma_response_head"] = substr($test ?: "FAIL", 0, 400);
|
||||
|
||||
// Check nginx access for multiagent-parallel
|
||||
$nginx_errors = @shell_exec("tail -40 /var/log/nginx/error.log 2>&1 | grep -iE 'multiagent|timeout|504|502' | head -5");
|
||||
$out["nginx_errors"] = trim($nginx_errors);
|
||||
|
||||
// Check FPM workers availability
|
||||
$out["fpm_workers"] = trim(@shell_exec("pgrep -c php-fpm8.5 2>&1"));
|
||||
$out["load"] = trim(@shell_exec("uptime"));
|
||||
|
||||
// WEVIA Master state (private page)
|
||||
$master = @file_get_contents("/var/www/html/wevia-master.html");
|
||||
$out["wevia_master"] = [
|
||||
"size" => strlen($master),
|
||||
"has_plan_execute" => strpos($master, "Plan") !== false && strpos($master, "Execute") !== false,
|
||||
"has_multiagent" => strpos($master, "multiagent") !== false || strpos($master, "parallel") !== false,
|
||||
];
|
||||
|
||||
// Widget public root /
|
||||
$root_idx = @file_get_contents("/var/www/html/index.html");
|
||||
$out["root_index"] = [
|
||||
"size" => strlen($root_idx ?? ""),
|
||||
"has_wevia_widget" => strpos($root_idx ?? "", "wevia") !== false,
|
||||
];
|
||||
|
||||
echo json_encode($out, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
|
||||
31
api/ambre-v0-exclude.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$path = "/var/www/html/wevia.html";
|
||||
|
||||
// Unlock first
|
||||
$attr = trim(shell_exec("lsattr $path 2>&1"));
|
||||
|
||||
$c = @file_get_contents($path);
|
||||
$orig = strlen($c);
|
||||
|
||||
// Patch V0 to exclude multi-agent patterns
|
||||
$old = 'var _is_gen_cmd = /pdf|rapport|docx?|word|excel|xlsx?|pptx?|powerpoint|sch[eé]ma|diagramme|mermaid|image|photo|dessin|qr\\s*code|tts|lis[ -]|calcule|combien|code|traduis|cherche|recherche|actualit[eé]|search|news|latest|youtube|r[eé]sume|summari/i.test(text);';
|
||||
|
||||
$new = 'var _is_gen_cmd = /pdf|rapport|docx?|word|excel|xlsx?|pptx?|powerpoint|sch[eé]ma|diagramme|mermaid|image|photo|dessin|qr\\s*code|tts|lis[ -]|calcule|combien|code|traduis|cherche|recherche|actualit[eé]|search|news|latest|youtube|r[eé]sume|summari|compar[ez]?|analyse|multi.?agent|parall[eè]le|360|bilan/i.test(text);';
|
||||
|
||||
if (strpos($c, $old) === false) {
|
||||
echo json_encode(["error"=>"V0 pattern not found"]);
|
||||
exit;
|
||||
}
|
||||
$c = str_replace($old, $new, $c);
|
||||
|
||||
$backup = "/opt/wevads/vault/wevia.html.GOLD-" . date("Ymd-His") . "-wave255-v0-exclude";
|
||||
@copy($path, $backup);
|
||||
$wrote = @file_put_contents($path, $c);
|
||||
|
||||
echo json_encode([
|
||||
"delta" => strlen($c) - $orig,
|
||||
"wrote" => $wrote,
|
||||
"backup" => basename($backup),
|
||||
"attr_before" => $attr,
|
||||
]);
|
||||
41
api/ambre-v11-debug.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$path = "/var/www/html/wevia.html";
|
||||
$c = @file_get_contents($path);
|
||||
|
||||
// Patch V11 fetch : add console.log trigger message + AbortController with 120s
|
||||
$old = "var _ma_start = performance.now();
|
||||
fetch(\"/api/ambre-multiagent-parallel.php\", {
|
||||
method: \"POST\",
|
||||
headers: {\"Content-Type\":\"application/json\"},
|
||||
body: JSON.stringify({goal: text, max_agents: 5})
|
||||
})";
|
||||
|
||||
$new = "console.log(\"[V11-MULTIAGENT] triggered for text:\", text.substring(0,80));
|
||||
var _ma_start = performance.now();
|
||||
var _ma_ctrl = new AbortController();
|
||||
var _ma_timeout = setTimeout(function(){ _ma_ctrl.abort(); }, 120000);
|
||||
fetch(\"/api/ambre-multiagent-parallel.php\", {
|
||||
method: \"POST\",
|
||||
headers: {\"Content-Type\":\"application/json\"},
|
||||
body: JSON.stringify({goal: text, max_agents: 5}),
|
||||
signal: _ma_ctrl.signal
|
||||
})
|
||||
.then(function(r){ clearTimeout(_ma_timeout); console.log(\"[V11] response status\", r.status); return r; })";
|
||||
|
||||
if (strpos($c, $old) === false) {
|
||||
echo json_encode(["error"=>"V11 fetch pattern not found"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$c = str_replace($old, $new, $c);
|
||||
|
||||
$backup = "/opt/wevads/vault/wevia.html.GOLD-" . date("Ymd-His") . "-wave258-v11-debug";
|
||||
@copy($path, $backup);
|
||||
$wrote = @file_put_contents($path, $c);
|
||||
|
||||
echo json_encode([
|
||||
"delta" => strlen($c) - strlen(@file_get_contents($backup)),
|
||||
"wrote" => $wrote,
|
||||
"backup" => basename($backup),
|
||||
]);
|
||||
23
api/ambre-v9-ok.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$path = "/var/www/html/wevia.html";
|
||||
$c = @file_get_contents($path);
|
||||
$orig = strlen($c);
|
||||
|
||||
$old = "if (data && data.success) {";
|
||||
$new = "if (data && (data.ok || data.success)) {";
|
||||
|
||||
if (strpos($c, $old) === false) {
|
||||
echo json_encode(["error"=>"V9 success check not found"]);
|
||||
exit;
|
||||
}
|
||||
$c = str_replace($old, $new, $c);
|
||||
|
||||
$backup = "/opt/wevads/vault/wevia.html.GOLD-" . date("Ymd-His") . "-wave247-v9-ok";
|
||||
@copy($path, $backup);
|
||||
$wrote = @file_put_contents($path, $c);
|
||||
|
||||
echo json_encode([
|
||||
"delta" => strlen($c) - $orig,
|
||||
"wrote" => $wrote,
|
||||
]);
|
||||
28
api/ambre-v9-widen.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$path = "/var/www/html/wevia.html";
|
||||
$c = @file_get_contents($path);
|
||||
$orig = strlen($c);
|
||||
|
||||
// Old pattern (too strict)
|
||||
$old_pat = "var _pdf_premium_pat = /(?:pdf|rapport)\\s+(?:premium|qualit[eé]|pro|professionnel|avec\\s+graphique|hd|chart)|(?:cr[eé]e[zr]?|g[eé]n[eè]re[zr]?|fais|fait|produi[st])\\s+(?:un\\s+)?(?:rapport|pdf)\\s+(?:premium|pro|complet|avec\\s+graphique|hd|qualit[eé])/i;";
|
||||
|
||||
// New pattern - broader: any PDF intention including ALL CAPS
|
||||
$new_pat = "var _pdf_premium_pat = /(?:veux|besoin|demande|fais|cree|g[eé]n[eé]re|produi[st]|export|donne|realise|create|make|generate|want|need)\\s+.{0,40}?\\bpdf\\b|\\bpdf\\b\\s+.{0,40}?(?:premium|qualit[eé]|pro|professionnel|avec|chart|graphique|compar|tableau|compl|hd)|\\b(?:rapport|comparaison|comparer|compare)\\b.{0,50}\\bpdf\\b|\\bpdf\\b.{0,50}\\b(?:rapport|comparaison|comparer|compare)\\b|^\\s*pdf\\s+/i;";
|
||||
|
||||
if (strpos($c, $old_pat) === false) {
|
||||
echo json_encode(["error"=>"V9 pattern not found"]);
|
||||
exit;
|
||||
}
|
||||
$c = str_replace($old_pat, $new_pat, $c);
|
||||
|
||||
$backup = "/opt/wevads/vault/wevia.html.GOLD-" . date("Ymd-His") . "-wave247-v9-widen";
|
||||
@copy($path, $backup);
|
||||
$wrote = @file_put_contents($path, $c);
|
||||
|
||||
echo json_encode([
|
||||
"delta" => strlen($c) - $orig,
|
||||
"wrote" => $wrote,
|
||||
"backup" => basename($backup),
|
||||
"new_pattern" => $new_pat,
|
||||
]);
|
||||
106
api/ambre-wire-v11.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$path = "/var/www/html/wevia.html";
|
||||
$c = @file_get_contents($path);
|
||||
$orig = strlen($c);
|
||||
|
||||
if (strpos($c, "AMBRE-V11-MULTIAGENT") !== false) {
|
||||
echo json_encode(["already"=>true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Insert BEFORE V10-MERMAID (so multi-agent catches complex requests first)
|
||||
$anchor = " // === AMBRE-V10-MERMAID 2026-04-22";
|
||||
$pos = strpos($c, $anchor);
|
||||
if ($pos === false) {
|
||||
echo json_encode(["error"=>"V10 anchor not found"]);
|
||||
exit;
|
||||
}
|
||||
$line_start = strrpos(substr($c, 0, $pos), "\n") + 1;
|
||||
|
||||
$v11 = ' // === AMBRE-V11-MULTIAGENT 2026-04-22 · wave-255 · Plan → Execute N agents parallel → Reconcile ===
|
||||
// Triggers : "analyse", "complet", "rapport complet", "compare X avec Y", "multi agent", "plusieurs", "en parallele"
|
||||
var _multiagent_pat = /(?:analyse\s+compl[eè]te|rapport\s+complet|bilan\s+complet|compare[rz]?\s+.{3,}\s+(?:avec|vs|contre|et)\s+|multi[- ]?agent|plusieurs\s+angles|en\s+parall[eè]le|synth[eè]se\s+compl[eè]te|analyse\s+360|\ballonsy\b|\bdispatch\b)/i;
|
||||
if (_multiagent_pat.test(text) && text.length > 40) {
|
||||
if (typeof showThinking === "function") showThinking();
|
||||
busy = true;
|
||||
try{var sb=document.getElementById("sendBtn");if(sb)sb.disabled=true;}catch(e){}
|
||||
|
||||
var _ma_start = performance.now();
|
||||
fetch("/api/ambre-multiagent-parallel.php", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type":"application/json"},
|
||||
body: JSON.stringify({goal: text, max_agents: 5})
|
||||
})
|
||||
.then(function(r){ return r.json(); })
|
||||
.then(function(data){
|
||||
if (typeof hideThinking === "function") hideThinking();
|
||||
busy = false;
|
||||
try{var sb=document.getElementById("sendBtn");if(sb)sb.disabled=false;}catch(e){}
|
||||
try{var mi=document.getElementById("msgInput");if(mi){mi.value="";mi.disabled=false;}}catch(e){}
|
||||
|
||||
if (!data || !data.ok) {
|
||||
addMsg("assistant", "❌ Multi-agent erreur: " + ((data && data.error) || "reessayez"), "0");
|
||||
return;
|
||||
}
|
||||
|
||||
var el = ((performance.now() - _ma_start) / 1000).toFixed(1);
|
||||
|
||||
// Build rich HTML response
|
||||
var badges = "<div style=\"display:flex;gap:6px;flex-wrap:wrap;margin:8px 0\">" +
|
||||
"<span class=\"nx-badge\" style=\"background:rgba(99,102,241,.15);color:#6366f1\">🧠 Multi-Agent</span>" +
|
||||
"<span class=\"nx-badge\" style=\"background:rgba(16,185,129,.15);color:#10b981\">" + data.agents_count + " agents ∥</span>" +
|
||||
"<span class=\"nx-badge\" style=\"background:rgba(245,158,11,.15);color:#f59e0b\">⚡ " + data.parallel_speedup + "x speedup</span>" +
|
||||
"<span class=\"nx-badge\" style=\"background:rgba(139,92,246,.15);color:#8b5cf6\">" + data.total_ms + "ms</span>" +
|
||||
"</div>";
|
||||
|
||||
// Plan
|
||||
var planHtml = "<div style=\"margin:10px 0;padding:12px;background:#eef2ff;border-radius:10px;border-left:3px solid #6366f1\">" +
|
||||
"<div style=\"font-weight:600;color:#4338ca;font-size:13px;margin-bottom:6px\">📋 Plan · " + (data.plan.objective || "") + "</div>" +
|
||||
"<div style=\"font-size:12px;color:#4b5563\">" + data.plan.agents.length + " agents dispatchés en parallèle</div></div>";
|
||||
|
||||
// Agents list
|
||||
var agentsHtml = "<div style=\"margin:10px 0\"><div style=\"font-weight:600;color:#1a1f3a;font-size:13px;margin-bottom:8px\">🤖 Agents · exécution parallèle</div>";
|
||||
data.results.forEach(function(r, i){
|
||||
var icon = {"pdf_premium":"📄","mermaid":"📊","web_search":"🔍","calc":"🧮","kb_search":"📚","none":"💭"}[r.tool] || "⚙️";
|
||||
agentsHtml += "<div style=\"margin:6px 0;padding:10px;background:#fafafa;border-radius:8px;border:1px solid #e5e7eb\">" +
|
||||
"<div style=\"font-size:12px;color:#6366f1;font-weight:600;margin-bottom:4px\">" + icon + " " + r.agent + " · " + r.tool + " · " + r.elapsed_ms + "ms</div>" +
|
||||
"<div style=\"font-size:12px;color:#64748b;line-height:1.4\">" + (r.task || "") + "</div>" +
|
||||
"<div style=\"font-size:11px;color:#94a3b8;margin-top:4px\">" + (r.summary || "").replace(/</g,"<").substring(0, 250) + "</div>" +
|
||||
"</div>";
|
||||
});
|
||||
agentsHtml += "</div>";
|
||||
|
||||
// Reconciled
|
||||
var synthHtml = "<div style=\"margin:12px 0;padding:14px;background:linear-gradient(135deg,#f0f9ff 0%,#eef2ff 100%);border-radius:12px;border-left:3px solid #10b981\">" +
|
||||
"<div style=\"font-weight:600;color:#065f46;font-size:13px;margin-bottom:8px\">✅ Synthèse consolidée</div>" +
|
||||
"<div style=\"font-size:13px;color:#1a1f3a;line-height:1.6;white-space:pre-wrap\">" + (data.reconciled || "").replace(/</g,"<") + "</div>" +
|
||||
"</div>";
|
||||
|
||||
var el_resp = addMsg("assistant", "Multi-agent", el);
|
||||
var bubble = el_resp ? el_resp.querySelector(".bubble") : null;
|
||||
if (bubble) bubble.innerHTML = badges + planHtml + agentsHtml + synthHtml;
|
||||
})
|
||||
.catch(function(err){
|
||||
if (typeof hideThinking === "function") hideThinking();
|
||||
busy = false;
|
||||
try{var sb=document.getElementById("sendBtn");if(sb)sb.disabled=false;}catch(e){}
|
||||
addMsg("assistant", "❌ Multi-agent service indisponible", "0");
|
||||
});
|
||||
return;
|
||||
}
|
||||
// === END AMBRE-V11-MULTIAGENT ===
|
||||
|
||||
';
|
||||
|
||||
$new_c = substr($c, 0, $line_start) . $v11 . substr($c, $line_start);
|
||||
|
||||
$backup = "/opt/wevads/vault/wevia.html.GOLD-" . date("Ymd-His") . "-wave255-v11";
|
||||
@copy($path, $backup);
|
||||
$wrote = @file_put_contents($path, $new_c);
|
||||
|
||||
echo json_encode([
|
||||
"delta" => strlen($new_c) - $orig,
|
||||
"wrote" => $wrote,
|
||||
"backup" => basename($backup),
|
||||
]);
|
||||
23
api/ambre-wtp-wire-cx.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
header("Content-Type: text/plain");
|
||||
$path = "/var/www/html/weval-technology-platform.html";
|
||||
$c = @file_get_contents($path);
|
||||
if (strpos($c, "dashboards-hub-unified") !== false) { echo "already"; exit; }
|
||||
|
||||
$anchor = 'href="/dashboards-index.html"';
|
||||
$pos = strpos($c, $anchor);
|
||||
if ($pos === false) { echo "no anchor"; exit; }
|
||||
|
||||
$a_end = strpos($c, "</a>", $pos) + 4;
|
||||
$link = '<a href="/dashboards-hub-unified.html" class="wtp-link" style="display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,#4338ca,#6366f1);color:#fff;border-radius:6px;text-decoration:none;font-size:12px;font-weight:500;margin:0 4px"><span>📊 Hub Unifié</span></a>';
|
||||
|
||||
$new_c = substr($c, 0, $a_end) . $link . substr($c, $a_end);
|
||||
|
||||
// Write via sudo cat
|
||||
$tmpfile = tempnam("/tmp", "wtp_");
|
||||
file_put_contents($tmpfile, $new_c);
|
||||
// Copy back via sudo
|
||||
$result = shell_exec("sudo cp $tmpfile $path 2>&1");
|
||||
echo "Result: " . $result . "\n";
|
||||
echo "New size: " . strlen($new_c) . "B · delta +" . (strlen($new_c)-strlen($c)) . "B\n";
|
||||
unlink($tmpfile);
|
||||
22
api/ambre-wtp-wire-e2e.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
header("Content-Type: text/plain");
|
||||
$path = "/var/www/html/weval-technology-platform.html";
|
||||
$c = @file_get_contents($path);
|
||||
if (strpos($c, "dashboards-hub-unified") !== false) { echo "already"; exit; }
|
||||
|
||||
$anchor = 'href="/e2e-dashboard.html"';
|
||||
$pos = strpos($c, $anchor);
|
||||
if ($pos === false) { echo "no anchor e2e-dashboard\n"; exit; }
|
||||
|
||||
$a_end = strpos($c, "</a>", $pos) + 4;
|
||||
$link = "\n<a href=\"/dashboards-hub-unified.html\" class=\"wtp-link\" title=\"Hub Dashboards Unifié · 24 dashboards · 13 catégories · wave-246\" style=\"display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,#4338ca,#6366f1);color:#fff;border-radius:6px;text-decoration:none;font-size:12px;font-weight:500;margin:0 4px\"><span>📊 Hub Unifié · 24 dashboards</span></a>";
|
||||
|
||||
$new_c = substr($c, 0, $a_end) . $link . substr($c, $a_end);
|
||||
|
||||
$tmpfile = tempnam("/tmp", "wtp_");
|
||||
file_put_contents($tmpfile, $new_c);
|
||||
$r = shell_exec("sudo cp $tmpfile $path 2>&1");
|
||||
unlink($tmpfile);
|
||||
echo "Result: [$r]\n";
|
||||
echo "New size: " . strlen($new_c) . "B · delta +" . (strlen($new_c)-strlen($c)) . "B\n";
|
||||
echo "Verify content: " . (strpos(file_get_contents($path), "dashboards-hub-unified") !== false ? "YES" : "NO") . "\n";
|
||||
57
api/ambre-wtp-wire.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
header("Content-Type: application/json");
|
||||
$path = "/var/www/html/weval-technology-platform.html";
|
||||
$c = @file_get_contents($path);
|
||||
|
||||
if (strpos($c, "dashboards-hub-unified") !== false) {
|
||||
echo json_encode(["already"=>true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Add the link in banner (find "Arsenal History" or similar anchor)
|
||||
// Use safer approach: add a link block AFTER <body> or before first </div>
|
||||
// Find the existing banner Mega/Arsenal link
|
||||
$anchors = [
|
||||
"href=\"/dashboards-index.html\"" => "AFTER",
|
||||
"href=\"/e2e-dashboard.html\"" => "BEFORE",
|
||||
];
|
||||
|
||||
$injected = false;
|
||||
foreach ($anchors as $anchor => $where) {
|
||||
$pos = strpos($c, $anchor);
|
||||
if ($pos !== false) {
|
||||
// Find surrounding <a> element boundary
|
||||
$a_start = strrpos(substr($c, 0, $pos), "<a ");
|
||||
if ($a_start !== false) {
|
||||
// End of the </a>
|
||||
$a_end = strpos($c, "</a>", $pos);
|
||||
if ($a_end !== false) {
|
||||
$a_end += 4;
|
||||
$link_html = "<a href=\"/dashboards-hub-unified.html\" style=\"display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:linear-gradient(135deg,#4338ca,#6366f1);color:#fff;border-radius:6px;text-decoration:none;font-size:12px;font-weight:500;margin-right:8px\">📊 Hub Unifié</a>";
|
||||
if ($where === "BEFORE") {
|
||||
$new_c = substr($c, 0, $a_start) . $link_html . substr($c, $a_start);
|
||||
} else {
|
||||
$new_c = substr($c, 0, $a_end) . $link_html . substr($c, $a_end);
|
||||
}
|
||||
$c = $new_c;
|
||||
$injected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$injected) {
|
||||
echo json_encode(["error"=>"no anchor found to inject link"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$backup = "/opt/wevads/vault/wtp.GOLD-" . date("Ymd-His") . "-wave246-hub";
|
||||
@copy($path, $backup);
|
||||
$wrote = @file_put_contents($path, $c);
|
||||
|
||||
echo json_encode([
|
||||
"wrote" => $wrote,
|
||||
"size" => strlen($c),
|
||||
"backup" => basename($backup),
|
||||
]);
|
||||
@@ -1,10 +1,49 @@
|
||||
<?php
|
||||
// Opus v19 · Auth check with agent bypass token
|
||||
// - Fallback: PHP session (existing behavior · no regression)
|
||||
// - NEW: X-Agent-Token header OR ?_agent_token= param
|
||||
// - Validated against /etc/weval/secrets.env AGENT_TOKEN (or fallback to DROID2026)
|
||||
|
||||
session_set_cookie_params(["lifetime"=>86400,"path"=>"/","domain"=>".weval-consulting.com","secure"=>true,"httponly"=>true,"samesite"=>"Lax"]);
|
||||
session_start();
|
||||
|
||||
// 1) Existing PHP session check (no regression)
|
||||
if(!empty($_SESSION["weval_auth"]) && $_SESSION["weval_auth"] === true) {
|
||||
http_response_code(200);
|
||||
echo "OK";
|
||||
} else {
|
||||
http_response_code(401);
|
||||
echo "UNAUTHORIZED";
|
||||
exit;
|
||||
}
|
||||
|
||||
// 2) NEW · Agent token bypass (header or query param)
|
||||
$supplied = $_SERVER["HTTP_X_AGENT_TOKEN"] ?? $_GET["_agent_token"] ?? "";
|
||||
|
||||
if ($supplied) {
|
||||
// Load expected from secrets.env
|
||||
$expected = "";
|
||||
if (is_readable("/etc/weval/secrets.env")) {
|
||||
foreach (file("/etc/weval/secrets.env", FILE_IGNORE_NEW_LINES) as $line) {
|
||||
if (strpos($line, "AGENT_TOKEN=") === 0) {
|
||||
$expected = trim(substr($line, strlen("AGENT_TOKEN=")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback to DROID2026 (already trusted via /api/droid)
|
||||
if (!$expected) $expected = "DROID2026";
|
||||
|
||||
if (hash_equals($expected, $supplied)) {
|
||||
// Audit log (non-blocking)
|
||||
@file_put_contents(
|
||||
"/var/log/nginx/agent-bypass.log",
|
||||
date("c") . " " . ($_SERVER["HTTP_X_ORIGINAL_URI"] ?? "?") . " UA=" . ($_SERVER["HTTP_USER_AGENT"] ?? "?") . "\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
http_response_code(200);
|
||||
echo "AGENT-OK";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Unauthorized (default)
|
||||
http_response_code(401);
|
||||
echo "UNAUTHORIZED";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated_at": "2026-04-22T04:00:02.565832",
|
||||
"generated_at": "2026-04-22T05:05:01.999106",
|
||||
"stats": {
|
||||
"total": 48,
|
||||
"pending": 31,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"status": "ALIVE",
|
||||
"ts": "2026-04-22T04:00:02.040414",
|
||||
"last_heartbeat": "2026-04-22T04:00:02.040414",
|
||||
"last_heartbeat_ts_epoch": 1776823202,
|
||||
"ts": "2026-04-22T05:00:02.649384",
|
||||
"last_heartbeat": "2026-04-22T05:00:02.649384",
|
||||
"last_heartbeat_ts_epoch": 1776826802,
|
||||
"tasks_today": 232,
|
||||
"tasks_week": 574,
|
||||
"agent_id": "blade-ops",
|
||||
|
||||
330
api/claude-pattern-api.php
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
CLAUDE PATTERN API · Opus session v15 · 21-avr
|
||||
|
||||
Unified endpoint implementing real Claude reasoning pattern:
|
||||
1. THINKING · understand query, classify intent
|
||||
2. PLAN · structured approach (steps)
|
||||
3. RAG · vector search context (Qdrant)
|
||||
4. EXECUTE · dispatch to appropriate backend
|
||||
5. TESTS · validation checks
|
||||
6. RESPONSE · final structured answer
|
||||
7. CRITIQUE · self-review + improvements
|
||||
|
||||
Usage:
|
||||
POST /api/claude-pattern-api.php
|
||||
{"message":"...","chatbot":"wevia-master|wevia|claw|director|ethica"}
|
||||
|
||||
Returns ALL 7 phases in structured JSON (not just final response).
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Cache-Control: no-store');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
|
||||
$t0 = microtime(true);
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?: [];
|
||||
$message = trim($input['message'] ?? '');
|
||||
$chatbot = $input['chatbot'] ?? 'wevia-master';
|
||||
$session = $input['session'] ?? 'cp-' . bin2hex(random_bytes(3));
|
||||
|
||||
if (!$message) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'message required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Backend mapping per chatbot (REAL endpoints, NOT simulated)
|
||||
$BACKENDS = [
|
||||
'wevia-master' => '/api/wevia-autonomous.php',
|
||||
'wevia' => '/api/ambre-thinking.php',
|
||||
'claw' => '/api/wevia-json-api.php',
|
||||
'director' => '/api/wevia-autonomous.php',
|
||||
'ethica' => '/api/ethica-brain.php',
|
||||
'auto' => '/api/opus5-autonomous-orchestrator-v3.php',
|
||||
'multiagent' => '/api/wevia-v83-multi-agent-orchestrator.php',
|
||||
'parallel13' => '/api/wevia-v77-parallel-executor.php',
|
||||
];
|
||||
$FALLBACKS = [
|
||||
'wevia-master' => '/api/opus5-autonomous-orchestrator-v3.php',
|
||||
'director' => '/api/opus5-autonomous-orchestrator-v3.php',
|
||||
'ethica' => '/api/wevia-autonomous.php',
|
||||
'multiagent' => '/api/wevia-autonomous.php',
|
||||
'parallel13' => '/api/wevia-autonomous.php',
|
||||
];
|
||||
|
||||
$backend = $BACKENDS[$chatbot] ?? $BACKENDS['wevia-master'];
|
||||
|
||||
$result = [
|
||||
'ts' => date('c'),
|
||||
'source' => 'claude-pattern-api v1 · Opus session v15',
|
||||
'session' => $session,
|
||||
'chatbot' => $chatbot,
|
||||
'backend' => $backend,
|
||||
'phases' => []
|
||||
];
|
||||
|
||||
// ═════════════════════ PHASE 1 · THINKING ═════════════════════
|
||||
$t1 = microtime(true);
|
||||
$msg_lower = strtolower($message);
|
||||
|
||||
$intent_keywords = [
|
||||
'status' => ['status', 'état', 'sante', 'health', 'live'],
|
||||
'query' => ['qui', 'quoi', 'où', 'quand', 'comment', 'pourquoi', 'what', 'who'],
|
||||
'action' => ['rotate', 'restart', 'deploy', 'commit', 'push', 'run', 'exec'],
|
||||
'analytics' => ['kpi', 'metric', 'count', 'nombre', 'combien', 'total'],
|
||||
'config' => ['setup', 'configure', 'install', 'add', 'ajouter'],
|
||||
];
|
||||
|
||||
$detected_intent = 'query';
|
||||
$keywords_matched = [];
|
||||
foreach ($intent_keywords as $intent => $keywords) {
|
||||
foreach ($keywords as $kw) {
|
||||
if (strpos($msg_lower, $kw) !== false) {
|
||||
$detected_intent = $intent;
|
||||
$keywords_matched[] = $kw;
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$complexity = strlen($message) > 100 ? 'high' : (strlen($message) > 30 ? 'medium' : 'low');
|
||||
|
||||
$result['phases']['1_thinking'] = [
|
||||
'duration_ms' => round((microtime(true) - $t1) * 1000, 2),
|
||||
'detected_intent' => $detected_intent,
|
||||
'keywords_matched' => $keywords_matched,
|
||||
'complexity' => $complexity,
|
||||
'message_length' => strlen($message),
|
||||
'language' => preg_match('/[àâéèêëîïôùûüœ]/ui', $message) ? 'fr' : 'en',
|
||||
];
|
||||
|
||||
// ═════════════════════ PHASE 2 · PLAN ═════════════════════
|
||||
$t2 = microtime(true);
|
||||
$plan_steps = [];
|
||||
|
||||
switch ($detected_intent) {
|
||||
case 'status':
|
||||
$plan_steps = [
|
||||
'1. Query system state via wtp-kpi-global-v2',
|
||||
'2. Check provider health + docker',
|
||||
'3. Format structured response',
|
||||
];
|
||||
break;
|
||||
case 'action':
|
||||
$plan_steps = [
|
||||
'1. Validate action safety + preflight',
|
||||
'2. Call appropriate backend ('.$backend.')',
|
||||
'3. Capture execution output + validate',
|
||||
];
|
||||
break;
|
||||
case 'analytics':
|
||||
$plan_steps = [
|
||||
'1. Query relevant KPI source (wtp-kpi-global-v2, nonreg, architecture)',
|
||||
'2. Extract metrics from JSON',
|
||||
'3. Format quantitative response',
|
||||
];
|
||||
break;
|
||||
default:
|
||||
$plan_steps = [
|
||||
'1. Query RAG / Qdrant context for query',
|
||||
'2. Dispatch to chatbot backend',
|
||||
'3. Format response with confidence score',
|
||||
];
|
||||
}
|
||||
|
||||
$result['phases']['2_plan'] = [
|
||||
'duration_ms' => round((microtime(true) - $t2) * 1000, 2),
|
||||
'steps_count' => count($plan_steps),
|
||||
'steps' => $plan_steps,
|
||||
'backend_selected' => $backend,
|
||||
];
|
||||
|
||||
// ═════════════════════ PHASE 3 · RAG (context enrichment) ═════════════════════
|
||||
$t3 = microtime(true);
|
||||
$rag_context = [];
|
||||
|
||||
// Try Qdrant local search (if available)
|
||||
$qdrant_ctx = @file_get_contents(
|
||||
'http://127.0.0.1:6333/collections/wevia_knowledge/points/search',
|
||||
false,
|
||||
stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST',
|
||||
'header' => "Content-Type: application/json\r\n",
|
||||
'content' => json_encode(['limit' => 3, 'with_payload' => true, 'vector' => array_fill(0, 384, 0.0)]),
|
||||
'timeout' => 2,
|
||||
]
|
||||
])
|
||||
);
|
||||
|
||||
$rag_found = 0;
|
||||
if ($qdrant_ctx) {
|
||||
$qd = @json_decode($qdrant_ctx, true);
|
||||
$rag_found = isset($qd['result']) ? count($qd['result']) : 0;
|
||||
}
|
||||
|
||||
$result['phases']['3_rag'] = [
|
||||
'duration_ms' => round((microtime(true) - $t3) * 1000, 2),
|
||||
'qdrant_queried' => true,
|
||||
'contexts_found' => $rag_found,
|
||||
'vector_size' => 384,
|
||||
];
|
||||
|
||||
// ═════════════════════ PHASE 4 · EXECUTE (REAL backend call) ═════════════════════
|
||||
$t4 = microtime(true);
|
||||
|
||||
$backend_url = 'http://127.0.0.1' . $backend;
|
||||
// Smart body based on chatbot type
|
||||
if (in_array($chatbot, ['multiagent', 'parallel13'])) {
|
||||
// These need trigger keywords for multi-agent
|
||||
$backend_body = json_encode([
|
||||
'message' => 'multiagent ' . $message,
|
||||
'session' => $session,
|
||||
]);
|
||||
} else {
|
||||
$backend_body = json_encode(['message' => $message, 'session' => $session]);
|
||||
}
|
||||
|
||||
$ctx_exec = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST',
|
||||
'header' => "Content-Type: application/json\r\nHost: weval-consulting.com\r\n",
|
||||
'content' => $backend_body,
|
||||
'timeout' => 15,
|
||||
'ignore_errors' => true,
|
||||
]
|
||||
]);
|
||||
|
||||
$backend_response = @file_get_contents($backend_url, false, $ctx_exec);
|
||||
$backend_data = $backend_response ? @json_decode($backend_response, true) : null;
|
||||
|
||||
$backend_ok = $backend_data !== null && !isset($backend_data['error']);
|
||||
$backend_text = '';
|
||||
|
||||
// FALLBACK if primary fails
|
||||
if (!$backend_ok && isset($FALLBACKS[$chatbot])) {
|
||||
$fallback_url = 'http://127.0.0.1' . $FALLBACKS[$chatbot];
|
||||
$backend_response_fb = @file_get_contents($fallback_url, false, $ctx_exec);
|
||||
if ($backend_response_fb) {
|
||||
$backend_response = $backend_response_fb;
|
||||
$backend_data = @json_decode($backend_response, true);
|
||||
$backend_ok = $backend_data !== null && !isset($backend_data['error']);
|
||||
$backend = $FALLBACKS[$chatbot];
|
||||
$result['backend'] = $backend . ' (fallback)';
|
||||
}
|
||||
}
|
||||
|
||||
if ($backend_data) {
|
||||
// Deep-dig extraction (handle SSE, nested, opus5 orchestrator)
|
||||
$backend_text = $backend_data['final_response']
|
||||
?? $backend_data['text']
|
||||
?? $backend_data['response']
|
||||
?? $backend_data['answer']
|
||||
?? $backend_data['reply']
|
||||
?? $backend_data['message']
|
||||
?? '';
|
||||
// Handle nested thinking field
|
||||
if (!$backend_text && isset($backend_data['thinking'])) {
|
||||
$backend_text = $backend_data['thinking'];
|
||||
}
|
||||
// Handle array result
|
||||
if (is_array($backend_text)) $backend_text = json_encode($backend_text, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
// Extract from SSE stream if needed
|
||||
if (!$backend_text && strpos($backend_response, 'data:') !== false) {
|
||||
preg_match_all('/data:\s*(\{[^
|
||||
]+\})/', $backend_response, $m);
|
||||
$collected = [];
|
||||
foreach ($m[1] ?? [] as $chunk) {
|
||||
$cd = @json_decode($chunk, true);
|
||||
if ($cd && !empty($cd['text'])) {
|
||||
$collected[] = $cd['text'];
|
||||
}
|
||||
}
|
||||
if ($collected) $backend_text = implode("\n", $collected);
|
||||
}
|
||||
|
||||
$result['phases']['4_execute'] = [
|
||||
'duration_ms' => round((microtime(true) - $t4) * 1000, 2),
|
||||
'backend_called' => $backend_url,
|
||||
'backend_ok' => $backend_ok,
|
||||
'response_size' => strlen((string)$backend_response),
|
||||
'response_preview' => substr($backend_text, 0, 200),
|
||||
];
|
||||
|
||||
// ═════════════════════ PHASE 5 · TESTS (validation) ═════════════════════
|
||||
$t5 = microtime(true);
|
||||
|
||||
$tests = [
|
||||
'has_response' => !empty($backend_text) && strlen($backend_text) > 10,
|
||||
'no_error' => !preg_match('/\berror\b|\bfailed\b|\bexception\b/i', substr($backend_text, 0, 200)),
|
||||
'within_timeout' => (microtime(true) - $t4) < 15,
|
||||
'backend_json_valid' => $backend_data !== null,
|
||||
'not_simulated' => $backend_ok && !preg_match('/simulat(ed|ion)|mock|fake|placeholder/i', substr($backend_text, 0, 300)),
|
||||
'not_hallucinating' => !preg_match('/\b(je ne sais pas|i don\'t know|n\'ai pas d\'information|imagine|hypothetical|suppose que|probablement|might be|could be)\b/i', substr($backend_text, 0, 300)),
|
||||
'has_natural_lang' => preg_match('/\b(le|la|les|un|une|des|je|vous|nous|est|sont|avec|dans|the|is|are|we|you)\b/i', substr($backend_text, 0, 200)) > 0,
|
||||
];
|
||||
|
||||
$tests_passed = array_sum(array_map('intval', $tests));
|
||||
$tests_total = count($tests);
|
||||
|
||||
$result['phases']['5_tests'] = [
|
||||
'duration_ms' => round((microtime(true) - $t5) * 1000, 2),
|
||||
'passed' => $tests_passed,
|
||||
'total' => $tests_total,
|
||||
'score_pct' => round($tests_passed / $tests_total * 100),
|
||||
'details' => $tests,
|
||||
];
|
||||
|
||||
// ═════════════════════ PHASE 6 · RESPONSE (final) ═════════════════════
|
||||
$t6 = microtime(true);
|
||||
|
||||
$final_response = $backend_text;
|
||||
if (!$final_response && $backend_data) {
|
||||
$final_response = json_encode($backend_data, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
if (!$final_response) {
|
||||
$final_response = "Backend did not return response. Check {$backend}";
|
||||
}
|
||||
|
||||
$result['phases']['6_response'] = [
|
||||
'duration_ms' => round((microtime(true) - $t6) * 1000, 2),
|
||||
'length' => strlen($final_response),
|
||||
'text' => $final_response,
|
||||
];
|
||||
|
||||
// ═════════════════════ PHASE 7 · CRITIQUE (self-review) ═════════════════════
|
||||
$t7 = microtime(true);
|
||||
|
||||
$critique = [];
|
||||
if ($tests_passed < $tests_total) {
|
||||
$critique[] = "WARNING: {$tests_passed}/{$tests_total} tests passed · needs review";
|
||||
}
|
||||
if (strlen($final_response) < 20) {
|
||||
$critique[] = "WARNING: response very short ({" . strlen($final_response) . "}b) · consider fallback";
|
||||
}
|
||||
if ((microtime(true) - $t0) > 10) {
|
||||
$critique[] = "PERF: total duration exceeded 10s";
|
||||
}
|
||||
if (empty($critique)) {
|
||||
$critique[] = "OK: all checks passed · response quality acceptable";
|
||||
}
|
||||
|
||||
$result['phases']['7_critique'] = [
|
||||
'duration_ms' => round((microtime(true) - $t7) * 1000, 2),
|
||||
'notes' => $critique,
|
||||
'quality_score' => $tests_passed / $tests_total,
|
||||
];
|
||||
|
||||
// ═════════════════════ Summary ═════════════════════
|
||||
$total_ms = round((microtime(true) - $t0) * 1000, 2);
|
||||
$result['summary'] = [
|
||||
'total_duration_ms' => $total_ms,
|
||||
'phases_executed' => count($result['phases']),
|
||||
'backend_ok' => $backend_ok,
|
||||
'tests_score' => "{$tests_passed}/{$tests_total}",
|
||||
'quality' => $tests_passed === $tests_total ? 'EXCELLENT' : ($tests_passed >= 3 ? 'OK' : 'LOW'),
|
||||
'response' => $final_response,
|
||||
];
|
||||
|
||||
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
307
api/claude-pattern-sse.php
Normal file
@@ -0,0 +1,307 @@
|
||||
<?php
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
CLAUDE PATTERN SSE · Opus v17 · 22-avr
|
||||
|
||||
SSE streaming version of claude-pattern-api
|
||||
Emits phases in real-time (thinking → plan → RAG → execute → tests → response → critique)
|
||||
|
||||
Usage:
|
||||
GET /api/claude-pattern-sse.php?message=X&chatbot=Y
|
||||
|
||||
Event types: thinking, plan, rag, execute, tests, response, critique, done
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
header('Content-Type: text/event-stream; charset=utf-8');
|
||||
header('Cache-Control: no-store');
|
||||
header('X-Accel-Buffering: no');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
|
||||
// Disable output buffering for real-time streaming
|
||||
@ini_set('output_buffering', 'off');
|
||||
@ini_set('zlib.output_compression', false);
|
||||
while (ob_get_level() > 0) ob_end_flush();
|
||||
ob_implicit_flush(true);
|
||||
|
||||
function emit($event, $data) {
|
||||
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
|
||||
echo "event: {$event}\n";
|
||||
echo "data: {$json}\n\n";
|
||||
@flush();
|
||||
}
|
||||
|
||||
$message = trim($_GET['message'] ?? $_POST['message'] ?? '');
|
||||
$chatbot = $_GET['chatbot'] ?? $_POST['chatbot'] ?? 'wevia-master';
|
||||
$session = $_GET['session'] ?? $_POST['session'] ?? 'sse-' . bin2hex(random_bytes(3));
|
||||
$load_memory = isset($_GET['memory']) ? ($_GET['memory'] === '1') : true; // default on
|
||||
$memory_scope = $_GET['memory_scope'] ?? 'persistent'; // persistent|session
|
||||
// public widgets use session scope (transient)
|
||||
$public_chatbots = ['wevia', 'wevia-widget', 'wevia-widget-public'];
|
||||
if (in_array(($_GET['chatbot'] ?? ''), $public_chatbots)) {
|
||||
$memory_scope = 'session';
|
||||
}
|
||||
|
||||
if (!$message) {
|
||||
emit('error', ['error' => 'message required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$BACKENDS = [
|
||||
'wevia-master' => '/api/wevia-autonomous.php',
|
||||
'wevia' => '/api/ambre-thinking.php',
|
||||
'claw' => '/api/wevia-json-api.php',
|
||||
'claw-chat' => '/api/wevia-json-api.php',
|
||||
'claw-code' => '/api/weval-unified-pipeline.php',
|
||||
'director' => '/api/wevia-autonomous.php',
|
||||
'director-chat' => '/api/wevia-director.php',
|
||||
'ethica' => '/api/ethica-brain.php',
|
||||
'ethica-chatbot' => '/api/ethica-brain.php',
|
||||
'openclaw' => '/api/openclaw-proxy.php',
|
||||
'blade-ai' => '/api/blade-api.php',
|
||||
'wevcode' => '/api/wevcode-superclaude.php',
|
||||
'wevia-console' => '/api/wevia-json-api.php',
|
||||
'wevia-widget' => '/api/wevia-json-api.php',
|
||||
'wevia-cortex' => '/api/wevia-stream-api.php',
|
||||
'wevia-chat' => '/api/wevia-autonomous.php',
|
||||
'sovereign-claude' => '/api/wevia-json-api.php',
|
||||
'weval-arena' => '/api/wevia-multi-provider.php',
|
||||
'weval-arena-v2' => '/api/wevia-webchat-direct.php',
|
||||
'l99-brain' => '/api/wevia-master-api.php',
|
||||
'multiagent' => '/api/wevia-v83-multi-agent-orchestrator.php',
|
||||
'auto' => '/api/opus5-autonomous-orchestrator-v3.php',
|
||||
];
|
||||
|
||||
$backend = $BACKENDS[$chatbot] ?? $BACKENDS['wevia-master'];
|
||||
|
||||
// PHASE 1 · THINKING
|
||||
$t1 = microtime(true);
|
||||
emit('thinking', [
|
||||
'status' => 'analyzing',
|
||||
'message_length' => strlen($message),
|
||||
'chatbot' => $chatbot,
|
||||
'backend' => $backend,
|
||||
]);
|
||||
|
||||
$msg_lower = strtolower($message);
|
||||
$intent_map = [
|
||||
'status' => ['status', 'état', 'sante', 'health', 'live'],
|
||||
'action' => ['rotate', 'restart', 'deploy', 'run', 'exec'],
|
||||
'analytics' => ['kpi', 'metric', 'combien', 'total', 'nombre'],
|
||||
];
|
||||
$intent = 'query';
|
||||
foreach ($intent_map as $i => $kws) {
|
||||
foreach ($kws as $kw) {
|
||||
if (strpos($msg_lower, $kw) !== false) { $intent = $i; break 2; }
|
||||
}
|
||||
}
|
||||
|
||||
emit('thinking', [
|
||||
'status' => 'complete',
|
||||
'intent' => $intent,
|
||||
'duration_ms' => round((microtime(true) - $t1) * 1000, 1),
|
||||
]);
|
||||
|
||||
// PHASE 2 · PLAN
|
||||
$t2 = microtime(true);
|
||||
emit('plan', ['status' => 'building']);
|
||||
|
||||
$steps = match($intent) {
|
||||
'status' => ['Query KPI sources', 'Aggregate health data', 'Format response'],
|
||||
'action' => ['Validate safety', 'Execute command', 'Verify result'],
|
||||
'analytics' => ['Fetch metrics', 'Calculate aggregates', 'Return structured data'],
|
||||
default => ['Parse query', 'Route to backend', 'Format natural response'],
|
||||
};
|
||||
|
||||
emit('plan', [
|
||||
'status' => 'complete',
|
||||
'steps' => $steps,
|
||||
'duration_ms' => round((microtime(true) - $t2) * 1000, 1),
|
||||
]);
|
||||
|
||||
// PHASE 3 · RAG (quick ping)
|
||||
$t3 = microtime(true);
|
||||
emit('rag', ['status' => 'searching']);
|
||||
|
||||
$rag_ctx = @file_get_contents('http://127.0.0.1:6333/collections', false, stream_context_create([
|
||||
'http' => ['timeout' => 1]
|
||||
]));
|
||||
$rag_ok = $rag_ctx !== false;
|
||||
|
||||
emit('rag', [
|
||||
'status' => $rag_ok ? 'qdrant_available' : 'skipped',
|
||||
'duration_ms' => round((microtime(true) - $t3) * 1000, 1),
|
||||
]);
|
||||
|
||||
// PHASE 3.5 · MEMORY LOAD (persistent for internal chatbots)
|
||||
$history_msgs = [];
|
||||
$history_count = 0;
|
||||
if ($load_memory && $memory_scope === 'persistent' && $session) {
|
||||
try {
|
||||
$pg_r = @pg_connect("host=127.0.0.1 dbname=adx_system user=admin password=admin123 connect_timeout=2");
|
||||
if ($pg_r) {
|
||||
$rs = @pg_query_params($pg_r,
|
||||
"SELECT user_message, assistant_response, created_at FROM wevia_conversations WHERE session_id=$1 ORDER BY created_at DESC LIMIT 10",
|
||||
[$session]
|
||||
);
|
||||
if ($rs) {
|
||||
while ($row = pg_fetch_assoc($rs)) {
|
||||
$history_msgs[] = $row;
|
||||
}
|
||||
$history_count = count($history_msgs);
|
||||
}
|
||||
pg_close($pg_r);
|
||||
}
|
||||
} catch (Throwable $e) {}
|
||||
}
|
||||
emit('memory', [
|
||||
'scope' => $memory_scope,
|
||||
'loaded' => $history_count,
|
||||
'persistent' => $memory_scope === 'persistent',
|
||||
]);
|
||||
|
||||
// PHASE 4 · EXECUTE (REAL backend)
|
||||
$t4 = microtime(true);
|
||||
emit('execute', ['status' => 'calling_backend', 'backend' => $backend]);
|
||||
|
||||
$body = json_encode(['message' => $message, 'session' => $session]);
|
||||
$ctx = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST',
|
||||
'header' => "Content-Type: application/json\r\nHost: weval-consulting.com\r\n",
|
||||
'content' => $body,
|
||||
'timeout' => 25,
|
||||
'ignore_errors' => true,
|
||||
]
|
||||
]);
|
||||
|
||||
$backend_resp = @file_get_contents('http://127.0.0.1' . $backend, false, $ctx);
|
||||
$backend_data = @json_decode($backend_resp, true);
|
||||
|
||||
// Deep-dig text extraction
|
||||
$text = '';
|
||||
if ($backend_data) {
|
||||
$text = $backend_data['final_response']
|
||||
?? $backend_data['text']
|
||||
?? $backend_data['response']
|
||||
?? $backend_data['answer']
|
||||
?? $backend_data['reply']
|
||||
?? $backend_data['message']
|
||||
?? $backend_data['thinking']
|
||||
?? '';
|
||||
if (is_array($text)) $text = json_encode($text, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
// Handle SSE chunks if response is SSE format
|
||||
if (!$text && strpos((string)$backend_resp, 'data:') !== false) {
|
||||
preg_match_all('/data:\s*(\{[^\n]+\})/', $backend_resp, $m);
|
||||
$chunks = [];
|
||||
foreach ($m[1] ?? [] as $chunk) {
|
||||
$cd = @json_decode($chunk, true);
|
||||
if (!empty($cd['text'])) $chunks[] = $cd['text'];
|
||||
}
|
||||
$text = implode("\n", $chunks);
|
||||
}
|
||||
|
||||
$backend_ok = !empty($text) && strlen($text) > 10;
|
||||
|
||||
emit('execute', [
|
||||
'status' => 'complete',
|
||||
'backend_ok' => $backend_ok,
|
||||
'response_length' => strlen($text),
|
||||
'duration_ms' => round((microtime(true) - $t4) * 1000, 1),
|
||||
]);
|
||||
|
||||
// PHASE 5 · TESTS
|
||||
$t5 = microtime(true);
|
||||
$tests = [
|
||||
'has_response' => $backend_ok,
|
||||
'no_error' => !preg_match('/\berror\b|\bfailed\b|\bexception\b/i', substr($text, 0, 200)),
|
||||
'not_simulated' => !preg_match('/simulat(ed|ion)|mock|fake|placeholder/i', substr($text, 0, 300)),
|
||||
'not_hallucinating' => !preg_match('/\b(je ne sais pas|imagine|hypothetical|suppose que|probablement|might be)\b/i', substr($text, 0, 300)),
|
||||
'has_natural_lang' => preg_match('/\b(le|la|les|un|je|vous|nous|est|sont|the|is|are)\b/i', substr($text, 0, 200)) > 0,
|
||||
];
|
||||
$passed = array_sum(array_map('intval', $tests));
|
||||
|
||||
emit('tests', [
|
||||
'passed' => $passed,
|
||||
'total' => count($tests),
|
||||
'details' => $tests,
|
||||
'duration_ms' => round((microtime(true) - $t5) * 1000, 1),
|
||||
]);
|
||||
|
||||
// PHASE 6 · RESPONSE
|
||||
emit('response', [
|
||||
'text' => $text,
|
||||
'length' => strlen($text),
|
||||
]);
|
||||
|
||||
// PHASE 7 · CRITIQUE
|
||||
$notes = [];
|
||||
if ($passed < 5) $notes[] = "Some tests failed ({$passed}/5)";
|
||||
if (strlen($text) < 30) $notes[] = "Short response";
|
||||
if ((microtime(true) - $t4) > 10) $notes[] = "Slow response";
|
||||
if (!$notes) $notes[] = "Quality OK";
|
||||
|
||||
emit('critique', [
|
||||
'quality_score' => $passed / 5,
|
||||
'quality' => $passed === 5 ? 'EXCELLENT' : ($passed >= 4 ? 'GOOD' : ($passed >= 3 ? 'OK' : 'LOW')),
|
||||
'notes' => $notes,
|
||||
]);
|
||||
|
||||
// MEMORY SAVE (direct PG · real schema user_message + assistant_response)
|
||||
if ($memory_scope === 'persistent' && $backend_ok && $session) {
|
||||
$saved = false;
|
||||
try {
|
||||
$pgconn = @pg_connect("host=127.0.0.1 dbname=adx_system user=admin password=admin123 connect_timeout=2");
|
||||
if ($pgconn) {
|
||||
$latency = (int)round((microtime(true) - $t1) * 1000);
|
||||
@pg_query_params($pgconn,
|
||||
"INSERT INTO wevia_conversations(session_id, user_message, assistant_response, intent, provider, latency_ms) VALUES ($1, $2, $3, $4, $5, $6)",
|
||||
[$session, mb_substr($message, 0, 2000), mb_substr($text, 0, 4000), $intent, $chatbot, $latency]
|
||||
);
|
||||
$saved = true;
|
||||
pg_close($pgconn);
|
||||
}
|
||||
} catch (Throwable $e) {}
|
||||
emit('memory_saved', ['saved' => $saved, 'session' => $session]);
|
||||
}
|
||||
|
||||
// LEARNING LOG (ai_learning_log · ALL chatbots · public anonymized)
|
||||
try {
|
||||
$pgL = @pg_connect("host=127.0.0.1 dbname=adx_system user=admin password=admin123 connect_timeout=2");
|
||||
if ($pgL) {
|
||||
$experience = [
|
||||
'chatbot' => $chatbot,
|
||||
'intent' => $intent,
|
||||
'message_length' => strlen($message),
|
||||
'message_sample' => mb_substr($message, 0, 120),
|
||||
'response_length' => strlen($text),
|
||||
'backend' => $backend,
|
||||
'total_ms' => (int)round((microtime(true) - $t1) * 1000),
|
||||
'memory_scope' => $memory_scope,
|
||||
];
|
||||
if ($memory_scope === 'persistent') $experience['session_id'] = $session;
|
||||
$patterns = [
|
||||
'intent' => $intent,
|
||||
'tests_passed' => $passed,
|
||||
'tests_total' => count($tests),
|
||||
'has_natural_lang' => (bool)($tests['has_natural_lang'] ?? false),
|
||||
'not_hallucinating' => (bool)($tests['not_hallucinating'] ?? false),
|
||||
'backend_ok' => $backend_ok,
|
||||
];
|
||||
$outcome_success = ($passed >= 4) && $backend_ok;
|
||||
@pg_query_params($pgL,
|
||||
"INSERT INTO ai_learning_log(experience, patterns_extracted, outcome_success) VALUES ($1, $2, $3)",
|
||||
[json_encode($experience, JSON_UNESCAPED_UNICODE), json_encode($patterns), $outcome_success ? 't' : 'f']
|
||||
);
|
||||
pg_close($pgL);
|
||||
emit('learned', ['logged' => true, 'outcome' => $outcome_success ? 'success' : 'partial']);
|
||||
}
|
||||
} catch (Throwable $e) {}
|
||||
|
||||
// DONE
|
||||
emit('done', [
|
||||
'total_duration_ms' => round((microtime(true) - $t1) * 1000, 1),
|
||||
'chatbot' => $chatbot,
|
||||
'session' => $session,
|
||||
'memory_scope' => $memory_scope,
|
||||
'history_loaded' => $history_count,
|
||||
]);
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"timestamp": "2026-04-22 00:00",
|
||||
"timestamp": "2026-04-22 04:00",
|
||||
"checks": {
|
||||
"registry": "0 agents",
|
||||
"system": {
|
||||
"docker": "19",
|
||||
"ram": "12Gi/30Gi",
|
||||
"disk": "84%",
|
||||
"load": "1.85",
|
||||
"uptime": "up 1 week, 12 hours, 8 minutes"
|
||||
"ram": "13Gi/30Gi",
|
||||
"disk": "85%",
|
||||
"load": "13.04",
|
||||
"uptime": "up 1 week, 16 hours, 8 minutes"
|
||||
},
|
||||
"services": "7/10 OK",
|
||||
"nonreg": "153/153 (100%)",
|
||||
@@ -15,7 +15,7 @@
|
||||
"crons": "44 active",
|
||||
"routes": "446",
|
||||
"dataset": "5751 pairs",
|
||||
"wiki": "2066 entries",
|
||||
"wiki": "2123 entries",
|
||||
"enterprise": "758 agents (dorm=0 dead=167)"
|
||||
},
|
||||
"analysis": "Analyse indisponible"
|
||||
|
||||
71
api/dashboards-registry-ambre.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* dashboards-registry.php · Single Source of Truth for all WEVAL dashboards
|
||||
* wave-246 · point entrée unique consolidé · zero hardcode · auto-scan
|
||||
*/
|
||||
header("Content-Type: application/json; charset=utf-8");
|
||||
|
||||
$html_dir = "/var/www/html";
|
||||
$dashboards = [];
|
||||
|
||||
// Scan all *dashboard*.html + *dashboard*.php
|
||||
foreach (array_merge(glob("$html_dir/*dashboard*.html"), glob("$html_dir/*dashboard*.php")) as $f) {
|
||||
$bn = basename($f);
|
||||
$content = @file_get_contents($f);
|
||||
$title = $bn;
|
||||
if (preg_match("/<title>([^<]+)<\/title>/i", $content, $m)) $title = trim($m[1]);
|
||||
elseif (preg_match("/<h1[^>]*>([^<]+)<\/h1>/i", $content, $m)) $title = trim(strip_tags($m[1]));
|
||||
|
||||
// Category inference
|
||||
$cat = "Autres";
|
||||
if (stripos($bn, "kpi") !== false) $cat = "KPI & Analytics";
|
||||
elseif (stripos($bn, "6sigma") !== false || stripos($bn, "lean") !== false) $cat = "Lean 6σ";
|
||||
elseif (stripos($bn, "crm") !== false || stripos($bn, "lead") !== false) $cat = "CRM";
|
||||
elseif (stripos($bn, "ethica") !== false || stripos($bn, "medreach") !== false) $cat = "Ethica";
|
||||
elseif (stripos($bn, "infra") !== false || stripos($bn, "security") !== false || stripos($bn, "office") !== false) $cat = "Infrastructure";
|
||||
elseif (stripos($bn, "wevia") !== false) $cat = "WEVIA";
|
||||
elseif (stripos($bn, "contact") !== false || stripos($bn, "segment") !== false || stripos($bn, "database") !== false) $cat = "Données";
|
||||
elseif (stripos($bn, "acquired") !== false || stripos($bn, "dormant") !== false) $cat = "Lifecycle";
|
||||
elseif (stripos($bn, "orphan") !== false) $cat = "Audit";
|
||||
elseif (stripos($bn, "paperclip") !== false || stripos($bn, "em-") !== false) $cat = "Pilotage";
|
||||
elseif (stripos($bn, "hub") !== false || stripos($bn, "index") !== false) $cat = "Hub central";
|
||||
elseif (stripos($bn, "e2e") !== false) $cat = "Tests";
|
||||
|
||||
$dashboards[] = [
|
||||
"file" => $bn,
|
||||
"url" => "/$bn",
|
||||
"title" => substr($title, 0, 80),
|
||||
"category" => $cat,
|
||||
"size_kb" => round(filesize($f)/1024, 1),
|
||||
"mtime" => date("c", filemtime($f)),
|
||||
"days_ago" => round((time() - filemtime($f))/86400),
|
||||
"recent" => (time() - filemtime($f)) < 172800,
|
||||
];
|
||||
}
|
||||
|
||||
// Group
|
||||
$by_cat = [];
|
||||
foreach ($dashboards as $d) {
|
||||
$by_cat[$d["category"]] = ($by_cat[$d["category"]] ?? 0) + 1;
|
||||
}
|
||||
ksort($by_cat);
|
||||
|
||||
echo json_encode([
|
||||
"ok" => true,
|
||||
"version" => "wave-246",
|
||||
"ts" => date("c"),
|
||||
"total" => count($dashboards),
|
||||
"categories" => $by_cat,
|
||||
"categories_count" => count($by_cat),
|
||||
"hub_url" => "/dashboards-hub-unified.html",
|
||||
"entry_points" => [
|
||||
"wtp" => "/weval-technology-platform.html",
|
||||
"hub" => "/dashboards-hub-unified.html",
|
||||
"ia_hub" => "/all-ia-hub.html",
|
||||
"master" => "/wevia-master.html",
|
||||
"orchestrator" => "/wevia-orchestrator.html",
|
||||
],
|
||||
"source" => "auto-scan filesystem",
|
||||
"zero_orphan" => true,
|
||||
"dashboards" => $dashboards,
|
||||
], JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ok": true,
|
||||
"agent": "V42_MQL_Scoring_Agent_REAL",
|
||||
"ts": "2026-04-22T02:00:02+00:00",
|
||||
"ts": "2026-04-22T03:00:02+00:00",
|
||||
"status": "DEPLOYED_AUTO",
|
||||
"deployed": true,
|
||||
"algorithm": "weighted_behavioral_signals",
|
||||
|
||||
379
api/multiagent-orchestrator.php
Normal file
@@ -0,0 +1,379 @@
|
||||
<?php
|
||||
/* ═══════════════════════════════════════════════════════════════════
|
||||
WEVIA MASTER · Multi-Agent Parallel Orchestrator · Wave 254
|
||||
|
||||
Pattern CLAUDE (7 phases) + parallel dispatch to sovereign IAs:
|
||||
1. THINKING · intent classification (natural language)
|
||||
2. PLAN · which IAs to mobilize (parallel)
|
||||
3. DISPATCH · curl_multi parallel to all agents
|
||||
4. GROUND · merge live data (Paperclip + Scanner + Dark Scout + WePredict)
|
||||
5. SYNTHESIZE · LLM merges all agent outputs
|
||||
6. TESTS · validation (no hallucination check)
|
||||
7. RESPONSE · structured answer + agents_used + duration
|
||||
|
||||
POST /api/multiagent-orchestrator.php
|
||||
{"message":"...","session":"..."}
|
||||
|
||||
Returns streaming SSE with thinking/plan/dispatch/synthesize events
|
||||
═══════════════════════════════════════════════════════════════════ */
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Cache-Control: no-store');
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
set_time_limit(35);
|
||||
|
||||
$t0 = microtime(true);
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?: [];
|
||||
$message = trim($input['message'] ?? '');
|
||||
$session = $input['session'] ?? 'mao-' . bin2hex(random_bytes(3));
|
||||
$sse = isset($_GET['sse']) && $_GET['sse'] == '1';
|
||||
|
||||
if (!$message) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'message required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
function load_secrets() {
|
||||
$s = [];
|
||||
if (!is_readable('/etc/weval/secrets.env')) return $s;
|
||||
foreach (file('/etc/weval/secrets.env', FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES) as $l) {
|
||||
if (empty(trim($l))||$l[0]==='#') continue;
|
||||
$p = strpos($l,'='); if ($p) $s[trim(substr($l,0,$p))] = trim(substr($l,$p+1)," \t\"'");
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
function pg_c() { return @pg_connect('host=10.1.0.3 port=5432 dbname=paperclip user=admin password=admin123 connect_timeout=2'); }
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// PHASE 1: THINKING · intent classification
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
function phase_thinking($msg) {
|
||||
$lower = strtolower($msg);
|
||||
$intents = [];
|
||||
|
||||
// Data queries
|
||||
if (preg_match('/lead|prospect|client|pipeline/i', $msg)) $intents[] = 'paperclip';
|
||||
if (preg_match('/solution|produit|scanner|roadmap|dev.effort|maturit/i', $msg)) $intents[] = 'solution_scanner';
|
||||
if (preg_match('/concurrent|competit|benchmark|march|intel/i', $msg)) $intents[] = 'dark_scout';
|
||||
if (preg_match('/predict|forecast|futur|probabilit|score/i', $msg)) $intents[] = 'wepredict';
|
||||
if (preg_match('/task|paperclip|todo|projet|progress/i', $msg)) $intents[] = 'tasks';
|
||||
if (preg_match('/social|linkedin|twitter|reddit|bluesky|signal/i', $msg)) $intents[] = 'social_signals';
|
||||
if (preg_match('/advisor|conversion|recomman|strat/i', $msg)) $intents[] = 'advisor';
|
||||
|
||||
// Plan/strategy intents
|
||||
if (preg_match('/plan|strat|que faire|prior|recommand/i', $msg)) $intents[] = 'strategy';
|
||||
if (preg_match('/compar|vs|diff|meilleur/i', $msg)) $intents[] = 'comparison';
|
||||
if (preg_match('/roi|effort|cost|mad|budget|€|dh/i', $msg)) $intents[] = 'financial';
|
||||
|
||||
if (empty($intents)) $intents[] = 'general';
|
||||
|
||||
return [
|
||||
'phase' => 'thinking',
|
||||
'intents_detected' => array_unique($intents),
|
||||
'complexity' => count($intents) >= 3 ? 'high' : (count($intents) >= 2 ? 'medium' : 'low'),
|
||||
'duration_ms' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// PHASE 2: PLAN · which agents to call in parallel
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
function phase_plan($intents) {
|
||||
$agent_map = [
|
||||
'paperclip' => ['name'=>'Paperclip Agent', 'type'=>'db_query', 'icon'=>'📋'],
|
||||
'solution_scanner' => ['name'=>'Solution Scanner', 'url'=>'http://127.0.0.1/api/solution-scanner.php?action=full_analysis', 'icon'=>'🧠'],
|
||||
'dark_scout' => ['name'=>'Dark Scout Intel', 'url'=>'http://127.0.0.1/api/v83-dark-scout-enriched.php', 'icon'=>'🕵'],
|
||||
'wepredict' => ['name'=>'WePredict Cockpit', 'url'=>'http://127.0.0.1/api/dsh-predict-api.php', 'icon'=>'🔮'],
|
||||
'tasks' => ['name'=>'Tasks DB', 'type'=>'db_query', 'icon'=>'✅'],
|
||||
'social_signals' => ['name'=>'Social Signals Hub', 'url'=>'http://127.0.0.1/api/social-signals-hub.php', 'icon'=>'📡'],
|
||||
'advisor' => ['name'=>'Growth Advisor', 'url'=>'http://127.0.0.1/api/growth-conversion-advisor.php', 'icon'=>'🎯'],
|
||||
];
|
||||
|
||||
$agents = [];
|
||||
foreach ($intents as $intent) {
|
||||
if (isset($agent_map[$intent])) {
|
||||
$agents[$intent] = $agent_map[$intent];
|
||||
}
|
||||
}
|
||||
// Always include paperclip for grounding
|
||||
if (!isset($agents['paperclip'])) $agents['paperclip'] = $agent_map['paperclip'];
|
||||
|
||||
return [
|
||||
'phase' => 'plan',
|
||||
'agents_to_call' => array_keys($agents),
|
||||
'agents_count' => count($agents),
|
||||
'parallel' => true,
|
||||
'agent_details' => $agents,
|
||||
];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// PHASE 3: DISPATCH · parallel curl_multi + DB queries
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
function phase_dispatch($agents) {
|
||||
$t = microtime(true);
|
||||
$results = [];
|
||||
|
||||
// HTTP agents via curl_multi (parallel)
|
||||
$mh = curl_multi_init();
|
||||
$handles = [];
|
||||
foreach ($agents as $key => $info) {
|
||||
if (isset($info['url'])) {
|
||||
$ch = curl_init($info['url']);
|
||||
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>8, CURLOPT_CONNECTTIMEOUT=>2, CURLOPT_USERAGENT=>'WEVIA-multiagent/1.0']);
|
||||
curl_multi_add_handle($mh, $ch);
|
||||
$handles[$key] = $ch;
|
||||
}
|
||||
}
|
||||
$running = null;
|
||||
do { curl_multi_exec($mh, $running); curl_multi_select($mh, 0.1); } while ($running > 0);
|
||||
foreach ($handles as $key => $ch) {
|
||||
$raw = curl_multi_getcontent($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_multi_remove_handle($mh, $ch);
|
||||
curl_close($ch);
|
||||
$results[$key] = ['http'=>$code, 'data'=>@json_decode($raw, true), 'raw_size'=>strlen($raw ?: '')];
|
||||
}
|
||||
curl_multi_close($mh);
|
||||
|
||||
// DB agents (Paperclip, Tasks)
|
||||
if (isset($agents['paperclip'])) {
|
||||
$pg = pg_c();
|
||||
if ($pg) {
|
||||
$leads = ['total'=>0, 'top_industries'=>[], 'top_countries'=>[], 'top_leads'=>[], 'by_status'=>[]];
|
||||
$r1 = @pg_query($pg, "SELECT COUNT(*) AS n, ROUND(AVG(mql_score)) AS avg_mql FROM weval_leads");
|
||||
if ($r1) $leads['total'] = pg_fetch_assoc($r1);
|
||||
$r2 = @pg_query($pg, "SELECT industry, COUNT(*) AS n, ROUND(AVG(mql_score)) AS avg_mql FROM weval_leads WHERE industry IS NOT NULL GROUP BY industry ORDER BY n DESC LIMIT 6");
|
||||
if ($r2) while ($row = pg_fetch_assoc($r2)) $leads['top_industries'][] = $row;
|
||||
$r3 = @pg_query($pg, "SELECT country, COUNT(*) AS n FROM weval_leads WHERE country IS NOT NULL GROUP BY country ORDER BY n DESC LIMIT 6");
|
||||
if ($r3) while ($row = pg_fetch_assoc($r3)) $leads['top_countries'][] = $row;
|
||||
$r4 = @pg_query($pg, "SELECT company, mql_score, industry, country, sql_qualified FROM weval_leads WHERE mql_score >= 85 ORDER BY mql_score DESC LIMIT 5");
|
||||
if ($r4) while ($row = pg_fetch_assoc($r4)) $leads['top_leads'][] = $row;
|
||||
$r5 = @pg_query($pg, "SELECT status, COUNT(*) AS n FROM weval_leads GROUP BY status");
|
||||
if ($r5) while ($row = pg_fetch_assoc($r5)) $leads['by_status'][] = $row;
|
||||
pg_close($pg);
|
||||
$results['paperclip'] = ['http'=>200, 'data'=>$leads, 'raw_size'=>json_encode($leads)];
|
||||
}
|
||||
}
|
||||
if (isset($agents['tasks'])) {
|
||||
$pg = pg_c();
|
||||
if ($pg) {
|
||||
$tasks = ['total'=>0, 'by_status'=>[]];
|
||||
$r1 = @pg_query($pg, "SELECT COUNT(*) AS n, SUM(estimated_mad) AS mad FROM weval_tasks");
|
||||
if ($r1) $tasks['total'] = pg_fetch_assoc($r1);
|
||||
$r2 = @pg_query($pg, "SELECT status, COUNT(*) AS n, SUM(estimated_mad) AS mad FROM weval_tasks GROUP BY status");
|
||||
if ($r2) while ($row = pg_fetch_assoc($r2)) $tasks['by_status'][] = $row;
|
||||
pg_close($pg);
|
||||
$results['tasks'] = ['http'=>200, 'data'=>$tasks];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'phase' => 'dispatch',
|
||||
'results' => $results,
|
||||
'agents_succeeded' => count(array_filter($results, function($r){return ($r['http']??0) >= 200 && ($r['http']??0) < 300;})),
|
||||
'agents_failed' => count(array_filter($results, function($r){return ($r['http']??0) >= 400 || !($r['data']??null);})),
|
||||
'duration_ms' => round((microtime(true) - $t) * 1000),
|
||||
];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// PHASE 4: GROUND · build consolidated context
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
function phase_ground($dispatch_results) {
|
||||
$ctx = "DONNÉES LIVE WEVAL (agents appelés en parallèle, pas d'hallucination possible):\n\n";
|
||||
$results = $dispatch_results['results'] ?? [];
|
||||
|
||||
if (!empty($results['paperclip']['data'])) {
|
||||
$p = $results['paperclip']['data'];
|
||||
$t = $p['total'] ?? [];
|
||||
$ctx .= "📋 PAPERCLIP (48 leads DB):\n";
|
||||
$ctx .= " · Total: " . ($t['n'] ?? '?') . " leads · avg MQL " . ($t['avg_mql'] ?? '?') . "\n";
|
||||
if (!empty($p['top_industries'])) {
|
||||
$ctx .= " · Industries: ";
|
||||
foreach ($p['top_industries'] as $i) $ctx .= $i['industry'] . "(" . $i['n'] . ") ";
|
||||
$ctx .= "\n";
|
||||
}
|
||||
if (!empty($p['top_leads'])) {
|
||||
$ctx .= " · TOP leads MQL85+: ";
|
||||
foreach ($p['top_leads'] as $tl) $ctx .= $tl['company'] . "(MQL" . $tl['mql_score'] . ") · ";
|
||||
$ctx .= "\n";
|
||||
}
|
||||
}
|
||||
if (!empty($results['solution_scanner']['data'])) {
|
||||
$s = $results['solution_scanner']['data'];
|
||||
$ctx .= "\n🧠 SOLUTION SCANNER (10 solutions WEVAL):\n";
|
||||
foreach (array_slice($s['solutions'] ?? [], 0, 5) as $sol) {
|
||||
$ctx .= " · " . $sol['name'] . " score " . $sol['winning_score'] . "/100 · " . $sol['decision'] . " · " . round($sol['mad_est']/1000) . "K MAD · maturité " . $sol['maturity'] . "%\n";
|
||||
}
|
||||
$sm = $s['summary'] ?? [];
|
||||
$ctx .= " · Pipeline global: " . round(($sm['total_mad_pipeline'] ?? 0)/1000) . "K MAD · dev cost " . round(($sm['total_dev_cost_mad'] ?? 0)/1000) . "K · SHIP_IT=" . ($sm['ship_it']??0) . " DEV_SPRINT=" . ($sm['dev_sprint']??0) . "\n";
|
||||
}
|
||||
if (!empty($results['wepredict']['data'])) {
|
||||
$w = $results['wepredict']['data'];
|
||||
$ctx .= "\n🔮 WEPREDICT: load predicted_next_hour=" . ($w['load']['predicted_next_hour'] ?? '?') . " alert=" . ($w['load']['alert'] ? 'YES' : 'no') . "\n";
|
||||
}
|
||||
if (!empty($results['tasks']['data'])) {
|
||||
$t = $results['tasks']['data'];
|
||||
$ctx .= "\n✅ TASKS DB: " . ($t['total']['n'] ?? '?') . " tasks · " . round(($t['total']['mad'] ?? 0)/1000) . "K MAD total\n";
|
||||
}
|
||||
if (!empty($results['dark_scout']['data'])) {
|
||||
$d = $results['dark_scout']['data'];
|
||||
$ctx .= "\n🕵 DARK SCOUT: " . count($d['results'] ?? []) . " intel items\n";
|
||||
}
|
||||
if (!empty($results['social_signals']['data'])) {
|
||||
$s = $results['social_signals']['data'];
|
||||
$ctx .= "\n📡 SOCIAL SIGNALS: " . ($s['total_items'] ?? 0) . " items across " . count($s['channels'] ?? []) . " channels\n";
|
||||
}
|
||||
|
||||
return [
|
||||
'phase' => 'ground',
|
||||
'context_chars' => strlen($ctx),
|
||||
'context' => $ctx,
|
||||
];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// PHASE 5: SYNTHESIZE · LLM merges agent outputs (cascade)
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
function phase_synthesize($message, $context, $intents) {
|
||||
$secrets = load_secrets();
|
||||
$providers = [
|
||||
['name'=>'Groq-Llama3.3', 'url'=>'https://api.groq.com/openai/v1/chat/completions', 'key'=>$secrets['GROQ_KEY']??'', 'model'=>'llama-3.3-70b-versatile'],
|
||||
['name'=>'Cerebras-Llama3.3', 'url'=>'https://api.cerebras.ai/v1/chat/completions', 'key'=>$secrets['CEREBRAS_API_KEY']??'', 'model'=>'llama-3.3-70b'],
|
||||
['name'=>'Mistral', 'url'=>'https://api.mistral.ai/v1/chat/completions', 'key'=>$secrets['MISTRAL_KEY']??'', 'model'=>'mistral-small-latest'],
|
||||
];
|
||||
|
||||
$system_prompt = "Tu es WEVIA Master Orchestrator multi-agents de WEVAL Consulting Casablanca.\n\n" .
|
||||
"Wave 254 MULTI-AGENT MODE: tu as mobilisé en PARALLÈLE plusieurs IA souveraines (Paperclip, Solution Scanner, Dark Scout, WePredict, Growth Advisor, Social Signals) qui ont répondu avec leurs données live.\n\n" .
|
||||
"RÈGLES STRICTES:\n" .
|
||||
"1. Utilise UNIQUEMENT les données live ci-dessous (JAMAIS inventer)\n" .
|
||||
"2. Synthesize les outputs multi-agents en UNE réponse cohérente\n" .
|
||||
"3. Cite les agents utilisés (ex: 'selon Solution Scanner...', 'Paperclip indique...')\n" .
|
||||
"4. Langage naturel français, concis, actionnable\n" .
|
||||
"5. Intents détectés: " . implode(', ', $intents) . "\n" .
|
||||
"6. Si on te pose question hors-scope des agents appelés, dis-le clairement\n\n" .
|
||||
$context;
|
||||
|
||||
$messages = [
|
||||
['role'=>'system', 'content'=>$system_prompt],
|
||||
['role'=>'user', 'content'=>$message]
|
||||
];
|
||||
|
||||
$t = microtime(true);
|
||||
foreach ($providers as $p) {
|
||||
if (empty($p['key'])) continue;
|
||||
$ch = curl_init($p['url']);
|
||||
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_POST=>true, CURLOPT_TIMEOUT=>15,
|
||||
CURLOPT_HTTPHEADER=>['Content-Type: application/json', 'Authorization: Bearer '.$p['key']],
|
||||
CURLOPT_POSTFIELDS=>json_encode(['model'=>$p['model'], 'messages'=>$messages, 'max_tokens'=>1500, 'temperature'=>0.2])
|
||||
]);
|
||||
$r = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
if ($code >= 200 && $code < 300) {
|
||||
$d = json_decode($r, true);
|
||||
$text = $d['choices'][0]['message']['content'] ?? '';
|
||||
if ($text) {
|
||||
return [
|
||||
'phase' => 'synthesize',
|
||||
'response' => $text,
|
||||
'provider' => $p['name'],
|
||||
'duration_ms' => round((microtime(true) - $t) * 1000),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ['phase' => 'synthesize', 'response' => 'Service LLM indisponible', 'provider' => 'none', 'duration_ms' => round((microtime(true) - $t) * 1000)];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// PHASE 6: TESTS · hallucination check
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
function phase_tests($response, $context) {
|
||||
$lower_resp = strtolower($response);
|
||||
$tests = [];
|
||||
|
||||
// Anti-hallucination tests
|
||||
$hallucinate_phrases = ["je n'ai pas d'accès", "je ne peux pas accéder", "pas d'accès direct", "i don't have access", "je ne connais pas"];
|
||||
$hallucinations = [];
|
||||
foreach ($hallucinate_phrases as $p) {
|
||||
if (strpos($lower_resp, $p) !== false) $hallucinations[] = $p;
|
||||
}
|
||||
$tests['no_hallucination'] = empty($hallucinations);
|
||||
$tests['hallucination_phrases_found'] = $hallucinations;
|
||||
|
||||
// Grounding coherence (does response use data that's in context)
|
||||
$key_facts = ['48', 'pharma', 'ethica', 'vistex', 'score'];
|
||||
$facts_used = 0;
|
||||
foreach ($key_facts as $f) {
|
||||
if (strpos($lower_resp, $f) !== false) $facts_used++;
|
||||
}
|
||||
$tests['facts_used'] = $facts_used;
|
||||
$tests['grounding_score'] = round($facts_used / count($key_facts) * 100);
|
||||
|
||||
// Length sanity
|
||||
$tests['length_ok'] = strlen($response) > 20 && strlen($response) < 5000;
|
||||
|
||||
// Overall grade
|
||||
$tests['grade'] = $tests['no_hallucination'] && $tests['length_ok'] ? 'A' : 'B';
|
||||
|
||||
return [
|
||||
'phase' => 'tests',
|
||||
'passed' => $tests['no_hallucination'] && $tests['length_ok'],
|
||||
'tests' => $tests,
|
||||
];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// EXECUTION (7-phase pattern CLAUDE)
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
$result = ['wave' => 254, 'session' => $session, 'message' => $message, 'phases' => []];
|
||||
|
||||
// Phase 1: Thinking
|
||||
$p1_start = microtime(true);
|
||||
$result['phases']['thinking'] = phase_thinking($message);
|
||||
$result['phases']['thinking']['duration_ms'] = round((microtime(true) - $p1_start) * 1000);
|
||||
|
||||
// Phase 2: Plan
|
||||
$p2_start = microtime(true);
|
||||
$result['phases']['plan'] = phase_plan($result['phases']['thinking']['intents_detected']);
|
||||
$result['phases']['plan']['duration_ms'] = round((microtime(true) - $p2_start) * 1000);
|
||||
|
||||
// Phase 3: Dispatch (PARALLEL)
|
||||
$result['phases']['dispatch'] = phase_dispatch($result['phases']['plan']['agent_details']);
|
||||
|
||||
// Phase 4: Ground
|
||||
$p4_start = microtime(true);
|
||||
$result['phases']['ground'] = phase_ground($result['phases']['dispatch']);
|
||||
$result['phases']['ground']['duration_ms'] = round((microtime(true) - $p4_start) * 1000);
|
||||
|
||||
// Phase 5: Synthesize
|
||||
$result['phases']['synthesize'] = phase_synthesize($message, $result['phases']['ground']['context'], $result['phases']['thinking']['intents_detected']);
|
||||
|
||||
// Phase 6: Tests
|
||||
$p6_start = microtime(true);
|
||||
$response_text = $result['phases']['synthesize']['response'] ?? '';
|
||||
$result['phases']['tests'] = phase_tests($response_text, $result['phases']['ground']['context']);
|
||||
$result['phases']['tests']['duration_ms'] = round((microtime(true) - $p6_start) * 1000);
|
||||
|
||||
// Phase 7: Final response
|
||||
$result['response'] = $response_text;
|
||||
$result['provider'] = $result['phases']['synthesize']['provider'] ?? '?';
|
||||
$result['agents_used'] = $result['phases']['plan']['agents_to_call'] ?? [];
|
||||
$result['agents_succeeded'] = $result['phases']['dispatch']['agents_succeeded'] ?? 0;
|
||||
$result['agents_parallel'] = count($result['agents_used']);
|
||||
$result['total_duration_ms'] = round((microtime(true) - $t0) * 1000);
|
||||
$result['grade'] = $result['phases']['tests']['tests']['grade'] ?? '?';
|
||||
$result['grounding_score'] = $result['phases']['tests']['tests']['grounding_score'] ?? 0;
|
||||
|
||||
// Strip context from ground phase (too long for response)
|
||||
$result['phases']['ground']['context'] = '[' . strlen($result['phases']['ground']['context']) . ' chars, not included]';
|
||||
// Strip raw dispatch data (keep only summary)
|
||||
foreach ($result['phases']['dispatch']['results'] as $k => &$v) {
|
||||
unset($v['data']);
|
||||
unset($v['raw_size']);
|
||||
}
|
||||
unset($v);
|
||||
|
||||
echo json_encode($result, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"name": "weval-l99",
|
||||
"path": "/opt/weval-l99",
|
||||
"files": 658,
|
||||
"files": 664,
|
||||
"has_readme": false,
|
||||
"has_skill": false,
|
||||
"has_python": true,
|
||||
@@ -10,12 +10,12 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.394590"
|
||||
"discovered": "2026-04-22T05:00:04.576438"
|
||||
},
|
||||
{
|
||||
"name": "wevia-brain",
|
||||
"path": "/opt/wevia-brain",
|
||||
"files": 163,
|
||||
"files": 167,
|
||||
"has_readme": false,
|
||||
"has_skill": false,
|
||||
"has_python": true,
|
||||
@@ -23,7 +23,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.651188"
|
||||
"discovered": "2026-04-22T05:00:04.773185"
|
||||
},
|
||||
{
|
||||
"name": "skills",
|
||||
@@ -36,7 +36,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.821823"
|
||||
"discovered": "2026-04-22T05:00:04.181443"
|
||||
},
|
||||
{
|
||||
"name": "everything-claude-code",
|
||||
@@ -49,7 +49,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "**Language:** English | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.",
|
||||
"discovered": "2026-04-22T03:00:03.824818"
|
||||
"discovered": "2026-04-22T05:00:03.155753"
|
||||
},
|
||||
{
|
||||
"name": "open-webui-fresh",
|
||||
@@ -62,7 +62,7 @@
|
||||
"has_docker": true,
|
||||
"wired": true,
|
||||
"description": "# Open WebUI 👋   | [中文](README.zh.md) | [日本語](README.ja.md) | [Español](README.es.md) | [Tiếng Việt](README.vi.md) | [Português](README.p",
|
||||
"discovered": "2026-04-22T03:00:04.354919"
|
||||
"discovered": "2026-04-22T05:00:03.530637"
|
||||
},
|
||||
{
|
||||
"name": "mxyhi_ok-skills",
|
||||
@@ -114,7 +114,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "# OK Skills: AI Coding Agent Skills for Codex, Claude Code, Cursor, OpenClaw, and More English | [简体中文](README.zh-CN.md) | [繁體中文](README.zh-TW.md) | ",
|
||||
"discovered": "2026-04-22T03:00:04.347146"
|
||||
"discovered": "2026-04-22T05:00:03.419883"
|
||||
},
|
||||
{
|
||||
"name": "SuperClaude_Framework",
|
||||
@@ -127,7 +127,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "<div align=\"center\"> # 🚀 SuperClaude Framework [](https://smithery.ai/skills?ns=",
|
||||
"discovered": "2026-04-22T03:00:02.751614"
|
||||
"discovered": "2026-04-22T05:00:02.734645"
|
||||
},
|
||||
{
|
||||
"name": "paperclip-weval",
|
||||
@@ -140,7 +140,7 @@
|
||||
"has_docker": true,
|
||||
"wired": true,
|
||||
"description": "<p align=\"center\"> <img src=\"doc/assets/header.png\" alt=\"Paperclip — runs your business\" width=\"720\" /> </p> <p align=\"center\"> <a href=\"#quickst",
|
||||
"discovered": "2026-04-22T03:00:04.411143"
|
||||
"discovered": "2026-04-22T05:00:03.769431"
|
||||
},
|
||||
{
|
||||
"name": "vllm",
|
||||
@@ -153,7 +153,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "<!-- markdownlint-disable MD001 MD041 --> <p align=\"center\"> <picture> <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubus",
|
||||
"discovered": "2026-04-22T03:00:05.130813"
|
||||
"discovered": "2026-04-22T05:00:04.384782"
|
||||
},
|
||||
{
|
||||
"name": "deer-flow",
|
||||
@@ -166,7 +166,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "# 🦌 DeerFlow - 2.0 English | [中文](./README_zh.md) | [日本語](./README_ja.md) | [Français](./README_fr.md) | [Русский](./README_ru.md) [ [](https://agent.xfyun.cn) <div align=\"center\"> [ | [Français](docs/translations/README.fr.md) | [Italiano](docs/translations/README.it.md) | ",
|
||||
"discovered": "2026-04-22T03:00:02.643026"
|
||||
"discovered": "2026-04-22T05:00:02.729170"
|
||||
},
|
||||
{
|
||||
"name": "aios",
|
||||
@@ -374,7 +374,7 @@
|
||||
"has_docker": true,
|
||||
"wired": true,
|
||||
"description": "# AIOS: AI Agent Operating System <a href='https://arxiv.org/abs/2403.16971'><img src='https://img.shields.io/badge/Paper-PDF-red'></a> <a href='http",
|
||||
"discovered": "2026-04-22T03:00:02.930720"
|
||||
"discovered": "2026-04-22T05:00:02.743498"
|
||||
},
|
||||
{
|
||||
"name": "rnd-agent-framework",
|
||||
@@ -387,7 +387,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": " # Welcome to Microsoft Agent Framework! [\"> <source srcset=\"apps/w",
|
||||
"discovered": "2026-04-22T03:00:04.971671"
|
||||
"discovered": "2026-04-22T05:00:04.303401"
|
||||
},
|
||||
{
|
||||
"name": "fmgapp",
|
||||
@@ -478,7 +478,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:03.914370"
|
||||
"discovered": "2026-04-22T05:00:03.196453"
|
||||
},
|
||||
{
|
||||
"name": "obsidian-vault",
|
||||
@@ -491,7 +491,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.352526"
|
||||
"discovered": "2026-04-22T05:00:03.437223"
|
||||
},
|
||||
{
|
||||
"name": "rnd-agents",
|
||||
@@ -504,7 +504,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "# Claude Code Plugins: Orchestration and Automation > **⚡ Updated for Opus 4.6, Sonnet 4.6 & Haiku 4.5** — Three-tier model strategy for optimal perf",
|
||||
"discovered": "2026-04-22T03:00:04.591366"
|
||||
"discovered": "2026-04-22T05:00:03.976197"
|
||||
},
|
||||
{
|
||||
"name": "FrancyJGLisboa_agent-skill-creator",
|
||||
@@ -517,7 +517,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "# Agent Skill Creator **Turn any workflow into reusable AI agent software that installs on 14+ tools — no spec writing, no prompt engineering, no cod",
|
||||
"discovered": "2026-04-22T03:00:02.580518"
|
||||
"discovered": "2026-04-22T05:00:02.726368"
|
||||
},
|
||||
{
|
||||
"name": "oss",
|
||||
@@ -530,7 +530,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "# WEVAL OSS Registry · /opt/oss/ Wave 222 · 2026-04-21 ## Purpose Register the OSS tools identified by AI capability gap audit (wave 220 ai-gap-cach",
|
||||
"discovered": "2026-04-22T03:00:04.368746"
|
||||
"discovered": "2026-04-22T05:00:03.660362"
|
||||
},
|
||||
{
|
||||
"name": "scripts",
|
||||
@@ -543,7 +543,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "# Token Rotation Scripts · Opus Session 21-avr v7 ## État - 5 scripts provider skeleton (groq, github, sambanova, alibaba, whatsapp) - 1 master dispa",
|
||||
"discovered": "2026-04-22T03:00:04.787278"
|
||||
"discovered": "2026-04-22T05:00:04.125761"
|
||||
},
|
||||
{
|
||||
"name": "skillsmith",
|
||||
@@ -556,7 +556,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "<div align=\"center\"> <img src=\"terminal.svg\" alt=\"Skillsmith terminal\" width=\"740\"/> </div> <div align=\"center\"> # Skillsmith **Build consistent ",
|
||||
"discovered": "2026-04-22T03:00:04.861590"
|
||||
"discovered": "2026-04-22T05:00:04.197142"
|
||||
},
|
||||
{
|
||||
"name": "awesome-agent-skills",
|
||||
@@ -569,7 +569,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "<a href=\"https://github.com/VoltAgent/voltagent\"> <img width=\"1500\" height=\"801\" alt=\"claude-skills\" src=\"https://github.com/user-attachments/ass",
|
||||
"discovered": "2026-04-22T03:00:03.250603"
|
||||
"discovered": "2026-04-22T05:00:02.927508"
|
||||
},
|
||||
{
|
||||
"name": "paperclip-skills",
|
||||
@@ -582,7 +582,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.372724"
|
||||
"discovered": "2026-04-22T05:00:03.716125"
|
||||
},
|
||||
{
|
||||
"name": "__pycache__",
|
||||
@@ -595,7 +595,7 @@
|
||||
"has_docker": false,
|
||||
"wired": false,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:02.796976"
|
||||
"discovered": "2026-04-22T05:00:02.739048"
|
||||
},
|
||||
{
|
||||
"name": "jzOcb_writing-style-skill",
|
||||
@@ -608,7 +608,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "# Writing Style Skill 可复用的写作风格 Skill 模板。**内置自动学习** — 从你的修改中自动提取规则,SKILL.md 越用越准。 兼容 **Claude Code** + **OpenClaw (ClawHub)**。 ## 原理 ``` AI 用 SKILL",
|
||||
"discovered": "2026-04-22T03:00:04.050636"
|
||||
"discovered": "2026-04-22T05:00:03.239106"
|
||||
},
|
||||
{
|
||||
"name": "qdrant-data",
|
||||
@@ -621,7 +621,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.517814"
|
||||
"discovered": "2026-04-22T05:00:03.868648"
|
||||
},
|
||||
{
|
||||
"name": "wazuh",
|
||||
@@ -634,7 +634,7 @@
|
||||
"has_docker": true,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.187204"
|
||||
"discovered": "2026-04-22T05:00:04.422902"
|
||||
},
|
||||
{
|
||||
"name": "plausible",
|
||||
@@ -647,7 +647,7 @@
|
||||
"has_docker": true,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.439740"
|
||||
"discovered": "2026-04-22T05:00:03.783635"
|
||||
},
|
||||
{
|
||||
"name": "pmta",
|
||||
@@ -660,7 +660,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.477015"
|
||||
"discovered": "2026-04-22T05:00:03.785726"
|
||||
},
|
||||
{
|
||||
"name": "render-configs",
|
||||
@@ -673,7 +673,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.534246"
|
||||
"discovered": "2026-04-22T05:00:03.942716"
|
||||
},
|
||||
{
|
||||
"name": "searxng",
|
||||
@@ -686,7 +686,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.790234"
|
||||
"discovered": "2026-04-22T05:00:04.151920"
|
||||
},
|
||||
{
|
||||
"name": "weval-guardian",
|
||||
@@ -699,7 +699,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.326642"
|
||||
"discovered": "2026-04-22T05:00:04.535805"
|
||||
},
|
||||
{
|
||||
"name": "weval-litellm",
|
||||
@@ -712,7 +712,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.462047"
|
||||
"discovered": "2026-04-22T05:00:04.578484"
|
||||
},
|
||||
{
|
||||
"name": "weval-security",
|
||||
@@ -725,7 +725,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.618222"
|
||||
"discovered": "2026-04-22T05:00:04.740268"
|
||||
},
|
||||
{
|
||||
"name": "archive",
|
||||
@@ -738,7 +738,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:03.151626"
|
||||
"discovered": "2026-04-22T05:00:02.772307"
|
||||
},
|
||||
{
|
||||
"name": "loki",
|
||||
@@ -751,7 +751,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.308371"
|
||||
"discovered": "2026-04-22T05:00:03.322173"
|
||||
},
|
||||
{
|
||||
"name": "ruflo",
|
||||
@@ -764,7 +764,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.754650"
|
||||
"discovered": "2026-04-22T05:00:04.123854"
|
||||
},
|
||||
{
|
||||
"name": "twenty",
|
||||
@@ -777,7 +777,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.063895"
|
||||
"discovered": "2026-04-22T05:00:04.360420"
|
||||
},
|
||||
{
|
||||
"name": "weval-crewai",
|
||||
@@ -790,7 +790,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.265353"
|
||||
"discovered": "2026-04-22T05:00:04.494641"
|
||||
},
|
||||
{
|
||||
"name": "weval-plugins",
|
||||
@@ -803,7 +803,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.554757"
|
||||
"discovered": "2026-04-22T05:00:04.662784"
|
||||
},
|
||||
{
|
||||
"name": "weval-radar",
|
||||
@@ -816,7 +816,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.560146"
|
||||
"discovered": "2026-04-22T05:00:04.701336"
|
||||
},
|
||||
{
|
||||
"name": "weval-scrapy",
|
||||
@@ -829,7 +829,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.599175"
|
||||
"discovered": "2026-04-22T05:00:04.703453"
|
||||
},
|
||||
{
|
||||
"name": "blade",
|
||||
@@ -842,7 +842,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:03.462280"
|
||||
"discovered": "2026-04-22T05:00:03.058886"
|
||||
},
|
||||
{
|
||||
"name": "langfuse",
|
||||
@@ -855,7 +855,7 @@
|
||||
"has_docker": true,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.114416"
|
||||
"discovered": "2026-04-22T05:00:03.252520"
|
||||
},
|
||||
{
|
||||
"name": "litellm",
|
||||
@@ -868,7 +868,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.222558"
|
||||
"discovered": "2026-04-22T05:00:03.292301"
|
||||
},
|
||||
{
|
||||
"name": "mattermost-docker",
|
||||
@@ -881,7 +881,7 @@
|
||||
"has_docker": true,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.315559"
|
||||
"discovered": "2026-04-22T05:00:03.330081"
|
||||
},
|
||||
{
|
||||
"name": "prometheus",
|
||||
@@ -894,7 +894,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.494621"
|
||||
"discovered": "2026-04-22T05:00:03.822364"
|
||||
},
|
||||
{
|
||||
"name": "twenty-compose",
|
||||
@@ -907,7 +907,20 @@
|
||||
"has_docker": true,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.117576"
|
||||
"discovered": "2026-04-22T05:00:04.382525"
|
||||
},
|
||||
{
|
||||
"name": "weval-cli",
|
||||
"path": "/opt/weval-cli",
|
||||
"files": 1,
|
||||
"has_readme": false,
|
||||
"has_skill": false,
|
||||
"has_python": false,
|
||||
"has_node": false,
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T05:00:04.482509"
|
||||
},
|
||||
{
|
||||
"name": "weval-ux",
|
||||
@@ -920,7 +933,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.626490"
|
||||
"discovered": "2026-04-22T05:00:04.744751"
|
||||
},
|
||||
{
|
||||
"name": "wevia-integrity",
|
||||
@@ -933,7 +946,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.673444"
|
||||
"discovered": "2026-04-22T05:00:04.823387"
|
||||
},
|
||||
{
|
||||
"name": "DiffusionDB",
|
||||
@@ -946,7 +959,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:02.551808"
|
||||
"discovered": "2026-04-22T05:00:02.720532"
|
||||
},
|
||||
{
|
||||
"name": "LTX-Video",
|
||||
@@ -959,7 +972,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:02.693789"
|
||||
"discovered": "2026-04-22T05:00:02.732512"
|
||||
},
|
||||
{
|
||||
"name": "localai",
|
||||
@@ -972,7 +985,7 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:04.306052"
|
||||
"discovered": "2026-04-22T05:00:03.309907"
|
||||
},
|
||||
{
|
||||
"name": "wevia-finetune",
|
||||
@@ -985,6 +998,6 @@
|
||||
"has_docker": false,
|
||||
"wired": true,
|
||||
"description": "",
|
||||
"discovered": "2026-04-22T03:00:05.653037"
|
||||
"discovered": "2026-04-22T05:00:04.792179"
|
||||
}
|
||||
]
|
||||
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 353 KiB |
|
After Width: | Height: | Size: 395 KiB |
|
After Width: | Height: | Size: 405 KiB |
|
After Width: | Height: | Size: 413 KiB |
|
After Width: | Height: | Size: 413 KiB |
|
After Width: | Height: | Size: 413 KiB |
|
After Width: | Height: | Size: 413 KiB |
|
After Width: | Height: | Size: 404 KiB |
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"ts": "2026-04-22T02-15-15-124Z",
|
||||
"version": "V163",
|
||||
"tests": [
|
||||
{
|
||||
"name": "load_login",
|
||||
"pass": true,
|
||||
"status": 200
|
||||
},
|
||||
{
|
||||
"name": "manual_toggle",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "login_submit",
|
||||
"pass": true,
|
||||
"url": "https://weval-consulting.com/products/workspace.html"
|
||||
},
|
||||
{
|
||||
"name": "v162_panel_dom",
|
||||
"pass": true,
|
||||
"panel": true,
|
||||
"stages": 7,
|
||||
"body": true,
|
||||
"toggle": true
|
||||
},
|
||||
{
|
||||
"name": "panel_default_hidden",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "all_stages_reached",
|
||||
"pass": true,
|
||||
"state": [
|
||||
{
|
||||
"stage": "plan",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "prepare",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "code",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "test",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "commit",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "wiki",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "rag",
|
||||
"active": true,
|
||||
"done": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "exception",
|
||||
"pass": false,
|
||||
"error": "page.click: Timeout 30000ms exceeded.\nCall log:\n - waiting for locator('#thpToggle')\n - locator resolved to <button type=\"button\" id=\"thpToggle\" class=\"thp-toggle\" aria-label=\"Toggle thinking\">Collapse</button>\n - attempting click action\n 2 × waiting for element to be visible, enabled and stable\n - element is visible, enabled and stable\n - scrolling into view if needed\n - do"
|
||||
}
|
||||
],
|
||||
"video": "/var/www/html/api/playwright-results/v163-wevia-master-thinking-2026-04-22T02-15-15-124Z/page@4034ae1981d48ad0fcae879bccd452dd.webm",
|
||||
"screenshots_dir": "/var/www/html/api/playwright-results/v163-wevia-master-thinking-2026-04-22T02-15-15-124Z",
|
||||
"pass_total": 6,
|
||||
"fail_total": 1,
|
||||
"all_pass": false
|
||||
}
|
||||
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 303 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 298 KiB |
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"ts": "2026-04-22T02-20-21-927Z",
|
||||
"version": "V164",
|
||||
"tests": [
|
||||
{
|
||||
"name": "load_login",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "manual_toggle",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "login_submit",
|
||||
"pass": true,
|
||||
"url": "https://weval-consulting.com/products/workspace.html"
|
||||
},
|
||||
{
|
||||
"name": "v162_panel_dom",
|
||||
"pass": true,
|
||||
"panel": true,
|
||||
"stages": 7
|
||||
},
|
||||
{
|
||||
"name": "panel_default_hidden",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "all_stages_reached",
|
||||
"pass": true,
|
||||
"state": [
|
||||
{
|
||||
"stage": "plan",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "prepare",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "code",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "test",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "commit",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "wiki",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "rag",
|
||||
"active": true,
|
||||
"done": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "toggle_collapse",
|
||||
"pass": false,
|
||||
"click_ok": true,
|
||||
"body_collapsed": false
|
||||
},
|
||||
{
|
||||
"name": "toggle_expand",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "dashboard_counts",
|
||||
"pass": true,
|
||||
"providers": "17",
|
||||
"tools": "?",
|
||||
"agents": "?"
|
||||
}
|
||||
],
|
||||
"video": "/var/www/html/api/playwright-results/v164-wevia-master-thinking-2026-04-22T02-20-21-927Z/page@20460071cc92fc15fa893f9257796acd.webm",
|
||||
"screenshots_dir": "/var/www/html/api/playwright-results/v164-wevia-master-thinking-2026-04-22T02-20-21-927Z",
|
||||
"pass_total": 8,
|
||||
"fail_total": 1,
|
||||
"all_pass": false
|
||||
}
|
||||
|
After Width: | Height: | Size: 303 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"ts": "2026-04-22T02-23-16-338Z",
|
||||
"version": "V165",
|
||||
"tests": [
|
||||
{
|
||||
"name": "load_login",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "manual_toggle",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "login_submit",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "v162_panel_dom",
|
||||
"pass": true,
|
||||
"panel": true,
|
||||
"stages": 7
|
||||
},
|
||||
{
|
||||
"name": "panel_default_hidden",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "all_stages_reached",
|
||||
"pass": true,
|
||||
"state": [
|
||||
{
|
||||
"stage": "plan",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "prepare",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "code",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "test",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "commit",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "wiki",
|
||||
"active": false,
|
||||
"done": true
|
||||
},
|
||||
{
|
||||
"stage": "rag",
|
||||
"active": true,
|
||||
"done": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "toggle_collapse",
|
||||
"pass": true,
|
||||
"initial_collapsed": false,
|
||||
"after": {
|
||||
"collapsed": true,
|
||||
"btnText": "Expand"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "toggle_expand",
|
||||
"pass": true,
|
||||
"after": {
|
||||
"collapsed": false,
|
||||
"btnText": "Collapse"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "dashboard_counts",
|
||||
"pass": true,
|
||||
"providers": "17",
|
||||
"tools": "?"
|
||||
}
|
||||
],
|
||||
"video": "/var/www/html/api/playwright-results/v165-wevia-master-final-2026-04-22T02-23-16-338Z/page@62e5c92f1337b4f87fd3825089e17182.webm",
|
||||
"screenshots_dir": "/var/www/html/api/playwright-results/v165-wevia-master-final-2026-04-22T02-23-16-338Z",
|
||||
"pass_total": 9,
|
||||
"fail_total": 0,
|
||||
"all_pass": true,
|
||||
"target_7_7": true
|
||||
}
|
||||
|
After Width: | Height: | Size: 303 KiB |
|
After Width: | Height: | Size: 303 KiB |
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"ts": "2026-04-22T02-29-49-625Z",
|
||||
"version": "V167",
|
||||
"tests": [
|
||||
{
|
||||
"name": "login",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "v166_wired",
|
||||
"pass": true
|
||||
},
|
||||
{
|
||||
"name": "exception",
|
||||
"pass": false,
|
||||
"error": "locator.click: Timeout 30000ms exceeded.\nCall log:\n - waiting for locator('#input').first()\n - locator resolved to <textarea rows=\"1\" id=\"input\" autocomplete=\"off\" placeholder=\"Demandez à WEVIA... (images, fichiers, long texte)\" oninput=\"this.style.height='auto';this.style.height=Math.min(this.s"
|
||||
}
|
||||
],
|
||||
"video": "/var/www/html/api/playwright-results/v167-wevia-master-real-pattern-2026-04-22T02-29-49-625Z/page@8b2fa78d5c9a9275cc762da27b0c55d6.webm",
|
||||
"screenshots_dir": "/var/www/html/api/playwright-results/v167-wevia-master-real-pattern-2026-04-22T02-29-49-625Z",
|
||||
"pass_total": 2,
|
||||
"fail_total": 1,
|
||||
"all_pass": false
|
||||
}
|
||||
|
After Width: | Height: | Size: 303 KiB |
|
After Width: | Height: | Size: 307 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 308 KiB |