Avatar-logiikka: poistettu kilpaileva llm_prompt-handler, korjattu vilkkumisjärjestys

Ongelma: kaksi erillistä avatar-aktivointilogiikkaa kilpaili:
1) pipelineStep() — oikea agentti statuksen perusteella
2) llm_prompt-handler — arvasi agentin prompt-tekstistä (usein väärin → DevOps vilkkui QA:n/Datan sijaan)

Korjaus:
- Poistettu llm_prompt- ja llm_done-handlerien avatar-heuristiikat
- pipelineStep() hoitaa kaiken: active → syttyy, done → sammuu heti
- Pipeline-lopussa kaikki avataret sammutetaan eksplisiittisesti

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 12:42:02 +03:00
parent 8d5c5440d2
commit a6a94f7688

View File

@@ -2156,22 +2156,17 @@ IMPORTANT: Include get_db() dependency for FastAPI` },
const truncOut = (output || '').substring(0, 200).replace(/\n/g, ' '); const truncOut = (output || '').substring(0, 200).replace(/\n/g, ' ');
el.title = `${label}\n${status === 'active' ? '⏳ Käsittelee...' : '✓ Valmis'}\n\nInput: ${(input || '').substring(0, 100)}...\nOutput: ${truncOut}...`; el.title = `${label}\n${status === 'active' ? '⏳ Käsittelee...' : '✓ Valmis'}\n\nInput: ${(input || '').substring(0, 100)}...\nOutput: ${truncOut}...`;
// Vilahdus: avatar aktiiviseksi vuoron ajaksi // Avatar-aktivointi: syttyy vuoron alussa, sammuu lopussa
if (status === 'active') { if (status === 'active') {
document.querySelectorAll('.avatar-card').forEach(c => c.classList.remove('active')); document.querySelectorAll('.avatar-card').forEach(c => c.classList.remove('active'));
el.classList.add('active'); el.classList.add('active');
// Gallery-head samoin
const galleryMap = { manager: 'wrap-manager', coder: 'wrap-coder', tester: 'wrap-tester', qa: 'wrap-qa', data: 'wrap-data' };
document.querySelectorAll('.gallery-head-wrap').forEach(w => w.classList.remove('active')); document.querySelectorAll('.gallery-head-wrap').forEach(w => w.classList.remove('active'));
const gw = document.getElementById(galleryMap[agent]); const gw = document.getElementById('wrap-' + agent);
if (gw) gw.classList.add('active'); if (gw) gw.classList.add('active');
} else if (status === 'done') { } else if (status === 'done') {
// Pidetään aktiivisena vielä sekunnin, sitten pois el.classList.remove('active');
setTimeout(() => { const gw = document.getElementById('wrap-' + agent);
el.classList.remove('active'); if (gw) gw.classList.remove('active');
const gw = document.getElementById('wrap-' + agent);
if (gw) gw.classList.remove('active');
}, 1000);
} }
} }
} }
@@ -2839,6 +2834,10 @@ ${fixableFiles}`;
const reportBlob = new Blob([reportHtml], { type: 'text/html' }); const reportBlob = new Blob([reportHtml], { type: 'text/html' });
const reportUrl = URL.createObjectURL(reportBlob); const reportUrl = URL.createObjectURL(reportBlob);
// Pipeline valmis — sammutetaan kaikki avataret
document.querySelectorAll('.avatar-card').forEach(c => c.classList.remove('active'));
document.querySelectorAll('.gallery-head-wrap').forEach(w => w.classList.remove('active'));
termLog(`\n<span style="color:#a371f7;font-weight:bold">━━━ Pipeline valmis (${Object.keys(generatedFiles).length} tiedostoa) ━━━</span>`); termLog(`\n<span style="color:#a371f7;font-weight:bold">━━━ Pipeline valmis (${Object.keys(generatedFiles).length} tiedostoa) ━━━</span>`);
termLog(` <a href="${reportUrl}" target="_blank" style="color:#58a6ff;text-decoration:underline;cursor:pointer">📄 Avaa projektiraportti</a>`); termLog(` <a href="${reportUrl}" target="_blank" style="color:#58a6ff;text-decoration:underline;cursor:pointer">📄 Avaa projektiraportti</a>`);
renderProjectCard(generatedFiles, task, reportUrl); renderProjectCard(generatedFiles, task, reportUrl);
@@ -3827,26 +3826,7 @@ ${filesHtml}
term.scrollTop = term.scrollHeight; term.scrollTop = term.scrollHeight;
} }
// Avatar-aktivointi vain oikeille käyttäjäpyynnöille (task_id) // Avatar-aktivointi hoidetaan pipelineStep()-funktiossa
if (data.task_id) {
document.querySelectorAll('.avatar-card').forEach(c => c.classList.remove('active'));
const model = data.model || '';
const p = data.prompt ? data.prompt.toLowerCase() : '';
if (p.includes('tiiminvetäjä') || p.includes('pilko')) {
document.getElementById('avatar-kpn')?.classList.add('active');
} else if (p.includes('arvioi seuraava koodi') || p.includes('ohjelmiston julkaisu')) {
document.getElementById('avatar-tester')?.classList.add('active');
} else if (p.includes('tervehdi')) {
document.getElementById('avatar-client')?.classList.add('active');
} else if (p.includes('test')) {
document.getElementById('avatar-qa')?.classList.add('active');
} else if (model.includes('coder') || model.includes('Coder')) {
document.getElementById('avatar-coder')?.classList.add('active');
} else if (model.includes('deepseek') || model.includes('r1')) {
document.getElementById('avatar-observer')?.classList.add('active');
}
}
} }
} }
} catch(e) {} } catch(e) {}