egaki 0.5.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 (280) hide show
  1. package/CHANGELOG.md +188 -0
  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/cli.js +1329 -0
  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/{credentials.d.ts → cli/credentials.d.ts} +11 -2
  22. package/dist/cli/credentials.d.ts.map +1 -0
  23. package/dist/{credentials.js → cli/credentials.js} +88 -5
  24. package/dist/cli/elevenlabs-speech-provider.d.ts +26 -0
  25. package/dist/cli/elevenlabs-speech-provider.d.ts.map +1 -0
  26. package/dist/cli/elevenlabs-speech-provider.js +199 -0
  27. package/dist/cli/generate.d.ts +140 -0
  28. package/dist/cli/generate.d.ts.map +1 -0
  29. package/dist/cli/generate.js +604 -0
  30. package/dist/cli/generate.test.d.ts +2 -0
  31. package/dist/cli/generate.test.d.ts.map +1 -0
  32. package/dist/cli/generate.test.js +131 -0
  33. package/dist/cli/login.d.ts.map +1 -0
  34. package/dist/{login.js → cli/login.js} +45 -4
  35. package/dist/cli/main.d.ts +3 -0
  36. package/dist/cli/main.d.ts.map +1 -0
  37. package/dist/cli/main.js +7 -0
  38. package/dist/cli/model-catalog.d.ts +141 -0
  39. package/dist/cli/model-catalog.d.ts.map +1 -0
  40. package/dist/cli/model-catalog.js +2135 -0
  41. package/dist/{models.d.ts → cli/models.d.ts} +16 -9
  42. package/dist/cli/models.d.ts.map +1 -0
  43. package/dist/cli/models.js +313 -0
  44. package/dist/cli/open-browser.d.ts.map +1 -0
  45. package/dist/cli/openai-speech-provider.d.ts +3 -0
  46. package/dist/cli/openai-speech-provider.d.ts.map +1 -0
  47. package/dist/cli/openai-speech-provider.js +28 -0
  48. package/dist/cli/separation-generate.d.ts +34 -0
  49. package/dist/cli/separation-generate.d.ts.map +1 -0
  50. package/dist/cli/separation-generate.js +117 -0
  51. package/dist/cli/speech-catalog.d.ts +35 -0
  52. package/dist/cli/speech-catalog.d.ts.map +1 -0
  53. package/dist/cli/speech-catalog.js +195 -0
  54. package/dist/cli/speech-generate.d.ts +86 -0
  55. package/dist/cli/speech-generate.d.ts.map +1 -0
  56. package/dist/cli/speech-generate.js +156 -0
  57. package/dist/cli/speech-models.d.ts +8 -0
  58. package/dist/cli/speech-models.d.ts.map +1 -0
  59. package/dist/cli/speech-models.js +109 -0
  60. package/dist/cli/speech-provider.test.d.ts +2 -0
  61. package/dist/cli/speech-provider.test.d.ts.map +1 -0
  62. package/dist/cli/speech-provider.test.js +197 -0
  63. package/dist/cli/subscription.d.ts.map +1 -0
  64. package/dist/cli/transcription-catalog.d.ts +35 -0
  65. package/dist/cli/transcription-catalog.d.ts.map +1 -0
  66. package/dist/cli/transcription-catalog.js +192 -0
  67. package/dist/cli/transcription-generate.d.ts +62 -0
  68. package/dist/cli/transcription-generate.d.ts.map +1 -0
  69. package/dist/cli/transcription-generate.js +144 -0
  70. package/dist/cli/transcription-models.d.ts +9 -0
  71. package/dist/cli/transcription-models.d.ts.map +1 -0
  72. package/dist/cli/transcription-models.js +100 -0
  73. package/dist/cli/transcription-providers.d.ts +22 -0
  74. package/dist/cli/transcription-providers.d.ts.map +1 -0
  75. package/dist/cli/transcription-providers.js +290 -0
  76. package/dist/cli/video-model-catalog.d.ts +2 -0
  77. package/dist/cli/video-model-catalog.d.ts.map +1 -0
  78. package/dist/cli/video-model-catalog.js +5 -0
  79. package/dist/cli/xai-auth.d.ts +29 -0
  80. package/dist/cli/xai-auth.d.ts.map +1 -0
  81. package/dist/cli/xai-auth.js +325 -0
  82. package/dist/vite/angled-screen.d.ts +57 -0
  83. package/dist/vite/angled-screen.d.ts.map +1 -0
  84. package/dist/vite/angled-screen.js +115 -0
  85. package/dist/vite/app.d.ts +51 -0
  86. package/dist/vite/app.d.ts.map +1 -0
  87. package/dist/vite/app.js +150 -0
  88. package/dist/vite/bands-shader.d.ts +47 -0
  89. package/dist/vite/bands-shader.d.ts.map +1 -0
  90. package/dist/vite/bands-shader.js +267 -0
  91. package/dist/vite/code-block.d.ts +107 -0
  92. package/dist/vite/code-block.d.ts.map +1 -0
  93. package/dist/vite/code-block.js +641 -0
  94. package/dist/vite/components.d.ts +36 -0
  95. package/dist/vite/components.d.ts.map +1 -0
  96. package/dist/vite/components.js +113 -0
  97. package/dist/vite/dispersion-rings-shader.d.ts +44 -0
  98. package/dist/vite/dispersion-rings-shader.d.ts.map +1 -0
  99. package/dist/vite/dispersion-rings-shader.js +282 -0
  100. package/dist/vite/easing-curves.d.ts +129 -0
  101. package/dist/vite/easing-curves.d.ts.map +1 -0
  102. package/dist/vite/easing-curves.js +584 -0
  103. package/dist/vite/easing-curves.test.d.ts +2 -0
  104. package/dist/vite/easing-curves.test.d.ts.map +1 -0
  105. package/dist/vite/easing-curves.test.js +200 -0
  106. package/dist/vite/generated-media-client.d.ts +35 -0
  107. package/dist/vite/generated-media-client.d.ts.map +1 -0
  108. package/dist/vite/generated-media-client.js +76 -0
  109. package/dist/vite/keyframes.d.ts +129 -0
  110. package/dist/vite/keyframes.d.ts.map +1 -0
  111. package/dist/vite/keyframes.js +194 -0
  112. package/dist/vite/layout-editor.d.ts +45 -0
  113. package/dist/vite/layout-editor.d.ts.map +1 -0
  114. package/dist/vite/layout-editor.js +587 -0
  115. package/dist/vite/layout-transition.d.ts +136 -0
  116. package/dist/vite/layout-transition.d.ts.map +1 -0
  117. package/dist/vite/layout-transition.js +581 -0
  118. package/dist/vite/liquid-gradient-shader.d.ts +62 -0
  119. package/dist/vite/liquid-gradient-shader.d.ts.map +1 -0
  120. package/dist/vite/liquid-gradient-shader.js +413 -0
  121. package/dist/vite/mdx-client.d.ts +15 -0
  122. package/dist/vite/mdx-client.d.ts.map +1 -0
  123. package/dist/vite/mdx-client.js +265 -0
  124. package/dist/vite/mdx-parse.d.ts +102 -0
  125. package/dist/vite/mdx-parse.d.ts.map +1 -0
  126. package/dist/vite/mdx-parse.js +251 -0
  127. package/dist/vite/mdx-provided-components.d.ts +18 -0
  128. package/dist/vite/mdx-provided-components.d.ts.map +1 -0
  129. package/dist/vite/mdx-provided-components.js +14 -0
  130. package/dist/vite/mdx-video.d.ts +327 -0
  131. package/dist/vite/mdx-video.d.ts.map +1 -0
  132. package/dist/vite/mdx-video.js +596 -0
  133. package/dist/vite/mdx-video.test.d.ts +9 -0
  134. package/dist/vite/mdx-video.test.d.ts.map +1 -0
  135. package/dist/vite/mdx-video.test.js +1945 -0
  136. package/dist/vite/media-components.d.ts +45 -0
  137. package/dist/vite/media-components.d.ts.map +1 -0
  138. package/dist/vite/media-components.js +355 -0
  139. package/dist/vite/media-duration-store.d.ts +66 -0
  140. package/dist/vite/media-duration-store.d.ts.map +1 -0
  141. package/dist/vite/media-duration-store.js +204 -0
  142. package/dist/vite/player-page.d.ts +35 -0
  143. package/dist/vite/player-page.d.ts.map +1 -0
  144. package/dist/vite/player-page.js +720 -0
  145. package/dist/vite/render-client.d.ts +18 -0
  146. package/dist/vite/render-client.d.ts.map +1 -0
  147. package/dist/vite/render-client.js +67 -0
  148. package/dist/vite/sdk.d.ts +221 -0
  149. package/dist/vite/sdk.d.ts.map +1 -0
  150. package/dist/vite/sdk.js +355 -0
  151. package/dist/vite/server-components.d.ts +55 -0
  152. package/dist/vite/server-components.d.ts.map +1 -0
  153. package/dist/vite/server-components.js +156 -0
  154. package/dist/vite/server-mdx.d.ts +74 -0
  155. package/dist/vite/server-mdx.d.ts.map +1 -0
  156. package/dist/vite/server-mdx.js +259 -0
  157. package/dist/vite/shader-renderer.d.ts +48 -0
  158. package/dist/vite/shader-renderer.d.ts.map +1 -0
  159. package/dist/vite/shader-renderer.js +411 -0
  160. package/dist/vite/store-hooks.d.ts +12 -0
  161. package/dist/vite/store-hooks.d.ts.map +1 -0
  162. package/dist/vite/store-hooks.js +93 -0
  163. package/dist/vite/store.d.ts +75 -0
  164. package/dist/vite/store.d.ts.map +1 -0
  165. package/dist/vite/store.js +52 -0
  166. package/dist/vite/store.test.d.ts +6 -0
  167. package/dist/vite/store.test.d.ts.map +1 -0
  168. package/dist/vite/store.test.js +172 -0
  169. package/dist/vite/tweakpane-hook.d.ts +94 -0
  170. package/dist/vite/tweakpane-hook.d.ts.map +1 -0
  171. package/dist/vite/tweakpane-hook.js +450 -0
  172. package/dist/vite/vite-plugin.d.ts +28 -0
  173. package/dist/vite/vite-plugin.d.ts.map +1 -0
  174. package/dist/vite/vite-plugin.js +538 -0
  175. package/dist/vite/wave-gradient-shader.d.ts +41 -0
  176. package/dist/vite/wave-gradient-shader.d.ts.map +1 -0
  177. package/dist/vite/wave-gradient-shader.js +207 -0
  178. package/package.json +103 -25
  179. package/skills/egaki/SKILL.md +162 -1
  180. package/src/cli/cache-utils.ts +169 -0
  181. package/src/cli/cached-generate.test.ts +531 -0
  182. package/src/cli/cached-generate.ts +348 -0
  183. package/src/cli/cartesia-provider.ts +249 -0
  184. package/src/cli/cli.ts +1818 -0
  185. package/src/cli/clone-generate.ts +202 -0
  186. package/src/{credentials.ts → cli/credentials.ts} +90 -7
  187. package/src/cli/elevenlabs-speech-provider.ts +243 -0
  188. package/src/cli/generate.test.ts +166 -0
  189. package/src/cli/generate.ts +912 -0
  190. package/src/{login.ts → cli/login.ts} +48 -3
  191. package/src/cli/main.ts +8 -0
  192. package/src/cli/model-catalog.ts +2336 -0
  193. package/src/cli/models.ts +408 -0
  194. package/src/cli/openai-speech-provider.ts +34 -0
  195. package/src/cli/separation-generate.ts +187 -0
  196. package/src/cli/speech-catalog.ts +253 -0
  197. package/src/cli/speech-generate.ts +275 -0
  198. package/src/cli/speech-models.ts +146 -0
  199. package/src/cli/speech-provider.test.ts +226 -0
  200. package/src/cli/transcription-catalog.ts +250 -0
  201. package/src/cli/transcription-generate.ts +214 -0
  202. package/src/cli/transcription-models.ts +136 -0
  203. package/src/cli/transcription-providers.ts +427 -0
  204. package/src/cli/video-model-catalog.ts +14 -0
  205. package/src/cli/xai-auth.ts +396 -0
  206. package/src/vite/angled-screen.tsx +214 -0
  207. package/src/vite/app.tsx +197 -0
  208. package/src/vite/bands-shader.tsx +319 -0
  209. package/src/vite/code-block.tsx +939 -0
  210. package/src/vite/components.tsx +278 -0
  211. package/src/vite/dispersion-rings-shader.tsx +331 -0
  212. package/src/vite/easing-curves.test.ts +232 -0
  213. package/src/vite/easing-curves.ts +743 -0
  214. package/src/vite/generated-media-client.tsx +121 -0
  215. package/src/vite/keyframes.tsx +347 -0
  216. package/src/vite/layout-editor.tsx +709 -0
  217. package/src/vite/layout-transition.tsx +706 -0
  218. package/src/vite/liquid-gradient-shader.tsx +474 -0
  219. package/src/vite/mdx-client.tsx +420 -0
  220. package/src/vite/mdx-parse.ts +343 -0
  221. package/src/vite/mdx-provided-components.ts +19 -0
  222. package/src/vite/mdx-video.test.tsx +2219 -0
  223. package/src/vite/mdx-video.tsx +976 -0
  224. package/src/vite/media-components.tsx +473 -0
  225. package/src/vite/media-duration-store.ts +225 -0
  226. package/src/vite/motion-timing.ts +194 -0
  227. package/src/vite/player-page.tsx +1107 -0
  228. package/src/vite/render-client.ts +84 -0
  229. package/src/vite/sdk.ts +598 -0
  230. package/src/vite/server-components.tsx +241 -0
  231. package/src/vite/server-mdx.ts +285 -0
  232. package/src/vite/shader-renderer.tsx +535 -0
  233. package/src/vite/store-hooks.ts +117 -0
  234. package/src/vite/store.test.ts +202 -0
  235. package/src/vite/store.ts +115 -0
  236. package/src/vite/styles.css +21 -0
  237. package/src/vite/tweakpane-hook.tsx +593 -0
  238. package/src/vite/virtual-modules.d.ts +30 -0
  239. package/src/vite/vite-plugin.ts +584 -0
  240. package/src/vite/wave-gradient-shader.tsx +253 -0
  241. package/README.md +0 -266
  242. package/dist/antigravity-auth.d.ts +0 -15
  243. package/dist/antigravity-auth.d.ts.map +0 -1
  244. package/dist/antigravity-auth.js +0 -544
  245. package/dist/antigravity-image.d.ts +0 -11
  246. package/dist/antigravity-image.d.ts.map +0 -1
  247. package/dist/antigravity-image.js +0 -285
  248. package/dist/chatgpt-auth.d.ts.map +0 -1
  249. package/dist/cli.d.ts +0 -3
  250. package/dist/cli.d.ts.map +0 -1
  251. package/dist/cli.js +0 -968
  252. package/dist/credentials.d.ts.map +0 -1
  253. package/dist/gateway-model-candidates.generated.d.ts +0 -11
  254. package/dist/gateway-model-candidates.generated.d.ts.map +0 -1
  255. package/dist/gateway-model-candidates.generated.js +0 -64
  256. package/dist/login.d.ts.map +0 -1
  257. package/dist/model-catalog.d.ts +0 -42
  258. package/dist/model-catalog.d.ts.map +0 -1
  259. package/dist/model-catalog.js +0 -1001
  260. package/dist/models.d.ts.map +0 -1
  261. package/dist/models.js +0 -246
  262. package/dist/open-browser.d.ts.map +0 -1
  263. package/dist/subscription.d.ts.map +0 -1
  264. package/dist/video-model-catalog.d.ts +0 -52
  265. package/dist/video-model-catalog.d.ts.map +0 -1
  266. package/dist/video-model-catalog.js +0 -306
  267. package/src/cli.ts +0 -1378
  268. package/src/model-catalog.ts +0 -1077
  269. package/src/models.ts +0 -309
  270. package/src/video-model-catalog.ts +0 -363
  271. /package/dist/{chatgpt-auth.d.ts → cli/chatgpt-auth.d.ts} +0 -0
  272. /package/dist/{chatgpt-auth.js → cli/chatgpt-auth.js} +0 -0
  273. /package/dist/{login.d.ts → cli/login.d.ts} +0 -0
  274. /package/dist/{open-browser.d.ts → cli/open-browser.d.ts} +0 -0
  275. /package/dist/{open-browser.js → cli/open-browser.js} +0 -0
  276. /package/dist/{subscription.d.ts → cli/subscription.d.ts} +0 -0
  277. /package/dist/{subscription.js → cli/subscription.js} +0 -0
  278. /package/src/{chatgpt-auth.ts → cli/chatgpt-auth.ts} +0 -0
  279. /package/src/{open-browser.ts → cli/open-browser.ts} +0 -0
  280. /package/src/{subscription.ts → cli/subscription.ts} +0 -0
