1058 lines
68 KiB
HTML
1058 lines
68 KiB
HTML
<!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); }
|
||
|
||
/* ===== WEVIA-LAYOUT-FIX-24AVR - root cause: body{display:flex} with banner 1st child => column ===== */
|
||
html,body{height:100%;overflow:hidden;margin:0;padding:0}
|
||
body{display:flex !important;flex-direction:column !important}
|
||
.wevia-portal-banner{flex-shrink:0;width:100%}
|
||
/* wrapper appears below banner with remaining height */
|
||
body > .sidebar, body > .main{height:calc(100vh - 44px)}
|
||
body{position:relative}
|
||
/* inner layout: sidebar + main side-by-side via wrapper illusion */
|
||
body::after{content:none}
|
||
.sidebar{position:fixed !important;top:44px !important;left:0 !important;bottom:0 !important;width:230px !important;z-index:50}
|
||
.main{position:fixed !important;top:44px !important;left:230px !important;right:0 !important;bottom:0 !important;width:auto !important;flex:none !important;display:flex;flex-direction:column}
|
||
/* beton-doctrine dummies stay hidden */
|
||
#weval-global-logout,#weval-gl{display:none !important;position:absolute !important;width:0 !important;height:0 !important}
|
||
/* factory pill top-left rejoined */
|
||
#w265-factory-cross{top:10px !important;left:14px !important;right:auto !important}
|
||
/* ensure msgs area scrolls within main */
|
||
.msgs{overflow-y:auto}
|
||
/* ===== END WEVIA-LAYOUT-FIX-24AVR ===== */
|
||
|
||
/* ===== WEVIA-OVERLAP-FIX-24AVR-V2 - doctrine zero chauvauchement ===== */
|
||
/* 1. Banner: ensure horizontal top full width, items don't wrap weirdly */
|
||
.wevia-portal-banner{
|
||
position:fixed !important;top:0 !important;left:0 !important;right:0 !important;
|
||
height:auto !important;min-height:44px !important;max-height:60px !important;
|
||
z-index:10000 !important;padding:8px 16px !important;
|
||
overflow-x:auto !important;overflow-y:hidden !important;
|
||
flex-wrap:nowrap !important;gap:10px !important;
|
||
background:linear-gradient(135deg,rgba(10,12,20,.95),rgba(18,22,40,.92)) !important;
|
||
backdrop-filter:blur(16px) !important;
|
||
border-bottom:1px solid rgba(34,211,238,.2) !important;
|
||
}
|
||
/* 2. Factory pill top-left => INTEGRATED IN BANNER as first item (move by z-index and offset) */
|
||
#w265-factory-cross{
|
||
position:fixed !important;top:8px !important;right:8px !important;left:auto !important;
|
||
z-index:10001 !important;
|
||
padding:4px 10px !important;font-size:10px !important;
|
||
background:linear-gradient(135deg,rgba(16,185,129,.2),rgba(6,182,212,.15)) !important;
|
||
border-radius:10px !important;
|
||
}
|
||
/* 3. opus-xlinks top-right badges => MOVE BELOW banner (top:50px), smaller, RIGHT of page */
|
||
#opus-xlinks{
|
||
/* V3 24avr 17:21 Opus - masqué car doublons avec banner header (WTP/IA Hub/Arena déjà dans le banner top) */
|
||
display:none !important;
|
||
}
|
||
#opus-xlinks a{
|
||
padding:3px 8px !important;font-size:10px !important;
|
||
border-radius:10px !important;
|
||
line-height:1.2 !important;
|
||
}
|
||
/* 4. Live Ops bottom-right => MOVE ABOVE send button (bottom:60px instead of 16px) */
|
||
a[href="/weval-live-ops.html"]{
|
||
bottom:60px !important;right:10px !important;
|
||
padding:6px 12px !important;font-size:11px !important;
|
||
z-index:9997 !important;
|
||
}
|
||
/* 5. Native chat widget bottom-left (speech bubble) => Higher z so visible but doesn't overlap banner */
|
||
.chat-launcher,.chat-bubble,[class*="chat-widget-launcher"]{
|
||
bottom:16px !important;left:16px !important;z-index:9996 !important;
|
||
}
|
||
/* 6. main content starts below banner (44px already set by layout-fix v1, re-affirm) */
|
||
.sidebar{top:44px !important}
|
||
.main{top:44px !important}
|
||
/* 7. Within sidebar, move opus-xlinks wrapping doesn't push elements */
|
||
/* 8. Prevent any button fixed top-right from overlapping banner: force min top:50px */
|
||
body > [style*="top:12px"][style*="right:12px"],
|
||
body > [style*="top: 12px"][style*="right: 12px"]{
|
||
top:50px !important;
|
||
}
|
||
/* 9. Within main chat - ensure chat send button + input area has margin bottom:60px for Live Ops */
|
||
.input-area,.input-row{padding-bottom:4px !important}
|
||
.main .msgs{padding-bottom:70px !important}
|
||
/* ===== END WEVIA-OVERLAP-FIX-24AVR-V2 ===== */
|
||
|
||
</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=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[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==='<'?'<':'>');
|
||
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>
|