Tiedostoparsinta: hyväksyy myös pelkät tiedostonimet ilman kuvausta

Manageri tuottaa toisinaan pelkän listan (app.py, requirements.txt)
ilman "filename: description" -formaattia. Parsija hyväksyy nyt molemmat.
Koodarin prompti vahvistettu: "Use the exact libraries mentioned in the
project description" estää Flaskiin vaihtamisen kun tehtävä sanoo FastAPI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jaakko Vanhala
2026-04-05 20:44:16 +03:00
parent 4dff534fbf
commit 4cb6128a27

View File

@@ -2033,26 +2033,28 @@ Project: ${task}`;
if (!plan) { termLog(' ✗ Pipeline keskeytyi (manageri)', '#f85149'); return; } if (!plan) { termLog(' ✗ Pipeline keskeytyi (manageri)', '#f85149'); return; }
pipelineStep('manager', 'Suunnittelu', 'done', task, plan); pipelineStep('manager', 'Suunnittelu', 'done', task, plan);
// Parsitaan tiedostolista: "FILENAME: description" -rivit // Parsitaan tiedostolista: "filename.py: description" TAI pelkkä "filename.py"
const fileList = plan.split('\n') const fileList = plan.split('\n')
.map(line => line.trim()) .map(line => line.trim().replace(/^[\d\.\-\*\s]+/, '').replace(/\*+/g, '').replace(/`/g, ''))
.filter(line => line.includes(':'))
.map(line => { .map(line => {
const [name, ...desc] = line.replace(/^[\d\.\-\*\s]+/, '').split(':'); if (line.includes(':')) {
return { name: name.trim().replace(/\*+/g, '').replace(/`/g, ''), desc: desc.join(':').trim() }; const [name, ...desc] = line.split(':');
return { name: name.trim(), desc: desc.join(':').trim() };
}
// Pelkkä tiedostonimi ilman kuvausta
return { name: line.trim(), desc: '' };
}) })
.filter(f => { .filter(f => {
// Tiedostonimen pitää sisältää piste + tunniste, ei polkuja
const n = f.name; const n = f.name;
return n.length > 0 && n.length < 40 && !n.includes('/') && !n.includes(' ') return n.length > 0 && n.length < 40 && !n.includes('/') && !n.includes(' ')
&& /\.\w{1,5}$/.test(n); // Päättyy tiedostopäätteeseen (.py, .txt, .json jne.) && /\.\w{1,5}$/.test(n);
}); });
if (fileList.length === 0) { if (fileList.length === 0) {
// Fallback: manageri ei tuottanut tiedostolistaa, käytetään koko vastausta ohjeena // Fallback: manageri ei tuottanut tiedostolistaa, käytetään koko vastausta ohjeena
termLog(' <span style="color:#8b949e">Ei tiedostojakoa — generoidaan yhtenä kokonaisuutena</span>'); termLog(' <span style="color:#8b949e">Ei tiedostojakoa — generoidaan yhtenä kokonaisuutena</span>');
termLog(`\n<span style="color:#3fb950;font-weight:bold">[2] Koodari</span> — toteutus`); termLog(`\n<span style="color:#3fb950;font-weight:bold">[2] Koodari</span> — toteutus`);
const code = await kpnRun(agentPrompts.coder.model, `${plan}\n\nWrite the code.`); const code = await kpnRun(agentPrompts.coder.model, `Project: ${task}\nFiles: ${plan}\n\nWrite all the code for this project. Use the exact libraries mentioned in the project description.`);
if (code) { if (code) {
termLog(`\n<span style="color:#a371f7;font-weight:bold">━━━ Pipeline valmis ━━━</span>`); termLog(`\n<span style="color:#a371f7;font-weight:bold">━━━ Pipeline valmis ━━━</span>`);
} }
@@ -2078,9 +2080,8 @@ Project: ${task}`;
} }
const coderPrompt = `${context}Project: ${task} const coderPrompt = `${context}Project: ${task}
Write ONLY the file "${file.name}". Write ONLY the file "${file.name}"${file.desc ? ': ' + file.desc : ''}.
Purpose: ${file.desc} Use the exact libraries mentioned in the project description. Write correct, working code.`;
Write correct, working code. No explanations.`;
const code = await kpnRun(agentPrompts.coder.model, coderPrompt); const code = await kpnRun(agentPrompts.coder.model, coderPrompt);
if (!code) { if (!code) {
termLog(` ✗ Pipeline keskeytyi (${file.name})`, '#f85149'); termLog(` ✗ Pipeline keskeytyi (${file.name})`, '#f85149');