@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,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sanitize
|
|
3
|
+
* @description Sanitize AI/LLM responses to prevent prompt injection and terminal exploits.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Strip suspicious prompt injection patterns from LLM text output.
|
|
8
|
+
* Catches common injection attempts like "Ignore previous instructions",
|
|
9
|
+
* fake system prompts, and markdown-disguised commands.
|
|
10
|
+
*/
|
|
11
|
+
export function sanitizeLLMResponse(text: string): string {
|
|
12
|
+
if (!text || typeof text !== "string") return text;
|
|
13
|
+
|
|
14
|
+
let sanitized = text;
|
|
15
|
+
|
|
16
|
+
// Strip ANSI escape sequences that could manipulate terminal
|
|
17
|
+
// eslint-disable-next-line no-control-regex
|
|
18
|
+
sanitized = sanitized.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "");
|
|
19
|
+
|
|
20
|
+
// Strip other control characters (except newline, tab, carriage return)
|
|
21
|
+
// eslint-disable-next-line no-control-regex
|
|
22
|
+
sanitized = sanitized.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g, "");
|
|
23
|
+
|
|
24
|
+
return sanitized;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Sanitize a file path returned by an AI model.
|
|
29
|
+
* Prevents path traversal and null byte injection.
|
|
30
|
+
*/
|
|
31
|
+
export function sanitizeFilePath(path: string): string {
|
|
32
|
+
if (!path || typeof path !== "string") return path;
|
|
33
|
+
|
|
34
|
+
// Remove null bytes
|
|
35
|
+
let sanitized = path.replace(/\0/g, "");
|
|
36
|
+
|
|
37
|
+
// Remove control characters
|
|
38
|
+
// eslint-disable-next-line no-control-regex
|
|
39
|
+
sanitized = sanitized.replace(/[\x00-\x1f\x7f-\x9f]/g, "");
|
|
40
|
+
|
|
41
|
+
return sanitized;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Sanitize structured data from AI responses (e.g., JSON parsed results).
|
|
46
|
+
* Recursively sanitizes all string values.
|
|
47
|
+
*/
|
|
48
|
+
export function sanitizeAIResult<T>(data: T): T {
|
|
49
|
+
if (data === null || data === undefined) return data;
|
|
50
|
+
if (typeof data === "string") return sanitizeLLMResponse(data) as T;
|
|
51
|
+
if (Array.isArray(data)) return data.map(sanitizeAIResult) as T;
|
|
52
|
+
if (typeof data === "object") {
|
|
53
|
+
const result: Record<string, unknown> = {};
|
|
54
|
+
for (const [key, value] of Object.entries(data as Record<string, unknown>)) {
|
|
55
|
+
result[key] = sanitizeAIResult(value);
|
|
56
|
+
}
|
|
57
|
+
return result as T;
|
|
58
|
+
}
|
|
59
|
+
return data;
|
|
60
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module schema
|
|
3
|
+
* @description Schema introspection command. Outputs JSON Schema for any CLI command,
|
|
4
|
+
* enabling agent introspection without static docs.
|
|
5
|
+
*
|
|
6
|
+
* Usage: vibe schema generate.image
|
|
7
|
+
* vibe schema edit.silence-cut
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
|
|
12
|
+
export const schemaCommand = new Command("schema")
|
|
13
|
+
.description("Show JSON schema for a CLI command")
|
|
14
|
+
.argument("<command>", "Command path (e.g., generate.image, edit.silence-cut)")
|
|
15
|
+
.action((commandPath: string) => {
|
|
16
|
+
// Access the parent program to find commands
|
|
17
|
+
const program = schemaCommand.parent;
|
|
18
|
+
if (!program) {
|
|
19
|
+
console.error("Schema command must be registered on a program");
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const parts = commandPath.split(".");
|
|
24
|
+
if (parts.length !== 2) {
|
|
25
|
+
console.error(
|
|
26
|
+
`Invalid command path: ${commandPath}. Use format: group.action (e.g., generate.image)`
|
|
27
|
+
);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const [groupName, actionName] = parts;
|
|
32
|
+
|
|
33
|
+
// Find the group command
|
|
34
|
+
const groupCmd = program.commands.find(
|
|
35
|
+
(c: Command) => c.name() === groupName
|
|
36
|
+
);
|
|
37
|
+
if (!groupCmd) {
|
|
38
|
+
console.error(`Unknown group: ${groupName}`);
|
|
39
|
+
console.error(
|
|
40
|
+
`Available groups: ${program.commands.map((c: Command) => c.name()).join(", ")}`
|
|
41
|
+
);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Find the action command
|
|
46
|
+
const actionCmd = (groupCmd as Command).commands.find(
|
|
47
|
+
(c: Command) => c.name() === actionName
|
|
48
|
+
);
|
|
49
|
+
if (!actionCmd) {
|
|
50
|
+
console.error(`Unknown action: ${actionName} in group ${groupName}`);
|
|
51
|
+
console.error(
|
|
52
|
+
`Available actions: ${(groupCmd as Command).commands
|
|
53
|
+
.map((c: Command) => c.name())
|
|
54
|
+
.join(", ")}`
|
|
55
|
+
);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Build JSON schema from Commander options and arguments
|
|
60
|
+
const toolName = `${groupName}_${actionName.replace(/-/g, "_")}`;
|
|
61
|
+
const schema = buildSchema(actionCmd as Command, toolName);
|
|
62
|
+
console.log(JSON.stringify(schema, null, 2));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
function buildSchema(
|
|
66
|
+
cmd: Command,
|
|
67
|
+
toolName: string
|
|
68
|
+
): Record<string, unknown> {
|
|
69
|
+
const properties: Record<string, unknown> = {};
|
|
70
|
+
const required: string[] = [];
|
|
71
|
+
|
|
72
|
+
// Extract arguments
|
|
73
|
+
for (const arg of cmd.registeredArguments || []) {
|
|
74
|
+
const name = arg.name();
|
|
75
|
+
properties[name] = {
|
|
76
|
+
type: "string",
|
|
77
|
+
description: arg.description,
|
|
78
|
+
};
|
|
79
|
+
if (arg.required) {
|
|
80
|
+
required.push(name);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Extract options
|
|
85
|
+
for (const opt of cmd.options) {
|
|
86
|
+
const name = camelCase(
|
|
87
|
+
opt.long?.replace(/^--/, "") || opt.short?.replace(/^-/, "") || ""
|
|
88
|
+
);
|
|
89
|
+
if (!name || name === "help") continue;
|
|
90
|
+
|
|
91
|
+
const prop: Record<string, unknown> = {
|
|
92
|
+
description: opt.description,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Detect type from default value or flags
|
|
96
|
+
if (
|
|
97
|
+
opt.flags.includes("<number>") ||
|
|
98
|
+
opt.flags.includes("<seconds>") ||
|
|
99
|
+
opt.flags.includes("<sec>") ||
|
|
100
|
+
opt.flags.includes("<dB>") ||
|
|
101
|
+
opt.flags.includes("<pixels>")
|
|
102
|
+
) {
|
|
103
|
+
prop.type = "number";
|
|
104
|
+
} else if (opt.flags.includes("<") && opt.flags.includes(">")) {
|
|
105
|
+
prop.type = "string";
|
|
106
|
+
} else {
|
|
107
|
+
prop.type = "boolean";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (opt.defaultValue !== undefined) {
|
|
111
|
+
prop.default = opt.defaultValue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
properties[name] = prop;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
name: toolName,
|
|
119
|
+
description: cmd.description(),
|
|
120
|
+
parameters: {
|
|
121
|
+
type: "object",
|
|
122
|
+
properties,
|
|
123
|
+
required: required.length > 0 ? required : undefined,
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function camelCase(str: string): string {
|
|
129
|
+
return str.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());
|
|
130
|
+
}
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup command - Interactive configuration wizard
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { resolve, dirname } from "node:path";
|
|
8
|
+
import { access, readFile, mkdir, writeFile } from "node:fs/promises";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { parse as parseDotenv } from "dotenv";
|
|
11
|
+
import {
|
|
12
|
+
loadConfig,
|
|
13
|
+
saveConfig,
|
|
14
|
+
createDefaultConfig,
|
|
15
|
+
CONFIG_PATH,
|
|
16
|
+
type LLMProvider,
|
|
17
|
+
PROVIDER_NAMES,
|
|
18
|
+
} from "../config/index.js";
|
|
19
|
+
import {
|
|
20
|
+
promptHidden,
|
|
21
|
+
promptSelect,
|
|
22
|
+
promptConfirm,
|
|
23
|
+
closeTTYStream,
|
|
24
|
+
hasTTY,
|
|
25
|
+
} from "../utils/tty.js";
|
|
26
|
+
import { loadEnv } from "../utils/api-key.js";
|
|
27
|
+
|
|
28
|
+
export const setupCommand = new Command("setup")
|
|
29
|
+
.description("Configure VibeFrame (LLM provider, API keys)")
|
|
30
|
+
.option("--reset", "Reset configuration to defaults")
|
|
31
|
+
.option("--full", "Run full setup with all optional providers")
|
|
32
|
+
.option("--show", "Show current configuration (for debugging)")
|
|
33
|
+
.option("--claude-code", "Set up Claude Code integration (.claude/rules/) in current directory")
|
|
34
|
+
.action(async (options) => {
|
|
35
|
+
if (options.claudeCode) {
|
|
36
|
+
await setupClaudeCode();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (options.show) {
|
|
41
|
+
await showConfig();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (options.reset) {
|
|
46
|
+
const config = createDefaultConfig();
|
|
47
|
+
await saveConfig(config);
|
|
48
|
+
console.log(chalk.green("✓ Configuration reset to defaults"));
|
|
49
|
+
console.log(chalk.dim(` Saved to: ${CONFIG_PATH}`));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Check if TTY is available
|
|
54
|
+
if (!hasTTY()) {
|
|
55
|
+
console.error(chalk.red("Error: Interactive setup requires a terminal."));
|
|
56
|
+
console.log(chalk.dim("Run 'vibe setup' directly from your terminal."));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
await runSetupWizard(options.full);
|
|
62
|
+
closeTTYStream();
|
|
63
|
+
// Explicitly exit to ensure clean termination when run from install script
|
|
64
|
+
// The TTY stream can keep the event loop alive otherwise
|
|
65
|
+
process.exit(0);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
closeTTYStream();
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Run the interactive setup wizard
|
|
74
|
+
*/
|
|
75
|
+
async function runSetupWizard(fullSetup = false): Promise<void> {
|
|
76
|
+
console.log();
|
|
77
|
+
console.log(chalk.bold.magenta("VibeFrame Setup"));
|
|
78
|
+
console.log(chalk.dim("─".repeat(40)));
|
|
79
|
+
console.log();
|
|
80
|
+
|
|
81
|
+
// Load existing config or create default
|
|
82
|
+
let config = await loadConfig();
|
|
83
|
+
if (!config) {
|
|
84
|
+
config = createDefaultConfig();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Step 1: Select LLM Provider
|
|
88
|
+
console.log(chalk.bold("1. Choose your AI provider"));
|
|
89
|
+
console.log(chalk.dim(" This provider handles natural language commands."));
|
|
90
|
+
console.log();
|
|
91
|
+
|
|
92
|
+
const providers: LLMProvider[] = ["claude", "openai", "gemini", "xai", "ollama"];
|
|
93
|
+
const providerDescriptions: Record<LLMProvider, string> = {
|
|
94
|
+
claude: "Best understanding, most capable",
|
|
95
|
+
openai: "GPT-5-mini, reliable and fast",
|
|
96
|
+
gemini: "Google AI, good for general use",
|
|
97
|
+
xai: "Grok 4.1, optimized for tool calling",
|
|
98
|
+
ollama: "Free, local, no API key needed",
|
|
99
|
+
};
|
|
100
|
+
const providerLabels = providers.map((p) => {
|
|
101
|
+
const rec = p === "claude" ? chalk.dim(" (recommended)") : "";
|
|
102
|
+
const desc = chalk.dim(` - ${providerDescriptions[p]}`);
|
|
103
|
+
return `${PROVIDER_NAMES[p]}${rec}${desc}`;
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const currentIndex = providers.indexOf(config.llm.provider);
|
|
107
|
+
const providerIndex = await promptSelect(
|
|
108
|
+
chalk.cyan(" Select [1-5]: "),
|
|
109
|
+
providerLabels,
|
|
110
|
+
currentIndex >= 0 ? currentIndex : 0
|
|
111
|
+
);
|
|
112
|
+
config.llm.provider = providers[providerIndex];
|
|
113
|
+
console.log();
|
|
114
|
+
|
|
115
|
+
// Step 2: API Key for selected provider
|
|
116
|
+
const selectedProvider = config.llm.provider;
|
|
117
|
+
|
|
118
|
+
// Show Ollama-specific guidance
|
|
119
|
+
if (selectedProvider === "ollama") {
|
|
120
|
+
console.log(chalk.bold("2. Ollama Setup"));
|
|
121
|
+
console.log();
|
|
122
|
+
console.log(chalk.dim(" Ollama runs locally and requires no API key."));
|
|
123
|
+
console.log(chalk.dim(" Make sure Ollama is running before using VibeFrame:"));
|
|
124
|
+
console.log();
|
|
125
|
+
console.log(chalk.cyan(" ollama serve") + chalk.dim(" # Start server"));
|
|
126
|
+
console.log(chalk.cyan(" ollama pull llama3.2") + chalk.dim(" # Download model (first time)"));
|
|
127
|
+
console.log();
|
|
128
|
+
console.log(chalk.dim(" Server should be running at http://localhost:11434"));
|
|
129
|
+
console.log();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (selectedProvider !== "ollama") {
|
|
133
|
+
const providerKey =
|
|
134
|
+
selectedProvider === "gemini"
|
|
135
|
+
? "google"
|
|
136
|
+
: selectedProvider === "claude"
|
|
137
|
+
? "anthropic"
|
|
138
|
+
: selectedProvider;
|
|
139
|
+
|
|
140
|
+
console.log(chalk.bold(`2. ${PROVIDER_NAMES[selectedProvider]} API Key`));
|
|
141
|
+
console.log(
|
|
142
|
+
chalk.dim(` You can also set ${getEnvVarName(selectedProvider)} environment variable.`)
|
|
143
|
+
);
|
|
144
|
+
console.log();
|
|
145
|
+
|
|
146
|
+
const existingKey = config.providers[providerKey as keyof typeof config.providers];
|
|
147
|
+
if (existingKey) {
|
|
148
|
+
console.log(chalk.dim(` Current: ${maskApiKey(existingKey)}`));
|
|
149
|
+
const change = await promptConfirm(chalk.cyan(" Update?"), false);
|
|
150
|
+
if (change) {
|
|
151
|
+
const newKey = await promptHidden(chalk.cyan(" Enter API key: "));
|
|
152
|
+
if (newKey.trim()) {
|
|
153
|
+
config.providers[providerKey as keyof typeof config.providers] = newKey.trim();
|
|
154
|
+
console.log(chalk.green(" ✓ Updated"));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
const newKey = await promptHidden(chalk.cyan(" Enter API key: "));
|
|
159
|
+
if (newKey.trim()) {
|
|
160
|
+
config.providers[providerKey as keyof typeof config.providers] = newKey.trim();
|
|
161
|
+
console.log(chalk.green(" ✓ Saved"));
|
|
162
|
+
} else {
|
|
163
|
+
console.log(chalk.yellow(" ⚠ Skipped (required for AI features)"));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
console.log();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Step 3: Optional providers (only in full setup mode)
|
|
170
|
+
if (fullSetup) {
|
|
171
|
+
console.log(chalk.bold("3. Additional Providers (optional)"));
|
|
172
|
+
console.log(chalk.dim(" Natural language, video generation, TTS, images, etc."));
|
|
173
|
+
console.log();
|
|
174
|
+
|
|
175
|
+
// Build list of optional providers, excluding the one already configured as primary LLM
|
|
176
|
+
const allOptionalProviders = [
|
|
177
|
+
{ key: "openai", name: "OpenAI", desc: "NL Commands, DALL-E, Whisper" },
|
|
178
|
+
{ key: "anthropic", name: "Anthropic", desc: "Claude, NL Commands" },
|
|
179
|
+
{ key: "google", name: "Google", desc: "Gemini" },
|
|
180
|
+
{ key: "xai", name: "xAI", desc: "Grok, NL Commands" },
|
|
181
|
+
{ key: "elevenlabs", name: "ElevenLabs", desc: "TTS & Voice" },
|
|
182
|
+
{ key: "runway", name: "Runway", desc: "Video Gen" },
|
|
183
|
+
{ key: "kling", name: "Kling", desc: "Video Gen" },
|
|
184
|
+
{ key: "imgbb", name: "ImgBB", desc: "Image Hosting (for Kling)" },
|
|
185
|
+
{ key: "replicate", name: "Replicate", desc: "Various" },
|
|
186
|
+
];
|
|
187
|
+
|
|
188
|
+
// Get the key of the primary LLM provider to skip it
|
|
189
|
+
const primaryProviderKey =
|
|
190
|
+
selectedProvider === "gemini"
|
|
191
|
+
? "google"
|
|
192
|
+
: selectedProvider === "claude"
|
|
193
|
+
? "anthropic"
|
|
194
|
+
: selectedProvider;
|
|
195
|
+
|
|
196
|
+
// Filter out the primary provider
|
|
197
|
+
const optionalProviders = allOptionalProviders.filter(
|
|
198
|
+
(p) => p.key !== primaryProviderKey
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
for (const provider of optionalProviders) {
|
|
202
|
+
const existing = config.providers[provider.key as keyof typeof config.providers];
|
|
203
|
+
const status = existing ? chalk.green("✓") : chalk.dim("○");
|
|
204
|
+
|
|
205
|
+
const configure = await promptConfirm(
|
|
206
|
+
chalk.cyan(` ${status} ${provider.name} ${chalk.dim(`(${provider.desc})`)}?`),
|
|
207
|
+
false
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
if (configure) {
|
|
211
|
+
const key = await promptHidden(chalk.cyan(` API key: `));
|
|
212
|
+
if (key.trim()) {
|
|
213
|
+
config.providers[provider.key as keyof typeof config.providers] = key.trim();
|
|
214
|
+
console.log(chalk.green(" ✓ Saved"));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
console.log();
|
|
219
|
+
|
|
220
|
+
// Step 4: Default aspect ratio
|
|
221
|
+
console.log(chalk.bold("4. Default Aspect Ratio"));
|
|
222
|
+
console.log();
|
|
223
|
+
|
|
224
|
+
const ratios = ["16:9", "9:16", "1:1", "4:5"] as const;
|
|
225
|
+
const ratioLabels = [
|
|
226
|
+
"16:9 (YouTube, landscape)",
|
|
227
|
+
"9:16 (TikTok, Reels, Shorts)",
|
|
228
|
+
"1:1 (Instagram, square)",
|
|
229
|
+
"4:5 (Instagram portrait)",
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
const currentRatioIndex = ratios.indexOf(config.defaults.aspectRatio);
|
|
233
|
+
const ratioIndex = await promptSelect(
|
|
234
|
+
chalk.cyan(" Select [1-4]: "),
|
|
235
|
+
ratioLabels,
|
|
236
|
+
currentRatioIndex >= 0 ? currentRatioIndex : 0
|
|
237
|
+
);
|
|
238
|
+
config.defaults.aspectRatio = ratios[ratioIndex];
|
|
239
|
+
console.log();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Save configuration
|
|
243
|
+
await saveConfig(config);
|
|
244
|
+
|
|
245
|
+
// Done
|
|
246
|
+
console.log(chalk.dim("─".repeat(40)));
|
|
247
|
+
console.log(chalk.green.bold("✓ Setup complete!"));
|
|
248
|
+
console.log();
|
|
249
|
+
console.log(chalk.dim(`Config: ${CONFIG_PATH}`));
|
|
250
|
+
console.log();
|
|
251
|
+
|
|
252
|
+
// Suggest a "try it" command based on configured providers
|
|
253
|
+
const { hasApiKey } = await import("../utils/api-key.js");
|
|
254
|
+
if (hasApiKey("GOOGLE_API_KEY")) {
|
|
255
|
+
console.log(` Try: ${chalk.cyan('vibe generate image "a sunset over mountains" -o test.png')}`);
|
|
256
|
+
} else if (hasApiKey("ELEVENLABS_API_KEY")) {
|
|
257
|
+
console.log(` Try: ${chalk.cyan('vibe generate speech "Hello world" -o hello.mp3')}`);
|
|
258
|
+
} else if (hasApiKey("OPENAI_API_KEY")) {
|
|
259
|
+
console.log(` Try: ${chalk.cyan('vibe generate image "a cute robot" -p openai -o test.png')}`);
|
|
260
|
+
} else {
|
|
261
|
+
console.log(` Try: ${chalk.cyan("vibe")} to start the interactive Agent`);
|
|
262
|
+
}
|
|
263
|
+
console.log();
|
|
264
|
+
console.log(chalk.dim(` vibe doctor Check what's ready`));
|
|
265
|
+
console.log(chalk.dim(` vibe setup --show Verify configuration`));
|
|
266
|
+
console.log(chalk.dim(` vibe setup --full Configure more providers`));
|
|
267
|
+
console.log();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Set up Claude Code integration in current directory
|
|
272
|
+
*/
|
|
273
|
+
async function setupClaudeCode(): Promise<void> {
|
|
274
|
+
const targetDir = resolve(process.cwd(), ".claude", "rules");
|
|
275
|
+
const targetFile = resolve(targetDir, "cli-reference.md");
|
|
276
|
+
|
|
277
|
+
// Check if already exists
|
|
278
|
+
let isUpdate = false;
|
|
279
|
+
try {
|
|
280
|
+
await access(targetFile);
|
|
281
|
+
isUpdate = true;
|
|
282
|
+
} catch {
|
|
283
|
+
// doesn't exist yet, fresh install
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Read the bundled CLI reference from the package
|
|
287
|
+
// In built dist: packages/cli/dist/commands/setup.js
|
|
288
|
+
// Source reference: .claude/rules/cli-reference.md (relative to repo root)
|
|
289
|
+
// We'll embed it directly since the file ships with the npm package
|
|
290
|
+
|
|
291
|
+
const cliReference = await getCliReference();
|
|
292
|
+
|
|
293
|
+
await mkdir(targetDir, { recursive: true });
|
|
294
|
+
await writeFile(targetFile, cliReference, "utf-8");
|
|
295
|
+
|
|
296
|
+
console.log();
|
|
297
|
+
console.log(chalk.green(`✓ Claude Code integration ${isUpdate ? "updated" : "set up"}!`));
|
|
298
|
+
console.log();
|
|
299
|
+
console.log(chalk.dim(` ${isUpdate ? "Updated" : "Created"}: ${targetFile}`));
|
|
300
|
+
console.log();
|
|
301
|
+
console.log(" Claude Code now knows all VibeFrame commands.");
|
|
302
|
+
console.log(" It will use " + chalk.cyan("vibe") + " commands directly without running --help.");
|
|
303
|
+
console.log();
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Get CLI reference content (embedded)
|
|
308
|
+
*/
|
|
309
|
+
async function getCliReference(): Promise<string> {
|
|
310
|
+
// Try to read from the repo's .claude/rules/ first (dev mode)
|
|
311
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
312
|
+
const __dirname = dirname(__filename);
|
|
313
|
+
|
|
314
|
+
// Walk up to find the repo root or package root
|
|
315
|
+
const possiblePaths = [
|
|
316
|
+
// Dev mode: repo root
|
|
317
|
+
resolve(__dirname, "..", "..", "..", "..", ".claude", "rules", "cli-reference.md"),
|
|
318
|
+
// Built CLI (dist/commands/setup.js): packages/cli/.claude/rules/cli-reference.md
|
|
319
|
+
resolve(__dirname, "..", "..", ".claude", "rules", "cli-reference.md"),
|
|
320
|
+
// Installed via curl (~/.vibeframe/): .claude/rules/cli-reference.md
|
|
321
|
+
resolve(__dirname, "..", "..", "..", "..", ".claude", "rules", "cli-reference.md"),
|
|
322
|
+
];
|
|
323
|
+
|
|
324
|
+
for (const p of possiblePaths) {
|
|
325
|
+
try {
|
|
326
|
+
return await readFile(p, "utf-8");
|
|
327
|
+
} catch {
|
|
328
|
+
// try next
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Fallback: generate a minimal reference
|
|
333
|
+
return generateMinimalReference();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Generate minimal CLI reference if bundled file not found
|
|
338
|
+
*/
|
|
339
|
+
function generateMinimalReference(): string {
|
|
340
|
+
return `# VibeFrame CLI Reference
|
|
341
|
+
|
|
342
|
+
> Use these commands directly — no need to run \`--help\` first.
|
|
343
|
+
|
|
344
|
+
## Quick Reference
|
|
345
|
+
|
|
346
|
+
\`\`\`bash
|
|
347
|
+
# Image
|
|
348
|
+
vibe ai image "<prompt>" -o out.png
|
|
349
|
+
vibe ai gemini-edit <image> "<instruction>" -o out.png
|
|
350
|
+
|
|
351
|
+
# Video
|
|
352
|
+
vibe ai video "<prompt>" -o out.mp4 -d 5
|
|
353
|
+
vibe ai kling "<prompt>" -o out.mp4 -d 5
|
|
354
|
+
|
|
355
|
+
# Audio
|
|
356
|
+
vibe ai tts "<text>" -o out.mp3
|
|
357
|
+
vibe ai transcribe <audio> -o out.srt
|
|
358
|
+
|
|
359
|
+
# Editing
|
|
360
|
+
vibe ai silence-cut <video> -o out.mp4
|
|
361
|
+
vibe ai caption <video> -o out.mp4 -s bold
|
|
362
|
+
vibe ai noise-reduce <input> -o out.mp4
|
|
363
|
+
vibe ai fade <video> -o out.mp4 --fade-in 1 --fade-out 1
|
|
364
|
+
vibe ai grade <video> -o out.mp4 -p cinematic-warm
|
|
365
|
+
vibe ai jump-cut <video> -o out.mp4
|
|
366
|
+
|
|
367
|
+
# Analysis
|
|
368
|
+
vibe ai analyze <source> "<prompt>"
|
|
369
|
+
vibe ai gemini-video <video> "<prompt>"
|
|
370
|
+
|
|
371
|
+
# Pipeline
|
|
372
|
+
vibe ai script-to-video "<script>" -o output-dir/ -g runway
|
|
373
|
+
vibe ai highlights <video> -d 60
|
|
374
|
+
vibe ai auto-shorts <video> -o shorts/ -n 3
|
|
375
|
+
|
|
376
|
+
# Project
|
|
377
|
+
vibe project create <name> -o project.vibe.json
|
|
378
|
+
vibe timeline add-source <project> <media>
|
|
379
|
+
vibe timeline add-clip <project> <source-id>
|
|
380
|
+
vibe export <project> -o output.mp4 -y
|
|
381
|
+
\`\`\`
|
|
382
|
+
|
|
383
|
+
Run \`vibe ai --help\` for full command list with all options.
|
|
384
|
+
`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Mask API key for display
|
|
389
|
+
*/
|
|
390
|
+
function maskApiKey(key: string): string {
|
|
391
|
+
if (key.length <= 8) return "****";
|
|
392
|
+
return `${key.slice(0, 4)}${"*".repeat(8)}${key.slice(-4)}`;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get environment variable name for a provider
|
|
397
|
+
*/
|
|
398
|
+
function getEnvVarName(provider: LLMProvider): string {
|
|
399
|
+
const envVars: Record<LLMProvider, string> = {
|
|
400
|
+
claude: "ANTHROPIC_API_KEY",
|
|
401
|
+
openai: "OPENAI_API_KEY",
|
|
402
|
+
gemini: "GOOGLE_API_KEY",
|
|
403
|
+
xai: "XAI_API_KEY",
|
|
404
|
+
ollama: "",
|
|
405
|
+
};
|
|
406
|
+
return envVars[provider];
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Show current configuration for debugging
|
|
411
|
+
*/
|
|
412
|
+
async function showConfig(): Promise<void> {
|
|
413
|
+
// Load CWD .env before showing config
|
|
414
|
+
loadEnv();
|
|
415
|
+
|
|
416
|
+
const cwdEnvPath = resolve(process.cwd(), ".env");
|
|
417
|
+
let hasCwdEnv = false;
|
|
418
|
+
try {
|
|
419
|
+
await access(cwdEnvPath);
|
|
420
|
+
hasCwdEnv = true;
|
|
421
|
+
} catch {
|
|
422
|
+
// no .env in CWD
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
console.log();
|
|
426
|
+
console.log(chalk.bold.magenta("VibeFrame Configuration"));
|
|
427
|
+
console.log(chalk.dim("─".repeat(40)));
|
|
428
|
+
console.log();
|
|
429
|
+
console.log(chalk.dim(`Config file: ${CONFIG_PATH}`));
|
|
430
|
+
if (hasCwdEnv) {
|
|
431
|
+
console.log(chalk.dim(`Project .env: ${cwdEnvPath}`));
|
|
432
|
+
}
|
|
433
|
+
console.log();
|
|
434
|
+
|
|
435
|
+
const config = await loadConfig();
|
|
436
|
+
|
|
437
|
+
// Parse .env file directly to know which keys are in it
|
|
438
|
+
let dotenvKeys: Record<string, string> = {};
|
|
439
|
+
if (hasCwdEnv) {
|
|
440
|
+
try {
|
|
441
|
+
const envContent = await readFile(cwdEnvPath, "utf-8");
|
|
442
|
+
dotenvKeys = parseDotenv(Buffer.from(envContent));
|
|
443
|
+
} catch {
|
|
444
|
+
// ignore parse errors
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (!config && !hasCwdEnv) {
|
|
449
|
+
console.log(chalk.yellow("No configuration found."));
|
|
450
|
+
console.log(chalk.dim("Run 'vibe setup' or create .env in your project directory."));
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Show LLM provider
|
|
455
|
+
if (config) {
|
|
456
|
+
console.log(chalk.bold("LLM Provider:"));
|
|
457
|
+
console.log(` ${PROVIDER_NAMES[config.llm.provider]}`);
|
|
458
|
+
console.log();
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Show API keys (masked) with accurate source detection
|
|
462
|
+
console.log(chalk.bold("API Keys:"));
|
|
463
|
+
const providerKeys = [
|
|
464
|
+
{ key: "anthropic", name: "Anthropic", env: "ANTHROPIC_API_KEY" },
|
|
465
|
+
{ key: "openai", name: "OpenAI", env: "OPENAI_API_KEY" },
|
|
466
|
+
{ key: "google", name: "Google", env: "GOOGLE_API_KEY" },
|
|
467
|
+
{ key: "xai", name: "xAI", env: "XAI_API_KEY" },
|
|
468
|
+
{ key: "elevenlabs", name: "ElevenLabs", env: "ELEVENLABS_API_KEY" },
|
|
469
|
+
{ key: "runway", name: "Runway", env: "RUNWAY_API_SECRET" },
|
|
470
|
+
{ key: "kling", name: "Kling", env: "KLING_API_KEY" },
|
|
471
|
+
{ key: "imgbb", name: "ImgBB", env: "IMGBB_API_KEY" },
|
|
472
|
+
{ key: "replicate", name: "Replicate", env: "REPLICATE_API_TOKEN" },
|
|
473
|
+
];
|
|
474
|
+
|
|
475
|
+
for (const p of providerKeys) {
|
|
476
|
+
const configValue = config?.providers[p.key as keyof typeof config.providers];
|
|
477
|
+
const dotenvValue = dotenvKeys[p.env];
|
|
478
|
+
|
|
479
|
+
if (configValue || dotenvValue) {
|
|
480
|
+
// Show effective value (config wins) and all sources
|
|
481
|
+
const sources: string[] = [];
|
|
482
|
+
if (configValue) sources.push("config");
|
|
483
|
+
if (dotenvValue) sources.push(".env");
|
|
484
|
+
const value = configValue || dotenvValue;
|
|
485
|
+
const status = chalk.green("✓");
|
|
486
|
+
console.log(` ${status} ${p.name.padEnd(12)} ${maskApiKey(value)} (${sources.join(" + ")})`);
|
|
487
|
+
} else {
|
|
488
|
+
const status = chalk.dim("○");
|
|
489
|
+
console.log(` ${status} ${p.name.padEnd(12)} ${chalk.dim("not set")}`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
console.log();
|
|
493
|
+
|
|
494
|
+
// Show defaults
|
|
495
|
+
if (config) {
|
|
496
|
+
console.log(chalk.bold("Defaults:"));
|
|
497
|
+
console.log(` Aspect Ratio: ${config.defaults.aspectRatio}`);
|
|
498
|
+
console.log(` Export Quality: ${config.defaults.exportQuality}`);
|
|
499
|
+
console.log();
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Show resolution order
|
|
503
|
+
console.log(chalk.bold("Resolution order:"));
|
|
504
|
+
console.log(chalk.dim(" 1. --api-key CLI option"));
|
|
505
|
+
console.log(chalk.dim(` 2. ${CONFIG_PATH}`));
|
|
506
|
+
console.log(chalk.dim(" 3. .env in current directory"));
|
|
507
|
+
console.log(chalk.dim(" 4. Shell environment variables"));
|
|
508
|
+
console.log();
|
|
509
|
+
}
|