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/cli.js CHANGED
@@ -719,17 +719,12 @@ function imageToVeoFormat(imageInput) {
719
719
  `Veo image inputs must be data: URIs or gs:// URIs (got ${imageInput.slice(0, 24)}...)`
720
720
  );
721
721
  }
722
- var GEMINI_IMAGE_MODELS = [
723
- "gemini-2.5-flash-image",
724
- "gemini-3-pro-image-preview",
725
- "gemini-3.1-flash-image-preview"
726
- ];
727
722
  function resolveModel(model) {
728
723
  if (!model) return "gemini-2.5-flash-image";
729
724
  return MODEL_ALIASES[model] ?? model;
730
725
  }
731
726
  function isGeminiImageModel(model) {
732
- return GEMINI_IMAGE_MODELS.some((m) => model.startsWith(m));
727
+ return model.startsWith("gemini-");
733
728
  }
734
729
  async function downloadBytes3(url) {
735
730
  log3("Downloading from:", url.slice(0, 100) + "...");
@@ -1254,9 +1249,127 @@ var openaiProvider = {
1254
1249
  }
1255
1250
  };
1256
1251
 
1252
+ // src/providers/vercel.ts
1253
+ import {
1254
+ experimental_generateVideo as sdkGenerateVideo,
1255
+ generateImage as sdkGenerateImage,
1256
+ createGateway
1257
+ } from "ai";
1258
+ function getGatewayApiKey(env) {
1259
+ return env.AI_GATEWAY_API_KEY;
1260
+ }
1261
+ var verboseMode4 = false;
1262
+ function log5(...args) {
1263
+ if (verboseMode4) console.error("[vercel]", ...args);
1264
+ }
1265
+ function makeGateway(apiKey) {
1266
+ return createGateway({ apiKey });
1267
+ }
1268
+ function dataUriToUint8Array(dataUri) {
1269
+ const commaIdx = dataUri.indexOf(",");
1270
+ const b64 = dataUri.slice(commaIdx + 1);
1271
+ return Uint8Array.from(Buffer.from(b64, "base64"));
1272
+ }
1273
+ var DEFAULT_VIDEO_MODEL2 = "xai/grok-imagine-video";
1274
+ var DEFAULT_IMAGE_MODEL2 = "xai/grok-imagine-image";
1275
+ async function generateVercelVideo(req, apiKey) {
1276
+ const gw = makeGateway(apiKey);
1277
+ const model = req.model ?? DEFAULT_VIDEO_MODEL2;
1278
+ log5("Starting video generation, model:", model);
1279
+ const imageInput = req.startFrame ?? req.inputImages?.[0];
1280
+ let prompt;
1281
+ if (imageInput) {
1282
+ const imageData = imageInput.startsWith("data:") ? dataUriToUint8Array(imageInput) : imageInput;
1283
+ prompt = { image: imageData, text: req.prompt };
1284
+ log5("Using image-to-video mode");
1285
+ } else {
1286
+ prompt = req.prompt;
1287
+ }
1288
+ log5("Calling experimental_generateVideo...");
1289
+ const startTime = Date.now();
1290
+ const result = await sdkGenerateVideo({
1291
+ model: gw.video(model),
1292
+ prompt,
1293
+ ...req.aspectRatio ? { aspectRatio: req.aspectRatio } : {},
1294
+ ...req.duration !== void 0 ? { duration: req.duration } : {},
1295
+ n: req.n
1296
+ });
1297
+ log5(`Video generation completed in ${Date.now() - startTime}ms`);
1298
+ const videos = result.videos ?? (result.video ? [result.video] : []);
1299
+ log5(`Got ${videos.length} video(s)`);
1300
+ if (!videos.length) {
1301
+ throw new Error("Vercel AI Gateway returned no videos");
1302
+ }
1303
+ return videos.map((v, i) => ({
1304
+ kind: "video",
1305
+ provider: "vercel",
1306
+ model,
1307
+ index: i,
1308
+ bytes: v.uint8Array,
1309
+ mimeType: "video/mp4"
1310
+ }));
1311
+ }
1312
+ async function generateVercelImage(req, apiKey) {
1313
+ const gw = makeGateway(apiKey);
1314
+ const model = req.model ?? DEFAULT_IMAGE_MODEL2;
1315
+ log5("Starting image generation, model:", model);
1316
+ log5("Calling generateImage...");
1317
+ const startTime = Date.now();
1318
+ const result = await sdkGenerateImage({
1319
+ model: gw.image(model),
1320
+ prompt: req.prompt,
1321
+ ...req.aspectRatio ? { aspectRatio: req.aspectRatio } : {},
1322
+ n: req.n
1323
+ });
1324
+ log5(`Image generation completed in ${Date.now() - startTime}ms`);
1325
+ const images = result.images ?? (result.image ? [result.image] : []);
1326
+ log5(`Got ${images.length} image(s)`);
1327
+ if (!images.length) {
1328
+ throw new Error("Vercel AI Gateway returned no images");
1329
+ }
1330
+ return images.map((img, i) => ({
1331
+ kind: "image",
1332
+ provider: "vercel",
1333
+ model,
1334
+ index: i,
1335
+ bytes: img.uint8Array,
1336
+ mimeType: "image/png"
1337
+ }));
1338
+ }
1339
+ var vercelCapabilities = {
1340
+ maxInputImages: 1,
1341
+ supportsCustomAspectRatio: true,
1342
+ supportsVideoInterpolation: false,
1343
+ videoDurationRange: [1, 15],
1344
+ supportsImageEditing: false
1345
+ };
1346
+ var vercelProvider = {
1347
+ id: "vercel",
1348
+ displayName: "Vercel AI Gateway",
1349
+ supports: ["video", "image"],
1350
+ capabilities: vercelCapabilities,
1351
+ isAvailable(env) {
1352
+ return Boolean(getGatewayApiKey(env));
1353
+ },
1354
+ async generate(req, env) {
1355
+ const apiKey = getGatewayApiKey(env);
1356
+ if (!apiKey) throw new Error("Missing AI Gateway API key. Set AI_GATEWAY_API_KEY.");
1357
+ verboseMode4 = req.verbose;
1358
+ log5("Provider initialized, kind:", req.kind);
1359
+ if (req.kind === "video") return generateVercelVideo(req, apiKey);
1360
+ return generateVercelImage(req, apiKey);
1361
+ }
1362
+ };
1363
+
1257
1364
  // src/core/router.ts
