Files
ai-toy-patent-workflow/src/app/api/generate/route.ts

92 lines
2.8 KiB
TypeScript

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);
}