vargai 0.3.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.
Files changed (154) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.env.example +27 -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 +125 -0
  11. package/CONTRIBUTING.md +150 -0
  12. package/LICENSE.md +53 -0
  13. package/README.md +78 -0
  14. package/SKILLS.md +173 -0
  15. package/STRUCTURE.md +92 -0
  16. package/biome.json +34 -0
  17. package/bun.lock +1254 -0
  18. package/commitlint.config.js +22 -0
  19. package/docs/plan.md +66 -0
  20. package/docs/todo.md +14 -0
  21. package/docs/varg-sdk.md +812 -0
  22. package/ffmpeg/CLAUDE.md +68 -0
  23. package/package.json +69 -0
  24. package/pipeline/cookbooks/SKILL.md +285 -0
  25. package/pipeline/cookbooks/remotion-video.md +585 -0
  26. package/pipeline/cookbooks/round-video-character.md +337 -0
  27. package/pipeline/cookbooks/scripts/animate-frames-parallel.ts +84 -0
  28. package/pipeline/cookbooks/scripts/combine-scenes.sh +53 -0
  29. package/pipeline/cookbooks/scripts/generate-frames-parallel.ts +99 -0
  30. package/pipeline/cookbooks/scripts/still-to-video.sh +37 -0
  31. package/pipeline/cookbooks/talking-character.md +59 -0
  32. package/pipeline/cookbooks/text-to-tiktok.md +669 -0
  33. package/pipeline/cookbooks/trendwatching.md +156 -0
  34. package/plan.md +281 -0
  35. package/scripts/.gitkeep +0 -0
  36. package/src/ai-sdk/cache.ts +142 -0
  37. package/src/ai-sdk/examples/cached-generation.ts +53 -0
  38. package/src/ai-sdk/examples/duet-scene-4.ts +53 -0
  39. package/src/ai-sdk/examples/duet-scene-5-audio.ts +32 -0
  40. package/src/ai-sdk/examples/duet-video.ts +56 -0
  41. package/src/ai-sdk/examples/editly-composition.ts +63 -0
  42. package/src/ai-sdk/examples/editly-test.ts +57 -0
  43. package/src/ai-sdk/examples/editly-video-test.ts +52 -0
  44. package/src/ai-sdk/examples/fal-lipsync.ts +43 -0
  45. package/src/ai-sdk/examples/higgsfield-image.ts +61 -0
  46. package/src/ai-sdk/examples/music-generation.ts +19 -0
  47. package/src/ai-sdk/examples/openai-sora.ts +34 -0
  48. package/src/ai-sdk/examples/replicate-bg-removal.ts +52 -0
  49. package/src/ai-sdk/examples/simpsons-scene.ts +61 -0
  50. package/src/ai-sdk/examples/talking-lion.ts +55 -0
  51. package/src/ai-sdk/examples/video-generation.ts +39 -0
  52. package/src/ai-sdk/examples/workflow-animated-girl.ts +104 -0
  53. package/src/ai-sdk/examples/workflow-before-after.ts +114 -0
  54. package/src/ai-sdk/examples/workflow-character-grid.ts +112 -0
  55. package/src/ai-sdk/examples/workflow-slideshow.ts +161 -0
  56. package/src/ai-sdk/file-cache.ts +112 -0
  57. package/src/ai-sdk/file.ts +238 -0
  58. package/src/ai-sdk/generate-element.ts +92 -0
  59. package/src/ai-sdk/generate-music.ts +46 -0
  60. package/src/ai-sdk/generate-video.ts +165 -0
  61. package/src/ai-sdk/index.ts +72 -0
  62. package/src/ai-sdk/music-model.ts +110 -0
  63. package/src/ai-sdk/providers/editly/editly.test.ts +1108 -0
  64. package/src/ai-sdk/providers/editly/ffmpeg.ts +60 -0
  65. package/src/ai-sdk/providers/editly/index.ts +817 -0
  66. package/src/ai-sdk/providers/editly/layers.ts +772 -0
  67. package/src/ai-sdk/providers/editly/plan.md +144 -0
  68. package/src/ai-sdk/providers/editly/types.ts +328 -0
  69. package/src/ai-sdk/providers/elevenlabs-provider.ts +255 -0
  70. package/src/ai-sdk/providers/fal-provider.ts +512 -0
  71. package/src/ai-sdk/providers/higgsfield.ts +379 -0
  72. package/src/ai-sdk/providers/openai.ts +251 -0
  73. package/src/ai-sdk/providers/replicate.ts +16 -0
  74. package/src/ai-sdk/video-model.ts +185 -0
  75. package/src/cli/commands/find.tsx +137 -0
  76. package/src/cli/commands/help.tsx +85 -0
  77. package/src/cli/commands/index.ts +9 -0
  78. package/src/cli/commands/list.tsx +238 -0
  79. package/src/cli/commands/run.tsx +511 -0
  80. package/src/cli/commands/which.tsx +253 -0
  81. package/src/cli/index.ts +112 -0
  82. package/src/cli/quiet.ts +44 -0
  83. package/src/cli/types.ts +32 -0
  84. package/src/cli/ui/components/Badge.tsx +29 -0
  85. package/src/cli/ui/components/DataTable.tsx +51 -0
  86. package/src/cli/ui/components/Header.tsx +23 -0
  87. package/src/cli/ui/components/HelpBlock.tsx +44 -0
  88. package/src/cli/ui/components/KeyValue.tsx +33 -0
  89. package/src/cli/ui/components/OptionRow.tsx +81 -0
  90. package/src/cli/ui/components/Separator.tsx +23 -0
  91. package/src/cli/ui/components/StatusBox.tsx +108 -0
  92. package/src/cli/ui/components/VargBox.tsx +51 -0
  93. package/src/cli/ui/components/VargProgress.tsx +36 -0
  94. package/src/cli/ui/components/VargSpinner.tsx +34 -0
  95. package/src/cli/ui/components/VargText.tsx +56 -0
  96. package/src/cli/ui/components/index.ts +19 -0
  97. package/src/cli/ui/index.ts +12 -0
  98. package/src/cli/ui/render.ts +35 -0
  99. package/src/cli/ui/theme.ts +63 -0
  100. package/src/cli/utils.ts +78 -0
  101. package/src/core/executor/executor.ts +201 -0
  102. package/src/core/executor/index.ts +13 -0
  103. package/src/core/executor/job.ts +214 -0
  104. package/src/core/executor/pipeline.ts +222 -0
  105. package/src/core/index.ts +11 -0
  106. package/src/core/registry/index.ts +9 -0
  107. package/src/core/registry/loader.ts +149 -0
  108. package/src/core/registry/registry.ts +221 -0
  109. package/src/core/registry/resolver.ts +206 -0
  110. package/src/core/schema/helpers.ts +134 -0
  111. package/src/core/schema/index.ts +8 -0
  112. package/src/core/schema/shared.ts +102 -0
  113. package/src/core/schema/types.ts +279 -0
  114. package/src/core/schema/validator.ts +92 -0
  115. package/src/definitions/actions/captions.ts +261 -0
  116. package/src/definitions/actions/edit.ts +298 -0
  117. package/src/definitions/actions/image.ts +125 -0
  118. package/src/definitions/actions/index.ts +114 -0
  119. package/src/definitions/actions/music.ts +205 -0
  120. package/src/definitions/actions/sync.ts +128 -0
  121. package/src/definitions/actions/transcribe.ts +200 -0
  122. package/src/definitions/actions/upload.ts +111 -0
  123. package/src/definitions/actions/video.ts +163 -0
  124. package/src/definitions/actions/voice.ts +119 -0
  125. package/src/definitions/index.ts +23 -0
  126. package/src/definitions/models/elevenlabs.ts +50 -0
  127. package/src/definitions/models/flux.ts +56 -0
  128. package/src/definitions/models/index.ts +36 -0
  129. package/src/definitions/models/kling.ts +56 -0
  130. package/src/definitions/models/llama.ts +54 -0
  131. package/src/definitions/models/nano-banana-pro.ts +102 -0
  132. package/src/definitions/models/sonauto.ts +68 -0
  133. package/src/definitions/models/soul.ts +65 -0
  134. package/src/definitions/models/wan.ts +54 -0
  135. package/src/definitions/models/whisper.ts +44 -0
  136. package/src/definitions/skills/index.ts +12 -0
  137. package/src/definitions/skills/talking-character.ts +87 -0
  138. package/src/definitions/skills/text-to-tiktok.ts +97 -0
  139. package/src/index.ts +118 -0
  140. package/src/providers/apify.ts +269 -0
  141. package/src/providers/base.ts +264 -0
  142. package/src/providers/elevenlabs.ts +217 -0
  143. package/src/providers/fal.ts +392 -0
  144. package/src/providers/ffmpeg.ts +544 -0
  145. package/src/providers/fireworks.ts +193 -0
  146. package/src/providers/groq.ts +149 -0
  147. package/src/providers/higgsfield.ts +145 -0
  148. package/src/providers/index.ts +143 -0
  149. package/src/providers/replicate.ts +147 -0
  150. package/src/providers/storage.ts +206 -0
  151. package/src/tests/all.test.ts +509 -0
  152. package/src/tests/index.ts +33 -0
  153. package/src/tests/unit.test.ts +403 -0
  154. package/tsconfig.json +45 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * VideoModelV3 - Extension to AI SDK for video generation
