// POST /api/seed/finalize // // Pivot flow: turn the SeedDraft into structured prose, persist it as the // NarrativeDocument, create an empty model snapshot, and return the new // project id so the client can navigate to /editor/[id]. The analyze // pipeline runs on first paint of the editor (or via Analyze All). import { NextResponse } from "next/server"; import { createProjectFromSeed, saveDocument } from "../../../../lib/db/repo"; import { seedToProseDoc } from "../../../../lib/llm/seedToProse"; import { runAnalyze } from "../../../../lib/llm/analyze/runAll"; import type { SeedDraft } from "../../../../lib/llm/seedInterview"; import type { SysMLModel } from "../../../../lib/sysml/model"; export async function POST(req: Request) { let body: { draft?: SeedDraft }; try { body = await req.json(); } catch { return NextResponse.json({ error: "invalid json body" }, { status: 400 }); } const draft = body.draft; if (!draft || !draft.problem || !draft.targetUser || !draft.desiredOutcome) { return NextResponse.json( { error: "draft must include problem, targetUser, desiredOutcome" }, { status: 400 } ); } try { const emptyModel: SysMLModel = { blocks: [], associations: [], constraints: [], requirements: [] }; const created = await createProjectFromSeed({ name: draft.title?.trim() || "Untitled idea", scope: "Untitled scope", tagline: draft.problem.slice(0, 80), model: emptyModel, }); await saveDocument(created.projectId, seedToProseDoc(draft)); // Kick off the full Analyze pipeline in the background so the editor lands // populated. Errors are logged but do not block the redirect — the user // can hit Analyze All again from the TopBar if anything goes sideways. void runAnalyze(created.projectId, "all").catch(err => console.error(`[seed/finalize] background analyze failed for ${created.projectId}:`, err) ); return NextResponse.json({ projectId: created.projectId, version: created.version }); } catch (err) { return NextResponse.json({ error: (err as Error).message }, { status: 500 }); } }