egaki 0.6.0 → 0.7.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 (271) hide show
  1. package/CHANGELOG.md +140 -9
  2. package/dist/cli/cache-utils.d.ts +33 -0
  3. package/dist/cli/cache-utils.d.ts.map +1 -0
  4. package/dist/cli/cache-utils.js +157 -0
  5. package/dist/cli/cached-generate.d.ts +105 -0
  6. package/dist/cli/cached-generate.d.ts.map +1 -0
  7. package/dist/cli/cached-generate.js +208 -0
  8. package/dist/cli/cached-generate.test.d.ts +11 -0
  9. package/dist/cli/cached-generate.test.d.ts.map +1 -0
  10. package/dist/cli/cached-generate.test.js +431 -0
  11. package/dist/cli/cartesia-provider.d.ts +16 -0
  12. package/dist/cli/cartesia-provider.d.ts.map +1 -0
  13. package/dist/cli/cartesia-provider.js +184 -0
  14. package/dist/cli/chatgpt-auth.d.ts.map +1 -0
  15. package/dist/cli/cli.d.ts +4 -0
  16. package/dist/cli/cli.d.ts.map +1 -0
  17. package/dist/{cli.js → cli/cli.js} +626 -600
  18. package/dist/cli/clone-generate.d.ts +26 -0
  19. package/dist/cli/clone-generate.d.ts.map +1 -0
  20. package/dist/cli/clone-generate.js +148 -0
  21. package/dist/cli/credentials.d.ts.map +1 -0
  22. package/dist/{credentials.js → cli/credentials.js} +20 -0
  23. package/dist/cli/elevenlabs-speech-provider.d.ts +26 -0
  24. package/dist/cli/elevenlabs-speech-provider.d.ts.map +1 -0
  25. package/dist/cli/elevenlabs-speech-provider.js +199 -0
  26. package/dist/cli/generate.d.ts +140 -0
  27. package/dist/cli/generate.d.ts.map +1 -0
  28. package/dist/cli/generate.js +604 -0
  29. package/dist/cli/generate.test.d.ts +2 -0
  30. package/dist/cli/generate.test.d.ts.map +1 -0
  31. package/dist/cli/generate.test.js +131 -0
  32. package/dist/cli/login.d.ts.map +1 -0
  33. package/dist/cli/main.d.ts +3 -0
  34. package/dist/cli/main.d.ts.map +1 -0
  35. package/dist/cli/main.js +7 -0
  36. package/dist/{model-catalog.d.ts → cli/model-catalog.d.ts} +6 -0
  37. package/dist/cli/model-catalog.d.ts.map +1 -0
  38. package/dist/{model-catalog.js → cli/model-catalog.js} +714 -4
  39. package/dist/{models.d.ts → cli/models.d.ts} +12 -5
  40. package/dist/cli/models.d.ts.map +1 -0
  41. package/dist/{models.js → cli/models.js} +58 -57
  42. package/dist/cli/open-browser.d.ts.map +1 -0
  43. package/dist/cli/openai-speech-provider.d.ts +3 -0
  44. package/dist/cli/openai-speech-provider.d.ts.map +1 -0
  45. package/dist/cli/openai-speech-provider.js +28 -0
  46. package/dist/cli/separation-generate.d.ts +34 -0
  47. package/dist/cli/separation-generate.d.ts.map +1 -0
  48. package/dist/cli/separation-generate.js +117 -0
  49. package/dist/cli/speech-catalog.d.ts +35 -0
  50. package/dist/cli/speech-catalog.d.ts.map +1 -0
  51. package/dist/cli/speech-catalog.js +195 -0
  52. package/dist/cli/speech-generate.d.ts +86 -0
  53. package/dist/cli/speech-generate.d.ts.map +1 -0
  54. package/dist/cli/speech-generate.js +156 -0
  55. package/dist/cli/speech-models.d.ts +8 -0
  56. package/dist/cli/speech-models.d.ts.map +1 -0
  57. package/dist/cli/speech-models.js +109 -0
  58. package/dist/cli/speech-provider.test.d.ts +2 -0
  59. package/dist/cli/speech-provider.test.d.ts.map +1 -0
  60. package/dist/cli/speech-provider.test.js +197 -0
  61. package/dist/cli/subscription.d.ts.map +1 -0
  62. package/dist/cli/transcription-catalog.d.ts +35 -0
  63. package/dist/cli/transcription-catalog.d.ts.map +1 -0
  64. package/dist/cli/transcription-catalog.js +192 -0
  65. package/dist/cli/transcription-generate.d.ts +62 -0
  66. package/dist/cli/transcription-generate.d.ts.map +1 -0
  67. package/dist/cli/transcription-generate.js +144 -0
  68. package/dist/cli/transcription-models.d.ts +9 -0
  69. package/dist/cli/transcription-models.d.ts.map +1 -0
  70. package/dist/cli/transcription-models.js +100 -0
  71. package/dist/cli/transcription-providers.d.ts +22 -0
  72. package/dist/cli/transcription-providers.d.ts.map +1 -0
  73. package/dist/cli/transcription-providers.js +290 -0
  74. package/dist/cli/video-model-catalog.d.ts.map +1 -0
  75. package/dist/cli/xai-auth.d.ts.map +1 -0
  76. package/dist/{xai-auth.js → cli/xai-auth.js} +1 -1
  77. package/dist/vite/angled-screen.d.ts +57 -0
  78. package/dist/vite/angled-screen.d.ts.map +1 -0
  79. package/dist/vite/angled-screen.js +115 -0
  80. package/dist/vite/app.d.ts +51 -0
  81. package/dist/vite/app.d.ts.map +1 -0
  82. package/dist/vite/app.js +150 -0
  83. package/dist/vite/bands-shader.d.ts +47 -0
  84. package/dist/vite/bands-shader.d.ts.map +1 -0
  85. package/dist/vite/bands-shader.js +267 -0
  86. package/dist/vite/code-block.d.ts +107 -0
  87. package/dist/vite/code-block.d.ts.map +1 -0
  88. package/dist/vite/code-block.js +641 -0
  89. package/dist/vite/components.d.ts +36 -0
  90. package/dist/vite/components.d.ts.map +1 -0
  91. package/dist/vite/components.js +113 -0
  92. package/dist/vite/dispersion-rings-shader.d.ts +44 -0
  93. package/dist/vite/dispersion-rings-shader.d.ts.map +1 -0
  94. package/dist/vite/dispersion-rings-shader.js +282 -0
  95. package/dist/vite/easing-curves.d.ts +129 -0
  96. package/dist/vite/easing-curves.d.ts.map +1 -0
  97. package/dist/vite/easing-curves.js +584 -0
  98. package/dist/vite/easing-curves.test.d.ts +2 -0
  99. package/dist/vite/easing-curves.test.d.ts.map +1 -0
  100. package/dist/vite/easing-curves.test.js +200 -0
  101. package/dist/vite/generated-media-client.d.ts +35 -0
  102. package/dist/vite/generated-media-client.d.ts.map +1 -0
  103. package/dist/vite/generated-media-client.js +76 -0
  104. package/dist/vite/keyframes.d.ts +129 -0
  105. package/dist/vite/keyframes.d.ts.map +1 -0
  106. package/dist/vite/keyframes.js +194 -0
  107. package/dist/vite/layout-editor.d.ts +45 -0
  108. package/dist/vite/layout-editor.d.ts.map +1 -0
  109. package/dist/vite/layout-editor.js +587 -0
  110. package/dist/vite/layout-transition.d.ts +136 -0
  111. package/dist/vite/layout-transition.d.ts.map +1 -0
  112. package/dist/vite/layout-transition.js +581 -0
  113. package/dist/vite/liquid-gradient-shader.d.ts +62 -0
  114. package/dist/vite/liquid-gradient-shader.d.ts.map +1 -0
  115. package/dist/vite/liquid-gradient-shader.js +413 -0
  116. package/dist/vite/mdx-client.d.ts +15 -0
  117. package/dist/vite/mdx-client.d.ts.map +1 -0
  118. package/dist/vite/mdx-client.js +265 -0
  119. package/dist/vite/mdx-parse.d.ts +102 -0
  120. package/dist/vite/mdx-parse.d.ts.map +1 -0
  121. package/dist/vite/mdx-parse.js +251 -0
  122. package/dist/vite/mdx-provided-components.d.ts +18 -0
  123. package/dist/vite/mdx-provided-components.d.ts.map +1 -0
  124. package/dist/vite/mdx-provided-components.js +14 -0
  125. package/dist/vite/mdx-video.d.ts +327 -0
  126. package/dist/vite/mdx-video.d.ts.map +1 -0
  127. package/dist/vite/mdx-video.js +596 -0
  128. package/dist/vite/mdx-video.test.d.ts +9 -0
  129. package/dist/vite/mdx-video.test.d.ts.map +1 -0
  130. package/dist/vite/mdx-video.test.js +1945 -0
  131. package/dist/vite/media-components.d.ts +45 -0
  132. package/dist/vite/media-components.d.ts.map +1 -0
  133. package/dist/vite/media-components.js +355 -0
  134. package/dist/vite/media-duration-store.d.ts +66 -0
  135. package/dist/vite/media-duration-store.d.ts.map +1 -0
  136. package/dist/vite/media-duration-store.js +204 -0
  137. package/dist/vite/player-page.d.ts +35 -0
  138. package/dist/vite/player-page.d.ts.map +1 -0
  139. package/dist/vite/player-page.js +720 -0
  140. package/dist/vite/render-client.d.ts +18 -0
  141. package/dist/vite/render-client.d.ts.map +1 -0
  142. package/dist/vite/render-client.js +67 -0
  143. package/dist/vite/sdk.d.ts +221 -0
  144. package/dist/vite/sdk.d.ts.map +1 -0
  145. package/dist/vite/sdk.js +355 -0
  146. package/dist/vite/server-components.d.ts +55 -0
  147. package/dist/vite/server-components.d.ts.map +1 -0
  148. package/dist/vite/server-components.js +156 -0
  149. package/dist/vite/server-mdx.d.ts +74 -0
  150. package/dist/vite/server-mdx.d.ts.map +1 -0
  151. package/dist/vite/server-mdx.js +259 -0
  152. package/dist/vite/shader-renderer.d.ts +48 -0
  153. package/dist/vite/shader-renderer.d.ts.map +1 -0
  154. package/dist/vite/shader-renderer.js +411 -0
  155. package/dist/vite/store-hooks.d.ts +12 -0
  156. package/dist/vite/store-hooks.d.ts.map +1 -0
  157. package/dist/vite/store-hooks.js +93 -0
  158. package/dist/vite/store.d.ts +75 -0
  159. package/dist/vite/store.d.ts.map +1 -0
  160. package/dist/vite/store.js +52 -0
  161. package/dist/vite/store.test.d.ts +6 -0
  162. package/dist/vite/store.test.d.ts.map +1 -0
  163. package/dist/vite/store.test.js +172 -0
  164. package/dist/vite/tweakpane-hook.d.ts +94 -0
  165. package/dist/vite/tweakpane-hook.d.ts.map +1 -0
  166. package/dist/vite/tweakpane-hook.js +450 -0
  167. package/dist/vite/vite-plugin.d.ts +28 -0
  168. package/dist/vite/vite-plugin.d.ts.map +1 -0
  169. package/dist/vite/vite-plugin.js +538 -0
  170. package/dist/vite/wave-gradient-shader.d.ts +41 -0
  171. package/dist/vite/wave-gradient-shader.d.ts.map +1 -0
  172. package/dist/vite/wave-gradient-shader.js +207 -0
  173. package/package.json +101 -24
  174. package/skills/egaki/SKILL.md +162 -1
  175. package/src/cli/cache-utils.ts +169 -0
  176. package/src/cli/cached-generate.test.ts +531 -0
  177. package/src/cli/cached-generate.ts +348 -0
  178. package/src/cli/cartesia-provider.ts +249 -0
  179. package/src/{cli.ts → cli/cli.ts} +836 -884
  180. package/src/cli/clone-generate.ts +202 -0
  181. package/src/{credentials.ts → cli/credentials.ts} +20 -0
  182. package/src/cli/elevenlabs-speech-provider.ts +243 -0
  183. package/src/cli/generate.test.ts +166 -0
  184. package/src/cli/generate.ts +912 -0
  185. package/src/cli/main.ts +8 -0
  186. package/src/{model-catalog.ts → cli/model-catalog.ts} +787 -58
  187. package/src/{models.ts → cli/models.ts} +65 -86
  188. package/src/cli/openai-speech-provider.ts +34 -0
  189. package/src/cli/separation-generate.ts +187 -0
  190. package/src/cli/speech-catalog.ts +253 -0
  191. package/src/cli/speech-generate.ts +275 -0
  192. package/src/cli/speech-models.ts +146 -0
  193. package/src/cli/speech-provider.test.ts +226 -0
  194. package/src/cli/transcription-catalog.ts +250 -0
  195. package/src/cli/transcription-generate.ts +214 -0
  196. package/src/cli/transcription-models.ts +136 -0
  197. package/src/cli/transcription-providers.ts +427 -0
  198. package/src/{xai-auth.ts → cli/xai-auth.ts} +1 -1
  199. package/src/vite/angled-screen.tsx +214 -0
  200. package/src/vite/app.tsx +197 -0
  201. package/src/vite/bands-shader.tsx +319 -0
  202. package/src/vite/code-block.tsx +939 -0
  203. package/src/vite/components.tsx +278 -0
  204. package/src/vite/dispersion-rings-shader.tsx +331 -0
  205. package/src/vite/easing-curves.test.ts +232 -0
  206. package/src/vite/easing-curves.ts +743 -0
  207. package/src/vite/generated-media-client.tsx +121 -0
  208. package/src/vite/keyframes.tsx +347 -0
  209. package/src/vite/layout-editor.tsx +709 -0
  210. package/src/vite/layout-transition.tsx +706 -0
  211. package/src/vite/liquid-gradient-shader.tsx +474 -0
  212. package/src/vite/mdx-client.tsx +420 -0
  213. package/src/vite/mdx-parse.ts +343 -0
  214. package/src/vite/mdx-provided-components.ts +19 -0
  215. package/src/vite/mdx-video.test.tsx +2219 -0
  216. package/src/vite/mdx-video.tsx +976 -0
  217. package/src/vite/media-components.tsx +473 -0
  218. package/src/vite/media-duration-store.ts +225 -0
  219. package/src/vite/motion-timing.ts +194 -0
  220. package/src/vite/player-page.tsx +1107 -0
  221. package/src/vite/render-client.ts +84 -0
  222. package/src/vite/sdk.ts +598 -0
  223. package/src/vite/server-components.tsx +241 -0
  224. package/src/vite/server-mdx.ts +285 -0
  225. package/src/vite/shader-renderer.tsx +535 -0
  226. package/src/vite/store-hooks.ts +117 -0
  227. package/src/vite/store.test.ts +202 -0
  228. package/src/vite/store.ts +115 -0
  229. package/src/vite/styles.css +21 -0
  230. package/src/vite/tweakpane-hook.tsx +593 -0
  231. package/src/vite/virtual-modules.d.ts +30 -0
  232. package/src/vite/vite-plugin.ts +584 -0
  233. package/src/vite/wave-gradient-shader.tsx +253 -0
  234. package/README.md +0 -370
  235. package/dist/antigravity-auth.d.ts +0 -15
  236. package/dist/antigravity-auth.d.ts.map +0 -1
  237. package/dist/antigravity-auth.js +0 -544
  238. package/dist/antigravity-image.d.ts +0 -11
  239. package/dist/antigravity-image.d.ts.map +0 -1
  240. package/dist/antigravity-image.js +0 -285
  241. package/dist/chatgpt-auth.d.ts.map +0 -1
  242. package/dist/cli.d.ts +0 -3
  243. package/dist/cli.d.ts.map +0 -1
  244. package/dist/credentials.d.ts.map +0 -1
  245. package/dist/gateway-model-candidates.generated.d.ts +0 -11
  246. package/dist/gateway-model-candidates.generated.d.ts.map +0 -1
  247. package/dist/gateway-model-candidates.generated.js +0 -64
  248. package/dist/login.d.ts.map +0 -1
  249. package/dist/model-catalog.d.ts.map +0 -1
  250. package/dist/models.d.ts.map +0 -1
  251. package/dist/open-browser.d.ts.map +0 -1
  252. package/dist/subscription.d.ts.map +0 -1
  253. package/dist/video-model-catalog.d.ts.map +0 -1
  254. package/dist/xai-auth.d.ts.map +0 -1
  255. /package/dist/{chatgpt-auth.d.ts → cli/chatgpt-auth.d.ts} +0 -0
  256. /package/dist/{chatgpt-auth.js → cli/chatgpt-auth.js} +0 -0
  257. /package/dist/{credentials.d.ts → cli/credentials.d.ts} +0 -0
  258. /package/dist/{login.d.ts → cli/login.d.ts} +0 -0
  259. /package/dist/{login.js → cli/login.js} +0 -0
  260. /package/dist/{open-browser.d.ts → cli/open-browser.d.ts} +0 -0
  261. /package/dist/{open-browser.js → cli/open-browser.js} +0 -0
  262. /package/dist/{subscription.d.ts → cli/subscription.d.ts} +0 -0
  263. /package/dist/{subscription.js → cli/subscription.js} +0 -0
  264. /package/dist/{video-model-catalog.d.ts → cli/video-model-catalog.d.ts} +0 -0
  265. /package/dist/{video-model-catalog.js → cli/video-model-catalog.js} +0 -0
  266. /package/dist/{xai-auth.d.ts → cli/xai-auth.d.ts} +0 -0
  267. /package/src/{chatgpt-auth.ts → cli/chatgpt-auth.ts} +0 -0
  268. /package/src/{login.ts → cli/login.ts} +0 -0
  269. /package/src/{open-browser.ts → cli/open-browser.ts} +0 -0
  270. /package/src/{subscription.ts → cli/subscription.ts} +0 -0
  271. /package/src/{video-model-catalog.ts → cli/video-model-catalog.ts} +0 -0
