climage 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -690,17 +690,12 @@ function imageToVeoFormat(imageInput) {
690
690
  `Veo image inputs must be data: URIs or gs:// URIs (got ${imageInput.slice(0, 24)}...)`
691
691
  );
692
692
  }
693
- var GEMINI_IMAGE_MODELS = [
694
- "gemini-2.5-flash-image",
695
- "gemini-3-pro-image-preview",
696
- "gemini-3.1-flash-image-preview"
697
- ];
698
693
  function resolveModel(model) {
699
694
  if (!model) return "gemini-2.5-flash-image";
700
695
  return MODEL_ALIASES[model] ?? model;
701
696
  }
702
697
  function isGeminiImageModel(model) {
703
- return GEMINI_IMAGE_MODELS.some((m) => model.startsWith(m));
698
+ return model.startsWith("gemini-");
704
699
  }
705
700
  async function downloadBytes3(url) {
706
701
  log3("Downloading from:", url.slice(0, 100) + "...");
@@ -1225,9 +1220,127 @@ var openaiProvider = {
1225
1220
  }
1226
1221
  };
1227
1222
 
1223
+ // src/providers/vercel.ts
1224
+ import {
1225
+ experimental_generateVideo as sdkGenerateVideo,
1226
+ generateImage as sdkGenerateImage,
1227
+ createGateway
1228
+ } from "ai";
1229
+ function getGatewayApiKey(env) {
1230
+ return env.AI_GATEWAY_API_KEY;
1231
+ }
1232
+ var verboseMode4 = false;
1233
+ function log5(...args) {
1234
+ if (verboseMode4) console.error("[vercel]", ...args);
1235
+ }
1236
+ function makeGateway(apiKey) {
1237
+ return createGateway({ apiKey });
1238
+ }
1239
+ function dataUriToUint8Array(dataUri) {
1240
+ const commaIdx = dataUri.indexOf(",");
1241
+ const b64 = dataUri.slice(commaIdx + 1);
1242
+ return Uint8Array.from(Buffer.from(b64, "base64"));
1243
+ }
1244
+ var DEFAULT_VIDEO_MODEL2 = "xai/grok-imagine-video";
1245
+ var DEFAULT_IMAGE_MODEL2 = "xai/grok-imagine-image";
1246
+ async function generateVercelVideo(req, apiKey) {
1247
+ const gw = makeGateway(apiKey);
1248
+ const model = req.model ?? DEFAULT_VIDEO_MODEL2;
1249
+ log5("Starting video generation, model:", model);
1250
+ const imageInput = req.startFrame ?? req.inputImages?.[0];
1251
+ let prompt;
1252
+ if (imageInput) {
1253
+ const imageData = imageInput.startsWith("data:") ? dataUriToUint8Array(imageInput) : imageInput;
1254
+ prompt = { image: imageData, text: req.prompt };
1255
+ log5("Using image-to-video mode");
1256
+ } else {
1257
+ prompt = req.prompt;
1258
+ }
1259
+ log5("Calling experimental_generateVideo...");
1260
+ const startTime = Date.now();
1261
+ const result = await sdkGenerateVideo({
1262
+ model: gw.video(model),
1263
+ prompt,
1264
+ ...req.aspectRatio ? { aspectRatio: req.aspectRatio } : {},
1265
+ ...req.duration !== void 0 ? { duration: req.duration } : {},
1266
+ n: req.n
1267
+ });
1268
+ log5(`Video generation completed in ${Date.now() - startTime}ms`);
1269
+ const videos = result.videos ?? (result.video ? [result.video] : []);
1270
+ log5(`Got ${videos.length} video(s)`);
1271
+ if (!videos.length) {
1272
+ throw new Error("Vercel AI Gateway returned no videos");
1273
+ }
1274
+ return videos.map((v, i) => ({
1275
+ kind: "video",
1276
+ provider: "vercel",
1277
+ model,
1278
+ index: i,
1279
+ bytes: v.uint8Array,
1280
+ mimeType: "video/mp4"
1281
+ }));
1282
+ }
1283
+ async function generateVercelImage(req, apiKey) {
1284
+ const gw = makeGateway(apiKey);
1285
+ const model = req.model ?? DEFAULT_IMAGE_MODEL2;
1286
+ log5("Starting image generation, model:", model);
1287
+ log5("Calling generateImage...");
1288
+ const startTime = Date.now();
1289
+ const result = await sdkGenerateImage({
1290
+ model: gw.image(model),
1291
+ prompt: req.prompt,
1292
+ ...req.aspectRatio ? { aspectRatio: req.aspectRatio } : {},
1293
+ n: req.n
1294
+ });
1295
+ log5(`Image generation completed in ${Date.now() - startTime}ms`);
1296
+ const images = result.images ?? (result.image ? [result.image] : []);
1297
+ log5(`Got ${images.length} image(s)`);
1298
+ if (!images.length) {
1299
+ throw new Error("Vercel AI Gateway returned no images");
1300
+ }
1301
+ return images.map((img, i) => ({
1302
+ kind: "image",
1303
+ provider: "vercel",
1304
+ model,
1305
+ index: i,
1306
+ bytes: img.uint8Array,
1307
+ mimeType: "image/png"
1308
+ }));
1309
+ }
1310
+ var vercelCapabilities = {
1311
+ maxInputImages: 1,
1312
+ supportsCustomAspectRatio: true,
1313
+ supportsVideoInterpolation: false,
1314
+ videoDurationRange: [1, 15],
1315
+ supportsImageEditing: false
1316
+ };
1317
+ var vercelProvider = {
1318
+ id: "vercel",
1319
+ displayName: "Vercel AI Gateway",
1320
+ supports: ["video", "image"],
1321
+ capabilities: vercelCapabilities,
1322
+ isAvailable(env) {
1323
+ return Boolean(getGatewayApiKey(env));
1324
+ },
1325
+ async generate(req, env) {
1326
+ const apiKey = getGatewayApiKey(env);
1327
+ if (!apiKey) throw new Error("Missing AI Gateway API key. Set AI_GATEWAY_API_KEY.");
1328
+ verboseMode4 = req.verbose;
1329
+ log5("Provider initialized, kind:", req.kind);
1330
+ if (req.kind === "video") return generateVercelVideo(req, apiKey);
1331
+ return generateVercelImage(req, apiKey);
1332
+ }
1333
+ };
1334
+
1228
1335
  // src/core/router.ts
