varg.ai-sdk 0.1.1 → 0.4.0-alpha.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.
Files changed (246) hide show
  1. package/.claude/settings.local.json +1 -1
  2. package/.env.example +3 -0
  3. package/.github/workflows/ci.yml +23 -0
  4. package/.husky/README.md +102 -0
  5. package/.husky/commit-msg +6 -0
  6. package/.husky/pre-commit +9 -0
  7. package/.husky/pre-push +6 -0
  8. package/.size-limit.json +8 -0
  9. package/.test-hooks.ts +5 -0
  10. package/CLAUDE.md +10 -3
  11. package/CONTRIBUTING.md +150 -0
  12. package/LICENSE.md +53 -0
  13. package/README.md +56 -209
  14. package/SKILLS.md +26 -10
  15. package/biome.json +7 -1
  16. package/bun.lock +1286 -0
  17. package/commitlint.config.js +22 -0
  18. package/docs/index.html +1130 -0
  19. package/docs/prompting.md +326 -0
  20. package/docs/react.md +834 -0
  21. package/docs/sdk.md +812 -0
  22. package/ffmpeg/CLAUDE.md +68 -0
  23. package/package.json +43 -10
  24. package/pipeline/cookbooks/scripts/animate-frames-parallel.ts +84 -0
  25. package/pipeline/cookbooks/scripts/combine-scenes.sh +53 -0
  26. package/pipeline/cookbooks/scripts/generate-frames-parallel.ts +99 -0
  27. package/pipeline/cookbooks/scripts/still-to-video.sh +37 -0
  28. package/pipeline/cookbooks/text-to-tiktok.md +669 -0
  29. package/pipeline/cookbooks/trendwatching.md +156 -0
  30. package/plan.md +281 -0
  31. package/scripts/.gitkeep +0 -0
  32. package/src/ai-sdk/cache.ts +142 -0
  33. package/src/ai-sdk/examples/cached-generation.ts +53 -0
  34. package/src/ai-sdk/examples/duet-scene-4.ts +53 -0
  35. package/src/ai-sdk/examples/duet-scene-5-audio.ts +32 -0
  36. package/src/ai-sdk/examples/duet-video.ts +56 -0
  37. package/src/ai-sdk/examples/editly-composition.ts +63 -0
  38. package/src/ai-sdk/examples/editly-test.ts +57 -0
  39. package/src/ai-sdk/examples/editly-video-test.ts +52 -0
  40. package/src/ai-sdk/examples/fal-lipsync.ts +43 -0
  41. package/src/ai-sdk/examples/higgsfield-image.ts +61 -0
  42. package/src/ai-sdk/examples/music-generation.ts +19 -0
  43. package/src/ai-sdk/examples/openai-sora.ts +34 -0
  44. package/src/ai-sdk/examples/replicate-bg-removal.ts +52 -0
  45. package/src/ai-sdk/examples/simpsons-scene.ts +61 -0
  46. package/src/ai-sdk/examples/talking-lion.ts +55 -0
  47. package/src/ai-sdk/examples/video-generation.ts +39 -0
  48. package/src/ai-sdk/examples/workflow-animated-girl.ts +104 -0
  49. package/src/ai-sdk/examples/workflow-before-after.ts +114 -0
  50. package/src/ai-sdk/examples/workflow-character-grid.ts +112 -0
  51. package/src/ai-sdk/examples/workflow-slideshow.ts +161 -0
  52. package/src/ai-sdk/file-cache.ts +112 -0
  53. package/src/ai-sdk/file.ts +238 -0
  54. package/src/ai-sdk/generate-element.ts +92 -0
  55. package/src/ai-sdk/generate-music.ts +46 -0
  56. package/src/ai-sdk/generate-video.ts +165 -0
  57. package/src/ai-sdk/index.ts +72 -0
  58. package/src/ai-sdk/music-model.ts +110 -0
  59. package/src/ai-sdk/providers/editly/editly.test.ts +1108 -0
  60. package/src/ai-sdk/providers/editly/ffmpeg.ts +60 -0
  61. package/src/ai-sdk/providers/editly/index.ts +817 -0
  62. package/src/ai-sdk/providers/editly/layers.ts +776 -0
  63. package/src/ai-sdk/providers/editly/plan.md +144 -0
  64. package/src/ai-sdk/providers/editly/types.ts +328 -0
  65. package/src/ai-sdk/providers/elevenlabs-provider.ts +255 -0
  66. package/src/ai-sdk/providers/fal-provider.ts +512 -0
  67. package/src/ai-sdk/providers/higgsfield.ts +379 -0
  68. package/src/ai-sdk/providers/openai.ts +251 -0
  69. package/src/ai-sdk/providers/replicate.ts +16 -0
  70. package/src/ai-sdk/video-model.ts +185 -0
  71. package/src/cli/commands/find.tsx +137 -0
  72. package/src/cli/commands/help.tsx +85 -0
  73. package/src/cli/commands/index.ts +6 -0
  74. package/src/cli/commands/list.tsx +238 -0
  75. package/src/cli/commands/render.tsx +71 -0
  76. package/src/cli/commands/run.tsx +511 -0
  77. package/src/cli/commands/which.tsx +253 -0
  78. package/src/cli/index.ts +114 -0
  79. package/src/cli/quiet.ts +44 -0
  80. package/src/cli/types.ts +32 -0
  81. package/src/cli/ui/components/Badge.tsx +29 -0
  82. package/src/cli/ui/components/DataTable.tsx +51 -0
  83. package/src/cli/ui/components/Header.tsx +23 -0
  84. package/src/cli/ui/components/HelpBlock.tsx +44 -0
  85. package/src/cli/ui/components/KeyValue.tsx +33 -0
  86. package/src/cli/ui/components/OptionRow.tsx +81 -0
  87. package/src/cli/ui/components/Separator.tsx +23 -0
  88. package/src/cli/ui/components/StatusBox.tsx +108 -0
  89. package/src/cli/ui/components/VargBox.tsx +51 -0
  90. package/src/cli/ui/components/VargProgress.tsx +36 -0
  91. package/src/cli/ui/components/VargSpinner.tsx +34 -0
  92. package/src/cli/ui/components/VargText.tsx +56 -0
  93. package/src/cli/ui/components/index.ts +19 -0
  94. package/src/cli/ui/index.ts +12 -0
  95. package/src/cli/ui/render.ts +35 -0
  96. package/src/cli/ui/theme.ts +63 -0
  97. package/src/cli/utils.ts +78 -0
  98. package/src/core/executor/executor.ts +201 -0
  99. package/src/core/executor/index.ts +13 -0
  100. package/src/core/executor/job.ts +214 -0
  101. package/src/core/executor/pipeline.ts +222 -0
  102. package/src/core/index.ts +11 -0
  103. package/src/core/registry/index.ts +9 -0
  104. package/src/core/registry/loader.ts +149 -0
  105. package/src/core/registry/registry.ts +221 -0
  106. package/src/core/registry/resolver.ts +206 -0
  107. package/src/core/schema/helpers.ts +134 -0
  108. package/src/core/schema/index.ts +8 -0
  109. package/src/core/schema/shared.ts +102 -0
  110. package/src/core/schema/types.ts +279 -0
  111. package/src/core/schema/validator.ts +92 -0
  112. package/src/definitions/actions/captions.ts +261 -0
  113. package/src/definitions/actions/edit.ts +298 -0
  114. package/src/definitions/actions/image.ts +125 -0
  115. package/src/definitions/actions/index.ts +114 -0
  116. package/src/definitions/actions/music.ts +205 -0
  117. package/src/definitions/actions/sync.ts +128 -0
  118. package/{action/transcribe/index.ts → src/definitions/actions/transcribe.ts} +58 -68
  119. package/src/definitions/actions/upload.ts +111 -0
  120. package/src/definitions/actions/video.ts +163 -0
  121. package/src/definitions/actions/voice.ts +119 -0
  122. package/src/definitions/index.ts +23 -0
  123. package/src/definitions/models/elevenlabs.ts +50 -0
  124. package/src/definitions/models/flux.ts +56 -0
  125. package/src/definitions/models/index.ts +36 -0
  126. package/src/definitions/models/kling.ts +56 -0
  127. package/src/definitions/models/llama.ts +54 -0
  128. package/src/definitions/models/nano-banana-pro.ts +102 -0
  129. package/src/definitions/models/sonauto.ts +68 -0
  130. package/src/definitions/models/soul.ts +65 -0
  131. package/src/definitions/models/wan.ts +54 -0
  132. package/src/definitions/models/whisper.ts +44 -0
  133. package/src/definitions/skills/index.ts +12 -0
  134. package/src/definitions/skills/talking-character.ts +87 -0
  135. package/src/definitions/skills/text-to-tiktok.ts +97 -0
  136. package/src/index.ts +118 -0
  137. package/src/providers/apify.ts +269 -0
  138. package/src/providers/base.ts +264 -0
  139. package/src/providers/elevenlabs.ts +217 -0
  140. package/src/providers/fal.ts +392 -0
  141. package/src/providers/ffmpeg.ts +544 -0
  142. package/src/providers/fireworks.ts +193 -0
  143. package/src/providers/groq.ts +149 -0
  144. package/src/providers/higgsfield.ts +145 -0
  145. package/src/providers/index.ts +143 -0
  146. package/src/providers/replicate.ts +147 -0
  147. package/src/providers/storage.ts +206 -0
  148. package/src/react/cli.ts +52 -0
  149. package/src/react/elements.ts +146 -0
  150. package/src/react/examples/branching.tsx +66 -0
  151. package/src/react/examples/captions-demo.tsx +37 -0
  152. package/src/react/examples/character-video.tsx +84 -0
  153. package/src/react/examples/grid.tsx +53 -0
  154. package/src/react/examples/layouts-demo.tsx +57 -0
  155. package/src/react/examples/madi.tsx +60 -0
  156. package/src/react/examples/music-test.tsx +35 -0
  157. package/src/react/examples/onlyfans-1m/workflow.tsx +88 -0
  158. package/src/react/examples/orange-portrait.tsx +41 -0
  159. package/src/react/examples/split-element-demo.tsx +60 -0
  160. package/src/react/examples/split-layout-demo.tsx +60 -0
  161. package/src/react/examples/split.tsx +41 -0
  162. package/src/react/examples/video-grid.tsx +46 -0
  163. package/src/react/index.ts +43 -0
  164. package/src/react/layouts/grid.tsx +28 -0
  165. package/src/react/layouts/index.ts +2 -0
  166. package/src/react/layouts/split.tsx +20 -0
  167. package/src/react/react.test.ts +309 -0
  168. package/src/react/render.ts +21 -0
  169. package/src/react/renderers/animate.ts +59 -0
  170. package/src/react/renderers/captions.ts +297 -0
  171. package/src/react/renderers/clip.ts +248 -0
  172. package/src/react/renderers/context.ts +17 -0
  173. package/src/react/renderers/image.ts +109 -0
  174. package/src/react/renderers/index.ts +22 -0
  175. package/src/react/renderers/music.ts +60 -0
  176. package/src/react/renderers/packshot.ts +84 -0
  177. package/src/react/renderers/progress.ts +173 -0
  178. package/src/react/renderers/render.ts +243 -0
  179. package/src/react/renderers/slider.ts +69 -0
  180. package/src/react/renderers/speech.ts +53 -0
  181. package/src/react/renderers/split.ts +91 -0
  182. package/src/react/renderers/subtitle.ts +16 -0
  183. package/src/react/renderers/swipe.ts +75 -0
  184. package/src/react/renderers/title.ts +17 -0
  185. package/src/react/renderers/utils.ts +124 -0
  186. package/src/react/renderers/video.ts +127 -0
  187. package/src/react/runtime/jsx-dev-runtime.ts +43 -0
  188. package/src/react/runtime/jsx-runtime.ts +35 -0
  189. package/src/react/types.ts +232 -0
  190. package/src/studio/index.ts +26 -0
  191. package/src/studio/scanner.ts +102 -0
  192. package/src/studio/server.ts +554 -0
  193. package/src/studio/stages.ts +251 -0
  194. package/src/studio/step-renderer.ts +279 -0
  195. package/src/studio/types.ts +60 -0
  196. package/src/studio/ui/cache.html +303 -0
  197. package/src/studio/ui/index.html +1820 -0
  198. package/src/tests/all.test.ts +509 -0
  199. package/src/tests/index.ts +33 -0
  200. package/src/tests/unit.test.ts +403 -0
  201. package/tsconfig.cli.json +8 -0
  202. package/tsconfig.json +21 -3
  203. package/TEST_RESULTS.md +0 -122
  204. package/action/captions/SKILL.md +0 -170
  205. package/action/captions/index.ts +0 -169
  206. package/action/edit/SKILL.md +0 -235
  207. package/action/edit/index.ts +0 -437
  208. package/action/image/SKILL.md +0 -140
  209. package/action/image/index.ts +0 -105
  210. package/action/sync/SKILL.md +0 -136
  211. package/action/sync/index.ts +0 -145
  212. package/action/transcribe/SKILL.md +0 -179
  213. package/action/video/SKILL.md +0 -116
  214. package/action/video/index.ts +0 -125
  215. package/action/voice/SKILL.md +0 -125
  216. package/action/voice/index.ts +0 -136
  217. package/cli/commands/find.ts +0 -58
  218. package/cli/commands/help.ts +0 -70
  219. package/cli/commands/list.ts +0 -49
  220. package/cli/commands/run.ts +0 -237
  221. package/cli/commands/which.ts +0 -66
  222. package/cli/discover.ts +0 -66
  223. package/cli/index.ts +0 -33
  224. package/cli/runner.ts +0 -65
  225. package/cli/types.ts +0 -49
  226. package/cli/ui.ts +0 -185
  227. package/index.ts +0 -75
  228. package/lib/README.md +0 -144
  229. package/lib/ai-sdk/fal.ts +0 -106
  230. package/lib/ai-sdk/replicate.ts +0 -107
  231. package/lib/elevenlabs.ts +0 -382
  232. package/lib/fal.ts +0 -467
  233. package/lib/ffmpeg.ts +0 -467
  234. package/lib/fireworks.ts +0 -235
  235. package/lib/groq.ts +0 -246
  236. package/lib/higgsfield.ts +0 -176
  237. package/lib/remotion/SKILL.md +0 -823
  238. package/lib/remotion/cli.ts +0 -115
  239. package/lib/remotion/functions.ts +0 -283
  240. package/lib/remotion/index.ts +0 -19
  241. package/lib/remotion/templates.ts +0 -73
  242. package/lib/replicate.ts +0 -304
  243. package/output.txt +0 -1
  244. package/test-import.ts +0 -7
  245. package/test-services.ts +0 -97
  246. package/utilities/s3.ts +0 -147
