feat(multichat): wave 311 WEVIA Master pivot + KB-augment + sovereign fallback

- ai-multichat.html: WEVIA Master ajoute en provider PIVOT (port 4000 sovereign-api)
- ai-multichat.html: toggle KB+ (Qdrant context injection)
- ai-multichat.html: toggle Fallback (sovereign-api si Chrome CDP fail)
- ai-multichat.html: auto-select WEVIA on load (patron par defaut)
- ai-multichat.html: PIVOT badge violet sur WEVIA Master card
- api/cdp-broadcast.php v2: queryWeviaKB() Qdrant scroll wevia_brain_knowledge + 3 fallback collections
- api/cdp-broadcast.php v2: callWeviaMaster() OpenAI-compatible /v1/chat/completions Cerebras-fast 364ms avg
- api/cdp-broadcast.php v2: auto-fallback CDP fail -> sovereign avec persona prompt provider
- Test verified: WEVIA solo 591ms / Mistral CDP fail -> fallback Cerebras 6522ms (cloudflare bot block)
- Doctrine 311: WEVIA Master = patron, Chrome CDP = optional ground-truth
- KB integration: 15+ Qdrant collections (wevia_brain_knowledge, kb_consulting_strategy, kb_bpmn_patterns, kb_dmaic_playbooks, etc)
This commit is contained in:
Opus
2026-04-24 12:19:15 +02:00
parent 0253a72bbb
commit 11d9e0fbbd

View File

@@ -138,6 +138,8 @@ body{background:var(--bg);color:var(--ink);font-family:var(--font-sans);min-heig
<span><span class="k">Enter</span> Send</span>
<span><span class="k">Shift+Enter</span> Newline</span>
<span id="selected-count">0 providers selected</span>
<label style="display:flex;align-items:center;gap:5px;cursor:pointer"><input type="checkbox" id="opt-kb" checked style="cursor:pointer"> <span class="k">KB+</span> WEVIA augment</label>
<label style="display:flex;align-items:center;gap:5px;cursor:pointer"><input type="checkbox" id="opt-fallback" checked style="cursor:pointer"> <span class="k"></span> Fallback sovereign</label>
</div>
</div>
</main>
@@ -147,6 +149,7 @@ body{background:var(--bg);color:var(--ink);font-family:var(--font-sans);min-heig
<script>
// Provider metadata
const PROVIDERS = [
{ slug: 'wevia', name: 'WEVIA Master', icon: 'W', port: 4000, url: 'sovereign-api', is_master: true },
{ slug: 'openai', name: 'ChatGPT', icon: 'C', port: 9222, url: 'https://chat.openai.com/' },
{ slug: 'anthropic', name: 'Claude.ai', icon: 'A', port: 9223, url: 'https://claude.ai/' },
{ slug: 'google', name: 'Gemini', icon: 'G', port: 9224, url: 'https://gemini.google.com/' },
@@ -164,12 +167,12 @@ let cdpStatus = {};
function buildProviders() {
const container = document.getElementById('providers-list');
container.innerHTML = PROVIDERS.map(p => {
const running = cdpStatus[p.slug]?.cdp_listening;
const running = p.is_master ? true : cdpStatus[p.slug]?.cdp_listening;
return `<div class="provider-card${selected.has(p.slug) ? ' selected' : ''}${running === false ? ' offline' : ''}" onclick="toggleProvider('${p.slug}')" data-slug="${p.slug}">
<div class="pc-check"></div>
<div class="pc-icon">${p.icon}</div>
<div class="pc-info">
<div class="pc-name">${p.name}</div>
<div class="pc-name">${p.name}${p.is_master ? ' <span style="color:var(--violet);font-size:9px;letter-spacing:.15em;background:rgba(167,139,250,.15);padding:2px 5px;border-radius:2px;margin-left:4px">PIVOT</span>' : ''}</div>
<div class="pc-status">
<span class="pc-dot ${running ? 'running' : 'offline'}"></span>
<span>${running ? 'CDP :' + p.port : 'offline'}</span>
@@ -198,7 +201,7 @@ function toggleProvider(slug) {
function selectAll(on) {
PROVIDERS.forEach(p => {
const running = cdpStatus[p.slug]?.cdp_listening;
const running = p.is_master ? true : cdpStatus[p.slug]?.cdp_listening;
if (!running) return;
if (on) selected.add(p.slug);
else selected.delete(p.slug);
@@ -272,7 +275,7 @@ async function sendBroadcast() {
const r = await fetch('/api/cdp-broadcast.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, providers: Array.from(selected) })
body: JSON.stringify({ message, providers: Array.from(selected), augment_with_kb: document.getElementById('opt-kb').checked, fallback_sovereign: document.getElementById('opt-fallback').checked })
});
const d = await r.json();
@@ -335,7 +338,10 @@ ta.addEventListener('keydown', (e) => {
// Init
refreshStatus();
setInterval(refreshStatus, 10000); // poll every 10s
setInterval(refreshStatus, 10000);
// Auto-select WEVIA Master on load (it's the patron)
setTimeout(() => { selected.add('wevia'); buildProviders(); }, 500); // poll every 10s
</script>
</body>
</html>