@vibeframe/cli 0.27.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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-lint.log +21 -0
- package/.turbo/turbo-test.log +689 -0
- package/dist/agent/adapters/claude.d.ts +15 -0
- package/dist/agent/adapters/claude.d.ts.map +1 -0
- package/dist/agent/adapters/claude.js +119 -0
- package/dist/agent/adapters/claude.js.map +1 -0
- package/dist/agent/adapters/gemini.d.ts +15 -0
- package/dist/agent/adapters/gemini.d.ts.map +1 -0
- package/dist/agent/adapters/gemini.js +132 -0
- package/dist/agent/adapters/gemini.js.map +1 -0
- package/dist/agent/adapters/index.d.ts +27 -0
- package/dist/agent/adapters/index.d.ts.map +1 -0
- package/dist/agent/adapters/index.js +38 -0
- package/dist/agent/adapters/index.js.map +1 -0
- package/dist/agent/adapters/ollama.d.ts +20 -0
- package/dist/agent/adapters/ollama.d.ts.map +1 -0
- package/dist/agent/adapters/ollama.js +186 -0
- package/dist/agent/adapters/ollama.js.map +1 -0
- package/dist/agent/adapters/openai.d.ts +15 -0
- package/dist/agent/adapters/openai.d.ts.map +1 -0
- package/dist/agent/adapters/openai.js +92 -0
- package/dist/agent/adapters/openai.js.map +1 -0
- package/dist/agent/adapters/xai.d.ts +15 -0
- package/dist/agent/adapters/xai.d.ts.map +1 -0
- package/dist/agent/adapters/xai.js +95 -0
- package/dist/agent/adapters/xai.js.map +1 -0
- package/dist/agent/index.d.ts +69 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +180 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/memory/index.d.ts +70 -0
- package/dist/agent/memory/index.d.ts.map +1 -0
- package/dist/agent/memory/index.js +132 -0
- package/dist/agent/memory/index.js.map +1 -0
- package/dist/agent/prompts/system.d.ts +6 -0
- package/dist/agent/prompts/system.d.ts.map +1 -0
- package/dist/agent/prompts/system.js +103 -0
- package/dist/agent/prompts/system.js.map +1 -0
- package/dist/agent/tools/ai-editing.d.ts +15 -0
- package/dist/agent/tools/ai-editing.d.ts.map +1 -0
- package/dist/agent/tools/ai-editing.js +763 -0
- package/dist/agent/tools/ai-editing.js.map +1 -0
- package/dist/agent/tools/ai-generation.d.ts +13 -0
- package/dist/agent/tools/ai-generation.d.ts.map +1 -0
- package/dist/agent/tools/ai-generation.js +973 -0
- package/dist/agent/tools/ai-generation.js.map +1 -0
- package/dist/agent/tools/ai-pipeline.d.ts +14 -0
- package/dist/agent/tools/ai-pipeline.d.ts.map +1 -0
- package/dist/agent/tools/ai-pipeline.js +961 -0
- package/dist/agent/tools/ai-pipeline.js.map +1 -0
- package/dist/agent/tools/ai.d.ts +13 -0
- package/dist/agent/tools/ai.d.ts.map +1 -0
- package/dist/agent/tools/ai.js +19 -0
- package/dist/agent/tools/ai.js.map +1 -0
- package/dist/agent/tools/batch.d.ts +6 -0
- package/dist/agent/tools/batch.d.ts.map +1 -0
- package/dist/agent/tools/batch.js +383 -0
- package/dist/agent/tools/batch.js.map +1 -0
- package/dist/agent/tools/e2e.test.d.ts +26 -0
- package/dist/agent/tools/e2e.test.d.ts.map +1 -0
- package/dist/agent/tools/e2e.test.js +397 -0
- package/dist/agent/tools/e2e.test.js.map +1 -0
- package/dist/agent/tools/export.d.ts +6 -0
- package/dist/agent/tools/export.d.ts.map +1 -0
- package/dist/agent/tools/export.js +171 -0
- package/dist/agent/tools/export.js.map +1 -0
- package/dist/agent/tools/filesystem.d.ts +6 -0
- package/dist/agent/tools/filesystem.d.ts.map +1 -0
- package/dist/agent/tools/filesystem.js +212 -0
- package/dist/agent/tools/filesystem.js.map +1 -0
- package/dist/agent/tools/index.d.ts +65 -0
- package/dist/agent/tools/index.d.ts.map +1 -0
- package/dist/agent/tools/index.js +120 -0
- package/dist/agent/tools/index.js.map +1 -0
- package/dist/agent/tools/integration.test.d.ts +11 -0
- package/dist/agent/tools/integration.test.d.ts.map +1 -0
- package/dist/agent/tools/integration.test.js +659 -0
- package/dist/agent/tools/integration.test.js.map +1 -0
- package/dist/agent/tools/media.d.ts +6 -0
- package/dist/agent/tools/media.d.ts.map +1 -0
- package/dist/agent/tools/media.js +616 -0
- package/dist/agent/tools/media.js.map +1 -0
- package/dist/agent/tools/project.d.ts +6 -0
- package/dist/agent/tools/project.d.ts.map +1 -0
- package/dist/agent/tools/project.js +284 -0
- package/dist/agent/tools/project.js.map +1 -0
- package/dist/agent/tools/timeline.d.ts +6 -0
- package/dist/agent/tools/timeline.d.ts.map +1 -0
- package/dist/agent/tools/timeline.js +873 -0
- package/dist/agent/tools/timeline.js.map +1 -0
- package/dist/agent/types.d.ts +59 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/commands/agent.d.ts +21 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +290 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/ai-analyze.d.ts +106 -0
- package/dist/commands/ai-analyze.d.ts.map +1 -0
- package/dist/commands/ai-analyze.js +327 -0
- package/dist/commands/ai-analyze.js.map +1 -0
- package/dist/commands/ai-animated-caption.d.ts +64 -0
- package/dist/commands/ai-animated-caption.d.ts.map +1 -0
- package/dist/commands/ai-animated-caption.js +272 -0
- package/dist/commands/ai-animated-caption.js.map +1 -0
- package/dist/commands/ai-audio.d.ts +20 -0
- package/dist/commands/ai-audio.d.ts.map +1 -0
- package/dist/commands/ai-audio.js +808 -0
- package/dist/commands/ai-audio.js.map +1 -0
- package/dist/commands/ai-broll.d.ts +15 -0
- package/dist/commands/ai-broll.d.ts.map +1 -0
- package/dist/commands/ai-broll.js +406 -0
- package/dist/commands/ai-broll.js.map +1 -0
- package/dist/commands/ai-edit-cli.d.ts +14 -0
- package/dist/commands/ai-edit-cli.d.ts.map +1 -0
- package/dist/commands/ai-edit-cli.js +579 -0
- package/dist/commands/ai-edit-cli.js.map +1 -0
- package/dist/commands/ai-edit.d.ts +398 -0
- package/dist/commands/ai-edit.d.ts.map +1 -0
- package/dist/commands/ai-edit.js +1019 -0
- package/dist/commands/ai-edit.js.map +1 -0
- package/dist/commands/ai-fill-gaps.d.ts +14 -0
- package/dist/commands/ai-fill-gaps.d.ts.map +1 -0
- package/dist/commands/ai-fill-gaps.js +451 -0
- package/dist/commands/ai-fill-gaps.js.map +1 -0
- package/dist/commands/ai-helpers.d.ts +20 -0
- package/dist/commands/ai-helpers.d.ts.map +1 -0
- package/dist/commands/ai-helpers.js +59 -0
- package/dist/commands/ai-helpers.js.map +1 -0
- package/dist/commands/ai-highlights.d.ts +127 -0
- package/dist/commands/ai-highlights.d.ts.map +1 -0
- package/dist/commands/ai-highlights.js +1026 -0
- package/dist/commands/ai-highlights.js.map +1 -0
- package/dist/commands/ai-image.d.ts +34 -0
- package/dist/commands/ai-image.d.ts.map +1 -0
- package/dist/commands/ai-image.js +653 -0
- package/dist/commands/ai-image.js.map +1 -0
- package/dist/commands/ai-motion.d.ts +50 -0
- package/dist/commands/ai-motion.d.ts.map +1 -0
- package/dist/commands/ai-motion.js +271 -0
- package/dist/commands/ai-motion.js.map +1 -0
- package/dist/commands/ai-narrate.d.ts +66 -0
- package/dist/commands/ai-narrate.d.ts.map +1 -0
- package/dist/commands/ai-narrate.js +329 -0
- package/dist/commands/ai-narrate.js.map +1 -0
- package/dist/commands/ai-review.d.ts +57 -0
- package/dist/commands/ai-review.d.ts.map +1 -0
- package/dist/commands/ai-review.js +251 -0
- package/dist/commands/ai-review.js.map +1 -0
- package/dist/commands/ai-script-pipeline-cli.d.ts +9 -0
- package/dist/commands/ai-script-pipeline-cli.d.ts.map +1 -0
- package/dist/commands/ai-script-pipeline-cli.js +1494 -0
- package/dist/commands/ai-script-pipeline-cli.js.map +1 -0
- package/dist/commands/ai-script-pipeline.d.ts +259 -0
- package/dist/commands/ai-script-pipeline.d.ts.map +1 -0
- package/dist/commands/ai-script-pipeline.js +1027 -0
- package/dist/commands/ai-script-pipeline.js.map +1 -0
- package/dist/commands/ai-suggest-edit.d.ts +14 -0
- package/dist/commands/ai-suggest-edit.d.ts.map +1 -0
- package/dist/commands/ai-suggest-edit.js +220 -0
- package/dist/commands/ai-suggest-edit.js.map +1 -0
- package/dist/commands/ai-video-fx.d.ts +14 -0
- package/dist/commands/ai-video-fx.d.ts.map +1 -0
- package/dist/commands/ai-video-fx.js +395 -0
- package/dist/commands/ai-video-fx.js.map +1 -0
- package/dist/commands/ai-video.d.ts +15 -0
- package/dist/commands/ai-video.d.ts.map +1 -0
- package/dist/commands/ai-video.js +785 -0
- package/dist/commands/ai-video.js.map +1 -0
- package/dist/commands/ai-viral.d.ts +15 -0
- package/dist/commands/ai-viral.d.ts.map +1 -0
- package/dist/commands/ai-viral.js +519 -0
- package/dist/commands/ai-viral.js.map +1 -0
- package/dist/commands/ai-visual-fx.d.ts +14 -0
- package/dist/commands/ai-visual-fx.d.ts.map +1 -0
- package/dist/commands/ai-visual-fx.js +505 -0
- package/dist/commands/ai-visual-fx.js.map +1 -0
- package/dist/commands/ai.d.ts +38 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +225 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/ai.test.d.ts +2 -0
- package/dist/commands/ai.test.d.ts.map +1 -0
- package/dist/commands/ai.test.js +554 -0
- package/dist/commands/ai.test.js.map +1 -0
- package/dist/commands/analyze.d.ts +16 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +247 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/audio.d.ts +18 -0
- package/dist/commands/audio.d.ts.map +1 -0
- package/dist/commands/audio.js +539 -0
- package/dist/commands/audio.js.map +1 -0
- package/dist/commands/batch.d.ts +3 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +366 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/batch.test.d.ts +2 -0
- package/dist/commands/batch.test.d.ts.map +1 -0
- package/dist/commands/batch.test.js +203 -0
- package/dist/commands/batch.test.js.map +1 -0
- package/dist/commands/detect.d.ts +3 -0
- package/dist/commands/detect.d.ts.map +1 -0
- package/dist/commands/detect.js +273 -0
- package/dist/commands/detect.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +191 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/edit-cmd.d.ts +26 -0
- package/dist/commands/edit-cmd.d.ts.map +1 -0
- package/dist/commands/edit-cmd.js +870 -0
- package/dist/commands/edit-cmd.js.map +1 -0
- package/dist/commands/export.d.ts +39 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +730 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/generate.d.ts +25 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +1885 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/media.d.ts +3 -0
- package/dist/commands/media.d.ts.map +1 -0
- package/dist/commands/media.js +165 -0
- package/dist/commands/media.js.map +1 -0
- package/dist/commands/output.d.ts +45 -0
- package/dist/commands/output.d.ts.map +1 -0
- package/dist/commands/output.js +122 -0
- package/dist/commands/output.js.map +1 -0
- package/dist/commands/pipeline.d.ts +19 -0
- package/dist/commands/pipeline.d.ts.map +1 -0
- package/dist/commands/pipeline.js +345 -0
- package/dist/commands/pipeline.js.map +1 -0
- package/dist/commands/project.d.ts +3 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +139 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/project.test.d.ts +2 -0
- package/dist/commands/project.test.d.ts.map +1 -0
- package/dist/commands/project.test.js +105 -0
- package/dist/commands/project.test.js.map +1 -0
- package/dist/commands/sanitize.d.ts +21 -0
- package/dist/commands/sanitize.d.ts.map +1 -0
- package/dist/commands/sanitize.js +56 -0
- package/dist/commands/sanitize.js.map +1 -0
- package/dist/commands/schema.d.ts +11 -0
- package/dist/commands/schema.d.ts.map +1 -0
- package/dist/commands/schema.js +101 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +440 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/timeline.d.ts +3 -0
- package/dist/commands/timeline.d.ts.map +1 -0
- package/dist/commands/timeline.js +469 -0
- package/dist/commands/timeline.js.map +1 -0
- package/dist/commands/timeline.test.d.ts +2 -0
- package/dist/commands/timeline.test.d.ts.map +1 -0
- package/dist/commands/timeline.test.js +320 -0
- package/dist/commands/timeline.test.js.map +1 -0
- package/dist/commands/validate.d.ts +32 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +63 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config/config.test.d.ts +2 -0
- package/dist/config/config.test.d.ts.map +1 -0
- package/dist/config/config.test.js +164 -0
- package/dist/config/config.test.js.map +1 -0
- package/dist/config/index.d.ts +35 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +101 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +43 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +42 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/engine/index.d.ts +3 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +2 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/project.d.ts +84 -0
- package/dist/engine/project.d.ts.map +1 -0
- package/dist/engine/project.js +355 -0
- package/dist/engine/project.js.map +1 -0
- package/dist/engine/project.test.d.ts +2 -0
- package/dist/engine/project.test.d.ts.map +1 -0
- package/dist/engine/project.test.js +599 -0
- package/dist/engine/project.test.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +131 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/api-key.d.ts +36 -0
- package/dist/utils/api-key.d.ts.map +1 -0
- package/dist/utils/api-key.js +211 -0
- package/dist/utils/api-key.js.map +1 -0
- package/dist/utils/api-key.test.d.ts +2 -0
- package/dist/utils/api-key.test.d.ts.map +1 -0
- package/dist/utils/api-key.test.js +35 -0
- package/dist/utils/api-key.test.js.map +1 -0
- package/dist/utils/audio.d.ts +23 -0
- package/dist/utils/audio.d.ts.map +1 -0
- package/dist/utils/audio.js +79 -0
- package/dist/utils/audio.js.map +1 -0
- package/dist/utils/exec-safe.d.ts +22 -0
- package/dist/utils/exec-safe.d.ts.map +1 -0
- package/dist/utils/exec-safe.js +62 -0
- package/dist/utils/exec-safe.js.map +1 -0
- package/dist/utils/first-run.d.ts +13 -0
- package/dist/utils/first-run.d.ts.map +1 -0
- package/dist/utils/first-run.js +48 -0
- package/dist/utils/first-run.js.map +1 -0
- package/dist/utils/provider-resolver.d.ts +15 -0
- package/dist/utils/provider-resolver.d.ts.map +1 -0
- package/dist/utils/provider-resolver.js +42 -0
- package/dist/utils/provider-resolver.js.map +1 -0
- package/dist/utils/remotion.d.ts +210 -0
- package/dist/utils/remotion.d.ts.map +1 -0
- package/dist/utils/remotion.js +731 -0
- package/dist/utils/remotion.js.map +1 -0
- package/dist/utils/subtitle.d.ts +65 -0
- package/dist/utils/subtitle.d.ts.map +1 -0
- package/dist/utils/subtitle.js +135 -0
- package/dist/utils/subtitle.js.map +1 -0
- package/dist/utils/subtitle.test.d.ts +2 -0
- package/dist/utils/subtitle.test.d.ts.map +1 -0
- package/dist/utils/subtitle.test.js +175 -0
- package/dist/utils/subtitle.test.js.map +1 -0
- package/dist/utils/tty.d.ts +45 -0
- package/dist/utils/tty.d.ts.map +1 -0
- package/dist/utils/tty.js +172 -0
- package/dist/utils/tty.js.map +1 -0
- package/package.json +102 -0
- package/src/agent/adapters/claude.ts +143 -0
- package/src/agent/adapters/gemini.ts +159 -0
- package/src/agent/adapters/index.ts +61 -0
- package/src/agent/adapters/ollama.ts +231 -0
- package/src/agent/adapters/openai.ts +116 -0
- package/src/agent/adapters/xai.ts +119 -0
- package/src/agent/index.ts +251 -0
- package/src/agent/memory/index.ts +151 -0
- package/src/agent/prompts/system.ts +106 -0
- package/src/agent/tools/ai-editing.ts +845 -0
- package/src/agent/tools/ai-generation.ts +1073 -0
- package/src/agent/tools/ai-pipeline.ts +1055 -0
- package/src/agent/tools/ai.ts +21 -0
- package/src/agent/tools/batch.ts +429 -0
- package/src/agent/tools/e2e.test.ts +545 -0
- package/src/agent/tools/export.ts +184 -0
- package/src/agent/tools/filesystem.ts +237 -0
- package/src/agent/tools/index.ts +150 -0
- package/src/agent/tools/integration.test.ts +775 -0
- package/src/agent/tools/media.ts +697 -0
- package/src/agent/tools/project.ts +313 -0
- package/src/agent/tools/timeline.ts +951 -0
- package/src/agent/types.ts +68 -0
- package/src/commands/agent.ts +340 -0
- package/src/commands/ai-analyze.ts +429 -0
- package/src/commands/ai-animated-caption.ts +390 -0
- package/src/commands/ai-audio.ts +941 -0
- package/src/commands/ai-broll.ts +490 -0
- package/src/commands/ai-edit-cli.ts +658 -0
- package/src/commands/ai-edit.ts +1542 -0
- package/src/commands/ai-fill-gaps.ts +566 -0
- package/src/commands/ai-helpers.ts +65 -0
- package/src/commands/ai-highlights.ts +1303 -0
- package/src/commands/ai-image.ts +761 -0
- package/src/commands/ai-motion.ts +347 -0
- package/src/commands/ai-narrate.ts +451 -0
- package/src/commands/ai-review.ts +309 -0
- package/src/commands/ai-script-pipeline-cli.ts +1710 -0
- package/src/commands/ai-script-pipeline.ts +1365 -0
- package/src/commands/ai-suggest-edit.ts +264 -0
- package/src/commands/ai-video-fx.ts +445 -0
- package/src/commands/ai-video.ts +915 -0
- package/src/commands/ai-viral.ts +595 -0
- package/src/commands/ai-visual-fx.ts +601 -0
- package/src/commands/ai.test.ts +627 -0
- package/src/commands/ai.ts +307 -0
- package/src/commands/analyze.ts +282 -0
- package/src/commands/audio.ts +644 -0
- package/src/commands/batch.test.ts +279 -0
- package/src/commands/batch.ts +440 -0
- package/src/commands/detect.ts +329 -0
- package/src/commands/doctor.ts +237 -0
- package/src/commands/edit-cmd.ts +1014 -0
- package/src/commands/export.ts +918 -0
- package/src/commands/generate.ts +2146 -0
- package/src/commands/media.ts +177 -0
- package/src/commands/output.ts +142 -0
- package/src/commands/pipeline.ts +398 -0
- package/src/commands/project.test.ts +127 -0
- package/src/commands/project.ts +149 -0
- package/src/commands/sanitize.ts +60 -0
- package/src/commands/schema.ts +130 -0
- package/src/commands/setup.ts +509 -0
- package/src/commands/timeline.test.ts +499 -0
- package/src/commands/timeline.ts +529 -0
- package/src/commands/validate.ts +77 -0
- package/src/config/config.test.ts +197 -0
- package/src/config/index.ts +125 -0
- package/src/config/schema.ts +82 -0
- package/src/engine/index.ts +2 -0
- package/src/engine/project.test.ts +702 -0
- package/src/engine/project.ts +439 -0
- package/src/index.ts +146 -0
- package/src/utils/api-key.test.ts +41 -0
- package/src/utils/api-key.ts +247 -0
- package/src/utils/audio.ts +83 -0
- package/src/utils/exec-safe.ts +75 -0
- package/src/utils/first-run.ts +52 -0
- package/src/utils/provider-resolver.ts +56 -0
- package/src/utils/remotion.ts +951 -0
- package/src/utils/subtitle.test.ts +227 -0
- package/src/utils/subtitle.ts +169 -0
- package/src/utils/tty.ts +196 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,973 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module ai-generation
|
|
3
|
+
* @description Agent tools for AI asset generation (image, video, TTS, SFX, music,
|
|
4
|
+
* storyboard, motion). Wraps providers for agent use. Some features require
|
|
5
|
+
* async polling -- tool returns immediately with task status.
|
|
6
|
+
*
|
|
7
|
+
* ## Tools: generate_image, generate_video, generate_speech, generate_sound_effect, generate_music, generate_storyboard, generate_motion
|
|
8
|
+
* ## Dependencies: OpenAI, Gemini, Runway, Kling, ElevenLabs (TTS/SFX/Music), Replicate, Claude, Remotion
|
|
9
|
+
* @see MODELS.md for the Single Source of Truth (SSOT) on supported providers/models
|
|
10
|
+
*/
|
|
11
|
+
import { writeFile, readFile } from "node:fs/promises";
|
|
12
|
+
import { resolve } from "node:path";
|
|
13
|
+
import { getApiKeyFromConfig } from "../../config/index.js";
|
|
14
|
+
import { downloadVideo } from "../../commands/ai-helpers.js";
|
|
15
|
+
import { sanitizeAIResult } from "../../commands/sanitize.js";
|
|
16
|
+
// Helper to get timestamp for filenames
|
|
17
|
+
function getTimestamp() {
|
|
18
|
+
return Date.now().toString();
|
|
19
|
+
}
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Tool Definitions
|
|
22
|
+
// ============================================================================
|
|
23
|
+
const imageDef = {
|
|
24
|
+
name: "generate_image",
|
|
25
|
+
description: "Generate an image using AI (OpenAI GPT Image 1.5, Gemini, or xAI Grok)",
|
|
26
|
+
parameters: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
prompt: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Image generation prompt",
|
|
32
|
+
},
|
|
33
|
+
output: {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "Output file path (default: generated-{timestamp}.png)",
|
|
36
|
+
},
|
|
37
|
+
provider: {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "Provider to use: openai (GPT Image 1.5), gemini (Nano Banana), grok (Grok Imagine). 'dalle' is deprecated, use 'openai' instead.",
|
|
40
|
+
enum: ["openai", "dalle", "gemini", "grok"],
|
|
41
|
+
},
|
|
42
|
+
size: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "Image size (1024x1024, 1536x1024, 1024x1536)",
|
|
45
|
+
enum: ["1024x1024", "1536x1024", "1024x1536"],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
required: ["prompt"],
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
const videoDef = {
|
|
52
|
+
name: "generate_video",
|
|
53
|
+
description: "Generate video using AI. Supports Grok Imagine (default, native audio), Runway Gen-4.5 (text/image-to-video) and gen4_turbo (image-to-video), Kling (text/image-to-video), and Veo (text/image-to-video) via provider selection.",
|
|
54
|
+
parameters: {
|
|
55
|
+
type: "object",
|
|
56
|
+
properties: {
|
|
57
|
+
prompt: {
|
|
58
|
+
type: "string",
|
|
59
|
+
description: "Video generation prompt describing the motion/animation",
|
|
60
|
+
},
|
|
61
|
+
provider: {
|
|
62
|
+
type: "string",
|
|
63
|
+
description: "Video provider to use (default: grok)",
|
|
64
|
+
enum: ["grok", "runway", "kling", "veo"],
|
|
65
|
+
},
|
|
66
|
+
image: {
|
|
67
|
+
type: "string",
|
|
68
|
+
description: "Input image path. Required for runway gen4_turbo, optional for runway gen4.5/kling/veo.",
|
|
69
|
+
},
|
|
70
|
+
runwayModel: {
|
|
71
|
+
type: "string",
|
|
72
|
+
description: "Runway model: gen4.5 (default, text+image-to-video) or gen4_turbo (image-to-video only)",
|
|
73
|
+
enum: ["gen4.5", "gen4_turbo"],
|
|
74
|
+
},
|
|
75
|
+
output: {
|
|
76
|
+
type: "string",
|
|
77
|
+
description: "Output file path",
|
|
78
|
+
},
|
|
79
|
+
duration: {
|
|
80
|
+
type: "number",
|
|
81
|
+
description: "Video duration in seconds",
|
|
82
|
+
},
|
|
83
|
+
mode: {
|
|
84
|
+
type: "string",
|
|
85
|
+
description: "Quality mode for Kling (std or pro)",
|
|
86
|
+
enum: ["std", "pro"],
|
|
87
|
+
},
|
|
88
|
+
negativePrompt: {
|
|
89
|
+
type: "string",
|
|
90
|
+
description: "What to avoid in the generated video (Veo only)",
|
|
91
|
+
},
|
|
92
|
+
resolution: {
|
|
93
|
+
type: "string",
|
|
94
|
+
description: "Video resolution (Veo only)",
|
|
95
|
+
enum: ["720p", "1080p", "4k"],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
required: ["prompt"],
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
const ttsDef = {
|
|
102
|
+
name: "generate_speech",
|
|
103
|
+
description: "Generate speech from text using ElevenLabs",
|
|
104
|
+
parameters: {
|
|
105
|
+
type: "object",
|
|
106
|
+
properties: {
|
|
107
|
+
text: {
|
|
108
|
+
type: "string",
|
|
109
|
+
description: "Text to convert to speech",
|
|
110
|
+
},
|
|
111
|
+
output: {
|
|
112
|
+
type: "string",
|
|
113
|
+
description: "Output audio file path",
|
|
114
|
+
},
|
|
115
|
+
voice: {
|
|
116
|
+
type: "string",
|
|
117
|
+
description: "Voice ID or name",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
required: ["text"],
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
const sfxDef = {
|
|
124
|
+
name: "generate_sound_effect",
|
|
125
|
+
description: "Generate sound effects using ElevenLabs",
|
|
126
|
+
parameters: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
prompt: {
|
|
130
|
+
type: "string",
|
|
131
|
+
description: "Sound effect description",
|
|
132
|
+
},
|
|
133
|
+
output: {
|
|
134
|
+
type: "string",
|
|
135
|
+
description: "Output audio file path",
|
|
136
|
+
},
|
|
137
|
+
duration: {
|
|
138
|
+
type: "number",
|
|
139
|
+
description: "Duration in seconds",
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
required: ["prompt"],
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
const musicDef = {
|
|
146
|
+
name: "generate_music",
|
|
147
|
+
description: "Generate music using AI. Default: ElevenLabs (synchronous, up to 10min). Alternative: Replicate/MusicGen (async, max 30s).",
|
|
148
|
+
parameters: {
|
|
149
|
+
type: "object",
|
|
150
|
+
properties: {
|
|
151
|
+
prompt: {
|
|
152
|
+
type: "string",
|
|
153
|
+
description: "Music description/prompt",
|
|
154
|
+
},
|
|
155
|
+
output: {
|
|
156
|
+
type: "string",
|
|
157
|
+
description: "Output audio file path",
|
|
158
|
+
},
|
|
159
|
+
duration: {
|
|
160
|
+
type: "number",
|
|
161
|
+
description: "Duration in seconds (elevenlabs: 3-600, replicate: 1-30)",
|
|
162
|
+
},
|
|
163
|
+
provider: {
|
|
164
|
+
type: "string",
|
|
165
|
+
description: "Provider: elevenlabs (default, synchronous, up to 10min) or replicate (async, max 30s)",
|
|
166
|
+
enum: ["elevenlabs", "replicate"],
|
|
167
|
+
},
|
|
168
|
+
instrumental: {
|
|
169
|
+
type: "boolean",
|
|
170
|
+
description: "Force instrumental music with no vocals (ElevenLabs only)",
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
required: ["prompt"],
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
const storyboardDef = {
|
|
177
|
+
name: "generate_storyboard",
|
|
178
|
+
description: "Generate a storyboard from a script using Claude",
|
|
179
|
+
parameters: {
|
|
180
|
+
type: "object",
|
|
181
|
+
properties: {
|
|
182
|
+
script: {
|
|
183
|
+
type: "string",
|
|
184
|
+
description: "Video script or concept",
|
|
185
|
+
},
|
|
186
|
+
targetDuration: {
|
|
187
|
+
type: "number",
|
|
188
|
+
description: "Target video duration in seconds",
|
|
189
|
+
},
|
|
190
|
+
output: {
|
|
191
|
+
type: "string",
|
|
192
|
+
description: "Output JSON file path",
|
|
193
|
+
},
|
|
194
|
+
creativity: {
|
|
195
|
+
type: "string",
|
|
196
|
+
description: "Creativity level: 'low' (default, consistent scenes) or 'high' (varied, unexpected scenes)",
|
|
197
|
+
enum: ["low", "high"],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
required: ["script"],
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
const motionDef = {
|
|
204
|
+
name: "generate_motion",
|
|
205
|
+
description: "Generate motion graphics using Claude + Remotion. Can render to video and composite onto existing footage. " +
|
|
206
|
+
"Without --video: generates and renders a standalone motion graphic. With --video: renders and composites onto the base video.",
|
|
207
|
+
parameters: {
|
|
208
|
+
type: "object",
|
|
209
|
+
properties: {
|
|
210
|
+
description: {
|
|
211
|
+
type: "string",
|
|
212
|
+
description: "Natural language description of the motion graphic (e.g., 'cinematic title card with fade-in')",
|
|
213
|
+
},
|
|
214
|
+
video: {
|
|
215
|
+
type: "string",
|
|
216
|
+
description: "Base video path to composite the motion graphic onto (triggers render + composite)",
|
|
217
|
+
},
|
|
218
|
+
output: {
|
|
219
|
+
type: "string",
|
|
220
|
+
description: "Output file path (.mp4 if compositing, .webm if render-only, .tsx if code-only)",
|
|
221
|
+
},
|
|
222
|
+
duration: {
|
|
223
|
+
type: "number",
|
|
224
|
+
description: "Duration in seconds (default: 5)",
|
|
225
|
+
},
|
|
226
|
+
width: {
|
|
227
|
+
type: "number",
|
|
228
|
+
description: "Width in pixels (default: 1920)",
|
|
229
|
+
},
|
|
230
|
+
height: {
|
|
231
|
+
type: "number",
|
|
232
|
+
description: "Height in pixels (default: 1080)",
|
|
233
|
+
},
|
|
234
|
+
style: {
|
|
235
|
+
type: "string",
|
|
236
|
+
description: "Style preset",
|
|
237
|
+
enum: ["minimal", "corporate", "playful", "cinematic"],
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
required: ["description"],
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
// ============================================================================
|
|
244
|
+
// Tool Handlers
|
|
245
|
+
// ============================================================================
|
|
246
|
+
const generateImage = async (args, context) => {
|
|
247
|
+
const prompt = args.prompt;
|
|
248
|
+
const provider = args.provider || "gemini";
|
|
249
|
+
const output = args.output || `generated-${getTimestamp()}.png`;
|
|
250
|
+
const size = args.size || "1024x1024";
|
|
251
|
+
try {
|
|
252
|
+
let providerKey;
|
|
253
|
+
switch (provider) {
|
|
254
|
+
case "gemini":
|
|
255
|
+
providerKey = "google";
|
|
256
|
+
break;
|
|
257
|
+
case "openai":
|
|
258
|
+
case "dalle": // backward compatibility
|
|
259
|
+
providerKey = "openai";
|
|
260
|
+
break;
|
|
261
|
+
case "grok":
|
|
262
|
+
providerKey = "xai";
|
|
263
|
+
break;
|
|
264
|
+
default:
|
|
265
|
+
providerKey = "openai";
|
|
266
|
+
}
|
|
267
|
+
const apiKey = await getApiKeyFromConfig(providerKey);
|
|
268
|
+
if (!apiKey) {
|
|
269
|
+
return {
|
|
270
|
+
toolCallId: "",
|
|
271
|
+
success: false,
|
|
272
|
+
output: "",
|
|
273
|
+
error: `API key required for ${provider}. Configure via 'vibe setup'.`,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
277
|
+
if (provider === "dalle" || provider === "openai") {
|
|
278
|
+
const { OpenAIImageProvider } = await import("@vibeframe/ai-providers");
|
|
279
|
+
const openaiImage = new OpenAIImageProvider();
|
|
280
|
+
await openaiImage.initialize({ apiKey });
|
|
281
|
+
const result = await openaiImage.generateImage(prompt, {
|
|
282
|
+
size: size,
|
|
283
|
+
});
|
|
284
|
+
if (!result.success || !result.images || result.images.length === 0) {
|
|
285
|
+
return {
|
|
286
|
+
toolCallId: "",
|
|
287
|
+
success: false,
|
|
288
|
+
output: "",
|
|
289
|
+
error: `Image generation failed: ${result.error || "No image generated"}`,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
// Save image (handle both URL and base64)
|
|
293
|
+
const image = result.images[0];
|
|
294
|
+
let buffer;
|
|
295
|
+
if (image.url) {
|
|
296
|
+
const response = await fetch(image.url);
|
|
297
|
+
buffer = Buffer.from(await response.arrayBuffer());
|
|
298
|
+
}
|
|
299
|
+
else if (image.base64) {
|
|
300
|
+
buffer = Buffer.from(image.base64, "base64");
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
return {
|
|
304
|
+
toolCallId: "",
|
|
305
|
+
success: false,
|
|
306
|
+
output: "",
|
|
307
|
+
error: "Image generated but no URL or base64 data returned",
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
await writeFile(outputPath, buffer);
|
|
311
|
+
}
|
|
312
|
+
else if (provider === "gemini") {
|
|
313
|
+
const { GeminiProvider } = await import("@vibeframe/ai-providers");
|
|
314
|
+
const gemini = new GeminiProvider();
|
|
315
|
+
await gemini.initialize({ apiKey });
|
|
316
|
+
const result = await gemini.generateImage(prompt);
|
|
317
|
+
if (!result.success || !result.images || result.images.length === 0) {
|
|
318
|
+
return {
|
|
319
|
+
toolCallId: "",
|
|
320
|
+
success: false,
|
|
321
|
+
output: "",
|
|
322
|
+
error: `Image generation failed: ${result.error || "No image generated"}`,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
// Gemini returns base64
|
|
326
|
+
const image = result.images[0];
|
|
327
|
+
if (image.base64) {
|
|
328
|
+
const buffer = Buffer.from(image.base64, "base64");
|
|
329
|
+
await writeFile(outputPath, buffer);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else if (provider === "grok") {
|
|
333
|
+
const { GrokProvider } = await import("@vibeframe/ai-providers");
|
|
334
|
+
const grok = new GrokProvider();
|
|
335
|
+
await grok.initialize({ apiKey });
|
|
336
|
+
const result = await grok.generateImage(prompt);
|
|
337
|
+
if (!result.success || !result.images || result.images.length === 0) {
|
|
338
|
+
return {
|
|
339
|
+
toolCallId: "",
|
|
340
|
+
success: false,
|
|
341
|
+
output: "",
|
|
342
|
+
error: `Image generation failed: ${result.error || "No image generated"}`,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
// Grok returns URLs
|
|
346
|
+
const image = result.images[0];
|
|
347
|
+
if (image.url) {
|
|
348
|
+
const response = await fetch(image.url);
|
|
349
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
350
|
+
await writeFile(outputPath, buffer);
|
|
351
|
+
}
|
|
352
|
+
else if (image.base64) {
|
|
353
|
+
const buffer = Buffer.from(image.base64, "base64");
|
|
354
|
+
await writeFile(outputPath, buffer);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
toolCallId: "",
|
|
359
|
+
success: true,
|
|
360
|
+
output: `Image generated: ${output}\nPrompt: ${prompt}\nProvider: ${provider}\nSize: ${size}`,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
return {
|
|
365
|
+
toolCallId: "",
|
|
366
|
+
success: false,
|
|
367
|
+
output: "",
|
|
368
|
+
error: `Failed to generate image: ${error instanceof Error ? error.message : String(error)}`,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
const generateVideo = async (args, context) => {
|
|
373
|
+
const prompt = args.prompt;
|
|
374
|
+
const provider = args.provider || "grok";
|
|
375
|
+
const imagePath = args.image;
|
|
376
|
+
const output = args.output || `${provider}-${getTimestamp()}.mp4`;
|
|
377
|
+
const duration = args.duration || (provider === "veo" ? 6 : 5);
|
|
378
|
+
const runwayModel = args.runwayModel || "gen4.5";
|
|
379
|
+
// Validate: Runway gen4_turbo requires an image; gen4.5 supports text-to-video
|
|
380
|
+
if (provider === "runway" && !imagePath && runwayModel !== "gen4.5") {
|
|
381
|
+
return {
|
|
382
|
+
toolCallId: "",
|
|
383
|
+
success: false,
|
|
384
|
+
output: "",
|
|
385
|
+
error: `Runway ${runwayModel} requires an input image. Provide 'image' parameter, use 'gen4.5' model, or use provider 'kling'/'veo' for text-to-video.`,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
// Helper to prepare reference image
|
|
389
|
+
async function prepareReferenceImage(imgPath) {
|
|
390
|
+
const absImagePath = resolve(context.workingDirectory, imgPath);
|
|
391
|
+
const imageBuffer = await readFile(absImagePath);
|
|
392
|
+
const base64 = imageBuffer.toString("base64");
|
|
393
|
+
const ext = imgPath.split(".").pop()?.toLowerCase() || "png";
|
|
394
|
+
const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext}`;
|
|
395
|
+
return `data:${mimeType};base64,${base64}`;
|
|
396
|
+
}
|
|
397
|
+
try {
|
|
398
|
+
if (provider === "runway") {
|
|
399
|
+
const apiKey = await getApiKeyFromConfig("runway");
|
|
400
|
+
if (!apiKey) {
|
|
401
|
+
return {
|
|
402
|
+
toolCallId: "",
|
|
403
|
+
success: false,
|
|
404
|
+
output: "",
|
|
405
|
+
error: "Runway API key required. Configure via 'vibe setup'.",
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
const { RunwayProvider } = await import("@vibeframe/ai-providers");
|
|
409
|
+
const runway = new RunwayProvider();
|
|
410
|
+
await runway.initialize({ apiKey });
|
|
411
|
+
const referenceImage = imagePath ? await prepareReferenceImage(imagePath) : undefined;
|
|
412
|
+
const result = await runway.generateVideo(prompt, {
|
|
413
|
+
prompt,
|
|
414
|
+
model: runwayModel,
|
|
415
|
+
duration,
|
|
416
|
+
referenceImage,
|
|
417
|
+
});
|
|
418
|
+
if (result.status === "failed") {
|
|
419
|
+
return {
|
|
420
|
+
toolCallId: "",
|
|
421
|
+
success: false,
|
|
422
|
+
output: "",
|
|
423
|
+
error: `Video generation failed: ${result.error}`,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
if (result.status === "pending" || result.status === "processing") {
|
|
427
|
+
let finalResult = result;
|
|
428
|
+
const maxAttempts = 60;
|
|
429
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
430
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
431
|
+
finalResult = await runway.getGenerationStatus(result.id);
|
|
432
|
+
if (finalResult.status === "completed" || finalResult.status === "failed") {
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (finalResult.status !== "completed") {
|
|
437
|
+
return {
|
|
438
|
+
toolCallId: "",
|
|
439
|
+
success: false,
|
|
440
|
+
output: "",
|
|
441
|
+
error: `Video generation timed out or failed: ${finalResult.error || finalResult.status}`,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
if (finalResult.videoUrl) {
|
|
445
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
446
|
+
const buffer = await downloadVideo(finalResult.videoUrl, apiKey);
|
|
447
|
+
await writeFile(outputPath, buffer);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
toolCallId: "",
|
|
452
|
+
success: true,
|
|
453
|
+
output: `Video generated: ${output}\nProvider: runway\nPrompt: ${prompt}\nDuration: ${duration}s`,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
else if (provider === "veo") {
|
|
457
|
+
const apiKey = await getApiKeyFromConfig("google");
|
|
458
|
+
if (!apiKey) {
|
|
459
|
+
return {
|
|
460
|
+
toolCallId: "",
|
|
461
|
+
success: false,
|
|
462
|
+
output: "",
|
|
463
|
+
error: "Google API key required. Configure via 'vibe setup'.",
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
const { GeminiProvider } = await import("@vibeframe/ai-providers");
|
|
467
|
+
const gemini = new GeminiProvider();
|
|
468
|
+
await gemini.initialize({ apiKey });
|
|
469
|
+
const referenceImage = imagePath ? await prepareReferenceImage(imagePath) : undefined;
|
|
470
|
+
const negativePrompt = args.negativePrompt;
|
|
471
|
+
const resolution = args.resolution;
|
|
472
|
+
const veoDuration = duration <= 6 ? (duration <= 4 ? 4 : 6) : 8;
|
|
473
|
+
const result = await gemini.generateVideo(prompt, {
|
|
474
|
+
prompt,
|
|
475
|
+
duration: veoDuration,
|
|
476
|
+
referenceImage,
|
|
477
|
+
model: "veo-3.1-fast-generate-preview",
|
|
478
|
+
negativePrompt,
|
|
479
|
+
resolution,
|
|
480
|
+
});
|
|
481
|
+
if (result.status === "failed") {
|
|
482
|
+
return {
|
|
483
|
+
toolCallId: "",
|
|
484
|
+
success: false,
|
|
485
|
+
output: "",
|
|
486
|
+
error: `Veo video generation failed: ${result.error}`,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
if (result.status === "pending" || result.status === "processing") {
|
|
490
|
+
const finalResult = await gemini.waitForVideoCompletion(result.id, undefined, 300000);
|
|
491
|
+
if (finalResult.status !== "completed") {
|
|
492
|
+
return {
|
|
493
|
+
toolCallId: "",
|
|
494
|
+
success: false,
|
|
495
|
+
output: "",
|
|
496
|
+
error: `Veo video generation timed out or failed: ${finalResult.error || finalResult.status}`,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
if (finalResult.videoUrl) {
|
|
500
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
501
|
+
const buffer = await downloadVideo(finalResult.videoUrl, apiKey);
|
|
502
|
+
await writeFile(outputPath, buffer);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
toolCallId: "",
|
|
507
|
+
success: true,
|
|
508
|
+
output: `Video generated: ${output}\nProvider: veo\nPrompt: ${prompt}\nDuration: ${duration}s`,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
else if (provider === "grok") {
|
|
512
|
+
const apiKey = await getApiKeyFromConfig("xai");
|
|
513
|
+
if (!apiKey) {
|
|
514
|
+
return {
|
|
515
|
+
toolCallId: "",
|
|
516
|
+
success: false,
|
|
517
|
+
output: "",
|
|
518
|
+
error: "xAI API key required. Configure via 'vibe setup'.",
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
const { GrokProvider } = await import("@vibeframe/ai-providers");
|
|
522
|
+
const grok = new GrokProvider();
|
|
523
|
+
await grok.initialize({ apiKey });
|
|
524
|
+
const referenceImage = imagePath ? await prepareReferenceImage(imagePath) : undefined;
|
|
525
|
+
const result = await grok.generateVideo(prompt, {
|
|
526
|
+
prompt,
|
|
527
|
+
duration,
|
|
528
|
+
referenceImage,
|
|
529
|
+
aspectRatio: "16:9",
|
|
530
|
+
});
|
|
531
|
+
if (result.status === "failed") {
|
|
532
|
+
return {
|
|
533
|
+
toolCallId: "",
|
|
534
|
+
success: false,
|
|
535
|
+
output: "",
|
|
536
|
+
error: `Grok video generation failed: ${result.error}`,
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
if (result.status === "pending" || result.status === "processing") {
|
|
540
|
+
const finalResult = await grok.waitForCompletion(result.id, undefined, 300000);
|
|
541
|
+
if (finalResult.status !== "completed") {
|
|
542
|
+
return {
|
|
543
|
+
toolCallId: "",
|
|
544
|
+
success: false,
|
|
545
|
+
output: "",
|
|
546
|
+
error: `Grok video generation timed out or failed: ${finalResult.error || finalResult.status}`,
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
if (finalResult.videoUrl) {
|
|
550
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
551
|
+
const buffer = await downloadVideo(finalResult.videoUrl, apiKey);
|
|
552
|
+
await writeFile(outputPath, buffer);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return {
|
|
556
|
+
toolCallId: "",
|
|
557
|
+
success: true,
|
|
558
|
+
output: `Video generated: ${output}\nProvider: grok (native audio)\nPrompt: ${prompt}\nDuration: ${duration}s`,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
// kling
|
|
563
|
+
const apiKey = await getApiKeyFromConfig("kling");
|
|
564
|
+
if (!apiKey) {
|
|
565
|
+
return {
|
|
566
|
+
toolCallId: "",
|
|
567
|
+
success: false,
|
|
568
|
+
output: "",
|
|
569
|
+
error: "Kling API key required. Configure via 'vibe setup'.",
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
const { KlingProvider } = await import("@vibeframe/ai-providers");
|
|
573
|
+
const kling = new KlingProvider();
|
|
574
|
+
await kling.initialize({ apiKey });
|
|
575
|
+
let referenceImage = imagePath ? await prepareReferenceImage(imagePath) : undefined;
|
|
576
|
+
const mode = args.mode || "std";
|
|
577
|
+
// Kling v2.5+ requires image URL, not base64 — auto-upload to ImgBB
|
|
578
|
+
if (referenceImage && referenceImage.startsWith("data:")) {
|
|
579
|
+
const imgbbKey = await getApiKeyFromConfig("imgbb") || process.env.IMGBB_API_KEY;
|
|
580
|
+
if (!imgbbKey) {
|
|
581
|
+
return {
|
|
582
|
+
toolCallId: "",
|
|
583
|
+
success: false,
|
|
584
|
+
output: "",
|
|
585
|
+
error: "Kling requires image URL for image-to-video. Set IMGBB_API_KEY for auto-upload via 'vibe setup'.",
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
const { uploadToImgbb } = await import("../../commands/ai-script-pipeline.js");
|
|
589
|
+
const base64Data = referenceImage.split(",")[1];
|
|
590
|
+
const imageBuffer = Buffer.from(base64Data, "base64");
|
|
591
|
+
const uploadResult = await uploadToImgbb(imageBuffer, imgbbKey);
|
|
592
|
+
if (!uploadResult.success || !uploadResult.url) {
|
|
593
|
+
return {
|
|
594
|
+
toolCallId: "",
|
|
595
|
+
success: false,
|
|
596
|
+
output: "",
|
|
597
|
+
error: `ImgBB upload failed: ${uploadResult.error || "Unknown error"}`,
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
referenceImage = uploadResult.url;
|
|
601
|
+
}
|
|
602
|
+
const result = await kling.generateVideo(prompt, {
|
|
603
|
+
prompt,
|
|
604
|
+
duration: duration,
|
|
605
|
+
mode,
|
|
606
|
+
referenceImage,
|
|
607
|
+
});
|
|
608
|
+
if (result.status === "failed") {
|
|
609
|
+
return {
|
|
610
|
+
toolCallId: "",
|
|
611
|
+
success: false,
|
|
612
|
+
output: "",
|
|
613
|
+
error: `Kling video generation failed: ${result.error}`,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (result.status === "pending" || result.status === "processing") {
|
|
617
|
+
let finalResult = result;
|
|
618
|
+
const maxAttempts = 60;
|
|
619
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
620
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
621
|
+
finalResult = await kling.getGenerationStatus(result.id);
|
|
622
|
+
if (finalResult.status === "completed" || finalResult.status === "failed") {
|
|
623
|
+
break;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (finalResult.status !== "completed") {
|
|
627
|
+
return {
|
|
628
|
+
toolCallId: "",
|
|
629
|
+
success: false,
|
|
630
|
+
output: "",
|
|
631
|
+
error: `Kling video generation timed out or failed: ${finalResult.error || finalResult.status}`,
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
if (finalResult.videoUrl) {
|
|
635
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
636
|
+
const buffer = await downloadVideo(finalResult.videoUrl, apiKey);
|
|
637
|
+
await writeFile(outputPath, buffer);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
return {
|
|
641
|
+
toolCallId: "",
|
|
642
|
+
success: true,
|
|
643
|
+
output: `Video generated: ${output}\nProvider: kling\nPrompt: ${prompt}\nDuration: ${duration}s\nMode: ${mode}`,
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
catch (error) {
|
|
648
|
+
return {
|
|
649
|
+
toolCallId: "",
|
|
650
|
+
success: false,
|
|
651
|
+
output: "",
|
|
652
|
+
error: `Failed to generate video: ${error instanceof Error ? error.message : String(error)}`,
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
const generateTTS = async (args, context) => {
|
|
657
|
+
const text = args.text;
|
|
658
|
+
const output = args.output || `tts-${getTimestamp()}.mp3`;
|
|
659
|
+
const voice = args.voice;
|
|
660
|
+
try {
|
|
661
|
+
const apiKey = await getApiKeyFromConfig("elevenlabs");
|
|
662
|
+
if (!apiKey) {
|
|
663
|
+
return {
|
|
664
|
+
toolCallId: "",
|
|
665
|
+
success: false,
|
|
666
|
+
output: "",
|
|
667
|
+
error: "ElevenLabs API key required. Configure via 'vibe setup'.",
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
const { ElevenLabsProvider } = await import("@vibeframe/ai-providers");
|
|
671
|
+
const elevenlabs = new ElevenLabsProvider();
|
|
672
|
+
await elevenlabs.initialize({ apiKey });
|
|
673
|
+
const result = await elevenlabs.textToSpeech(text, {
|
|
674
|
+
voiceId: voice,
|
|
675
|
+
});
|
|
676
|
+
if (!result.success || !result.audioBuffer) {
|
|
677
|
+
return {
|
|
678
|
+
toolCallId: "",
|
|
679
|
+
success: false,
|
|
680
|
+
output: "",
|
|
681
|
+
error: `TTS generation failed: ${result.error || "No audio generated"}`,
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
// Save audio
|
|
685
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
686
|
+
await writeFile(outputPath, result.audioBuffer);
|
|
687
|
+
return {
|
|
688
|
+
toolCallId: "",
|
|
689
|
+
success: true,
|
|
690
|
+
output: `Speech generated: ${output}\nText: ${text.substring(0, 100)}${text.length > 100 ? "..." : ""}`,
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
catch (error) {
|
|
694
|
+
return {
|
|
695
|
+
toolCallId: "",
|
|
696
|
+
success: false,
|
|
697
|
+
output: "",
|
|
698
|
+
error: `Failed to generate speech: ${error instanceof Error ? error.message : String(error)}`,
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
const generateSFX = async (args, context) => {
|
|
703
|
+
const prompt = args.prompt;
|
|
704
|
+
const output = args.output || `sfx-${getTimestamp()}.mp3`;
|
|
705
|
+
const duration = args.duration;
|
|
706
|
+
try {
|
|
707
|
+
const apiKey = await getApiKeyFromConfig("elevenlabs");
|
|
708
|
+
if (!apiKey) {
|
|
709
|
+
return {
|
|
710
|
+
toolCallId: "",
|
|
711
|
+
success: false,
|
|
712
|
+
output: "",
|
|
713
|
+
error: "ElevenLabs API key required. Configure via 'vibe setup'.",
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
const { ElevenLabsProvider } = await import("@vibeframe/ai-providers");
|
|
717
|
+
const elevenlabs = new ElevenLabsProvider();
|
|
718
|
+
await elevenlabs.initialize({ apiKey });
|
|
719
|
+
const result = await elevenlabs.generateSoundEffect(prompt, {
|
|
720
|
+
duration,
|
|
721
|
+
});
|
|
722
|
+
if (!result.success || !result.audioBuffer) {
|
|
723
|
+
return {
|
|
724
|
+
toolCallId: "",
|
|
725
|
+
success: false,
|
|
726
|
+
output: "",
|
|
727
|
+
error: `SFX generation failed: ${result.error || "No audio generated"}`,
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
// Save audio
|
|
731
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
732
|
+
await writeFile(outputPath, result.audioBuffer);
|
|
733
|
+
return {
|
|
734
|
+
toolCallId: "",
|
|
735
|
+
success: true,
|
|
736
|
+
output: `Sound effect generated: ${output}\nPrompt: ${prompt}`,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
catch (error) {
|
|
740
|
+
return {
|
|
741
|
+
toolCallId: "",
|
|
742
|
+
success: false,
|
|
743
|
+
output: "",
|
|
744
|
+
error: `Failed to generate sound effect: ${error instanceof Error ? error.message : String(error)}`,
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
const generateMusic = async (args, context) => {
|
|
749
|
+
const prompt = args.prompt;
|
|
750
|
+
const output = args.output || `music-${getTimestamp()}.mp3`;
|
|
751
|
+
const duration = args.duration || 8;
|
|
752
|
+
const provider = args.provider || "elevenlabs";
|
|
753
|
+
const instrumental = args.instrumental || false;
|
|
754
|
+
try {
|
|
755
|
+
if (provider === "elevenlabs") {
|
|
756
|
+
// ElevenLabs Music API — synchronous, up to 10 minutes
|
|
757
|
+
const apiKey = await getApiKeyFromConfig("elevenlabs");
|
|
758
|
+
if (!apiKey) {
|
|
759
|
+
return {
|
|
760
|
+
toolCallId: "",
|
|
761
|
+
success: false,
|
|
762
|
+
output: "",
|
|
763
|
+
error: "ElevenLabs API key required. Configure via 'vibe setup'.",
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
const { ElevenLabsProvider } = await import("@vibeframe/ai-providers");
|
|
767
|
+
const elevenlabs = new ElevenLabsProvider();
|
|
768
|
+
await elevenlabs.initialize({ apiKey });
|
|
769
|
+
const result = await elevenlabs.generateMusic(prompt, {
|
|
770
|
+
duration,
|
|
771
|
+
forceInstrumental: instrumental,
|
|
772
|
+
});
|
|
773
|
+
if (!result.success || !result.audioBuffer) {
|
|
774
|
+
return {
|
|
775
|
+
toolCallId: "",
|
|
776
|
+
success: false,
|
|
777
|
+
output: "",
|
|
778
|
+
error: `Music generation failed: ${result.error || "No audio generated"}`,
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
782
|
+
await writeFile(outputPath, result.audioBuffer);
|
|
783
|
+
return {
|
|
784
|
+
toolCallId: "",
|
|
785
|
+
success: true,
|
|
786
|
+
output: `Music generated: ${output}\nPrompt: ${prompt}\nDuration: ${duration}s\nProvider: ElevenLabs${instrumental ? "\nMode: Instrumental" : ""}`,
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
// Replicate MusicGen — async polling
|
|
791
|
+
const apiKey = await getApiKeyFromConfig("replicate");
|
|
792
|
+
if (!apiKey) {
|
|
793
|
+
return {
|
|
794
|
+
toolCallId: "",
|
|
795
|
+
success: false,
|
|
796
|
+
output: "",
|
|
797
|
+
error: "Replicate API key required. Configure via 'vibe setup'.",
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
const { ReplicateProvider } = await import("@vibeframe/ai-providers");
|
|
801
|
+
const replicate = new ReplicateProvider();
|
|
802
|
+
await replicate.initialize({ apiKey });
|
|
803
|
+
const result = await replicate.generateMusic(prompt, {
|
|
804
|
+
duration,
|
|
805
|
+
});
|
|
806
|
+
if (!result.success) {
|
|
807
|
+
return {
|
|
808
|
+
toolCallId: "",
|
|
809
|
+
success: false,
|
|
810
|
+
output: "",
|
|
811
|
+
error: `Music generation failed: ${result.error || "Unknown error"}`,
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
// Music generation is async - need to poll
|
|
815
|
+
if (result.taskId) {
|
|
816
|
+
let finalResult = result;
|
|
817
|
+
const maxAttempts = 60;
|
|
818
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
819
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
820
|
+
finalResult = await replicate.getMusicStatus(result.taskId);
|
|
821
|
+
if (finalResult.success && finalResult.audioUrl) {
|
|
822
|
+
break;
|
|
823
|
+
}
|
|
824
|
+
if (finalResult.error) {
|
|
825
|
+
return {
|
|
826
|
+
toolCallId: "",
|
|
827
|
+
success: false,
|
|
828
|
+
output: "",
|
|
829
|
+
error: `Music generation failed: ${finalResult.error}`,
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
if (finalResult.audioUrl) {
|
|
834
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
835
|
+
const response = await fetch(finalResult.audioUrl);
|
|
836
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
837
|
+
await writeFile(outputPath, buffer);
|
|
838
|
+
}
|
|
839
|
+
else {
|
|
840
|
+
return {
|
|
841
|
+
toolCallId: "",
|
|
842
|
+
success: false,
|
|
843
|
+
output: "",
|
|
844
|
+
error: "Music generation timed out",
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return {
|
|
849
|
+
toolCallId: "",
|
|
850
|
+
success: true,
|
|
851
|
+
output: `Music generated: ${output}\nPrompt: ${prompt}\nDuration: ${duration}s\nProvider: Replicate`,
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
catch (error) {
|
|
856
|
+
return {
|
|
857
|
+
toolCallId: "",
|
|
858
|
+
success: false,
|
|
859
|
+
output: "",
|
|
860
|
+
error: `Failed to generate music: ${error instanceof Error ? error.message : String(error)}`,
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
const generateStoryboard = async (args, context) => {
|
|
865
|
+
const script = args.script;
|
|
866
|
+
const targetDuration = args.targetDuration;
|
|
867
|
+
const output = args.output || `storyboard-${getTimestamp()}.json`;
|
|
868
|
+
const creativity = args.creativity;
|
|
869
|
+
try {
|
|
870
|
+
const apiKey = await getApiKeyFromConfig("anthropic");
|
|
871
|
+
if (!apiKey) {
|
|
872
|
+
return {
|
|
873
|
+
toolCallId: "",
|
|
874
|
+
success: false,
|
|
875
|
+
output: "",
|
|
876
|
+
error: "Anthropic API key required. Configure via 'vibe setup'.",
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
const { ClaudeProvider } = await import("@vibeframe/ai-providers");
|
|
880
|
+
const claude = new ClaudeProvider();
|
|
881
|
+
await claude.initialize({ apiKey });
|
|
882
|
+
const result = await claude.analyzeContent(script, targetDuration, { creativity });
|
|
883
|
+
if (!result || result.length === 0) {
|
|
884
|
+
return {
|
|
885
|
+
toolCallId: "",
|
|
886
|
+
success: false,
|
|
887
|
+
output: "",
|
|
888
|
+
error: "Failed to generate storyboard",
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
// Save storyboard
|
|
892
|
+
const outputPath = resolve(context.workingDirectory, output);
|
|
893
|
+
await writeFile(outputPath, JSON.stringify(result, null, 2), "utf-8");
|
|
894
|
+
// Format summary
|
|
895
|
+
const sanitizedResult = sanitizeAIResult(result);
|
|
896
|
+
const summary = sanitizedResult.map((scene, i) => `Scene ${i + 1}: ${scene.description.substring(0, 60)}...`).join("\n");
|
|
897
|
+
return {
|
|
898
|
+
toolCallId: "",
|
|
899
|
+
success: true,
|
|
900
|
+
output: `Storyboard generated: ${output}\n\n${summary}`,
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
catch (error) {
|
|
904
|
+
return {
|
|
905
|
+
toolCallId: "",
|
|
906
|
+
success: false,
|
|
907
|
+
output: "",
|
|
908
|
+
error: `Failed to generate storyboard: ${error instanceof Error ? error.message : String(error)}`,
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
const generateMotion = async (args, context) => {
|
|
913
|
+
try {
|
|
914
|
+
const { executeMotion } = await import("../../commands/ai-motion.js");
|
|
915
|
+
const video = args.video
|
|
916
|
+
? resolve(context.workingDirectory, args.video)
|
|
917
|
+
: undefined;
|
|
918
|
+
const output = args.output
|
|
919
|
+
? resolve(context.workingDirectory, args.output)
|
|
920
|
+
: undefined;
|
|
921
|
+
const result = await executeMotion({
|
|
922
|
+
description: args.description,
|
|
923
|
+
duration: args.duration,
|
|
924
|
+
width: args.width,
|
|
925
|
+
height: args.height,
|
|
926
|
+
style: args.style,
|
|
927
|
+
render: true, // Always render in agent mode
|
|
928
|
+
video,
|
|
929
|
+
output,
|
|
930
|
+
});
|
|
931
|
+
if (!result.success) {
|
|
932
|
+
return {
|
|
933
|
+
toolCallId: "",
|
|
934
|
+
success: false,
|
|
935
|
+
output: result.codePath ? `TSX code saved to: ${result.codePath}` : "",
|
|
936
|
+
error: result.error || "Motion generation failed",
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
const parts = [];
|
|
940
|
+
if (result.codePath)
|
|
941
|
+
parts.push(`Code: ${result.codePath}`);
|
|
942
|
+
if (result.renderedPath)
|
|
943
|
+
parts.push(`Rendered: ${result.renderedPath}`);
|
|
944
|
+
if (result.compositedPath)
|
|
945
|
+
parts.push(`Composited: ${result.compositedPath}`);
|
|
946
|
+
return {
|
|
947
|
+
toolCallId: "",
|
|
948
|
+
success: true,
|
|
949
|
+
output: parts.join("\n"),
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
catch (error) {
|
|
953
|
+
return {
|
|
954
|
+
toolCallId: "",
|
|
955
|
+
success: false,
|
|
956
|
+
output: "",
|
|
957
|
+
error: `Motion generation failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
// ============================================================================
|
|
962
|
+
// Registration
|
|
963
|
+
// ============================================================================
|
|
964
|
+
export function registerGenerationTools(registry) {
|
|
965
|
+
registry.register(imageDef, generateImage);
|
|
966
|
+
registry.register(videoDef, generateVideo);
|
|
967
|
+
registry.register(ttsDef, generateTTS);
|
|
968
|
+
registry.register(sfxDef, generateSFX);
|
|
969
|
+
registry.register(musicDef, generateMusic);
|
|
970
|
+
registry.register(storyboardDef, generateStoryboard);
|
|
971
|
+
registry.register(motionDef, generateMotion);
|
|
972
|
+
}
|
|
973
|
+
//# sourceMappingURL=ai-generation.js.map
|