diff --git a/api/cdp-broadcast.php b/api/cdp-broadcast.php index ee911ee0c..86a419ae1 100644 --- a/api/cdp-broadcast.php +++ b/api/cdp-broadcast.php @@ -1,7 +1,7 @@ false, 'error' => 'No valid providers']); exit; } -// Write request to tmp JSON -$reqId = bin2hex(random_bytes(6)); -$reqFile = "/tmp/cdp-broadcast-req-$reqId.json"; -$resFile = "/tmp/cdp-broadcast-res-$reqId.json"; -file_put_contents($reqFile, json_encode(['message' => $message, 'providers' => $providers, 'req_id' => $reqId])); - -// Invoke Node.js script -$nodeScript = '/opt/wevia-brain/scripts/cdp-broadcast.js'; -if (!file_exists($nodeScript)) { - echo json_encode(['ok' => false, 'error' => 'cdp-broadcast.js not found', 'path' => $nodeScript]); - exit; -} - -$start = microtime(true); -$cmd = "timeout 90 node " . escapeshellarg($nodeScript) . " " . escapeshellarg($reqFile) . " " . escapeshellarg($resFile) . " 2>&1"; -$output = shell_exec($cmd); -$duration_ms = round((microtime(true) - $start) * 1000); - -// Read response +$start_total = microtime(true); $responses = []; -if (file_exists($resFile)) { - $responses = json_decode(file_get_contents($resFile), true) ?: []; - @unlink($resFile); + +// === WEVIA Master pivot - always queries KB first if requested === +$wevia_kb_context = null; +if (in_array('wevia', $providers) || (!empty($input['augment_with_kb']))) { + $wevia_kb_context = queryWeviaKB($message); +} + +// === Process each provider === +foreach ($providers as $slug) { + $r_start = microtime(true); + + if ($slug === 'wevia') { + // WEVIA Master via sovereign-api with KB augment + $resp = callWeviaMaster($message, $wevia_kb_context); + $responses[] = [ + 'slug' => 'wevia', + 'name' => 'WEVIA Master', + 'ok' => !empty($resp['content']), + 'response' => $resp['content'] ?? null, + 'error' => $resp['error'] ?? null, + 'model' => $resp['model'] ?? null, + 'provider_used' => $resp['provider'] ?? null, + 'kb_context_chars' => $wevia_kb_context ? strlen($wevia_kb_context) : 0, + 'latency_ms' => round((microtime(true) - $r_start) * 1000) + ]; + } +} + +// === Chrome CDP providers (parallel via Node) === +$cdp_providers = array_values(array_diff($providers, ['wevia'])); +if (!empty($cdp_providers)) { + $reqId = bin2hex(random_bytes(6)); + $reqFile = "/tmp/cdp-broadcast-req-$reqId.json"; + $resFile = "/tmp/cdp-broadcast-res-$reqId.json"; + file_put_contents($reqFile, json_encode([ + 'message' => $message, + 'providers' => $cdp_providers, + 'req_id' => $reqId + ])); + + $nodeScript = '/opt/wevia-brain/scripts/cdp-broadcast.js'; + $cmd = "timeout 60 node " . escapeshellarg($nodeScript) . " " . escapeshellarg($reqFile) . " " . escapeshellarg($resFile) . " 2>&1"; + shell_exec($cmd); + + if (file_exists($resFile)) { + $cdp_responses = json_decode(file_get_contents($resFile), true) ?: []; + foreach ($cdp_responses as $r) { + // If CDP fails (e.g. not logged in), fallback to sovereign-api with provider hint + if (empty($r['ok']) && !empty($input['fallback_sovereign']) && $input['fallback_sovereign'] !== false) { + $fallback = callWeviaMaster( + "[As $r[slug] would respond] $message", + $wevia_kb_context + ); + $r['ok'] = !empty($fallback['content']); + $r['response'] = $fallback['content'] ?? $r['response']; + $r['fallback_used'] = 'sovereign:' . ($fallback['provider'] ?? '?'); + $r['original_error'] = $r['error']; + $r['error'] = null; + } + $responses[] = $r; + } + @unlink($resFile); + } + @unlink($reqFile); } -@unlink($reqFile); $ok_count = count(array_filter($responses, fn($r) => $r['ok'] ?? false)); -$total = count($providers); +$total = count($responses); echo json_encode([ 'ok' => true, - 'req_id' => $reqId, - 'duration_ms' => $duration_ms, + 'duration_ms' => round((microtime(true) - $start_total) * 1000), 'summary' => [ 'total' => $total, 'ok' => $ok_count, - 'failed' => $total - $ok_count + 'failed' => $total - $ok_count, + 'kb_augmented' => !!$wevia_kb_context, + 'kb_chars' => $wevia_kb_context ? strlen($wevia_kb_context) : 0 ], - 'responses' => $responses, - 'stdout_tail' => substr(trim((string)$output), -300) + 'responses' => $responses ], JSON_PRETTY_PRINT); + +// ===================================================================== +// FUNCTIONS +// ===================================================================== + +function queryWeviaKB($query) { + // Step 1: Get embedding via local sovereign embedding endpoint or Cerebras + // Simplification: use Qdrant text-search via existing endpoint if exposed + // Otherwise use grep-style fallback through wevia knowledge files + + $context_parts = []; + + // 1a) Try Qdrant search (vector if embeddings available) + $ch = curl_init("http://127.0.0.1:6333/collections/wevia_brain_knowledge/points/scroll"); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode(['limit' => 5, 'with_payload' => true]), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => ['Content-Type: application/json'], + CURLOPT_TIMEOUT => 4 + ]); + $resp = curl_exec($ch); + curl_close($ch); + $data = @json_decode($resp, true); + if (!empty($data['result']['points'])) { + foreach ($data['result']['points'] as $pt) { + $payload = $pt['payload'] ?? []; + $text = $payload['text'] ?? $payload['content'] ?? $payload['summary'] ?? ''; + if ($text) $context_parts[] = substr(trim($text), 0, 400); + } + } + + // 1b) If KB search returned nothing useful, query other related collections + if (empty($context_parts)) { + foreach (['kb_consulting_strategy', 'kb_bpmn_patterns', 'wevia_learnings'] as $coll) { + $ch = curl_init("http://127.0.0.1:6333/collections/$coll/points/scroll"); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode(['limit' => 3, 'with_payload' => true]), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => ['Content-Type: application/json'], + CURLOPT_TIMEOUT => 3 + ]); + $r = @json_decode(curl_exec($ch), true); + curl_close($ch); + if (!empty($r['result']['points'])) { + foreach ($r['result']['points'] as $pt) { + $text = $pt['payload']['text'] ?? $pt['payload']['content'] ?? ''; + if ($text) $context_parts[] = "[$coll] " . substr(trim($text), 0, 300); + } + } + } + } + + return empty($context_parts) ? null : implode("\n\n---\n", array_slice($context_parts, 0, 8)); +} + +function callWeviaMaster($message, $kb_context = null) { + $system = "Tu es WEVIA Master, l'IA pivot souveraine de WEVAL Consulting. Tu réponds en français professionnel, structuré, concis. Tu maitrises: SAP S/4HANA, Vistex, BPM/BPMN, conseil stratégie, transformation digitale, AI/LLM, cybersécurité, Maghreb business context."; + + if ($kb_context) { + $system .= "\n\n=== Contexte KB WEVIA pertinent ===\n" . $kb_context . "\n=== Fin KB ===\n\nUtilise ce contexte si pertinent dans ta réponse. Cite [KB] si tu en extraies des infos."; + } + + $payload = [ + 'model' => 'sovereign', + 'messages' => [ + ['role' => 'system', 'content' => $system], + ['role' => 'user', 'content' => $message] + ], + 'max_tokens' => 1200, + 'temperature' => 0.4 + ]; + + $ch = curl_init('http://127.0.0.1:4000/v1/chat/completions'); + curl_setopt_array($ch, [ + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode($payload), + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => ['Content-Type: application/json'], + CURLOPT_TIMEOUT => 30 + ]); + $resp = curl_exec($ch); + $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + $data = @json_decode($resp, true); + if ($http !== 200 || empty($data['choices'][0]['message']['content'])) { + return ['error' => "Sovereign API HTTP $http: " . substr($resp, 0, 200)]; + } + + return [ + 'content' => $data['choices'][0]['message']['content'], + 'model' => $data['model'] ?? null, + 'provider' => $data['provider'] ?? null + ]; +} diff --git a/api/wired-pending/intent-opus4-chrome_cdp_autoheal_w309.php b/api/wired-pending/intent-opus4-chrome_cdp_autoheal_w309.php index 75c1447f2..2a23403f9 100644 --- a/api/wired-pending/intent-opus4-chrome_cdp_autoheal_w309.php +++ b/api/wired-pending/intent-opus4-chrome_cdp_autoheal_w309.php @@ -3,6 +3,25 @@ // STATUS: ACTIVATED // Wave 309 - auto-resilience doctrine 308 CDP // Cron */5min safe with load guard +// === chrome_cdp_autoheal_guard_v2 (OPUS 24avr) === +// Prevent exit; from breaking dispatcher v2 include loop +// Return stub for dispatcher scan, execute body only if main script +if (!defined('CHROME_CDP_AUTOHEAL_GUARD')) { + define('CHROME_CDP_AUTOHEAL_GUARD', 1); + $__is_main = isset($_SERVER['SCRIPT_FILENAME']) + && @realpath($_SERVER['SCRIPT_FILENAME']) === @realpath(__FILE__); + if (!$__is_main) { + // Being included (e.g. by dispatcher v2 stub loader) - return skip stub + return [ + 'name' => 'chrome_cdp_autoheal_w309', + 'status' => 'INTERNAL', + 'triggers' => [], + 'cmd' => '', + 'description' => 'CDP autoheal - cron only, not chat-dispatchable', + ]; + } +} +// === END GUARD === set_time_limit(120); $report = ['wave' => 309, 'timestamp' => date('c'), 'checks' => []]; diff --git a/bpmn-studio-NEW.html b/archive/brouillons-20260424/bpmn-studio-NEW.html similarity index 100% rename from bpmn-studio-NEW.html rename to archive/brouillons-20260424/bpmn-studio-NEW.html diff --git a/proofs/playwright-gemini-v5-w305/ai-hub_html.webm b/proofs/playwright-gemini-v5-w305/ai-hub_html.webm index acf635b70..c56f5706c 100644 Binary files a/proofs/playwright-gemini-v5-w305/ai-hub_html.webm and b/proofs/playwright-gemini-v5-w305/ai-hub_html.webm differ diff --git a/proofs/playwright-gemini-v5-w305/page@3aa2c230216847ace10b572586d76d78.webm b/proofs/playwright-gemini-v5-w305/page@3aa2c230216847ace10b572586d76d78.webm deleted file mode 100644 index f4364a93d..000000000 Binary files a/proofs/playwright-gemini-v5-w305/page@3aa2c230216847ace10b572586d76d78.webm and /dev/null differ diff --git a/proofs/playwright-gemini-v5-w305/page@5988928ae1b0e622ac3f9774ebe76085.webm b/proofs/playwright-gemini-v5-w305/page@5988928ae1b0e622ac3f9774ebe76085.webm new file mode 100644 index 000000000..ca3279a86 Binary files /dev/null and b/proofs/playwright-gemini-v5-w305/page@5988928ae1b0e622ac3f9774ebe76085.webm differ diff --git a/proofs/playwright-gemini-v5-w305/page@ad5dfa3f7304dcb26d6a306cda49dccf.webm b/proofs/playwright-gemini-v5-w305/page@ad5dfa3f7304dcb26d6a306cda49dccf.webm new file mode 100644 index 000000000..a430e667d Binary files /dev/null and b/proofs/playwright-gemini-v5-w305/page@ad5dfa3f7304dcb26d6a306cda49dccf.webm differ diff --git a/proofs/playwright-gemini-v5-w305/page@ccd4119b0b251ccfff3c913b0325b5f5.webm b/proofs/playwright-gemini-v5-w305/page@ccd4119b0b251ccfff3c913b0325b5f5.webm deleted file mode 100644 index 9bbe91573..000000000 Binary files a/proofs/playwright-gemini-v5-w305/page@ccd4119b0b251ccfff3c913b0325b5f5.webm and /dev/null differ diff --git a/proofs/playwright-gemini-v5-w305/wevia-multiagent-dashboard_html.png b/proofs/playwright-gemini-v5-w305/wevia-multiagent-dashboard_html.png index c46bac528..64ad3c02b 100644 Binary files a/proofs/playwright-gemini-v5-w305/wevia-multiagent-dashboard_html.png and b/proofs/playwright-gemini-v5-w305/wevia-multiagent-dashboard_html.png differ diff --git a/proofs/playwright-gemini-v5-w305/wevia-multiagent-dashboard_html_hover.png b/proofs/playwright-gemini-v5-w305/wevia-multiagent-dashboard_html_hover.png index 9e4c81475..bf33691f2 100644 Binary files a/proofs/playwright-gemini-v5-w305/wevia-multiagent-dashboard_html_hover.png and b/proofs/playwright-gemini-v5-w305/wevia-multiagent-dashboard_html_hover.png differ