From ec17eb833c8e7d9662d8bbc1fcf437b5d4bfb362 Mon Sep 17 00:00:00 2001 From: AI Bot Date: Wed, 2 Sep 2026 14:14:57 +0530 Subject: [PATCH] fix: switch to Gemini Imagen 3 API endpoint to fix image base64 extraction --- backend/server.js | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/backend/server.js b/backend/server.js index 64ba053..a27ba51 100644 --- a/backend/server.js +++ b/backend/server.js @@ -370,52 +370,46 @@ app.post('/api/sparkplug/extract', authenticate, upload.single('file'), async (r } }); -// 2. Generate Images (Nano Banana / Gemini Imagen) +// 2. Generate Images (Gemini Imagen 3) app.post('/api/sparkplug/generate-images', authenticate, async (req, res) => { const { prompt } = req.body; if (!prompt) return res.status(400).json({ error: 'No prompt provided' }); try { const keys = await getKeysFromProfile(req.user.id); - const apiKey = keys.NANO_BANANA_API_KEY || keys.GEMINI_API_KEY; - if (!apiKey) return res.status(400).json({ error: 'Nano Banana (Gemini) API key missing' }); + const apiKey = keys.GEMINI_API_KEY || keys.NANO_BANANA_API_KEY; + if (!apiKey) return res.status(400).json({ error: 'Gemini API key missing' }); - // We will use axios to call the new Gemini 3.1 REST API via /interactions - const baseUrl = 'https://generativelanguage.googleapis.com/v1beta/interactions'; + // Use the standard Gemini Imagen 3 API + const baseUrl = 'https://generativelanguage.googleapis.com/v1beta/models/imagen-3.0-generate-images:predict'; const views = ['Front view', 'Back view', 'Left side view', 'Right side view']; - const imageUrls = []; // Run parallel generation for all 4 views const promises = views.map(async (view, index) => { const fullPrompt = `${prompt}. ${view}, isolated on a pure white background, studio lighting.`; const payload = { - model: "gemini-3.1-flash-lite-image", - input: [ - { type: "text", text: fullPrompt } - ] + instances: [ + { prompt: fullPrompt } + ], + parameters: { + sampleCount: 1, + aspectRatio: "1:1" + } }; const response = await axios.post(`${baseUrl}?key=${apiKey}`, payload, { headers: { 'Content-Type': 'application/json' } }); - // The new interactions endpoint returns the interaction object. - // We look for the image output. let base64Image = null; - if (response.data.interaction?.output_image?.data) { - base64Image = response.data.interaction.output_image.data; - } else if (response.data.interaction?.output?.blocks) { - // Fallback for raw REST shape if output_image is an SDK-only convenience wrapper - const imgBlock = response.data.interaction.output.blocks.find(b => b.type === 'image' || b.image); - if (imgBlock) { - base64Image = imgBlock.image?.data || imgBlock.data; - } + if (response.data && response.data.predictions && response.data.predictions.length > 0) { + base64Image = response.data.predictions[0].bytesBase64Encoded; } if (!base64Image) { - throw new Error("Could not extract base64 image data from Gemini response: " + JSON.stringify(response.data)); + throw new Error(`Could not extract base64 image data from Gemini response: ${JSON.stringify(response.data)}`); } const buffer = Buffer.from(base64Image, 'base64'); @@ -432,7 +426,6 @@ app.post('/api/sparkplug/generate-images', authenticate, async (req, res) => { } catch (err) { let errorMsg = err.message; if (err.response && err.response.data) { - // Just stringify the entire response data so we can see the exact error from Google! errorMsg = typeof err.response.data === 'object' ? JSON.stringify(err.response.data) : err.response.data; } console.error("Gemini Image Gen Error:", errorMsg);