import { NextRequest, NextResponse } from 'next/server'; import { type ImageGenerationConfig, getSafetySettings } from '@/lib/google-ai'; import { vertexAI } from '@/lib/google-ai-server'; export const runtime = 'nodejs'; export const maxDuration = 60; export async function POST(req: NextRequest) { try { const body: ImageGenerationConfig = await req.json(); const { model, prompt, aspectRatio = '1:1', numberOfImages = 1, negativePrompt, temperature = 1, safetyFilterLevel = 'block_some', referenceImages, } = body; if (!prompt || !model) { return NextResponse.json( { error: 'Prompt y modelo son requeridos' }, { status: 400 } ); } // Obtener el modelo generativo de Vertex AI const generativeModel = vertexAI.getGenerativeModel({ model: model, safetySettings: getSafetySettings(safetyFilterLevel) as any, generationConfig: { temperature: temperature, maxOutputTokens: 8192, }, }); // Construir el prompt completo let fullPrompt = prompt; if (negativePrompt) { fullPrompt += `\n\nNo incluir: ${negativePrompt}`; } // Agregar instrucciones de aspect ratio si no es 1:1 if (aspectRatio !== '1:1') { fullPrompt += `\n\nGenera la imagen en formato ${aspectRatio}.`; } // Construir parts con imágenes de referencia si existen const parts: any[] = []; // Agregar imágenes de referencia primero if (referenceImages && referenceImages.length > 0) { for (const refImg of referenceImages) { parts.push({ inlineData: { data: refImg.data, mimeType: refImg.mimeType, }, }); } } // Agregar el prompt de texto parts.push({ text: fullPrompt }); // Generar contenido const result = await generativeModel.generateContent({ contents: [ { role: 'user', parts: parts, }, ], }); const response = result.response; // Extraer imágenes de la respuesta const images: string[] = []; if (response.candidates && response.candidates.length > 0) { for (const candidate of response.candidates) { if (candidate.content?.parts) { for (const part of candidate.content.parts) { // Verificar si la parte contiene datos inline (imagen) if ('inlineData' in part && part.inlineData) { const imageData = part.inlineData.data; if (imageData) { images.push(imageData); } } } } } } // Si no hay imágenes, intentar generar más información de debug if (images.length === 0) { console.error('No se encontraron imágenes en la respuesta'); return NextResponse.json( { error: 'El modelo no generó imágenes', details: 'El modelo respondió pero no incluyó datos de imagen', response: response, suggestion: 'Prueba con un prompt más descriptivo o cambia el modelo', }, { status: 500 } ); } return NextResponse.json({ images: images, model: model, prompt: prompt, aspectRatio: aspectRatio, count: images.length, }); } catch (error: any) { console.error('Error generando imagen:', error); // Manejar errores específicos de la API let errorMessage = 'Error generando imagen'; let errorDetails = error.message; if (error.message?.includes('credentials') || error.message?.includes('authentication')) { errorMessage = 'Error de autenticación'; errorDetails = 'Verifica las credenciales del Service Account'; } else if (error.message?.includes('quota')) { errorMessage = 'Límite de cuota excedido'; errorDetails = 'Has alcanzado el límite de uso de la API'; } else if (error.message?.includes('safety')) { errorMessage = 'Contenido bloqueado por seguridad'; errorDetails = 'El prompt fue bloqueado por políticas de seguridad'; } else if (error.message?.includes('permission')) { errorMessage = 'Error de permisos'; errorDetails = 'El Service Account no tiene permisos para Vertex AI'; } return NextResponse.json( { error: errorMessage, details: errorDetails, stack: process.env.NODE_ENV === 'development' ? error.stack : undefined, }, { status: 500 } ); } }