const OPENROUTER_URL = "https://openrouter.ai/api/v1/chat/completions"; function toDataUrlMaybe(item) { if (!item) return null; if (typeof item === "string") { if (item.startsWith("http://") || item.startsWith("https://") || item.startsWith("data:image/")) return item; return `data:image/png;base64,${item}`; } if (item.url) return item.url; if (item.image_url?.url) return item.image_url.url; if (item.b64_json) return `data:image/png;base64,${item.b64_json}`; if (item.data) return `data:image/png;base64,${item.data}`; return null; } function extractImageFromResponse(json) { const c = json?.choices?.[0]; if (!c) return null; const msg = c.message || {}; const content = msg.content; if (Array.isArray(content)) { for (const part of content) { if (part?.type === "image_url") { const u = part?.image_url?.url || part?.url; if (u) return u; } if (part?.type === "output_image" && part?.image_url?.url) return part.image_url.url; if (part?.type === "text" && typeof part.text === "string") { const m = part.text.match(/https?:\/\/\S+\.(?:png|jpg|jpeg|webp|gif)/i); if (m) return m[0]; } } } const fallbackPools = [ json?.images, json?.data, msg?.images, c?.images ]; for (const pool of fallbackPools) { if (Array.isArray(pool) && pool.length) { const x = toDataUrlMaybe(pool[0]); if (x) return x; } } if (typeof content === "string") { const m = content.match(/https?:\/\/\S+\.(?:png|jpg|jpeg|webp|gif)/i); if (m) return m[0]; } return null; } export async function generateImageFrame({ apiKey, model, textPrompt, previousFrames = [], imageSize = "1K", aspectRatio = "1:1" }) { const messages = []; // rolling window of 2 frames only const recent = previousFrames.slice(-2); if (recent.length) { for (const frame of recent) { messages.push({ role: "user", content: [ { type: "image_url", image_url: { url: frame } } ] }); } } messages.push({ role: "user", content: [ { type: "text", text: textPrompt } ] }); const body = { model, modalities: ["image"], messages, image_config: { image_size: imageSize, aspect_ratio: aspectRatio } }; const res = await fetch(OPENROUTER_URL, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, "HTTP-Referer": window.location.origin, "X-Title": "vibegif.lol" }, body: JSON.stringify(body) }); const json = await res.json().catch(() => ({})); if (!res.ok) { const msg = json?.error?.message || `OpenRouter error (${res.status})`; throw new Error(msg); } const image = extractImageFromResponse(json); if (!image) throw new Error("No image found in model response."); return image; }