feat: Add layer-wise texture editing using Gemini AI
Build and Deploy / build-and-push (push) Failing after 54s

This commit is contained in:
AI Bot
2026-09-17 09:56:37 +05:30
parent 6e182cf4ac
commit c4253022db
3 changed files with 170 additions and 292 deletions
+71
View File
@@ -647,6 +647,77 @@ CRITICAL INSTRUCTIONS:
}
});
// Edit Layer (Gemini Flash Image)
app.post('/api/sparkplug/edit-layer', authenticate, async (req, res) => {
const { prompt, imageBase64, mimeType } = req.body;
if (!prompt || !imageBase64) return res.status(400).json({ error: 'Missing prompt or image' });
try {
const keys = await getKeysFromProfile(req.user.id);
const apiKey = keys.GEMINI_API_KEY || keys.NANO_BANANA_API_KEY;
if (!apiKey) return res.status(400).json({ error: 'Gemini API key missing' });
const baseUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-image:generateContent';
const base64Data = imageBase64.replace(/^data:image\/\w+;base64,/, "");
const payload = {
contents: [
{
parts: [
{ text: `You are an expert texture editor. Edit the following image based on this prompt: "${prompt}". \nCRITICAL INSTRUCTIONS:\n1. Output MUST be an image with the exact same aspect ratio as the input.\n2. Do NOT change the layout or mapping of the texture.\n3. Increase the resolution and quality of the visual elements as requested.` },
{
inlineData: {
mimeType: mimeType || "image/png",
data: base64Data
}
}
]
}
],
generationConfig: {
responseModalities: ["IMAGE"]
}
};
const response = await axios.post(`${baseUrl}?key=${apiKey}`, payload, {
headers: { 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip,deflate,compress' }
});
let resultBase64 = null;
let resultMime = 'image/jpeg';
const candidate = response.data?.candidates?.[0];
if (candidate?.content?.parts) {
for (const part of candidate.content.parts) {
if (part.inlineData && part.inlineData.data) {
resultBase64 = part.inlineData.data;
resultMime = part.inlineData.mimeType || 'image/jpeg';
break;
}
}
}
if (!resultBase64) {
throw new Error(`Could not extract base64 image data from Gemini response`);
}
const buffer = Buffer.from(resultBase64, 'base64');
const ext = resultMime === 'image/png' ? 'png' : 'jpg';
const filename = `layer-edit-${req.user.id}-${Date.now()}.${ext}`;
const filepath = path.join(uploadsDir, filename);
fs.writeFileSync(filepath, buffer);
res.json({ imageUrl: \`/uploads/\${filename}\` });
} catch (err) {
let errorMsg = err.message;
if (err.response && err.response.data) {
errorMsg = typeof err.response.data === 'object' ? JSON.stringify(err.response.data) : err.response.data;
}
console.error("Gemini Edit Layer Error:", errorMsg);
res.status(500).json({ error: errorMsg });
}
});
// 3. Generate 3D (Meshy)
app.post('/api/sparkplug/generate-3d', authenticate, async (req, res) => {
const { imageUrls } = req.body;