Files
html/skills/index.html

205 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>WEVIA Skills Explorer · 15 499 skills multi-source</title>
<style>
:root{--bg:#0a0e1a;--panel:#141933;--panel2:#1a2140;--border:#263161;--text:#e4e8f7;--muted:#8b95b8;--accent:#00d4b4;--green:#10b981;--amber:#f59e0b;--blue:#6ba3ff;--purple:#c084fc}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;background:var(--bg);color:var(--text);padding:24px;min-height:100vh;line-height:1.5}
.header{display:flex;justify-content:space-between;align-items:center;padding:20px 26px;background:linear-gradient(135deg,#1e1b4b,#312e81);border-radius:14px;margin-bottom:22px;border:1px solid var(--border)}
.header h1{color:#fff;font-size:24px}
.header .sub{color:rgba(255,255,255,.75);font-size:12px;margin-top:4px}
.total-box{padding:24px 28px;background:linear-gradient(135deg,#065f46,#064e3b);border-radius:14px;margin-bottom:22px;border:1px solid rgba(16,185,129,.3);text-align:center}
.total-box .l{font-size:12px;color:#6ee7b7;text-transform:uppercase;letter-spacing:1.2px;font-weight:600}
.total-box .v{font-size:56px;font-weight:900;font-family:'SF Mono',monospace;color:#fff;line-height:1;margin-top:4px}
.total-box .max{font-size:16px;color:rgba(255,255,255,.5);margin-left:6px}
.total-box .breakdown{margin-top:16px;display:flex;gap:30px;justify-content:center;flex-wrap:wrap;font-size:12px;color:rgba(255,255,255,.75)}
.total-box .breakdown b{color:#fff;font-family:monospace;margin-right:4px}
.source-section{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:20px 22px;margin-bottom:18px}
.source-section h2{font-size:16px;font-weight:600;color:var(--accent);padding-bottom:10px;border-bottom:1px dashed var(--border);display:flex;justify-content:space-between;align-items:center}
.source-section h2 .count{font-family:monospace;background:rgba(0,212,180,.15);color:var(--accent);padding:4px 10px;border-radius:5px;font-size:14px}
.source-section .desc{color:var(--muted);font-size:12px;margin:10px 0 14px 0}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:10px}
.card{background:var(--panel2);border:1px solid var(--border);border-radius:8px;padding:12px 14px}
.card .title{font-size:13px;font-weight:700;color:var(--accent);margin-bottom:4px;font-family:monospace}
.card .sub-count{font-size:10px;background:rgba(192,132,252,.2);color:#d8b4fe;padding:2px 6px;border-radius:3px;margin-left:6px}
.card .d{font-size:11.5px;color:var(--text);margin-top:4px;line-height:1.4;min-height:30px}
.card .samples{font-size:10.5px;color:var(--muted);margin-top:6px;font-family:monospace}
.card a{display:inline-block;margin-top:8px;padding:4px 9px;background:rgba(0,212,180,.12);color:var(--accent);text-decoration:none;border-radius:4px;font-size:10.5px;font-weight:600;margin-right:4px}
.card a:hover{background:var(--accent);color:#000}
.search-box{margin-top:14px;display:flex;gap:10px;align-items:center}
.search-box input{flex:1;padding:10px 14px;background:var(--bg);border:1px solid var(--border);color:var(--text);border-radius:6px;font-size:13px;font-family:monospace}
.search-box input:focus{outline:none;border-color:var(--accent)}
.search-box button{padding:10px 18px;background:var(--accent);color:#000;border:none;border-radius:6px;cursor:pointer;font-size:12px;font-weight:700}
.search-box button:hover{background:#00f5d4}
.results{margin-top:14px;max-height:500px;overflow-y:auto}
.footer{text-align:center;margin-top:24px;font-size:11px;color:var(--muted)}
.footer a{color:#93c5fd;text-decoration:none;margin:0 8px}
.loading{text-align:center;padding:20px;color:var(--muted);font-size:12px}
.hidden{display:none}
.badge-green{background:rgba(16,185,129,.2);color:#6ee7b7}
.badge-blue{background:rgba(108,163,255,.2);color:#93c5fd}
.badge-purple{background:rgba(192,132,252,.2);color:#d8b4fe}
.badge-amber{background:rgba(245,158,11,.2);color:#fbbf24}
.badge{font-size:10px;padding:2px 7px;border-radius:4px;font-weight:600;margin-left:6px}
</style></head>
<body>
<div class="header">
<div>
<h1>🎯 WEVIA Skills Explorer</h1>
<div class="sub">5 sources · disk SKILL.md · catalogs · Qdrant vectorisé · tools registry · arena</div>
</div>
<a href="/wevia-autonomy-dashboard.html" style="color:#93c5fd;text-decoration:none;font-size:13px">← Autonomy Dashboard</a>
</div>
<div class="total-box">
<div class="l">Total skills multi-source</div>
<div class="v" id="total"><span class="max">/20K</span></div>
<div class="breakdown" id="breakdown"></div>
</div>
<div class="source-section">
<h2>🔍 Search Qdrant · 14 477 skills vectorisés (semantic + text)</h2>
<div class="desc">Search within Qdrant's <code>weval_skills</code> collection · scrolls up to 1000 skills for matches</div>
<div class="search-box">
<input type="text" id="q" placeholder="Try: security, agent, rag, claude, feynman, magika..." onkeypress="if(event.key==='Enter')doSearch()">
<button onclick="doSearch()">🔎 Search</button>
</div>
<div class="results" id="search-results"></div>
</div>
<div class="source-section">
<h2>📦 Source 1 · Disk /skills/ avec SKILL.md <span class="count" id="c1"></span></h2>
<div class="desc">Vitrine des skills visibles comme dossiers + fichier SKILL.md</div>
<div class="grid" id="disk-grid"></div>
</div>
<div class="source-section">
<h2>📚 Source 2 · Gros catalogs (deer-flow, paperclip, ecc, etc.) <span class="count" id="c2"></span></h2>
<div class="desc">Gros catalogs open-source clonés · chacun contient des dizaines/centaines de sub-skills</div>
<div class="grid" id="catalogs-grid"></div>
</div>
<div class="source-section">
<h2>🧠 Source 3 · Qdrant weval_skills vectorisés <span class="count" id="c3"></span></h2>
<div class="desc">Skills indexés dans la base vectorielle Qdrant · searchable par embeddings · utilisés par WEVIA Master pour routage intelligent</div>
<div id="qdrant-sample"></div>
<div style="text-align:center;margin-top:12px"><button onclick="loadQdrantSample()" style="padding:8px 14px;background:var(--accent);color:#000;border:none;border-radius:5px;cursor:pointer;font-size:11px;font-weight:700">Charger 50 samples</button></div>
</div>
<div class="source-section">
<h2>🛠 Source 4 · Tools Registry (wevia-tool-registry.json) <span class="count" id="c4"></span></h2>
<div class="desc">Tools callable programmatiquement · référencés dans le resolver dynamique</div>
<div class="grid" id="tools-grid"></div>
</div>
<div class="source-section">
<h2>🎭 Source 5 · Arena declared skills <span class="count" id="c5"></span></h2>
<div class="desc">Skills déclarés dans arena-intent-registry.json · Wave 115 · associés aux 310 intents</div>
<div style="padding:14px;background:var(--panel2);border-radius:8px;font-size:12.5px;color:var(--muted)">
Voir <a href="/api/arena-intent-registry.json" style="color:var(--accent);text-decoration:none">arena-intent-registry.json</a> pour détails par domaine (14 domaines all GREEN)
</div>
</div>
<div class="footer">
<a href="/wevia-autonomy-dashboard.html">Autonomy Dashboard</a>·
<a href="/wevia-master.html">WEVIA Master</a>·
<a href="/wevia-business-visual-studio.html">BVS Studio</a>·
<a href="/visual-management.html">Visual Mgmt</a>·
<a href="/l99.html">L99</a>
</div>
<script>
function fmt(n){return (n||0).toLocaleString('fr-FR');}
function esc(s){return String(s||'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));}
async function loadSources(){
try{
const r = await fetch('/api/skills-explorer-api.php?action=sources&t='+Date.now(),{cache:'no-store'});
const d = await r.json();
const s = d.sources || {};
document.getElementById('total').innerHTML = fmt(s.TOTAL_ALL_SOURCES) + '<span class="max">/20K</span>';
const s1 = s.source_1_disk_skill_md || {};
const s2 = s.source_2_disk_big_catalogs || {};
const s3 = s.source_3_qdrant_vectorized || {};
const s4 = s.source_4_tools_registry || {};
const s5 = s.source_5_arena_declared || {};
document.getElementById('breakdown').innerHTML =
'<span><b>'+fmt(s1.count)+'</b> SKILL.md disque</span>'+
'<span><b>'+fmt(s2.count)+'</b> gros catalogs ('+fmt(s2.total_sub_items)+' sub)</span>'+
'<span><b>'+fmt(s3.count)+'</b> Qdrant vectorisés</span>'+
'<span><b>'+fmt(s4.count)+'</b> tools registry</span>'+
'<span><b>'+fmt(s5.count)+'</b> arena declared</span>';
document.getElementById('c1').textContent = fmt(s1.count);
document.getElementById('c2').textContent = fmt(s2.count) + ' catalogs · '+fmt(s2.total_sub_items)+' sub';
document.getElementById('c3').textContent = fmt(s3.count);
document.getElementById('c4').textContent = fmt(s4.count);
document.getElementById('c5').textContent = fmt(s5.count);
// Render disk skills
document.getElementById('disk-grid').innerHTML = (s1.items || []).map(i =>
'<div class="card"><div class="title">📄 '+esc(i.name)+'</div><div class="d">'+esc(i.desc || 'SKILL.md disponible')+'</div><a href="'+esc(i.path)+'">SKILL.md</a><a href="/skills/'+esc(i.name)+'/">Dossier</a></div>'
).join('');
// Render catalogs
document.getElementById('catalogs-grid').innerHTML = (s2.items || []).map(i => {
const samples = (i.samples || []).join(', ');
return '<div class="card"><div class="title">📚 '+esc(i.name)+'<span class="sub-count">'+i.sub_count+' sub</span></div>'+
'<div class="d">'+esc(i.desc)+'</div>'+
(samples ? '<div class="samples">→ '+esc(samples)+'...</div>' : '')+
'<a href="'+esc(i.path)+'">Explorer</a></div>';
}).join('');
// Render tools sample
document.getElementById('tools-grid').innerHTML = (s4.samples || []).map(t =>
'<div class="card"><div class="title">🛠 '+esc(t.name)+'</div><div class="d">'+esc(t.desc || 'Tool callable')+'</div></div>'
).join('') + '<div class="card" style="text-align:center;background:transparent"><a href="/api/wevia-tool-registry.json" style="padding:8px 14px">Voir tous les '+fmt(s4.count)+' tools</a></div>';
}catch(e){ console.error(e); }
}
async function loadQdrantSample(){
const el = document.getElementById('qdrant-sample');
el.innerHTML = '<div class="loading">Chargement 50 samples Qdrant...</div>';
try{
const r = await fetch('/api/skills-explorer-api.php?action=qdrant_sample&limit=50');
const d = await r.json();
const skills = d.qdrant_skills || [];
el.innerHTML = '<div class="grid">' + skills.map(s =>
'<div class="card"><div class="title">🧠 '+esc(s.name).substring(0,60)+'<span class="badge badge-blue">'+esc(s.source||'?').substring(0,20)+'</span></div>'+
'<div class="d">'+esc(s.desc).substring(0,150)+'</div>'+
'<div class="samples">id: '+esc(s.id)+' · '+esc(s.path).substring(0,60)+'</div></div>'
).join('') + '</div>';
}catch(e){
el.innerHTML = '<div class="loading">Erreur: '+e.message+'</div>';
}
}
async function doSearch(){
const q = document.getElementById('q').value.trim();
if (!q) return;
const el = document.getElementById('search-results');
el.innerHTML = '<div class="loading">Searching Qdrant...</div>';
try{
const r = await fetch('/api/skills-explorer-api.php?action=search&q=' + encodeURIComponent(q));
const d = await r.json();
const m = d.matches || [];
const header = '<div style="margin-bottom:10px;font-size:12px;color:var(--muted)">Scanned '+fmt(d.scanned)+' skills · '+fmt(m.length)+' matches for <b style="color:var(--accent)">"'+esc(q)+'"</b></div>';
el.innerHTML = header + '<div class="grid">' + m.map(s =>
'<div class="card"><div class="title">🎯 '+esc(s.name).substring(0,60)+'</div>'+
'<div class="d">'+esc(s.desc).substring(0,200)+'</div>'+
'<div class="samples">source: '+esc(s.source)+' · '+esc(s.path).substring(0,60)+'</div></div>'
).join('') + '</div>';
}catch(e){
el.innerHTML = '<div class="loading">Erreur: '+e.message+'</div>';
}
}
loadSources();
</script>
</body></html>