import { NextResponse } from 'next/server'; import { recordEvent } from '@/lib/auditDb'; import { startGenerationLock } from '@/lib/generationLocks'; import { regeneratePackAsset } from '@/lib/packGenerator'; import { detectProvider } from '@/lib/providers'; import { loadSession, saveSession } from '@/lib/storage'; import type { RegenerateAssetRequest, RegenerateAssetResponse } from '@/lib/types'; export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; export async function POST(req: Request, ctx: { params: Promise<{ assetId: string }> }) { const { assetId } = await ctx.params; const { sessionId, userRefinement, confirmCost } = (await req.json()) as RegenerateAssetRequest; if (!assetId || !sessionId) { return NextResponse.json({ error: 'assetId and sessionId required' }, { status: 400 }); } if (confirmCost !== true) { recordEvent({ action: 'asset.regenerate_blocked_unconfirmed', sessionId, targetType: 'asset', targetId: assetId, status: 'blocked', provider: detectProvider(), }); return NextResponse.json({ error: 'confirmCost required for paid regenerate' }, { status: 400 }); } const session = await loadSession(sessionId); if (!session) return NextResponse.json({ error: 'session not found' }, { status: 404 }); const releaseLock = startGenerationLock(`regenerate:${sessionId}:${assetId}`); if (!releaseLock) { recordEvent({ action: 'asset.regenerate_blocked_running', sessionId, targetType: 'asset', targetId: assetId, status: 'blocked', provider: detectProvider(), }); return NextResponse.json({ error: 'asset regenerate already running' }, { status: 429 }); } try { recordEvent({ action: 'asset.regenerate_started', sessionId, targetType: 'asset', targetId: assetId, status: 'started', provider: detectProvider(), metadata: { refinement: Boolean(userRefinement?.trim()) }, }); const regenerated = await regeneratePackAsset({ session, assetId, userRefinement }); await saveSession(session); recordEvent({ action: 'asset.regenerate_completed', sessionId, targetType: 'asset', targetId: assetId, status: 'ok', provider: regenerated.provider, metadata: { packId: regenerated.pack.id, templateId: regenerated.asset.templateId, url: regenerated.asset.url }, }); return NextResponse.json({ asset: regenerated.asset, pack: regenerated.pack, provider: regenerated.provider, } satisfies RegenerateAssetResponse); } catch (error) { recordEvent({ action: 'asset.regenerate_failed', sessionId, targetType: 'asset', targetId: assetId, status: 'error', provider: detectProvider(), message: String(error) }); return NextResponse.json({ error: String(error) }, { status: 500 }); } finally { releaseLock(); } }