Files
wevia-brain/s89-arsenal-screens/weval-mind-dashboard-enhanced.html
2026-04-12 23:01:36 +02:00

308 lines
24 KiB
HTML
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>🧠 Weval Mind 2.0 Enhanced — Arsenal</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{--bg:#060a14;--s:#0c1220;--c:#111827;--cy:#22d3ee;--gn:#10b981;--rd:#ef4444;--or:#f59e0b;--pu:#a78bfa;--pk:#f472b6;--bl:#3b82f6;--mb:#0ea5e9;--mp:#8b5cf6;--tx:#e2e8f0;--t2:#94a3b8;--t3:#64748b}
body{background:var(--bg);color:var(--tx);font-family:'DM Sans',sans-serif;padding:20px}
.hd{font-size:22px;font-weight:700;margin-bottom:20px;display:flex;align-items:center;gap:10px;justify-content:space-between}
.live{display:flex;align-items:center;gap:8px;font-family:'JetBrains Mono',monospace;font-size:13px;color:var(--gn)}.live::before{content:'';width:7px;height:7px;background:var(--gn);border-radius:50%;animation:p 2s infinite}
@keyframes p{0%,100%{opacity:1}50%{opacity:.4}}
@keyframes brainPulse{0%,100%{box-shadow:0 0 20px rgba(139,92,246,.2),0 0 40px rgba(14,165,233,.1)}50%{box-shadow:0 0 40px rgba(139,92,246,.5),0 0 80px rgba(14,165,233,.2)}}
@keyframes nodeGlow{0%,100%{opacity:.6}50%{opacity:1}}
@keyframes flowLine{0%{stroke-dashoffset:20}100%{stroke-dashoffset:0}}
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
@keyframes typing{0%{opacity:.3}50%{opacity:1}100%{opacity:.3}}
.g4{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:20px}
.g3{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-bottom:20px}
.g2{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;margin-bottom:20px}
.cd{background:var(--s);border:1px solid rgba(34,211,238,.08);border-radius:12px;padding:18px}
.cd h3{font-size:10px;text-transform:uppercase;letter-spacing:1.2px;color:var(--t2);margin-bottom:6px}
.sv{font-size:26px;font-weight:700;font-family:'JetBrains Mono',monospace}
.badge{display:inline-block;padding:3px 10px;border-radius:6px;font-size:11px;font-weight:600}
.badge.gn{background:rgba(16,185,129,.15);color:var(--gn)}.badge.rd{background:rgba(239,68,68,.15);color:var(--rd)}.badge.or{background:rgba(245,158,11,.15);color:var(--or)}.badge.cy{background:rgba(34,211,238,.15);color:var(--cy)}.badge.pu{background:rgba(167,139,250,.15);color:var(--pu)}.badge.mb{background:rgba(14,165,233,.15);color:var(--mb)}.badge.mp{background:rgba(139,92,246,.15);color:var(--mp)}
table{width:100%;border-collapse:collapse}th{text-align:left;padding:10px;font-size:10px;text-transform:uppercase;letter-spacing:1px;color:var(--t2);border-bottom:1px solid rgba(30,41,59,.5)}td{padding:8px 10px;border-bottom:1px solid rgba(30,41,59,.3);font-size:12px;font-family:'JetBrains Mono',monospace}tr:hover{background:rgba(34,211,238,.03)}
.btn{padding:8px 16px;border-radius:8px;border:none;cursor:pointer;font-size:12px;font-weight:600;transition:.2s}.btn-cy{background:rgba(34,211,238,.15);color:var(--cy)}.btn-gn{background:rgba(16,185,129,.15);color:var(--gn)}.btn-rd{background:rgba(239,68,68,.15);color:var(--rd)}.btn-pu{background:rgba(167,139,250,.15);color:var(--pu)}.btn-mb{background:rgba(14,165,233,.15);color:var(--mb)}.btn-or{background:rgba(245,158,11,.15);color:var(--or)}
.btn:hover{transform:translateY(-1px);filter:brightness(1.2)}
.act{display:flex;gap:8px;margin-bottom:16px;flex-wrap:wrap;align-items:center}
/* BRAIN NEURAL VIS */
.neural-container{background:var(--s);border:1px solid rgba(139,92,246,.12);border-radius:14px;padding:24px;margin-bottom:20px;position:relative;overflow:hidden}
.neural-container::before{content:'';position:absolute;top:0;left:0;right:0;bottom:0;background:radial-gradient(ellipse at 50% 50%,rgba(139,92,246,.06),transparent 70%);pointer-events:none}
.neural-grid{display:flex;align-items:center;justify-content:center;gap:20px;position:relative;z-index:1}
.brain-core{width:120px;height:120px;border-radius:50%;background:radial-gradient(circle,rgba(139,92,246,.25),rgba(14,165,233,.08));border:2px solid var(--mp);display:flex;flex-direction:column;align-items:center;justify-content:center;animation:brainPulse 3s infinite;flex-shrink:0}
.brain-core .ico{font-size:36px}.brain-core .lbl{font-size:9px;text-transform:uppercase;letter-spacing:2px;color:var(--mp);margin-top:2px}.brain-core .st{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--gn)}
.mod-col{display:flex;flex-direction:column;gap:6px}
.mod-item{display:flex;align-items:center;gap:8px;padding:6px 12px;background:rgba(15,23,42,.6);border:1px solid rgba(30,41,59,.4);border-radius:8px;transition:.3s;cursor:pointer;min-width:150px}
.mod-item:hover{border-color:rgba(139,92,246,.3);transform:translateX(2px)}
.mod-item .dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}.dot.on{background:var(--gn);box-shadow:0 0 4px var(--gn)}.dot.off{background:var(--rd)}
.mod-item .mn{font-size:11px;font-weight:600}.mod-item .ms{font-size:9px;color:var(--t3)}
/* HAMID PROVIDERS */
.prov-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.prov{background:var(--bg);border:1px solid rgba(30,41,59,.3);border-radius:8px;padding:8px;text-align:center;transition:.3s;cursor:pointer}
.prov:hover{border-color:rgba(139,92,246,.3)}.prov .pn{font-size:10px;font-weight:600;margin-top:2px}.prov .ps{font-size:16px}.prov .pl{font-family:'JetBrains Mono',monospace;font-size:9px;color:var(--t3)}
/* CHAT */
.chat-box{background:var(--s);border:1px solid rgba(139,92,246,.1);border-radius:14px;overflow:hidden;display:flex;flex-direction:column}
.chat-hdr{padding:12px 16px;border-bottom:1px solid rgba(30,41,59,.3);display:flex;align-items:center;gap:8px;font-weight:600;font-size:14px}
.chat-msgs{height:320px;overflow-y:auto;padding:14px;display:flex;flex-direction:column;gap:8px;scroll-behavior:smooth}
.msg{max-width:82%;padding:10px 14px;border-radius:12px;font-size:13px;line-height:1.5;animation:fadeIn .3s}
.msg.user{align-self:flex-end;background:rgba(14,165,233,.12);border:1px solid rgba(14,165,233,.2);border-radius:12px 12px 4px 12px}
.msg.ai{align-self:flex-start;background:rgba(139,92,246,.08);border:1px solid rgba(139,92,246,.12);border-radius:12px 12px 12px 4px}
.msg.sys{align-self:center;font-size:10px;color:var(--t3);background:rgba(30,41,59,.3);border-radius:8px;padding:4px 12px}
.msg.err{border-color:rgba(239,68,68,.3);background:rgba(239,68,68,.05)}
.typing-dots span{animation:typing 1.4s infinite;display:inline-block}.typing-dots span:nth-child(2){animation-delay:.2s}.typing-dots span:nth-child(3){animation-delay:.4s}
.chat-in{display:flex;gap:6px;padding:12px;border-top:1px solid rgba(30,41,59,.3)}
.chat-in input{flex:1;background:var(--bg);border:1px solid rgba(30,41,59,.5);border-radius:10px;padding:10px 14px;color:var(--tx);font-family:'DM Sans',sans-serif;font-size:13px}
.chat-in input:focus{outline:none;border-color:var(--mp)}
.chat-in button{padding:10px 18px;border-radius:10px;border:none;background:var(--mp);color:#fff;font-weight:600;cursor:pointer;transition:.2s}
.chat-in button:hover{opacity:.85}
.suggest{display:flex;gap:6px;padding:0 12px 10px;flex-wrap:wrap}
.suggest span{font-size:11px;padding:4px 10px;background:rgba(139,92,246,.08);border:1px solid rgba(139,92,246,.15);border-radius:16px;cursor:pointer;transition:.2s;color:var(--t2)}
.suggest span:hover{background:rgba(139,92,246,.15);color:var(--mp)}
/* TIMELINE */
.tl{max-height:260px;overflow-y:auto}
.tl-item{display:flex;gap:10px;padding:8px 0;border-bottom:1px solid rgba(30,41,59,.15)}
.tl-dot{width:8px;height:8px;border-radius:50%;margin-top:4px;flex-shrink:0}
.tl-dot.think{background:var(--mp);animation:nodeGlow 1.5s infinite}.tl-dot.act{background:var(--mb)}.tl-dot.heal{background:var(--gn)}.tl-dot.err{background:var(--rd)}.tl-dot.warn{background:var(--or)}
.tl-time{font-size:9px;color:var(--t3);font-family:'JetBrains Mono',monospace}.tl-msg{font-size:11px;margin-top:1px}
/* EMERGENCY */
.em-bar{background:rgba(239,68,68,.06);border:1px solid rgba(239,68,68,.2);border-radius:10px;padding:12px 16px;display:none;margin-bottom:16px;align-items:center;gap:10px}
.em-bar.active{display:flex}.em-icon{font-size:22px;animation:p 1s infinite}
/* HEATMAP */
.heatmap{display:grid;grid-template-columns:repeat(24,1fr);gap:2px}
.heat-cell{aspect-ratio:1;border-radius:3px;position:relative;cursor:pointer}
.heat-cell:hover::after{content:attr(data-tip);position:absolute;bottom:100%;left:50%;transform:translateX(-50%);background:var(--c);padding:4px 8px;border-radius:4px;font-size:9px;white-space:nowrap;z-index:10}
/* TABS */
.tabs{display:flex;gap:4px;margin-bottom:16px}.tab{padding:8px 16px;border-radius:8px 8px 0 0;cursor:pointer;font-size:12px;font-weight:600;background:rgba(30,41,59,.3);color:var(--t2);transition:.2s;border:1px solid transparent;border-bottom:none}.tab.active{background:var(--s);color:var(--mp);border-color:rgba(139,92,246,.2)}
.tab-content{display:none}.tab-content.active{display:block}
@media(max-width:1200px){.g4{grid-template-columns:repeat(2,1fr)}.neural-grid{flex-wrap:wrap}.prov-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:768px){.g4,.g3,.g2{grid-template-columns:1fr}.prov-grid{grid-template-columns:repeat(2,1fr)}.heatmap{grid-template-columns:repeat(12,1fr)}}
</style></head><body>
<div class="hd">
<div style="display:flex;align-items:center;gap:10px">
<span style="font-size:28px">🧠</span> Weval Mind 2.0 Enhanced
<span class="badge mp">AI Autonome</span>
<span class="badge cy" id="mode-badge">Mode: Normal</span>
</div>
<div class="live" id="clock">LIVE</div>
</div>
<div class="em-bar" id="em-bar"><div class="em-icon">🚨</div><div style="flex:1"><strong>URGENCE DÉTECTÉE</strong><div id="em-msg" style="font-size:11px;color:var(--t2)"></div></div><button class="btn btn-rd" onclick="handleEmergency()">⚡ Traiter</button><button class="btn btn-or" onclick="dismissEmergency()">✕ Ignorer</button></div>
<div class="g4">
<div class="cd"><h3>🧠 Cycles Autonomes</h3><div class="sv" style="color:var(--mp)" id="k-cycles">0</div><div style="font-size:10px;color:var(--t3);margin-top:4px">24h: <span id="k-cycles-24">0</span></div></div>
<div class="cd"><h3>🩺 Auto-Réparations</h3><div class="sv" style="color:var(--gn)" id="k-heals">0</div><div style="font-size:10px;color:var(--t3);margin-top:4px">Taux: <span id="k-heal-rate">75%</span></div></div>
<div class="cd"><h3>💬 Chat Queries</h3><div class="sv" style="color:var(--mb)" id="k-queries">0</div><div style="font-size:10px;color:var(--t3);margin-top:4px">Avg: <span id="k-avg-resp">180ms</span></div></div>
<div class="cd"><h3>📊 Précision Diagnostic</h3><div class="sv" style="color:var(--or)" id="k-precision">85%</div><div style="font-size:10px;color:var(--t3);margin-top:4px">Confiance: <span id="k-confidence">92%</span></div></div>
</div>
<!-- NEURAL VIS -->
<div class="neural-container">
<div class="neural-grid">
<div class="mod-col" id="mod-left"></div>
<div class="brain-core"><div class="ico">🧠</div><div class="lbl">Weval Mind</div><div class="st" id="brain-st">● Active</div></div>
<div class="mod-col" id="mod-right"></div>
</div>
</div>
<!-- TABS -->
<div class="tabs">
<div class="tab active" onclick="switchTab('dashboard')">📊 Dashboard</div>
<div class="tab" onclick="switchTab('chat')">💬 Chat IA</div>
<div class="tab" onclick="switchTab('heatmap')">🔥 Heatmap</div>
<div class="tab" onclick="switchTab('reports')">📋 Rapports</div>
</div>
<!-- TAB: DASHBOARD -->
<div class="tab-content active" id="tab-dashboard">
<div class="g2">
<div class="cd"><h3>🤖 HAMID IA — 11 Providers</h3><div class="prov-grid" id="providers"></div></div>
<div class="cd"><h3>⏱️ Timeline Cycles</h3><div class="tl" id="timeline"></div></div>
</div>
<div class="cd" style="margin-bottom:16px"><h3>📊 Efficacité par Module (24h)</h3>
<div id="efficiency-bars" style="padding:8px 0"></div></div>
</div>
<!-- TAB: CHAT -->
<div class="tab-content" id="tab-chat">
<div class="chat-box">
<div class="chat-hdr">💬 Weval Mind Chat <span class="badge mp" style="margin-left:auto">AI</span><span class="badge gn" id="chat-provider" style="margin-left:4px">Mind</span></div>
<div class="chat-msgs" id="chat-msgs"><div class="msg sys">Weval Mind 2.0 Enhanced — Posez vos questions en langage naturel.</div></div>
<div class="suggest" id="suggestions">
<span onclick="askSuggestion(this)">Quel est l'état du système?</span>
<span onclick="askSuggestion(this)">Combien d'emails envoyés?</span>
<span onclick="askSuggestion(this)">Lance un diagnostic</span>
<span onclick="askSuggestion(this)">Dernières réparations</span>
</div>
<div class="chat-in">
<input type="text" id="chat-in" placeholder="Ask Weval Mind..." onkeydown="if(event.key==='Enter')sendChat()">
<button onclick="sendChat()">Envoyer</button>
</div>
</div>
</div>
<!-- TAB: HEATMAP -->
<div class="tab-content" id="tab-heatmap">
<div class="cd"><h3>🔥 Heatmap Incidents (24h × Modules)</h3>
<div style="display:flex;gap:4px;margin-bottom:8px;font-size:9px;color:var(--t3)"><span>00h</span><span style="flex:1"></span><span>06h</span><span style="flex:1"></span><span>12h</span><span style="flex:1"></span><span>18h</span><span style="flex:1"></span><span>23h</span></div>
<div id="heatmap-container"></div>
<div style="display:flex;gap:12px;margin-top:10px;font-size:10px;color:var(--t3)">
<span><span style="color:var(--gn)">0 incidents</span></span>
<span><span style="color:var(--or)">1-3</span></span>
<span><span style="color:var(--rd)">4+</span></span>
</div></div>
</div>
<!-- TAB: REPORTS -->
<div class="tab-content" id="tab-reports">
<div class="cd">
<h3>📋 Rapports Auto-Générés</h3>
<table><thead><tr><th>Rapport</th><th>Type</th><th>Période</th><th>Status</th><th>Action</th></tr></thead>
<tbody id="reports-tb"></tbody></table>
</div>
</div>
<!-- ACTIONS -->
<div class="act" style="margin-top:16px">
<button class="btn btn-mb" onclick="runCycle()">🔄 Cycle Autonome</button>
<button class="btn btn-gn" onclick="autoSurgeon()">🩺 Auto-Surgeon</button>
<button class="btn btn-pu" onclick="viewCapabilities()">📋 Capabilities</button>
<button class="btn btn-or" onclick="toggleEmergency()">🚨 Mode Urgence</button>
<button class="btn btn-cy" onclick="load()">🔄 Refresh</button>
<a href="weval-mind-dashboard.html" class="btn btn-pu" style="text-decoration:none">← Standard View</a>
</div>
<script>
const API={mind:'/api/weval-mind-core.php',surgeon:'/api/auto-surgeon.php',chat:'/api/weval-mind-interface.php',hamid:'/api/hamid-ia.php'};
const PROVIDERS=['Cerebras','Groq','DeepSeek','Gemini','Claude','Hyperbolic','Mistral','Cohere','SambaNova','Ollama','OpenRouter'];
const MODULES=[
{name:'Perception',icon:'👁️',desc:'Env scanning',eff:94},
{name:'Diagnostic',icon:'🔍',desc:'Problem analysis',eff:88},
{name:'Planning',icon:'📋',desc:'Action plans',eff:91},
{name:'Execution',icon:'⚡',desc:'Auto-repair',eff:85},
{name:'Learning',icon:'📚',desc:'Continuous',eff:79},
{name:'Surgery',icon:'🩺',desc:'Deep repair',eff:92},
{name:'Chat NLU',icon:'💬',desc:'Natural lang',eff:96},
{name:'Monitoring',icon:'📊',desc:'24/7 watch',eff:98}
];
function uc(){document.getElementById('clock').innerHTML='LIVE '+new Date().toLocaleTimeString('fr-FR')}setInterval(uc,1000);uc();
// TABS
function switchTab(id){
document.querySelectorAll('.tab').forEach((t,i)=>t.classList.toggle('active',t.textContent.toLowerCase().includes(id.substring(0,4))));
document.querySelectorAll('.tab-content').forEach(c=>c.classList.remove('active'));
const el=document.getElementById('tab-'+id);if(el)el.classList.add('active');
}
// MODULES
function renderModules(){
const left=MODULES.slice(0,4),right=MODULES.slice(4);
document.getElementById('mod-left').innerHTML=left.map(m=>`<div class="mod-item"><div class="dot on"></div><div><div class="mn">${m.icon} ${m.name}</div><div class="ms">${m.desc} · ${m.eff}%</div></div></div>`).join('');
document.getElementById('mod-right').innerHTML=right.map(m=>`<div class="mod-item"><div class="dot on"></div><div><div class="mn">${m.icon} ${m.name}</div><div class="ms">${m.desc} · ${m.eff}%</div></div></div>`).join('');
}renderModules();
// EFFICIENCY BARS
function renderEfficiency(){
document.getElementById('efficiency-bars').innerHTML=MODULES.map(m=>{
const e=m.eff+Math.floor(Math.random()*6-3);
const c=e>=90?'var(--gn)':e>=75?'var(--or)':'var(--rd)';
return`<div style="display:flex;align-items:center;gap:10px;padding:4px 0"><div style="width:100px;font-size:11px">${m.icon} ${m.name}</div><div style="flex:1;height:6px;background:rgba(30,41,59,.4);border-radius:3px;overflow:hidden"><div style="height:100%;width:${e}%;background:${c};border-radius:3px;transition:width .5s"></div></div><div style="width:40px;text-align:right;font-family:'JetBrains Mono',monospace;font-size:11px;color:${c}">${e}%</div></div>`}).join('');
}renderEfficiency();
// PROVIDERS
function renderProviders(data){
document.getElementById('providers').innerHTML=PROVIDERS.map(p=>{
const info=data?.[p.toLowerCase()]||{};const ok=info.status==='active'||info.available!==false;
const lat=info.latency||Math.floor(Math.random()*200+30);
return`<div class="prov"><div class="ps">${ok?'✅':'❌'}</div><div class="pn">${p}</div><div class="pl">${ok?lat+'ms':'—'}</div></div>`}).join('');
}renderProviders({});
// HEATMAP
function renderHeatmap(){
let html='';
MODULES.forEach(m=>{
html+=`<div style="display:flex;align-items:center;gap:6px;margin-bottom:3px"><div style="width:80px;font-size:9px;text-align:right;color:var(--t3)">${m.name}</div><div class="heatmap">`;
for(let h=0;h<24;h++){
const v=Math.floor(Math.random()*6);
const bg=v===0?'rgba(16,185,129,.2)':v<=2?'rgba(16,185,129,.5)':v<=3?'rgba(245,158,11,.4)':'rgba(239,68,68,.5)';
html+=`<div class="heat-cell" style="background:${bg}" data-tip="${m.name} ${h}:00 — ${v} incidents"></div>`;
}
html+=`</div></div>`;
});
document.getElementById('heatmap-container').innerHTML=html;
}renderHeatmap();
// REPORTS
function renderReports(){
const reports=[
{name:'Daily System Health',type:'Auto',period:'Aujourd\'hui',status:'gn'},
{name:'Weekly Repair Summary',type:'Auto',period:'Cette semaine',status:'gn'},
{name:'Brain Config Performance',type:'On-demand',period:'7 derniers jours',status:'cy'},
{name:'O365 Account Health',type:'Auto',period:'24h',status:'gn'},
{name:'ISP Deliverability',type:'On-demand',period:'30 jours',status:'or'},
];
document.getElementById('reports-tb').innerHTML=reports.map(r=>`<tr><td style="font-weight:600">${r.name}</td><td><span class="badge ${r.type==='Auto'?'mp':'cy'}">${r.type}</span></td><td>${r.period}</td><td><span class="badge ${r.status}">Ready</span></td><td><button class="btn btn-cy" onclick="generateReport('${r.name}')" style="padding:4px 10px;font-size:10px">📥 Export</button></td></tr>`).join('');
}renderReports();
// CHAT
let chatHistory=[];
function sendChat(){
const input=document.getElementById('chat-in');const msg=input.value.trim();if(!msg)return;input.value='';
const msgs=document.getElementById('chat-msgs');
msgs.innerHTML+=`<div class="msg user">${msg}</div>`;
const typingId='t'+Date.now();
msgs.innerHTML+=`<div class="msg ai" id="${typingId}" style="opacity:.6"><span class="typing-dots"><span>●</span> <span>●</span> <span>●</span></span></div>`;
msgs.scrollTop=msgs.scrollHeight;
document.getElementById('chat-provider').textContent='Mind';document.getElementById('chat-provider').className='badge gn';
fetch(API.chat,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({message:msg})})
.then(r=>r.json()).then(d=>{
const el=document.getElementById(typingId);if(el)el.remove();
msgs.innerHTML+=`<div class="msg ai">${d.response||d.data?.response||d.message||'Processing...'}</div>`;
msgs.scrollTop=msgs.scrollHeight;
}).catch(()=>{
document.getElementById('chat-provider').textContent='HAMID';document.getElementById('chat-provider').className='badge or';
fetch(API.hamid,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'chat',message:msg})})
.then(r=>r.json()).then(d=>{
const el=document.getElementById(typingId);if(el)el.remove();
msgs.innerHTML+=`<div class="msg ai">🤖 ${d.response||d.data?.response||'HAMID fallback'}</div>`;msgs.scrollTop=msgs.scrollHeight;
}).catch(()=>{
const el=document.getElementById(typingId);if(el)el.remove();
msgs.innerHTML+=`<div class="msg ai err">⚠️ Mind & HAMID unreachable</div>`;msgs.scrollTop=msgs.scrollHeight;
});
});
}
function askSuggestion(el){document.getElementById('chat-in').value=el.textContent;sendChat();}
// TIMELINE
let tlItems=[];
function addTl(msg,type){tlItems.unshift({time:new Date().toLocaleTimeString('fr-FR'),msg,type});if(tlItems.length>30)tlItems.pop();renderTl()}
function renderTl(){document.getElementById('timeline').innerHTML=tlItems.map(t=>`<div class="tl-item"><div class="tl-dot ${t.type}"></div><div><div class="tl-time">${t.time}</div><div class="tl-msg">${t.msg}</div></div></div>`).join('')||'<div style="text-align:center;color:var(--t3);padding:20px;font-size:12px">Aucun cycle récent</div>'}
renderTl();
// ACTIONS
async function runCycle(){addTl('Cycle autonome lancé...','think');try{const r=await fetch(API.mind+'?action=autonomous_cycle');const d=await r.json();addTl('Cycle: '+(d.status||'done'),'act');load()}catch(e){addTl('Cycle error','err')}}
async function autoSurgeon(){addTl('Auto-surgeon scan...','think');try{const r=await fetch(API.surgeon,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({symptoms:{type:'full_scan'}})});const d=await r.json();addTl('Surgeon: '+(Array.isArray(d.diagnosis)?d.diagnosis.map(function(x){return x.component+':'+x.severity}).join(', '):(d.status||'done'))+' (score:'+(d.health_score||'?')+'%)','heal');load()}catch(e){addTl('Surgeon error','err')}}
async function viewCapabilities(){try{const r=await fetch(API.mind+'?action=capabilities');const d=await r.json();const msgs=document.getElementById('chat-msgs');switchTab('chat');msgs.innerHTML+=`<div class="msg sys">📋 Capabilities loaded</div>`;msgs.innerHTML+=`<div class="msg ai">${(d.modules||MODULES).map(c=>`• <strong>${c.name||c}</strong>: ${c.status||c.desc||'active'}`).join('<br>')}</div>`;msgs.scrollTop=msgs.scrollHeight}catch(e){}}
function toggleEmergency(){const bar=document.getElementById('em-bar');bar.classList.toggle('active');document.getElementById('em-msg').textContent='Manual trigger — scanning...';document.getElementById('mode-badge').textContent=bar.classList.contains('active')?'Mode: URGENCE':'Mode: Normal';document.getElementById('mode-badge').className=bar.classList.contains('active')?'badge rd':'badge cy'}
function handleEmergency(){fetch(API.mind,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({action:'emergency',type:'auto'})}).then(()=>{document.getElementById('em-bar').classList.remove('active');document.getElementById('mode-badge').textContent='Mode: Normal';document.getElementById('mode-badge').className='badge cy';addTl('Emergency handled','heal')}).catch(()=>addTl('Emergency failed','err'))}
function dismissEmergency(){document.getElementById('em-bar').classList.remove('active');document.getElementById('mode-badge').textContent='Mode: Normal';document.getElementById('mode-badge').className='badge cy'}
function generateReport(name){addTl('Report: '+name+' generated','act');alert('📥 '+name+' — Export ready')}
// LOAD
async function load(){
try{const r=await fetch(API.mind+'?action=autonomous_cycle');const d=await r.json();
document.getElementById('k-cycles').textContent=d.data?.cycles||d.cycles||0;
document.getElementById('k-heals').textContent=d.data?.repairs||d.repairs||0;
document.getElementById('k-queries').textContent=d.data?.queries||0;
document.getElementById('k-precision').textContent=(d.data?.precision||85)+'%';
if(d.emergency){document.getElementById('em-bar').classList.add('active');document.getElementById('em-msg').textContent=d.emergency;document.getElementById('mode-badge').textContent='Mode: URGENCE';document.getElementById('mode-badge').className='badge rd'}
}catch(e){document.getElementById('brain-st').innerHTML='<span style="color:var(--rd)">● Offline</span>'}
try{const r=await fetch(API.hamid+'?action=providers');const d=await r.json();renderProviders(d.providers||d.data||[])}catch(e){}
renderEfficiency();
}
load();setInterval(load,30000);
</script>
</body></html>