@@ -0,0 +1,253 @@
1
+ /**
2
+ * varg which command
3
+ * Ink-based inspection view
4
+ */
5
+
6
+ import { defineCommand } from "citty";
7
+ import { Box, Text } from "ink";
8
+ import { resolve } from "../../core/registry/resolver.ts";
9
+ import { getCliSchemaInfo, toJsonSchema } from "../../core/schema/helpers.ts";
10
+ import type {
11
+ ActionDefinition,
12
+ Definition,
13
+ ModelDefinition,
14
+ SkillDefinition,
15
+ } from "../../core/schema/types.ts";
16
+ import {
17
+ Badge,
18
+ Header,
19
+ OptionRow,
20
+ Separator,
21
+ VargBox,
22
+ VargText,
23
+ } from "../ui/index.ts";
24
+ import { renderStatic } from "../ui/render.ts";
25
+ import { theme } from "../ui/theme.ts";
26
+
27
+ interface WhichViewProps {
28
+ item: Definition;
29
+ }
30
+
31
+ function InputSchemaView({ schema }: { schema: unknown }) {
32
+ // biome-ignore lint/suspicious/noExplicitAny: Zod v4 type compatibility
33
+ const { properties, required } = getCliSchemaInfo(schema as any);
34
+ return (
35
+ <>
36
+ <Header>INPUT SCHEMA</Header>
37
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
38
+ {Object.entries(properties).map(([key, prop]) => (
39
+ <OptionRow
40
+ key={key}
41
+ name={key}
42
+ description={prop.description}
43
+ required={required.includes(key)}
44
+ defaultValue={prop.default}
45
+ enumValues={prop.enum}
46
+ type={prop.type}
47
+ />
48
+ ))}
49
+ </Box>
50
+ </>
51
+ );
52
+ }
53
+
54
+ function OutputSchemaView({ schema }: { schema: unknown }) {
55
+ // biome-ignore lint/suspicious/noExplicitAny: Zod v4 type compatibility
56
+ const jsonSchema = toJsonSchema(schema as any);
57
+ return (
58
+ <>
59
+ <Header>OUTPUT</Header>
60
+ <Box paddingLeft={2} marginBottom={1}>
61
+ <Text>{jsonSchema.description || "Output result"}</Text>
62
+ </Box>
63
+ </>
64
+ );
65
+ }
66
+
67
+ function WhichView({ item }: WhichViewProps) {
68
+ return (
69
+ <VargBox title={item.name}>
70
+ <Box marginBottom={1}>
71
+ <Text>{item.description}</Text>
72
+ </Box>
73
+
74
+ <Header>TYPE</Header>
75
+ <Box paddingLeft={2} marginBottom={1}>
76
+ <Badge type={item.type} />
77
+ </Box>
78
+
79
+ {/* Providers for models */}
80
+ {item.type === "model" && (
81
+ <>
82
+ <Header>PROVIDERS</Header>
83
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
84
+ <Text>{(item as ModelDefinition).providers.join(", ")}</Text>
85
+ <Text dimColor>
86
+ default: {(item as ModelDefinition).defaultProvider}
87
+ </Text>
88
+ </Box>
89
+ </>
90
+ )}
91
+
92
+ {/* Routes for actions */}
93
+ {item.type === "action" &&
94
+ (item as ActionDefinition).routes.length > 0 && (
95
+ <>
96
+ <Header>ROUTES</Header>
97
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
98
+ {(item as ActionDefinition).routes.map((route) => (
99
+ <Box key={route.target}>
100
+ <Text>
101
+ {"\u2192"} {route.target}
102
+ </Text>
103
+ {route.when && (
104
+ <Text dimColor> when {JSON.stringify(route.when)}</Text>
105
+ )}
106
+ </Box>
107
+ ))}
108
+ </Box>
109
+ </>
110
+ )}
111
+
112
+ {/* Steps for skills */}
113
+ {item.type === "skill" && (
114
+ <>
115
+ <Header>STEPS</Header>
116
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
117
+ {(item as SkillDefinition).steps.map((step, index) => (
118
+ <Box key={step.name}>
119
+ <Text>
120
+ {index + 1}. {step.name} {"\u2192"} {step.run}
121
+ </Text>
122
+ </Box>
123
+ ))}
124
+ </Box>
125
+ </>
126
+ )}
127
+
128
+ {/* Input schema */}
129
+ <InputSchemaView schema={item.schema.input} />
130
+
131
+ {/* Output */}
132
+ <OutputSchemaView schema={item.schema.output} />
133
+
134
+ <Separator />
135
+ <Box marginTop={1}>
136
+ <Text dimColor>run with </Text>
137
+ <Text color={theme.colors.accent}>varg run {item.name} [options]</Text>
138
+ </Box>
139
+ </VargBox>
140
+ );
141
+ }
142
+
143
+ function NotFoundView({
144
+ name,
145
+ suggestions,
146
+ }: {
147
+ name: string;
148
+ suggestions?: string[];
149
+ }) {
150
+ return (
151
+ <Box flexDirection="column" padding={1}>
152
+ <VargText variant="error">not found: '{name}'</VargText>
153
+ {suggestions && suggestions.length > 0 && (
154
+ <Box marginTop={1}>
155
+ <Text>did you mean: {suggestions.slice(0, 3).join(", ")}?</Text>
156
+ </Box>
157
+ )}
158
+ </Box>
159
+ );
160
+ }
161
+
162
+ /** Help view for which command */
163
+ function WhichHelpView() {
164
+ return (
165
+ <VargBox title="varg which">
166
+ <Box marginBottom={1}>
167
+ <Text>inspect a model, action, or skill</Text>
168
+ </Box>
169
+
170
+ <Header>USAGE</Header>
171
+ <Box paddingLeft={2} marginBottom={1}>
172
+ <VargText variant="accent">varg which {"<name>"} [--json]</VargText>
173
+ </Box>
174
+
175
+ <Header>ARGUMENTS</Header>
176
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
177
+ <Text>name name of item to inspect</Text>
178
+ </Box>
179
+
180
+ <Header>OPTIONS</Header>
181
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
182
+ <Text>--json output as json</Text>
183
+ </Box>
184
+
185
+ <Header>EXAMPLES</Header>
186
+ <Box flexDirection="column" paddingLeft={2}>
187
+ <Box flexDirection="column" marginBottom={1}>
188
+ <Text dimColor># inspect video action</Text>
189
+ <VargText variant="accent">varg which video</VargText>
190
+ </Box>
191
+ <Box flexDirection="column">
192
+ <Text dimColor># get json schema</Text>
193
+ <VargText variant="accent">varg which flux --json</VargText>
194
+ </Box>
195
+ </Box>
196
+ </VargBox>
197
+ );
198
+ }
199
+
200
+ /** Show which command help */
201
+ export function showWhichHelp() {
202
+ renderStatic(<WhichHelpView />);
203
+ }
204
+
205
+ export const whichCmd = defineCommand({
206
+ meta: {
207
+ name: "which",
208
+ description: "inspect a model, action, or skill",
209
+ },
210
+ args: {
211
+ name: {
212
+ type: "positional",
213
+ description: "name to inspect",
214
+ required: false,
215
+ },
216
+ json: {
217
+ type: "boolean",
218
+ description: "output as json",
219
+ },
220
+ },
221
+ async run({ args, rawArgs }) {
222
+ // Handle --help
223
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
224
+ showWhichHelp();
225
+ return;
226
+ }
227
+
228
+ const name = args.name as string;
229
+
230
+ if (!name) {
231
+ showWhichHelp();
232
+ return;
233
+ }
234
+
235
+ const result = resolve(name, { fuzzy: true });
236
+
237
+ if (!result.definition) {
238
+ renderStatic(
239
+ <NotFoundView name={name} suggestions={result.suggestions} />,
240
+ );
241
+ process.exit(1);
242
+ }
243
+
244
+ const item = result.definition;
245
+
246
+ if (args.json) {
247
+ console.log(JSON.stringify(item, null, 2));
248
+ return;
249
+ }
250
+
251
+ renderStatic(<WhichView item={item} />);
252
+ },
253
+ });
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * varg cli
5
+ * ai video infrastructure from your terminal
6
+ */
7
+
8
+ // Must be first import to suppress logs before other modules load
9
+ import "./quiet";
10
+
11
+ import { defineCommand, runMain } from "citty";
12
+ import { registry } from "../core/registry";
13
+ import { allDefinitions } from "../definitions";
14
+ import {
15
+ findCmd,
16
+ helpCmd,
17
+ listCmd,
18
+ renderCmd,
19
+ runCmd,
20
+ showFindHelp,
21
+ showHelp,
22
+ showListHelp,
23
+ showRunHelp,
24
+ showTargetHelp,
25
+ showWhichHelp,
26
+ whichCmd,
27
+ } from "./commands";
28
+
29
+ // Register all providers
30
+ import "../providers"; // Side effect: registers providers to base registry
31
+ import { providers } from "../providers/base";
32
+
33
+ // Register all definitions
34
+ for (const definition of allDefinitions) {
35
+ registry.register(definition);
36
+ }
37
+
38
+ // Also register providers to core registry
39
+ for (const provider of providers.all()) {
40
+ registry.registerProvider(provider);
41
+ }
42
+
43
+ // Intercept --help and -h to use our custom help views
44
+ const args = process.argv.slice(2);
45
+ const hasHelp = args.includes("--help") || args.includes("-h");
46
+
47
+ // Map subcommands to their help functions
48
+ const subcommandHelp: Record<string, () => void> = {
49
+ run: showRunHelp,
50
+ list: showListHelp,
51
+ ls: showListHelp,
52
+ find: showFindHelp,
53
+ search: showFindHelp,
54
+ which: showWhichHelp,
55
+ inspect: showWhichHelp,
56
+ };
57
+
58
+ // Handle help for root or subcommands
59
+ if (args.length === 0 || args[0] === "help") {
60
+ showHelp();
61
+ process.exit(0);
62
+ }
63
+
64
+ if (hasHelp) {
65
+ const subcommand = args[0];
66
+ // Root --help
67
+ if (subcommand === "--help" || subcommand === "-h") {
68
+ showHelp();
69
+ process.exit(0);
70
+ }
71
+
72
+ // Handle subcommand help
73
+ if (subcommand && subcommand in subcommandHelp) {
74
+ const nonHelpArgs = args.filter((a) => a !== "--help" && a !== "-h");
75
+
76
+ // "varg run --help" - show run help
77
+ if (nonHelpArgs.length === 1) {
78
+ const helpFn = subcommandHelp[subcommand];
79
+ if (helpFn) {
80
+ helpFn();
81
+ process.exit(0);
82
+ }
83
+ }
84
+
85
+ // "varg run <target> --help" - show target-specific help
86
+ if (subcommand === "run" && nonHelpArgs.length === 2) {
87
+ const target = nonHelpArgs[1];
88
+ if (target && showTargetHelp(target)) {
89
+ process.exit(0);
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ const main = defineCommand({
96
+ meta: {
97
+ name: "varg",
98
+ version: "0.3.0",
99
+ description: "ai video infrastructure from your terminal",
100
+ },
101
+ subCommands: {
102
+ run: runCmd,
103
+ render: renderCmd,
104
+ list: listCmd,
105
+ ls: listCmd,
106
+ find: findCmd,
107
+ search: findCmd,
108
+ which: whichCmd,
109
+ inspect: whichCmd,
110
+ help: helpCmd,
111
+ },
112
+ });
113
+
114
+ runMain(main);
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Quiet mode setup - must be imported first
3
+ * Suppresses console.log for --json and --quiet modes
4
+ */
5
+
6
+ const args = process.argv.slice(2);
7
+ export const isQuietMode = args.includes("--json") || args.includes("--quiet");
8
+
9
+ // Store original write function
10
+ const _originalWrite = process.stdout.write.bind(process.stdout);
11
+
12
+ if (isQuietMode) {
13
+ // Override process.stdout.write to filter non-JSON output
14
+ process.stdout.write = ((
15
+ // biome-ignore lint/suspicious/noExplicitAny: complex overload signature
16
+ chunk: any,
17
+ // biome-ignore lint/suspicious/noExplicitAny: complex overload signature
18
+ encoding?: any,
19
+ // biome-ignore lint/suspicious/noExplicitAny: complex overload signature
20
+ callback?: any,
21
+ ): boolean => {
22
+ const str = typeof chunk === "string" ? chunk : chunk.toString();
23
+ const trimmed = str.trim();
24
+
25
+ // Only allow JSON output (starts with { or [) or empty lines
26
+ if (trimmed === "" || trimmed.startsWith("{") || trimmed.startsWith("[")) {
27
+ return _originalWrite(chunk, encoding, callback);
28
+ }
29
+
30
+ // Suppress non-JSON output, still call callback if provided
31
+ if (typeof encoding === "function") {
32
+ encoding();
33
+ } else if (callback) {
34
+ callback();
35
+ }
36
+ return true;
37
+ }) as typeof process.stdout.write;
38
+ }
39
+
40
+ // Export for direct output when needed (bypasses quiet mode)
41
+ export function rawLog(...args: unknown[]): void {
42
+ const message = `${args.map(String).join(" ")}\n`;
43
+ _originalWrite(message);
44
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * CLI type definitions
3
+ */
4
+
5
+ export interface NotFoundOptions {
6
+ /** Suggested alternatives */
7
+ suggestions?: string[];
8
+ /** Max number of suggestions to show */
9
+ maxSuggestions?: number;
10
+ /** Custom hint message */
11
+ hint?: string;
12
+ /** Color function for error text */
13
+ errorColorFn?: (s: string) => string;
14
+ /** Color function for hints */
15
+ hintColorFn?: (s: string) => string;
16
+ /** Whether to exit process (default: true) */
17
+ exit?: boolean;
18
+ }
19
+
20
+ export interface JsonSchemaProperty {
21
+ type?: string;
22
+ description?: string;
23
+ default?: unknown;
24
+ enum?: string[];
25
+ }
26
+
27
+ export interface JsonSchema {
28
+ type?: string;
29
+ properties?: Record<string, JsonSchemaProperty>;
30
+ required?: string[];
31
+ description?: string;
32
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Badge - Type indicator badge
3
+ * Shows [model] [action] [skill] with appropriate styling
4
+ */
5
+
6
+ import { Text } from "ink";
7
+ import { theme } from "../theme.ts";
8
+
9
+ type BadgeType = "model" | "action" | "skill";
10
+
11
+ interface BadgeProps {
12
+ type: BadgeType;
13
+ }
14
+
15
+ const badgeColors: Record<BadgeType, string> = {
16
+ model: theme.colors.accent,
17
+ action: theme.colors.success,
18
+ skill: theme.colors.warning,
19
+ };
20
+
21
+ export function Badge({ type }: BadgeProps) {
22
+ return (
23
+ <Text color={badgeColors[type]} dimColor>
24
+ [{type}]
25
+ </Text>
26
+ );
27
+ }
28
+
29
+ export default Badge;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * DataTable - Table display component
3
+ * Clean text-based table for listing items
4
+ */
5
+
6
+ import { Box, Text } from "ink";
7
+ import { Badge } from "./Badge.tsx";
8
+ import { VargText } from "./VargText.tsx";
9
+
10
+ interface TableRow {
11
+ name: string;
12
+ description: string;
13
+ type?: "model" | "action" | "skill";
14
+ }
15
+
16
+ interface DataTableProps {
17
+ rows: TableRow[];
18
+ showType?: boolean;
19
+ }
20
+
21
+ export function DataTable({ rows, showType = false }: DataTableProps) {
22
+ if (rows.length === 0) {
23
+ return (
24
+ <Box paddingLeft={2}>
25
+ <VargText variant="muted">no items</VargText>
26
+ </Box>
27
+ );
28
+ }
29
+
30
+ // Calculate max name width for alignment
31
+ const maxNameWidth = Math.max(...rows.map((r) => r.name.length), 12);
32
+
33
+ return (
34
+ <Box flexDirection="column">
35
+ {rows.map((row) => (
36
+ <Box key={row.name} paddingLeft={2}>
37
+ {showType && row.type && (
38
+ <>
39
+ <Badge type={row.type} />
40
+ <Text> </Text>
41
+ </>
42
+ )}
43
+ <Text bold>{row.name.padEnd(maxNameWidth)}</Text>
44
+ <VargText variant="muted"> {row.description}</VargText>
45
+ </Box>
46
+ ))}
47
+ </Box>
48
+ );
49
+ }
50
+
51
+ export default DataTable;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Header - Section header component
3
+ * Bold dimmed text for section titles
4
+ */
5
+
6
+ import { Box, Text } from "ink";
7
+ import type { ReactNode } from "react";
8
+
9
+ interface HeaderProps {
10
+ children: ReactNode;
11
+ }
12
+
13
+ export function Header({ children }: HeaderProps) {
14
+ return (
15
+ <Box>
16
+ <Text bold dimColor>
17
+ {children}
18
+ </Text>
19
+ </Box>
20
+ );
21
+ }
22
+
23
+ export default Header;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * HelpBlock - Command help and examples
3
+ * Displays usage patterns and command examples
4
+ */
5
+
6
+ import { Box, Text } from "ink";
7
+ import { VargText } from "./VargText.tsx";
8
+
9
+ interface HelpBlockProps {
10
+ usage?: string;
11
+ examples?: Array<{ command: string; description?: string }>;
12
+ }
13
+
14
+ export function HelpBlock({ usage, examples }: HelpBlockProps) {
15
+ return (
16
+ <Box flexDirection="column">
17
+ {usage && (
18
+ <Box marginBottom={1}>
19
+ <VargText variant="muted">usage: </VargText>
20
+ <VargText variant="accent">{usage}</VargText>
21
+ </Box>
22
+ )}
23
+
24
+ {examples && examples.length > 0 && (
25
+ <Box flexDirection="column">
26
+ {examples.map((ex) => (
27
+ <Box key={ex.command} flexDirection="column" marginBottom={1}>
28
+ {ex.description && (
29
+ <Box paddingLeft={2}>
30
+ <Text dimColor># {ex.description}</Text>
31
+ </Box>
32
+ )}
33
+ <Box paddingLeft={2}>
34
+ <VargText variant="accent">{ex.command}</VargText>
35
+ </Box>
36
+ </Box>
37
+ ))}
38
+ </Box>
39
+ )}
40
+ </Box>
41
+ );
42
+ }
43
+
44
+ export default HelpBlock;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * KeyValue - Label-value pair display
3
+ * Aligned key-value pairs with optional required marker
4
+ */
5
+
6
+ import { Box, Text } from "ink";
7
+ import { theme } from "../theme.ts";
8
+
9
+ interface KeyValueProps {
10
+ label: string;
11
+ value: string;
12
+ labelWidth?: number;
13
+ required?: boolean;
14
+ }
15
+
16
+ export function KeyValue({
17
+ label,
18
+ value,
19
+ labelWidth = theme.layout.optionNameWidth,
20
+ required = false,
21
+ }: KeyValueProps) {
22
+ const paddedLabel = label.padEnd(labelWidth);
23
+
24
+ return (
25
+ <Box>
26
+ <Text dimColor>{paddedLabel}</Text>
27
+ {required && <Text color={theme.colors.warning}>* </Text>}
28
+ <Text>{value}</Text>
29
+ </Box>
30
+ );
31
+ }
32
+
33
+ export default KeyValue;