Paranneltu project-pipelinen promptit ja tiedostoparsinta

Managerin prompti:
- Selkeämpi formaatti: "filename.py: what this file contains"
- Eksplisiittiset säännöt: max 4 tiedostoa, ei polkuja, vain tiedostonimet
- Sallitut tiedostopäätteet: .py, .txt, .json, .html

Tiedostoparsinta tiukennettu:
- Hylkää polut (chucknorris/fastapi/...) — vaatii ettei sisällä /
- Vaatii tiedostopäätteen (.xyz)
- Ei välilyöntejä nimessä

Koodarin prompti:
- "Project:" konteksti ensin, sitten tarkka tiedostokohtainen ohje
- "Write correct, working code. No explanations."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jaakko Vanhala
2026-04-05 20:34:23 +03:00
parent 2e7b86deeb
commit d5ab6272d3

View File

@@ -1878,11 +1878,15 @@
// Vaihe 1: Manageri pilkkoo projektin tiedostoiksi
termLog(`\n<span style="color:#d29922;font-weight:bold">[1] Manageri</span> — projektin suunnittelu`);
pipelineStep('manager', 'Suunnittelu', 'active', task);
const managerPrompt = `You are a project manager. Break this task into individual source files.
For each file, write one line: FILENAME: description
List only the essential files (max 5). No explanations.
const managerPrompt = `List the source files needed for this project. One file per line, format:
filename.py: what this file contains
Task: ${task}`;
Rules:
- Max 4 files
- Only .py, .txt, .json, .html files
- No directories, no paths, just filenames
Project: ${task}`;
const plan = await kpnRun(agentPrompts.manager.model, managerPrompt);
if (!plan) { termLog(' ✗ Pipeline keskeytyi (manageri)', '#f85149'); return; }
pipelineStep('manager', 'Suunnittelu', 'done', task, plan);
@@ -1890,12 +1894,17 @@ Task: ${task}`;
// Parsitaan tiedostolista: "FILENAME: description" -rivit
const fileList = plan.split('\n')
.map(line => line.trim())
.filter(line => line.includes(':') && (line.includes('.') || line.includes('/')))
.filter(line => line.includes(':'))
.map(line => {
const [name, ...desc] = line.replace(/^[\d\.\-\*]+\s*/, '').split(':');
return { name: name.trim().replace(/\*+/g, ''), desc: desc.join(':').trim() };
const [name, ...desc] = line.replace(/^[\d\.\-\*\s]+/, '').split(':');
return { name: name.trim().replace(/\*+/g, '').replace(/`/g, ''), desc: desc.join(':').trim() };
})
.filter(f => f.name.length > 0 && f.name.length < 50);
.filter(f => {
// Tiedostonimen pitää sisältää piste + tunniste, ei polkuja
const n = f.name;
return n.length > 0 && n.length < 40 && !n.includes('/') && !n.includes(' ')
&& /\.\w{1,5}$/.test(n); // Päättyy tiedostopäätteeseen (.py, .txt, .json jne.)
});
if (fileList.length === 0) {
// Fallback: manageri ei tuottanut tiedostolistaa, käytetään koko vastausta ohjeena
@@ -1926,8 +1935,10 @@ Task: ${task}`;
).join('\n\n') + '\n\n';
}
const coderPrompt = `${context}Write ONLY the file "${file.name}": ${file.desc}
Project: ${task}`;
const coderPrompt = `${context}Project: ${task}
Write ONLY the file "${file.name}".
Purpose: ${file.desc}
Write correct, working code. No explanations.`;
const code = await kpnRun(agentPrompts.coder.model, coderPrompt);
if (!code) {
termLog(` ✗ Pipeline keskeytyi (${file.name})`, '#f85149');