/** * Image Service * Handles communication with Image Generation APIs. */ const axios = require('axios'); // Assuming axios might be used // Placeholder for API Key configuration const API_KEY = process.env.IMG_API_KEY || process.env.LLM_API_KEY || ''; const MODEL = 'gemini-3-pro-image-preview'; const API_URL = `https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent`; /** * Generates an image based on the text prompt. * @param {string} prompt - The text description for the image. * @param {Object} options - Optional parameters (aspectRatio, etc.) * @returns {Promise} - The base64 string of the generated image. */ async function generateImage(prompt, options = {}) { if (!API_KEY) { throw new Error("IMG_API_KEY or LLM_API_KEY is not defined in environment variables."); } try { console.log(`[Image Service] Sending request to ${MODEL}...`, prompt); const url = `${API_URL}?key=${API_KEY}`; const payload = { contents: [{ parts: [{ text: prompt }] }] }; // Add optional configuration if supported by the model and needed /* if (options.aspectRatio) { payload.generationConfig = { aspectRatio: options.aspectRatio // e.g., "1:1", "4:3", "16:9" }; } */ const response = await axios.post(url, payload, { headers: { 'Content-Type': 'application/json' }, timeout: 120000 // 2 minutes timeout }); // Extract base64 image data from Gemini response structure if (response.data && response.data.candidates && response.data.candidates.length > 0) { const candidate = response.data.candidates[0]; if (candidate.content && candidate.content.parts) { const imagePart = candidate.content.parts.find(p => p.inlineData); if (imagePart && imagePart.inlineData) { return imagePart.inlineData.data; // This is the base64 string } } } console.warn("[Image Service] Unexpected response structure:", JSON.stringify(response.data)); throw new Error("Empty or invalid response from Image Generation API."); } catch (error) { console.error('[Image Service] Error generating image:', error.response ? JSON.stringify(error.response.data) : error.message); throw error; } } /** * Regenerates/Edits an image based on a text prompt and an existing image. * * @param {string} prompt - The text instruction. * @param {string} imageBase64 - The base64 string of the previous image. * @returns {Promise} - The base64 string of the new image. */ async function regenerateImage(prompt, imageBase64) { if (!API_KEY) { throw new Error("IMG_API_KEY or LLM_API_KEY is not defined."); } try { console.log(`[Image Service] Regenerating image with prompt: ${prompt}`); const url = `${API_URL}?key=${API_KEY}`; const payload = { contents: [{ parts: [ { text: prompt }, { inline_data: { mime_type: "image/png", // Assuming PNG for now, simplest for base64 data: imageBase64 } } ] }] }; const response = await axios.post(url, payload, { headers: { 'Content-Type': 'application/json' }, timeout: 120000 }); if (response.data && response.data.candidates && response.data.candidates.length > 0) { const candidate = response.data.candidates[0]; if (candidate.content && candidate.content.parts) { const imagePart = candidate.content.parts.find(p => p.inlineData); if (imagePart && imagePart.inlineData) { return imagePart.inlineData.data; } } } console.warn("[Image Service] Unexpected response structure:", JSON.stringify(response.data)); throw new Error("Empty or invalid response from Image Generation API."); } catch (error) { console.error('[Image Service] Error regenerating image:', error.response ? JSON.stringify(error.response.data) : error.message); throw error; } } module.exports = { generateImage, regenerateImage };