Viestien säätöä
This commit is contained in:
@@ -1107,7 +1107,19 @@
|
||||
<script type="module">
|
||||
import init, { start_agent_node, set_gpu_load, set_auto_tasks } from './pkg/node.js';
|
||||
|
||||
// Päävälilehtien vaihto
|
||||
// HTML-escape kaikelle käyttäjä-/backendidatalle joka menee innerHTML:ään
|
||||
function esc(str) {
|
||||
if (!str) return '';
|
||||
return String(str).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
||||
}
|
||||
// Poistaa system-promptin näkyvästä prompt-tekstistä (agents-pipeline lisää sen alkuun)
|
||||
function stripSystemPrompt(prompt) {
|
||||
if (!prompt) return '';
|
||||
// Poistetaan kaikki ennen viimeistä kappaletta (system + agent promptit erotettu \n\n:llä)
|
||||
const parts = prompt.split('\n\n');
|
||||
return parts[parts.length - 1] || prompt;
|
||||
}
|
||||
|
||||
// Agenttien system promptit
|
||||
const agentPrompts = {
|
||||
client: { name: 'Asiakas — Projektin vaatimukset', model: 'user-input', default: 'Kirjoita tähän asiakkaan toiveet ja projektin vaatimukset. Orkestraattori (Manageri) purkaa ja delegoi nämä työt asiantuntijoille.' },
|
||||
@@ -1736,7 +1748,7 @@
|
||||
const tokGen = data.tokens_generated || 0;
|
||||
termLog(` <span style="color:#3fb950">✓</span> <span style="color:#58a6ff">${data.model || model}</span> <span style="color:#8b949e">(${tokGen} tok)</span>`);
|
||||
if (!silent) {
|
||||
termLog(` ${response.replace(/</g,'<').replace(/\n/g,'\n ')}`, '#c9d1d9');
|
||||
termLog(` ${esc(response).replace(/\n/g,'\n ')}`, '#c9d1d9');
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
@@ -1775,7 +1787,7 @@
|
||||
}
|
||||
|
||||
function termExec(cmd) {
|
||||
termLog(`<span class="terminal-prompt">$</span> ${cmd.replace(/</g,'<')}`);
|
||||
termLog(`<span class="terminal-prompt">$</span> ${esc(cmd)}`);
|
||||
termHistory.unshift(cmd);
|
||||
termHistIdx = -1;
|
||||
|
||||
@@ -1919,7 +1931,7 @@
|
||||
const cpt = parseFloat((r.chars_per_token || 0).toFixed(2));
|
||||
const cptColor = cpt >= 4 ? "#3fb950" : cpt >= 3 ? "#d29922" : "#f85149";
|
||||
const renderTokens = (tokens) => (tokens || []).map(t =>
|
||||
`<span class="tok tok-en">${t.replace(/</g,'<')}</span>`
|
||||
`<span class="tok tok-en">${esc(t)}</span>`
|
||||
).join('');
|
||||
const tokHtml = renderTokens(r.tokens);
|
||||
const detailId = 'stok-' + Date.now();
|
||||
@@ -1934,7 +1946,7 @@
|
||||
<span style="color:#8b949e;font-size:13px">${typeof ms === 'number' ? ms.toFixed(2) : ms}ms</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size:14px;color:#79b8ff;margin-bottom:6px">"${r.text || ''}"</div>
|
||||
<div style="font-size:14px;color:#79b8ff;margin-bottom:6px">"${esc(r.text)}"</div>
|
||||
<div style="font-size:14px;display:flex;gap:16px">
|
||||
<span style="color:#8b949e">${r.char_count || 0} merkkiä</span>
|
||||
<span style="color:#8b949e">${r.word_count || 0} sanaa</span>
|
||||
@@ -1957,8 +1969,8 @@
|
||||
msgDiv.className = 'chat-msg';
|
||||
msgDiv.innerHTML = `<span class="chat-prompt">Tokenisoidaan...</span>
|
||||
<div style="font-size:12px;color:#8b949e">
|
||||
<div><strong style="color:#58a6ff">EN</strong> "${data.en}"</div>
|
||||
<div><strong style="color:#d29922">FI</strong> "${data.fi}"</div>
|
||||
<div><strong style="color:#58a6ff">EN</strong> "${esc(data.en)}"</div>
|
||||
<div><strong style="color:#d29922">FI</strong> "${esc(data.fi)}"</div>
|
||||
</div>`;
|
||||
chatBox.appendChild(msgDiv);
|
||||
if (chatBox.children.length > 5) chatBox.removeChild(chatBox.firstChild);
|
||||
@@ -1997,7 +2009,7 @@
|
||||
|
||||
// Tokenilistat renderöitäväksi
|
||||
const renderTokens = (tokens, cls) => (tokens || []).map(t =>
|
||||
`<span class="tok ${cls}">${t.replace(/</g,'<')}</span>`
|
||||
`<span class="tok ${cls}">${esc(t)}</span>`
|
||||
).join('');
|
||||
const enTokHtml = renderTokens(en.tokens, 'tok-en');
|
||||
const fiTokHtml = renderTokens(fi.tokens, 'tok-fi');
|
||||
@@ -2013,13 +2025,13 @@
|
||||
</div>
|
||||
<div style="font-size:14px;display:grid;grid-template-columns:32px 1fr auto auto auto;gap:6px 10px;align-items:baseline">
|
||||
<strong style="color:#58a6ff">EN</strong>
|
||||
<span style="color:#79b8ff">"${en.text || ''}"</span>
|
||||
<span style="color:#79b8ff">"${esc(en.text)}"</span>
|
||||
<span style="color:#8b949e">${en.char_count} m</span>
|
||||
<span style="color:var(--accent-color);font-weight:600">${en.token_count} tok</span>
|
||||
<span style="color:${cptColor(enCpt)};font-weight:600">${enCpt} m/t</span>
|
||||
|
||||
<strong style="color:#d29922">FI</strong>
|
||||
<span style="color:#e3b341">"${fi.text || ''}"</span>
|
||||
<span style="color:#e3b341">"${esc(fi.text)}"</span>
|
||||
<span style="color:#8b949e">${fi.char_count} m</span>
|
||||
<span style="color:var(--accent-color);font-weight:600">${fi.token_count} tok</span>
|
||||
<span style="color:${cptColor(fiCpt)};font-weight:600">${fiCpt} m/t</span>
|
||||
@@ -2084,10 +2096,10 @@
|
||||
<span style="color:#8b949e;font-size:12px">${typeof durMs === 'number' ? durMs.toFixed(0) : durMs}ms | ${tokS} tok/s</span>
|
||||
</div>
|
||||
<div style="font-size:13px;color:#8b949e;margin-bottom:6px">
|
||||
Prompt: <span style="color:#d29922">"${data.prompt || ''}"</span>
|
||||
Prompt: <span style="color:#d29922">"${esc(stripSystemPrompt(data.prompt))}"</span>
|
||||
</div>
|
||||
<div style="font-size:14px;color:var(--text-color);line-height:1.5;${(model.includes('Coder') || (data.response||'').includes('def ')) ? 'font-family:Courier New,monospace;background:#010409;padding:10px;border-radius:4px;white-space:pre-wrap;font-size:12px' : ''}">
|
||||
${(data.response || '<em>tyhjä vastaus</em>').replace(/</g, '<').replace(/>/g, '>')}
|
||||
${data.response ? esc(data.response) : '<em>tyhjä vastaus</em>'}
|
||||
</div>
|
||||
<div style="margin-top:8px;font-size:12px;color:#8b949e">
|
||||
${tokGen} tokenia generoitu | malli ladattu: ${typeof loadMs === 'number' ? loadMs.toFixed(0) : loadMs}ms
|
||||
@@ -2151,7 +2163,7 @@
|
||||
<span style="color:#a371f7;font-weight:600">${model}</span>
|
||||
<span class="stream-counter" style="color:var(--accent-color);font-size:12px">0 tok</span>
|
||||
</div>
|
||||
<div style="font-size:13px;color:#8b949e;margin-bottom:4px">Prompt: "${data.prompt || ''}"</div>
|
||||
<div style="font-size:13px;color:#8b949e;margin-bottom:4px">Prompt: "${esc(stripSystemPrompt(data.prompt))}"</div>
|
||||
<div class="stream-text" style="font-size:14px;color:var(--text-color);line-height:1.5;${isCoder ? 'font-family:Courier New,monospace;background:#010409;padding:8px;border-radius:4px;white-space:pre-wrap;font-size:12px;color:#3fb950' : ''}"></div>
|
||||
<div style="margin-top:6px;font-size:11px;color:#d29922">
|
||||
<span class="spinner" style="display:inline-block;animation:spin 1s linear infinite">◠</span> Generating...
|
||||
@@ -2175,7 +2187,7 @@
|
||||
const term = document.getElementById('agent-terminal');
|
||||
if (term) {
|
||||
const model = data.model || 'llm';
|
||||
const promptShort = (data.prompt || '').substring(0, 50).replace(/</g,'<');
|
||||
const promptShort = esc(stripSystemPrompt(data.prompt)).substring(0, 50);
|
||||
const div = document.createElement('div');
|
||||
div.className = 'terminal-line';
|
||||
div.innerHTML = `<span class="terminal-prompt">$</span> kpn run ${model} <span style="color:#8b949e">"${promptShort}"</span>`;
|
||||
@@ -2365,7 +2377,7 @@
|
||||
const tokGen = data.tokens_generated || 0;
|
||||
const durMs = data.duration_ms || 0;
|
||||
const tokS = data.tokens_per_sec || 0;
|
||||
const response = (data.response || '').replace(/</g, '<').replace(/>/g, '>');
|
||||
const response = esc(data.response);
|
||||
|
||||
codeMetrics.tasks++;
|
||||
codeMetrics.tokens += tokGen;
|
||||
@@ -2386,7 +2398,7 @@
|
||||
const card = document.createElement('div');
|
||||
card.className = 'code-task-card';
|
||||
card.innerHTML = `
|
||||
<div class="prompt">${data.prompt || ''}</div>
|
||||
<div class="prompt">${esc(stripSystemPrompt(data.prompt))}</div>
|
||||
<div class="code-output">${highlightPython(response)}</div>
|
||||
<div class="meta">
|
||||
${model} · ${tokGen} tokenia · ${typeof durMs === 'number' ? durMs.toFixed(0) : durMs}ms · ${tokS} tok/s
|
||||
@@ -2440,7 +2452,14 @@
|
||||
if (msg.includes('[Coder]') && msg.includes('model') && msg.includes('löytyi')) { setStep('step-model', 'done', 'cache'); }
|
||||
if (msg.includes('[Coder]') && msg.includes('model') && msg.includes('tallennettu')) { setStep('step-model', 'done', '100%'); }
|
||||
if (msg.includes('[Coder]') && msg.includes('Rakennetaan')) { setStep('step-build', 'active'); }
|
||||
if (msg.includes('[Coder]') && msg.includes('Malli ladattu')) { setStep('step-build', 'done'); setStep('step-ready', 'done'); }
|
||||
if (msg.includes('[Coder]') && msg.includes('Malli ladattu')) {
|
||||
// Malli on valmis — merkataan kaikki vaiheet valmiiksi (myös cache-hitillä)
|
||||
setStep('step-wasm', 'done');
|
||||
setStep('step-tokenizer', 'done');
|
||||
setStep('step-model', 'done', 'cache');
|
||||
setStep('step-build', 'done');
|
||||
setStep('step-ready', 'done');
|
||||
}
|
||||
if (msg.includes('[Coder]') && msg.includes('Syöte:')) {
|
||||
// Pipeline piiloon kun generointi alkaa
|
||||
setTimeout(() => { document.getElementById('code-pipeline').style.display = 'none'; }, 1000);
|
||||
|
||||
Reference in New Issue
Block a user