diff --git a/network-poc/static/index.html b/network-poc/static/index.html index 2e93435..df19615 100644 --- a/network-poc/static/index.html +++ b/network-poc/static/index.html @@ -1751,8 +1751,15 @@ // Lähettää promptin mallille ja palauttaa vastauksen (tai null virhetilanteessa) async function kpnRun(model, prompt, silent) { - termLog(` → ${model} käsittelee...`, '#8b949e'); const taskId = crypto.randomUUID(); + // Yksittäinen status-rivi jota päivitetään läpi pyynnön elinkaaren + const statusDiv = document.createElement('div'); + statusDiv.className = 'terminal-line'; + statusDiv.id = 'status-' + taskId; + statusDiv.innerHTML = ` ${model} käsittelee...`; + termPanel.appendChild(statusDiv); + termPanel.scrollTop = termPanel.scrollHeight; + try { const agent = Object.values(agentPrompts).find(a => a.model === model); const parts = []; @@ -1780,13 +1787,15 @@ if (!res.ok) { const errText = await res.text().catch(() => res.statusText); - termLog(` ✗ ${errText}`, '#f85149'); + statusDiv.innerHTML = ` ✗ ${esc(errText)}`; return null; } const data = await res.json(); const response = (data.response || '').trim(); const tokGen = data.tokens_generated || 0; - termLog(` ${data.model || model} (${tokGen} tok)`); + const durS = data.duration_ms ? (data.duration_ms / 1000).toFixed(1) + 's' : ''; + const tokS = data.tokens_per_sec ? data.tokens_per_sec.toFixed(1) + ' tok/s' : ''; + statusDiv.innerHTML = ` ${esc(data.model || model)} ${tokGen} tok · ${durS} · ${tokS}`; if (!silent) { // Kompakti yksirivinen esikatselu — klikkaa/hover laajentaa const firstLine = response.split('\n').find(l => l.trim()) || response; @@ -1800,7 +1809,7 @@ } return response; } catch (e) { - termLog(` ✗ ${e.message}`, '#f85149'); + statusDiv.innerHTML = ` ✗ ${esc(e.message)}`; return null; } finally { if (activeStreams[taskId]) { @@ -2462,24 +2471,16 @@ } } } else if (data.type === "task_routed") { - const term = document.getElementById('agent-terminal'); const isQueued = data.status === 'queued'; - const color = isQueued ? '#d29922' : '#58a6ff'; + const color = isQueued ? '#d29922' : '#8b949e'; const icon = isQueued ? '⏳' : '→'; const msg = esc(data.message || ''); - // Agents-terminaali - if (term && data.task_id && activeStreams[data.task_id]) { - const div = document.createElement('div'); - div.className = 'terminal-line'; - div.style.color = color; - div.innerHTML = ` ${icon} ${msg}`; - if (isQueued) div.id = 'routing-' + data.task_id; - // Päivitetään olemassaoleva jonorivi jos löytyy - const existing = document.getElementById('routing-' + data.task_id); - if (existing) { existing.innerHTML = ` ${icon} ${msg}`; existing.style.color = color; } - else term.appendChild(div); - term.scrollTop = term.scrollHeight; + // Päivitetään olemassaoleva status-rivi (kpnRun luo sen) + const statusDiv = document.getElementById('status-' + data.task_id); + if (statusDiv) { + statusDiv.innerHTML = ` ${icon} ${msg}${isQueued ? '' : ' '}`; + termPanel.scrollTop = termPanel.scrollHeight; } // Codelab-loading-teksti