@@ -3,18 +3,25 @@ import { type ImageModelEntry, type VideoModelEntry, type AnyModelEntry } from '
3
3
  export type { ImageModelEntry, VideoModelEntry, AnyModelEntry };
4
4
  /** @deprecated Use ImageModelEntry instead */
5
5
  export type ModelEntry = ImageModelEntry;
6
+ /**
7
+ * Validation error for user-facing input issues (wrong model, missing key, etc.).
8
+ * CLI prints just the message; provider/runtime errors get full stack + details.
9
+ */
10
+ export declare class ValidationError extends Error {
11
+ constructor(message: string);
12
+ }
6
13
  export declare const IMAGE_MODELS: [string, ...string[]];
7
14
  export declare const VIDEO_MODELS: [string, ...string[]];
8
15
  export declare const DEFAULT_MODEL = "nano-banana-pro-preview";
9
16
  export declare const DEFAULT_VIDEO_MODEL = "veo-3.1-fast-generate-001";
10
- export declare function getModelConfig(modelId: string): AnyModelEntry;
11
- export declare function ensureProviderKey(providerName: string): void;
17
+ export declare function getModelConfig(modelId: string): Error | AnyModelEntry;
18
+ export declare function ensureProviderKey(providerName: string): Error | undefined;
12
19
  /**
13
20
  * ChatGPT OAuth image generation goes through the Codex backend instead of the
14
21
  * OpenAI Image API, so OpenAI image models need the custom responses path.
15
22
  */
