Files
html/wevia-master.html
opus aeab7c054e
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
auto-sync-1155
2026-04-21 11:55:02 +02:00

455 lines
33 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}}
</style>
<!-- V109 Plausible Analytics -->
<script defer data-domain="weval-consulting.com" src="https://analytics.weval-consulting.com/js/script.js"></script>
</head>
<body>
<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>
<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"><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="msgs" id="msgs">
<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');
let busy=false,files=[],chatHistory=[],sessionId="s-"+Date.now();
inp.addEventListener('keydown',e=>{if(e.key==='Enter'&&!e.shiftKey&&!busy){e.preventDefault();send()}});
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...';
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...'
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é';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>
</div>
<script src="/api/a11y-auto-enhancer.js" defer></script>
</body>
</html>