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.
- package/CHANGELOG.md +140 -9
- package/dist/cli/cache-utils.d.ts +33 -0
- package/dist/cli/cache-utils.d.ts.map +1 -0
- package/dist/cli/cache-utils.js +157 -0
- package/dist/cli/cached-generate.d.ts +105 -0
- package/dist/cli/cached-generate.d.ts.map +1 -0
- package/dist/cli/cached-generate.js +208 -0
- package/dist/cli/cached-generate.test.d.ts +11 -0
- package/dist/cli/cached-generate.test.d.ts.map +1 -0
- package/dist/cli/cached-generate.test.js +431 -0
- package/dist/cli/cartesia-provider.d.ts +16 -0
- package/dist/cli/cartesia-provider.d.ts.map +1 -0
- package/dist/cli/cartesia-provider.js +184 -0
- package/dist/cli/chatgpt-auth.d.ts.map +1 -0
- package/dist/cli/cli.d.ts +4 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/{cli.js → cli/cli.js} +626 -600
- package/dist/cli/clone-generate.d.ts +26 -0
- package/dist/cli/clone-generate.d.ts.map +1 -0
- package/dist/cli/clone-generate.js +148 -0
- package/dist/cli/credentials.d.ts.map +1 -0
- package/dist/{credentials.js → cli/credentials.js} +20 -0
- package/dist/cli/elevenlabs-speech-provider.d.ts +26 -0
- package/dist/cli/elevenlabs-speech-provider.d.ts.map +1 -0
- package/dist/cli/elevenlabs-speech-provider.js +199 -0
- package/dist/cli/generate.d.ts +140 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +604 -0
- package/dist/cli/generate.test.d.ts +2 -0
- package/dist/cli/generate.test.d.ts.map +1 -0
- package/dist/cli/generate.test.js +131 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +7 -0
- package/dist/{model-catalog.d.ts → cli/model-catalog.d.ts} +6 -0
- package/dist/cli/model-catalog.d.ts.map +1 -0
- package/dist/{model-catalog.js → cli/model-catalog.js} +714 -4
- package/dist/{models.d.ts → cli/models.d.ts} +12 -5
- package/dist/cli/models.d.ts.map +1 -0
- package/dist/{models.js → cli/models.js} +58 -57
- package/dist/cli/open-browser.d.ts.map +1 -0
- package/dist/cli/openai-speech-provider.d.ts +3 -0
- package/dist/cli/openai-speech-provider.d.ts.map +1 -0
- package/dist/cli/openai-speech-provider.js +28 -0
- package/dist/cli/separation-generate.d.ts +34 -0
- package/dist/cli/separation-generate.d.ts.map +1 -0
- package/dist/cli/separation-generate.js +117 -0
- package/dist/cli/speech-catalog.d.ts +35 -0
- package/dist/cli/speech-catalog.d.ts.map +1 -0
- package/dist/cli/speech-catalog.js +195 -0
- package/dist/cli/speech-generate.d.ts +86 -0
- package/dist/cli/speech-generate.d.ts.map +1 -0
- package/dist/cli/speech-generate.js +156 -0
- package/dist/cli/speech-models.d.ts +8 -0
- package/dist/cli/speech-models.d.ts.map +1 -0
- package/dist/cli/speech-models.js +109 -0
- package/dist/cli/speech-provider.test.d.ts +2 -0
- package/dist/cli/speech-provider.test.d.ts.map +1 -0
- package/dist/cli/speech-provider.test.js +197 -0
- package/dist/cli/subscription.d.ts.map +1 -0
- package/dist/cli/transcription-catalog.d.ts +35 -0
- package/dist/cli/transcription-catalog.d.ts.map +1 -0
- package/dist/cli/transcription-catalog.js +192 -0
- package/dist/cli/transcription-generate.d.ts +62 -0
- package/dist/cli/transcription-generate.d.ts.map +1 -0
- package/dist/cli/transcription-generate.js +144 -0
- package/dist/cli/transcription-models.d.ts +9 -0
- package/dist/cli/transcription-models.d.ts.map +1 -0
- package/dist/cli/transcription-models.js +100 -0
- package/dist/cli/transcription-providers.d.ts +22 -0
- package/dist/cli/transcription-providers.d.ts.map +1 -0
- package/dist/cli/transcription-providers.js +290 -0
- package/dist/cli/video-model-catalog.d.ts.map +1 -0
- package/dist/cli/xai-auth.d.ts.map +1 -0
- package/dist/{xai-auth.js → cli/xai-auth.js} +1 -1
- package/dist/vite/angled-screen.d.ts +57 -0
- package/dist/vite/angled-screen.d.ts.map +1 -0
- package/dist/vite/angled-screen.js +115 -0
- package/dist/vite/app.d.ts +51 -0
- package/dist/vite/app.d.ts.map +1 -0
- package/dist/vite/app.js +150 -0
- package/dist/vite/bands-shader.d.ts +47 -0
- package/dist/vite/bands-shader.d.ts.map +1 -0
- package/dist/vite/bands-shader.js +267 -0
- package/dist/vite/code-block.d.ts +107 -0
- package/dist/vite/code-block.d.ts.map +1 -0
- package/dist/vite/code-block.js +641 -0
- package/dist/vite/components.d.ts +36 -0
- package/dist/vite/components.d.ts.map +1 -0
- package/dist/vite/components.js +113 -0
- package/dist/vite/dispersion-rings-shader.d.ts +44 -0
- package/dist/vite/dispersion-rings-shader.d.ts.map +1 -0
- package/dist/vite/dispersion-rings-shader.js +282 -0
- package/dist/vite/easing-curves.d.ts +129 -0
- package/dist/vite/easing-curves.d.ts.map +1 -0
- package/dist/vite/easing-curves.js +584 -0
- package/dist/vite/easing-curves.test.d.ts +2 -0
- package/dist/vite/easing-curves.test.d.ts.map +1 -0
- package/dist/vite/easing-curves.test.js +200 -0
- package/dist/vite/generated-media-client.d.ts +35 -0
- package/dist/vite/generated-media-client.d.ts.map +1 -0
- package/dist/vite/generated-media-client.js +76 -0
- package/dist/vite/keyframes.d.ts +129 -0
- package/dist/vite/keyframes.d.ts.map +1 -0
- package/dist/vite/keyframes.js +194 -0
- package/dist/vite/layout-editor.d.ts +45 -0
- package/dist/vite/layout-editor.d.ts.map +1 -0
- package/dist/vite/layout-editor.js +587 -0
- package/dist/vite/layout-transition.d.ts +136 -0
- package/dist/vite/layout-transition.d.ts.map +1 -0
- package/dist/vite/layout-transition.js +581 -0
- package/dist/vite/liquid-gradient-shader.d.ts +62 -0
- package/dist/vite/liquid-gradient-shader.d.ts.map +1 -0
- package/dist/vite/liquid-gradient-shader.js +413 -0
- package/dist/vite/mdx-client.d.ts +15 -0
- package/dist/vite/mdx-client.d.ts.map +1 -0
- package/dist/vite/mdx-client.js +265 -0
- package/dist/vite/mdx-parse.d.ts +102 -0
- package/dist/vite/mdx-parse.d.ts.map +1 -0
- package/dist/vite/mdx-parse.js +251 -0
- package/dist/vite/mdx-provided-components.d.ts +18 -0
- package/dist/vite/mdx-provided-components.d.ts.map +1 -0
- package/dist/vite/mdx-provided-components.js +14 -0
- package/dist/vite/mdx-video.d.ts +327 -0
- package/dist/vite/mdx-video.d.ts.map +1 -0
- package/dist/vite/mdx-video.js +596 -0
- package/dist/vite/mdx-video.test.d.ts +9 -0
- package/dist/vite/mdx-video.test.d.ts.map +1 -0
- package/dist/vite/mdx-video.test.js +1945 -0
- package/dist/vite/media-components.d.ts +45 -0
- package/dist/vite/media-components.d.ts.map +1 -0
- package/dist/vite/media-components.js +355 -0
- package/dist/vite/media-duration-store.d.ts +66 -0
- package/dist/vite/media-duration-store.d.ts.map +1 -0
- package/dist/vite/media-duration-store.js +204 -0
- package/dist/vite/player-page.d.ts +35 -0
- package/dist/vite/player-page.d.ts.map +1 -0
- package/dist/vite/player-page.js +720 -0
- package/dist/vite/render-client.d.ts +18 -0
- package/dist/vite/render-client.d.ts.map +1 -0
- package/dist/vite/render-client.js +67 -0
- package/dist/vite/sdk.d.ts +221 -0
- package/dist/vite/sdk.d.ts.map +1 -0
- package/dist/vite/sdk.js +355 -0
- package/dist/vite/server-components.d.ts +55 -0
- package/dist/vite/server-components.d.ts.map +1 -0
- package/dist/vite/server-components.js +156 -0
- package/dist/vite/server-mdx.d.ts +74 -0
- package/dist/vite/server-mdx.d.ts.map +1 -0
- package/dist/vite/server-mdx.js +259 -0
- package/dist/vite/shader-renderer.d.ts +48 -0
- package/dist/vite/shader-renderer.d.ts.map +1 -0
- package/dist/vite/shader-renderer.js +411 -0
- package/dist/vite/store-hooks.d.ts +12 -0
- package/dist/vite/store-hooks.d.ts.map +1 -0
- package/dist/vite/store-hooks.js +93 -0
- package/dist/vite/store.d.ts +75 -0
- package/dist/vite/store.d.ts.map +1 -0
- package/dist/vite/store.js +52 -0
- package/dist/vite/store.test.d.ts +6 -0
- package/dist/vite/store.test.d.ts.map +1 -0
- package/dist/vite/store.test.js +172 -0
- package/dist/vite/tweakpane-hook.d.ts +94 -0
- package/dist/vite/tweakpane-hook.d.ts.map +1 -0
- package/dist/vite/tweakpane-hook.js +450 -0
- package/dist/vite/vite-plugin.d.ts +28 -0
- package/dist/vite/vite-plugin.d.ts.map +1 -0
- package/dist/vite/vite-plugin.js +538 -0
- package/dist/vite/wave-gradient-shader.d.ts +41 -0
- package/dist/vite/wave-gradient-shader.d.ts.map +1 -0
- package/dist/vite/wave-gradient-shader.js +207 -0
- package/package.json +101 -24
- package/skills/egaki/SKILL.md +162 -1
- package/src/cli/cache-utils.ts +169 -0
- package/src/cli/cached-generate.test.ts +531 -0
- package/src/cli/cached-generate.ts +348 -0
- package/src/cli/cartesia-provider.ts +249 -0
- package/src/{cli.ts → cli/cli.ts} +836 -884
- package/src/cli/clone-generate.ts +202 -0
- package/src/{credentials.ts → cli/credentials.ts} +20 -0
- package/src/cli/elevenlabs-speech-provider.ts +243 -0
- package/src/cli/generate.test.ts +166 -0
- package/src/cli/generate.ts +912 -0
- package/src/cli/main.ts +8 -0
- package/src/{model-catalog.ts → cli/model-catalog.ts} +787 -58
- package/src/{models.ts → cli/models.ts} +65 -86
- package/src/cli/openai-speech-provider.ts +34 -0
- package/src/cli/separation-generate.ts +187 -0
- package/src/cli/speech-catalog.ts +253 -0
- package/src/cli/speech-generate.ts +275 -0
- package/src/cli/speech-models.ts +146 -0
- package/src/cli/speech-provider.test.ts +226 -0
- package/src/cli/transcription-catalog.ts +250 -0
- package/src/cli/transcription-generate.ts +214 -0
- package/src/cli/transcription-models.ts +136 -0
- package/src/cli/transcription-providers.ts +427 -0
- package/src/{xai-auth.ts → cli/xai-auth.ts} +1 -1
- package/src/vite/angled-screen.tsx +214 -0
- package/src/vite/app.tsx +197 -0
- package/src/vite/bands-shader.tsx +319 -0
- package/src/vite/code-block.tsx +939 -0
- package/src/vite/components.tsx +278 -0
- package/src/vite/dispersion-rings-shader.tsx +331 -0
- package/src/vite/easing-curves.test.ts +232 -0
- package/src/vite/easing-curves.ts +743 -0
- package/src/vite/generated-media-client.tsx +121 -0
- package/src/vite/keyframes.tsx +347 -0
- package/src/vite/layout-editor.tsx +709 -0
- package/src/vite/layout-transition.tsx +706 -0
- package/src/vite/liquid-gradient-shader.tsx +474 -0
- package/src/vite/mdx-client.tsx +420 -0
- package/src/vite/mdx-parse.ts +343 -0
- package/src/vite/mdx-provided-components.ts +19 -0
- package/src/vite/mdx-video.test.tsx +2219 -0
- package/src/vite/mdx-video.tsx +976 -0
- package/src/vite/media-components.tsx +473 -0
- package/src/vite/media-duration-store.ts +225 -0
- package/src/vite/motion-timing.ts +194 -0
- package/src/vite/player-page.tsx +1107 -0
- package/src/vite/render-client.ts +84 -0
- package/src/vite/sdk.ts +598 -0
- package/src/vite/server-components.tsx +241 -0
- package/src/vite/server-mdx.ts +285 -0
- package/src/vite/shader-renderer.tsx +535 -0
- package/src/vite/store-hooks.ts +117 -0
- package/src/vite/store.test.ts +202 -0
- package/src/vite/store.ts +115 -0
- package/src/vite/styles.css +21 -0
- package/src/vite/tweakpane-hook.tsx +593 -0
- package/src/vite/virtual-modules.d.ts +30 -0
- package/src/vite/vite-plugin.ts +584 -0
- package/src/vite/wave-gradient-shader.tsx +253 -0
- package/README.md +0 -370
- package/dist/antigravity-auth.d.ts +0 -15
- package/dist/antigravity-auth.d.ts.map +0 -1
- package/dist/antigravity-auth.js +0 -544
- package/dist/antigravity-image.d.ts +0 -11
- package/dist/antigravity-image.d.ts.map +0 -1
- package/dist/antigravity-image.js +0 -285
- package/dist/chatgpt-auth.d.ts.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/credentials.d.ts.map +0 -1
- package/dist/gateway-model-candidates.generated.d.ts +0 -11
- package/dist/gateway-model-candidates.generated.d.ts.map +0 -1
- package/dist/gateway-model-candidates.generated.js +0 -64
- package/dist/login.d.ts.map +0 -1
- package/dist/model-catalog.d.ts.map +0 -1
- package/dist/models.d.ts.map +0 -1
- package/dist/open-browser.d.ts.map +0 -1
- package/dist/subscription.d.ts.map +0 -1
- package/dist/video-model-catalog.d.ts.map +0 -1
- package/dist/xai-auth.d.ts.map +0 -1
- /package/dist/{chatgpt-auth.d.ts → cli/chatgpt-auth.d.ts} +0 -0
- /package/dist/{chatgpt-auth.js → cli/chatgpt-auth.js} +0 -0
- /package/dist/{credentials.d.ts → cli/credentials.d.ts} +0 -0
- /package/dist/{login.d.ts → cli/login.d.ts} +0 -0
- /package/dist/{login.js → cli/login.js} +0 -0
- /package/dist/{open-browser.d.ts → cli/open-browser.d.ts} +0 -0
- /package/dist/{open-browser.js → cli/open-browser.js} +0 -0
- /package/dist/{subscription.d.ts → cli/subscription.d.ts} +0 -0
- /package/dist/{subscription.js → cli/subscription.js} +0 -0
- /package/dist/{video-model-catalog.d.ts → cli/video-model-catalog.d.ts} +0 -0
- /package/dist/{video-model-catalog.js → cli/video-model-catalog.js} +0 -0
- /package/dist/{xai-auth.d.ts → cli/xai-auth.d.ts} +0 -0
- /package/src/{chatgpt-auth.ts → cli/chatgpt-auth.ts} +0 -0
- /package/src/{login.ts → cli/login.ts} +0 -0
- /package/src/{open-browser.ts → cli/open-browser.ts} +0 -0
- /package/src/{subscription.ts → cli/subscription.ts} +0 -0
- /package/src/{video-model-catalog.ts → cli/video-model-catalog.ts} +0 -0
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
// Programmatic API for egaki image and video generation.
|
|
2
|
+
// Returns Error | Result (errore style) instead of process.exit/console.error.
|
|
3
|
+
//
|
|
4
|
+
// Two variants for each function:
|
|
5
|
+
// - `generateImage(opts)` — cached, writes to public/generated/, returns { src: string }
|
|
6
|
+
// - `generateImageUncached(opts)` — raw, returns bytes in GenerateImageResult
|
|
7
|
+
//
|
|
8
|
+
// The CLI uses *Uncached variants. The cached variants are for the Vite MDX
|
|
9
|
+
// video framework and .server.tsx components.
|
|
10
|
+
//
|
|
11
|
+
// Usage:
|
|
12
|
+
// import { generateImage, generateImageUncached } from 'egaki/generate'
|
|
13
|
+
// const cached = await generateImage({ prompt: 'a sunset' })
|
|
14
|
+
// if (!(cached instanceof Error)) cached.src // '/generated/image/sunset-a1b2c3d4.png'
|
|
15
|
+
// const raw = await generateImageUncached({ prompt: 'a sunset' })
|
|
16
|
+
// if (!(raw instanceof Error)) raw.images[0].uint8Array // raw bytes
|
|
17
|
+
import { generateImage as aiGenerateImage, generateText, experimental_generateVideo as aiGenerateVideo, } from 'ai';
|
|
18
|
+
import { createParser } from 'eventsource-parser';
|
|
19
|
+
import { injectCredentialsToEnv, getChatGptAuth, saveChatGptAuth, } from './credentials.js';
|
|
20
|
+
import { getModelConfig, createImageModel, createTextModel, createVideoModel, shouldUseResponsesApi, DEFAULT_MODEL, DEFAULT_VIDEO_MODEL, ValidationError, } from './models.js';
|
|
21
|
+
export { ValidationError };
|
|
22
|
+
import { getValidChatGptAuth } from './chatgpt-auth.js';
|
|
23
|
+
export function buildImageProviderOptions(provider, opts) {
|
|
24
|
+
switch (provider) {
|
|
25
|
+
case 'google': {
|
|
26
|
+
const googleOpts = {
|
|
27
|
+
...(opts.allowPeople ? { personGeneration: 'allow_all' } : {}),
|
|
28
|
+
...(opts.aspectRatio ? { aspectRatio: opts.aspectRatio } : {}),
|
|
29
|
+
};
|
|
30
|
+
return { google: googleOpts };
|
|
31
|
+
}
|
|
32
|
+
case 'vertex': {
|
|
33
|
+
const vertexOpts = {
|
|
34
|
+
...(opts.allowPeople ? { personGeneration: 'allow_all' } : {}),
|
|
35
|
+
...(opts.negativePrompt ? { negativePrompt: opts.negativePrompt } : {}),
|
|
36
|
+
};
|
|
37
|
+
return { vertex: vertexOpts };
|
|
38
|
+
}
|
|
39
|
+
case 'xai': {
|
|
40
|
+
const xaiOpts = {
|
|
41
|
+
...(opts.quality ? { quality: opts.quality } : {}),
|
|
42
|
+
...(opts.resolution ? { resolution: opts.resolution } : {}),
|
|
43
|
+
...(opts.outputFormat ? { output_format: opts.outputFormat } : {}),
|
|
44
|
+
};
|
|
45
|
+
return { xai: xaiOpts };
|
|
46
|
+
}
|
|
47
|
+
case 'openai': {
|
|
48
|
+
const openaiOpts = {
|
|
49
|
+
...(opts.quality ? { quality: opts.quality } : {}),
|
|
50
|
+
...(opts.outputFormat ? { outputFormat: opts.outputFormat } : {}),
|
|
51
|
+
};
|
|
52
|
+
return { openai: openaiOpts };
|
|
53
|
+
}
|
|
54
|
+
case 'fal': {
|
|
55
|
+
const falOpts = {
|
|
56
|
+
...(opts.outputFormat ? { outputFormat: opts.outputFormat } : {}),
|
|
57
|
+
...(opts.negativePrompt ? { negativePrompt: opts.negativePrompt } : {}),
|
|
58
|
+
};
|
|
59
|
+
return { fal: falOpts };
|
|
60
|
+
}
|
|
61
|
+
default:
|
|
62
|
+
return {};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function buildVideoProviderOptions(provider, opts) {
|
|
66
|
+
switch (provider) {
|
|
67
|
+
case 'xai': {
|
|
68
|
+
const base = {
|
|
69
|
+
...(opts.resolution ? { resolution: opts.resolution } : {}),
|
|
70
|
+
};
|
|
71
|
+
if (opts.mode === 'edit-video' && opts.videoUrl) {
|
|
72
|
+
const xaiOpts = { ...base, mode: 'edit-video', videoUrl: opts.videoUrl };
|
|
73
|
+
return { xai: xaiOpts };
|
|
74
|
+
}
|
|
75
|
+
if (opts.mode === 'extend-video' && opts.videoUrl) {
|
|
76
|
+
const xaiOpts = { ...base, mode: 'extend-video', videoUrl: opts.videoUrl };
|
|
77
|
+
return { xai: xaiOpts };
|
|
78
|
+
}
|
|
79
|
+
if (opts.mode === 'reference-to-video' && opts.referenceImages) {
|
|
80
|
+
const xaiOpts = { ...base, mode: 'reference-to-video', referenceImageUrls: opts.referenceImages };
|
|
81
|
+
return { xai: xaiOpts };
|
|
82
|
+
}
|
|
83
|
+
if (Object.keys(base).length === 0)
|
|
84
|
+
return undefined;
|
|
85
|
+
const xaiOpts = { ...base };
|
|
86
|
+
return { xai: xaiOpts };
|
|
87
|
+
}
|
|
88
|
+
case 'bytedance': {
|
|
89
|
+
const bytedanceOpts = {
|
|
90
|
+
...(opts.resolution ? { resolution: opts.resolution } : {}),
|
|
91
|
+
...(opts.referenceImages ? { referenceImages: opts.referenceImages } : {}),
|
|
92
|
+
};
|
|
93
|
+
if (Object.keys(bytedanceOpts).length === 0)
|
|
94
|
+
return undefined;
|
|
95
|
+
return { bytedance: bytedanceOpts };
|
|
96
|
+
}
|
|
97
|
+
case 'fal': {
|
|
98
|
+
const falOpts = {
|
|
99
|
+
...(opts.resolution ? { resolution: opts.resolution } : {}),
|
|
100
|
+
...(opts.negativePrompt ? { negativePrompt: opts.negativePrompt } : {}),
|
|
101
|
+
};
|
|
102
|
+
if (Object.keys(falOpts).length === 0)
|
|
103
|
+
return undefined;
|
|
104
|
+
return { fal: falOpts };
|
|
105
|
+
}
|
|
106
|
+
case 'google': {
|
|
107
|
+
const googleOpts = {
|
|
108
|
+
...(opts.negativePrompt ? { negativePrompt: opts.negativePrompt } : {}),
|
|
109
|
+
};
|
|
110
|
+
if (Object.keys(googleOpts).length === 0)
|
|
111
|
+
return undefined;
|
|
112
|
+
return { google: googleOpts };
|
|
113
|
+
}
|
|
114
|
+
case 'vertex': {
|
|
115
|
+
const vertexOpts = {
|
|
116
|
+
...(opts.negativePrompt ? { negativePrompt: opts.negativePrompt } : {}),
|
|
117
|
+
};
|
|
118
|
+
if (Object.keys(vertexOpts).length === 0)
|
|
119
|
+
return undefined;
|
|
120
|
+
return { vertex: vertexOpts };
|
|
121
|
+
}
|
|
122
|
+
default:
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ─── cost calculation ────────────────────────────────────────────────────────
|
|
127
|
+
export function calculateCost(cost, usage, count = 1) {
|
|
128
|
+
if (cost.type === 'per-image') {
|
|
129
|
+
return cost.perImage * count;
|
|
130
|
+
}
|
|
131
|
+
if (cost.type === 'per-token' && usage.inputTokens != null && usage.outputTokens != null) {
|
|
132
|
+
return ((usage.inputTokens * cost.inputPerM + usage.outputTokens * cost.outputPerM) / 1_000_000);
|
|
133
|
+
}
|
|
134
|
+
if (cost.type === 'per-video-second') {
|
|
135
|
+
const durationSec = usage.durationSeconds ?? cost.defaultDurationSec;
|
|
136
|
+
const resolution = normalizeResolutionKey(usage.resolution);
|
|
137
|
+
const hasVideoInput = usage.hasVideoInput ?? false;
|
|
138
|
+
const tier = cost.tiers.find((t) => normalizeResolutionKey(t.resolution) === resolution &&
|
|
139
|
+
(t.hasVideoInput == null || t.hasVideoInput === hasVideoInput)) ??
|
|
140
|
+
cost.tiers.find((t) => normalizeResolutionKey(t.resolution) === resolution) ??
|
|
141
|
+
cost.tiers[0];
|
|
142
|
+
if (!tier) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return tier.costPerSecond * durationSec * count;
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
function normalizeResolutionKey(input) {
|
|
150
|
+
if (!input)
|
|
151
|
+
return undefined;
|
|
152
|
+
const normalized = input.trim().toLowerCase();
|
|
153
|
+
if (normalized === '1920x1080')
|
|
154
|
+
return '1080p';
|
|
155
|
+
if (normalized === '1280x720')
|
|
156
|
+
return '720p';
|
|
157
|
+
if (normalized === '854x480' || normalized === '848x480')
|
|
158
|
+
return '480p';
|
|
159
|
+
return normalized;
|
|
160
|
+
}
|
|
161
|
+
// ─── image byte helpers ──────────────────────────────────────────────────────
|
|
162
|
+
function inferImageMediaType(image) {
|
|
163
|
+
if (image.length >= 8 && image[0] === 0x89 && image[1] === 0x50 && image[2] === 0x4e && image[3] === 0x47) {
|
|
164
|
+
return 'image/png';
|
|
165
|
+
}
|
|
166
|
+
if (image.length >= 3 && image[0] === 0xff && image[1] === 0xd8 && image[2] === 0xff) {
|
|
167
|
+
return 'image/jpeg';
|
|
168
|
+
}
|
|
169
|
+
if (image.length >= 12 &&
|
|
170
|
+
image[0] === 0x52 && image[1] === 0x49 && image[2] === 0x46 && image[3] === 0x46 &&
|
|
171
|
+
image[8] === 0x57 && image[9] === 0x45 && image[10] === 0x42 && image[11] === 0x50) {
|
|
172
|
+
return 'image/webp';
|
|
173
|
+
}
|
|
174
|
+
if (image.length >= 6 &&
|
|
175
|
+
image[0] === 0x47 && image[1] === 0x49 && image[2] === 0x46 && image[3] === 0x38) {
|
|
176
|
+
return 'image/gif';
|
|
177
|
+
}
|
|
178
|
+
return 'image/png';
|
|
179
|
+
}
|
|
180
|
+
function imageBytesToDataUrl(image) {
|
|
181
|
+
const mediaType = inferImageMediaType(image);
|
|
182
|
+
return `data:${mediaType};base64,${Buffer.from(image).toString('base64')}`;
|
|
183
|
+
}
|
|
184
|
+
function chatGptImageSizeFromAspectRatio(aspectRatio) {
|
|
185
|
+
switch (aspectRatio) {
|
|
186
|
+
case '1:1':
|
|
187
|
+
return '1024x1024';
|
|
188
|
+
case '3:2':
|
|
189
|
+
return '1536x1024';
|
|
190
|
+
case '2:3':
|
|
191
|
+
return '1024x1536';
|
|
192
|
+
default:
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function isAspectRatio(input) {
|
|
197
|
+
return /^\d+:\d+$/.test(input);
|
|
198
|
+
}
|
|
199
|
+
/** Convert any thrown value into an Error instance. */
|
|
200
|
+
function toError(err) {
|
|
201
|
+
if (err instanceof Error)
|
|
202
|
+
return err;
|
|
203
|
+
return new Error(String(err));
|
|
204
|
+
}
|
|
205
|
+
// ─── generateImage ───────────────────────────────────────────────────────────
|
|
206
|
+
/**
|
|
207
|
+
* Generate images from a text prompt. Auto-detects which generation strategy
|
|
208
|
+
* to use (image API, text model, or ChatGPT Responses API) based on model ID.
|
|
209
|
+
* Shares credentials and subscription with the CLI.
|
|
210
|
+
*/
|
|
211
|
+
export async function generateImageUncached(opts) {
|
|
212
|
+
injectCredentialsToEnv();
|
|
213
|
+
const model = opts.model ?? DEFAULT_MODEL;
|
|
214
|
+
const count = opts.count ?? 1;
|
|
215
|
+
const config = getModelConfig(model);
|
|
216
|
+
if (config instanceof Error)
|
|
217
|
+
return config;
|
|
218
|
+
const parsedAspectRatio = opts.aspectRatio && isAspectRatio(opts.aspectRatio)
|
|
219
|
+
? opts.aspectRatio
|
|
220
|
+
: undefined;
|
|
221
|
+
const inputImages = opts.inputImages ?? [];
|
|
222
|
+
// ChatGPT OAuth + OpenAI image models → Responses API path
|
|
223
|
+
const useResponsesApi = config.strategy === 'image' && shouldUseResponsesApi(model);
|
|
224
|
+
if (useResponsesApi) {
|
|
225
|
+
return generateWithResponsesApi({
|
|
226
|
+
prompt: opts.prompt,
|
|
227
|
+
model,
|
|
228
|
+
count,
|
|
229
|
+
aspectRatio: parsedAspectRatio,
|
|
230
|
+
seed: opts.seed,
|
|
231
|
+
maskImage: opts.maskImage,
|
|
232
|
+
inputImages,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
if (config.strategy === 'image') {
|
|
236
|
+
return generateWithImageModel({
|
|
237
|
+
prompt: opts.prompt,
|
|
238
|
+
model,
|
|
239
|
+
count,
|
|
240
|
+
aspectRatio: parsedAspectRatio,
|
|
241
|
+
seed: opts.seed,
|
|
242
|
+
inputImages,
|
|
243
|
+
maskImage: opts.maskImage,
|
|
244
|
+
allowPeople: opts.allowPeople ?? false,
|
|
245
|
+
quality: opts.quality,
|
|
246
|
+
resolution: opts.resolution,
|
|
247
|
+
outputFormat: opts.outputFormat,
|
|
248
|
+
negativePrompt: opts.negativePrompt,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
// Text model path (Gemini multimodal)
|
|
252
|
+
return generateWithTextModelPath({
|
|
253
|
+
prompt: opts.prompt,
|
|
254
|
+
model,
|
|
255
|
+
inputImages,
|
|
256
|
+
imageSize: opts.imageSize,
|
|
257
|
+
aspectRatio: opts.aspectRatio,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
// ─── generateVideo ───────────────────────────────────────────────────────────
|
|
261
|
+
/**
|
|
262
|
+
* Generate videos from a text prompt (or image+text for i2v models).
|
|
263
|
+
* Shares credentials and subscription with the CLI.
|
|
264
|
+
*/
|
|
265
|
+
export async function generateVideoUncached(opts) {
|
|
266
|
+
injectCredentialsToEnv();
|
|
267
|
+
const model = opts.model ?? DEFAULT_VIDEO_MODEL;
|
|
268
|
+
const count = opts.count ?? 1;
|
|
269
|
+
const config = getModelConfig(model);
|
|
270
|
+
if (config instanceof Error)
|
|
271
|
+
return config;
|
|
272
|
+
if (config.strategy !== 'video') {
|
|
273
|
+
return new ValidationError(`Model ${model} is not a video model`);
|
|
274
|
+
}
|
|
275
|
+
const isVideoInputMode = opts.mode === 'edit-video' || opts.mode === 'extend-video';
|
|
276
|
+
// Validate mode-specific required inputs
|
|
277
|
+
if (isVideoInputMode && !opts.videoUrl) {
|
|
278
|
+
return new ValidationError(`videoUrl is required with mode ${opts.mode}`);
|
|
279
|
+
}
|
|
280
|
+
if (opts.mode === 'reference-to-video' && (!opts.referenceImages || opts.referenceImages.length === 0)) {
|
|
281
|
+
return new ValidationError('referenceImages is required with mode reference-to-video');
|
|
282
|
+
}
|
|
283
|
+
if (opts.referenceImages?.length && !config.providerOptions?.some((opt) => opt.flag === 'reference-images')) {
|
|
284
|
+
return new ValidationError(`Model ${model} does not support referenceImages`);
|
|
285
|
+
}
|
|
286
|
+
if (opts.videoUrl && !config.providerOptions?.some((opt) => opt.flag === 'video-url')) {
|
|
287
|
+
return new ValidationError(`Model ${model} does not support video URL input for editing/extension`);
|
|
288
|
+
}
|
|
289
|
+
const videoModel = await createVideoModel(model);
|
|
290
|
+
if (videoModel instanceof Error)
|
|
291
|
+
return videoModel;
|
|
292
|
+
const providerOptions = buildVideoProviderOptions(config.provider, {
|
|
293
|
+
resolution: opts.resolution,
|
|
294
|
+
mode: opts.mode,
|
|
295
|
+
videoUrl: opts.videoUrl,
|
|
296
|
+
referenceImages: opts.referenceImages,
|
|
297
|
+
negativePrompt: opts.negativePrompt,
|
|
298
|
+
model,
|
|
299
|
+
});
|
|
300
|
+
let result;
|
|
301
|
+
try {
|
|
302
|
+
result = await aiGenerateVideo({
|
|
303
|
+
model: videoModel,
|
|
304
|
+
prompt: opts.inputImage
|
|
305
|
+
? { image: opts.inputImage, text: opts.prompt }
|
|
306
|
+
: opts.prompt,
|
|
307
|
+
n: count,
|
|
308
|
+
...(opts.aspectRatio ? { aspectRatio: opts.aspectRatio } : {}),
|
|
309
|
+
...(opts.resolution ? { resolution: opts.resolution } : {}),
|
|
310
|
+
...(opts.duration != null ? { duration: opts.duration } : {}),
|
|
311
|
+
...(opts.fps != null ? { fps: opts.fps } : {}),
|
|
312
|
+
...(opts.seed != null ? { seed: opts.seed } : {}),
|
|
313
|
+
...(providerOptions ? { providerOptions } : {}),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
return toError(err);
|
|
318
|
+
}
|
|
319
|
+
const videos = result.videos.map((v) => ({
|
|
320
|
+
uint8Array: v.uint8Array,
|
|
321
|
+
mediaType: v.mediaType,
|
|
322
|
+
}));
|
|
323
|
+
const cost = calculateCost(config.cost, {
|
|
324
|
+
videosGenerated: result.videos.length,
|
|
325
|
+
durationSeconds: opts.duration,
|
|
326
|
+
resolution: opts.resolution,
|
|
327
|
+
hasVideoInput: Boolean(opts.inputImage || opts.videoUrl || opts.referenceImages?.length),
|
|
328
|
+
}, result.videos.length);
|
|
329
|
+
return {
|
|
330
|
+
videos,
|
|
331
|
+
model,
|
|
332
|
+
cost,
|
|
333
|
+
warnings: result.warnings,
|
|
334
|
+
responses: result.responses,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
// ─── internal generation paths ───────────────────────────────────────────────
|
|
338
|
+
async function generateWithImageModel(opts) {
|
|
339
|
+
const imagePrompt = opts.inputImages.length > 0
|
|
340
|
+
? { text: opts.prompt, images: opts.inputImages, ...(opts.maskImage ? { mask: opts.maskImage } : {}) }
|
|
341
|
+
: opts.prompt;
|
|
342
|
+
const config = getModelConfig(opts.model);
|
|
343
|
+
if (config instanceof Error)
|
|
344
|
+
return config;
|
|
345
|
+
const imageModel = await createImageModel(opts.model);
|
|
346
|
+
if (imageModel instanceof Error)
|
|
347
|
+
return imageModel;
|
|
348
|
+
const providerOptions = buildImageProviderOptions(config.provider, {
|
|
349
|
+
aspectRatio: opts.aspectRatio,
|
|
350
|
+
allowPeople: opts.allowPeople,
|
|
351
|
+
quality: opts.quality,
|
|
352
|
+
resolution: opts.resolution,
|
|
353
|
+
outputFormat: opts.outputFormat,
|
|
354
|
+
negativePrompt: opts.negativePrompt,
|
|
355
|
+
});
|
|
356
|
+
let result;
|
|
357
|
+
try {
|
|
358
|
+
result = await aiGenerateImage({
|
|
359
|
+
model: imageModel,
|
|
360
|
+
prompt: imagePrompt,
|
|
361
|
+
n: opts.count,
|
|
362
|
+
...(opts.aspectRatio ? { aspectRatio: opts.aspectRatio } : {}),
|
|
363
|
+
...(opts.seed !== undefined ? { seed: opts.seed } : {}),
|
|
364
|
+
providerOptions,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
return toError(err);
|
|
369
|
+
}
|
|
370
|
+
const images = result.images.map((img) => ({
|
|
371
|
+
uint8Array: img.uint8Array,
|
|
372
|
+
mediaType: img.mediaType,
|
|
373
|
+
}));
|
|
374
|
+
const cost = calculateCost(config.cost, result.usage, result.images.length);
|
|
375
|
+
return {
|
|
376
|
+
images,
|
|
377
|
+
model: opts.model,
|
|
378
|
+
cost,
|
|
379
|
+
usage: result.usage,
|
|
380
|
+
warnings: result.warnings,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
async function generateWithTextModelPath(opts) {
|
|
384
|
+
const textModel = await createTextModel(opts.model);
|
|
385
|
+
if (textModel instanceof Error)
|
|
386
|
+
return textModel;
|
|
387
|
+
const config = getModelConfig(opts.model);
|
|
388
|
+
if (config instanceof Error)
|
|
389
|
+
return config;
|
|
390
|
+
const messages = opts.inputImages.length > 0
|
|
391
|
+
? [
|
|
392
|
+
{
|
|
393
|
+
role: 'user',
|
|
394
|
+
content: [
|
|
395
|
+
{ type: 'text', text: opts.prompt },
|
|
396
|
+
...opts.inputImages.map((img) => ({
|
|
397
|
+
type: 'image',
|
|
398
|
+
image: img,
|
|
399
|
+
})),
|
|
400
|
+
],
|
|
401
|
+
},
|
|
402
|
+
]
|
|
403
|
+
: undefined;
|
|
404
|
+
const googleOpts = {
|
|
405
|
+
responseModalities: ['TEXT', 'IMAGE'],
|
|
406
|
+
...(opts.imageSize || opts.aspectRatio
|
|
407
|
+
? {
|
|
408
|
+
imageConfig: {
|
|
409
|
+
...(opts.imageSize ? { imageSize: opts.imageSize } : {}),
|
|
410
|
+
...(opts.aspectRatio ? { aspectRatio: opts.aspectRatio } : {}),
|
|
411
|
+
},
|
|
412
|
+
}
|
|
413
|
+
: {}),
|
|
414
|
+
};
|
|
415
|
+
const providerOptionsKey = config.provider === 'vertex' ? 'vertex' : 'google';
|
|
416
|
+
let result;
|
|
417
|
+
try {
|
|
418
|
+
result = await generateText({
|
|
419
|
+
model: textModel,
|
|
420
|
+
...(messages ? { messages } : { prompt: opts.prompt }),
|
|
421
|
+
providerOptions: {
|
|
422
|
+
[providerOptionsKey]: googleOpts,
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
catch (err) {
|
|
427
|
+
return toError(err);
|
|
428
|
+
}
|
|
429
|
+
const imageFiles = result.files.filter((f) => f.mediaType.startsWith('image/'));
|
|
430
|
+
if (imageFiles.length === 0) {
|
|
431
|
+
return new Error('No images generated by the text model.');
|
|
432
|
+
}
|
|
433
|
+
const images = imageFiles.map((f) => ({
|
|
434
|
+
uint8Array: f.uint8Array,
|
|
435
|
+
mediaType: f.mediaType,
|
|
436
|
+
}));
|
|
437
|
+
const cost = calculateCost(config.cost, result.usage, imageFiles.length);
|
|
438
|
+
return {
|
|
439
|
+
images,
|
|
440
|
+
model: opts.model,
|
|
441
|
+
cost,
|
|
442
|
+
usage: result.usage,
|
|
443
|
+
text: result.text || undefined,
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
async function generateWithResponsesApi(opts) {
|
|
447
|
+
if (opts.count !== 1) {
|
|
448
|
+
return new ValidationError('ChatGPT image generation currently supports exactly one output image.');
|
|
449
|
+
}
|
|
450
|
+
if (opts.seed !== undefined) {
|
|
451
|
+
return new ValidationError('ChatGPT image generation does not support seed.');
|
|
452
|
+
}
|
|
453
|
+
if (opts.maskImage) {
|
|
454
|
+
return new ValidationError('ChatGPT image generation does not support mask yet.');
|
|
455
|
+
}
|
|
456
|
+
const size = opts.aspectRatio ? chatGptImageSizeFromAspectRatio(opts.aspectRatio) : undefined;
|
|
457
|
+
if (opts.aspectRatio && !size) {
|
|
458
|
+
return new ValidationError('ChatGPT image generation only supports aspect ratios 1:1, 3:2, or 2:3.');
|
|
459
|
+
}
|
|
460
|
+
const storedAuth = getChatGptAuth();
|
|
461
|
+
if (!storedAuth?.accountId) {
|
|
462
|
+
return new ValidationError('Missing ChatGPT account metadata. Please run `egaki login --provider chatgpt` again.');
|
|
463
|
+
}
|
|
464
|
+
const auth = await getValidChatGptAuth(storedAuth, saveChatGptAuth);
|
|
465
|
+
if (auth instanceof Error)
|
|
466
|
+
return auth;
|
|
467
|
+
const content = [
|
|
468
|
+
{ type: 'input_text', text: opts.prompt },
|
|
469
|
+
...opts.inputImages.map((image) => ({
|
|
470
|
+
type: 'input_image',
|
|
471
|
+
image_url: imageBytesToDataUrl(image),
|
|
472
|
+
})),
|
|
473
|
+
];
|
|
474
|
+
let response;
|
|
475
|
+
try {
|
|
476
|
+
response = await fetch('https://chatgpt.com/backend-api/codex/responses', {
|
|
477
|
+
method: 'POST',
|
|
478
|
+
headers: {
|
|
479
|
+
Authorization: `Bearer ${auth.access}`,
|
|
480
|
+
...(auth.accountId && { 'ChatGPT-Account-ID': auth.accountId }),
|
|
481
|
+
'Content-Type': 'application/json',
|
|
482
|
+
},
|
|
483
|
+
body: JSON.stringify({
|
|
484
|
+
model: 'gpt-5.4',
|
|
485
|
+
instructions: 'You are Codex.',
|
|
486
|
+
input: [
|
|
487
|
+
{
|
|
488
|
+
type: 'message',
|
|
489
|
+
role: 'user',
|
|
490
|
+
content,
|
|
491
|
+
},
|
|
492
|
+
],
|
|
493
|
+
tools: [
|
|
494
|
+
{
|
|
495
|
+
type: 'image_generation',
|
|
496
|
+
model: opts.model,
|
|
497
|
+
size: 'auto',
|
|
498
|
+
quality: 'auto',
|
|
499
|
+
output_format: 'png',
|
|
500
|
+
output_compression: 100,
|
|
501
|
+
moderation: 'auto',
|
|
502
|
+
...(size ? { size } : {}),
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
tool_choice: 'auto',
|
|
506
|
+
parallel_tool_calls: true,
|
|
507
|
+
stream: true,
|
|
508
|
+
store: false,
|
|
509
|
+
include: [],
|
|
510
|
+
}),
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
catch (err) {
|
|
514
|
+
return toError(err);
|
|
515
|
+
}
|
|
516
|
+
if (!response.ok || !response.body) {
|
|
517
|
+
const body = await response.text().catch(() => '');
|
|
518
|
+
return new Error(`ChatGPT image generation failed: ${response.status}${body ? ` ${body}` : ''}`);
|
|
519
|
+
}
|
|
520
|
+
let imageBase64;
|
|
521
|
+
let revisedPrompt = null;
|
|
522
|
+
const parser = createParser({
|
|
523
|
+
onEvent: (message) => {
|
|
524
|
+
if (!message.data)
|
|
525
|
+
return;
|
|
526
|
+
try {
|
|
527
|
+
const event = JSON.parse(message.data);
|
|
528
|
+
if (event.type === 'response.image_generation_call.partial_image' &&
|
|
529
|
+
event.partial_image_b64 &&
|
|
530
|
+
!imageBase64) {
|
|
531
|
+
imageBase64 = event.partial_image_b64;
|
|
532
|
+
}
|
|
533
|
+
if (event.type === 'response.output_item.done' &&
|
|
534
|
+
event.item?.type === 'image_generation_call') {
|
|
535
|
+
if (event.item.result)
|
|
536
|
+
imageBase64 = event.item.result;
|
|
537
|
+
revisedPrompt = event.item.revised_prompt ?? revisedPrompt;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
catch {
|
|
541
|
+
// Ignore keepalive and partial parse noise.
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
});
|
|
545
|
+
const decoder = new TextDecoder();
|
|
546
|
+
for await (const chunk of response.body) {
|
|
547
|
+
parser.feed(decoder.decode(chunk, { stream: true }));
|
|
548
|
+
}
|
|
549
|
+
parser.feed(decoder.decode());
|
|
550
|
+
if (!imageBase64) {
|
|
551
|
+
return new Error('No images generated by ChatGPT.');
|
|
552
|
+
}
|
|
553
|
+
const imageBytes = new Uint8Array(Buffer.from(imageBase64, 'base64'));
|
|
554
|
+
return {
|
|
555
|
+
images: [{ uint8Array: imageBytes, mediaType: 'image/png' }],
|
|
556
|
+
model: opts.model,
|
|
557
|
+
cost: null,
|
|
558
|
+
revisedPrompt,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
// ─── cached generateImage ───────────────────────────────────────────────────
|
|
562
|
+
import { cachedGenerate } from './cached-generate.js';
|
|
563
|
+
import { extensionFromMediaType } from './cache-utils.js';
|
|
564
|
+
export const generateImage = cachedGenerate({
|
|
565
|
+
namespace: 'image',
|
|
566
|
+
prefixFrom: (p) => p.prompt,
|
|
567
|
+
modelFrom: (p) => p.model,
|
|
568
|
+
generate: async (params) => {
|
|
569
|
+
const result = await generateImageUncached(params);
|
|
570
|
+
if (result instanceof Error)
|
|
571
|
+
throw result;
|
|
572
|
+
const file = result.images[0];
|
|
573
|
+
if (!file)
|
|
574
|
+
throw new Error('No image generated');
|
|
575
|
+
return file;
|
|
576
|
+
},
|
|
577
|
+
serialize: (file) => ({
|
|
578
|
+
bytes: file.uint8Array,
|
|
579
|
+
extension: extensionFromMediaType(file.mediaType),
|
|
580
|
+
}),
|
|
581
|
+
});
|
|
582
|
+
// ─── cached generateVideo ───────────────────────────────────────────────────
|
|
583
|
+
export const generateVideo = cachedGenerate({
|
|
584
|
+
namespace: 'video',
|
|
585
|
+
prefixFrom: (p) => p.prompt,
|
|
586
|
+
modelFrom: (p) => p.model,
|
|
587
|
+
generate: async (params) => {
|
|
588
|
+
const result = await generateVideoUncached(params);
|
|
589
|
+
if (result instanceof Error)
|
|
590
|
+
throw result;
|
|
591
|
+
const file = result.videos[0];
|
|
592
|
+
if (!file)
|
|
593
|
+
throw new Error('No video generated');
|
|
594
|
+
return file;
|
|
595
|
+
},
|
|
596
|
+
serialize: (file) => ({
|
|
597
|
+
bytes: file.uint8Array,
|
|
598
|
+
extension: extensionFromMediaType(file.mediaType),
|
|
599
|
+
}),
|
|
600
|
+
});
|
|
601
|
+
// ─── re-export speech generation ─────────────────────────────────────────────
|
|
602
|
+
export { generateSpeech, generateSpeechUncached, calculateSpeechCost, } from './speech-generate.js';
|
|
603
|
+
// ─── re-export transcription ─────────────────────────────────────────────────
|
|
604
|
+
export { transcribeAudio, transcribeAudioUncached, calculateTranscriptionCost, segmentsToWordTimestamps, wordTimestampsToCaptions, } from './transcription-generate.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.test.d.ts","sourceRoot":"","sources":["../../src/cli/generate.test.ts"],"names":[],"mappings":""}
|