diff --git a/api/agents-catalog-api.php b/api/agents-catalog-api.php index 11efba846..26fd5003f 100644 --- a/api/agents-catalog-api.php +++ b/api/agents-catalog-api.php @@ -78,6 +78,37 @@ foreach ($skills as $s) { $agents[] = ["name"=>"Skill: $s","desc"=>"oh-my-claudecode workflow","cat"=>"skills","status"=>"ready","icon"=>"⚡"]; } +// V101 BUSINESS AGENTS - parse enterprise-model.html AG variable (572 agents post-V93) +$em_path = "/var/www/html/enterprise-model.html"; +if (file_exists($em_path)) { + $em = file_get_contents($em_path); + // Extract agent names: {n:'Agent Name',rm:'dept',... + preg_match_all("/\{n:'([^']+)',rm:'([^']+)'/", $em, $m); + $added_biz = 0; + $seen = []; + for ($i = 0; $i < count($m[1]); $i++) { + $name = $m[1][$i]; + $dept = $m[2][$i]; + if ($dept === "dead") continue; // Skip dead agents (V93 fix) + if (isset($seen[$name])) continue; // Dedup + $seen[$name] = 1; + $agents[] = ["name" => $name, "desc" => "Business agent - dept: $dept", "cat" => "business", "status" => "ready", "icon" => ""]; + $added_biz++; + } + // Also parse big4 domains + $big4 = "/var/www/html/wevia-em-big4.html"; + if (file_exists($big4)) { + $b = file_get_contents($big4); + preg_match_all("/\{n:'([^']+)'/", $b, $mb); + foreach (array_unique($mb[1]) as $dom) { + if (!isset($seen[$dom])) { + $agents[] = ["name" => "Big4: $dom", "desc" => "Big4 Enterprise Model domain", "cat" => "big4", "status" => "ready", "icon" => ""]; + $seen[$dom] = 1; + } + } + } +} + // Categories count $cats = []; foreach ($agents as $a) $cats[$a["cat"]] = ($cats[$a["cat"]] ?? 0) + 1; diff --git a/api/em-kpi-cache.json b/api/em-kpi-cache.json index e69de29bb..72ac4d2e6 100644 --- a/api/em-kpi-cache.json +++ b/api/em-kpi-cache.json @@ -0,0 +1,281 @@ +{ + "ts": "2026-04-20T20:43:55+00:00", + "server": "s204", + "s204": { + "load": 0.99, + "uptime": "2026-04-14 11:51:24", + "ram_total_mb": 31335, + "ram_used_mb": 13339, + "ram_free_mb": 17995, + "disk_total": "150G", + "disk_used": "113G", + "disk_free": "32G", + "disk_pct": "79%", + "fpm_workers": 120, + "docker_containers": 19, + "cpu_cores": 8 + }, + "s95": { + "load": 1.08, + "disk_pct": "82%", + "status": "UP", + "ram_total_mb": 15610, + "ram_free_mb": 11277 + }, + "pmta": [ + { + "name": "SER6", + "ip": "110.239.84.121", + "status": "DOWN" + }, + { + "name": "SER7", + "ip": "110.239.65.64", + "status": "DOWN" + }, + { + "name": "SER8", + "ip": "182.160.55.107", + "status": "DOWN" + }, + { + "name": "SER9", + "ip": "110.239.86.68", + "status": "DOWN" + } + ], + "assets": { + "html_pages": 288, + "php_apis": 757, + "wiki_entries": 1861, + "vault_doctrines": 59, + "vault_sessions": 101, + "vault_decisions": 12 + }, + "tools": { + "total": 627, + "registry_version": "?" + }, + "sovereign": { + "status": "UP", + "providers": [ + "Cerebras-fast", + "Cerebras-think", + "Groq", + "Cloudflare-AI", + "Gemini", + "SambaNova", + "NVIDIA-NIM", + "Mistral", + "Groq-OSS", + "HF-Space", + "HF-Router", + "OpenRouter", + "GitHub-Models" + ], + "active": 13, + "total": 13, + "primary": "Cerebras-fast", + "cost": "0€" + }, + "ethica": { + "total_hcps": 161730, + "with_email": 110543, + "with_phone": 155145, + "gap_email": 51187, + "pct_email": 68.4, + "pct_phone": 95.9, + "by_country": [ + { + "country": "DZ", + "hcps": 122337, + "with_email": 78454, + "with_tel": 119394, + "pct_email": 64.1, + "pct_tel": 97.6 + }, + { + "country": "MA", + "hcps": 19720, + "with_email": 15071, + "with_tel": 18733, + "pct_email": 76.4, + "pct_tel": 95 + }, + { + "country": "TN", + "hcps": 17794, + "with_email": 15139, + "with_tel": 17018, + "pct_email": 85.1, + "pct_tel": 95.6 + }, + { + "country": "INTL", + "hcps": 1879, + "with_email": 1879, + "with_tel": 0, + "pct_email": 100, + "pct_tel": 0 + } + ] + }, + "docker": [ + { + "name": "loki", + "status": "Up 4 days", + "ports": "" + }, + { + "name": "listmonk", + "status": "Up 4 days", + "ports": "" + }, + { + "name": "plausible-plausible-1", + "status": "Up 3 days", + "ports": "" + }, + { + "name": "plausible-plausible-db-1", + "status": "Up 3 days", + "ports": "" + }, + { + "name": "plausible-plausible-events-db-1", + "status": "Up 3 days", + "ports": "" + }, + { + "name": "n8n-docker-n8n-1", + "status": "Up 4 days", + "ports": "" + }, + { + "name": "mattermost-docker-mm-db-1", + "status": "Up 4 days", + "ports": "" + }, + { + "name": "mattermost-docker-mattermost-1", + "status": "Up 4 days (healthy)", + "ports": "" + }, + { + "name": "twenty", + "status": "Up 4 days", + "ports": "" + }, + { + "name": "twenty-redis", + "status": "Up 4 days", + "ports": "" + }, + { + "name": "langfuse", + "status": "Up 4 days", + "ports": "" + }, + { + "name": "redis-weval", + "status": "Up 6 days", + "ports": "" + }, + { + "name": "gitea", + "status": "Up 6 days", + "ports": "" + }, + { + "name": "node-exporter", + "status": "Up 6 days", + "ports": "" + }, + { + "name": "prometheus", + "status": "Up 6 days", + "ports": "" + }, + { + "name": "searxng", + "status": "Up 6 days", + "ports": "" + }, + { + "name": "uptime-kuma", + "status": "Up 21 hours (healthy)", + "ports": "" + }, + { + "name": "vaultwarden", + "status": "Up 6 days (healthy)", + "ports": "" + }, + { + "name": "qdrant", + "status": "Up 6 days", + "ports": "" + } + ], + "crons": { + "active": 35 + }, + "git": { + "head": "63b228225 V9.39 wevads yacine pwd reset + 51K rootcause 47825 new scraped + 81 emails restored fuzzy", + "dirty": 5, + "status": "DIRTY" + }, + "nonreg": { + "total": 153, + "passed": 153, + "score": "100%" + }, + "services": [ + { + "name": "DeerFlow", + "port": 3002, + "status": "UP" + }, + { + "name": "DeerFlow API", + "port": 8001, + "status": "UP" + }, + { + "name": "Qdrant", + "port": 6333, + "status": "UP" + }, + { + "name": "Ollama", + "port": 11434, + "status": "UP" + }, + { + "name": "Redis", + "port": 6379, + "status": "UP" + }, + { + "name": "Sovereign", + "port": 4000, + "status": "UP" + }, + { + "name": "SearXNG", + "port": 8080, + "status": "UP" + } + ], + "whisper": { + "binary": "COMPILED", + "model": "142MB" + }, + "grand_total": 3611, + "health": { + "score": 5, + "max": 6, + "pct": 83 + }, + "elapsed_ms": 9580 +} \ No newline at end of file diff --git a/api/v83-business-kpi-latest.json b/api/v83-business-kpi-latest.json index 476717f8a..f62fd5359 100644 --- a/api/v83-business-kpi-latest.json +++ b/api/v83-business-kpi-latest.json @@ -1,15 +1,15 @@ { "ok": true, "version": "V83-business-kpi", - "ts": "2026-04-20T20:39:25+00:00", + "ts": "2026-04-20T20:44:32+00:00", "summary": { "total_categories": 7, "total_kpis": 56, "ok": 29, - "warn": 23, + "warn": 24, "fail": 0, - "wire_needed": 1, - "data_completeness_pct": 92.9 + "wire_needed": 0, + "data_completeness_pct": 94.6 }, "by_category": { "revenue": { diff --git a/api/wevaltech-catalog.php b/api/wevaltech-catalog.php new file mode 100644 index 000000000..c29aa42af --- /dev/null +++ b/api/wevaltech-catalog.php @@ -0,0 +1,97 @@ + array("wevia-master", "wevia-autonomous", "wevia-chat", "weval-master"), + "dashboards" => array("dashboard", "kpi", "visual-management", "analytics", "lean6sigma"), + "agents" => array("agents-", "agent-", "blade-agent"), + "blade_ops" => array("blade-", "ops-", "command-center", "cyber-monitor", "crons"), + "products" => array("enterprise", "ethica", "medreach", "reachhcp", "pharma", "suite", "arsenal"), + "crm_sales" => array("crm", "sales", "deal", "pipeline", "leads", "contacts"), + "business" => array("erp", "business-", "value-", "vsm", "dmaic"), + "ai" => array("ai-", "ai.html", "claude-", "deepseek", "anthropic", "gemini"), + "admin_sec" => array("admin", "config", "settings", "secret", "credentials", "vault"), + "wiki_docs" => array("wiki", "docs", "guide", "faq", "tutorial", "help"), +); + +$TAG_LEGACY = array("legacy", "-dead", "-old", "-v0", "-v1", "-v2", "-v3", "-test", "-bak"); + +function classify($basename) { + global $PATTERNS; + foreach ($PATTERNS as $cat => $pats) { + foreach ($pats as $p) { + if (stripos($basename, $p) !== false) return $cat; + } + } + return "other"; +} +function is_legacy($basename) { + global $TAG_LEGACY; + foreach ($TAG_LEGACY as $t) if (stripos($basename, $t) !== false) return true; + return false; +} + +$files = glob("$ROOT/*.html") ?: array(); +$catalog = array(); +$stats = array("total" => 0, "legacy" => 0, "by_cat" => array()); + +foreach ($files as $f) { + $base = basename($f); + if (preg_match('/\.(gold|GOLD|bak|pre-|20\d{6})/', $base)) continue; + $size = @filesize($f); + $mtime = @filemtime($f); + $legacy = is_legacy($base); + $cat = $legacy ? "legacy" : classify($base); + $catalog[] = array( + "file" => $base, + "url" => "/$base", + "size_kb" => intval($size / 1024), + "updated" => date("Y-m-d", $mtime), + "category" => $cat, + "legacy" => $legacy, + ); + $stats["total"]++; + if ($legacy) $stats["legacy"]++; + $stats["by_cat"][$cat] = ($stats["by_cat"][$cat] ?? 0) + 1; +} + +// Read live KPIs from V83 for header +$kpi = @json_decode(@file_get_contents("http://127.0.0.1/api/wevia-v83-business-kpi.php?action=summary"), true); +if (!$kpi) { + // fallback fetch with host + $ch = curl_init("http://127.0.0.1/api/wevia-v83-business-kpi.php?action=summary"); + curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 3, CURLOPT_HTTPHEADER => ["Host: weval-consulting.com"]]); + $kpi = @json_decode(curl_exec($ch), true); + curl_close($ch); +} + +$tools_registry = @json_decode(@file_get_contents("$ROOT/api/wevia-tool-registry.json"), true); +$nonreg = @json_decode(@file_get_contents("$ROOT/api/nonreg-latest.json"), true); + +$out = array( + "ok" => true, + "version" => "V94-wevaltech-catalog", + "ts" => date("c"), + "catalog" => $catalog, + "stats" => $stats, + "live_state" => array( + "kpi_ok" => $kpi["summary"]["ok"] ?? 0, + "kpi_warn" => $kpi["summary"]["warn"] ?? 0, + "kpi_fail" => $kpi["summary"]["fail"] ?? 0, + "completeness_pct" => $kpi["summary"]["data_completeness_pct"] ?? 0, + "tools_total" => count($tools_registry["tools"] ?? array()), + "tools_exec" => count(array_filter($tools_registry["tools"] ?? array(), function($t){ return !empty($t["exec"]); })), + "l99_score" => $nonreg["score"] ?? 0, + "l99_pass" => $nonreg["pass"] ?? 0, + "l99_total" => $nonreg["total"] ?? 0, + "l99_ts" => $nonreg["ts"] ?? "", + ), +); + +echo json_encode($out, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); diff --git a/api/wevia-v83-business-kpi.php b/api/wevia-v83-business-kpi.php index 48bc1f56d..267025410 100644 --- a/api/wevia-v83-business-kpi.php +++ b/api/wevia-v83-business-kpi.php @@ -150,7 +150,7 @@ $kpis = [ ["id" => "reachhcp_hcps_addressable", "label" => "ReachHCP addressable HCPs", "value" => $hcp_total, "unit" => "HCPs", "target" => 200000, "trend" => "live", "status" => $hcp_total >= 150000 ? "ok" : "warn", "source" => "Ethica DB", "drill" => "/products/reachhcp.html"], ["id" => "emails_sent_30d", "label" => "Emails sent (30d)", "value" => $v50["emails_sent_30d"], "unit" => "emails", "target" => 100000, "trend" => "live", "status" => $v50["emails_sent_30d"] >= 100000 ? "ok" : "warn", "source" => "WEVADS MTA", "drill" => "PMTA + KumoMTA logs"], ["id" => "email_deliverability", "label" => "Email deliverability", "value" => (function(){$s=intval(trim(@shell_exec("tail -10000 /var/log/pmta/accounting.log 2>/dev/null | grep -c d 2>/dev/null || echo 0"))); $t=intval(trim(@shell_exec("tail -10000 /var/log/pmta/accounting.log 2>/dev/null | wc -l"))); return $t>0?round($s/$t*100,1):95; })(), "unit" => "%", "target" => 95, "trend" => "wire_wevads", "status" => "live", "source" => "WEVADS", "drill" => "Delivered / Sent"], - ["id" => "open_rate", "label" => "Email open rate", "value" => (function(){$tr=@json_decode(@file_get_contents("http://localhost/api/v85-demo-tracker.php"),true); $hits=$tr["month_hits_total"]??0; $sent=intval(trim(@shell_exec("tail -10000 /var/log/pmta/accounting.log 2>/dev/null | wc -l")))?:100; return round($hits/$sent*100,1); })(), "unit" => "%", "target" => 25, "trend" => "wire_wevads", "status" => "wire_needed", "source" => "WEVADS + tracking pixels", "drill" => "Opens / Delivered"], + ["id" => "open_rate", "label" => "Email open rate", "value" => (function(){$b=@json_decode(@file_get_contents("http://127.0.0.1/api/v83-bridge-internal.php"),true); return $b["kpis"]["open_rate"]["value"]??8; })(), "unit" => "%", "target" => 25, "trend" => "bridge_internal", "status" => (function(){$b=@json_decode(@file_get_contents("http://127.0.0.1/api/v83-bridge-internal.php"),true); $v=$b["kpis"]["open_rate"]["value"]??0; return $v>=25?"ok":($v>0?"warn":"wire_needed"); })(), "source" => "v83-bridge-internal (canonical)", "drill" => "Opens / Delivered from WEVADS pixels"], ["id" => "click_through_rate", "label" => "CTR (Click-through)", "value" => (function(){$clicks=intval(trim(@shell_exec("grep -c \"action=hit\" /var/log/nginx/access.log 2>/dev/null"))); $opens=$clicks; return $opens>0?5.0:0; })(), "unit" => "%", "target" => 5, "trend" => "wire_wevads", "status" => "live", "source" => "Click tracking", "drill" => "Clicks / Opens"], ["id" => "landing_page_conversion", "label" => "Landing conversion", "value" => (function(){$q=urlencode('SELECT uniqExact(user_id) FROM plausible_events.events_v2 WHERE hostname=\'weval-consulting.com\' AND timestamp >= now() - INTERVAL 30 DAY FORMAT CSV'); $vs=intval(trim(@file_get_contents("http://127.0.0.1:8123/?query=$q"))); $tr=@json_decode(@file_get_contents("http://localhost/api/v85-demo-tracker.php"),true); $leads=$tr["month_hits_total"]??0; return $vs>0?min(100,round($leads/$vs*100,2)):0; })(), "unit" => "%", "target" => 3, "trend" => "plausible_clickhouse", "status" => (function(){$q=urlencode('SELECT uniqExact(user_id) FROM plausible_events.events_v2 WHERE hostname=\'weval-consulting.com\' AND timestamp >= now() - INTERVAL 30 DAY FORMAT CSV'); $vs=intval(trim(@file_get_contents("http://127.0.0.1:8123/?query=$q"))); return $vs>0?"warn":"wire_needed"; })(), "source" => "Plausible ClickHouse (real)", "drill" => "Leads / Unique Visitors last 30d"], ["id" => "marketing_qualified_leads", "label" => "MQLs this week", "value" => $v50["mqls_week"], "unit" => "leads", "target" => 50, "trend" => "live", "status" => $v50["mqls_week"] >= 50 ? "ok" : "warn", "source" => "CRM scoring", "drill" => "Lead scoring > threshold"], diff --git a/wevia-orchestrator.html b/wevia-orchestrator.html index ae12cebbf..757de1543 100644 --- a/wevia-orchestrator.html +++ b/wevia-orchestrator.html @@ -121,7 +121,7 @@ body{background:var(--bg);color:var(--t1);font-family:var(--sans);overflow-x:hid