From 6b756e2e8322cb6d3d529b9b658978daa6b9a82d Mon Sep 17 00:00:00 2001 From: jaakko Date: Tue, 7 Apr 2026 08:24:29 +0300 Subject: [PATCH] =?UTF-8?q?Prompt-editori=20modal:=20avain-arvo-parit,=20e?= =?UTF-8?q?ditoitavat=20kent=C3=A4t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Klikkaa agenttia → 'Näytä viimeisin prompti' → modal-ikkuna jossa prompti on pilkottu rakenteellisiin kenttiin (Project, CONSTRAINTS, EXAMPLE jne.). Editoitavat kentät sinisellä ✏️, lukitut harmaalla 🔒. 'Aja uudelleen' kokoaa promptin kentistä ja ajaa sen. Co-Authored-By: Claude Opus 4.6 (1M context) --- network-poc/static/index.html | 127 ++++++++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 22 deletions(-) diff --git a/network-poc/static/index.html b/network-poc/static/index.html index 85a551a..3f75b4e 100644 --- a/network-poc/static/index.html +++ b/network-poc/static/index.html @@ -1076,12 +1076,8 @@ - @@ -1260,14 +1256,7 @@ if (selectedAgents.size === 1) { const agent = [...selectedAgents][0]; const lastStep = [...pipelineSteps].reverse().find(s => s.agent === agent && s.status === 'done' && s.input); - if (lastStep) { - lastPromptDiv.style.display = 'block'; - lastPromptText.value = lastStep.input; - lastPromptText.dataset.agent = agent; - lastPromptText.dataset.label = lastStep.label; - } else { - lastPromptDiv.style.display = 'none'; - } + lastPromptDiv.style.display = lastStep ? 'block' : 'none'; } else { lastPromptDiv.style.display = 'none'; } @@ -1327,15 +1316,94 @@ saved._t = setTimeout(() => saved.style.opacity = '0', 1500); }); - // "Aja uudelleen" -nappi: ajaa editoidun promptin samalla agentilla - document.getElementById('agent-rerun-btn')?.addEventListener('click', () => { - const textEl = document.getElementById('agent-last-prompt-text'); - const prompt = textEl?.value?.trim(); - if (!prompt) return; - const agent = textEl.dataset.agent; - const model = agentPrompts[agent]?.model || 'qwen-coder'; - termLog(`$ ↻ Aja uudelleen: ${esc(agent)} — ${esc(prompt.substring(0, 60))}...`); + // Prompt-editori modal + let modalAgent = null; + let modalPromptParts = []; + + function parsePromptToFields(prompt) { + // Pilkotaan prompti avain-arvo-pareiksi + const fields = []; + const lines = prompt.split('\n'); + let currentKey = null; + let currentVal = []; + + for (const line of lines) { + // Tunnistetaan avain: KEYWORD: tai KEYWORD — tai rivin alku isolla + const keyMatch = line.match(/^(Project|CONSTRAINTS|EXAMPLE|RULES|IMPORTANT|Check|Files in project|Main app|Already written files|PROJECT CODE|Current code|Review feedback|Feedback)[\s:—]*(.*)/i); + if (keyMatch) { + if (currentKey) fields.push({ key: currentKey, value: currentVal.join('\n').trim(), editable: isEditable(currentKey) }); + currentKey = keyMatch[1]; + currentVal = keyMatch[2] ? [keyMatch[2]] : []; + } else { + currentVal.push(line); + } + } + if (currentKey) fields.push({ key: currentKey, value: currentVal.join('\n').trim(), editable: isEditable(currentKey) }); + + // Jos ei löytynyt rakenteellisia avaimia, näytetään koko prompti yhtenä + if (fields.length === 0) fields.push({ key: 'Prompti', value: prompt, editable: true }); + return fields; + } + + function isEditable(key) { + const editableKeys = ['Project', 'CONSTRAINTS', 'IMPORTANT', 'Feedback', 'Review feedback']; + return editableKeys.some(k => key.toLowerCase().includes(k.toLowerCase())); + } + + function openPromptModal(agent, label, prompt) { + modalAgent = agent; + modalPromptParts = parsePromptToFields(prompt); + const modal = document.getElementById('prompt-modal'); + const title = document.getElementById('prompt-modal-title'); + const fields = document.getElementById('prompt-modal-fields'); + + const agentNames = { manager: 'Manageri', coder: 'Koodari', tester: 'DevOps', qa: 'QA', data: 'Data' }; + title.textContent = `${agentNames[agent] || agent} — ${label}`; + + fields.innerHTML = modalPromptParts.map((f, i) => ` +
+
+ ${f.editable ? '✏️' : '🔒'} ${f.key} +
+ +
+ `).join(''); + + modal.style.display = 'block'; + // Sulje klikatessa taustaa + modal.onclick = (e) => { if (e.target === modal) closePromptModal(); }; + } + window.openPromptModal = openPromptModal; + + function closePromptModal() { + document.getElementById('prompt-modal').style.display = 'none'; + } + window.closePromptModal = closePromptModal; + + function rerunFromModal() { + // Kootaan prompti takaisin kentistä + const fields = document.getElementById('prompt-modal-fields'); + const textareas = fields.querySelectorAll('textarea'); + const parts = []; + textareas.forEach((ta, i) => { + const key = modalPromptParts[i]?.key || ''; + const val = ta.value.trim(); + if (val) parts.push(`${key}: ${val}`); + }); + const prompt = parts.join('\n\n'); + const model = agentPrompts[modalAgent]?.model || 'qwen-coder'; + closePromptModal(); + termLog(`$ ↻ Aja uudelleen: ${esc(modalAgent)}`); kpnRun(model, prompt); + } + window.rerunFromModal = rerunFromModal; + + // "Näytä prompti" -nappi avaa modalin + document.getElementById('agent-open-modal-btn')?.addEventListener('click', () => { + if (selectedAgents.size !== 1) return; + const agent = [...selectedAgents][0]; + const lastStep = [...pipelineSteps].reverse().find(s => s.agent === agent && s.status === 'done' && s.input); + if (lastStep) openPromptModal(agent, lastStep.label, lastStep.input); }); function checkAgentConfusion() { @@ -4112,5 +4180,20 @@ ${generatedFiles['Dockerfile'] || '(puuttuu)'}`; return html; } + + +