1258
- var providers = [googleProvider, xaiProvider, falProvider, openaiProvider];
1259
- function log5(verbose, ...args) {
1365
+ var providers = [
1366
+ googleProvider,
1367
+ xaiProvider,
1368
+ falProvider,
1369
+ openaiProvider,
1370
+ vercelProvider
1371
+ ];
1372
+ function log6(verbose, ...args) {
1260
1373
  if (verbose) console.error("[router]", ...args);
1261
1374
  }
1262
1375
  function listProviders() {
@@ -1289,18 +1402,18 @@ async function normalizeOptions(prompt, opts, verbose) {
1289
1402
  const nameBase = slugify(opts.name ?? prompt);
1290
1403
  let inputImages;
1291
1404
  if (opts.inputImages?.length) {
1292
- log5(verbose, `Resolving ${opts.inputImages.length} input image(s)...`);
1405
+ log6(verbose, `Resolving ${opts.inputImages.length} input image(s)...`);
1293
1406
  inputImages = await resolveImageInputs(opts.inputImages);
1294
- log5(verbose, `Resolved input images`);
1407
+ log6(verbose, `Resolved input images`);
1295
1408
  }
1296
1409
  let startFrame;
1297
1410
  let endFrame;
1298
1411
  if (opts.startFrame) {
1299
- log5(verbose, `Resolving start frame: ${opts.startFrame}`);
1412
+ log6(verbose, `Resolving start frame: ${opts.startFrame}`);
1300
1413
  startFrame = await resolveImageInput(opts.startFrame);
1301
1414
  }
1302
1415
  if (opts.endFrame) {
1303
- log5(verbose, `Resolving end frame: ${opts.endFrame}`);
1416
+ log6(verbose, `Resolving end frame: ${opts.endFrame}`);
1304
1417
  endFrame = await resolveImageInput(opts.endFrame);
1305
1418
  }
1306
1419
  return {
@@ -1376,27 +1489,27 @@ async function generateMedia(prompt, opts = {}) {
1376
1489
  startFrame: req.startFrame?.startsWith("data:") ? `data:...${req.startFrame.length} chars` : req.startFrame,
1377
1490
  endFrame: req.endFrame?.startsWith("data:") ? `data:...${req.endFrame.length} chars` : req.endFrame
1378
1491
  };
1379
- log5(verbose, "Request:", JSON.stringify(reqSummary));
1492
+ log6(verbose, "Request:", JSON.stringify(reqSummary));
1380
1493
  const provider = pickProvider(req.provider, env);
1381
- log5(verbose, "Selected provider:", provider.id, "| supports:", provider.supports);
1494
+ log6(verbose, "Selected provider:", provider.id, "| supports:", provider.supports);
1382
1495
  if (!provider.supports.includes(req.kind)) {
1383
1496
  throw new Error(`Provider ${provider.id} does not support ${req.kind} generation`);
1384
1497
  }
1385
1498
  validateRequestForProvider(req, provider);
1386
- log5(verbose, "Calling provider.generate()...");
1499
+ log6(verbose, "Calling provider.generate()...");
1387
1500
  const startTime = Date.now();
1388
1501
  const partials = await provider.generate(req, env);
1389
- log5(verbose, `Provider returned ${partials.length} items in ${Date.now() - startTime}ms`);
1502
+ log6(verbose, `Provider returned ${partials.length} items in ${Date.now() - startTime}ms`);
1390
1503
  const items = [];
1391
1504
  for (let i = 0; i < partials.length; i++) {
1392
1505
  const p = partials[i];
1393
1506
  if (!p) continue;
1394
1507
  const filePath = makeOutputPath(req, i, p.mimeType);
1395
- log5(verbose, `Writing ${p.bytes.byteLength} bytes to: ${filePath}`);
1508
+ log6(verbose, `Writing ${p.bytes.byteLength} bytes to: ${filePath}`);
1396
1509
  await writeMediaFile(filePath, p.bytes);
1397
1510
  items.push({ ...p, filePath });
1398
1511
  }
1399
- log5(verbose, `Done! Generated ${items.length} ${req.kind}(s)`);
1512
+ log6(verbose, `Done! Generated ${items.length} ${req.kind}(s)`);
1400
1513
  return items;
1401
1514
  }
1402
1515
 
@@ -1435,6 +1548,7 @@ Env:
1435
1548
  XAI_API_KEY (or XAI_TOKEN, GROK_API_KEY)
1436
1549
  FAL_KEY (or FAL_API_KEY)
1437
1550
  OPENAI_API_KEY
1551
+ AI_GATEWAY_API_KEY (Vercel AI Gateway)
1438
1552
 
1439
1553
  Examples:
1440
1554
  npx climage "make image of kitten"