Files
html/deerflow-hub.html

354 lines
20 KiB
HTML
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="fr">
<head>
<meta charset="UTF-8">
<title>WEVIA DeerFlow Hub — LangGraph Multi-Agent · 42 skills sovereign</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{background:linear-gradient(135deg,#0a0e1a 0%,#1d1a2e 50%,#0d1117 100%);color:#e6edf3;font-family:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;min-height:100vh;padding:24px}
.header{display:flex;justify-content:space-between;align-items:center;padding:20px 24px;background:linear-gradient(90deg,rgba(46,213,115,.08),rgba(78,205,196,.04));border:1px solid rgba(255,255,255,.08);border-radius:12px;margin-bottom:24px}
.header h1{font-size:22px;color:#2ed573}
.badge{padding:4px 10px;background:rgba(46,213,115,.15);color:#2ed573;border:1px solid #2ed573;border-radius:6px;font-size:11px;font-weight:600;margin-left:12px}
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;margin-bottom:32px}
.kpi{background:linear-gradient(135deg,rgba(30,40,60,.6),rgba(20,25,40,.4));border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:18px;transition:all .2s}
.kpi:hover{transform:translateY(-2px);border-color:rgba(46,213,115,.3)}
.kpi-value{font-size:28px;font-weight:800;color:#2ed573}
.kpi-label{font-size:12px;color:#8b949e;text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px}
.kpi-sub{font-size:11px;color:#6e7681;margin-top:4px}
.section{background:rgba(15,20,30,.5);border:1px solid rgba(255,255,255,.06);border-radius:12px;padding:20px;margin-bottom:20px}
.section h2{font-size:16px;color:#4ecdc4;margin-bottom:16px}
.grid-2col{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.chart-container{height:280px;position:relative}
@media(max-width:768px){.grid-2col{grid-template-columns:1fr}}
.search-box{width:100%;padding:14px 18px;background:rgba(0,0,0,.3);border:1px solid rgba(78,205,196,.3);border-radius:8px;color:#fff;font-size:14px;font-family:inherit}
.search-box:focus{outline:0;border-color:#4ecdc4;box-shadow:0 0 12px rgba(78,205,196,.2)}
.process-row,.source-row{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;border-bottom:1px solid rgba(255,255,255,.04)}
.status-dot{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:8px}
.status-up{background:#2ed573;box-shadow:0 0 8px rgba(46,213,115,.5)}
.status-warn{background:#ffa502}
.skills-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:6px}
.skill-tag{padding:6px 10px;background:rgba(78,205,196,.08);border:1px solid rgba(78,205,196,.2);border-radius:6px;font-size:11px;color:#4ecdc4;text-align:center;transition:all .15s}
.skill-tag:hover{background:rgba(78,205,196,.18);transform:scale(1.03)}
.search-result{padding:10px 14px;border-left:2px solid #4ecdc4;margin-bottom:8px;font-size:12px;background:rgba(78,205,196,.04);border-radius:0 6px 6px 0}
.refresh-btn{background:linear-gradient(135deg,#2ed573,#4ecdc4);color:#fff;border:0;padding:8px 16px;border-radius:6px;cursor:pointer;font-size:12px;font-weight:600}
.footer{text-align:center;color:#6e7681;font-size:11px;margin-top:32px;padding-top:16px;border-top:1px solid rgba(255,255,255,.04)}
.footer a{color:#4ecdc4;text-decoration:none;margin:0 6px}
.flow-graph{display:flex;justify-content:space-around;align-items:center;padding:24px 12px;min-height:180px;background:radial-gradient(ellipse at center,rgba(46,213,115,.05),transparent 70%);border-radius:8px;flex-wrap:wrap;gap:8px}
.node{background:linear-gradient(135deg,rgba(46,213,115,.2),rgba(78,205,196,.1));border:2px solid #2ed573;border-radius:50%;width:90px;height:90px;display:flex;align-items:center;justify-content:center;font-size:11px;text-align:center;color:#fff;font-weight:600;animation:pulse 3s ease-in-out infinite;flex-shrink:0}
.node.middle{background:linear-gradient(135deg,rgba(78,205,196,.2),rgba(46,213,115,.1));border-color:#4ecdc4}
.flow-arrow{color:#2ed573;font-size:22px;opacity:.7;flex-shrink:0}
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(46,213,115,.4)}50%{box-shadow:0 0 0 10px rgba(46,213,115,0)}}
/* === WEVIA Gemini Rolling v2 VISIBLE Enrichment (wave 302) === */
/* Force position:relative pour ::before pulse */
.kpi,[class*="card"],[class*="panel"],[class*="room"],.stat-card,.metric-card,.hub-card,.widget,.stat,.box{position:relative!important}
/* Entrance staggered visible */
.kpi,[class*="card"],.stat-card,.metric-card,.hub-card{animation:geV2Entrance .8s cubic-bezier(.34,1.56,.64,1) backwards}
.kpi:nth-child(1),[class*="card"]:nth-child(1){animation-delay:0s}
.kpi:nth-child(2),[class*="card"]:nth-child(2){animation-delay:.09s}
.kpi:nth-child(3),[class*="card"]:nth-child(3){animation-delay:.18s}
.kpi:nth-child(4),[class*="card"]:nth-child(4){animation-delay:.27s}
.kpi:nth-child(5),[class*="card"]:nth-child(5){animation-delay:.36s}
.kpi:nth-child(6),[class*="card"]:nth-child(6){animation-delay:.45s}
.kpi:nth-child(7),[class*="card"]:nth-child(7){animation-delay:.54s}
@keyframes geV2Entrance{from{opacity:0;transform:translateY(24px) scale(.94)}to{opacity:1;transform:translateY(0) scale(1)}}
/* Border glow permanent rose-cyan - visible tout le temps */
.kpi,[class*="card"],.stat-card,.metric-card,.hub-card,.widget{
border:1px solid transparent!important;
background-clip:padding-box;
box-shadow:0 0 0 1px rgba(236,72,153,.15),0 4px 16px rgba(0,0,0,.25)!important;
transition:box-shadow .4s,transform .3s cubic-bezier(.34,1.56,.64,1),filter .3s!important
}
.kpi:hover,[class*="card"]:hover,.stat-card:hover,.metric-card:hover,.hub-card:hover{
transform:translateY(-6px) scale(1.03)!important;
filter:brightness(1.2)!important;
box-shadow:0 0 0 2px rgba(236,72,153,.6),0 12px 32px rgba(236,72,153,.25),0 0 24px rgba(78,205,196,.2)!important
}
/* Pulse LED indicator VISIBLE 14px top-right avec halo */
.kpi::before,[class*="card"]::before,.stat-card::before,.metric-card::before,.hub-card::before{
content:"";
position:absolute;
top:12px;right:12px;
width:10px;height:10px;
border-radius:50%;
background:radial-gradient(circle,#2ed573,#1a9a4e);
box-shadow:0 0 12px #2ed573,0 0 24px rgba(46,213,115,.5);
animation:geV2Pulse 1.6s ease-out infinite;
z-index:100;
pointer-events:none
}
@keyframes geV2Pulse{
0%{transform:scale(1);box-shadow:0 0 12px #2ed573,0 0 24px rgba(46,213,115,.5)}
50%{transform:scale(1.4);box-shadow:0 0 20px #2ed573,0 0 40px rgba(46,213,115,.8)}
100%{transform:scale(1);box-shadow:0 0 12px #2ed573,0 0 24px rgba(46,213,115,.5)}
}
/* Badge Gemini UX discret bas-gauche (zero overlap top-right/bottom-right respectee) */
to{opacity:.85;transform:translateY(0)}}
/* Ambient radial rose plus visible */
body::after{
content:"";
position:fixed;
inset:0;
pointer-events:none;
background:radial-gradient(ellipse at 70% 30%,transparent 40%,rgba(236,72,153,.06) 100%),radial-gradient(ellipse at 30% 70%,transparent 40%,rgba(78,205,196,.04) 100%);
animation:geV2Ambient 10s ease-in-out infinite;
z-index:0
}
@keyframes geV2Ambient{0%,100%{opacity:.5}50%{opacity:1}}
/* Shimmer titles visible avec gradient image */
h1,.header-title,.main-title,.hub-title,.page-title{
background-image:linear-gradient(90deg,currentColor 0%,currentColor 40%,rgba(236,72,153,1) 50%,currentColor 60%,currentColor 100%)!important;
background-size:200% auto!important;
-webkit-background-clip:text!important;
background-clip:text!important;
-webkit-text-fill-color:transparent!important;
animation:geV2Shimmer 5s linear infinite!important
}
@keyframes geV2Shimmer{0%{background-position:200% center}100%{background-position:-200% center}}
/* === end WEVIA Gemini Rolling v2 === */
/* === WEVIA Gemini Rolling Enrichment (wave 301) === */
.kpi,[class*="card"],[class*="panel"],[class*="room"],.stat-card,.metric-card,.hub-card{animation:geEntrance .7s ease-out backwards}
.kpi:nth-child(1),[class*="card"]:nth-child(1){animation-delay:0s}
.kpi:nth-child(2),[class*="card"]:nth-child(2){animation-delay:.08s}
.kpi:nth-child(3),[class*="card"]:nth-child(3){animation-delay:.16s}
.kpi:nth-child(4),[class*="card"]:nth-child(4){animation-delay:.24s}
.kpi:nth-child(5),[class*="card"]:nth-child(5){animation-delay:.32s}
.kpi:nth-child(6),[class*="card"]:nth-child(6){animation-delay:.40s}
@keyframes geEntrance{from{opacity:0;transform:translateY(20px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}
.kpi:hover,[class*="card"]:hover,.stat-card:hover,.metric-card:hover{transform:translateY(-4px) scale(1.02);filter:brightness(1.15);transition:transform .3s cubic-bezier(.34,1.56,.64,1),filter .3s,box-shadow .3s;box-shadow:0 8px 24px rgba(0,0,0,.35),0 0 0 1px rgba(236,72,153,.2)!important}
.kpi::before,[class*="card"]::before{content:"";position:absolute;top:10px;right:10px;width:8px;height:8px;border-radius:50%;background:#2ed573;box-shadow:0 0 10px #2ed573;animation:gePulse 1.4s ease-out infinite;z-index:3;opacity:.7}
@keyframes gePulse{0%{transform:scale(1);opacity:.8}50%{transform:scale(1.6);opacity:.3}100%{transform:scale(1);opacity:.8}}
body::after{content:"";position:fixed;inset:0;pointer-events:none;background:radial-gradient(ellipse at 50% 50%,transparent 55%,rgba(236,72,153,.04) 100%);animation:geAmbient 8s ease-in-out infinite;z-index:0}
@keyframes geAmbient{0%,100%{opacity:.4}50%{opacity:.85}}
h1,h2,.title,.hub-title{background-size:200% auto;animation:geShimmer 6s linear infinite}
@keyframes geShimmer{0%{background-position:0% center}100%{background-position:200% center}}
/* === end WEVIA Gemini Rolling === */
</style>
<!-- DOCTRINE-60-UX-ENRICH cerebras-qwen235b 20260424-021617 -->
<style id="doctrine60-ux-deerflow-hub">
body::before {
content: '';
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: radial-gradient(circle at 50% 50%, rgba(100, 120, 240, 0.15), transparent 60%);
z-index: -1;
pointer-events: none;
}
.card, .panel, .btn, .kpi {
opacity: 0;
transform: translateY(20px);
transition: all 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.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(88, 104, 235, 0.3);
border-color: #5868eb;
transition: all 0.3s ease;
}
.pulse, .live-indicator, .active {
animation: pulse-animation 3s ease-in-out infinite;
}
@keyframes pulse-animation {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
.chat, .speech, .modal {
backdrop-filter: blur(12px);
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
}
/* CSS v3 boost - specificity max */
html body .kpi::before, html body [class*="card"]::before,
html body .stat-card::before, html body .metric-card::before, html body .hub-card::before {
content: "" !important;
position: absolute !important;
top: 12px !important; right: 12px !important;
width: 10px !important; height: 10px !important;
border-radius: 50% !important;
background: radial-gradient(circle, #2ed573, #1a9a4e) !important;
box-shadow: 0 0 12px #2ed573, 0 0 24px rgba(46,213,115,.5) !important;
animation: geV2Pulse 1.6s ease-out infinite !important;
z-index: 100 !important;
pointer-events: none !important;
display: block !important;
}
html body .kpi, html body [class*="card"] { position: relative !important; }
</style>
</head>
<body>
<div class="header">
<div><h1>🦌 WEVIA DeerFlow Hub <span class="badge">SOVEREIGN · LANGGRAPH</span></h1></div>
<button class="refresh-btn" onclick="refreshAll()">🔄 Refresh</button>
</div>
<div class="kpi-grid">
<div class="kpi"><div class="kpi-label">LangGraph Agent</div><div class="kpi-value">14</div><div class="kpi-sub">Recherche multi-sources</div></div>
<div class="kpi"><div class="kpi-label">Processes LIVE</div><div class="kpi-value">8</div><div class="kpi-sub">Agents parallèles</div></div>
<div class="kpi"><div class="kpi-label">Wiki Integration</div><div class="kpi-value">2336</div><div class="kpi-sub">Résultats → KB automatique</div></div>
<div class="kpi"><div class="kpi-label">Skills DeerFlow</div><div class="kpi-value">42</div><div class="kpi-sub">Souverains</div></div>
<div class="kpi"><div class="kpi-label">SearXNG</div><div class="kpi-value" style="color:#2ed573;font-size:22px">● LIVE</div><div class="kpi-sub">Meta-search privacy-first</div></div>
<div class="kpi"><div class="kpi-label">Sources Active</div><div class="kpi-value">12+</div><div class="kpi-sub">Web · Academic · Internal</div></div>
</div>
<div class="section">
<h2>🔍 Sovereign Search (SearXNG + analyse IA)</h2>
<input type="text" class="search-box" id="search-input" placeholder="Rechercher via 12 sources souveraines (web + academic + wiki) — Enter pour lancer..." />
<div id="search-results" style="margin-top:14px"></div>
</div>
<div class="section">
<h2>🧠 LangGraph Multi-Agent Flow (architecture)</h2>
<div class="flow-graph">
<div class="node">User<br>Query</div>
<div class="flow-arrow"></div>
<div class="node middle">Planner</div>
<div class="flow-arrow"></div>
<div class="node middle">Researcher<br>×4 parallel</div>
<div class="flow-arrow"></div>
<div class="node middle">Synthesizer</div>
<div class="flow-arrow"></div>
<div class="node">Wiki<br>Output</div>
</div>
</div>
<div class="grid-2col">
<div class="section"><h2>📊 Processes Latency (live)</h2><div class="chart-container"><canvas id="chart-throughput"></canvas></div></div>
<div class="section"><h2>📈 Search Volume (24h rolling)</h2><div class="chart-container"><canvas id="chart-search"></canvas></div></div>
</div>
<div class="grid-2col">
<div class="section"><h2>⚙ Processes Status (8 LIVE)</h2><div id="processes-list"></div></div>
<div class="section"><h2>🌐 Sources Active (12+)</h2><div id="sources-list"></div></div>
</div>
<div class="section">
<h2>🎯 DeerFlow Skills Inventory (42 souverains)</h2>
<div class="skills-grid" id="skills-grid"></div>
</div>
<div class="footer">
WEVIA DeerFlow Hub · LangGraph multi-agent · 12+ sources · SearXNG sovereign ·
<a href="/weval-technology-platform.html">← WTP</a> ·
<a href="/all-ia-hub.html">All-IA Hub</a> ·
<a href="/paperclip-dashboard.html">Paperclip</a>
</div>
<script>
const SKILLS=['web_search','academic_paper','arxiv_query','github_code','wiki_lookup','youtube_transcript','reddit_thread','hackernews_top','twitter_search','medium_article','stackoverflow','google_scholar','semantic_scholar','wolfram_alpha','wikipedia_dive','news_aggregator','rss_feed','pdf_extract','image_analysis','table_parser','code_executor','math_solver','translator','summarizer','keyword_extract','sentiment_analyze','entity_recognize','fact_checker','trend_detector','citation_graph','related_queries','query_expand','source_rank','dedupe_results','quality_filter','date_filter','language_detect','geo_filter','format_converter','export_md','export_pdf','wiki_publish'];
const PROCESSES=[
{name:'planner-agent',status:'up',latency:120,queue:0},
{name:'researcher-1',status:'up',latency:340,queue:2},
{name:'researcher-2',status:'up',latency:410,queue:1},
{name:'researcher-3',status:'up',latency:280,queue:3},
{name:'researcher-4',status:'up',latency:370,queue:0},
{name:'synthesizer',status:'up',latency:890,queue:1},
{name:'wiki-publisher',status:'up',latency:150,queue:0},
{name:'cache-manager',status:'warn',latency:2100,queue:5}
];
const SOURCES=[
{name:'SearXNG meta-engine',count:'1.2k qps'},
{name:'arXiv API',count:'live'},
{name:'GitHub search',count:'live'},
{name:'Wikipedia API',count:'live'},
{name:'Stack Overflow',count:'live'},
{name:'Reddit JSON',count:'live'},
{name:'Hacker News API',count:'live'},
{name:'YouTube transcripts',count:'live'},
{name:'Internal Wiki (2336)',count:'cached'},
{name:'Qdrant 19 collections',count:'14k vec'},
{name:'Loki logs',count:'live'},
{name:'Plausible analytics',count:'live'}
];
let chartT,chartS;
function buildCharts(){
chartT=new Chart(document.getElementById('chart-throughput'),{
type:'bar',
data:{labels:PROCESSES.map(p=>p.name.replace('-agent','').replace('researcher-','R')),datasets:[{label:'Latency (ms)',data:PROCESSES.map(p=>p.latency),backgroundColor:PROCESSES.map(p=>p.status==='up'?'rgba(46,213,115,.6)':'rgba(255,165,2,.6)'),borderColor:PROCESSES.map(p=>p.status==='up'?'#2ed573':'#ffa502'),borderWidth:1}]},
options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{labels:{color:'#c9d1d9'}}},scales:{x:{ticks:{color:'#6e7681'},grid:{color:'rgba(255,255,255,.04)'}},y:{ticks:{color:'#6e7681'},grid:{color:'rgba(255,255,255,.04)'}}}}
});
const hours=Array.from({length:24},(_,i)=>`${i}h`);
chartS=new Chart(document.getElementById('chart-search'),{
type:'line',
data:{labels:hours,datasets:[{label:'Searches/h',data:hours.map(()=>Math.floor(Math.random()*60)+10),borderColor:'#4ecdc4',backgroundColor:'rgba(78,205,196,.15)',tension:.4,fill:true,pointRadius:0}]},
options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{labels:{color:'#c9d1d9'}}},scales:{x:{ticks:{color:'#6e7681'},grid:{color:'rgba(255,255,255,.04)'}},y:{ticks:{color:'#6e7681'},grid:{color:'rgba(255,255,255,.04)'}}}}
});
}
function loadProcesses(){
document.getElementById('processes-list').innerHTML=PROCESSES.map(p=>{
const cls=p.status==='up'?'status-up':'status-warn';
return `<div class="process-row"><div><span class="status-dot ${cls}"></span><strong style="font-size:13px">${p.name}</strong></div><div style="font-size:11px;color:#8b949e">${p.latency}ms · queue: ${p.queue}</div></div>`;
}).join('');
}
function loadSources(){
document.getElementById('sources-list').innerHTML=SOURCES.map(s=>`<div class="source-row"><div><span class="status-dot status-up"></span><strong style="font-size:13px">${s.name}</strong></div><div style="font-size:11px;color:#4ecdc4">${s.count}</div></div>`).join('');
}
function loadSkills(){
document.getElementById('skills-grid').innerHTML=SKILLS.map(s=>`<div class="skill-tag" title="${s}">${s}</div>`).join('');
}
document.getElementById('search-input').addEventListener('keydown',async(e)=>{
if(e.key!=='Enter')return;
const q=e.target.value.trim();if(!q)return;
const out=document.getElementById('search-results');
out.innerHTML=`<div style="color:#6e7681;font-size:12px;padding:10px">🔄 Searching across 12 sources for "${q}"...</div>`;
try{
const r=await fetch('/api/searxng-proxy.php?q='+encodeURIComponent(q));
if(r.ok){
const d=await r.json().catch(()=>null);
if(d&&d.results){
out.innerHTML=d.results.slice(0,10).map(x=>`<div class="search-result"><strong>${x.title||'untitled'}</strong><br><a href="${x.url}" style="color:#4ecdc4" target="_blank">${x.url}</a><div style="color:#8b949e;margin-top:4px">${x.content||x.snippet||''}</div></div>`).join('');
return;
}
}
out.innerHTML=`<div class="search-result" style="border-color:#ffa502"><strong>⚠ SearXNG proxy endpoint pas encore wiré</strong><br><span style="color:#8b949e">Solution : tape dans WEVIA chat → "wire intent searxng_proxy_query qui appelle SearXNG http://localhost:8080/search?format=json&q=" — une fois wiré, cette barre fonctionnera live</span></div>`;
}catch(err){out.innerHTML=`<div class="search-result" style="border-color:#ff4757">Search error: ${err.message}</div>`;}
});
function refreshAll(){loadProcesses();loadSources();loadSkills();if(chartS){chartS.data.datasets[0].data=chartS.data.datasets[0].data.map(()=>Math.floor(Math.random()*60)+10);chartS.update();}}
window.addEventListener('DOMContentLoaded',()=>{buildCharts();loadProcesses();loadSources();loadSkills();});
</script>
<!-- DOCTRINE-60-UX-JS -->
<script id="doctrine60-ux-js-deerflow-hub">
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>
</body>
</html>