Files
html/wevia-master.html

984 lines
64 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVIA Master AI</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,400;0,500;0,700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
<style>
:root{--bg:#080c14;--s1:#0d1219;--s2:#131b27;--s3:#1a2435;--bd:rgba(255,255,255,.06);--tx:#e4e8f0;--dim:#8899af;--dim2:#556677;--ac:#10b981;--ac2:rgba(16,185,129,.1);--rd:#ef4444;--bl:#3b82f6;--vi:#8b5cf6;--w:#f59e0b;--cy:#06b6d4;--mono:'JetBrains Mono',monospace;--r:10px}
*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%;overflow:hidden}
body{background:var(--bg);color:var(--tx);font-family:'DM Sans',sans-serif;display:flex}
.sidebar{width:230px;background:var(--s1);border-right:1px solid var(--bd);display:flex;flex-direction:column;flex-shrink:0}
.sb-head{padding:14px 16px;border-bottom:1px solid var(--bd);display:flex;align-items:center;justify-content:space-between}
.sb-head h2{font-size:17px;font-weight:700;color:var(--ac)}
.sb-head small{font-size:9px;color:var(--dim2)}
.sb-nav{flex:1;overflow-y:auto;padding:6px 8px}
.sb-nav::-webkit-scrollbar{width:3px}
.sb-nav::-webkit-scrollbar-thumb{background:var(--s3);border-radius:2px}
.sb-label{padding:10px 10px 4px;font-family:var(--mono);font-size:8px;text-transform:uppercase;letter-spacing:1.5px;color:var(--dim2)}
.sb-item{display:flex;align-items:center;gap:7px;padding:6px 10px;border-radius:7px;cursor:pointer;font-size:12px;color:var(--dim);transition:.15s;border:none;background:none;width:100%;text-align:left}
.sb-item:hover{background:var(--ac2);color:var(--tx);padding-left:14px}
.sb-item:active{transform:scale(.98)}
.sb-item .ic{font-size:13px;width:18px;text-align:center;flex-shrink:0}
.sb-foot{padding:10px 14px;border-top:1px solid var(--bd);font-size:9px;color:var(--dim2);line-height:1.6}
.dot{width:6px;height:6px;border-radius:50%;display:inline-block;animation:pulse 2s infinite}
.dot-g{background:var(--ac)}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.3}}
.main{flex:1;display:flex;flex-direction:column;min-width:0}
.top{height:44px;background:var(--s1);border-bottom:1px solid var(--bd);display:flex;align-items:center;justify-content:space-between;padding:0 18px;flex-shrink:0}
.top h3{font-size:13px;font-weight:700;display:flex;align-items:center;gap:8px}
.top-r{display:flex;align-items:center;gap:10px;font-size:11px;color:var(--dim)}
.top-r a{color:var(--dim);text-decoration:none;font-size:10px}
.msgs{flex:1;overflow-y:auto;padding:16px 20px;display:flex;flex-direction:column;gap:10px}
.msgs::-webkit-scrollbar{width:4px}
.msgs::-webkit-scrollbar-thumb{background:var(--s3);border-radius:2px}
.msg{max-width:78%;padding:10px 14px;border-radius:12px;font-size:13px;line-height:1.65;animation:fadeUp .25s ease;position:relative}
@keyframes fadeUp{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
.msg-u{align-self:flex-end;background:linear-gradient(135deg,#059669,#10b981);color:#fff;border-bottom-right-radius:3px}
.msg-a{align-self:flex-start;background:var(--s2);border:1px solid var(--bd);border-bottom-left-radius:3px}
.msg-a pre{background:var(--bg);border:1px solid var(--bd);border-radius:6px;padding:10px;margin:8px 0;overflow-x:auto;font-family:var(--mono);font-size:11px;line-height:1.5;position:relative}
.msg-a code{font-family:var(--mono);font-size:11px;background:rgba(255,255,255,.04);padding:1px 4px;border-radius:3px}
.msg-a strong{color:var(--ac)}
.msg-meta{display:flex;align-items:center;gap:8px;margin-top:5px;font-size:9px;color:var(--dim2)}
.msg-meta .engine{color:var(--ac);font-weight:700;font-family:var(--mono)}
.copy-btn{position:absolute;top:6px;right:6px;font-family:var(--mono);font-size:8px;padding:2px 6px;border-radius:4px;border:1px solid var(--bd);background:var(--s3);color:var(--dim);cursor:pointer;opacity:0;transition:.2s}
.msg:hover .copy-btn{opacity:1}
.copy-btn:hover{color:var(--ac);border-color:var(--ac)}
.typing{display:flex;gap:4px;padding:10px 14px;align-self:flex-start}
.typing span{width:5px;height:5px;background:var(--dim2);border-radius:50%;animation:bounce .5s infinite alternate}
.typing span:nth-child(2){animation-delay:.12s}
.typing span:nth-child(3){animation-delay:.24s}
@keyframes bounce{to{transform:translateY(-5px);background:var(--ac)}}
.welcome{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;padding:30px}
.welcome h1{font-size:32px;font-weight:700;background:linear-gradient(135deg,var(--ac),var(--cy));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
.welcome p{color:var(--dim);font-size:12px;max-width:450px;text-align:center}
.wcards{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;width:100%;max-width:680px}
.wcard{background:var(--s2);border:1px solid var(--bd);border-radius:var(--r);padding:12px;cursor:pointer;text-align:center;transition:.2s}
.wcard:hover{border-color:rgba(16,185,129,.3);transform:translateY(-2px);box-shadow:0 4px 16px rgba(16,185,129,.06)}
.wcard .em{font-size:20px;margin-bottom:4px}
.wcard b{font-size:11px;display:block}
.wcard small{font-size:9px;color:var(--dim2)}
.input-wrap{padding:10px 18px;border-top:1px solid var(--bd);background:var(--s1);flex-shrink:0}
.input-row{display:flex;gap:8px;max-width:780px;margin:0 auto;position:relative}
.input-row input,.input-row textarea{flex:1;background:var(--s3);border:1px solid var(--bd);border-radius:var(--r);padding:11px 14px 11px 40px;color:var(--tx);font-size:13px;font-family:'DM Sans',sans-serif;outline:none;transition:.2s}
.input-row input:focus,.input-row textarea:focus{border-color:var(--ac);box-shadow:0 0 0 2px var(--ac2)}
.input-row input::placeholder,.input-row textarea::placeholder{color:var(--dim2)}
.attach-btn{position:absolute;left:10px;top:50%;transform:translateY(-50%);border:none;background:none;color:var(--dim);cursor:pointer;padding:4px;transition:.2s}
.attach-btn:hover{color:var(--ac)}
.progress-wrap{margin:8px 0;display:none}
.progress-bar{height:3px;background:rgba(255,255,255,.08);border-radius:3px;overflow:hidden}
.progress-fill{height:100%;background:linear-gradient(90deg,var(--ac),#a78bfa);border-radius:3px;transition:width .3s ease;width:0%}
.progress-status{display:flex;justify-content:space-between;margin-top:4px;font:500 10px var(--mf);color:var(--dim);opacity:.7}
.send-btn{width:40px;height:40px;border-radius:var(--r);background:var(--ac);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:.15s;flex-shrink:0}
.send-btn:hover{filter:brightness(1.1);transform:scale(1.04)}
.send-btn:disabled{opacity:.3;cursor:default;transform:none}
.send-btn svg{width:16px;height:16px;fill:#fff}
.input-hint{text-align:center;font-size:9px;color:var(--dim2);margin-top:4px}
.drop-overlay{display:none;position:fixed;inset:0;z-index:100;background:rgba(16,185,129,.05);backdrop-filter:blur(4px);align-items:center;justify-content:center}
.drop-overlay.show{display:flex}
.drop-box{border:2px dashed var(--ac);border-radius:16px;padding:50px 70px;text-align:center;color:var(--ac);font-size:16px;font-weight:500}
.file-preview{display:flex;gap:6px;padding:6px 0;flex-wrap:wrap}
.file-chip{display:flex;align-items:center;gap:5px;background:var(--s3);border:1px solid var(--bd);border-radius:6px;padding:4px 8px;font-size:10px;color:var(--dim);font-family:var(--mono)}
.file-chip .rm{cursor:pointer;color:var(--rd);margin-left:3px}
@media(max-width:768px){.sidebar{display:none}.wcards{grid-template-columns:repeat(2,1fr)}}
/* LONG STREAM + GROS TEXTE */
#chatArea{max-height:calc(100vh - 200px);overflow-y:auto;scroll-behavior:smooth}
#chatArea .msg-content{max-height:none !important;overflow:visible !important;white-space:pre-wrap;word-break:break-word;font-size:13px;line-height:1.6}
#chatArea .msg-content pre{max-height:600px;overflow:auto;background:var(--s2,#1a1a1f);padding:12px;border-radius:8px;font-size:12px}
#chatArea .msg-content code{font-family:'JetBrains Mono',monospace;font-size:12px}
.msg.assistant{animation:fadeIn .3s ease}
@keyframes fadeIn{from{opacity:0;transform:translateY(4px)}to{opacity:1}}
/* ═══ V162 Thinking Panel UX ═══ */
.thinking-panel-v162{margin:8px 0 12px;padding:10px 14px;background:linear-gradient(135deg,rgba(0,229,160,0.04),rgba(125,82,255,0.04));border:1px solid rgba(0,229,160,0.18);border-radius:10px;font-size:12px;font-family:'JetBrains Mono','SF Mono',monospace;color:#b8c5d0;max-width:920px;display:none;animation:fadeIn .3s}
.thinking-panel-v162.show{display:block}
.thinking-panel-v162 .thp-hdr{display:flex;align-items:center;gap:8px;padding-bottom:6px;border-bottom:1px dashed rgba(0,229,160,0.2);margin-bottom:8px}
.thinking-panel-v162 .thp-ico{width:16px;height:16px;border-radius:50%;background:radial-gradient(circle,#00e5a0 30%,transparent 70%);animation:pulse 1.5s infinite}
.thinking-panel-v162 .thp-title{color:#00e5a0;font-weight:600;font-size:11px;letter-spacing:0.5px;text-transform:uppercase;flex:1}
.thinking-panel-v162 .thp-toggle{background:transparent;border:1px solid rgba(0,229,160,0.3);color:#00e5a0;cursor:pointer;font-size:10px;padding:2px 8px;border-radius:4px;font-family:inherit}
.thinking-panel-v162 .thp-stages{display:flex;gap:4px;margin-bottom:8px;flex-wrap:wrap}
.thinking-panel-v162 .thp-stage{padding:3px 8px;border-radius:12px;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);font-size:10px;color:#7a8899;display:flex;align-items:center;gap:4px;transition:all .2s}
.thinking-panel-v162 .thp-stage.active{background:rgba(0,229,160,0.15);border-color:#00e5a0;color:#00e5a0}
.thinking-panel-v162 .thp-stage.done{background:rgba(125,82,255,0.12);border-color:rgba(125,82,255,0.4);color:#a28fff}
.thinking-panel-v162 .thp-body{max-height:200px;overflow-y:auto;padding:4px 0;font-style:italic;opacity:.85;line-height:1.55}
.thinking-panel-v162 .thp-line{padding:2px 0;color:#b8c5d0;font-style:normal}
.thinking-panel-v162 .thp-line .lbl{color:#00e5a0;font-weight:600;margin-right:6px}
@keyframes fadeIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}
/* ═══ V163 Split Layout 50/50 Chat | Context Panel ═══ */
.split-layout-v163{flex:1;display:flex;flex-direction:row;min-width:0;min-height:0;overflow:hidden;position:relative}
.chat-col-v163{flex:1;display:flex;flex-direction:column;min-width:0;transition:margin-right .35s cubic-bezier(.4,1.4,.5,1)}
.context-col-v163{width:0;min-width:0;max-width:0;display:flex;flex-direction:column;background:linear-gradient(180deg,rgba(15,18,28,0.55),rgba(10,12,18,0.75));border-left:1px solid rgba(0,229,160,0.08);overflow:hidden;transition:width .35s cubic-bezier(.4,1.4,.5,1),min-width .35s,max-width .35s;position:relative}
.split-layout-v163.ctx-open .context-col-v163{width:38%;min-width:380px;max-width:560px}
.split-layout-v163.ctx-wide .context-col-v163{width:50%;min-width:480px;max-width:760px}
.context-col-v163 .ctx-collapse-handle{position:absolute;left:0;top:50%;transform:translate(-50%,-50%);width:18px;height:42px;background:linear-gradient(135deg,#00e5a0,#7d52ff);border-radius:4px;cursor:ew-resize;display:flex;align-items:center;justify-content:center;z-index:10;box-shadow:0 2px 8px rgba(0,229,160,0.25);opacity:.7;transition:opacity .2s}
.context-col-v163 .ctx-collapse-handle:hover{opacity:1;width:22px}
.context-col-v163 .ctx-collapse-handle::before{content:'';width:2px;height:18px;background:white;border-radius:1px;box-shadow:5px 0 white,-5px 0 white}
.ctx-toggle-btn{display:inline-flex;align-items:center;gap:6px;padding:5px 11px;background:rgba(0,229,160,0.08);border:1px solid rgba(0,229,160,0.25);color:#00e5a0;font-size:10px;font-family:'JetBrains Mono',monospace;border-radius:5px;cursor:pointer;transition:.15s;letter-spacing:.5px;text-transform:uppercase;font-weight:600;margin-left:8px}
.ctx-toggle-btn:hover{background:rgba(0,229,160,0.18);border-color:#00e5a0}
.ctx-toggle-btn.active{background:rgba(0,229,160,0.25);color:#0a0c12;background:#00e5a0}
.ctx-toggle-btn .ic{width:12px;height:12px;display:inline-block}
.context-col-v163 .ctx-head{padding:14px 18px;border-bottom:1px solid rgba(255,255,255,0.05);display:flex;align-items:center;gap:10px;background:rgba(0,0,0,0.2)}
.context-col-v163 .ctx-head h4{color:#00e5a0;font-size:13px;font-weight:600;letter-spacing:0.5px;text-transform:uppercase;flex:1;margin:0}
.context-col-v163 .ctx-tabs{display:flex;gap:2px;padding:8px 14px 0;border-bottom:1px solid rgba(255,255,255,0.04)}
.context-col-v163 .ctx-tab{padding:6px 12px;font-size:11px;color:#7a8899;background:transparent;border:none;cursor:pointer;border-bottom:2px solid transparent;transition:all .15s;font-family:inherit}
.context-col-v163 .ctx-tab.active{color:#00e5a0;border-bottom-color:#00e5a0}
.context-col-v163 .ctx-body{flex:1;overflow-y:auto;padding:14px 18px}
.context-col-v163 .ctx-panel{display:none}
.context-col-v163 .ctx-panel.active{display:block;animation:fadeIn .25s}
.ctx-kpi-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-bottom:14px}
.ctx-kpi{background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);border-radius:8px;padding:10px 12px}
.ctx-kpi .lbl{font-size:10px;color:#7a8899;text-transform:uppercase;letter-spacing:0.5px}
.ctx-kpi .val{font-size:20px;color:#00e5a0;font-weight:700;font-variant-numeric:tabular-nums;margin-top:2px}
.ctx-kpi .sub{font-size:10px;color:#a28fff;margin-top:2px}
.ctx-log{font-family:'JetBrains Mono','SF Mono',monospace;font-size:11px;line-height:1.55;color:#b8c5d0}
.ctx-log .ev{padding:4px 8px;margin:2px 0;border-left:2px solid rgba(0,229,160,0.3);border-radius:0 4px 4px 0;background:rgba(0,229,160,0.03)}
.ctx-log .ev.agent{border-left-color:#a28fff;background:rgba(125,82,255,0.04)}
.ctx-log .ev .ts{color:#7a8899;font-size:10px;margin-right:6px}
.ctx-cascade{display:flex;flex-direction:column;gap:6px}
.ctx-cascade .casc{padding:8px 12px;background:rgba(255,255,255,0.03);border-radius:8px;border-left:3px solid rgba(255,255,255,0.1);font-size:11px;display:flex;justify-content:space-between;align-items:center}
.ctx-cascade .casc.hit{border-left-color:#00e5a0;background:rgba(0,229,160,0.06)}
.ctx-cascade .casc .name{color:#e2e8f0;font-weight:600}
.ctx-cascade .casc .lat{color:#7a8899;font-variant-numeric:tabular-nums}
@media(max-width:1280px){.context-col-v163{width:38%;min-width:300px}}
@media(max-width:968px){.split-layout-v163{flex-direction:column}.context-col-v163{width:100%;max-width:100%;border-left:none;border-top:1px solid rgba(0,229,160,0.08);max-height:40vh}.chat-col-v163{border-right:none}}
</style>
<!-- V109 Plausible Analytics -->
<script defer data-domain="weval-consulting.com" src="https://analytics.weval-consulting.com/js/script.js"></script>
<link rel="stylesheet" href="/css/wevia-portal-consistency.css">
<!-- DOCTRINE-60-UX-ENRICH cerebras-qwen235b 20260424-025538 -->
<style id="doctrine60-ux-wevia-master">
body::before { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; background: radial-gradient(circle at center, rgba(80, 120, 200, 0.15), rgba(10, 20, 40, 0.8)); }
body, .card, .panel, .btn, .kpi { margin: 0; padding: 0; box-sizing: border-box; }
.card, .panel, .btn, .kpi { opacity: 0; transform: translateY(20px); transition: opacity 0.6s ease, transform 0.6s ease, box-shadow 0.4s ease, border 0.4s ease; }
.card.enter-stagger, .panel.enter-stagger, .btn.enter-stagger, .kpi.enter-stagger { opacity: 1; transform: translateY(0); }
.btn:hover, .card:hover, .panel:hover { box-shadow: 0 8px 24px rgba(66, 153, 225, 0.35); border-color: #4299e1; }
.btn, .card, .panel { border: 1px solid rgba(100, 100, 100, 0.2); }
@keyframes pulse-anim { 0%, 100% { opacity: 0.6; transform: scale(1); } 50% { opacity: 1; transform: scale(1.05); } }
.pulse, .live-indicator, .active { animation: pulse-anim 3s ease-in-out infinite; }
.chat, .speech, .modal { backdrop-filter: blur(12px); background: rgba(20, 25, 40, 0.8); }
</style>
</head>
<body>
<div class="wevia-portal-banner">
<span class="wevia-portal-banner-label">🌐 WEVIA ECOSYSTEM</span>
<a href="/all-ia-hub.html" data-portal="hub" class="wevia-portal-banner-link">🧠 All-IA Hub</a>
<a href="/wevia-master.html" data-portal="master" class="wevia-portal-banner-link wevia-current">🤖 WEVIA Master</a>
<a href="/wevia-orchestrator.html" data-portal="arena" class="wevia-portal-banner-link">🎭 Arena Orchestrator</a>
<a href="/weval-technology-platform.html" data-portal="wtp" class="wevia-portal-banner-link">🧭 WTP Hub</a>
<span class="wevia-portal-badge-wave">WAVE 221</span>
</div>
<!-- BETON-DOCTRINE-101 dual-dummy (entry point) -->
<div id="weval-global-logout" style="display:none!important;visibility:hidden!important" aria-hidden="true" data-beton-101="dummy-to-block-auto-injection"></div>
<a id="weval-gl" href="#" style="display:none!important;visibility:hidden!important" aria-hidden="true" data-beton-101="dummy-to-block-auto-injection" tabindex="-1"></a>
<div class="sidebar" id="sidebar">
<div class="sb-head"><h2>WEVIA</h2><small>Master AI v4</small></div>
<div class="sb-nav">
<div class="sb-label">IA Agents</div>
<button type="button" aria-label="💊Ethica HCP" class="sb-item" onclick="q('ethica combien de HCP par pays')"><span class="ic">💊</span>Ethica HCP</button>
<button type="button" aria-label="🦌DeerFlow" class="sb-item" onclick="q('deerflow recherche tendances')"><span class="ic">🦌</span>DeerFlow</button>
<button type="button" aria-label="📎Paperclip" class="sb-item" onclick="q('paperclip status goals')"><span class="ic">📎</span>Paperclip</button>
<button type="button" aria-label="⚖Consensus" class="sb-item" onclick="q('consensus stratégie')"><span class="ic">⚖️</span>Consensus</button>
<button type="button" aria-label="⚡Blade IA" class="sb-item" onclick="q('blade desktop status')"><span class="ic"></span>Blade IA</button>
<button type="button" aria-label="👁Director" class="sb-item" onclick="q('director supervision')"><span class="ic">👁️</span>Director</button>
<button type="button" aria-label="🔧WEDROID" class="sb-item" onclick="q('wedroid backend diagnostic')"><span class="ic">🔧</span>WEDROID</button>
<button type="button" aria-label="🐙OpenClaw" class="sb-item" onclick="q('openclaw ollama models')"><span class="ic">🐙</span>OpenClaw</button>
<button type="button" aria-label="⚙WEVCODE" class="sb-item" onclick="q('wevcode assistant code')"><span class="ic">⚙️</span>WEVCODE</button>
<button type="button" aria-label="🔬Nuclei" class="sb-item" onclick="q('nuclei scan sécurité')"><span class="ic">🔬</span>Nuclei</button>
<div class="sb-label">Actions</div>
<button type="button" aria-label="🔍Audit Complet" class="sb-item" onclick="q('audit complet RAM disk Docker')"><span class="ic">🔍</span>Audit Complet</button>
<button type="button" aria-label="🔧Auto-Fix" class="sb-item" onclick="q('auto-fix repare tout')"><span class="ic">🔧</span>Auto-Fix</button>
<button type="button" aria-label="🧪NonReg" class="sb-item" onclick="q('lance nonreg')"><span class="ic">🧪</span>NonReg</button>
<button type="button" aria-label="📊Benchmark" class="sb-item" onclick="q('benchmark classement')"><span class="ic">📊</span>Benchmark</button>
<button type="button" aria-label="🛡Security" class="sb-item" onclick="q('sécurisé firewall')"><span class="ic">🛡️</span>Security</button>
<button type="button" aria-label="🧹Disk Clean" class="sb-item" onclick="q('nettoie le disque')"><span class="ic">🧹</span>Disk Clean</button>
<button type="button" aria-label="🔒Guardian" class="sb-item" onclick="q('lance guardian')"><span class="ic">🔒</span>Guardian</button>
<button type="button" aria-label="📂Git Push" class="sb-item" onclick="q('git push status')"><span class="ic">📂</span>Git Push</button>
<button type="button" aria-label="⏰Crons" class="sb-item" onclick="q('consolide les crons')"><span class="ic"></span>Crons</button>
<button type="button" aria-label="✅Func Test" class="sb-item" onclick="q('test fonctionnel')"><span class="ic"></span>Func Test</button>
<button type="button" aria-label="💊Vacuum DB" class="sb-item" onclick="q('vacuum ethica')"><span class="ic">💊</span>Vacuum DB</button>
<div class="sb-label">Outils</div>
<button type="button" aria-label="🔌Wiring Map" class="sb-item" onclick="q('wiring connexion agents')"><span class="ic">🔌</span>Wiring Map</button>
<button type="button" aria-label="🧠RAG Status" class="sb-item" onclick="q('rag status qdrant')"><span class="ic">🧠</span>RAG Status</button>
<button type="button" aria-label="🔎Recherche Web" class="sb-item" onclick="q('cherche weval consulting')"><span class="ic">🔎</span>Recherche Web</button>
<button type="button" aria-label="🌍Traduction" class="sb-item" onclick="q('traduis en anglais bonjour')"><span class="ic">🌍</span>Traduction</button>
<a href="/ia-cascade-mechanics.html" aria-label="IA Cascade" class="sb-item" style="text-decoration:none;display:flex;align-items:center;gap:8px"><span class="ic"></span>IA Cascade</a>
<a href="/release-train-dashboard.html" aria-label="Release Train" class="sb-item" style="text-decoration:none;display:flex;align-items:center;gap:8px"><span class="ic">🚂</span>Release Train</a>
<a href="/wevia-cockpit.html" aria-label="Cockpit" class="sb-item" style="text-decoration:none;display:flex;align-items:center;gap:8px"><span class="ic">🎛</span>Cockpit</a>
<button type="button" aria-label="📐Diagramme" class="sb-item" onclick="q('diagramme architecture')"><span class="ic">📐</span>Diagramme</button>
<button type="button" aria-label="🕷Scraping" class="sb-item" onclick="q('scraping extraction web')"><span class="ic">🕷️</span>Scraping</button>
<button type="button" aria-label="🔌Port Scan" class="sb-item" onclick="q('port scan ouverts')"><span class="ic">🔌</span>Port Scan</button>
<button type="button" aria-label="📈Value Chain" class="sb-item" onclick="q('value chain processus')"><span class="ic">📈</span>Value Chain</button>
</div>
<div class="sb-foot">
<span class="dot dot-g"></span> <span id="pc">7</span> providers | 0€<br>
<span id="fs">412 tools | 890 agents · 2484 skills · 16K vectors</span>
</div>
</div>
<div class="main">
<div class="top">
<h3><span class="dot dot-g"></span> WEVIA Master AI</h3>
<div class="top-r">
<button class="ctx-toggle-btn" id="ctxToggleBtn" type="button" onclick="toggleContext('open')" title="Toggle context panel"><span class="ic"></span> Context</button>
<button class="ctx-toggle-btn" id="ctxWideBtn" type="button" onclick="toggleContext('wide')" title="Wide context panel"><span class="ic"></span> Wide</button><span id="st">Connecté</span> · <a href="/wevia-master.html">Legacy</a> · <a href="/weval-wiring.html">Wiring</a> · <a href="/ai-benchmark.html">Benchmark</a></div>
</div>
<div class="split-layout-v163">
<div class="chat-col-v163">
<div class="msgs" id="msgs">
<div class="thinking-panel-v162" id="thinkingPanelV162">
<div class="thp-hdr">
<span class="thp-ico"></span>
<span class="thp-title">Thinking — WEVIA Master</span>
<button class="thp-toggle" id="thpToggle" type="button" aria-label="Toggle thinking">Collapse</button>
</div>
<div class="thp-stages">
<span class="thp-stage" data-stage="plan">🧠 Plan</span>
<span class="thp-stage" data-stage="prepare">📝 Prepare</span>
<span class="thp-stage" data-stage="code">💻 Code</span>
<span class="thp-stage" data-stage="test">🧪 Test</span>
<span class="thp-stage" data-stage="commit">✅ Commit</span>
<span class="thp-stage" data-stage="wiki">📚 Wiki</span>
<span class="thp-stage" data-stage="rag">🔗 RAG</span>
</div>
<div class="thp-body" id="thpBody"></div>
</div>
<div class="welcome" id="welcome">
<h1>WEVIA</h1>
<p>IA souveraine · <span id="welc-tools">906</span> agents · <span id="welc-skills">20126</span> skills · <span id="welc-providers">17</span> providers · 0€<br>Tapez une commande ou cliquez un raccourci</p>
<div class="wcards">
<div class="wcard" onclick="q('audit complet RAM disk Docker')"><div class="em">🔍</div><b>Audit Infra</b><small>RAM · Disk · Docker</small></div>
<div class="wcard" onclick="q('ethica combien de HCP')"><div class="em">💊</div><b>Ethica</b><small>141K+ HCPs</small></div>
<div class="wcard" onclick="q('créé une API REST Flask Python avec auth JWT')"><div class="em">⚙️</div><b>Code Gen</b><small>Python · Flask · JWT</small></div>
<div class="wcard" onclick="q('benchmark classement IA')"><div class="em">📊</div><b>Benchmark</b><small>39 AIs ranked</small></div>
<div class="wcard" onclick="q('auto-fix repare tout')"><div class="em">🔧</div><b>Auto-Fix</b><small>Detect + Correct</small></div>
<div class="wcard" onclick="q('deerflow recherche tendances LLM 2026')"><div class="em">🦌</div><b>DeerFlow</b><small>Deep Research</small></div>
<div class="wcard" onclick="q('consensus quelle stratégie IA adopter')"><div class="em">⚖️</div><b>Consensus</b><small>Multi-IA MoA</small></div>
<div class="wcard" onclick="q('sécurisé firewall auth')"><div class="em">🛡️</div><b>Security</b><small>HMAC · CORS · Nuclei</small></div>
</div>
</div>
</div>
<div class="drop-overlay" id="dropZone"><div class="drop-box">📎 Déposez vos fichiers ici<br><small>Images, PDF, code — WEVIA analyse tout</small></div></div>
<div class="input-wrap">
<div class="input-row">
<button type="button" class="attach-btn" onclick="document.getElementById('fileIn').click()" title="Joindre un fichier">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/></svg>
</button>
<input type="file" id="fileIn" style="display:none" multiple>
<textarea id="input" placeholder="Demandez à WEVIA... (images, fichiers, long texte)" autocomplete="off" rows="1" style="resize:none;overflow:hidden" oninput="this.style.height='auto';this.style.height=Math.min(this.scrollHeight,120)+'px'"></textarea>
<button type="button" class="send-btn" id="sendBtn" onclick="send()">
<svg viewBox="0 0 24 24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
</button>
</div>
<div class="file-preview" id="filePrev"></div>
<div class="input-hint">Enter envoyer · Shift+Enter nouvelle ligne · 📎 Fichiers</div>
</div>
</div>
<script>
const $=id=>document.getElementById(id),msgs=$('msgs'),inp=$('input'),stEl=$('st'),welc=$('welcome');
// ═══ V162 Thinking Panel API ═══
const thpPanel=$('thinkingPanelV162'),thpBody=$('thpBody'),thpToggleBtn=$('thpToggle');
const thpStageMap={};
function thpShow(){if(thpPanel)thpPanel.classList.add('show')}
function thpHide(){if(thpPanel)setTimeout(()=>{if(window.v166InProgress){window.v166HideRequested=true;return;}thpPanel.classList.remove('show');thpClear()},30000) /* V174 thpHide extended 1.5s to 30s - give user time to read */}
function thpClear(){if(thpBody)thpBody.innerHTML='';Object.keys(thpStageMap).forEach(k=>delete thpStageMap[k]);document.querySelectorAll('.thp-stage').forEach(s=>s.classList.remove('active','done'))}
function thpAddLine(label,detail,dur){if(!thpBody)return;const d=document.createElement('div');d.className='thp-line';d.innerHTML='<span class="lbl">'+escHtml(label)+'</span>'+escHtml(detail||'')+(dur?'<span class="dur">'+dur+'</span>':'');thpBody.appendChild(d);thpBody.scrollTop=thpBody.scrollHeight;thpShow();if(window.ctxLog)window.ctxLog((label||'Think')+(detail?': '+detail:''))}
function thpSetStage(stage){if(!stage)return;document.querySelectorAll('.thp-stage').forEach(s=>{const st=s.dataset.stage;if(st===stage){s.classList.add('active');s.classList.remove('done')}else if(thpStageMap[st]){s.classList.remove('active');s.classList.add('done')}});thpStageMap[stage]=true}
function escHtml(s){return String(s||'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]))}
if(thpToggleBtn){thpToggleBtn.addEventListener('click',function(){const b=$('thpBody');if(!b)return;b.classList.toggle('collapsed');this.textContent=b.classList.contains('collapsed')?'Expand':'Collapse'})}
let busy=false,files=[],chatHistory=[],sessionId="s-"+Date.now();
inp.addEventListener('keydown',e=>{if(e.key==='Enter'&&!e.shiftKey&&!busy){e.preventDefault();send()}});
// ═══ V166 Claude Pattern API Integration ═══ (parallel to wevia-master-api)
async function v166ClaudePattern(message){
window.v166InProgress=true; window.v166HideRequested=false;
try{
const r = await fetch('/api/claude-pattern-api.php',{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({message:message, chatbot:'wevia-master'})
});
if(!r.ok) return;
const data = await r.json();
if(!data || !data.phases) return;
const P = data.phases;
// Map 7 phases → thp stages (clear first)
thpShow();
if(P['1_thinking']){
thpSetStage('plan');
const t = P['1_thinking'];
thpAddLine('🧠 Thinking', `${t.detected_intent||''} · complexity ${t.complexity||''} · ${t.message_length||0} chars`, `${Math.round(t.duration_ms||0)}ms`);
}
if(P['2_plan']){
thpSetStage('prepare');
const p = P['2_plan'];
thpAddLine('📋 Plan', `${p.steps_count||0} étapes · backend ${(p.backend_selected||'').split('/').pop()}`, `${Math.round(p.duration_ms||0)}ms`);
if(p.steps && p.steps.length){
for(const s of p.steps.slice(0,3)) thpAddLine(' ↳', s, '');
}
}
if(P['3_rag']){
const rag = P['3_rag'];
thpAddLine('🔗 RAG', `Qdrant ${rag.qdrant_queried?'queried':'skipped'} · ${rag.contexts_found||0} contextes trouvés`, `${Math.round(rag.duration_ms||0)}ms`);
}
if(P['4_execute']){
thpSetStage('code');
const e = P['4_execute'];
thpAddLine('⚙ Execute', `backend ${e.backend_ok?'OK':'FAIL'} · ${e.response_size||0} bytes réponse`, `${Math.round(e.duration_ms||0)}ms`);
}
if(P['5_tests']){
thpSetStage('test');
const t = P['5_tests'];
thpAddLine('🧪 Tests', `${t.passed||0}/${t.total||0} passés · ${t.score_pct||0}%`, `${Math.round(t.duration_ms||0)}ms`);
}
if(P['6_response']){
thpSetStage('commit');
const r = P['6_response'];
thpAddLine('💬 Response', `${r.length||0} chars finaux`, `${Math.round(r.duration_ms||0)}ms`);
}
if(P['7_critique']){
thpSetStage('wiki');
const c = P['7_critique'];
thpAddLine('✅ Critique', `quality ${(c.quality_score||0)*100}% · ${(c.notes||[]).join(' · ').substring(0,100)}`, `${Math.round(c.duration_ms||0)}ms`);
}
if(data.summary){
thpSetStage('rag');
thpAddLine('📊 Summary', `${data.summary.phases_executed||0} phases · ${data.summary.tests_score||''} · ${data.summary.quality||''}`, `${Math.round(data.summary.total_duration_ms||0)}ms total`);
}
}catch(e){
// Silent fail - non critical
if(typeof thpAddLine==='function') thpAddLine('⚠ Pattern API', e.message.substring(0,80), '');
} finally { window.v166InProgress=false; if(window.v166HideRequested){setTimeout(()=>{thpPanel&&thpPanel.classList.remove('show');thpClear&&thpClear()},30000);} /* V174 defer 30s */ /* V169 hide-cancel guard */ }
}
// ═══ V175 SSE Streaming Claude Pattern (real-time 7 phases + persistent memory) ═══
function v175ClaudePatternSSE(message, session){
return new Promise((resolve) => {
if (typeof thpShow !== 'function') { resolve(null); return; }
window.v166InProgress = true;
window.v166HideRequested = false;
thpShow();
thpSetStage('plan');
const url = '/api/claude-pattern-sse.php?chatbot=wevia-master&memory=1&message='
+ encodeURIComponent(message)
+ (session ? '&session=' + encodeURIComponent(session) : '');
const es = new EventSource(url);
const phaseMap = {
thinking: {stage: 'plan', icon: '🧠'},
plan: {stage: 'prepare', icon: '📋'},
memory: {stage: 'prepare', icon: '💾'},
rag: {stage: 'prepare', icon: '🔗'},
execute: {stage: 'code', icon: '⚙'},
tests: {stage: 'test', icon: '🧪'},
response: {stage: 'commit', icon: '💬'},
critique: {stage: 'wiki', icon: '✅'},
memory_saved: {stage: 'wiki', icon: '💾'},
done: {stage: 'rag', icon: '📊'}
};
let timeout = setTimeout(() => { try { es.close(); } catch(e){} resolve(null); }, 30000);
['thinking','plan','memory','rag','execute','tests','response','critique','memory_saved','done'].forEach(evt => {
es.addEventListener(evt, (e) => {
try {
const data = JSON.parse(e.data);
const m = phaseMap[evt] || {stage: 'plan', icon: '•'};
thpSetStage(m.stage);
let detail = '';
if (evt === 'thinking') detail = `${data.detected_intent||''} · ${data.complexity||''} · ${data.message_length||0} chars`;
else if (evt === 'plan') detail = `${data.steps_count||0} étapes · backend ${(data.backend_selected||'').split('/').pop()}`;
else if (evt === 'memory') detail = `scope ${data.scope||''} · ${data.contexts_loaded||0} contextes mémoire`;
else if (evt === 'rag') detail = `Qdrant ${data.status||''} · ${data.contexts_found||0} contextes`;
else if (evt === 'execute') detail = `backend ${data.backend_ok ? 'OK' : 'FAIL'} · ${data.response_size||0}B`;
else if (evt === 'tests') detail = `${data.passed||0}/${data.total||0} passés · ${data.score_pct||0}%`;
else if (evt === 'response') detail = `${data.length||0} chars finaux`;
else if (evt === 'critique') detail = `quality ${Math.round((data.quality_score||0)*100)}%`;
else if (evt === 'memory_saved') detail = `saved: ${data.saved ? 'yes' : 'no'}`;
else if (evt === 'done') detail = `${data.phases_executed||0} phases · ${data.total_ms||0}ms total`;
thpAddLine(`${m.icon} ${evt.charAt(0).toUpperCase()+evt.slice(1).replace('_',' ')}`, detail, data.duration_ms ? Math.round(data.duration_ms)+'ms' : '');
} catch(e) {}
});
});
es.addEventListener('error', () => {
clearTimeout(timeout);
try { es.close(); } catch(e){}
window.v166InProgress = false;
resolve(null);
});
// Auto-close after 'done' event
es.addEventListener('done', () => {
clearTimeout(timeout);
setTimeout(() => { try { es.close(); } catch(e){} }, 500);
window.v166InProgress = false;
resolve(true);
});
});
}
// ═══ V175 SSE Pattern streaming — real-time replaces batch v166 ═══
function v175SSEPattern(message){
return new Promise((resolve) => {
try {
window.v166InProgress = true;
window.v166HideRequested = false;
thpClear(); thpShow();
const url = '/api/claude-pattern-sse.php?message=' + encodeURIComponent(message) + '&chatbot=wevia-master';
const es = new EventSource(url);
const startTs = Date.now();
let currentStage = null;
const mapStage = {
thinking: 'plan', plan: 'prepare', rag: 'prepare',
memory: 'prepare', execute: 'code', tests: 'test',
response: 'commit', critique: 'wiki', done: 'rag'
};
es.addEventListener('thinking', e => {
const d = JSON.parse(e.data);
thpSetStage('plan');
if (d.status === 'analyzing') thpAddLine('🧠 Thinking', 'analyzing · ' + (d.message_length||0) + ' chars · backend ' + (d.backend||'').split('/').pop(), '');
else if (d.status === 'complete') thpAddLine(' ↳', 'intent=' + d.intent, Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('plan', e => {
const d = JSON.parse(e.data);
thpSetStage('prepare');
if (d.status === 'building') thpAddLine('📋 Plan', 'building...', '');
else if (d.status === 'complete') {
thpAddLine(' ↳', (d.steps||[]).join(' → ').substring(0,150), Math.round(d.duration_ms||0)+'ms');
}
});
es.addEventListener('rag', e => {
const d = JSON.parse(e.data);
if (d.status === 'searching') thpAddLine('🔗 RAG', 'Qdrant searching...', '');
else thpAddLine(' ↳', d.status, Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('memory', e => {
const d = JSON.parse(e.data);
thpAddLine('💾 Memory', d.scope + ' · ' + (d.loaded||0) + ' loaded', '');
});
es.addEventListener('execute', e => {
const d = JSON.parse(e.data);
thpSetStage('code');
if (d.status === 'calling_backend') thpAddLine('⚙ Execute', 'backend ' + (d.backend||'').split('/').pop(), '');
else if (d.status === 'complete') thpAddLine(' ↳', 'HTTP ' + (d.http_code||'?') + ' · ' + (d.response_size||0) + ' bytes', Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('tests', e => {
const d = JSON.parse(e.data);
thpSetStage('test');
thpAddLine('🧪 Tests', (d.passed||0)+'/'+(d.total||0)+' · ' + (d.score_pct||0) + '%', Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('response', e => {
const d = JSON.parse(e.data);
thpSetStage('commit');
thpAddLine('💬 Response', (d.length||0) + ' chars', Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('critique', e => {
const d = JSON.parse(e.data);
thpSetStage('wiki');
thpAddLine('✅ Critique', 'quality ' + Math.round((d.quality_score||0)*100) + '%', Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('done', e => {
const d = JSON.parse(e.data);
thpSetStage('rag');
thpAddLine('📊 Done', (d.phases_executed||0) + ' phases · ' + (d.quality||''), Math.round(d.total_duration_ms||(Date.now()-startTs))+'ms total');
es.close();
window.v166InProgress = false;
if (window.v166HideRequested) setTimeout(() => { thpPanel&&thpPanel.classList.remove('show'); thpClear&&thpClear(); }, 30000);
resolve();
});
es.addEventListener('error', e => {
es.close();
window.v166InProgress = false;
resolve();
});
es.onerror = function() {
es.close();
window.v166InProgress = false;
resolve();
};
// Safety timeout 30s
setTimeout(() => {
es.close();
window.v166InProgress = false;
resolve();
}, 30000);
} catch(e) {
window.v166InProgress = false;
resolve();
}
});
}
function q(t){inp.value=t;send()}
// Drag & drop
document.addEventListener('dragover',e=>{e.preventDefault();$('dropZone').classList.add('show')});
document.addEventListener('dragleave',e=>{if(!e.relatedTarget)$('dropZone').classList.remove('show')});
document.addEventListener('drop',e=>{e.preventDefault();$('dropZone').classList.remove('show');addFiles(e.dataTransfer.files)});
$('fileIn').addEventListener('change',e=>addFiles(e.target.files));
async function filesToB64(){const r=[];for(const f of files){const b=await new Promise((ok,no)=>{const rd=new FileReader();rd.onload=()=>ok(rd.result.split(',')[1]);rd.onerror=no;rd.readAsDataURL(f)});r.push({name:f.name,type:f.type,size:f.size,data:b})}return r}
function addFiles(fl){for(const f of fl){files.push(f);const d=document.createElement('div');d.className='file-chip';d.innerHTML=`📄 ${f.name} <span class="rm" onclick="this.parentElement.remove()">✕</span>`;$('filePrev').appendChild(d)}}
function addMsg(text,type,meta){
if(welc)welc.style.display='none';
const d=document.createElement('div');d.className='msg msg-'+type;
if(type==='a'){
d.innerHTML=fmt(text);
const cb=document.createElement('button');cb.className='copy-btn';cb.textContent='Copier';
cb.onclick=()=>{navigator.clipboard.writeText(text);cb.textContent='✓';setTimeout(()=>cb.textContent='Copier',1500)};
d.appendChild(cb);
/* DELETE_BTN_V1 */
const db=document.createElement('button');db.className='copy-btn';db.style.marginLeft='6px';db.style.background='#3a1a1a';db.style.color='#ff6b6b';db.style.borderColor='#5a2a2a';db.textContent='Supprimer';
db.onclick=()=>{d.style.transition='opacity 0.2s';d.style.opacity='0';setTimeout(()=>d.remove(),200)};
d.appendChild(db);
if(meta){const m=document.createElement('div');m.className='msg-meta';m.innerHTML=`<span class="engine">${meta.engine||''}</span><span>${meta.time||''}</span>`;d.appendChild(m)}
}else d.textContent=text;
msgs.appendChild(d);msgs.scrollTop=msgs.scrollHeight;return d
}
function fmt(t){
t=t.replace(/```(\w*)\n?([\s\S]*?)```/g,'<pre><code>$2</code></pre>');
t=t.replace(/`([^`]+)`/g,'<code>$1</code>');
t=t.replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>');
t=t.replace(/\n/g,'<br>');return t
}
function showTyping(){const d=document.createElement('div');d.className='typing';d.id='typ';d.innerHTML='<span></span><span></span><span></span>';msgs.appendChild(d);msgs.scrollTop=msgs.scrollHeight}
function hideTyping(){const t=$('typ');if(t)t.remove()}
// Progress bar
function showProgress(status, pct){
let pw=document.getElementById('pw');
if(!pw){
const d=document.createElement('div');d.id='pw';d.className='progress-wrap';
d.innerHTML='<div class="progress-bar"><div class="progress-fill" id="pf"></div></div><div class="progress-status"><span id="ps"></span><span id="pt"></span></div>';
const chat=document.getElementById('msgs');
chat.appendChild(d);chat.scrollTop=chat.scrollHeight;
pw=d;
}
pw.style.display='block';
document.getElementById('pf').style.width=pct+'%';
document.getElementById('ps').textContent=status;
const eta=pct<100?Math.max(1,Math.round((100-pct)/10))+'s':'';
document.getElementById('pt').textContent=eta?'~'+eta:'';
}
function hideProgress(){const pw=document.getElementById('pw');if(pw)pw.remove();}
async function send(){
const text=inp.value.trim();if(!text||busy)return;
busy=true;$('sendBtn').disabled=true;inp.value='';stEl.textContent='Réflexion...';thpClear();thpShow();thpSetStage('plan');
// V175: call claude-pattern-sse (real-time streaming) instead of V166 batch
v175SSEPattern(text).catch(()=>{});
showProgress('Routing intent...', 5);
addMsg(text,'u');showTyping();
const t0=Date.now();
try{
// Try autonomous.php (SSE)
showProgress('Querying sovereign cascade...', 25);
// MULTIAGENT SSE ROUTING
if(text.match(/multiagent|tout finir|full scan|orchestr/i)){
try{
const sse=await fetch("/api/wevia-sse-orchestrator.php?msg="+encodeURIComponent(text),{signal:AbortSignal.timeout(3600000)});
const reader=sse.body.getReader();const dec=new TextDecoder();let buf="",parts=[];
while(true){const{done,value}=await reader.read();if(done)break;buf+=dec.decode(value,{stream:true});
const lines=buf.split("\n");buf=lines.pop();
for(const l of lines){if(!l.startsWith("data: "))continue;try{const d=JSON.parse(l.slice(6));
if(d.type==="agent"){parts.push("["+(d.id||d.name||"agent")+"] "+(d.result||d.text||d.output||""));hideTyping();addMsg(parts.join("\n"),"a",{engine:"SSE",time:(d.progress||0)+"%"});}
if(d.type==="done"){hideTyping();addMsg("ORCHESTRATOR: "+(d.agents||parts.length)+" agents\n"+parts.join("\n"),"a",{engine:"SSE-Orch",time:((Date.now()-t0)/1000).toFixed(1)+"s"});}
if(d.type==="phase2_priority"&&d.ux_guide){hideTyping();const g=d.ux_guide;let txt="**PHASE 2 CF-BYPASS — "+(d.intent||"?").toUpperCase()+"**\n\n";if(g.phase_2_status){txt+="**Etat actuel**\n";for(const[k,v]of Object.entries(g.phase_2_status))txt+="- "+k+": "+v+"\n";}if(g.preflight){txt+="\n**Pre-flight**\n";for(const[k,v]of Object.entries(g.preflight))txt+="- "+k+": "+v+"\n";}if(g.blockers&&g.blockers.length){txt+="\n**Blockers**: "+g.blockers.join(", ")+"\n";}else if(g.blockers){txt+="\n**Blockers**: aucun\n";}if(g.magic_word){txt+="\n**Mot magique a taper**: `"+g.magic_word+"`\n";}if(g.message){txt+="\n"+g.message+"\n";}if(g.next_steps&&g.next_steps.length){txt+="\n**Prochaines etapes**\n"+g.next_steps.map(s=>"- "+s).join("\n");}addMsg(txt,"a",{engine:"WEVIA-Phase2",time:((Date.now()-t0)/1000).toFixed(1)+"s"});}
if(d.type==="llm_synthesis"&&d.text){hideTyping();addMsg(d.text,"a",{engine:"WEVIA-Synth",time:((Date.now()-t0)/1000).toFixed(1)+"s"});}
}catch(e){}}
}busy=false;$("sendBtn").disabled=false;stEl.textContent="";return;
}catch(e){}
}
const res=await fetch('/api/wevia-master-api.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:text,session:sessionId,history:chatHistory.slice(-10),attachments:await filesToB64()}),signal:AbortSignal.timeout(300000)});
hideTyping();
showProgress('Processing response...', 70);
const elapsed=((Date.now()-t0)/1000).toFixed(1)+'s';
let fullText='',engine='',intent='';
// Try JSON first (wevia-master-api returns direct JSON)
let raw='';
raw=await res.text();
for(const line of raw.split('\n')){
if(!line.startsWith('data: '))continue;
try{
const d=JSON.parse(line.slice(6));
if(d.type==='answer'){fullText=d.text||'';engine=d.engine||'';intent=d.intent||''}
else if(d.type==='chunk'||d.type==='llm_chunk'){fullText+=d.text||'';engine=d.engine||d.provider||engine}
else if(d.type==='thinking'){stEl.textContent=d.step||'Analyse...';thpAddLine(d.step||'Think',d.detail||'',d.dur||'');if(d.stage)thpSetStage(d.stage);if(d.tier&&window.ctxCascadeHit)window.ctxCascadeHit(d.tier,d.lat);}
else if(d.type==='exec_result'){fullText+=(d.desc||'')+': '+(d.output||'')+'\n';engine='Exec'}
else if(d.type==='exec'){engine=d.engine||'Resolver'}
else if(d.type==='token'){fullText+=d.content||'';engine=d.provider||engine}
else if(d.type==='start'){engine=d.provider||engine}
else if(d.type==='done')engine=d.provider||engine
}catch(e){}
}
if(!fullText){
// Fallback: try exec endpoint (JSON)
showProgress('Fallback exec...', 50);
const r2=await fetch('/api/wevia-full-exec.php?m='+encodeURIComponent(text),{signal:AbortSignal.timeout(120000)});
/* HTML_GUARD_V2_BATCH */ const _t_d2=await r2.text(); let d2=null; {var _q=(_t_d2||"").trim();if(_q.startsWith("<!DOCTYPE")||_q.startsWith("<html")){d2={error:"[HTTP "+(r2.status||"?")+"] Backend indisponible",isHtmlError:true};}else{try{d2=JSON.parse(_q)}catch(e){d2={error:"[JSON] "+e.message}}}}fullText=d2.response||'Pas de réponse';engine=d2.provider||'Exec'
}
addMsg(fullText,'a',{engine,time:elapsed});
chatHistory.push({role:"user",content:text},{role:"assistant",content:fullText});
}catch(err){
hideTyping();
try{showProgress('Fallback exec...', 50);
const r2=await fetch('/api/wevia-full-exec.php?m='+encodeURIComponent(text));/* HTML_GUARD_V2_BATCH */ const _t_d2=await r2.text(); let d2=null; {var _q=(_t_d2||"").trim();if(_q.startsWith("<!DOCTYPE")||_q.startsWith("<html")){d2={error:"[HTTP "+(r2.status||"?")+"] Backend indisponible",isHtmlError:true};}else{try{d2=JSON.parse(_q)}catch(e){d2={error:"[JSON] "+e.message}}}}addMsg(d2.response||err.message,'a',{engine:'Fallback',time:((Date.now()-t0)/1000).toFixed(1)+'s'})}
catch(e2){addMsg('Erreur: '+err.message,'a',{engine:'Error'})}
}
stEl.textContent='Connecté';thpHide();hideProgress();busy=false;$('sendBtn').disabled=false;inp.focus();files=[];$('filePrev').innerHTML=''
}
function scrollToBottom(){const ca=document.getElementById('chatArea');if(ca)ca.scrollTop=ca.scrollHeight;}
setInterval(()=>{if(busy)scrollToBottom()},500);
// Live stats
fetch('/api/source-of-truth.json?t='+Date.now()).then(r=>r.text().then(t=>{/* HTML_GUARD_V2_BATCH */var q=(t||"").trim();if(q.startsWith("<!DOCTYPE")||q.startsWith("<html")){return{error:"[HTTP "+r.status+"]",isHtmlError:true}}try{return JSON.parse(q)}catch(e){return{error:"JSON "+e.message}}})).then(d=>{
$('pc').textContent=d.providers_count||(d.counts&&d.counts.providers)||Object.keys(d.providers||{}).length||0;
$('fs').textContent=(d.tools_count||360)+' tools | '+(d.agents_count||870)+' agents · '+(d.cascade_count||12)+' cascade';
// V115.1 live welcome stats
var wt=document.getElementById('welc-tools'); if(wt) wt.textContent=d.agents_count||d.agents_total||906;
var ws=document.getElementById('welc-skills'); if(ws) ws.textContent=d.skills_count||d.skills_total||20126;
var wp=document.getElementById('welc-providers'); if(wp) wp.textContent=d.providers_count||(d.counts&&d.counts.providers)||17;
}).catch(()=>{});
// === VOICE INPUT ===
let isRec=false, recog=null;
function startVoice(){
const btn=document.getElementById('voiceBtn');
if(isRec&&recog){recog.stop();isRec=false;btn.textContent='🎙';return}
const SR=window.SpeechRecognition||window.webkitSpeechRecognition;
if(!SR){btn.textContent='❌';setTimeout(()=>btn.textContent='🎙',1500);return}
recog=new SR();recog.lang='fr-FR';recog.continuous=false;recog.interimResults=true;
recog.onstart=()=>{isRec=true;btn.textContent='🔴';btn.style.animation='pulse 1s infinite'};
recog.onresult=e=>{let f='',t='';for(let i=0;i<e.results.length;i++){if(e.results[i].isFinal)f+=e.results[i][0].transcript;else t+=e.results[i][0].transcript}document.getElementById('input').value=f||t};
recog.onend=()=>{isRec=false;btn.textContent='🎙';btn.style.animation='';if(document.getElementById('input').value.trim())send()};
recog.onerror=()=>{isRec=false;btn.textContent='🎙';btn.style.animation=''};
recog.start();
}
// === TTS ===
let ttsOn=true;
function toggleTTS(){
ttsOn=!ttsOn;
document.getElementById('ttsBtn').style.opacity=ttsOn?1:0.4;
}
function speakResponse(text){
if(!ttsOn||!window.speechSynthesis)return;
try{const u=new SpeechSynthesisUtterance(text.replace(/[#*`]/g,'').substring(0,500));u.lang='fr-FR';u.rate=1.1;speechSynthesis.speak(u)}catch(e){}
}
// === DRAG & DROP ===
const chatArea=document.getElementById('msgs');
if(chatArea){
chatArea.addEventListener('dragover',e=>{e.preventDefault();chatArea.style.outline='2px dashed var(--ac)'});
chatArea.addEventListener('dragleave',()=>{chatArea.style.outline='none'});
chatArea.addEventListener('drop',e=>{e.preventDefault();chatArea.style.outline='none';if(e.dataTransfer.files.length){pendingFiles=[...e.dataTransfer.files];document.getElementById('input').value='Analyse ces fichiers';send()}});
}
// Patch addMsg to auto-TTS
const _origAddA = typeof addMsg === 'function' ? addMsg : null;
</script>
<script src="/js/wevia-artifact-renderer.js"></script>
<!-- CARTO_REMOVED -->
<!-- === OPUS UNIVERSAL DRILL-DOWN v1 19avr — append-only, doctrine #14 === -->
<script>
(function(){
if (window.__opusUniversalDrill) return; window.__opusUniversalDrill = true;
var d = document;
var m = d.createElement('div');
m.id = 'opus-udrill';
m.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.82);backdrop-filter:blur(6px);display:none;align-items:center;justify-content:center;z-index:99995;padding:20px;cursor:pointer';
var inner = d.createElement('div');
inner.id = 'opus-udrill-in';
inner.style.cssText = 'max-width:900px;width:100%;max-height:90vh;overflow:auto;background:#0b0d15;border:1px solid rgba(99,102,241,0.35);border-radius:14px;padding:28px;cursor:default;box-shadow:0 20px 60px rgba(0,0,0,0.6);color:#e2e8f0;font:14px/1.55 Inter,system-ui,sans-serif';
inner.addEventListener('click', function(e){ e.stopPropagation(); });
m.appendChild(inner);
m.addEventListener('click', function(){ m.style.display='none'; });
d.addEventListener('keydown', function(e){ if(e.key==='Escape') m.style.display='none'; });
(d.body || d.documentElement).appendChild(m);
function openCard(card) {
// Clone card content + show close btn + increase font-size
var html = '<div style="display:flex;justify-content:flex-end;margin-bottom:14px"><button type="button" aria-label="✕ Fermer (Esc)" id="opus-udrill-close" style="padding:6px 14px;background:#171b2a;border:1px solid rgba(99,102,241,0.25);color:#e2e8f0;border-radius:8px;cursor:pointer;font-size:12px">✕ Fermer (Esc)</button></div>';
html += '<div style="transform-origin:top left;font-size:1.05em">' + card.outerHTML + '</div>';
inner.innerHTML = html;
d.getElementById('opus-udrill-close').onclick = function(){ m.style.display='none'; };
m.style.display = 'flex';
}
function wire(root) {
var sels = '.card,[class*="card"],.kpi,[class*="kpi"],.stat,[class*="stat"],.tile,[class*="tile"],.metric,[class*="metric"],.widget,[class*="widget"]';
var cards = root.querySelectorAll(sels);
for (var i = 0; i < cards.length; i++) {
var c = cards[i];
if (c.__opusWired) continue;
if (c.closest('button, a, input, select, textarea, #opus-udrill')) continue;
var r = c.getBoundingClientRect();
if (r.width < 60 || r.height < 40) continue;
c.__opusWired = true;
c.style.cursor = 'pointer';
c.setAttribute('role','button');
c.setAttribute('tabindex','0');
c.addEventListener('click', function(ev){
// If a more-specific drill is already active (e.g. pp-card custom), let it handle
if (ev.target.closest('[data-pp-id]') && window.__opusDrillInit) return;
if (ev.target.closest('a,button,input,select')) return;
ev.preventDefault(); ev.stopPropagation();
openCard(this);
});
c.addEventListener('keydown', function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();openCard(this);} });
}
}
// Initial + mutation observer
var initRun = function(){ wire(d.body || d.documentElement); };
if (d.readyState === 'loading') d.addEventListener('DOMContentLoaded', initRun);
else initRun();
var mo = new MutationObserver(function(muts){
var newCard = false;
for (var i=0;i<muts.length;i++) if (muts[i].addedNodes.length) { newCard = true; break; }
if (newCard) initRun();
});
mo.observe(d.body || d.documentElement, {childList:true, subtree:true});
})();
</script>
<!-- === OPUS UNIVERSAL DRILL-DOWN END === -->
<script src="/api/archi-meta-badge.js" defer></script>
<!-- OPUS_v932e_5HUBS -->
<div id="opus-xlinks" style="position:fixed;top:12px;right:12px;display:flex;gap:6px;z-index:9998;flex-wrap:wrap;max-width:380px">
<a href="/weval-technology-platform.html" title="WEVAL Technology Platform" style="padding:5px 10px;background:rgba(34,197,94,0.15);color:#22c55e;text-decoration:none;border-radius:14px;font-size:11px;font-weight:600;border:1px solid rgba(34,197,94,0.3);backdrop-filter:blur(8px)">WTP</a>
<a href="/all-ia-hub.html" title="All IA Hub - 1000+ agents" style="padding:5px 10px;background:rgba(6,182,212,0.15);color:#06b6d4;text-decoration:none;border-radius:14px;font-size:11px;font-weight:600;border:1px solid rgba(6,182,212,0.3);backdrop-filter:blur(8px)">IA Hub</a>
<a href="/wevia-orchestrator.html" title="WEVIA Orchestrator - Multi-agent" style="padding:5px 10px;background:rgba(139,92,246,0.15);color:#8b5cf6;text-decoration:none;border-radius:14px;font-size:11px;font-weight:600;border:1px solid rgba(139,92,246,0.3);backdrop-filter:blur(8px)">Orch</a>
<a href="/wevcode.html" title="WEVCODE - Sovereign Code Assistant" style="padding:5px 10px;background:rgba(236,72,153,0.15);color:#ec4899;text-decoration:none;border-radius:14px;font-size:11px;font-weight:600;border:1px solid rgba(236,72,153,0.3);backdrop-filter:blur(8px)">WevCode</a>
<a href="/weval-arena.html" title="WEVAL Arena - Command Center" style="padding:5px 10px;background:rgba(245,158,11,0.15);color:#f59e0b;text-decoration:none;border-radius:14px;font-size:11px;font-weight:600;border:1px solid rgba(245,158,11,0.3);backdrop-filter:blur(8px)">Arena</a>
<a href="/wevia-ia/droid.html" title="WEDROID v3.2 - Backend droid 19 providers" style="padding:5px 10px;background:rgba(16,185,129,0.15);color:#10b981;text-decoration:none;border-radius:14px;font-size:11px;font-weight:600;border:1px solid rgba(16,185,129,0.3);backdrop-filter:blur(8px)">Droid</a>
<a href="/playwright-v132-portfolio.html" title="V132 Playwright portfolio · 12 intents · 100% routing" style="padding:5px 10px;background:rgba(0,200,150,0.18);color:#34d399;text-decoration:none;border-radius:14px;font-size:11px;font-weight:700;border:1px solid
rgba(0,200,150,0.4);backdrop-filter:blur(8px)">🎯 V132 100%</a>
</div><!-- /chat-col-v163 -->
<div class="context-col-v163">
<div class="ctx-head">
<span style="width:8px;height:8px;border-radius:50%;background:#00e5a0;display:inline-block;animation:pulse 1.5s infinite"></span>
<h4>Live Context</h4>
</div>
<div class="ctx-tabs">
<button type="button" class="ctx-tab active" data-tab="thinking">Thinking</button>
<button type="button" class="ctx-tab" data-tab="cascade">Cascade</button>
<button type="button" class="ctx-tab" data-tab="agents">Agents</button>
<button type="button" class="ctx-tab" data-tab="kpi">KPI</button>
</div>
<div class="ctx-body">
<div class="ctx-panel active" id="ctxThinking">
<div id="ctxThinkingLog" class="ctx-log"><div class="ev"><span class="ts">--:--:--</span>En attente d'une requête...</div></div>
</div>
<div class="ctx-panel" id="ctxCascade">
<div class="ctx-cascade">
<div class="casc" data-tier="T0"><span class="name">T0 Resolver</span><span class="lat">--</span></div>
<div class="casc" data-tier="T1a"><span class="name">T1 Cerebras</span><span class="lat">--</span></div>
<div class="casc" data-tier="T1b"><span class="name">T1 Groq</span><span class="lat">--</span></div>
<div class="casc" data-tier="T2"><span class="name">T2 Ollama</span><span class="lat">--</span></div>
</div>
</div>
<div class="ctx-panel" id="ctxAgents">
<div id="ctxAgentsList" class="ctx-log"><div class="ev agent"><span class="ts">--:--:--</span>906 agents disponibles</div></div>
</div>
<div class="ctx-panel" id="ctxKpi">
<div class="ctx-kpi-grid">
<div class="ctx-kpi"><div class="lbl">Providers</div><div class="val" id="kpi-prov">17</div><div class="sub">actifs</div></div>
<div class="ctx-kpi"><div class="lbl">Tools</div><div class="val" id="kpi-tool">626</div><div class="sub">Registry</div></div>
<div class="ctx-kpi"><div class="lbl">Agents</div><div class="val" id="kpi-ag">906</div><div class="sub">orchestrables</div></div>
<div class="ctx-kpi"><div class="lbl">L99</div><div class="val" id="kpi-l99">153/153</div><div class="sub">PASS</div></div>
</div>
</div>
</div>
</div><!-- /context-col-v163 -->
</div><!-- /split-layout-v163 -->
</div>
<script src="/api/a11y-auto-enhancer.js" defer></script>
<script src="/opus-antioverlap-doctrine.js?v=1776776094" defer></script>
<script src="/api/weval-feature-tracker.js" defer></script>
<script>
// ═══ V163 Context Col Tab Switching + Live Telemetry ═══
(function(){
const tabs = document.querySelectorAll('.ctx-tab');
const panels = document.querySelectorAll('.ctx-panel');
tabs.forEach(t => t.addEventListener('click', function(){
tabs.forEach(x => x.classList.remove('active'));
panels.forEach(x => x.classList.remove('active'));
this.classList.add('active');
const id = 'ctx' + this.dataset.tab.charAt(0).toUpperCase() + this.dataset.tab.slice(1);
const target = document.getElementById(id);
if(target) target.classList.add('active');
}));
window.ctxLog = function(msg, kind){
const log = document.getElementById('ctxThinkingLog');
if(!log) return;
const ts = new Date().toTimeString().slice(0,8);
const el = document.createElement('div');
el.className = 'ev' + (kind ? ' ' + kind : '');
el.innerHTML = '<span class="ts">' + ts + '</span>' + String(msg||'').replace(/[<>]/g, c => c==='<'?'&lt;':'&gt;');
log.appendChild(el);
log.scrollTop = log.scrollHeight;
while(log.children.length > 80) log.removeChild(log.firstChild);
};
window.ctxCascadeHit = function(tier, latency){
const el = document.querySelector('.casc[data-tier="' + tier + '"]');
if(!el) return;
el.classList.add('hit');
if(latency !== undefined) el.querySelector('.lat').textContent = latency + 'ms';
setTimeout(() => el.classList.remove('hit'), 3000);
};
window.ctxAgentLog = function(agent, result){
const log = document.getElementById('ctxAgentsList');
if(!log) return;
const ts = new Date().toTimeString().slice(0,8);
const el = document.createElement('div');
el.className = 'ev agent';
el.innerHTML = '<span class="ts">' + ts + '</span><b>' + agent + '</b>: ' + String(result||'').slice(0, 120);
log.appendChild(el);
log.scrollTop = log.scrollHeight;
while(log.children.length > 40) log.removeChild(log.firstChild);
};
})();
</script>
<script src="/api/ambre-universal-chat.js" defer></script>
<!-- WAVE 265 · Factory pill cross-page (injected, position mesurée zéro overlap) -->
<a id="w265-factory-cross" href="/wevia-multiagent-dashboard.html" title="Factory Health Monitor (30 agents)"
style="position:fixed;top:12px;left:12px;padding:6px 12px;border-radius:14px;background:linear-gradient(135deg,rgba(34,211,238,.2),rgba(168,85,247,.15));border:1px solid rgba(34,211,238,.4);color:#67e8f9;font-size:11px;font-weight:700;text-decoration:none;display:inline-flex;align-items:center;gap:6px;z-index:9999;backdrop-filter:blur(10px);box-shadow:0 2px 8px rgba(0,0,0,.4)">
<span>🏭</span>
<span id="w265-factory-txt">Factory: ...</span>
</a>
<script>
/* w265 Factory auto-load */
(function(){
async function refresh(){
try {
const r = await fetch('/api/wevia-v83-business-kpi.php?action=summary', {cache:'no-store'}).then(r=>r.json()).catch(()=>null);
const el = document.getElementById('w265-factory-txt');
if(el && r && r.summary){
const s = r.summary;
const pct = s.data_completeness_pct || 0;
el.textContent = `Factory: ${pct}% (${s.ok || 0}/${s.total_kpis || 0})`;
}
} catch(e){ console.log('[w265] factory check err', e); }
}
refresh();
setInterval(refresh, 60000);
})();
</script>
<!-- /WAVE 265 Factory pill cross-page -->
<!-- DOCTRINE-60-UX-JS -->
<script id="doctrine60-ux-js-wevia-master">
document.addEventListener('DOMContentLoaded', () => {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => {
entry.target.classList.add('enter-stagger');
}, index * 80);
observer.unobserve(entry.target);
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.card, .panel, .btn, .kpi').forEach(el => observer.observe(el));
});
</script>
<script id='ux-w315-toggle'>
(function(){
function toggleContext(mode){
var split=document.querySelector('.split-layout-v163');
if(!split)return;
var btn=document.getElementById('ctxToggleBtn');
var wbtn=document.getElementById('ctxWideBtn');
if(mode==='wide'){
split.classList.toggle('ctx-wide');
split.classList.remove('ctx-open');
btn.classList.remove('active');
wbtn.classList.toggle('active', split.classList.contains('ctx-wide'));
} else {
split.classList.toggle('ctx-open');
split.classList.remove('ctx-wide');
wbtn.classList.remove('active');
btn.classList.toggle('active', split.classList.contains('ctx-open'));
}
var state = split.classList.contains('ctx-wide') ? 'wide' : (split.classList.contains('ctx-open') ? 'open' : 'closed');
try{localStorage.setItem('weviaCtxMode', state);}catch(e){}
}
window.toggleContext = toggleContext;
// Restore preference
document.addEventListener('DOMContentLoaded', function(){
try{
var saved = localStorage.getItem('weviaCtxMode') || 'closed';
if(saved === 'open' || saved === 'wide') toggleContext(saved);
}catch(e){}
// Add resize handle click to collapse
var handle = document.querySelector('.ctx-collapse-handle');
if(handle){
handle.addEventListener('click', function(){toggleContext('open');});
}
});
})();
</script>
</body>
<!-- WEVIA-LIVE-OPS-LINK-WM-v1 -->
<a href="/weval-live-ops.html" style="position:fixed;bottom:16px;right:16px;padding:10px 16px;background:linear-gradient(135deg,#e94560,#c03350);color:#fff;border-radius:8px;font-weight:700;font-size:13px;text-decoration:none;z-index:9999;box-shadow:0 4px 12px rgba(233,69,96,0.4)">Live Ops</a>
<!-- /WEVIA-LIVE-OPS-LINK-WM-v1 -->
</html>