climage 0.5.3 → 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
@@ -1249,9 +1249,127 @@ var openaiProvider = {
1249
1249
  }
1250
1250
  };
1251
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
+
1252
1364
  // src/core/router.ts
1253
- var providers = [googleProvider, xaiProvider, falProvider, openaiProvider];
1254
- function log5(verbose, ...args) {
1365
+ var providers = [
1366
+ googleProvider,
1367
+ xaiProvider,
1368
+ falProvider,
1369
+ openaiProvider,
1370
+ vercelProvider
1371
+ ];
1372
+ function log6(verbose, ...args) {
1255
1373
  if (verbose) console.error("[router]", ...args);
1256
1374
  }
1257
1375
  function listProviders() {
@@ -1284,18 +1402,18 @@ async function normalizeOptions(prompt, opts, verbose) {
1284
1402
  const nameBase = slugify(opts.name ?? prompt);
1285
1403
  let inputImages;
1286
1404
  if (opts.inputImages?.length) {
1287
- log5(verbose, `Resolving ${opts.inputImages.length} input image(s)...`);
1405
+ log6(verbose, `Resolving ${opts.inputImages.length} input image(s)...`);
1288
1406
  inputImages = await resolveImageInputs(opts.inputImages);
1289
- log5(verbose, `Resolved input images`);
1407
+ log6(verbose, `Resolved input images`);
1290
1408
  }
1291
1409
  let startFrame;
1292
1410
  let endFrame;
1293
1411
  if (opts.startFrame) {
1294
- log5(verbose, `Resolving start frame: ${opts.startFrame}`);
1412
+ log6(verbose, `Resolving start frame: ${opts.startFrame}`);
1295
1413
  startFrame = await resolveImageInput(opts.startFrame);
1296
1414
  }
1297
1415
  if (opts.endFrame) {
1298
- log5(verbose, `Resolving end frame: ${opts.endFrame}`);
1416
+ log6(verbose, `Resolving end frame: ${opts.endFrame}`);
1299
1417
  endFrame = await resolveImageInput(opts.endFrame);
1300
1418
  }
1301
1419
  return {
@@ -1371,27 +1489,27 @@ async function generateMedia(prompt, opts = {}) {
1371
1489
  startFrame: req.startFrame?.startsWith("data:") ? `data:...${req.startFrame.length} chars` : req.startFrame,
1372
1490
  endFrame: req.endFrame?.startsWith("data:") ? `data:...${req.endFrame.length} chars` : req.endFrame
1373
1491
  };
1374
- log5(verbose, "Request:", JSON.stringify(reqSummary));
1492
+ log6(verbose, "Request:", JSON.stringify(reqSummary));
1375
1493
  const provider = pickProvider(req.provider, env);
1376
- log5(verbose, "Selected provider:", provider.id, "| supports:", provider.supports);
1494
+ log6(verbose, "Selected provider:", provider.id, "| supports:", provider.supports);
1377
1495
  if (!provider.supports.includes(req.kind)) {
1378
1496
  throw new Error(`Provider ${provider.id} does not support ${req.kind} generation`);
1379
1497
  }
1380
1498
  validateRequestForProvider(req, provider);
1381
- log5(verbose, "Calling provider.generate()...");
1499
+ log6(verbose, "Calling provider.generate()...");
1382
1500
  const startTime = Date.now();
1383
1501
  const partials = await provider.generate(req, env);
1384
- 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`);
1385
1503
  const items = [];
1386
1504
  for (let i = 0; i < partials.length; i++) {
1387
1505
  const p = partials[i];
1388
1506
  if (!p) continue;
1389
1507
  const filePath = makeOutputPath(req, i, p.mimeType);
1390
- log5(verbose, `Writing ${p.bytes.byteLength} bytes to: ${filePath}`);
1508
+ log6(verbose, `Writing ${p.bytes.byteLength} bytes to: ${filePath}`);
1391
1509
  await writeMediaFile(filePath, p.bytes);
1392
1510
  items.push({ ...p, filePath });
1393
1511
  }
1394
- log5(verbose, `Done! Generated ${items.length} ${req.kind}(s)`);
1512
+ log6(verbose, `Done! Generated ${items.length} ${req.kind}(s)`);
1395
1513
  return items;
1396
1514
  }
1397
1515
 
@@ -1430,6 +1548,7 @@ Env:
1430
1548
  XAI_API_KEY (or XAI_TOKEN, GROK_API_KEY)
1431
1549
  FAL_KEY (or FAL_API_KEY)
1432
1550
  OPENAI_API_KEY
1551
+ AI_GATEWAY_API_KEY (Vercel AI Gateway)
1433
1552
 
1434
1553
  Examples:
1435
1554
  npx climage "make image of kitten"