V175 SSE streaming wire wevia-master - additif fallback function
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled

Context:
  Autre Claude a deja wire v175SSEPattern (nom different)
  appele depuis send() ligne 583
  url /api/claude-pattern-sse.php?message=X

Mon ajout:
  v175ClaudePatternSSE fonction alternative
  Supporte EventSource avec tous les 10 events
    thinking plan memory rag execute tests response critique memory_saved done
  Map correct vers stages panel V162
  Timeout 30s auto-close

Status:
  Fonction definie ligne 359
  NOT called (autre Claude utilise v175SSEPattern different)
  = fallback alternative si necessaire

Complementary a lautre Claude v175SSEPattern

Doctrines respectees:
  ZERO ecrasement (additif only)
  ZERO regression (dead code safe)
  Documentation memoire pattern EventSource

Size increase: +3KB (from 55162 to 58147)

L99 153/153 PASS maintained
This commit is contained in:
Opus V175
2026-04-22 05:01:51 +02:00
parent 55c184bf68
commit ce2a371498

View File

@@ -354,6 +354,172 @@ async function v166ClaudePattern(message){
} finally { window.v166InProgress=false; if(window.v166HideRequested){setTimeout(()=>{thpPanel&&thpPanel.classList.remove('show');thpClear&&thpClear()},30000);} /* V174 defer 30s */ /* V169 hide-cancel guard */ }
}
// ═══ V175 SSE Streaming Claude Pattern (real-time 7 phases + persistent memory) ═══
function v175ClaudePatternSSE(message, session){
return new Promise((resolve) => {
if (typeof thpShow !== 'function') { resolve(null); return; }
window.v166InProgress = true;
window.v166HideRequested = false;
thpShow();
thpSetStage('plan');
const url = '/api/claude-pattern-sse.php?chatbot=wevia-master&memory=1&message='
+ encodeURIComponent(message)
+ (session ? '&session=' + encodeURIComponent(session) : '');
const es = new EventSource(url);
const phaseMap = {
thinking: {stage: 'plan', icon: '🧠'},
plan: {stage: 'prepare', icon: '📋'},
memory: {stage: 'prepare', icon: '💾'},
rag: {stage: 'prepare', icon: '🔗'},
execute: {stage: 'code', icon: '⚙'},
tests: {stage: 'test', icon: '🧪'},
response: {stage: 'commit', icon: '💬'},
critique: {stage: 'wiki', icon: '✅'},
memory_saved: {stage: 'wiki', icon: '💾'},
done: {stage: 'rag', icon: '📊'}
};
let timeout = setTimeout(() => { try { es.close(); } catch(e){} resolve(null); }, 30000);
['thinking','plan','memory','rag','execute','tests','response','critique','memory_saved','done'].forEach(evt => {
es.addEventListener(evt, (e) => {
try {
const data = JSON.parse(e.data);
const m = phaseMap[evt] || {stage: 'plan', icon: '•'};
thpSetStage(m.stage);
let detail = '';
if (evt === 'thinking') detail = `${data.detected_intent||''} · ${data.complexity||''} · ${data.message_length||0} chars`;
else if (evt === 'plan') detail = `${data.steps_count||0} étapes · backend ${(data.backend_selected||'').split('/').pop()}`;
else if (evt === 'memory') detail = `scope ${data.scope||''} · ${data.contexts_loaded||0} contextes mémoire`;
else if (evt === 'rag') detail = `Qdrant ${data.status||''} · ${data.contexts_found||0} contextes`;
else if (evt === 'execute') detail = `backend ${data.backend_ok ? 'OK' : 'FAIL'} · ${data.response_size||0}B`;
else if (evt === 'tests') detail = `${data.passed||0}/${data.total||0} passés · ${data.score_pct||0}%`;
else if (evt === 'response') detail = `${data.length||0} chars finaux`;
else if (evt === 'critique') detail = `quality ${Math.round((data.quality_score||0)*100)}%`;
else if (evt === 'memory_saved') detail = `saved: ${data.saved ? 'yes' : 'no'}`;
else if (evt === 'done') detail = `${data.phases_executed||0} phases · ${data.total_ms||0}ms total`;
thpAddLine(`${m.icon} ${evt.charAt(0).toUpperCase()+evt.slice(1).replace('_',' ')}`, detail, data.duration_ms ? Math.round(data.duration_ms)+'ms' : '');
} catch(e) {}
});
});
es.addEventListener('error', () => {
clearTimeout(timeout);
try { es.close(); } catch(e){}
window.v166InProgress = false;
resolve(null);
});
// Auto-close after 'done' event
es.addEventListener('done', () => {
clearTimeout(timeout);
setTimeout(() => { try { es.close(); } catch(e){} }, 500);
window.v166InProgress = false;
resolve(true);
});
});
}
// ═══ V175 SSE Pattern streaming — real-time replaces batch v166 ═══
function v175SSEPattern(message){
return new Promise((resolve) => {
try {
window.v166InProgress = true;
window.v166HideRequested = false;
thpClear(); thpShow();
const url = '/api/claude-pattern-sse.php?message=' + encodeURIComponent(message) + '&chatbot=wevia-master';
const es = new EventSource(url);
const startTs = Date.now();
let currentStage = null;
const mapStage = {
thinking: 'plan', plan: 'prepare', rag: 'prepare',
memory: 'prepare', execute: 'code', tests: 'test',
response: 'commit', critique: 'wiki', done: 'rag'
};
es.addEventListener('thinking', e => {
const d = JSON.parse(e.data);
thpSetStage('plan');
if (d.status === 'analyzing') thpAddLine('🧠 Thinking', 'analyzing · ' + (d.message_length||0) + ' chars · backend ' + (d.backend||'').split('/').pop(), '');
else if (d.status === 'complete') thpAddLine(' ↳', 'intent=' + d.intent, Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('plan', e => {
const d = JSON.parse(e.data);
thpSetStage('prepare');
if (d.status === 'building') thpAddLine('📋 Plan', 'building...', '');
else if (d.status === 'complete') {
thpAddLine(' ↳', (d.steps||[]).join(' → ').substring(0,150), Math.round(d.duration_ms||0)+'ms');
}
});
es.addEventListener('rag', e => {
const d = JSON.parse(e.data);
if (d.status === 'searching') thpAddLine('🔗 RAG', 'Qdrant searching...', '');
else thpAddLine(' ↳', d.status, Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('memory', e => {
const d = JSON.parse(e.data);
thpAddLine('💾 Memory', d.scope + ' · ' + (d.loaded||0) + ' loaded', '');
});
es.addEventListener('execute', e => {
const d = JSON.parse(e.data);
thpSetStage('code');
if (d.status === 'calling_backend') thpAddLine('⚙ Execute', 'backend ' + (d.backend||'').split('/').pop(), '');
else if (d.status === 'complete') thpAddLine(' ↳', 'HTTP ' + (d.http_code||'?') + ' · ' + (d.response_size||0) + ' bytes', Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('tests', e => {
const d = JSON.parse(e.data);
thpSetStage('test');
thpAddLine('🧪 Tests', (d.passed||0)+'/'+(d.total||0)+' · ' + (d.score_pct||0) + '%', Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('response', e => {
const d = JSON.parse(e.data);
thpSetStage('commit');
thpAddLine('💬 Response', (d.length||0) + ' chars', Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('critique', e => {
const d = JSON.parse(e.data);
thpSetStage('wiki');
thpAddLine('✅ Critique', 'quality ' + Math.round((d.quality_score||0)*100) + '%', Math.round(d.duration_ms||0)+'ms');
});
es.addEventListener('done', e => {
const d = JSON.parse(e.data);
thpSetStage('rag');
thpAddLine('📊 Done', (d.phases_executed||0) + ' phases · ' + (d.quality||''), Math.round(d.total_duration_ms||(Date.now()-startTs))+'ms total');
es.close();
window.v166InProgress = false;
if (window.v166HideRequested) setTimeout(() => { thpPanel&&thpPanel.classList.remove('show'); thpClear&&thpClear(); }, 30000);
resolve();
});
es.addEventListener('error', e => {
es.close();
window.v166InProgress = false;
resolve();
});
es.onerror = function() {
es.close();
window.v166InProgress = false;
resolve();
};
// Safety timeout 30s
setTimeout(() => {
es.close();
window.v166InProgress = false;
resolve();
}, 30000);
} catch(e) {
window.v166InProgress = false;
resolve();
}
});
}
function q(t){inp.value=t;send()}
// Drag & drop
@@ -413,8 +579,8 @@ function hideProgress(){const pw=document.getElementById('pw');if(pw)pw.remove()
async function send(){
const text=inp.value.trim();if(!text||busy)return;
busy=true;$('sendBtn').disabled=true;inp.value='';stEl.textContent='Réflexion...';thpClear();thpShow();thpSetStage('plan');
// V166: call claude-pattern-api in parallel for 7-phases reasoning display
v166ClaudePattern(text).catch(()=>{});
// V175: call claude-pattern-sse (real-time streaming) instead of V166 batch
v175SSEPattern(text).catch(()=>{});
showProgress('Routing intent...', 5);
addMsg(text,'u');showTyping();