climage 0.5.3 → 0.6.1

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,138 @@ 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
+ const hasInputImages = req.inputImages && req.inputImages.length > 0;
1317
+ let prompt;
1318
+ if (hasInputImages) {
1319
+ const images2 = req.inputImages.map(
1320
+ (img) => img.startsWith("data:") ? dataUriToUint8Array(img) : Uint8Array.from(Buffer.from(img))
1321
+ );
1322
+ prompt = { images: images2, text: req.prompt };
1323
+ log5("Using image editing mode with", images2.length, "input image(s)");
1324
+ } else {
1325
+ prompt = req.prompt;
1326
+ }
1327
+ log5("Calling generateImage...");
1328
+ const startTime = Date.now();
1329
+ const result = await sdkGenerateImage({
1330
+ model: gw.image(model),
1331
+ prompt,
1332
+ ...req.aspectRatio ? { aspectRatio: req.aspectRatio } : {},
1333
+ n: req.n
1334
+ });
1335
+ log5(`Image generation completed in ${Date.now() - startTime}ms`);
1336
+ const images = result.images ?? (result.image ? [result.image] : []);
1337
+ log5(`Got ${images.length} image(s)`);
1338
+ if (!images.length) {
1339
+ throw new Error("Vercel AI Gateway returned no images");
1340
+ }
1341
+ return images.map((img, i) => ({
1342
+ kind: "image",
1343
+ provider: "vercel",
1344
+ model,
1345
+ index: i,
1346
+ bytes: img.uint8Array,
1347
+ mimeType: "image/png"
1348
+ }));
1349
+ }
1350
+ var vercelCapabilities = {
1351
+ maxInputImages: 1,
1352
+ supportsCustomAspectRatio: true,
1353
+ supportsVideoInterpolation: false,
1354
+ videoDurationRange: [1, 15],
1355
+ supportsImageEditing: true
1356
+ };
1357
+ var vercelProvider = {
1358
+ id: "vercel",
1359
+ displayName: "Vercel AI Gateway",
1360
+ supports: ["video", "image"],
1361
+ capabilities: vercelCapabilities,
1362
+ isAvailable(env) {
1363
+ return Boolean(getGatewayApiKey(env));
1364
+ },
1365
+ async generate(req, env) {
1366
+ const apiKey = getGatewayApiKey(env);
1367
+ if (!apiKey) throw new Error("Missing AI Gateway API key. Set AI_GATEWAY_API_KEY.");
1368
+ verboseMode4 = req.verbose;
1369
+ log5("Provider initialized, kind:", req.kind);
1370
+ if (req.kind === "video") return generateVercelVideo(req, apiKey);
1371
+ return generateVercelImage(req, apiKey);
1372
+ }
1373
+ };
1374
+
1252
1375
  // src/core/router.ts
1253
- var providers = [googleProvider, xaiProvider, falProvider, openaiProvider];
1254
- function log5(verbose, ...args) {
1376
+ var providers = [
1377
+ googleProvider,
1378
+ xaiProvider,
1379
+ falProvider,
1380
+ openaiProvider,
1381
+ vercelProvider
1382
+ ];
1383
+ function log6(verbose, ...args) {
1255
1384
  if (verbose) console.error("[router]", ...args);
1256
1385
  }
1257
1386
  function listProviders() {
@@ -1284,18 +1413,18 @@ async function normalizeOptions(prompt, opts, verbose) {
1284
1413
  const nameBase = slugify(opts.name ?? prompt);
1285
1414
  let inputImages;
1286
1415
  if (opts.inputImages?.length) {
1287
- log5(verbose, `Resolving ${opts.inputImages.length} input image(s)...`);
1416
+ log6(verbose, `Resolving ${opts.inputImages.length} input image(s)...`);
1288
1417
  inputImages = await resolveImageInputs(opts.inputImages);
1289
- log5(verbose, `Resolved input images`);
1418
+ log6(verbose, `Resolved input images`);
1290
1419
  }
1291
1420
  let startFrame;
1292
1421
  let endFrame;
1293
1422
  if (opts.startFrame) {
1294
- log5(verbose, `Resolving start frame: ${opts.startFrame}`);
1423
+ log6(verbose, `Resolving start frame: ${opts.startFrame}`);
1295
1424
  startFrame = await resolveImageInput(opts.startFrame);
1296
1425
  }
1297
1426
  if (opts.endFrame) {
1298
- log5(verbose, `Resolving end frame: ${opts.endFrame}`);
1427
+ log6(verbose, `Resolving end frame: ${opts.endFrame}`);
1299
1428
  endFrame = await resolveImageInput(opts.endFrame);
1300
1429
  }
1301
1430
  return {
@@ -1371,27 +1500,27 @@ async function generateMedia(prompt, opts = {}) {
1371
1500
  startFrame: req.startFrame?.startsWith("data:") ? `data:...${req.startFrame.length} chars` : req.startFrame,
1372
1501
  endFrame: req.endFrame?.startsWith("data:") ? `data:...${req.endFrame.length} chars` : req.endFrame
1373
1502
  };
1374
- log5(verbose, "Request:", JSON.stringify(reqSummary));
1503
+ log6(verbose, "Request:", JSON.stringify(reqSummary));
1375
1504
  const provider = pickProvider(req.provider, env);
1376
- log5(verbose, "Selected provider:", provider.id, "| supports:", provider.supports);
1505
+ log6(verbose, "Selected provider:", provider.id, "| supports:", provider.supports);
1377
1506
  if (!provider.supports.includes(req.kind)) {
1378
1507
  throw new Error(`Provider ${provider.id} does not support ${req.kind} generation`);
1379
1508
  }
1380
1509
  validateRequestForProvider(req, provider);
1381
- log5(verbose, "Calling provider.generate()...");
1510
+ log6(verbose, "Calling provider.generate()...");
1382
1511
  const startTime = Date.now();
1383
1512
  const partials = await provider.generate(req, env);
1384
- log5(verbose, `Provider returned ${partials.length} items in ${Date.now() - startTime}ms`);
1513
+ log6(verbose, `Provider returned ${partials.length} items in ${Date.now() - startTime}ms`);
1385
1514
  const items = [];
1386
1515
  for (let i = 0; i < partials.length; i++) {
1387
1516
  const p = partials[i];
1388
1517
  if (!p) continue;
1389
1518
  const filePath = makeOutputPath(req, i, p.mimeType);
1390
- log5(verbose, `Writing ${p.bytes.byteLength} bytes to: ${filePath}`);
1519
+ log6(verbose, `Writing ${p.bytes.byteLength} bytes to: ${filePath}`);
1391
1520
  await writeMediaFile(filePath, p.bytes);
1392
1521
  items.push({ ...p, filePath });
1393
1522
  }
1394
- log5(verbose, `Done! Generated ${items.length} ${req.kind}(s)`);
1523
+ log6(verbose, `Done! Generated ${items.length} ${req.kind}(s)`);
1395
1524
  return items;
1396
1525
  }
1397
1526
 
@@ -1430,6 +1559,7 @@ Env:
1430
1559
  XAI_API_KEY (or XAI_TOKEN, GROK_API_KEY)
1431
1560
  FAL_KEY (or FAL_API_KEY)
1432
1561
  OPENAI_API_KEY
1562
+ AI_GATEWAY_API_KEY (Vercel AI Gateway)
1433
1563
 
1434
1564
  Examples:
1435
1565
  npx climage "make image of kitten"