diff --git a/network-poc/static/index.html b/network-poc/static/index.html
index c7bcbbf..00a3fa5 100644
--- a/network-poc/static/index.html
+++ b/network-poc/static/index.html
@@ -1514,7 +1514,7 @@ IMPORTANT: Use uv for package management (uv sync, uv run)` },
data: { label: 'Data', prompt: `SQLAlchemy models and database setup.
EXAMPLE:
-from sqlalchemy import create_engine, Column, Integer, String
+from sqlalchemy import create_engine, Column, Integer, String, Boolean, Text
from sqlalchemy.orm import sessionmaker, DeclarativeBase
engine = create_engine("sqlite:///app.db")
@@ -2463,7 +2463,7 @@ def create_user(name: str, db: Session = Depends(get_db)):
return {"id": user.id, "name": user.name}`
: file.name.includes('model')
? `\nEXAMPLE output for a models.py:
-from sqlalchemy import create_engine, Column, Integer, String
+from sqlalchemy import create_engine, Column, Integer, String, Boolean, Text
from sqlalchemy.orm import sessionmaker, DeclarativeBase
engine = create_engine("sqlite:///app.db")
@@ -2523,11 +2523,20 @@ IMPORTANT: Keep the code SHORT. Max ~50 lines. No comments, no docstrings. Write
}
}
// Tarkista puuttuvat importit
- if (code.includes('FastAPI') && !imports.some(i => i.includes('FastAPI'))) {
- staticIssues.push(`${name}: käyttää FastAPI mutta ei importtaa sitä`);
- }
- if (code.includes('Session') && !imports.some(i => i.includes('Session'))) {
- staticIssues.push(`${name}: käyttää Session mutta ei importtaa sitä`);
+ const importText = imports.join(' ');
+ const needsImport = [
+ ['FastAPI', 'FastAPI'], ['Session', 'Session'], ['Depends', 'Depends'],
+ ['HTTPException', 'HTTPException'], ['TestClient', 'TestClient'],
+ ['Boolean', 'Boolean'], ['Text', 'Text'], ['Float', 'Float'], ['DateTime', 'DateTime'],
+ ['Column', 'Column'], ['create_engine', 'create_engine'],
+ ['DeclarativeBase', 'DeclarativeBase'], ['sessionmaker', 'sessionmaker'],
+ ];
+ for (const [symbol, name_] of needsImport) {
+ // Tarkista käytetäänkö symbolia koodissa (ei import-riveillä)
+ const codeWithoutImports = lines.filter(l => !l.match(/^(from|import)\s/)).join('\n');
+ if (codeWithoutImports.includes(symbol) && !importText.includes(symbol)) {
+ staticIssues.push(`${name}: käyttää '${symbol}' mutta ei importtaa sitä`);
+ }
}
// Tarkista tyhjät funktiot
const emptyFuncs = code.match(/def \w+\([^)]*\):\s*\n\s*(pass|\.\.\.)/g);
@@ -2642,16 +2651,21 @@ CMD ["uv", "run", "uvicorn", "${mainFile.replace('.py','')}:app", "--host", "0.0
const step7 = step6 + 1;
termLog(`\n[${step7}] DevOps — docker-compose.yml`);
pipelineStep('tester', 'Compose', 'active', 'docker-compose.yml');
- const composePrompt = `Write a docker-compose.yml for this project. Include:
-- app service (build from Dockerfile, port mapping, restart: unless-stopped)
-- db service if SQLite/PostgreSQL is used (volume for data persistence)
-- Named volumes for persistent data
-Only output the YAML content, nothing else.
+ // docker-compose.yml templatesta (ei LLM:llä — vältetään version/postgres ongelmat)
+ const composeContent = `services:
+ app:
+ build: .
+ ports:
+ - "8000:8000"
+ volumes:
+ - app-data:/app/data
+ restart: unless-stopped
-Files: ${Object.keys(generatedFiles).join(', ')}`;
- const compose = await kpnRun(agentPrompts.tester.model, composePrompt, false, 256);
- if (compose) generatedFiles['docker-compose.yml'] = compose;
- pipelineStep('tester', 'Compose', 'done', 'docker-compose.yml', compose);
+volumes:
+ app-data:`;
+ generatedFiles['docker-compose.yml'] = composeContent;
+ termLog(` ✓ docker-compose.yml generoitu (template)`);
+ pipelineStep('tester', 'Compose', 'done', composeContent, composeContent);
// Vaihe 8: DevOps — README
const step8 = step7 + 1;