vargai 0.4.0-alpha86 → 0.4.0-alpha87

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/hello.tsx ADDED
@@ -0,0 +1,35 @@
1
+ /** @jsxImportSource vargai */
2
+ import { Render, Clip, Image, Video, assets } from "vargai/react";
3
+ import { fal } from "vargai/ai";
4
+
5
+ const girl = Image({
6
+ prompt: {
7
+ text: `Using the attached reference images, generate a photorealistic three-quarter editorial portrait of the exact same character — maintain identical face, hairstyle, and proportions from Image 1.
8
+
9
+ Framing: Head and shoulders, cropped at upper chest. Direct eye contact with camera.
10
+
11
+ Natural confident expression, relaxed shoulders.
12
+ Preserve the outfit neckline and visible clothing details from reference.
13
+
14
+ Background: Deep black with two contrasting orange gradient accents matching Reference 2. Soft gradient bleed, no hard edges.
15
+
16
+ Shot on 85mm f/1.4 lens, shallow depth of field. Clean studio lighting — soft key light on face, subtle rim light on hair and shoulders for separation. High-end fashion editorial aesthetic.`,
17
+ images: [assets.characters.orangeGirl, assets.backgrounds.orangeGradient],
18
+ },
19
+ model: fal.imageModel("nano-banana-pro/edit"),
20
+ aspectRatio: "9:16",
21
+ });
22
+
23
+ export default (
24
+ <Render width={1080} height={1920}>
25
+ <Clip duration={5}>
26
+ <Video
27
+ prompt={{
28
+ text: "She waves hello warmly, natural smile, friendly expression. Studio lighting, authentic confident slightly playful atmosphere. Camera static. Intense orange lighting.",
29
+ images: [girl],
30
+ }}
31
+ model={fal.videoModel("kling-v2.5")}
32
+ />
33
+ </Clip>
34
+ </Render>
35
+ );
package/package.json CHANGED
@@ -71,7 +71,7 @@
71
71
  "zod": "^4.2.1"
72
72
  },
73
73
  "sideEffects": false,
