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,403 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * Unit tests for varg SDK (no API calls required)
5
+ * Run with: bun run src/tests/unit.test.ts
6
+ */
7
+
8
+ import { z } from "zod";
9
+ import { registry } from "../core/registry";
10
+ import { findSimilar, resolve, suggest } from "../core/registry/resolver";
11
+ import { getCliSchemaInfo } from "../core/schema/helpers";
12
+ import {
13
+ applyDefaults,
14
+ validateAndPrepare,
15
+ validateInputs,
16
+ } from "../core/schema/validator";
17
+ import { allDefinitions } from "../definitions";
18
+ import { allActions } from "../definitions/actions";
19
+ import { allModels } from "../definitions/models";
20
+ import { allSkills } from "../definitions/skills";
21
+ import { providers } from "../providers";
22
+
23
+ // Colors for output
24
+ const green = (s: string) => `\x1b[32m${s}\x1b[0m`;
25
+ const red = (s: string) => `\x1b[31m${s}\x1b[0m`;
26
+ const cyan = (s: string) => `\x1b[36m${s}\x1b[0m`;
27
+ const dim = (s: string) => `\x1b[2m${s}\x1b[0m`;
28
+
29
+ let passed = 0;
30
+ let failed = 0;
31
+
32
+ function test(name: string, fn: () => void): void {
33
+ try {
34
+ fn();
35
+ passed++;
36
+ console.log(`${green("✓")} ${name}`);
37
+ } catch (error) {
38
+ failed++;
39
+ const msg = error instanceof Error ? error.message : String(error);
40
+ console.log(`${red("✗")} ${name}`);
41
+ console.log(` ${red(msg)}`);
42
+ }
43
+ }
44
+
45
+ function assert(condition: boolean, message: string): void {
46
+ if (!condition) throw new Error(message);
47
+ }
48
+
49
+ function assertEqual<T>(actual: T, expected: T, message?: string): void {
50
+ if (actual !== expected) {
51
+ throw new Error(message || `Expected ${expected}, got ${actual}`);
52
+ }
53
+ }
54
+
55
+ // Register all definitions first
56
+ for (const definition of allDefinitions) {
57
+ registry.register(definition);
58
+ }
59
+
60
+ console.log(`\n${cyan("═".repeat(60))}`);
61
+ console.log(cyan(" VARG SDK UNIT TESTS"));
62
+ console.log(`${cyan("═".repeat(60))}\n`);
63
+
64
+ // ============================================================================
65
+ // Definition Count Tests
66
+ // ============================================================================
67
+
68
+ console.log(dim("─ Definition Counts ─\n"));
69
+
70
+ test("all models are exported", () => {
71
+ assert(
72
+ allModels.length >= 8,
73
+ `Expected at least 8 models, got ${allModels.length}`,
74
+ );
75
+ });
76
+
77
+ test("all actions are exported", () => {
78
+ assert(
79
+ allActions.length >= 14,
80
+ `Expected at least 14 actions, got ${allActions.length}`,
81
+ );
82
+ });
83
+
84
+ test("all skills are exported", () => {
85
+ assert(
86
+ allSkills.length >= 2,
87
+ `Expected at least 2 skills, got ${allSkills.length}`,
88
+ );
89
+ });
90
+
91
+ test("allDefinitions contains all definitions", () => {
92
+ const expected = allModels.length + allActions.length + allSkills.length;
93
+ assertEqual(
94
+ allDefinitions.length,
95
+ expected,
96
+ `Expected ${expected} total definitions`,
97
+ );
98
+ });
99
+
100
+ // ============================================================================
101
+ // Registry Tests
102
+ // ============================================================================
103
+
104
+ console.log(`\n${dim("─ Registry ─\n")}`);
105
+
106
+ test("registry.list() returns all definitions", () => {
107
+ const all = registry.list();
108
+ assert(all.length > 0, "Registry is empty");
109
+ });
110
+
111
+ test("registry.list('model') filters correctly", () => {
112
+ const models = registry.list("model");
113
+ assert(
114
+ models.every((d) => d.type === "model"),
115
+ "Non-model in model list",
116
+ );
117
+ });
118
+
119
+ test("registry.list('action') filters correctly", () => {
120
+ const actions = registry.list("action");
121
+ assert(
122
+ actions.every((d) => d.type === "action"),
123
+ "Non-action in action list",
124
+ );
125
+ });
126
+
127
+ test("registry.list('skill') filters correctly", () => {
128
+ const skills = registry.list("skill");
129
+ assert(
130
+ skills.every((d) => d.type === "skill"),
131
+ "Non-skill in skill list",
132
+ );
133
+ });
134
+
135
+ test("registry.resolve() finds models", () => {
136
+ const kling = registry.resolve("kling");
137
+ assert(kling !== null, "Could not resolve kling");
138
+ assertEqual(kling?.type, "model");
139
+ });
140
+
141
+ test("registry.resolve() finds actions", () => {
142
+ const video = registry.resolve("video");
143
+ assert(video !== null, "Could not resolve video");
144
+ assertEqual(video?.type, "action");
145
+ });
146
+
147
+ test("registry.resolve() finds skills", () => {
148
+ const skill = registry.resolve("talking-character");
149
+ assert(skill !== null, "Could not resolve talking-character");
150
+ assertEqual(skill?.type, "skill");
151
+ });
152
+
153
+ test("registry.resolve() returns null for unknown", () => {
154
+ const unknown = registry.resolve("nonexistent-thing");
155
+ assert(unknown === null, "Should return null for unknown");
156
+ });
157
+
158
+ test("registry.has() works correctly", () => {
159
+ assert(registry.has("video"), "Should have video");
160
+ assert(!registry.has("nonexistent"), "Should not have nonexistent");
161
+ });
162
+
163
+ test("registry.search() finds matching definitions", () => {
164
+ const results = registry.search("video");
165
+ assert(results.length > 0, "Should find video-related definitions");
166
+ });
167
+
168
+ test("registry.getModel() returns only models", () => {
169
+ const kling = registry.getModel("kling");
170
+ assert(kling !== undefined, "Should find kling model");
171
+ assert(
172
+ registry.getModel("video") === undefined,
173
+ "Should not find video as model",
174
+ );
175
+ });
176
+
177
+ test("registry.getAction() returns only actions", () => {
178
+ const video = registry.getAction("video");
179
+ assert(video !== undefined, "Should find video action");
180
+ assert(
181
+ registry.getAction("kling") === undefined,
182
+ "Should not find kling as action",
183
+ );
184
+ });
185
+
186
+ test("registry.stats returns correct counts", () => {
187
+ const stats = registry.stats;
188
+ assert(stats.models > 0, "Should have models");
189
+ assert(stats.actions > 0, "Should have actions");
190
+ assert(stats.skills > 0, "Should have skills");
191
+ });
192
+
193
+ // ============================================================================
194
+ // Resolver Tests
195
+ // ============================================================================
196
+
197
+ console.log(`\n${dim("─ Resolver ─\n")}`);
198
+
199
+ test("resolve() returns exact matches", () => {
200
+ const result = resolve("video");
201
+ assertEqual(result.matchType, "exact");
202
+ assert(result.definition !== null, "Should find definition");
203
+ });
204
+
205
+ test("resolve() handles fuzzy matching", () => {
206
+ const result = resolve("vid", { fuzzy: true });
207
+ assert(result.suggestions !== undefined, "Should have suggestions");
208
+ });
209
+
210
+ test("resolve() throws on required not found", () => {
211
+ let threw = false;
212
+ try {
213
+ resolve("nonexistent", { required: true });
214
+ } catch {
215
+ threw = true;
216
+ }
217
+ assert(threw, "Should throw for required not found");
218
+ });
219
+
220
+ test("findSimilar() returns suggestions", () => {
221
+ const similar = findSimilar("vide");
222
+ assert(similar.length > 0, "Should find similar names");
223
+ assert(similar.includes("video"), "Should suggest 'video'");
224
+ });
225
+
226
+ test("suggest() returns prefix matches", () => {
227
+ const suggestions = suggest("vi");
228
+ assert(
229
+ suggestions.some((s) => s.startsWith("vi")),
230
+ "Should return prefix matches",
231
+ );
232
+ });
233
+
234
+ // ============================================================================
235
+ // Schema Validation Tests (Zod-based)
236
+ // ============================================================================
237
+
238
+ console.log(`\n${dim("─ Schema Validation (Zod) ─\n")}`);
239
+
240
+ // Create a test Zod schema
241
+ const testSchema = z.object({
242
+ prompt: z.string().describe("Test prompt"),
243
+ count: z.number().int().default(1).describe("Count"),
244
+ mode: z.enum(["fast", "slow"]).default("fast").describe("Mode"),
245
+ });
246
+
247
+ test("validateInputs accepts valid inputs", () => {
248
+ const result = validateInputs({ prompt: "test" }, testSchema);
249
+ assert(
250
+ result.valid,
251
+ `Should be valid: ${result.errors.map((e) => e.message).join(", ")}`,
252
+ );
253
+ });
254
+
255
+ test("validateInputs rejects missing required", () => {
256
+ const result = validateInputs({}, testSchema);
257
+ assert(!result.valid, "Should be invalid");
258
+ assert(
259
+ result.errors.some((e) => e.path === "prompt"),
260
+ "Should report missing prompt",
261
+ );
262
+ });
263
+
264
+ test("validateInputs validates enum values", () => {
265
+ const result = validateInputs(
266
+ { prompt: "test", mode: "invalid" },
267
+ testSchema,
268
+ );
269
+ assert(!result.valid, "Should reject invalid enum");
270
+ });
271
+
272
+ test("applyDefaults adds default values", () => {
273
+ const inputs = applyDefaults({ prompt: "test" }, testSchema);
274
+ assertEqual(inputs.count, 1, "Should apply count default");
275
+ assertEqual(inputs.mode, "fast", "Should apply mode default");
276
+ });
277
+
278
+ test("validateAndPrepare combines validation and defaults", () => {
279
+ const result = validateAndPrepare({ prompt: "test" }, testSchema);
280
+ assert(result.valid, "Should be valid");
281
+ assertEqual(result.data?.count, 1, "Should have default count");
282
+ });
283
+
284
+ // ============================================================================
285
+ // Model Definition Tests
286
+ // ============================================================================
287
+
288
+ console.log(`\n${dim("─ Model Definitions ─\n")}`);
289
+
290
+ for (const model of allModels) {
291
+ test(`model '${model.name}' has required fields`, () => {
292
+ assert(model.type === "model", "Type should be 'model'");
293
+ assert(model.name.length > 0, "Name should not be empty");
294
+ assert(model.description.length > 0, "Description should not be empty");
295
+ assert(model.providers.length > 0, "Should have providers");
296
+ assert(model.defaultProvider.length > 0, "Should have default provider");
297
+ assert(
298
+ model.providers.includes(model.defaultProvider),
299
+ "Default provider should be in providers",
300
+ );
301
+ assert(model.schema !== undefined, "Should have schema");
302
+ // Use getCliSchemaInfo to check properties
303
+ const { properties } = getCliSchemaInfo(model.schema.input);
304
+ assert(Object.keys(properties).length > 0, "Should have input properties");
305
+ });
306
+ }
307
+
308
+ // ============================================================================
309
+ // Action Definition Tests
310
+ // ============================================================================
311
+
312
+ console.log(`\n${dim("─ Action Definitions ─\n")}`);
313
+
314
+ for (const action of allActions) {
315
+ test(`action '${action.name}' has required fields`, () => {
316
+ assert(action.type === "action", "Type should be 'action'");
317
+ assert(action.name.length > 0, "Name should not be empty");
318
+ assert(action.description.length > 0, "Description should not be empty");
319
+ assert(action.schema !== undefined, "Should have schema");
320
+ assert(
321
+ action.routes !== undefined || action.execute !== undefined,
322
+ "Should have routes or execute function",
323
+ );
324
+ });
325
+ }
326
+
327
+ // ============================================================================
328
+ // Skill Definition Tests
329
+ // ============================================================================
330
+
331
+ console.log(`\n${dim("─ Skill Definitions ─\n")}`);
332
+
333
+ for (const skill of allSkills) {
334
+ test(`skill '${skill.name}' has required fields`, () => {
335
+ assert(skill.type === "skill", "Type should be 'skill'");
336
+ assert(skill.name.length > 0, "Name should not be empty");
337
+ assert(skill.description.length > 0, "Description should not be empty");
338
+ assert(skill.schema !== undefined, "Should have schema");
339
+ assert(skill.steps.length > 0, "Should have steps");
340
+ });
341
+
342
+ test(`skill '${skill.name}' steps reference valid targets`, () => {
343
+ for (const step of skill.steps) {
344
+ assert(step.name.length > 0, `Step should have name`);
345
+ assert(step.run.length > 0, `Step '${step.name}' should have run target`);
346
+ // Note: We don't validate if target exists as it might be another action/model
347
+ }
348
+ });
349
+ }
350
+
351
+ // ============================================================================
352
+ // Provider Registration Tests
353
+ // ============================================================================
354
+
355
+ console.log(`\n${dim("─ Provider Registration ─\n")}`);
356
+
357
+ const expectedProviders = [
358
+ "fal",
359
+ "replicate",
360
+ "elevenlabs",
361
+ "groq",
362
+ "fireworks",
363
+ "higgsfield",
364
+ "ffmpeg",
365
+ "storage",
366
+ ];
367
+
368
+ for (const name of expectedProviders) {
369
+ test(`provider '${name}' is registered`, () => {
370
+ const provider = providers.get(name);
371
+ assert(provider !== undefined, `Provider '${name}' not found`);
372
+ assertEqual(provider?.name, name, "Provider name should match");
373
+ });
374
+ }
375
+
376
+ test(`providers.all() returns all providers`, () => {
377
+ const list = providers.all();
378
+ assert(
379
+ list.length >= expectedProviders.length,
380
+ `Expected at least ${expectedProviders.length} providers`,
381
+ );
382
+ });
383
+
384
+ // ============================================================================
385
+ // Summary
386
+ // ============================================================================
387
+
388
+ console.log(`\n${cyan("═".repeat(60))}`);
389
+ console.log(cyan(" SUMMARY"));
390
+ console.log(`${cyan("═".repeat(60))}\n`);
391
+
392
+ const total = passed + failed;
393
+ console.log(`Total: ${total}`);
394
+ console.log(`Passed: ${green(String(passed))}`);
395
+ console.log(`Failed: ${failed > 0 ? red(String(failed)) : "0"}`);
396
+ console.log("");
397
+
398
+ if (failed > 0) {
399
+ console.log(red(`${failed} test(s) failed!`));
400
+ process.exit(1);
401
+ } else {
402
+ console.log(green("All tests passed! ✨"));
403
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "jsxImportSource": "react"
5
+ },
6
+ "include": ["src/cli/**/*"],
7
+ "exclude": ["node_modules"]
8
+ }
package/tsconfig.json CHANGED
@@ -3,9 +3,10 @@
3
3
  // Environment setup & latest features
