Esimerkkiprojektit HTML UI:lla + Mermaid-kaavio raporttiin + tooltips

- Esimerkkipromptit sisältävät nyt HTML-käyttöliittymän
- Manageri generoi index.html tiedoston, Dockerfile kopioi sen
- README: docker compose up → http://localhost:8000
- Raporttiin Mermaid-kaavio agenttien workflowsta (CDN)
- Pipeline-vaiheiden hover näyttää selityksen

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-07 11:06:15 +03:00
parent 77c8d46e7b
commit f5db2eb034

View File

@@ -1459,12 +1459,14 @@ filename.py: one-line description
CONSTRAINTS: the coder can only generate ~400 tokens per file
- Max 3 files (keep it minimal)
- Each file must be SHORT: one clear responsibility, no boilerplate
- Only .py and pyproject.toml files
- Only .py, .html and pyproject.toml files
- If the project has a UI, include one index.html served by FastAPI at /
EXAMPLE: for "FastAPI todo app with SQLite"
pyproject.toml: project metadata and dependencies
models.py: SQLAlchemy models and database setup
main.py: FastAPI app with CRUD endpoints
main.py: FastAPI app with CRUD endpoints and serves index.html at /
index.html: simple HTML UI with forms and fetch() to call the API
Project: (käyttäjän kuvaus)` },
coder: { label: 'Koodaus', prompt: `Project: (managerin suunnitelma)
@@ -2168,8 +2170,9 @@ IMPORTANT: Include get_db() dependency for FastAPI` },
const icon = s.status === 'done' ? '✓' : s.status === 'active' ? '◷' : '◯';
const iconColor = s.status === 'done' ? '#3fb950' : s.status === 'active' ? '#d29922' : '#8b949e';
const arrow = i < pipelineSteps.length - 1 ? ' <span style="color:#30363d">→</span> ' : '';
// Tooltip: input/output esikatselu
return `<span onclick="openPipelineStepModal(${i})" style="cursor:pointer;padding:2px 4px;border-radius:3px;transition:background 0.2s" onmouseenter="this.style.background='#21262d'" onmouseleave="this.style.background='transparent'"><span style="color:${iconColor}">${icon}</span> <span style="color:${color}">${esc(s.label)}</span></span>${arrow}`;
const stepDescs = { 'Suunnittelu': 'Pilkkoo tiedostoiksi', 'Review': 'Arvioi koodin laadun', 'Testit': 'Kirjoittaa testit', 'Dockerfile': 'Docker-image', 'Compose': 'Palvelumääritys', 'README': 'Dokumentaatio', 'Validointi': 'Tarkistaa yhteensopivuuden', 'Korjaukset': 'Korjaa löydetyt bugit' };
const desc = stepDescs[s.label] || s.label;
return `<span onclick="openPipelineStepModal(${i})" title="${desc}" style="cursor:pointer;padding:2px 4px;border-radius:3px;transition:background 0.2s" onmouseenter="this.style.background='#21262d'" onmouseleave="this.style.background='transparent'"><span style="color:${iconColor}">${icon}</span> <span style="color:${color}">${esc(s.label)}</span></span>${arrow}`;
}).join('');
}
@@ -2364,14 +2367,16 @@ filename.py: one-line description
CONSTRAINTS — the coder can only generate ~400 tokens per file:
- Max 3 files (keep it minimal)
- Each file must be SHORT: one clear responsibility, no boilerplate
- Only .py and pyproject.toml files
- Only .py, .html and pyproject.toml files
- If the project has a UI, include one index.html served by FastAPI at /
- No directories, no paths, just filenames
- List dependencies first, then main app
EXAMPLE for "FastAPI todo app with SQLite":
pyproject.toml: project metadata and dependencies
models.py: SQLAlchemy models and database setup
main.py: FastAPI app with CRUD endpoints
main.py: FastAPI app with CRUD endpoints and serves index.html at /
index.html: simple HTML UI with forms and fetch() to call the API
Project: ${task}`;
termLog(`\n<span style="color:#d29922;font-weight:bold">[1] Manageri</span> — projektin suunnittelu`);
@@ -2646,7 +2651,7 @@ ${Object.entries(generatedFiles).map(([n, c]) => `--- ${n} ---\n${c}`).join('\n\
const mainFile = Object.keys(generatedFiles).find(f => f.includes('main') || f.includes('app')) || Object.keys(generatedFiles)[0];
const hasPyproject = 'pyproject.toml' in generatedFiles;
const hasRequirements = 'requirements.txt' in generatedFiles;
const pyFiles = Object.keys(generatedFiles).filter(f => f.endsWith('.py'));
const codeFiles = Object.keys(generatedFiles).filter(f => f.endsWith('.py') || f.endsWith('.html'));
// Dockerfile-templatti: ei anneta mallin keksiä omaa
let depLines;
if (hasPyproject) {
@@ -2660,7 +2665,7 @@ ${Object.entries(generatedFiles).map(([n, c]) => `--- ${n} ---\n${c}`).join('\n\
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /app
${depLines}
COPY ${pyFiles.join(' ')} ./
COPY ${codeFiles.join(' ')} ./
EXPOSE 8000
CMD ["uv", "run", "uvicorn", "${mainFile.replace('.py','')}:app", "--host", "0.0.0.0", "--port", "8000"]`;
// Generoidaan Dockerfile suoraan templatesta, ei mallilla
@@ -2694,8 +2699,8 @@ volumes:
pipelineStep('tester', 'README', 'active', 'README.md');
const readmePrompt = `Write a minimal README.md. Include ONLY:
1. One-line description
2. Quick start: docker compose up
3. Development: uv sync && uv run uvicorn main:app --reload
2. Quick start: docker compose up → open http://localhost:8000
3. Development: uv sync && uv run uvicorn main:app --reload → http://localhost:8000
4. API endpoints (if applicable)
5. Testing: uv run pytest
Max 20 lines.
@@ -2822,6 +2827,11 @@ ${fixableFiles}`;
<h1>🔥 Kipinä Projektiraportti</h1>
<p style="color:#8b949e;margin-bottom:20px">${task}${new Date().toLocaleString('fi-FI')}${fileEntries.length} tiedostoa, ${steps.length} vaihetta</p>
<h2>🔄 Agenttien workflow</h2>
<div class="mermaid">
${generateMermaidDiagram(steps)}
</div>
<h2>📋 Pipeline-vaiheet</h2>
${stepsHtml}
@@ -2833,9 +2843,40 @@ ${filesHtml}
<hr style="border-color:#30363d;margin:24px 0">
<p style="color:#8b949e;font-size:12px">Generoitu Kipinä Agentic Playground v0.2.2 — <a href="https://kipina.studio">kipina.studio</a></p>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true, theme: 'dark', themeVariables: { primaryColor: '#58a6ff', primaryTextColor: '#c9d1d9', lineColor: '#30363d', primaryBorderColor: '#30363d' } });
</script>
</body></html>`;
}
function generateMermaidDiagram(steps) {
const agentLabels = { manager: 'Manageri', coder: 'Koodari', tester: 'DevOps', qa: 'QA', data: 'Data' };
const agentStyles = { manager: 'fill:#1c1206,stroke:#d29922,color:#d29922', coder: 'fill:#0d1a0d,stroke:#3fb950,color:#3fb950', tester: 'fill:#0d1117,stroke:#58a6ff,color:#58a6ff', qa: 'fill:#170d22,stroke:#a371f7,color:#a371f7', data: 'fill:#1a0d22,stroke:#d2a8ff,color:#d2a8ff' };
let lines = ['graph TD'];
let prevId = null;
const usedAgents = new Set();
steps.forEach((s, i) => {
const id = `S${i}`;
const agent = agentLabels[s.agent] || s.agent;
const label = s.label.replace(/"/g, "'");
usedAgents.add(s.agent);
lines.push(` ${id}["${agent}: ${label}"]`);
if (prevId) {
lines.push(` ${prevId} --> ${id}`);
}
if (agentStyles[s.agent]) {
lines.push(` style ${id} ${agentStyles[s.agent]}`);
}
prevId = id;
});
return lines.join('\n');
}
// Yksinkertainen pipeline (vanha: manageri → koodari → testaaja)
async function kpnPipelineSimple(task) {
termLog(`<span style="color:#a371f7;font-weight:bold">━━━ Pipeline käynnistyy ━━━</span>`);
@@ -3152,7 +3193,7 @@ ${filesHtml}
'kpn run coder-3b': ['"binary search tree in rust"', '"REST API with Flask"', '"async web scraper in python"'],
'kpn run manager': ['"suunnittele REST API"', '"priorisoi tiimin tehtävät"'],
'kpn run tester': ['"testaa login-toiminto"'],
'kpn project': ['"FastAPI + SQLite REST API for users"', '"Flask todo app with database"', '"CLI tool for CSV processing in Python"'],
'kpn project': ['"FastAPI + SQLite REST API for users with HTML UI at /"', '"Flask todo app with Jinja2 templates and form UI"', '"FastAPI bookmark manager with HTML frontend and search"'],
'kpn pipeline': ['"rakenna todo-sovellus"', '"tee laskin pythonilla"'],
};