74
- "version": "0.4.0-alpha86",
74
+ "version": "0.4.0-alpha87",
75
75
  "exports": {
76
76
  ".": "./src/index.ts",
77
77
  "./ai": "./src/ai-sdk/index.ts",
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Garry Tan Talking Head Video
3
+ * Generate a video of Garry Tan saying "varg.ai is cool!"
4
+ */
5
+
6
+ import {
7
+ generateImage,
8
+ experimental_generateSpeech as generateSpeech,
9
+ } from "ai";
10
+ import { elevenlabs, File, fal, generateVideo } from "../index";
11
+
12
+ async function main() {
13
+ const script = `varg.ai is cool!`;
14
+
15
+ console.log("generating Garry Tan image and voice in parallel...");
16
+ const [imageResult, speechResult] = await Promise.all([
17
+ generateImage({
18
+ model: fal.imageModel("flux-schnell"),
19
+ prompt:
20
+ "Garry Tan, Y Combinator CEO, Asian American man, short dark hair, glasses, friendly smile, professional headshot, studio lighting, clean background, looking at camera",
21
+ n: 1,
22
+ }),
23
+ generateSpeech({
24
+ model: elevenlabs.speechModel("turbo"),
25
+ text: script,
26
+ voice: "adam",
27
+ }),
28
+ ]);
29
+
30
+ const firstImage = imageResult.images[0];
31
+ if (!firstImage) throw new Error("No image generated");
32
+ const image = File.from(firstImage);
33
+ const audio = File.from(speechResult.audio);
34
+
35
+ console.log(`image: ${(await image.data()).byteLength} bytes`);
36
+ console.log(`audio: ${(await audio.data()).byteLength} bytes`);
37
+
38
+ await Bun.write("output/garry-tan-image.png", await image.data());
39
+ await Bun.write("output/garry-tan-voice.mp3", await audio.data());
40
+
41
+ console.log("\nanimating Garry Tan (5 seconds)...");
42
+ const { video } = await generateVideo({
43
+ model: fal.videoModel("wan-2.5"),
44
+ prompt: {
45
+ text: "man talking naturally, moving mouth while speaking, subtle head movements, professional demeanor, blinking naturally",
46
+ images: [await image.data()],
47
+ },
48
+ duration: 5,
49
+ });
50
+
51
+ const output = File.from(video);
52
+ console.log(`video: ${(await output.data()).byteLength} bytes`);
53
+ await Bun.write("output/garry-tan-varg.mp4", await output.data());
54
+
55
+ console.log("\ndone! files saved to output/");
56
+ console.log("- output/garry-tan-image.png");
57
+ console.log("- output/garry-tan-voice.mp3");
58
+ console.log("- output/garry-tan-varg.mp4");
59
+ }
60
+
61
+ main().catch(console.error);
@@ -43,7 +43,20 @@ class VargAPIError extends Error {
43
43
  }
44
44
 
45
45
  function resolveConfig(settings: VargProviderSettings = {}) {
46
- const apiKey = settings.apiKey ?? process.env.VARG_API_KEY ?? "";
46
+ let apiKey = settings.apiKey ?? process.env.VARG_API_KEY ?? "";
47
+
48
+ // Fallback to global credentials (~/.varg/credentials) if no key from settings or env
49
+ if (!apiKey) {
50
+ try {
51
+ const { getGlobalApiKey } = require("../../cli/credentials") as {
52
+ getGlobalApiKey: () => string | null;
53
+ };
54
+ apiKey = getGlobalApiKey() ?? "";
55
+ } catch {
56
+ // credentials module may not be available in all contexts (e.g., browser)
57
+ }
58
+ }
59
+
47
60
  const baseUrl = settings.baseUrl ?? "https://api.varg.ai/v1";
48
61
  return { apiKey, baseUrl };
49
62
  }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * vargai balance — check your credit balance
3
+ *
4
+ * Fetches the current balance from the Gateway API using the saved API key.
5
+ */
6
+
7
+ import { defineCommand } from "citty";
8
+ import { getCredentials, getGlobalApiKey } from "../credentials";
9
+
10
+ const GATEWAY_URL = process.env.VARG_GATEWAY_URL ?? "https://api.varg.ai";
11
+
12
+ const COLORS = {
13
+ reset: "\x1b[0m",
14
+ bold: "\x1b[1m",
15
+ dim: "\x1b[2m",
16
+ green: "\x1b[32m",
17
+ yellow: "\x1b[33m",
18
+ red: "\x1b[31m",
19
+ cyan: "\x1b[36m",
20
+ };
21
+
22
+ function formatCents(cents: number): string {
23
+ return `$${(cents / 100).toLocaleString("en-US", { minimumFractionDigits: 2 })}`;
24
+ }
25
+
26
+ export const balanceCmd = defineCommand({
27
+ meta: {
28
+ name: "balance",
29
+ description: "check your credit balance",
30
+ },
31
+ async run() {
32
+ const apiKey = process.env.VARG_API_KEY ?? getGlobalApiKey();
33
+ const creds = getCredentials();
34
+
35
+ if (!apiKey) {
36
+ console.log();
37
+ console.log(
38
+ `${COLORS.yellow} !${COLORS.reset} Not logged in. Run ${COLORS.cyan}vargai login${COLORS.reset} first.`,
39
+ );
40
+ console.log();
41
+ return;
42
+ }
43
+
44
+ process.stdout.write(
45
+ `\n${COLORS.dim} ● Fetching balance...${COLORS.reset}`,
46
+ );
47
+
48
+ try {
49
+ const res = await fetch(`${GATEWAY_URL}/v1/balance`, {
50
+ headers: {
51
+ Authorization: `Bearer ${apiKey}`,
52
+ },
53
+ });
54
+
55
+ if (!res.ok) {
56
+ process.stdout.write("\r\x1b[K");
57
+ const body = (await res.json().catch(() => ({}))) as {
58
+ error?: string | { message?: string };
59
+ };
60
+ const errMsg =
61
+ typeof body.error === "string"
62
+ ? body.error
63
+ : (body.error?.message ??
64
+ `Failed to fetch balance (${res.status})`);
65
+ console.log(`${COLORS.red} ✗${COLORS.reset} ${errMsg}`);
66
+ console.log();
67
+ return;
68
+ }
69
+
70
+ const data = (await res.json()) as { balance_cents: number };
71
+
72
+ process.stdout.write("\r\x1b[K");
73
+
74
+ console.log(
75
+ `${COLORS.bold}${COLORS.cyan}varg${COLORS.reset}${COLORS.dim} — account balance${COLORS.reset}`,
76
+ );
77
+ console.log();
78
+
79
+ if (creds?.email) {
80
+ console.log(` ${COLORS.dim}Account:${COLORS.reset} ${creds.email}`);
81
+ }
82
+
83
+ console.log(
84
+ ` ${COLORS.dim}Balance:${COLORS.reset} ${COLORS.bold}${data.balance_cents.toLocaleString()} credits${COLORS.reset} (${formatCents(data.balance_cents)})`,
85
+ );
86
+ console.log();
87
+
88
+ if (data.balance_cents <= 0) {
89
+ console.log(
90
+ ` ${COLORS.yellow}No credits remaining.${COLORS.reset} Run ${COLORS.cyan}vargai topup${COLORS.reset} to add more.`,
91
+ );
92
+ console.log();
93
+ }
94
+ } catch (error) {
95
+ process.stdout.write("\r\x1b[K");
96
+ console.log(
97
+ `${COLORS.red} ✗${COLORS.reset} Failed to connect to gateway. Check your connection.`,
98
+ );
99
+ console.log();
100
+ }
101
+ },
102
+ });
@@ -1,9 +1,12 @@
1
+ export { balanceCmd } from "./balance.ts";
1
2
  export { findCmd, showFindHelp } from "./find.tsx";
2
3
  export { frameCmd, showFrameHelp } from "./frame.tsx";
3
4
  export { helloCmd } from "./hello.ts";
4
5
  export { helpCmd, showHelp } from "./help.tsx";
5
6
  export { initCmd, showInitHelp } from "./init.tsx";
6
7
  export { listCmd, showListHelp } from "./list.tsx";
8
+ export { loginCmd } from "./login.tsx";
9
+ export { logoutCmd } from "./logout.ts";
7
10
  export {
8
11
  previewCmd,
9
12
  renderCmd,
@@ -13,4 +16,5 @@ export {
13
16
  export { runCmd, showRunHelp, showTargetHelp } from "./run.tsx";
14
17
  export { showStoryboardHelp, storyboardCmd } from "./storyboard.tsx";
15
18
  export { studioCmd } from "./studio.ts";
19
+ export { topupCmd } from "./topup.ts";
16
20
  export { showWhichHelp, whichCmd } from "./which.tsx";