16
23
  export declare function shouldUseResponsesApi(modelId: string): boolean;
17
- export declare function createImageModel(modelId: string): Promise<ImageModel>;
18
- export declare function createTextModel(modelId: string): Promise<LanguageModel>;
19
- export declare function createVideoModel(modelId: string): Promise<any>;
24
+ export declare function createImageModel(modelId: string): Promise<Error | ImageModel>;
25
+ export declare function createTextModel(modelId: string): Promise<Error | LanguageModel>;
26
+ export declare function createVideoModel(modelId: string): Promise<Error | any>;
20
27
  //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/cli/models.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AAWnD,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAA;AAE3B,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,CAAA;AAC/D,8CAA8C;AAC9C,MAAM,MAAM,UAAU,GAAG,eAAe,CAAA;AAExC;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,eAAO,MAAM,YAAY,EAA+B,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;AAC7E,eAAO,MAAM,YAAY,EAAqC,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;AAYnF,eAAO,MAAM,aAAa,4BAA4B,CAAA;AACtD,eAAO,MAAM,mBAAmB,8BAA8B,CAAA;AAE9D,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,aAAa,CAMrE;AAyHD,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAsBzE;AAoCD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAI9D;AAgED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,CAyBnF;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,CA2BrF;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC,CA6B5E"}