@@ -0,0 +1,100 @@
1
+ // Transcription model registry for egaki.
2
+ // Maps transcription model IDs to their provider and direct HTTP provider factory.
3
+ // Follows the same pattern as speech-models.ts: provider factory map with lazy
4
+ // imports, auth source detection, and key validation.
5
+ //
6
+ // No AI SDK dependency — all providers use direct HTTP calls via
7
+ // TranscriptionProvider implementations in transcription-providers.ts.
8
+ import pc from 'picocolors';
9
+ import { PROVIDERS, injectCredentialsToEnv, } from './credentials.js';
10
+ import { ValidationError } from './models.js';
11
+ import { TRANSCRIPTION_CATALOG, findTranscriptionModel, } from './transcription-catalog.js';
12
+ export {};
13
+ export const TRANSCRIPTION_MODELS = TRANSCRIPTION_CATALOG.map((m) => m.id);
14
+ export const DEFAULT_TRANSCRIPTION_MODEL = 'whisper-1';
15
+ const TRANSCRIPTION_PROVIDER_FACTORIES = {
16
+ openai: async () => {
17
+ const { createOpenAITranscriptionProvider } = await import('./transcription-providers.js');
18
+ return createOpenAITranscriptionProvider();
19
+ },
20
+ elevenlabs: async () => {
21
+ const { createElevenLabsTranscriptionProvider } = await import('./transcription-providers.js');
22
+ return createElevenLabsTranscriptionProvider();
23
+ },
24
+ deepgram: async () => {
25
+ const { createDeepgramTranscriptionProvider } = await import('./transcription-providers.js');
26
+ return createDeepgramTranscriptionProvider();
27
+ },
28
+ groq: async () => {
29
+ const { createGroqTranscriptionProvider } = await import('./transcription-providers.js');
30
+ return createGroqTranscriptionProvider();
31
+ },
32
+ cartesia: async () => {
33
+ const { createCartesiaTranscriptionProvider } = await import('./transcription-providers.js');
34
+ return createCartesiaTranscriptionProvider();
35
+ },
36
+ };
37
+ // ─── key checking ────────────────────────────────────────────────────────────
38
+ function hasDirectProviderKey(providerName) {
39
+ const info = PROVIDERS[providerName];
40
+ if (!info)
41
+ return false;
42
+ return Boolean(process.env[info.envVar]);
43
+ }
44
+ // ─── config lookup ───────────────────────────────────────────────────────────
45
+ export function getTranscriptionModelConfig(modelId) {
46
+ const entry = findTranscriptionModel(modelId);
47
+ if (!entry) {
48
+ return new ValidationError(`Unknown transcription model: ${modelId}`);
49
+ }
50
+ return entry;
51
+ }
52
+ function resolveAuthSource(providerName) {
53
+ const info = PROVIDERS[providerName];
54
+ if (info && process.env[info.envVar]) {
55
+ return { type: 'api-key', label: info.envVar };
56
+ }
57
+ return { type: 'api-key', label: 'unknown' };
58
+ }
59
+ function logAuthSource(source) {
60
+ console.error(pc.dim(`Auth: ${source.label}`));
61
+ }
62
+ // ─── ensure key ──────────────────────────────────────────────────────────────
63
+ export function ensureTranscriptionProviderKey(providerName) {
64
+ if (hasDirectProviderKey(providerName))
65
+ return undefined;
66
+ const info = PROVIDERS[providerName];
67
+ const label = info?.label || providerName;
68
+ return new ValidationError(`Missing API key for ${label}. ` +
69
+ `Run: egaki login --provider ${providerName} --key <key>. ` +
70
+ (info ? info.hint : ''));
71
+ }
72
+ // ─── provider cache ──────────────────────────────────────────────────────────
73
+ /** Global cache of provider instances, keyed by provider name. */
74
+ const providerCache = globalThis.__egakiTranscriptionProviderCache ??= new Map();
75
+ // ─── public factory ──────────────────────────────────────────────────────────
76
+ export function getTranscriptionProvider(providerName) {
77
+ injectCredentialsToEnv();
78
+ const keyError = ensureTranscriptionProviderKey(providerName);
79
+ if (keyError)
80
+ return keyError;
81
+ const authSource = resolveAuthSource(providerName);
82
+ logAuthSource(authSource);
83
+ const factory = TRANSCRIPTION_PROVIDER_FACTORIES[providerName];
84
+ if (!factory) {
85
+ return new Error(`Transcription is not supported for provider: ${providerName}`);
86
+ }
87
+ // Return a lazy provider: the factory is async but we want getTranscriptionProvider
88
+ // to be sync for ergonomic use in transcribeAudioUncached. The provider promise
89
+ // is cached globally per provider name so the factory runs once across all calls.
90
+ return {
91
+ async transcribe(options) {
92
+ const cached = providerCache.get(providerName);
93
+ if (cached)
94
+ return (await cached).transcribe(options);
95
+ const promise = factory();
96
+ providerCache.set(providerName, promise);
97
+ return (await promise).transcribe(options);
98
+ },
99
+ };
100
+ }
@@ -0,0 +1,22 @@
1
+ import type { TranscriptionSegment } from './transcription-generate.js';
2
+ export interface TranscriptionProviderOptions {
3
+ audio: Uint8Array;
4
+ modelId: string;
5
+ language?: string;
6
+ abortSignal?: AbortSignal;
7
+ }
8
+ export interface TranscriptionProviderResult {
9
+ text: string;
10
+ segments: TranscriptionSegment[];
11
+ language?: string;
12
+ durationInSeconds?: number;
13
+ }
14
+ export interface TranscriptionProvider {
15
+ transcribe(options: TranscriptionProviderOptions): Promise<TranscriptionProviderResult>;
16
+ }
17
+ export declare function createOpenAITranscriptionProvider(): TranscriptionProvider;
18
+ export declare function createGroqTranscriptionProvider(): TranscriptionProvider;
19
+ export declare function createElevenLabsTranscriptionProvider(): TranscriptionProvider;
20
+ export declare function createDeepgramTranscriptionProvider(): TranscriptionProvider;
21
+ export declare function createCartesiaTranscriptionProvider(): TranscriptionProvider;
22
+ //# sourceMappingURL=transcription-providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcription-providers.d.ts","sourceRoot":"","sources":["../../src/cli/transcription-providers.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAIvE,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,UAAU,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,oBAAoB,EAAE,CAAA;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAA;CACxF;AAiED,wBAAgB,iCAAiC,IAAI,qBAAqB,CAkDzE;AAgBD,wBAAgB,+BAA+B,IAAI,qBAAqB,CA6CvE;AAmBD,wBAAgB,qCAAqC,IAAI,qBAAqB,CAqD7E;AAsBD,wBAAgB,mCAAmC,IAAI,qBAAqB,CAmD3E;AAmBD,wBAAgB,mCAAmC,IAAI,qBAAqB,CA+C3E"}
@@ -0,0 +1,290 @@
1
+ // Direct HTTP transcription providers for egaki.
2
+ // Each provider sends multipart form or raw audio to the provider API
3
+ // and parses the response, including word-level timestamps.
4
+ //
5
+ // This replaces the AI SDK's experimental_transcribe + @ai-sdk/* provider
6
+ // packages, giving us full control over request/response handling.
7
+ // In particular, we can:
8
+ // - Send verbose_json + word timestamp granularities for whisper-1
9
+ // - Avoid verbose_json for gpt-4o-transcribe models, which only support json/text
10
+ // - Parse the top-level `words` array from Groq responses (the AI SDK
11
+ // Groq provider only parses `segments`)
12
+ //
13
+ // API reference / OpenAPI specs:
14
+ // OpenAI: https://platform.openai.com/docs/api-reference/audio/createTranscription
15
+ // Groq: https://console.groq.com/docs/api-reference#audio-transcription
16
+ // (OpenAI-compatible endpoint at /openai/v1/audio/transcriptions)
17
+ // ElevenLabs: https://elevenlabs.io/docs/api-reference/speech-to-text/convert
18
+ // Deepgram: https://developers.deepgram.com/reference/listen-file
19
+ // ─── shared helpers ──────────────────────────────────────────────────────────
20
+ function mediaTypeFromAudioBytes(audio) {
21
+ if (audio.length >= 3 && audio[0] === 0x49 && audio[1] === 0x44 && audio[2] === 0x33)
22
+ return 'audio/mpeg'; // ID3 header
23
+ if (audio.length >= 2 && audio[0] === 0xff && (audio[1] & 0xe0) === 0xe0)
24
+ return 'audio/mpeg'; // MP3 sync word
25
+ // MP4/M4A: ftyp box at byte offset 4 (box size in first 4 bytes, then 'ftyp')
26
+ if (audio.length >= 12 && audio[4] === 0x66 && audio[5] === 0x74 && audio[6] === 0x79 && audio[7] === 0x70)
27
+ return 'audio/mp4';
28
+ // WebM: EBML header magic bytes
29
+ if (audio.length >= 4 && audio[0] === 0x1a && audio[1] === 0x45 && audio[2] === 0xdf && audio[3] === 0xa3)
30
+ return 'audio/webm';
31
+ if (audio.length >= 4 && audio[0] === 0x52 && audio[1] === 0x49 && audio[2] === 0x46 && audio[3] === 0x46)
32
+ return 'audio/wav'; // RIFF
33
+ if (audio.length >= 4 && audio[0] === 0x4f && audio[1] === 0x67 && audio[2] === 0x67 && audio[3] === 0x53)
34
+ return 'audio/ogg'; // OggS
35
+ if (audio.length >= 4 && audio[0] === 0x66 && audio[1] === 0x4c && audio[2] === 0x61 && audio[3] === 0x43)
36
+ return 'audio/flac'; // fLaC
37
+ return 'audio/mpeg';
38
+ }
39
+ function extensionFromMediaType(mediaType) {
40
+ const map = {
41
+ 'audio/mpeg': 'mp3',
42
+ 'audio/mp3': 'mp3',
43
+ 'audio/wav': 'wav',
44
+ 'audio/x-wav': 'wav',
45
+ 'audio/ogg': 'ogg',
46
+ 'audio/flac': 'flac',
47
+ 'audio/webm': 'webm',
48
+ 'audio/mp4': 'm4a',
49
+ 'audio/m4a': 'm4a',
50
+ 'audio/x-m4a': 'm4a',
51
+ };
52
+ return map[mediaType] || 'mp3';
53
+ }
54
+ function buildAudioFormData(audio, modelId) {
55
+ const mediaType = mediaTypeFromAudioBytes(audio);
56
+ const ext = extensionFromMediaType(mediaType);
57
+ const formData = new FormData();
58
+ // Copy into a fresh ArrayBuffer to satisfy TypeScript's BlobPart constraint
59
+ // (Uint8Array backed by SharedArrayBuffer is not assignable to BlobPart).
60
+ const buf = new Uint8Array(audio);
61
+ const blob = new Blob([buf], { type: mediaType });
62
+ formData.append('file', new File([blob], `audio.${ext}`, { type: mediaType }), `audio.${ext}`);
63
+ formData.append('model', modelId);
64
+ return { formData, mediaType };
65
+ }
66
+ // ─── OpenAI ──────────────────────────────────────────────────────────────────
67
+ // POST https://api.openai.com/v1/audio/transcriptions
68
+ // Multipart form: file, model, response_format, timestamp_granularities[], language
69
+ //
70
+ // gpt-4o-transcribe and gpt-4o-mini-transcribe only support response_format=json
71
+ // (NOT verbose_json). Word timestamps require verbose_json, so these models
72
+ // cannot return word-level timestamps. This is an OpenAI API limitation, not ours.
73
+ // whisper-1 supports verbose_json and returns word timestamps.
74
+ const GPT4O_TRANSCRIBE_MODELS = ['gpt-4o-transcribe', 'gpt-4o-mini-transcribe'];
75
+ export function createOpenAITranscriptionProvider() {
76
+ return {
77
+ async transcribe(options) {
78
+ const apiKey = process.env['OPENAI_API_KEY'];
79
+ if (!apiKey) {
80
+ throw new Error('Missing OPENAI_API_KEY. Run: egaki login --provider openai --key <key>');
81
+ }
82
+ const { formData } = buildAudioFormData(options.audio, options.modelId);
83
+ // gpt-4o-transcribe models only support "json" format;
84
+ // whisper-1 supports "verbose_json" which enables word timestamps.
85
+ const isGpt4oTranscribe = GPT4O_TRANSCRIBE_MODELS.includes(options.modelId);
86
+ formData.append('response_format', isGpt4oTranscribe ? 'json' : 'verbose_json');
87
+ if (!isGpt4oTranscribe) {
88
+ formData.append('timestamp_granularities[]', 'word');
89
+ }
90
+ if (options.language) {
91
+ formData.append('language', options.language);
92
+ }
93
+ const response = await fetch('https://api.openai.com/v1/audio/transcriptions', {
94
+ method: 'POST',
95
+ headers: { 'Authorization': `Bearer ${apiKey}` },
96
+ body: formData,
97
+ signal: options.abortSignal,
98
+ });
99
+ if (!response.ok) {
100
+ const errorText = await response.text().catch(() => '');
101
+ throw new Error(`OpenAI transcription API error ${response.status}: ${errorText || response.statusText}`);
102
+ }
103
+ const json = await response.json();
104
+ // Prefer word-level segments from the `words` array; fall back to
105
+ // sentence-level `segments` if words are not present.
106
+ const segments = json.words?.map((w) => ({ text: w.word, startSecond: w.start, endSecond: w.end }))
107
+ ?? json.segments?.map((s) => ({ text: s.text, startSecond: s.start, endSecond: s.end }))
108
+ ?? [];
109
+ return {
110
+ text: json.text,
111
+ segments,
112
+ language: json.language,
113
+ durationInSeconds: json.duration,
114
+ };
115
+ },
116
+ };
117
+ }
118
+ export function createGroqTranscriptionProvider() {
119
+ return {
120
+ async transcribe(options) {
121
+ const apiKey = process.env['GROQ_API_KEY'];
122
+ if (!apiKey) {
123
+ throw new Error('Missing GROQ_API_KEY. Run: egaki login --provider groq --key <key>');
124
+ }
125
+ const { formData } = buildAudioFormData(options.audio, options.modelId);
126
+ formData.append('response_format', 'verbose_json');
127
+ formData.append('timestamp_granularities[]', 'word');
128
+ formData.append('timestamp_granularities[]', 'segment');
129
+ if (options.language) {
130
+ formData.append('language', options.language);
131
+ }
132
+ const response = await fetch('https://api.groq.com/openai/v1/audio/transcriptions', {
133
+ method: 'POST',
134
+ headers: { 'Authorization': `Bearer ${apiKey}` },
135
+ body: formData,
136
+ signal: options.abortSignal,
137
+ });
138
+ if (!response.ok) {
139
+ const errorText = await response.text().catch(() => '');
140
+ throw new Error(`Groq transcription API error ${response.status}: ${errorText || response.statusText}`);
141
+ }
142
+ const json = await response.json();
143
+ // Prefer word-level from the `words` array (now parsed correctly);
144
+ // fall back to sentence-level `segments`.
145
+ const segments = json.words?.map((w) => ({ text: w.word, startSecond: w.start, endSecond: w.end }))
146
+ ?? json.segments?.map((s) => ({ text: s.text, startSecond: s.start, endSecond: s.end }))
147
+ ?? [];
148
+ return {
149
+ text: json.text,
150
+ segments,
151
+ language: json.language,
152
+ durationInSeconds: json.duration,
153
+ };
154
+ },
155
+ };
156
+ }
157
+ export function createElevenLabsTranscriptionProvider() {
158
+ return {
159
+ async transcribe(options) {
160
+ const apiKey = process.env['ELEVENLABS_API_KEY'];
161
+ if (!apiKey) {
162
+ throw new Error('Missing ELEVENLABS_API_KEY. Run: egaki login --provider elevenlabs --key <key>');
163
+ }
164
+ const mediaType = mediaTypeFromAudioBytes(options.audio);
165
+ const ext = extensionFromMediaType(mediaType);
166
+ const formData = new FormData();
167
+ const buf = new Uint8Array(options.audio);
168
+ const blob = new Blob([buf], { type: mediaType });
169
+ formData.append('file', new File([blob], `audio.${ext}`, { type: mediaType }), `audio.${ext}`);
170
+ formData.append('model_id', options.modelId);
171
+ formData.append('timestamps_granularity', 'word');
172
+ formData.append('tag_audio_events', 'true');
173
+ if (options.language) {
174
+ formData.append('language_code', options.language);
175
+ }
176
+ const response = await fetch('https://api.elevenlabs.io/v1/speech-to-text', {
177
+ method: 'POST',
178
+ headers: { 'xi-api-key': apiKey },
179
+ body: formData,
180
+ signal: options.abortSignal,
181
+ });
182
+ if (!response.ok) {
183
+ const errorText = await response.text().catch(() => '');
184
+ throw new Error(`ElevenLabs transcription API error ${response.status}: ${errorText || response.statusText}`);
185
+ }
186
+ const json = await response.json();
187
+ // Filter to only 'word' type entries (skip 'spacing' and 'audio_event')
188
+ const segments = json.words
189
+ ?.filter((w) => w.type === 'word' && w.text.trim())
190
+ .map((w) => ({ text: w.text, startSecond: w.start ?? 0, endSecond: w.end ?? 0 }))
191
+ ?? [];
192
+ // Duration is the end time of the last word
193
+ const lastWord = json.words?.findLast((w) => w.type === 'word' && w.end != null);
194
+ const durationInSeconds = lastWord?.end ?? undefined;
195
+ return {
196
+ text: json.text,
197
+ segments,
198
+ language: json.language_code,
199
+ durationInSeconds,
200
+ };
201
+ },
202
+ };
203
+ }
204
+ export function createDeepgramTranscriptionProvider() {
205
+ return {
206
+ async transcribe(options) {
207
+ const apiKey = process.env['DEEPGRAM_API_KEY'];
208
+ if (!apiKey) {
209
+ throw new Error('Missing DEEPGRAM_API_KEY. Run: egaki login --provider deepgram --key <key>');
210
+ }
211
+ const mediaType = mediaTypeFromAudioBytes(options.audio);
212
+ const params = new URLSearchParams();
213
+ params.append('model', options.modelId);
214
+ params.append('smart_format', 'true');
215
+ if (options.language) {
216
+ params.append('language', options.language);
217
+ }
218
+ else {
219
+ params.append('detect_language', 'true');
220
+ }
221
+ const response = await fetch(`https://api.deepgram.com/v1/listen?${params}`, {
222
+ method: 'POST',
223
+ headers: {
224
+ 'Authorization': `Token ${apiKey}`,
225
+ 'Content-Type': mediaType,
226
+ },
227
+ body: new Uint8Array(options.audio),
228
+ signal: options.abortSignal,
229
+ });
230
+ if (!response.ok) {
231
+ const errorText = await response.text().catch(() => '');
232
+ throw new Error(`Deepgram transcription API error ${response.status}: ${errorText || response.statusText}`);
233
+ }
234
+ const json = await response.json();
235
+ const channel = json.results?.channels?.[0];
236
+ const alt = channel?.alternatives?.[0];
237
+ const segments = alt?.words?.map((w) => ({ text: w.word, startSecond: w.start, endSecond: w.end }))
238
+ ?? [];
239
+ return {
240
+ text: alt?.transcript ?? '',
241
+ segments,
242
+ language: channel?.detected_language,
243
+ durationInSeconds: json.metadata?.duration,
244
+ };
245
+ },
246
+ };
247
+ }
248
+ const CARTESIA_API_BASE = 'https://api.cartesia.ai';
249
+ const CARTESIA_API_VERSION = '2026-03-01';
250
+ export function createCartesiaTranscriptionProvider() {
251
+ return {
252
+ async transcribe(options) {
253
+ const apiKey = process.env['CARTESIA_API_KEY'];
254
+ if (!apiKey) {
255
+ throw new Error('Missing CARTESIA_API_KEY. Run: egaki login --provider cartesia --key <key>');
256
+ }
257
+ const mediaType = mediaTypeFromAudioBytes(options.audio);
258
+ const ext = extensionFromMediaType(mediaType);
259
+ const formData = new FormData();
260
+ const buf = new Uint8Array(options.audio);
261
+ const blob = new Blob([buf], { type: mediaType });
262
+ formData.append('file', new File([blob], `audio.${ext}`, { type: mediaType }), `audio.${ext}`);
263
+ formData.append('model', options.modelId);
264
+ formData.append('language', options.language || 'en');
265
+ formData.append('timestamp_granularities[]', 'word');
266
+ const response = await fetch(`${CARTESIA_API_BASE}/stt`, {
267
+ method: 'POST',
268
+ headers: {
269
+ 'Cartesia-Version': CARTESIA_API_VERSION,
270
+ 'Authorization': `Bearer ${apiKey}`,
271
+ },
272
+ body: formData,
273
+ signal: options.abortSignal,
274
+ });
275
+ if (!response.ok) {
276
+ const errorText = await response.text().catch(() => '');
277
+ throw new Error(`Cartesia STT API error ${response.status}: ${errorText || response.statusText}`);
278
+ }
279
+ const json = await response.json();
280
+ const segments = json.words?.map((w) => ({ text: w.word, startSecond: w.start, endSecond: w.end }))
281
+ ?? [];
282
+ return {
283
+ text: json.text,
284
+ segments,
285
+ language: json.language,
286
+ durationInSeconds: json.duration,
287
+ };
288
+ },
289
+ };
290
+ }
@@ -0,0 +1,2 @@
1
+ export { VIDEO_CATALOG, findVideoModel, type VideoModelEntry, type VideoModelFeatures, type VideoModelCost, type PerVideoSecondCost, type UnknownCost as UnknownVideoCost, type VideoDurationPricingTier, } from './model-catalog.js';
2
+ //# sourceMappingURL=video-model-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-model-catalog.d.ts","sourceRoot":"","sources":["../../src/cli/video-model-catalog.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,aAAa,EACb,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,WAAW,IAAI,gBAAgB,EACpC,KAAK,wBAAwB,GAC9B,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,5 @@
1
+ // Re-exports from the unified model catalog.
2
+ // video-model-catalog.ts used to be a separate file. All video model data now
3
+ // lives in model-catalog.ts alongside image models. This file exists only so
4
+ // existing imports (gateway/src/plans.ts, etc.) keep working without changes.
5
+ export { VIDEO_CATALOG, findVideoModel, } from './model-catalog.js';
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ export type XaiAuth = {
3
+ email?: string;
4
+ access: string;
5
+ refresh: string;
6
+ expires: number;
7
+ };
8
+ declare const tokenResponseSchema: z.ZodObject<{
9
+ access_token: z.ZodString;
10
+ refresh_token: z.ZodOptional<z.ZodString>;
11
+ id_token: z.ZodOptional<z.ZodString>;
12
+ expires_in: z.ZodOptional<z.ZodNumber>;
13
+ }, z.core.$strip>;
14
+ type TokenResponse = z.infer<typeof tokenResponseSchema>;
15
+ /** Returns true if the access token's exp claim is within the skew window. */
16
+ export declare function accessTokenIsExpiring(token: string | undefined, skewMs?: number): boolean;
17
+ export declare function refreshXaiToken(refreshToken: string): Promise<TokenResponse>;
18
+ /**
19
+ * Run the xAI OAuth browser flow. Opens the system browser for authorization,
20
+ * waits for the callback, and returns an XaiAuth object with tokens.
21
+ */
22
+ export declare function xaiOAuthLogin(): Promise<XaiAuth>;
23
+ /**
24
+ * Returns a valid XaiAuth, refreshing the access token if it's expired or
25
+ * about to expire. Calls `save` to persist the refreshed tokens.
26
+ */
27
+ export declare function getValidXaiAuth(auth: XaiAuth, save: (auth: XaiAuth) => void): Promise<XaiAuth | Error>;
28
+ export {};
29
+ //# sourceMappingURL=xai-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xai-auth.d.ts","sourceRoot":"","sources":["../../src/cli/xai-auth.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAwBvB,MAAM,MAAM,OAAO,GAAG;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,QAAA,MAAM,mBAAmB;;;;;iBAKvB,CAAA;AAEF,KAAK,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AA+DxD,8EAA8E;AAC9E,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,GAAE,MAAqC,GAC5C,OAAO,CAKT;AA6BD,wBAAsB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAelF;AAwHD;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAoEtD;AAID;;;GAGG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAC5B,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,CAuB1B"}