mirror of
https://github.com/vibegif/vibegif.lol.git
synced 2026-04-07 10:12:13 +00:00
Delete: Merged into app.js
This commit is contained in:
88
api.js
88
api.js
@@ -1,88 +0,0 @@
|
||||
import { getApiKey } from './storage.js';
|
||||
|
||||
const BASE = 'https://openrouter.ai/api/v1/chat/completions';
|
||||
const MASTER_PROMPT = 'minimal black and white line doodle, single stroke, white background, kawaii style';
|
||||
|
||||
/**
|
||||
* Generates a single image frame via OpenRouter.
|
||||
* @param {Object} opts
|
||||
* @param {string} opts.model
|
||||
* @param {Array} opts.messages - chat history messages
|
||||
* @param {string} opts.imageSize - "1K" or "0.5K"
|
||||
* @param {string} opts.aspectRatio - e.g. "1:1"
|
||||
* @returns {Promise<{base64: string, assistantMsg: Object}>}
|
||||
*/
|
||||
export async function generateFrame({ model, messages, imageSize, aspectRatio }) {
|
||||
const isGemini = model.startsWith('google/');
|
||||
|
||||
const body = {
|
||||
model,
|
||||
messages,
|
||||
modalities: ['image'],
|
||||
image_config: {
|
||||
aspect_ratio: aspectRatio,
|
||||
image_size: imageSize,
|
||||
},
|
||||
};
|
||||
|
||||
if (!isGemini && imageSize === '0.5K') {
|
||||
body.image_config.image_size = '1K';
|
||||
}
|
||||
|
||||
const res = await fetch(BASE, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${getApiKey()}`,
|
||||
'Content-Type': 'application/json',
|
||||
'HTTP-Referer': 'https://vibegif.lol',
|
||||
'X-Title': 'vibegif.lol',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({}));
|
||||
throw new Error(err?.error?.message || `API error ${res.status}`);
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
const choice = data.choices?.[0];
|
||||
if (!choice) throw new Error('No response from model');
|
||||
|
||||
const images = choice.message?.images;
|
||||
if (!images?.length) throw new Error('No image in response. The model may have refused or returned text only.');
|
||||
|
||||
const url = images[0].image_url?.url || images[0].url;
|
||||
if (!url) throw new Error('Could not parse image from response');
|
||||
|
||||
const base64 = url.startsWith('data:') ? url : `data:image/png;base64,${url}`;
|
||||
|
||||
const assistantMsg = {
|
||||
role: 'assistant',
|
||||
content: [
|
||||
{ type: 'image_url', image_url: { url: base64 } }
|
||||
]
|
||||
};
|
||||
|
||||
return { base64, assistantMsg };
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the first user message (frame 1).
|
||||
*/
|
||||
export function buildFirstMessage(userPrompt) {
|
||||
return {
|
||||
role: 'user',
|
||||
content: `${MASTER_PROMPT}, ${userPrompt}`
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Build follow-up user message for subsequent frames.
|
||||
*/
|
||||
export function buildNextMessage(frameIndex, frameCount) {
|
||||
return {
|
||||
role: 'user',
|
||||
content: `imagine we are trying to create a ${frameCount} frame gif. generate the next meaningful frame (frame ${frameIndex} of ${frameCount})`
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user