@@ -2,6 +2,16 @@ import pc from 'picocolors';
2
2
  import { PROVIDERS, EGAKI_GATEWAY_URL, shouldUseChatGptBackend, shouldUseXaiOAuth, getXaiAuth, saveXaiAuth, } from './credentials.js';
3
3
  import { getValidXaiAuth } from './xai-auth.js';
4
4
  import { CATALOG, VIDEO_CATALOG, findModel, findVideoModel, findAnyModel, } from './model-catalog.js';
5
+ /**
6
+ * Validation error for user-facing input issues (wrong model, missing key, etc.).
7
+ * CLI prints just the message; provider/runtime errors get full stack + details.
8
+ */
9
+ export class ValidationError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = 'ValidationError';
13
+ }
14
+ }
5
15
  export const IMAGE_MODELS = CATALOG.map((m) => m.id);
6
16
  export const VIDEO_MODELS = VIDEO_CATALOG.map((m) => m.id);
7
17
  /**
@@ -19,8 +29,7 @@ export const DEFAULT_VIDEO_MODEL = 'veo-3.1-fast-generate-001';
19
29
  export function getModelConfig(modelId) {
20
30
  const entry = findAnyModel(modelId);
21
31
  if (!entry) {
22
- console.error(pc.red(`Unknown model: ${modelId}`));
23
- process.exit(1);
32
+ return new ValidationError(`Unknown model: ${modelId}`);
24
33
  }
25
34
  return entry;
26
35
  }
@@ -52,10 +61,14 @@ const PROVIDER_SDKS = {
52
61
  xai: {
53
62
  image: async (id) => {
54
63
  const xaiProvider = await getXaiProviderInstance();
64
+ if (xaiProvider instanceof Error)
65
+ return xaiProvider;
55
66
  return xaiProvider.image(id);
56
67
  },
57
68
  video: async (id) => {
58
69
  const xaiProvider = await getXaiProviderInstance();
70
+ if (xaiProvider instanceof Error)
71
+ return xaiProvider;
59
72
  return xaiProvider.video(id);
60
73
  },
61
74
  },
@@ -78,13 +91,11 @@ async function getXaiProviderInstance() {
78
91
  // OAuth path: inject bearer token via custom fetch
79
92
  const storedAuth = getXaiAuth();
80
93
  if (!storedAuth) {
81
- console.error(pc.red('Missing xAI OAuth tokens. Please run `egaki login` and select xAI Grok Build.'));
82
- process.exit(1);
94
+ return new ValidationError('Missing xAI OAuth tokens. Please run `egaki login` and select xAI Grok Build.');
83
95
  }
84
96
  const auth = await getValidXaiAuth(storedAuth, saveXaiAuth);
85
97
  if (auth instanceof Error) {
86
- console.error(pc.red(auth.message));
87
- process.exit(1);
98
+ return auth;
88
99
  }
89
100
  return createXai({
90
101
  // Dummy key to satisfy the SDK's apiKey requirement; the custom fetch
@@ -120,44 +131,24 @@ function hasDirectProviderKey(providerName) {
120
131
  return false;
121
132
  }
122
133
  // Check that the provider's API key or OAuth login is available before making API calls.
123
- // Prints a user-friendly error with instructions on how to configure it.
134
+ // Returns an Error with a user-friendly message if no key is found.
124
135
  export function ensureProviderKey(providerName) {
125
136
  if (hasDirectProviderKey(providerName))
126
- return;
137
+ return undefined;
127
138
  // Vertex models require a direct key — the upstream Vercel AI Gateway
128
139
  // does not support vertex/ routing, so egaki gateway can't proxy them.
129
140
  if (providerName === 'vertex') {
130
- console.error('');
131
- console.error(pc.red(pc.bold('Vertex models require a direct Google Cloud API key')));
132
- console.error('');
133
- console.error(` ${pc.cyan('egaki login --provider vertex --key <key>')}`);
134
- console.error('');
135
- console.error(pc.dim('Get a key at https://console.cloud.google.com/apis/credentials'));
136
- console.error(pc.dim('Egaki subscription does not cover Vertex routing yet.'));
137
- console.error('');
138
- process.exit(1);
141
+ return new ValidationError('Vertex models require a direct Google Cloud API key. ' +
142
+ 'Run: egaki login --provider vertex --key <key>. ' +
143
+ 'Get a key at https://console.cloud.google.com/apis/credentials');
139
144
  }
140
145
  if (hasEgakiKey())
141
- return;
146
+ return undefined;
142
147
  const info = PROVIDERS[providerName];
143
- console.error('');
144
- console.error(pc.red(pc.bold(`Missing API key for ${info?.label || providerName}`)));
145
- console.error('');
146
- console.error(` ${pc.bold('Recommended:')} Use Egaki subscription (all models, one key)`);
147
- console.error('');
148
- console.error(` ${pc.cyan('egaki subscribe')} get started in 30 seconds`);
149
- console.error('');
150
- console.error(` ${pc.dim('Or configure a provider key directly:')}`);
151
- console.error('');
152
- console.error(` ${pc.cyan('egaki login')} interactive setup`);
153
- if (info) {
154
- console.error(` ${pc.cyan(`${info.envVar}=...`)} egaki image ... inline env var`);
155
- console.error(` ${pc.cyan(`egaki login --provider ${providerName} --key <key>`)}`);
156
- console.error('');
157
- console.error(` ${pc.dim(info.hint)}`);
158
- }
159
- console.error('');
160
- process.exit(1);
148
+ const label = info?.label || providerName;
149
+ return new ValidationError(`Missing API key for ${label}. ` +
150
+ 'Use an Egaki subscription (egaki subscribe) or configure a provider key directly (egaki login).' +
151
+ (info ? ` ${info.hint}` : ''));
161
152
  }
162
153
  // ─── gateway model factories ─────────────────────────────────────────────────
163
154
  async function createGatewayImageModel(modelId, provider) {
@@ -247,30 +238,38 @@ function logAuthSource(source) {
247
238
  // Uses PROVIDER_SDKS map for direct provider creation, eliminating switch blocks.
248
239
  export async function createImageModel(modelId) {
249
240
  const config = getModelConfig(modelId);
250
- ensureProviderKey(config.provider);
241
+ if (config instanceof Error)
242
+ return config;
243
+ const keyError = ensureProviderKey(config.provider);
244
+ if (keyError)
245
+ return keyError;
251
246
  const authSource = resolveAuthSource(config.provider);
252
247
  logAuthSource(authSource);
253
248
  if (hasDirectProviderKey(config.provider)) {
254
249
  const factory = PROVIDER_SDKS[config.provider]?.image;
255
250
  if (factory) {
256
- return factory(modelId);
251
+ const result = await factory(modelId);
252
+ if (result instanceof Error)
253
+ return result;
254
+ return result;
257
255
  }
258
- console.error(pc.red(`Direct image generation is not supported for provider: ${config.provider}.`));
259
- process.exit(1);
256
+ return new ValidationError(`Direct image generation is not supported for provider: ${config.provider}.`);
260
257
  }
261
258
  if (hasEgakiKey()) {
262
259
  return createGatewayImageModel(modelId, config.provider);
263
260
  }
264
- console.error(pc.red(`No API key available for provider: ${config.provider}`));
265
- process.exit(1);
261
+ return new ValidationError(`No API key available for provider: ${config.provider}`);
266
262
  }
267
263
  export async function createTextModel(modelId) {
268
264
  const config = getModelConfig(modelId);
265
+ if (config instanceof Error)
266
+ return config;
269
267
  if (config.strategy !== 'text') {
270
- console.error(pc.red(`Model ${modelId} is not a text model`));
271
- process.exit(1);
268
+ return new ValidationError(`Model ${modelId} is not a text model`);
272
269
  }
273
- ensureProviderKey(config.provider);
270
+ const keyError = ensureProviderKey(config.provider);
271
+ if (keyError)
272
+ return keyError;
274
273
  const authSource = resolveAuthSource(config.provider);
275
274
  logAuthSource(authSource);
276
275
  if (hasDirectProviderKey(config.provider)) {
@@ -278,35 +277,37 @@ export async function createTextModel(modelId) {
278
277
  if (factory) {
279
278
  return factory(modelId);
280
279
  }
281
- console.error(pc.red(`Text+image generation is not supported for provider: ${config.provider}`));
282
- process.exit(1);
280
+ return new ValidationError(`Text+image generation is not supported for provider: ${config.provider}`);
283
281
  }
284
282
  if (hasEgakiKey()) {
285
283
  return createGatewayTextModel(modelId, config.provider);
286
284
  }
287
- console.error(pc.red(`No API key available for provider: ${config.provider}`));
288
- process.exit(1);
285
+ return new ValidationError(`No API key available for provider: ${config.provider}`);
289
286
  }
290
287
  export async function createVideoModel(modelId) {
291
288
  const config = getModelConfig(modelId);
289
+ if (config instanceof Error)
290
+ return config;
292
291
  if (config.strategy !== 'video') {
293
- console.error(pc.red(`Model ${modelId} is not a video model`));
294
- process.exit(1);
292
+ return new ValidationError(`Model ${modelId} is not a video model`);
295
293
  }
296
- ensureProviderKey(config.provider);
294
+ const keyError = ensureProviderKey(config.provider);
295
+ if (keyError)
296
+ return keyError;
297
297
  const authSource = resolveAuthSource(config.provider);
298
298
  logAuthSource(authSource);
299
299
  if (hasDirectProviderKey(config.provider)) {
300
300
  const factory = PROVIDER_SDKS[config.provider]?.video;
301
301
  if (factory) {
302
- return factory(modelId);
302
+ const result = await factory(modelId);
303
+ if (result instanceof Error)
304
+ return result;
305
+ return result;
303
306
  }
304
- console.error(pc.red(`Direct video generation is not supported for provider: ${config.provider}. Use an egaki subscription instead.`));
305
- process.exit(1);
307
+ return new ValidationError(`Direct video generation is not supported for provider: ${config.provider}. Use an egaki subscription instead.`);
306
308
  }
307
309
  if (hasEgakiKey()) {
308
310
  return createGatewayVideoModel(modelId, config.provider);
309
311
  }
310
- console.error(pc.red(`No API key available for provider: ${config.provider}`));
311
- process.exit(1);
312
+ return new ValidationError(`No API key available for provider: ${config.provider}`);
312
313
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/cli/open-browser.ts"],"names":[],"mappings":"AAyBA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAsBrD"}
@@ -0,0 +1,3 @@
1
+ import type { SpeechProvider } from './speech-generate.js';
2
+ export declare function createOpenAISpeechProvider(): SpeechProvider;
3
+ //# sourceMappingURL=openai-speech-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-speech-provider.d.ts","sourceRoot":"","sources":["../../src/cli/openai-speech-provider.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAA+C,MAAM,sBAAsB,CAAA;AAEvG,wBAAgB,0BAA0B,IAAI,cAAc,CAyB3D"}
@@ -0,0 +1,28 @@
1
+ // OpenAI speech provider for egaki.
2
+ // Wraps the Vercel AI SDK @ai-sdk/openai since OpenAI TTS has no
3
+ // timestamp support. Returns audio only, timestamps are always undefined.
4
+ import { experimental_generateSpeech as aiGenerateSpeech, } from 'ai';
5
+ export function createOpenAISpeechProvider() {
6
+ return {
7
+ async generate(options) {
8
+ const { openai } = await import('@ai-sdk/openai');
9
+ const model = openai.speech(options.modelId);
10
+ const result = await aiGenerateSpeech({
11
+ model,
12
+ text: options.text,
13
+ ...(options.voice ? { voice: options.voice } : {}),
14
+ ...(options.outputFormat ? { outputFormat: options.outputFormat } : {}),
15
+ ...(options.instructions ? { instructions: options.instructions } : {}),
16
+ ...(options.speed != null ? { speed: options.speed } : {}),
17
+ ...(options.language ? { language: options.language } : {}),
18
+ ...(options.abortSignal ? { abortSignal: options.abortSignal } : {}),
19
+ });
20
+ return {
21
+ audio: result.audio.uint8Array,
22
+ mediaType: result.audio.mediaType || 'audio/mpeg',
23
+ // OpenAI TTS does not support word timestamps
24
+ timestamps: undefined,
25
+ };
26
+ },
27
+ };
28
+ }
@@ -0,0 +1,34 @@
1
+ export type StemName = 'vocals' | 'drums' | 'bass' | 'other' | 'guitar' | 'piano';
2
+ export type DemucsModel = 'htdemucs' | 'htdemucs_ft' | 'htdemucs_6s' | 'hdemucs_mmi' | 'mdx' | 'mdx_extra' | 'mdx_q' | 'mdx_extra_q';
3
+ export interface SeparateAudioOptions {
4
+ /** Raw audio bytes to separate. */
5
+ audio: Uint8Array;
6
+ /** Which stems to extract. Default: ['vocals', 'other'] */
7
+ stems?: StemName[];
8
+ /** Demucs model variant. Default: 'htdemucs_6s' */
9
+ model?: DemucsModel;
10
+ /** Output format: 'mp3' or 'wav'. Default: 'mp3' */
11
+ outputFormat?: 'mp3' | 'wav';
12
+ /** Number of random shifts for quality (higher = better but slower). Default: 1 */
13
+ shifts?: number;
14
+ /** Segment overlap 0.0-1.0 (higher = better quality). Default: 0.25 */
15
+ overlap?: number;
16
+ /** Original filename for display/logging. */
17
+ filename?: string;
18
+ /** Progress callback for queue updates. */
19
+ onProgress?: (message: string) => void;
20
+ }
21
+ export interface StemResult {
22
+ name: StemName;
23
+ url: string;
24
+ contentType: string;
25
+ }
26
+ export interface SeparateAudioResult {
27
+ stems: StemResult[];
28
+ model: string;
29
+ }
30
+ export declare function validateStems(stems: StemName[], model: DemucsModel): Error | void;
31
+ export declare function separateAudioUncached(opts: SeparateAudioOptions): Promise<Error | SeparateAudioResult>;
32
+ /** Download a stem from its URL and return the bytes. */
33
+ export declare function downloadStem(url: string): Promise<Error | Uint8Array>;
34
+ //# sourceMappingURL=separation-generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separation-generate.d.ts","sourceRoot":"","sources":["../../src/cli/separation-generate.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEjF,MAAM,MAAM,WAAW,GACnB,UAAU,GACV,aAAa,GACb,aAAa,GACb,aAAa,GACb,KAAK,GACL,WAAW,GACX,OAAO,GACP,aAAa,CAAA;AAEjB,MAAM,WAAW,oBAAoB;IACnC,mCAAmC;IACnC,KAAK,EAAE,UAAU,CAAA;IACjB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;IAClB,mDAAmD;IACnD,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,oDAAoD;IACpD,YAAY,CAAC,EAAE,KAAK,GAAG,KAAK,CAAA;IAC5B,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CACd;AAQD,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,KAAK,GAAG,IAAI,CAejF;AAID,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,KAAK,GAAG,mBAAmB,CAAC,CA0FtC;AAID,yDAAyD;AACzD,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,CAU3E"}
@@ -0,0 +1,117 @@
1
+ // Audio separation using fal.ai's Demucs API.
2
+ // Splits audio into stems (vocals, drums, bass, guitar, piano, other).
3
+ // Returns Error | Result (errore style) instead of throwing.
4
+ //
5
+ // Uses @fal-ai/client directly since Demucs is a fal-specific API
6
+ // with no Vercel AI SDK wrapper. Requires FAL_KEY env var or
7
+ // egaki login --provider fal.
8
+ import { fal } from '@fal-ai/client';
9
+ import { injectCredentialsToEnv } from './credentials.js';
10
+ // ─── validation ─────────────────────────────────────────────────────────────
11
+ const ALL_STEMS = ['vocals', 'drums', 'bass', 'other', 'guitar', 'piano'];
12
+ const FOUR_STEM_MODELS = ['htdemucs', 'htdemucs_ft', 'hdemucs_mmi', 'mdx', 'mdx_extra', 'mdx_q', 'mdx_extra_q'];
13
+ const SIX_STEM_ONLY = ['guitar', 'piano'];
14
+ export function validateStems(stems, model) {
15
+ for (const s of stems) {
16
+ if (!ALL_STEMS.includes(s)) {
17
+ return new Error(`Unknown stem: "${s}". Valid stems: ${ALL_STEMS.join(', ')}`);
18
+ }
19
+ }
20
+ if (FOUR_STEM_MODELS.includes(model)) {
21
+ const invalid = stems.filter((s) => SIX_STEM_ONLY.includes(s));
22
+ if (invalid.length > 0) {
23
+ return new Error(`Stems ${invalid.join(', ')} are only available with htdemucs_6s model. ` +
24
+ `Current model: ${model}`);
25
+ }
26
+ }
27
+ }
28
+ // ─── main function ──────────────────────────────────────────────────────────
29
+ export async function separateAudioUncached(opts) {
30
+ injectCredentialsToEnv();
31
+ const falKey = process.env['FAL_KEY'];
32
+ if (!falKey) {
33
+ return new Error('FAL_KEY not found. Run: egaki login --provider fal\n' +
34
+ 'Get your key at https://fal.ai/dashboard/keys');
35
+ }
36
+ fal.config({ credentials: falKey });
37
+ const model = opts.model ?? 'htdemucs_6s';
38
+ const stems = opts.stems ?? ['vocals', 'other'];
39
+ const outputFormat = opts.outputFormat ?? 'mp3';
40
+ const validationError = validateStems(stems, model);
41
+ if (validationError)
42
+ return validationError;
43
+ if (opts.audio.length === 0) {
44
+ return new Error('No audio data provided');
45
+ }
46
+ // Upload the audio file to fal storage so the API can access it
47
+ const file = new File([Buffer.from(opts.audio)], opts.filename ?? 'audio.mp3', { type: 'audio/mpeg' });
48
+ opts.onProgress?.('Uploading audio to fal.ai...');
49
+ let audioUrl;
50
+ try {
51
+ audioUrl = await fal.storage.upload(file);
52
+ }
53
+ catch (err) {
54
+ return new Error(`Failed to upload audio: ${err instanceof Error ? err.message : String(err)}`);
55
+ }
56
+ opts.onProgress?.('Audio uploaded. Starting separation...');
57
+ let result;
58
+ try {
59
+ result = await fal.subscribe('fal-ai/demucs', {
60
+ input: {
61
+ audio_url: audioUrl,
62
+ model,
63
+ stems,
64
+ shifts: opts.shifts ?? 1,
65
+ overlap: opts.overlap ?? 0.25,
66
+ output_format: outputFormat,
67
+ },
68
+ logs: true,
69
+ onQueueUpdate: (update) => {
70
+ if (update.status === 'IN_PROGRESS') {
71
+ const u = update;
72
+ if (u.logs) {
73
+ for (const log of u.logs) {
74
+ opts.onProgress?.(log.message);
75
+ }
76
+ }
77
+ }
78
+ },
79
+ });
80
+ }
81
+ catch (err) {
82
+ return new Error(`Separation failed: ${err instanceof Error ? err.message : String(err)}`);
83
+ }
84
+ // Extract the requested stems from the result
85
+ const resultStems = [];
86
+ for (const stemName of stems) {
87
+ const stemData = result.data[stemName];
88
+ if (stemData?.url) {
89
+ resultStems.push({
90
+ name: stemName,
91
+ url: stemData.url,
92
+ contentType: stemData.content_type ?? `audio/${outputFormat}`,
93
+ });
94
+ }
95
+ }
96
+ if (resultStems.length === 0) {
97
+ return new Error('No stems returned from the API. Check model and stem names.');
98
+ }
99
+ return {
100
+ stems: resultStems,
101
+ model,
102
+ };
103
+ }
104
+ // ─── download helper ────────────────────────────────────────────────────────
105
+ /** Download a stem from its URL and return the bytes. */
106
+ export async function downloadStem(url) {
107
+ try {
108
+ const response = await fetch(url);
109
+ if (!response.ok) {
110
+ return new Error(`Failed to download stem: HTTP ${response.status}`);
111
+ }
112
+ return new Uint8Array(await response.arrayBuffer());
113
+ }
114
+ catch (err) {
115
+ return new Error(`Failed to download stem: ${err instanceof Error ? err.message : String(err)}`);
116
+ }
117
+ }
@@ -0,0 +1,35 @@
1
+ import type { ProviderOption } from './model-catalog.js';
2
+ export type PerCharacterCost = {
3
+ type: 'per-character';
4
+ /** USD per 1 million characters */
5
+ perMillionChars: number;
6
+ };
7
+ export type SpeechModelCost = PerCharacterCost;
8
+ export type SpeechModelFeatures = {
9
+ /** Supported output audio formats */
10
+ outputFormats: string[];
11
+ /** Whether the model supports voice instructions / style prompts */
12
+ instructions: boolean;
13
+ /** Whether speed control is supported */
14
+ speed: boolean;
15
+ /** Whether language selection is supported */
16
+ language: boolean;
17
+ /** Max input characters per request (0 = unknown/unlimited) */
18
+ maxChars: number;
19
+ /** Built-in voice names (not exhaustive for providers with voice libraries) */
20
+ defaultVoices: string[];
21
+ };
22
+ export type SpeechModelEntry = {
23
+ id: string;
24
+ name: string;
25
+ description?: string;
26
+ provider: string;
27
+ strategy: 'speech';
28
+ released: string;
29
+ cost: SpeechModelCost;
30
+ features: SpeechModelFeatures;
31
+ providerOptions?: ProviderOption[];
32
+ };
33
+ export declare const SPEECH_CATALOG: SpeechModelEntry[];
34
+ export declare function findSpeechModel(modelId: string): SpeechModelEntry | undefined;
35
+ //# sourceMappingURL=speech-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speech-catalog.d.ts","sourceRoot":"","sources":["../../src/cli/speech-catalog.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAIxD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,eAAe,CAAA;IACrB,mCAAmC;IACnC,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAA;AAI9C,MAAM,MAAM,mBAAmB,GAAG;IAChC,qCAAqC;IACrC,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,oEAAoE;IACpE,YAAY,EAAE,OAAO,CAAA;IACrB,yCAAyC;IACzC,KAAK,EAAE,OAAO,CAAA;IACd,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAA;IACjB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAA;IAChB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,EAAE,CAAA;CACxB,CAAA;AAID,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,eAAe,CAAA;IACrB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,eAAe,CAAC,EAAE,cAAc,EAAE,CAAA;CACnC,CAAA;AAqBD,eAAO,MAAM,cAAc,EAAE,gBAAgB,EA8K5C,CAAA;AAID,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE7E"}