import { NextResponse } from 'next/server'; import { randomBytes } from 'node:crypto'; import { recordEvent } from '@/lib/auditDb'; import { detectProvider, generateGptImages, generateMock } from '@/lib/providers'; import { saveSession, saveGeneratedImage, saveRefImage } from '@/lib/storage'; import type { GenerateRequest, GenerateResponse, GenSession } from '@/lib/types'; export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; export async function POST(req: Request) { const body = (await req.json()) as GenerateRequest; const { prompt, refImages = [], count = 8, style } = body; if (!prompt || typeof prompt !== 'string') { return NextResponse.json({ error: 'prompt required' }, { status: 400 }); } const sessionId = `s_${Date.now().toString(36)}_${randomBytes(3).toString('hex')}`; const finalPrompt = style ? `${prompt}, style: ${style}` : prompt; const provider = detectProvider(); recordEvent({ action: 'idea.generate_started', sessionId, targetType: 'session', targetId: sessionId, status: 'started', provider, metadata: { count, refImages: refImages.length, style: style ?? null, promptLength: finalPrompt.length }, }); const savedRefUrls: string[] = []; for (let i = 0; i < refImages.length; i++) { const r = refImages[i]; if (r.startsWith('data:')) { savedRefUrls.push(await saveRefImage(sessionId, i, r)); } else { savedRefUrls.push(r); } } let rawImages; try { rawImages = provider === 'gpt' ? await generateGptImages({ sessionId, prompt: finalPrompt, count, refImages: savedRefUrls }) : await generateMock({ sessionId, prompt: finalPrompt, count }); } catch (e) { recordEvent({ action: 'idea.generate_failed', sessionId, targetType: 'session', targetId: sessionId, status: 'error', provider, message: String(e), metadata: { count }, }); return NextResponse.json({ error: String(e) }, { status: 500 }); } // 把 data URL 落盘成静态文件链接,便于后续选中复制 const images = await Promise.all(rawImages.map(async img => { if (img.url.startsWith('data:')) { const url = await saveGeneratedImage(sessionId, img.id, img.url); return { ...img, url }; } return img; })); const session: GenSession = { id: sessionId, createdAt: Date.now(), prompt: finalPrompt, refImages: savedRefUrls, count, images, }; await saveSession(session); recordEvent({ action: 'idea.generate_completed', sessionId, targetType: 'session', targetId: sessionId, status: 'ok', provider, metadata: { images: images.length }, }); const resp: GenerateResponse = { sessionId, images, provider }; return NextResponse.json(resp); }