1229
- var providers = [googleProvider, xaiProvider, falProvider, openaiProvider];
1230
- function log5(verbose, ...args) {
1336
+ var providers = [
1337
+ googleProvider,
1338
+ xaiProvider,
1339
+ falProvider,
1340
+ openaiProvider,
1341
+ vercelProvider
1342
+ ];
1343
+ function log6(verbose, ...args) {
1231
1344
  if (verbose) console.error("[router]", ...args);
1232
1345
  }
1233
1346
  function listProviders() {
@@ -1260,18 +1373,18 @@ async function normalizeOptions(prompt, opts, verbose) {
1260
1373
  const nameBase = slugify(opts.name ?? prompt);
1261
1374
  let inputImages;
1262
1375
  if (opts.inputImages?.length) {
1263
- log5(verbose, `Resolving ${opts.inputImages.length} input image(s)...`);
1376
+ log6(verbose, `Resolving ${opts.inputImages.length} input image(s)...`);
1264
1377
  inputImages = await resolveImageInputs(opts.inputImages);
1265
- log5(verbose, `Resolved input images`);
1378
+ log6(verbose, `Resolved input images`);
1266
1379
  }
1267
1380
  let startFrame;
1268
1381
  let endFrame;
1269
1382
  if (opts.startFrame) {
1270
- log5(verbose, `Resolving start frame: ${opts.startFrame}`);
1383
+ log6(verbose, `Resolving start frame: ${opts.startFrame}`);
1271
1384
  startFrame = await resolveImageInput(opts.startFrame);
1272
1385
  }
1273
1386
  if (opts.endFrame) {
1274
- log5(verbose, `Resolving end frame: ${opts.endFrame}`);
1387
+ log6(verbose, `Resolving end frame: ${opts.endFrame}`);
1275
1388
  endFrame = await resolveImageInput(opts.endFrame);
1276
1389
  }
1277
1390
  return {
@@ -1347,27 +1460,27 @@ async function generateMedia(prompt, opts = {}) {
1347
1460
  startFrame: req.startFrame?.startsWith("data:") ? `data:...${req.startFrame.length} chars` : req.startFrame,
1348
1461
  endFrame: req.endFrame?.startsWith("data:") ? `data:...${req.endFrame.length} chars` : req.endFrame
1349
1462
  };
1350
- log5(verbose, "Request:", JSON.stringify(reqSummary));
1463
+ log6(verbose, "Request:", JSON.stringify(reqSummary));
1351
1464
  const provider = pickProvider(req.provider, env);
1352
- log5(verbose, "Selected provider:", provider.id, "| supports:", provider.supports);
1465
+ log6(verbose, "Selected provider:", provider.id, "| supports:", provider.supports);
1353
1466
  if (!provider.supports.includes(req.kind)) {
1354
1467
  throw new Error(`Provider ${provider.id} does not support ${req.kind} generation`);
1355
1468
  }
1356
1469
  validateRequestForProvider(req, provider);
1357
- log5(verbose, "Calling provider.generate()...");
1470
+ log6(verbose, "Calling provider.generate()...");
1358
1471
  const startTime = Date.now();
1359
1472
  const partials = await provider.generate(req, env);
1360
- log5(verbose, `Provider returned ${partials.length} items in ${Date.now() - startTime}ms`);
1473
+ log6(verbose, `Provider returned ${partials.length} items in ${Date.now() - startTime}ms`);
1361
1474
  const items = [];
1362
1475
  for (let i = 0; i < partials.length; i++) {
1363
1476
  const p = partials[i];
1364
1477
  if (!p) continue;
1365
1478
  const filePath = makeOutputPath(req, i, p.mimeType);
1366
- log5(verbose, `Writing ${p.bytes.byteLength} bytes to: ${filePath}`);
1479
+ log6(verbose, `Writing ${p.bytes.byteLength} bytes to: ${filePath}`);
1367
1480
  await writeMediaFile(filePath, p.bytes);
1368
1481
  items.push({ ...p, filePath });
1369
1482
  }
1370
- log5(verbose, `Done! Generated ${items.length} ${req.kind}(s)`);
1483
+ log6(verbose, `Done! Generated ${items.length} ${req.kind}(s)`);
1371
1484
  return items;
1372
1485
  }
1373
1486
  async function generateImage(prompt, opts = {}) {