4
4
  "lib": ["ESNext"],
5
5
  "target": "ESNext",
6
- "module": "Preserve",
6
+ "module": "ESNext",
7
7
  "moduleDetection": "force",
8
8
  "jsx": "react-jsx",
9
+ "jsxImportSource": "@/react/runtime",
9
10
  "allowJs": true,
10
11
 
11
12
  // Bundler mode
@@ -24,6 +25,23 @@
24
25
  // Some stricter flags (disabled by default)
25
26
  "noUnusedLocals": false,
26
27
  "noUnusedParameters": false,
27
- "noPropertyAccessFromIndexSignature": false
28
- }
28
+ "noPropertyAccessFromIndexSignature": false,
29
+
30
+ // Base URL for imports
31
+ "baseUrl": ".",
32
+ "paths": {
33
+ "@/*": ["./src/*"]
34
+ }
35
+ },
36
+ "include": ["src/**/*"],
37
+ "exclude": [
38
+ "node_modules",
39
+ "action",
40
+ "lib",
41
+ "cli",
42
+ "service",
43
+ "utilities",
44
+ "pipeline",
45
+ "src/cli"
46
+ ]
29
47
  }
package/TEST_RESULTS.md DELETED
@@ -1,122 +0,0 @@
1
- # test results
2
-
3
- ## ✅ both fal approaches working
4
-
5
- ### approach 1: lib/ai-sdk/fal.ts (vercel ai sdk)
6
-
7
- ```bash
8
- $ bun run lib/ai-sdk/fal.ts generate_image "futuristic spaceship" "fal-ai/flux/dev" "16:9"
9
-
10
- [ai-sdk/fal] generating image with fal-ai/flux/dev
11
- [ai-sdk/fal] prompt: futuristic spaceship interior
12
- [ai-sdk/fal] aspect ratio: 16:9
13
- [ai-sdk/fal] completed!
14
-
15
- image saved to: /tmp/fal-ai-sdk-1763772836608.png
16
-
17
- metadata:
18
- {
19
- "images": [
20
- {
21
- "width": 1024,
22
- "height": 576,
23
- "contentType": "image/jpeg",
24
- "nsfw": false
25
- }
26
- ]
27
- }
28
- ```
29
-
30
- ✅ benefits:
31
- - clean typed api
32
- - auto image save + open
33
- - aspect ratio support
34
- - consistent with other ai-sdk providers
35
-
36
- ### approach 2: lib/fal.ts (fal client direct)
37
-
38
- ```bash
39
- $ bun run lib/fal.ts generate_image "ancient temple ruins"
40
-
41
- [fal] generating image with fal-ai/flux-pro/v1.1
42
- [fal] prompt: ancient temple ruins at sunset
43
- [fal] processing...
44
- [fal] completed!
45
-
46
- {
47
- "data": {
48
- "images": [
49
- {
50
- "url": "https://v3b.fal.media/files/b/koala/L5LYGCHZ4aZ_CKZsmPbUe.jpg",
51
- "width": 1024,
52
- "height": 768,
53
- "content_type": "image/jpeg"
54
- }
55
- ],
56
- "seed": 2946158106
57
- }
58
- }
59
- ```
60
-
61
- ✅ benefits:
62
- - full api access
63
- - queue updates
64
- - video support
65
- - custom parameters
66
-
67
- ## cli tests ✅
68
-
69
- all help menus working:
70
-
71
- ```bash
72
- bun run lib/ai-sdk/fal.ts # ✓
73
- bun run lib/fal.ts # ✓
74
- bun run lib/higgsfield.ts # ✓
75
- bun run service/image.ts # ✓
76
- bun run service/video.ts # ✓
77
- bun run utilities/s3.ts # ✓
78
- ```
79
-
80
- ## library imports ✅
81
-
82
- ```typescript
83
- import { generateImage } from "./index"
84
- import * as aiSdkFal from "./index"
85
-
86
- // both approaches available
87
- ```
88
-
89
- ## actual generation tests ✅
90
-
91
- successfully generated and opened:
92
- - cyberpunk city (16:9, ai-sdk)
93
- - spaceship interior (16:9, ai-sdk)
94
- - temple ruins (4:3, fal client)
95
- - aurora borealis (4:3, fal client)
96
-
97
- all images ~15-20 seconds generation time
98
-
99
- ## what works
100
-
101
- 1. **dual fal implementations** - ai-sdk for simplicity, client for power ✓
102
- 2. **all cli scripts executable** with proper help menus ✓
103
- 3. **library imports functional** ✓
104
- 4. **actual image generation working** ✓
105
- 5. **automatic image opening** (ai-sdk version) ✓
106
- 6. **queue progress updates** (fal client) ✓
107
-
108
- ## file structure
109
-
110
- ```
111
- lib/
112
- ├── ai-sdk/
113
- │ └── fal.ts # vercel ai sdk approach
114
- ├── fal.ts # fal client approach
115
- └── higgsfield.ts # soul character generation
116
- ```
117
-
118
- ## recommendations
119
-
120
- - **use lib/ai-sdk/fal.ts** for standard image generation
121
- - **use lib/fal.ts** for video or advanced features
122
- - **use service/**.ts for high-level operations with s3 upload