@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,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module ai-analyze
|
|
3
|
+
*
|
|
4
|
+
* Media analysis execute functions using Gemini multimodal AI.
|
|
5
|
+
*
|
|
6
|
+
* CLI commands: gemini-video, analyze
|
|
7
|
+
*
|
|
8
|
+
* Execute functions:
|
|
9
|
+
* executeGeminiVideo - Analyze video files or YouTube URLs with Gemini
|
|
10
|
+
* executeAnalyze - Unified analysis for images, videos, and YouTube URLs
|
|
11
|
+
*
|
|
12
|
+
* @dependencies Gemini (Google)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Command } from "commander";
|
|
16
|
+
import { readFile } from "node:fs/promises";
|
|
17
|
+
import { extname, resolve } from "node:path";
|
|
18
|
+
import { existsSync } from "node:fs";
|
|
19
|
+
import chalk from "chalk";
|
|
20
|
+
import ora from "ora";
|
|
21
|
+
import { GeminiProvider } from "@vibeframe/ai-providers";
|
|
22
|
+
import { getApiKey } from "../utils/api-key.js";
|
|
23
|
+
|
|
24
|
+
/** Options for {@link executeGeminiVideo}. */
|
|
25
|
+
export interface GeminiVideoOptions {
|
|
26
|
+
/** Video file path or YouTube URL */
|
|
27
|
+
source: string;
|
|
28
|
+
/** Analysis prompt (e.g. "Summarize this video") */
|
|
29
|
+
prompt: string;
|
|
30
|
+
/** Gemini model shorthand (default: "flash") */
|
|
31
|
+
model?: "flash" | "flash-2.5" | "pro";
|
|
32
|
+
/** Frames per second for video sampling (default: 1) */
|
|
33
|
+
fps?: number;
|
|
34
|
+
/** Start offset in seconds for clipping */
|
|
35
|
+
start?: number;
|
|
36
|
+
/** End offset in seconds for clipping */
|
|
37
|
+
end?: number;
|
|
38
|
+
/** Use low-resolution mode (fewer tokens, longer videos) */
|
|
39
|
+
lowRes?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Result from {@link executeGeminiVideo}. */
|
|
43
|
+
export interface GeminiVideoResult {
|
|
44
|
+
/** Whether the analysis succeeded */
|
|
45
|
+
success: boolean;
|
|
46
|
+
/** Gemini's text response */
|
|
47
|
+
response?: string;
|
|
48
|
+
/** Model used for analysis */
|
|
49
|
+
model?: string;
|
|
50
|
+
/** Total tokens consumed */
|
|
51
|
+
totalTokens?: number;
|
|
52
|
+
/** Prompt tokens consumed */
|
|
53
|
+
promptTokens?: number;
|
|
54
|
+
/** Response tokens generated */
|
|
55
|
+
responseTokens?: number;
|
|
56
|
+
/** Error message on failure */
|
|
57
|
+
error?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Analyze a video file or YouTube URL using Gemini multimodal AI.
|
|
62
|
+
*
|
|
63
|
+
* Supports local video files and YouTube URLs. Provides structured responses
|
|
64
|
+
* with optional token usage reporting.
|
|
65
|
+
*
|
|
66
|
+
* @param options - Video analysis configuration
|
|
67
|
+
* @returns Result with Gemini's response text and token usage
|
|
68
|
+
*/
|
|
69
|
+
export async function executeGeminiVideo(
|
|
70
|
+
options: GeminiVideoOptions
|
|
71
|
+
): Promise<GeminiVideoResult> {
|
|
72
|
+
try {
|
|
73
|
+
const apiKey = await getApiKey("GOOGLE_API_KEY", "Google");
|
|
74
|
+
if (!apiKey) {
|
|
75
|
+
return { success: false, error: "Google API key required. Run 'vibe setup' or set GOOGLE_API_KEY in .env" };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const isYouTube = options.source.includes("youtube.com") || options.source.includes("youtu.be");
|
|
79
|
+
|
|
80
|
+
const modelMap: Record<string, string> = {
|
|
81
|
+
flash: "gemini-3-flash-preview",
|
|
82
|
+
"flash-2.5": "gemini-2.5-flash",
|
|
83
|
+
pro: "gemini-2.5-pro",
|
|
84
|
+
};
|
|
85
|
+
const modelId = modelMap[options.model || "flash"] || modelMap.flash;
|
|
86
|
+
|
|
87
|
+
let videoData: Buffer | string;
|
|
88
|
+
if (isYouTube) {
|
|
89
|
+
videoData = options.source;
|
|
90
|
+
} else {
|
|
91
|
+
const absPath = resolve(process.cwd(), options.source);
|
|
92
|
+
if (!existsSync(absPath)) {
|
|
93
|
+
return { success: false, error: `File not found: ${absPath}` };
|
|
94
|
+
}
|
|
95
|
+
videoData = await readFile(absPath);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const gemini = new GeminiProvider();
|
|
99
|
+
await gemini.initialize({ apiKey });
|
|
100
|
+
|
|
101
|
+
const result = await gemini.analyzeVideo(videoData, options.prompt, {
|
|
102
|
+
model: modelId as "gemini-3-flash-preview" | "gemini-2.5-flash" | "gemini-2.5-pro",
|
|
103
|
+
fps: options.fps,
|
|
104
|
+
startOffset: options.start,
|
|
105
|
+
endOffset: options.end,
|
|
106
|
+
lowResolution: options.lowRes,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (!result.success) {
|
|
110
|
+
return { success: false, error: result.error || "Video analysis failed" };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
success: true,
|
|
115
|
+
response: result.response,
|
|
116
|
+
model: result.model,
|
|
117
|
+
totalTokens: result.totalTokens,
|
|
118
|
+
promptTokens: result.promptTokens,
|
|
119
|
+
responseTokens: result.responseTokens,
|
|
120
|
+
};
|
|
121
|
+
} catch (error) {
|
|
122
|
+
return {
|
|
123
|
+
success: false,
|
|
124
|
+
error: error instanceof Error ? error.message : String(error),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Options for {@link executeAnalyze}. */
|
|
130
|
+
export interface AnalyzeOptions {
|
|
131
|
+
/** Image/video file path, image URL, or YouTube URL */
|
|
132
|
+
source: string;
|
|
133
|
+
/** Analysis prompt (e.g. "Describe this image") */
|
|
134
|
+
prompt: string;
|
|
135
|
+
/** Gemini model shorthand (default: "flash") */
|
|
136
|
+
model?: "flash" | "flash-2.5" | "pro";
|
|
137
|
+
/** Frames per second for video sampling (default: 1) */
|
|
138
|
+
fps?: number;
|
|
139
|
+
/** Start offset in seconds (video only) */
|
|
140
|
+
start?: number;
|
|
141
|
+
/** End offset in seconds (video only) */
|
|
142
|
+
end?: number;
|
|
143
|
+
/** Use low-resolution mode (fewer tokens) */
|
|
144
|
+
lowRes?: boolean;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Result from {@link executeAnalyze}. */
|
|
148
|
+
export interface AnalyzeResult {
|
|
149
|
+
/** Whether the analysis succeeded */
|
|
150
|
+
success: boolean;
|
|
151
|
+
/** Gemini's text response */
|
|
152
|
+
response?: string;
|
|
153
|
+
/** Model used for analysis */
|
|
154
|
+
model?: string;
|
|
155
|
+
/** Detected source media type */
|
|
156
|
+
sourceType?: "image" | "video" | "youtube";
|
|
157
|
+
/** Total tokens consumed */
|
|
158
|
+
totalTokens?: number;
|
|
159
|
+
/** Prompt tokens consumed */
|
|
160
|
+
promptTokens?: number;
|
|
161
|
+
/** Response tokens generated */
|
|
162
|
+
responseTokens?: number;
|
|
163
|
+
/** Error message on failure */
|
|
164
|
+
error?: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Analyze any media source (image, video, or YouTube URL) using Gemini.
|
|
169
|
+
*
|
|
170
|
+
* Auto-detects source type from file extension or URL pattern. Supports
|
|
171
|
+
* local files, remote URLs, and YouTube links.
|
|
172
|
+
*
|
|
173
|
+
* @param options - Unified analysis configuration
|
|
174
|
+
* @returns Result with Gemini's response, detected source type, and token usage
|
|
175
|
+
*/
|
|
176
|
+
export async function executeAnalyze(
|
|
177
|
+
options: AnalyzeOptions
|
|
178
|
+
): Promise<AnalyzeResult> {
|
|
179
|
+
try {
|
|
180
|
+
const apiKey = await getApiKey("GOOGLE_API_KEY", "Google");
|
|
181
|
+
if (!apiKey) {
|
|
182
|
+
return { success: false, error: "Google API key required. Run 'vibe setup' or set GOOGLE_API_KEY in .env" };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const source = options.source;
|
|
186
|
+
|
|
187
|
+
const isYouTube = source.includes("youtube.com") || source.includes("youtu.be");
|
|
188
|
+
const isImageUrl = /^https?:\/\/.+\.(png|jpg|jpeg|webp|gif)(\?.*)?$/i.test(source);
|
|
189
|
+
const isVideoUrl = /^https?:\/\/.+\.(mp4|mov|webm)(\?.*)?$/i.test(source);
|
|
190
|
+
const ext = extname(source).toLowerCase();
|
|
191
|
+
const imageExts = [".png", ".jpg", ".jpeg", ".webp", ".gif"];
|
|
192
|
+
const videoExts = [".mp4", ".mov", ".webm", ".avi", ".mkv"];
|
|
193
|
+
const isLocalImage = imageExts.includes(ext);
|
|
194
|
+
const isLocalVideo = videoExts.includes(ext);
|
|
195
|
+
const isImage = isImageUrl || isLocalImage;
|
|
196
|
+
const isVideo = isYouTube || isVideoUrl || isLocalVideo;
|
|
197
|
+
|
|
198
|
+
if (!isImage && !isVideo) {
|
|
199
|
+
return {
|
|
200
|
+
success: false,
|
|
201
|
+
error: "Cannot detect source type. Supported: images (.png/.jpg/.webp/.gif), videos (.mp4/.mov/.webm), YouTube URLs, image URLs.",
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const modelMap: Record<string, string> = {
|
|
206
|
+
flash: "gemini-3-flash-preview",
|
|
207
|
+
"flash-2.5": "gemini-2.5-flash",
|
|
208
|
+
pro: "gemini-2.5-pro",
|
|
209
|
+
};
|
|
210
|
+
const modelId = modelMap[options.model || "flash"] || modelMap.flash;
|
|
211
|
+
|
|
212
|
+
const gemini = new GeminiProvider();
|
|
213
|
+
await gemini.initialize({ apiKey });
|
|
214
|
+
|
|
215
|
+
if (isImage) {
|
|
216
|
+
let imageBuffer: Buffer;
|
|
217
|
+
if (isImageUrl) {
|
|
218
|
+
const response = await fetch(source);
|
|
219
|
+
if (!response.ok) {
|
|
220
|
+
return { success: false, error: `Failed to fetch image: ${response.status}` };
|
|
221
|
+
}
|
|
222
|
+
imageBuffer = Buffer.from(await response.arrayBuffer());
|
|
223
|
+
} else {
|
|
224
|
+
const absPath = resolve(process.cwd(), source);
|
|
225
|
+
if (!existsSync(absPath)) {
|
|
226
|
+
return { success: false, error: `File not found: ${absPath}` };
|
|
227
|
+
}
|
|
228
|
+
imageBuffer = await readFile(absPath);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const result = await gemini.analyzeImage(imageBuffer, options.prompt, {
|
|
232
|
+
model: modelId as "gemini-3-flash-preview" | "gemini-2.5-flash" | "gemini-2.5-pro",
|
|
233
|
+
lowResolution: options.lowRes,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
if (!result.success) {
|
|
237
|
+
return { success: false, error: result.error || "Image analysis failed" };
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
success: true,
|
|
242
|
+
response: result.response,
|
|
243
|
+
model: result.model,
|
|
244
|
+
sourceType: "image",
|
|
245
|
+
totalTokens: result.totalTokens,
|
|
246
|
+
promptTokens: result.promptTokens,
|
|
247
|
+
responseTokens: result.responseTokens,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
let videoData: Buffer | string;
|
|
252
|
+
let sourceType: "video" | "youtube" = "video";
|
|
253
|
+
|
|
254
|
+
if (isYouTube) {
|
|
255
|
+
videoData = source;
|
|
256
|
+
sourceType = "youtube";
|
|
257
|
+
} else if (isVideoUrl) {
|
|
258
|
+
const response = await fetch(source);
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
return { success: false, error: `Failed to fetch video: ${response.status}` };
|
|
261
|
+
}
|
|
262
|
+
videoData = Buffer.from(await response.arrayBuffer());
|
|
263
|
+
} else {
|
|
264
|
+
const absPath = resolve(process.cwd(), source);
|
|
265
|
+
if (!existsSync(absPath)) {
|
|
266
|
+
return { success: false, error: `File not found: ${absPath}` };
|
|
267
|
+
}
|
|
268
|
+
videoData = await readFile(absPath);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const result = await gemini.analyzeVideo(videoData, options.prompt, {
|
|
272
|
+
model: modelId as "gemini-3-flash-preview" | "gemini-2.5-flash" | "gemini-2.5-pro",
|
|
273
|
+
fps: options.fps,
|
|
274
|
+
startOffset: options.start,
|
|
275
|
+
endOffset: options.end,
|
|
276
|
+
lowResolution: options.lowRes,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
if (!result.success) {
|
|
280
|
+
return { success: false, error: result.error || "Video analysis failed" };
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return {
|
|
284
|
+
success: true,
|
|
285
|
+
response: result.response,
|
|
286
|
+
model: result.model,
|
|
287
|
+
sourceType,
|
|
288
|
+
totalTokens: result.totalTokens,
|
|
289
|
+
promptTokens: result.promptTokens,
|
|
290
|
+
responseTokens: result.responseTokens,
|
|
291
|
+
};
|
|
292
|
+
} catch (error) {
|
|
293
|
+
return {
|
|
294
|
+
success: false,
|
|
295
|
+
error: error instanceof Error ? error.message : String(error),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export function registerAnalyzeCommands(aiCommand: Command): void {
|
|
301
|
+
aiCommand
|
|
302
|
+
.command("gemini-video")
|
|
303
|
+
.description("Analyze video using Gemini (summarize, Q&A, extract info)")
|
|
304
|
+
.argument("<source>", "Video file path or YouTube URL")
|
|
305
|
+
.argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')")
|
|
306
|
+
.option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)")
|
|
307
|
+
.option("-m, --model <model>", "Model: flash (default), flash-2.5, pro", "flash")
|
|
308
|
+
.option("--fps <number>", "Frames per second (default: 1, higher for action)")
|
|
309
|
+
.option("--start <seconds>", "Start offset in seconds (for clipping)")
|
|
310
|
+
.option("--end <seconds>", "End offset in seconds (for clipping)")
|
|
311
|
+
.option("--low-res", "Use low resolution mode (fewer tokens, longer videos)")
|
|
312
|
+
.option("-v, --verbose", "Show token usage")
|
|
313
|
+
.action(async (source: string, prompt: string, options) => {
|
|
314
|
+
try {
|
|
315
|
+
if (options.apiKey) {
|
|
316
|
+
process.env.GOOGLE_API_KEY = options.apiKey;
|
|
317
|
+
} else {
|
|
318
|
+
const apiKey = await getApiKey("GOOGLE_API_KEY", "Google");
|
|
319
|
+
if (!apiKey) {
|
|
320
|
+
console.error(chalk.red("Google API key required. Set GOOGLE_API_KEY in .env or run: vibe setup"));
|
|
321
|
+
console.error(chalk.dim("Use --api-key or set GOOGLE_API_KEY environment variable"));
|
|
322
|
+
process.exit(1);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const spinner = ora("Analyzing video...").start();
|
|
327
|
+
const result = await executeGeminiVideo({
|
|
328
|
+
source,
|
|
329
|
+
prompt,
|
|
330
|
+
model: options.model as "flash" | "flash-2.5" | "pro",
|
|
331
|
+
fps: options.fps ? parseFloat(options.fps) : undefined,
|
|
332
|
+
start: options.start ? parseInt(options.start, 10) : undefined,
|
|
333
|
+
end: options.end ? parseInt(options.end, 10) : undefined,
|
|
334
|
+
lowRes: options.lowRes,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
if (!result.success) {
|
|
338
|
+
spinner.fail(chalk.red(result.error || "Video analysis failed"));
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
spinner.succeed(chalk.green("Video analyzed"));
|
|
343
|
+
console.log();
|
|
344
|
+
console.log(result.response);
|
|
345
|
+
console.log();
|
|
346
|
+
|
|
347
|
+
if (options.verbose && result.totalTokens) {
|
|
348
|
+
console.log(chalk.dim("-".repeat(40)));
|
|
349
|
+
console.log(chalk.dim(`Model: ${result.model}`));
|
|
350
|
+
if (result.promptTokens) {
|
|
351
|
+
console.log(chalk.dim(`Prompt tokens: ${result.promptTokens.toLocaleString()}`));
|
|
352
|
+
}
|
|
353
|
+
if (result.responseTokens) {
|
|
354
|
+
console.log(chalk.dim(`Response tokens: ${result.responseTokens.toLocaleString()}`));
|
|
355
|
+
}
|
|
356
|
+
console.log(chalk.dim(`Total tokens: ${result.totalTokens.toLocaleString()}`));
|
|
357
|
+
}
|
|
358
|
+
} catch (error) {
|
|
359
|
+
console.error(chalk.red("Video analysis failed"));
|
|
360
|
+
console.error(error);
|
|
361
|
+
process.exit(1);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
aiCommand
|
|
366
|
+
.command("analyze")
|
|
367
|
+
.description("Analyze any media: images, videos, or YouTube URLs using Gemini")
|
|
368
|
+
.argument("<source>", "Image/video file path, image URL, or YouTube URL")
|
|
369
|
+
.argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')")
|
|
370
|
+
.option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)")
|
|
371
|
+
.option("-m, --model <model>", "Model: flash (default), flash-2.5, pro", "flash")
|
|
372
|
+
.option("--fps <number>", "Frames per second for video (default: 1)")
|
|
373
|
+
.option("--start <seconds>", "Start offset in seconds (video only)")
|
|
374
|
+
.option("--end <seconds>", "End offset in seconds (video only)")
|
|
375
|
+
.option("--low-res", "Use low resolution mode (fewer tokens)")
|
|
376
|
+
.option("-v, --verbose", "Show token usage")
|
|
377
|
+
.action(async (source: string, prompt: string, options) => {
|
|
378
|
+
try {
|
|
379
|
+
if (options.apiKey) {
|
|
380
|
+
process.env.GOOGLE_API_KEY = options.apiKey;
|
|
381
|
+
} else {
|
|
382
|
+
const apiKey = await getApiKey("GOOGLE_API_KEY", "Google");
|
|
383
|
+
if (!apiKey) {
|
|
384
|
+
console.error(chalk.red("Google API key required. Set GOOGLE_API_KEY in .env or run: vibe setup"));
|
|
385
|
+
console.error(chalk.dim("Use --api-key or set GOOGLE_API_KEY environment variable"));
|
|
386
|
+
process.exit(1);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const spinner = ora("Analyzing source...").start();
|
|
391
|
+
const result = await executeAnalyze({
|
|
392
|
+
source,
|
|
393
|
+
prompt,
|
|
394
|
+
model: options.model as "flash" | "flash-2.5" | "pro",
|
|
395
|
+
fps: options.fps ? parseFloat(options.fps) : undefined,
|
|
396
|
+
start: options.start ? parseInt(options.start, 10) : undefined,
|
|
397
|
+
end: options.end ? parseInt(options.end, 10) : undefined,
|
|
398
|
+
lowRes: options.lowRes,
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
if (!result.success) {
|
|
402
|
+
spinner.fail(chalk.red(result.error || "Analysis failed"));
|
|
403
|
+
process.exit(1);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
spinner.succeed(chalk.green("Analysis complete"));
|
|
407
|
+
console.log();
|
|
408
|
+
console.log(result.response);
|
|
409
|
+
console.log();
|
|
410
|
+
|
|
411
|
+
if (options.verbose && result.totalTokens) {
|
|
412
|
+
console.log(chalk.dim("-".repeat(40)));
|
|
413
|
+
console.log(chalk.dim(`Source type: ${result.sourceType}`));
|
|
414
|
+
console.log(chalk.dim(`Model: ${result.model}`));
|
|
415
|
+
if (result.promptTokens) {
|
|
416
|
+
console.log(chalk.dim(`Prompt tokens: ${result.promptTokens.toLocaleString()}`));
|
|
417
|
+
}
|
|
418
|
+
if (result.responseTokens) {
|
|
419
|
+
console.log(chalk.dim(`Response tokens: ${result.responseTokens.toLocaleString()}`));
|
|
420
|
+
}
|
|
421
|
+
console.log(chalk.dim(`Total tokens: ${result.totalTokens.toLocaleString()}`));
|
|
422
|
+
}
|
|
423
|
+
} catch (error) {
|
|
424
|
+
console.error(chalk.red("Analysis failed"));
|
|
425
|
+
console.error(error);
|
|
426
|
+
process.exit(1);
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
}
|