feat(cloudbot-social): DOCTRINE 143 feed vivant SSE streaming reel + inter-agent conversations via /api/cloudbot-social-feed.php et /api/cloudbot-interagent.php - agents se parlent vraiment (log PG) - badge LIVE anime - zero ecrasement reconcilie v2 autre Claude

This commit is contained in:
Opus
2026-04-23 21:58:54 +02:00
parent 9b011a8976
commit 5eff1a306c

View File

@@ -194,6 +194,11 @@ main{max-width:1500px;margin:0 auto;padding:0 24px 40px;display:grid;grid-templa
/* Badge categories */
.cat-emoji{font-size:14px;line-height:1}
/* DOCTRINE 143 SSE badge */
#sse-live-badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:9px;font-weight:700;letter-spacing:.5px;color:#fff;background:#64748b;vertical-align:middle;margin-left:8px}
@keyframes flash{0%{opacity:1}50%{opacity:.3}100%{opacity:1}}
#sse-health-pulse{font-size:10px;color:var(--a2);font-weight:600}
</style>
</head>
<body>
@@ -689,6 +694,160 @@ document.addEventListener("keydown",function(e){
if(e.key==="/"&&document.activeElement.tagName!=="INPUT"){ e.preventDefault(); document.getElementById("q").focus(); }
if(e.key==="Escape"&&document.getElementById("chat-modal").classList.contains("on")){ closeModal(); }
});
// ============ DOCTRINE 143 LIVE SSE STREAMING v1 (additif) ============
var __SSE_ES = null;
var __SSE_CONN = false;
var __SSE_EVENTS = [];
function connectSSELive(){
if(__SSE_ES && __SSE_CONN)return;
try{
__SSE_ES = new EventSource("/api/cloudbot-social-feed.php");
__SSE_ES.addEventListener("hello", function(e){
__SSE_CONN = true;
try{
var d = JSON.parse(e.data);
console.log("[SSE Cloudbot] Connected", d);
var badge = document.getElementById("sse-live-badge");
if(badge){ badge.textContent = "LIVE"; badge.style.background = "#10b981"; badge.style.animation = "pulse 1.5s infinite"; }
}catch(ex){}
});
__SSE_ES.addEventListener("router_match", function(e){
try{
var d = JSON.parse(e.data);
pushSSEEvent({type:"router", msg:d.msg, ts:d.ts, pattern:d.pattern, agent:d.agent||"Router"});
}catch(ex){}
});
__SSE_ES.addEventListener("agent_msg", function(e){
try{
var d = JSON.parse(e.data);
pushSSEEvent({type:"conversation", role:d.role, msg:d.content, ts:d.ts, session:d.session, source:d.source, agent:d.agent});
}catch(ex){}
});
__SSE_ES.addEventListener("ecosystem_health", function(e){
try{
var d = JSON.parse(e.data);
var h = document.getElementById("sse-health-pulse");
if(h){ h.textContent = (d.agents_up||"-") + "/" + (d.agents_total||"-") + " agents"; h.style.animation = "flash 0.5s"; setTimeout(function(){h.style.animation=""},500);}
}catch(ex){}
});
__SSE_ES.addEventListener("ping", function(e){ /* keep alive */ });
__SSE_ES.addEventListener("bye", function(e){
__SSE_CONN = false;
if(__SSE_ES){ __SSE_ES.close(); __SSE_ES = null; }
setTimeout(connectSSELive, 2000); // auto reconnect
});
__SSE_ES.onerror = function(){
__SSE_CONN = false;
var badge = document.getElementById("sse-live-badge");
if(badge){ badge.textContent = "RECONNECT..."; badge.style.background = "#f59e0b"; }
setTimeout(function(){
if(__SSE_ES){ __SSE_ES.close(); __SSE_ES = null; }
connectSSELive();
}, 3000);
};
}catch(e){ console.warn("SSE init failed:", e); }
}
function pushSSEEvent(ev){
__SSE_EVENTS.unshift(ev);
if(__SSE_EVENTS.length > 50) __SSE_EVENTS = __SSE_EVENTS.slice(0, 50);
renderSSEFeed();
}
function renderSSEFeed(){
var feed = document.getElementById("live-feed");
if(!feed)return;
if(!__SSE_EVENTS.length){ return; }
var html = __SSE_EVENTS.slice(0, 12).map(function(ev){
var ago = timeAgo(ev.ts);
var icon = ev.type === "conversation" ? (ev.role === "user" ? "👤" : "🤖") : (ev.type === "router" ? "🎯" : "⚡");
var color = ev.type === "conversation" ? "#06d6ba" : (ev.type === "router" ? "#8b5cf6" : "#3b82f6");
var label = ev.agent || (ev.role === "user" ? "User" : "WEVIA");
var msg = (ev.msg||"").substring(0, 120);
var meta = ev.session ? "session " + ev.session : (ev.source ? "src:"+ev.source : (ev.pattern||"live"));
return '<div class="live-item" style="border-left-color:'+color+'">'+
'<div class="live-item-head">'+
'<div class="live-item-msg">'+icon+' <strong style="color:'+color+'">'+escapeHtml(label)+':</strong> '+escapeHtml(msg)+'</div>'+
'</div>'+
'<div class="live-item-meta">🕐 '+ago+' · <span style="font-family:monospace;opacity:.7">'+escapeHtml(meta)+'</span></div>'+
'</div>';
}).join("");
feed.innerHTML = html;
}
// Start SSE on page load
setTimeout(connectSSELive, 1000);
// ============ END SSE additif ============
function startCollab(){
// DOCTRINE 143 - Real inter-agent conversation via /api/cloudbot-interagent.php
var n1 = prompt("Nom agent 1 (ex: WEVIA, Ethica, WEVCODE, Blade, WEDROID, Manager, WEVAL MIND) :");
if(!n1) return;
var n2 = prompt("Nom agent 2 (different du premier) :");
if(!n2) return;
var topic = prompt("Topic de collaboration (question/sujet a discuter) :");
if(!topic) return;
var turns = prompt("Nombre de tours (2-4 recommande, max 6) :", "3");
turns = Math.min(6, Math.max(1, parseInt(turns)||3));
openInterAgentModal(n1, n2, topic, turns);
}
function openInterAgentModal(agent1, agent2, topic, turns){
var modal = document.getElementById("chat-modal");
document.getElementById("m-title").textContent = "🤝 "+agent1+" ↔ "+agent2;
document.getElementById("m-avatar").textContent = "🤝";
document.getElementById("m-avatar").style.background = "linear-gradient(135deg,#ec4899,#8b5cf6,#06d6ba)";
var chat = document.getElementById("m-chat");
chat.innerHTML = '<div class="msg sys">🤝 <strong>Conversation inter-agents en cours</strong> · '+agent1+' ↔ '+agent2+' · Topic: '+escapeHtml(topic)+' · '+turns+' tours</div>';
chat.innerHTML += '<div class="msg sys">⏳ Initialisation... (peut prendre 30-60 sec selon les APIs agents)</div>';
modal.classList.add("on");
document.getElementById("m-input").placeholder = "Conversation auto - attendez les reponses...";
document.getElementById("m-input").disabled = true;
document.getElementById("m-send").disabled = true;
fetch("/api/cloudbot-interagent.php", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({agent1: agent1, agent2: agent2, topic: topic, turns: turns})
}).then(function(r){ return r.json(); }).then(function(data){
chat.innerHTML = '<div class="msg sys">🤝 <strong>'+agent1+' ↔ '+agent2+'</strong> · Topic: '+escapeHtml(topic)+' · '+(data.turns_completed||0)+' tours</div>';
if(!data.dialogue || !data.dialogue.length){
chat.innerHTML += '<div class="msg sys" style="color:#ef4444">⚠️ Aucun dialogue (agent non trouve ou erreur API)</div>';
if(data.error) chat.innerHTML += '<div class="msg sys">ERR: '+escapeHtml(data.error)+'</div>';
document.getElementById("m-input").disabled = false;
document.getElementById("m-send").disabled = false;
return;
}
data.dialogue.forEach(function(t){
// Question de from -> to
chat.innerHTML += '<div class="msg u" style="max-width:85%"><div style="font-size:11px;font-weight:700;opacity:.9;margin-bottom:4px">🎯 '+escapeHtml(t.from)+' → '+escapeHtml(t.to)+' (tour '+t.turn+')</div>'+escapeHtml(t.message)+'</div>';
// Reponse
chat.innerHTML += '<div class="msg a"><div style="font-size:11px;font-weight:700;color:#06d6ba;margin-bottom:4px">🤖 '+escapeHtml(t.to)+' repond :</div>'+escapeHtml(t.response)+'<div class="msg-meta">via '+escapeHtml(t.provider)+' · '+t.latency_ms+'ms</div></div>';
});
chat.innerHTML += '<div class="msg sys">✅ Conversation terminee · '+(data.logged_to_db?"📝 loggee en PG (visible dans SSE feed)":"")+' · Session: '+(data.session_id||"").substring(0,30)+'</div>';
chat.scrollTop = chat.scrollHeight;
document.getElementById("m-input").disabled = false;
document.getElementById("m-send").disabled = false;
addActivity("🤝 Inter-Agent: "+agent1+" ↔ "+agent2+" sur "+topic.substring(0,30));
CONV_COUNT += data.dialogue.length;
var kc = document.getElementById("k-conv");
if(kc) kc.textContent = CONV_COUNT;
}).catch(function(e){
chat.innerHTML += '<div class="msg sys" style="color:#ef4444">⚠️ '+escapeHtml(e.message)+'</div>';
document.getElementById("m-input").disabled = false;
document.getElementById("m-send").disabled = false;
});
}
</script>
</body>