3
+ *
4
+ * This follows the same patterns as ImageModelV3 but adds video-specific
5
+ * options like duration, fps, and supports multimodal inputs via `files`.
6
+ *
7
+ * When upstream merges video support, we can migrate to their types.
8
+ */
9
+
10
+ import type {
11
+ ImageModelV3File,
12
+ JSONArray,
13
+ JSONValue,
14
+ SharedV3ProviderOptions,
15
+ SharedV3Warning,
16
+ } from "@ai-sdk/provider";
17
+
18
+ /**
19
+ * Re-export ImageModelV3File as VideoModelV3File for clarity.
20
+ * They're the same type - works for image, audio, and video inputs.
21
+ */
22
+ export type VideoModelV3File = ImageModelV3File;
23
+
24
+ // ============================================================================
25
+ // Call Options
26
+ // ============================================================================
27
+
28
+ export type VideoModelV3CallOptions = {
29
+ /**
30
+ * Prompt for the video generation.
31
+ */
32
+ prompt: string;
33
+
34
+ /**
35
+ * Number of videos to generate.
36
+ */
37
+ n: number;
38
+
39
+ /**
40
+ * Resolution of the videos to generate.
41
+ * Must have the format `{width}x{height}`.
42
+ * `undefined` will use the provider's default resolution.
43
+ */
44
+ resolution: `${number}x${number}` | undefined;
45
+
46
+ /**
47
+ * Aspect ratio of the videos to generate.
48
+ * Must have the format `{width}:{height}`.
49
+ * `undefined` will use the provider's default aspect ratio.
50
+ */
51
+ aspectRatio: `${number}:${number}` | undefined;
52
+
53
+ /**
54
+ * Duration of the generated video in seconds.
55
+ * `undefined` will use the provider's default duration.
56
+ */
57
+ duration: number | undefined;
58
+
59
+ /**
60
+ * Frames per second of the generated video.
61
+ * `undefined` will use the provider's default FPS.
62
+ */
63
+ fps: number | undefined;
64
+
65
+ /**
66
+ * Seed for the generation.
67
+ * `undefined` will use the provider's default seed.
68
+ */
69
+ seed: number | undefined;
70
+
71
+ /**
72
+ * Input files for video generation.
73
+ * - Images: for image-to-video generation
74
+ * - Audio: for audio-reactive video generation
75
+ * - Video: for video-to-video style transfer, extension, etc.
76
+ */
77
+ files: VideoModelV3File[] | undefined;
78
+
79
+ /**
80
+ * Additional provider-specific options.
81
+ */
82
+ providerOptions: SharedV3ProviderOptions;
83
+
84
+ /**
85
+ * Abort signal for cancelling the operation.
86
+ */
87
+ abortSignal?: AbortSignal;
88
+
89
+ /**
90
+ * Additional HTTP headers to be sent with the request.
91
+ */
92
+ headers?: Record<string, string | undefined>;
93
+ };
94
+
95
+ // ============================================================================
96
+ // Provider Metadata
97
+ // ============================================================================
98
+
99
+ export type VideoModelV3ProviderMetadata = Record<
100
+ string,
101
+ {
102
+ videos: JSONArray;
103
+ } & JSONValue
104
+ >;
105
+
106
+ // ============================================================================
107
+ // Usage
108
+ // ============================================================================
109
+
110
+ export type VideoModelV3Usage = {
111
+ /** Input tokens used (if applicable) */
112
+ inputTokens?: number;
113
+ /** Output tokens used (if applicable) */
114
+ outputTokens?: number;
115
+ /** Total tokens used */
116
+ totalTokens?: number;
117
+ };
118
+
119
+ // ============================================================================
120
+ // Model Interface
121
+ // ============================================================================
122
+
123
+ type GetMaxVideosPerCallFunction = (options: {
124
+ modelId: string;
125
+ }) => PromiseLike<number | undefined> | number | undefined;
126
+
127
+ /**
128
+ * Video generation model specification version 3.
129
+ * Follows the same patterns as ImageModelV3.
130
+ */
131
+ export type VideoModelV3 = {
132
+ /**
133
+ * The video model must specify which video model interface version it implements.
134
+ */
135
+ readonly specificationVersion: "v3";
136
+
137
+ /**
138
+ * Name of the provider for logging purposes.
139
+ */
140
+ readonly provider: string;
141
+
142
+ /**
143
+ * Provider-specific model ID for logging purposes.
144
+ */
145
+ readonly modelId: string;
146
+
147
+ /**
148
+ * Limit of how many videos can be generated in a single API call.
149
+ */
150
+ readonly maxVideosPerCall: number | undefined | GetMaxVideosPerCallFunction;
151
+
152
+ /**
153
+ * Generates videos.
154
+ */
155
+ doGenerate(options: VideoModelV3CallOptions): PromiseLike<{
156
+ /**
157
+ * Generated videos as base64 encoded strings or binary data.
158
+ */
159
+ videos: Array<string> | Array<Uint8Array>;
160
+
161
+ /**
162
+ * Warnings for the call, e.g. unsupported features.
163
+ */
164
+ warnings: Array<SharedV3Warning>;
165
+
166
+ /**
167
+ * Additional provider-specific metadata.
168
+ */
169
+ providerMetadata?: VideoModelV3ProviderMetadata;
170
+
171
+ /**
172
+ * Response information for telemetry and debugging purposes.
173
+ */
174
+ response: {
175
+ timestamp: Date;
176
+ modelId: string;
177
+ headers: Record<string, string> | undefined;
178
+ };
179
+
180
+ /**
181
+ * Optional token usage for the video generation call.
182
+ */
183
+ usage?: VideoModelV3Usage;
184
+ }>;
185
+ };
@@ -0,0 +1,137 @@
1
+ /**
2
+ * varg find command
3
+ * Ink-based search view
4
+ */
5
+
6
+ import { defineCommand } from "citty";
7
+ import { Box, Text } from "ink";
8
+ import { registry } from "../../core/registry/index.ts";
9
+ import { DataTable, Header, VargBox, VargText } from "../ui/index.ts";
10
+ import { renderStatic } from "../ui/render.ts";
11
+
12
+ interface FindViewProps {
13
+ query: string;
14
+ results: Array<{ name: string; description: string; type: string }>;
15
+ }
16
+
17
+ function FindView({ query, results }: FindViewProps) {
18
+ return (
19
+ <VargBox title={`search: ${query}`}>
20
+ <DataTable
21
+ rows={results.map((r) => ({
22
+ name: r.name,
23
+ description: r.description,
24
+ type: r.type as "model" | "action" | "skill",
25
+ }))}
26
+ showType
27
+ />
28
+ <Box marginTop={1}>
29
+ <VargText variant="muted">
30
+ {results.length} result{results.length > 1 ? "s" : ""}
31
+ </VargText>
32
+ </Box>
33
+ </VargBox>
34
+ );
35
+ }
36
+
37
+ function NoResultsView({ query }: { query: string }) {
38
+ return (
39
+ <Box flexDirection="column" padding={1}>
40
+ <VargText variant="warning">no results found for</VargText>
41
+ <Text> '{query}'</Text>
42
+ <Box marginTop={1}>
43
+ <VargText variant="muted">try </VargText>
44
+ <VargText variant="accent">varg list</VargText>
45
+ <VargText variant="muted"> to see all available items</VargText>
46
+ </Box>
47
+ </Box>
48
+ );
49
+ }
50
+
51
+ /** Help view for find command */
52
+ function FindHelpView() {
53
+ return (
54
+ <VargBox title="varg find">
55
+ <Box marginBottom={1}>
56
+ <Text>search for models, actions, and skills</Text>
57
+ </Box>
58
+
59
+ <Header>USAGE</Header>
60
+ <Box paddingLeft={2} marginBottom={1}>
61
+ <VargText variant="accent">
62
+ varg find {"<query>"} [--type type]
63
+ </VargText>
64
+ </Box>
65
+
66
+ <Header>ARGUMENTS</Header>
67
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
68
+ <Text>query search term to find</Text>
69
+ </Box>
70
+
71
+ <Header>OPTIONS</Header>
72
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
73
+ <Text>--type filter by type: model, action, skill</Text>
74
+ </Box>
75
+
76
+ <Header>EXAMPLES</Header>
77
+ <Box flexDirection="column" paddingLeft={2}>
78
+ <Box flexDirection="column" marginBottom={1}>
79
+ <Text dimColor># search for video-related items</Text>
80
+ <VargText variant="accent">varg find video</VargText>
81
+ </Box>
82
+ <Box flexDirection="column">
83
+ <Text dimColor># search only in models</Text>
84
+ <VargText variant="accent">varg find flux --type model</VargText>
85
+ </Box>
86
+ </Box>
87
+ </VargBox>
88
+ );
89
+ }
90
+
91
+ /** Show find command help */
92
+ export function showFindHelp() {
93
+ renderStatic(<FindHelpView />);
94
+ }
95
+
96
+ export const findCmd = defineCommand({
97
+ meta: {
98
+ name: "find",
99
+ description: "search for models, actions, and skills",
100
+ },
101
+ args: {
102
+ query: {
103
+ type: "positional",
104
+ description: "search query",
105
+ required: false,
106
+ },
107
+ type: {
108
+ type: "string",
109
+ description: "filter by type (model, action, skill)",
110
+ },
111
+ },
112
+ async run({ args, rawArgs }) {
113
+ // Handle --help
114
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
115
+ showFindHelp();
116
+ return;
117
+ }
118
+
119
+ const query = args.query as string;
120
+
121
+ if (!query) {
122
+ showFindHelp();
123
+ return;
124
+ }
125
+
126
+ const type = args.type as "model" | "action" | "skill" | undefined;
127
+
128
+ const results = registry.search(query, { type });
129
+
130
+ if (results.length === 0) {
131
+ renderStatic(<NoResultsView query={query} />);
132
+ return;
133
+ }
134
+
135
+ renderStatic(<FindView query={query} results={results} />);
136
+ },
137
+ });
@@ -0,0 +1,85 @@
1
+ /**
2
+ * varg help command
3
+ * Ink-based help display
4
+ */
5
+
6
+ import { defineCommand } from "citty";
7
+ import { Box, Text } from "ink";
8
+ import { Header, HelpBlock, VargBox, VargText } from "../ui/index.ts";
9
+ import { renderStatic } from "../ui/render.ts";
10
+
11
+ interface CommandRowProps {
12
+ name: string;
13
+ description: string;
14
+ }
15
+
16
+ function CommandRow({ name, description }: CommandRowProps) {
17
+ return (
18
+ <Box paddingLeft={2}>
19
+ <VargText variant="accent">{name.padEnd(12)}</VargText>
20
+ <Text>{description}</Text>
21
+ </Box>
22
+ );
23
+ }
24
+
25
+ function HelpView() {
26
+ const examples = [
27
+ {
28
+ command: 'varg run video --prompt "ocean waves"',
29
+ description: "generate a video from text",
30
+ },
31
+ {
32
+ command: 'varg run video --prompt "person talking" --image photo.jpg',
33
+ description: "generate video from image",
34
+ },
35
+ {
36
+ command: 'varg run voice --text "hello world" --voice sam',
37
+ description: "text to speech",
38
+ },
39
+ { command: "varg list", description: "see all available" },
40
+ {
41
+ command: "varg which video",
42
+ description: "inspect an action or model",
43
+ },
44
+ ];
45
+
46
+ return (
47
+ <VargBox title="varg">
48
+ <Box marginBottom={1}>
49
+ <Text>ai video infrastructure from your terminal</Text>
50
+ </Box>
51
+
52
+ <Header>COMMANDS</Header>
53
+ <Box flexDirection="column" marginY={1}>
54
+ <CommandRow name="run" description="run a model, action, or skill" />
55
+ <CommandRow name="list" description="discover what's available" />
56
+ <CommandRow
57
+ name="find"
58
+ description="search for models, actions, skills"
59
+ />
60
+ <CommandRow name="which" description="inspect a specific item" />
61
+ <CommandRow name="help" description="show this help" />
62
+ </Box>
63
+
64
+ <Header>EXAMPLES</Header>
65
+ <Box marginTop={1}>
66
+ <HelpBlock examples={examples} />
67
+ </Box>
68
+ </VargBox>
69
+ );
70
+ }
71
+
72
+ /** Render help view - can be called directly */
73
+ export function showHelp() {
74
+ renderStatic(<HelpView />);
75
+ }
76
+
77
+ export const helpCmd = defineCommand({
78
+ meta: {
79
+ name: "help",
80
+ description: "show help",
81
+ },
82
+ async run() {
83
+ showHelp();
84
+ },
85
+ });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * CLI commands exports
3
+ */
4
+
5
+ export { findCmd, showFindHelp } from "./find.tsx";
6
+ export { helpCmd, showHelp } from "./help.tsx";
7
+ export { listCmd, showListHelp } from "./list.tsx";
8
+ export { runCmd, showRunHelp, showTargetHelp } from "./run.tsx";
9
+ export { showWhichHelp, whichCmd } from "./which.tsx";
@@ -0,0 +1,238 @@
1
+ /**
2
+ * varg list command
3
+ * Ink-based discovery view
4
+ */
5
+
6
+ import { defineCommand } from "citty";
7
+ import { Box, Text } from "ink";
8
+ import { registry } from "../../core/registry/index.ts";
9
+ import { toJsonSchema } from "../../core/schema/helpers.ts";
10
+ import type { Definition } from "../../core/schema/types.ts";
11
+ import {
12
+ DataTable,
13
+ Header,
14
+ OptionRow,
15
+ Separator,
16
+ VargBox,
17
+ VargText,
18
+ } from "../ui/index.ts";
19
+ import { renderStatic } from "../ui/render.ts";
20
+
21
+ interface ListViewProps {
22
+ filterType?: "model" | "action" | "skill";
23
+ }
24
+
25
+ function ListView({ filterType }: ListViewProps) {
26
+ const definitions = registry.list(filterType);
27
+
28
+ const models = definitions.filter((d) => d.type === "model");
29
+ const actions = definitions.filter((d) => d.type === "action");
30
+ const skills = definitions.filter((d) => d.type === "skill");
31
+ const stats = registry.stats;
32
+
33
+ return (
34
+ <VargBox title="varg">
35
+ {/* Models section */}
36
+ {(!filterType || filterType === "model") && (
37
+ <Box flexDirection="column" marginBottom={1}>
38
+ <Header>MODELS</Header>
39
+ <Box marginY={1}>
40
+ {models.length > 0 ? (
41
+ <DataTable
42
+ rows={models.map((m) => ({
43
+ name: m.name,
44
+ description: m.description,
45
+ type: m.type as "model",
46
+ }))}
47
+ />
48
+ ) : (
49
+ <Box paddingLeft={2}>
50
+ <VargText variant="muted">no models registered</VargText>
51
+ </Box>
52
+ )}
53
+ </Box>
54
+ </Box>
55
+ )}
56
+
57
+ {/* Actions section */}
58
+ {(!filterType || filterType === "action") && (
59
+ <Box flexDirection="column" marginBottom={1}>
60
+ <Header>ACTIONS</Header>
61
+ <Box marginY={1}>
62
+ {actions.length > 0 ? (
63
+ <DataTable
64
+ rows={actions.map((a) => ({
65
+ name: a.name,
66
+ description: a.description,
67
+ type: a.type as "action",
68
+ }))}
69
+ />
70
+ ) : (
71
+ <Box paddingLeft={2}>
72
+ <VargText variant="muted">no actions registered</VargText>
73
+ </Box>
74
+ )}
75
+ </Box>
76
+ </Box>
77
+ )}
78
+
79
+ {/* Skills section */}
80
+ {(!filterType || filterType === "skill") && (
81
+ <Box flexDirection="column" marginBottom={1}>
82
+ <Header>SKILLS</Header>
83
+ <Box marginY={1}>
84
+ {skills.length > 0 ? (
85
+ <DataTable
86
+ rows={skills.map((s) => ({
87
+ name: s.name,
88
+ description: s.description,
89
+ type: s.type as "skill",
90
+ }))}
91
+ />
92
+ ) : (
93
+ <Box paddingLeft={2}>
94
+ <VargText variant="muted">no skills registered</VargText>
95
+ </Box>
96
+ )}
97
+ </Box>
98
+ </Box>
99
+ )}
100
+
101
+ {/* Footer */}
102
+ <Separator />
103
+ <Box marginTop={1}>
104
+ <Text>
105
+ {stats.models} models · {stats.actions} actions · {stats.skills}{" "}
106
+ skills
107
+ </Text>
108
+ </Box>
109
+ <Box marginTop={1}>
110
+ <VargText variant="muted">run </VargText>
111
+ <VargText variant="accent">varg which {"<name>"}</VargText>
112
+ <VargText variant="muted"> for details</VargText>
113
+ </Box>
114
+ </VargBox>
115
+ );
116
+ }
117
+
118
+ /**
119
+ * Convert a definition to an AI agent tool schema
120
+ */
121
+ function definitionToToolSchema(def: Definition) {
122
+ const inputSchema = toJsonSchema(def.schema.input);
123
+
124
+ return {
125
+ type: "function" as const,
126
+ function: {
127
+ name: def.name,
128
+ description: def.description,
129
+ parameters: {
130
+ type: "object",
131
+ properties: inputSchema.properties || {},
132
+ required: inputSchema.required || [],
133
+ },
134
+ },
135
+ };
136
+ }
137
+
138
+ /**
139
+ * Generate all tools as JSON schemas for AI agents
140
+ */
141
+ function generateToolsSchema(filterType?: "model" | "action" | "skill") {
142
+ const definitions = registry.list(filterType);
143
+
144
+ return {
145
+ tools: definitions.map(definitionToToolSchema),
146
+ };
147
+ }
148
+
149
+ /** Help view for list command */
150
+ function ListHelpView() {
151
+ return (
152
+ <VargBox title="varg list">
153
+ <Box marginBottom={1}>
154
+ <Text>discover what's available</Text>
155
+ </Box>
156
+
157
+ <Header>USAGE</Header>
158
+ <Box paddingLeft={2} marginBottom={1}>
159
+ <VargText variant="accent">varg list [type] [options]</VargText>
160
+ </Box>
161
+
162
+ <Header>ARGUMENTS</Header>
163
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
164
+ <Text>type filter by type: model, action, skill</Text>
165
+ </Box>
166
+
167
+ <Header>OPTIONS</Header>
168
+ <Box flexDirection="column" paddingLeft={2} marginBottom={1}>
169
+ <OptionRow
170
+ name="schema"
171
+ description="output all tools as JSON schemas for AI agents"
172
+ />
173
+ <OptionRow name="help, -h" description="show this help" />
174
+ </Box>
175
+
176
+ <Header>EXAMPLES</Header>
177
+ <Box flexDirection="column" paddingLeft={2}>
178
+ <Box flexDirection="column" marginBottom={1}>
179
+ <Text dimColor># list everything</Text>
180
+ <VargText variant="accent">varg list</VargText>
181
+ </Box>
182
+ <Box flexDirection="column" marginBottom={1}>
183
+ <Text dimColor># list only models</Text>
184
+ <VargText variant="accent">varg list model</VargText>
185
+ </Box>
186
+ <Box flexDirection="column" marginBottom={1}>
187
+ <Text dimColor># list only actions</Text>
188
+ <VargText variant="accent">varg list action</VargText>
189
+ </Box>
190
+ <Box flexDirection="column">
191
+ <Text dimColor># export tools for AI agent</Text>
192
+ <VargText variant="accent">varg list --schema</VargText>
193
+ </Box>
194
+ </Box>
195
+ </VargBox>
196
+ );
197
+ }
198
+
199
+ /** Show list command help */
200
+ export function showListHelp() {
201
+ renderStatic(<ListHelpView />);
202
+ }
203
+
204
+ export const listCmd = defineCommand({
205
+ meta: {
206
+ name: "list",
207
+ description: "discover what's available",
208
+ },
209
+ args: {
210
+ type: {
211
+ type: "positional",
212
+ description: "filter by type (model, action, skill)",
213
+ required: false,
214
+ },
215
+ schema: {
216
+ type: "boolean",
217
+ description: "output all tools as JSON schemas for AI agents",
218
+ },
219
+ },
220
+ async run({ args, rawArgs }) {
221
+ // Handle --help
222
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
223
+ showListHelp();
224
+ return;
225
+ }
226
+
227
+ const filterType = args.type as "model" | "action" | "skill" | undefined;
228
+
229
+ // Output JSON schemas for AI agents
230
+ if (args.schema) {
231
+ const toolsSchema = generateToolsSchema(filterType);
232
+ console.log(JSON.stringify(toolsSchema, null, 2));
233
+ return;
234
+ }
235
+
236
+ renderStatic(<ListView filterType={filterType} />);
237
+ },
238
+ });