@officexapp/vidfarm-devcli 0.21.10
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/.agents/skills/dollarplatoon-skill/SKILL.md +1227 -0
- package/.agents/skills/editor-capabilities/SKILL.md +182 -0
- package/.agents/skills/editor-capabilities/references/re-theme-walkthrough.md +58 -0
- package/.agents/skills/embedded-captions/CATALOG.md +93 -0
- package/.agents/skills/embedded-captions/SKILL.md +286 -0
- package/.agents/skills/embedded-captions/assets/brand/CDPR-fankit-terms.txt +35 -0
- package/.agents/skills/embedded-captions/assets/brand/cyberpunk-widths.json +115 -0
- package/.agents/skills/embedded-captions/assets/fonts/char-widths.json +2211 -0
- package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScript1.svg +242 -0
- package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScriptMed.svg +242 -0
- package/.agents/skills/embedded-captions/dna/README.md +148 -0
- package/.agents/skills/embedded-captions/dna/chrome.json +68 -0
- package/.agents/skills/embedded-captions/dna/cream.json +69 -0
- package/.agents/skills/embedded-captions/dna/documentary.json +62 -0
- package/.agents/skills/embedded-captions/dna/editorial.json +70 -0
- package/.agents/skills/embedded-captions/dna/glitch.json +82 -0
- package/.agents/skills/embedded-captions/dna/ink.json +65 -0
- package/.agents/skills/embedded-captions/dna/keynote.json +62 -0
- package/.agents/skills/embedded-captions/dna/loud.json +75 -0
- package/.agents/skills/embedded-captions/dna/neon.json +58 -0
- package/.agents/skills/embedded-captions/dna/velocity.json +89 -0
- package/.agents/skills/embedded-captions/modes/cinematic/README.md +48 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/spec.md +98 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/template.html +188 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/spec.md +134 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/template.html +179 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/spec.md +81 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/template.html +170 -0
- package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/spec.md +16 -0
- package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/template.html +226 -0
- package/.agents/skills/embedded-captions/modes/cinematic/engine.html +355 -0
- package/.agents/skills/embedded-captions/modes/standard/_anatomy.md +233 -0
- package/.agents/skills/embedded-captions/modes/standard/_motion.md +192 -0
- package/.agents/skills/embedded-captions/modes/standard/fonts/build-fonts-css.cjs +97 -0
- package/.agents/skills/embedded-captions/references/aesthetic-principles.md +168 -0
- package/.agents/skills/embedded-captions/references/anti-patterns.md +188 -0
- package/.agents/skills/embedded-captions/references/bespoke-vs-presets.md +178 -0
- package/.agents/skills/embedded-captions/references/caption-grouping.md +130 -0
- package/.agents/skills/embedded-captions/references/composition-craft.md +522 -0
- package/.agents/skills/embedded-captions/references/direction-catalog.md +138 -0
- package/.agents/skills/embedded-captions/references/example-renders/champion.html +371 -0
- package/.agents/skills/embedded-captions/references/example-renders/memory-wall.html +334 -0
- package/.agents/skills/embedded-captions/references/failure-modes.md +145 -0
- package/.agents/skills/embedded-captions/references/layout-heuristics.md +238 -0
- package/.agents/skills/embedded-captions/references/motion-vocabulary.md +148 -0
- package/.agents/skills/embedded-captions/references/rail.md +68 -0
- package/.agents/skills/embedded-captions/references/reference-bar.md +47 -0
- package/.agents/skills/embedded-captions/references/scene-types.md +94 -0
- package/.agents/skills/embedded-captions/references/test-set.md +66 -0
- package/.agents/skills/embedded-captions/references/typographic-moves.md +266 -0
- package/.agents/skills/embedded-captions/references/typography-presets.md +63 -0
- package/.agents/skills/embedded-captions/scripts/audio-envelope.cjs +95 -0
- package/.agents/skills/embedded-captions/scripts/check-occlusion.cjs +250 -0
- package/.agents/skills/embedded-captions/scripts/check-overflow.cjs +194 -0
- package/.agents/skills/embedded-captions/scripts/check-rail-climax.cjs +233 -0
- package/.agents/skills/embedded-captions/scripts/check-timing.cjs +173 -0
- package/.agents/skills/embedded-captions/scripts/fill-timings.cjs +124 -0
- package/.agents/skills/embedded-captions/scripts/fit-fonts.cjs +158 -0
- package/.agents/skills/embedded-captions/scripts/gen-stroke-path.py +46 -0
- package/.agents/skills/embedded-captions/scripts/inject-fonts.cjs +169 -0
- package/.agents/skills/embedded-captions/scripts/lib-dna.cjs +201 -0
- package/.agents/skills/embedded-captions/scripts/make-cinematic.cjs +1205 -0
- package/.agents/skills/embedded-captions/scripts/make-composition.cjs +404 -0
- package/.agents/skills/embedded-captions/scripts/make-theme.cjs +8781 -0
- package/.agents/skills/embedded-captions/scripts/matte.cjs +294 -0
- package/.agents/skills/embedded-captions/scripts/measure-layout.cjs +293 -0
- package/.agents/skills/embedded-captions/scripts/prepare.sh +39 -0
- package/.agents/skills/embedded-captions/scripts/preview-frames.cjs +268 -0
- package/.agents/skills/embedded-captions/scripts/render-and-composite.sh +509 -0
- package/.agents/skills/embedded-captions/scripts/render-theme.sh +34 -0
- package/.agents/skills/embedded-captions/scripts/safe-zones.cjs +813 -0
- package/.agents/skills/embedded-captions/scripts/transcribe.cjs +349 -0
- package/.agents/skills/embedded-captions/themes/PORTING.md +49 -0
- package/.agents/skills/embedded-captions/themes/README.md +244 -0
- package/.agents/skills/embedded-captions/themes/anchor.json +27 -0
- package/.agents/skills/embedded-captions/themes/arcade.json +51 -0
- package/.agents/skills/embedded-captions/themes/aurora.json +41 -0
- package/.agents/skills/embedded-captions/themes/biolume.json +35 -0
- package/.agents/skills/embedded-captions/themes/brush.json +74 -0
- package/.agents/skills/embedded-captions/themes/chalkboard.json +52 -0
- package/.agents/skills/embedded-captions/themes/dossier.json +56 -0
- package/.agents/skills/embedded-captions/themes/graffiti.json +62 -0
- package/.agents/skills/embedded-captions/themes/hologram.json +41 -0
- package/.agents/skills/embedded-captions/themes/inkwater.json +43 -0
- package/.agents/skills/embedded-captions/themes/laser.json +46 -0
- package/.agents/skills/embedded-captions/themes/lastpage.json +33 -0
- package/.agents/skills/embedded-captions/themes/neonsign.json +53 -0
- package/.agents/skills/embedded-captions/themes/nightcity.json +56 -0
- package/.agents/skills/embedded-captions/themes/ordnance.json +54 -0
- package/.agents/skills/embedded-captions/themes/papercut.json +37 -0
- package/.agents/skills/embedded-captions/themes/popup.json +46 -0
- package/.agents/skills/embedded-captions/themes/ransom.json +62 -0
- package/.agents/skills/embedded-captions/themes/scoreboard.json +54 -0
- package/.agents/skills/embedded-captions/themes/spectrum.json +46 -0
- package/.agents/skills/embedded-captions/themes/stardust.json +29 -0
- package/.agents/skills/embedded-captions/themes/stomp.json +43 -0
- package/.agents/skills/embedded-captions/themes/terminal.json +49 -0
- package/.agents/skills/embedded-captions/themes/thunder.json +44 -0
- package/.agents/skills/embedded-captions/themes/transit.json +44 -0
- package/.agents/skills/embedded-captions/themes/vhs.json +47 -0
- package/.agents/skills/faceless-explainer/SKILL.md +209 -0
- package/.agents/skills/faceless-explainer/references/cut-catalog.md +215 -0
- package/.agents/skills/faceless-explainer/references/motion-language.md +156 -0
- package/.agents/skills/faceless-explainer/references/story-design.md +248 -0
- package/.agents/skills/faceless-explainer/references/visual-design.md +146 -0
- package/.agents/skills/faceless-explainer/scripts/assemble-index.mjs +570 -0
- package/.agents/skills/faceless-explainer/scripts/audio.mjs +260 -0
- package/.agents/skills/faceless-explainer/scripts/build-frame.mjs +536 -0
- package/.agents/skills/faceless-explainer/scripts/captions.mjs +508 -0
- package/.agents/skills/faceless-explainer/scripts/lib/assets.mjs +55 -0
- package/.agents/skills/faceless-explainer/scripts/lib/dimensions.mjs +45 -0
- package/.agents/skills/faceless-explainer/scripts/lib/storyboard.mjs +249 -0
- package/.agents/skills/faceless-explainer/scripts/lib/tokens.mjs +204 -0
- package/.agents/skills/faceless-explainer/scripts/lib/transition-registry.mjs +38 -0
- package/.agents/skills/faceless-explainer/scripts/lib/transitions.json +71 -0
- package/.agents/skills/faceless-explainer/scripts/transitions.mjs +320 -0
- package/.agents/skills/faceless-explainer/sub-agents/frame-worker.md +75 -0
- package/.agents/skills/farmville-saas-ux/SKILL.md +156 -0
- package/.agents/skills/farmville-saas-ux/assets/starter.html +294 -0
- package/.agents/skills/farmville-saas-ux/references/components.md +340 -0
- package/.agents/skills/farmville-saas-ux/references/porting-guide.md +121 -0
- package/.agents/skills/farmville-saas-ux/references/tokens.md +271 -0
- package/.agents/skills/flockposter/LICENSE +17 -0
- package/.agents/skills/flockposter/README.md +72 -0
- package/.agents/skills/flockposter/SKILL.md +562 -0
- package/.agents/skills/flockposter/examples/cli-instagram-reel.sh +21 -0
- package/.agents/skills/flockposter/examples/cli-multi-platform.json +69 -0
- package/.agents/skills/flockposter/examples/cli-tiktok-upload-only.sh +22 -0
- package/.agents/skills/flockposter/examples/cli-x-thread.sh +17 -0
- package/.agents/skills/flockposter/examples/cli-youtube-short.sh +21 -0
- package/.agents/skills/flockposter/examples/public-api-instagram-reel.json +28 -0
- package/.agents/skills/general-video/SKILL.md +143 -0
- package/.agents/skills/hyperframes/SKILL.md +160 -0
- package/.agents/skills/hyperframes-animation/SKILL.md +84 -0
- package/.agents/skills/hyperframes-animation/adapters/animate-text.md +64 -0
- package/.agents/skills/hyperframes-animation/adapters/animejs.md +114 -0
- package/.agents/skills/hyperframes-animation/adapters/css-animations.md +143 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-easing-and-stagger.md +118 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-timeline-and-labels.md +96 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-transforms-and-perf.md +96 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap.md +105 -0
- package/.agents/skills/hyperframes-animation/adapters/html-in-canvas-patterns.md +507 -0
- package/.agents/skills/hyperframes-animation/adapters/lottie.md +117 -0
- package/.agents/skills/hyperframes-animation/adapters/three.md +131 -0
- package/.agents/skills/hyperframes-animation/adapters/typegpu.md +178 -0
- package/.agents/skills/hyperframes-animation/adapters/waapi.md +101 -0
- package/.agents/skills/hyperframes-animation/blueprints/comparison-split.md +27 -0
- package/.agents/skills/hyperframes-animation/blueprints/constellation-hub.md +44 -0
- package/.agents/skills/hyperframes-animation/blueprints/cta-morph-press.md +28 -0
- package/.agents/skills/hyperframes-animation/blueprints/cursor-ui-demo.md +57 -0
- package/.agents/skills/hyperframes-animation/blueprints/dataviz-countup.md +46 -0
- package/.agents/skills/hyperframes-animation/blueprints/device-surface-showcase.md +53 -0
- package/.agents/skills/hyperframes-animation/blueprints/grid-card-assemble.md +66 -0
- package/.agents/skills/hyperframes-animation/blueprints/kinetic-type-beats.md +78 -0
- package/.agents/skills/hyperframes-animation/blueprints/logo-assemble-lockup.md +69 -0
- package/.agents/skills/hyperframes-animation/blueprints/overwhelm-surround.md +28 -0
- package/.agents/skills/hyperframes-animation/blueprints/spatial-pan-stations.md +37 -0
- package/.agents/skills/hyperframes-animation/blueprints/ticker-takeover.md +29 -0
- package/.agents/skills/hyperframes-animation/blueprints/titlecard-reveal.md +42 -0
- package/.agents/skills/hyperframes-animation/blueprints/typewriter-reveal.md +51 -0
- package/.agents/skills/hyperframes-animation/blueprints/video-text-pivot.md +30 -0
- package/.agents/skills/hyperframes-animation/blueprints-index.md +146 -0
- package/.agents/skills/hyperframes-animation/examples/assets/avatars/02.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/github.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/nvidia.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/visa.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/zoominfo.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/brand-reveal-assemble-zoom.html +382 -0
- package/.agents/skills/hyperframes-animation/examples/comparison-split-cards.html +649 -0
- package/.agents/skills/hyperframes-animation/examples/concept-demo-decode-pan.html +520 -0
- package/.agents/skills/hyperframes-animation/examples/cta-morph-press.html +468 -0
- package/.agents/skills/hyperframes-animation/examples/cta-orbit-collapse.html +1298 -0
- package/.agents/skills/hyperframes-animation/examples/demo-page-scroll-spotlight.html +759 -0
- package/.agents/skills/hyperframes-animation/examples/hook-counter-burst.html +729 -0
- package/.agents/skills/hyperframes-animation/examples/messaging-multi-phrase.html +352 -0
- package/.agents/skills/hyperframes-animation/examples/metric-video-text-pivot.html +779 -0
- package/.agents/skills/hyperframes-animation/examples/problem-mockup-overwhelm.html +1374 -0
- package/.agents/skills/hyperframes-animation/examples/proof-logo-chain.html +861 -0
- package/.agents/skills/hyperframes-animation/examples/takeover-ticker-displace.html +347 -0
- package/.agents/skills/hyperframes-animation/examples/workflow-approve-press.html +606 -0
- package/.agents/skills/hyperframes-animation/rules/3d-page-scroll.md +227 -0
- package/.agents/skills/hyperframes-animation/rules/3d-text-depth-layers.md +297 -0
- package/.agents/skills/hyperframes-animation/rules/ai-tracking-box.md +382 -0
- package/.agents/skills/hyperframes-animation/rules/ambient-glow-bloom.md +305 -0
- package/.agents/skills/hyperframes-animation/rules/asr-keyword-glow.md +286 -0
- package/.agents/skills/hyperframes-animation/rules/avatar-cloud-network.md +371 -0
- package/.agents/skills/hyperframes-animation/rules/camera-cursor-tracking.md +246 -0
- package/.agents/skills/hyperframes-animation/rules/card-morph-anchor.md +267 -0
- package/.agents/skills/hyperframes-animation/rules/center-outward-expansion.md +227 -0
- package/.agents/skills/hyperframes-animation/rules/context-sensitive-cursor.md +257 -0
- package/.agents/skills/hyperframes-animation/rules/coordinate-target-zoom.md +332 -0
- package/.agents/skills/hyperframes-animation/rules/counting-dynamic-scale.md +283 -0
- package/.agents/skills/hyperframes-animation/rules/css-marker-patterns.md +373 -0
- package/.agents/skills/hyperframes-animation/rules/cursor-click-ripple.md +262 -0
- package/.agents/skills/hyperframes-animation/rules/depth-of-field-blur.md +313 -0
- package/.agents/skills/hyperframes-animation/rules/depth-scatter-assemble.md +303 -0
- package/.agents/skills/hyperframes-animation/rules/discrete-text-sequence.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +307 -0
- package/.agents/skills/hyperframes-animation/rules/gsap-effects.md +299 -0
- package/.agents/skills/hyperframes-animation/rules/hacker-flip-3d.md +223 -0
- package/.agents/skills/hyperframes-animation/rules/kinetic-beat-slam.md +183 -0
- package/.agents/skills/hyperframes-animation/rules/motion-blur-streak.md +328 -0
- package/.agents/skills/hyperframes-animation/rules/multi-phase-camera.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/orbit-3d-entry.md +301 -0
- package/.agents/skills/hyperframes-animation/rules/physics-press-reaction.md +350 -0
- package/.agents/skills/hyperframes-animation/rules/press-release-spring.md +296 -0
- package/.agents/skills/hyperframes-animation/rules/reactive-displacement.md +277 -0
- package/.agents/skills/hyperframes-animation/rules/scale-swap-transition.md +298 -0
- package/.agents/skills/hyperframes-animation/rules/sine-wave-loop.md +278 -0
- package/.agents/skills/hyperframes-animation/rules/split-tilt-cards.md +277 -0
- package/.agents/skills/hyperframes-animation/rules/spring-pop-entrance.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/stat-bars-and-fills.md +156 -0
- package/.agents/skills/hyperframes-animation/rules/svg-icon-enrichment.md +329 -0
- package/.agents/skills/hyperframes-animation/rules/svg-path-draw.md +274 -0
- package/.agents/skills/hyperframes-animation/rules/vertical-spring-ticker.md +239 -0
- package/.agents/skills/hyperframes-animation/rules/viewport-change.md +349 -0
- package/.agents/skills/hyperframes-animation/rules-index.md +86 -0
- package/.agents/skills/hyperframes-animation/scripts/animation-map.mjs +606 -0
- package/.agents/skills/hyperframes-animation/scripts/package-loader.mjs +288 -0
- package/.agents/skills/hyperframes-animation/scripts/package-loader.test.mjs +62 -0
- package/.agents/skills/hyperframes-animation/techniques.md +507 -0
- package/.agents/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +167 -0
- package/.agents/skills/hyperframes-animation/transitions/catalog.md +127 -0
- package/.agents/skills/hyperframes-animation/transitions/css-3d.md +12 -0
- package/.agents/skills/hyperframes-animation/transitions/css-blur.md +51 -0
- package/.agents/skills/hyperframes-animation/transitions/css-cover.md +43 -0
- package/.agents/skills/hyperframes-animation/transitions/css-destruction.md +95 -0
- package/.agents/skills/hyperframes-animation/transitions/css-dissolve.md +66 -0
- package/.agents/skills/hyperframes-animation/transitions/css-distortion.md +45 -0
- package/.agents/skills/hyperframes-animation/transitions/css-grid.md +10 -0
- package/.agents/skills/hyperframes-animation/transitions/css-light.md +49 -0
- package/.agents/skills/hyperframes-animation/transitions/css-mechanical.md +30 -0
- package/.agents/skills/hyperframes-animation/transitions/css-other.md +25 -0
- package/.agents/skills/hyperframes-animation/transitions/css-push.md +41 -0
- package/.agents/skills/hyperframes-animation/transitions/css-radial.md +37 -0
- package/.agents/skills/hyperframes-animation/transitions/css-scale.md +24 -0
- package/.agents/skills/hyperframes-animation/transitions/overview.md +153 -0
- package/.agents/skills/hyperframes-cli/SKILL.md +113 -0
- package/.agents/skills/hyperframes-cli/references/doctor-browser.md +45 -0
- package/.agents/skills/hyperframes-cli/references/init-and-scaffold.md +55 -0
- package/.agents/skills/hyperframes-cli/references/lambda.md +132 -0
- package/.agents/skills/hyperframes-cli/references/lint-validate-inspect.md +121 -0
- package/.agents/skills/hyperframes-cli/references/preview-render.md +149 -0
- package/.agents/skills/hyperframes-cli/references/upgrade-info-misc.md +75 -0
- package/.agents/skills/hyperframes-core/SKILL.md +78 -0
- package/.agents/skills/hyperframes-core/references/composition-patterns.md +263 -0
- package/.agents/skills/hyperframes-core/references/data-attributes.md +70 -0
- package/.agents/skills/hyperframes-core/references/determinism-rules.md +68 -0
- package/.agents/skills/hyperframes-core/references/full-screen-motion.md +62 -0
- package/.agents/skills/hyperframes-core/references/minimal-composition.md +66 -0
- package/.agents/skills/hyperframes-core/references/script-format.md +49 -0
- package/.agents/skills/hyperframes-core/references/storyboard-format.md +95 -0
- package/.agents/skills/hyperframes-core/references/sub-compositions.md +237 -0
- package/.agents/skills/hyperframes-core/references/subagent-dispatch.md +41 -0
- package/.agents/skills/hyperframes-core/references/tailwind.md +125 -0
- package/.agents/skills/hyperframes-core/references/tracks-and-clips.md +76 -0
- package/.agents/skills/hyperframes-core/references/variables-and-media.md +90 -0
- package/.agents/skills/hyperframes-creative/SKILL.md +70 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/FRAME.md +289 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/caption-skin.html +221 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/FRAME.md +275 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/frame-showcase.html +1347 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/FRAME.md +307 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/caption-skin.html +223 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/frame-showcase.html +1372 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/FRAME.md +275 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/caption-skin.html +230 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/frame-showcase.html +1140 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/FRAME.md +284 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/caption-skin.html +225 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/frame-showcase.html +1166 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/FRAME.md +284 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/frame-showcase.html +1465 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/FRAME.md +278 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/caption-skin.html +222 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/frame-showcase.html +1263 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/FRAME.md +277 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/frame-showcase.html +1439 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/FRAME.md +265 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/caption-skin.html +238 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/FRAME.md +314 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/caption-skin.html +226 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/frame-showcase.html +1268 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/FRAME.md +333 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/caption-skin.html +227 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/frame-showcase.html +1330 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/FRAME.md +274 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/caption-skin.html +230 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/frame-showcase.html +1444 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/FRAME.md +265 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/caption-skin.html +223 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/frame-showcase.html +1273 -0
- package/.agents/skills/hyperframes-creative/palettes/bold-energetic.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/clean-corporate.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/dark-premium.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/jewel-rich.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/monochrome.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/nature-earth.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/neon-electric.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/pastel-soft.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/warm-editorial.md +14 -0
- package/.agents/skills/hyperframes-creative/references/audio-reactive.md +76 -0
- package/.agents/skills/hyperframes-creative/references/beat-direction.md +164 -0
- package/.agents/skills/hyperframes-creative/references/composition-patterns.md +199 -0
- package/.agents/skills/hyperframes-creative/references/data-in-motion.md +19 -0
- package/.agents/skills/hyperframes-creative/references/design-adherence.md +19 -0
- package/.agents/skills/hyperframes-creative/references/design-picker.md +123 -0
- package/.agents/skills/hyperframes-creative/references/design-spec.md +55 -0
- package/.agents/skills/hyperframes-creative/references/house-style.md +73 -0
- package/.agents/skills/hyperframes-creative/references/motion-principles.md +150 -0
- package/.agents/skills/hyperframes-creative/references/narration.md +92 -0
- package/.agents/skills/hyperframes-creative/references/prompt-expansion.md +68 -0
- package/.agents/skills/hyperframes-creative/references/typography.md +218 -0
- package/.agents/skills/hyperframes-creative/references/video-composition.md +63 -0
- package/.agents/skills/hyperframes-creative/references/visual-styles.md +457 -0
- package/.agents/skills/hyperframes-creative/scripts/contrast-report.mjs +353 -0
- package/.agents/skills/hyperframes-creative/scripts/extract-audio-data.py +188 -0
- package/.agents/skills/hyperframes-creative/scripts/package-loader.mjs +288 -0
- package/.agents/skills/hyperframes-creative/scripts/package-loader.test.mjs +62 -0
- package/.agents/skills/hyperframes-creative/templates/design-picker.html +1432 -0
- package/.agents/skills/hyperframes-keyframes/SKILL.md +237 -0
- package/.agents/skills/hyperframes-keyframes/agents/openai.yaml +4 -0
- package/.agents/skills/hyperframes-keyframes/references/keyframe-patterns.md +106 -0
- package/.agents/skills/motion-graphics/SKILL.md +172 -0
- package/.agents/skills/motion-graphics/agents/builder.md +40 -0
- package/.agents/skills/motion-graphics/agents/director.md +53 -0
- package/.agents/skills/motion-graphics/agents/finalize.md +17 -0
- package/.agents/skills/motion-graphics/catalog-map.md +40 -0
- package/.agents/skills/motion-graphics/categories/asset-fusion/module.md +37 -0
- package/.agents/skills/motion-graphics/categories/charts/module.md +21 -0
- package/.agents/skills/motion-graphics/categories/kinetic-type/module.md +19 -0
- package/.agents/skills/motion-graphics/categories/logo-reveal/module.md +17 -0
- package/.agents/skills/motion-graphics/categories/lower-thirds/module.md +16 -0
- package/.agents/skills/motion-graphics/categories/maps/bake-basemap.mjs +273 -0
- package/.agents/skills/motion-graphics/categories/maps/module.md +61 -0
- package/.agents/skills/motion-graphics/categories/news/module.md +56 -0
- package/.agents/skills/motion-graphics/categories/stat/module.md +21 -0
- package/.agents/skills/motion-graphics/categories/tweet/module.md +16 -0
- package/.agents/skills/motion-graphics/categories/webpage/module.md +21 -0
- package/.agents/skills/motion-graphics/grounding/PROTOCOL.md +64 -0
- package/.agents/skills/motion-graphics/grounding/locate.mjs +227 -0
- package/.agents/skills/motion-graphics/phases/source/guide.md +21 -0
- package/.agents/skills/motion-graphics/references/builder-contract.md +38 -0
- package/.agents/skills/motion-graphics/references/motion-vocabulary.md +43 -0
- package/.agents/skills/motion-graphics/references/shot-plan-ir.md +54 -0
- package/.agents/skills/motion-graphics/samples/asset-fusion/_ref-circle-highlight.html +306 -0
- package/.agents/skills/music/SKILL.md +416 -0
- package/.agents/skills/music/references/api_reference.md +519 -0
- package/.agents/skills/music/references/installation.md +65 -0
- package/.agents/skills/product-launch-video/SKILL.md +208 -0
- package/.agents/skills/product-launch-video/references/cut-catalog.md +220 -0
- package/.agents/skills/product-launch-video/references/motion-language.md +156 -0
- package/.agents/skills/product-launch-video/references/story-design.md +373 -0
- package/.agents/skills/product-launch-video/references/visual-design.md +126 -0
- package/.agents/skills/product-launch-video/scripts/assemble-index.mjs +570 -0
- package/.agents/skills/product-launch-video/scripts/audio.mjs +260 -0
- package/.agents/skills/product-launch-video/scripts/build-frame.mjs +536 -0
- package/.agents/skills/product-launch-video/scripts/captions.mjs +508 -0
- package/.agents/skills/product-launch-video/scripts/lib/assets.mjs +55 -0
- package/.agents/skills/product-launch-video/scripts/lib/dimensions.mjs +45 -0
- package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.mjs +36 -0
- package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.test.mjs +76 -0
- package/.agents/skills/product-launch-video/scripts/lib/storyboard.mjs +249 -0
- package/.agents/skills/product-launch-video/scripts/lib/tokens.mjs +204 -0
- package/.agents/skills/product-launch-video/scripts/lib/transition-registry.mjs +38 -0
- package/.agents/skills/product-launch-video/scripts/lib/transitions.json +71 -0
- package/.agents/skills/product-launch-video/scripts/stage-assets.mjs +39 -0
- package/.agents/skills/product-launch-video/scripts/transitions.mjs +327 -0
- package/.agents/skills/product-launch-video/sub-agents/frame-worker.md +75 -0
- package/.agents/skills/slideshow/SKILL.md +550 -0
- package/.agents/skills/slideshow/references/standalone-harness.md +1020 -0
- package/.agents/skills/talking-head-recut/NOTICE.md +39 -0
- package/.agents/skills/talking-head-recut/SKILL.md +1195 -0
- package/.agents/skills/talking-head-recut/assets/vendor/gsap.min.js +10 -0
- package/.agents/skills/talking-head-recut/references/DESIGN_INDEX.md +145 -0
- package/.agents/skills/talking-head-recut/references/frames/clean.html +92 -0
- package/.agents/skills/talking-head-recut/references/frames/hairline.html +171 -0
- package/.agents/skills/talking-head-recut/references/frames/polaroid.html +131 -0
- package/.agents/skills/talking-head-recut/references/layouts/overlay.html +164 -0
- package/.agents/skills/talking-head-recut/references/layouts/pip.html +143 -0
- package/.agents/skills/talking-head-recut/references/layouts/split.html +121 -0
- package/.agents/skills/talking-head-recut/references/layouts/stack.html +109 -0
- package/.agents/skills/talking-head-recut/references/styles/academic.html +172 -0
- package/.agents/skills/talking-head-recut/references/styles/audit.html +170 -0
- package/.agents/skills/talking-head-recut/references/styles/editorial.html +189 -0
- package/.agents/skills/talking-head-recut/references/styles/geom.html +181 -0
- package/.agents/skills/talking-head-recut/references/styles/minimal.html +130 -0
- package/.agents/skills/talking-head-recut/references/styles/spotlight.html +142 -0
- package/.agents/skills/talking-head-recut/references/styles/swiss.html +188 -0
- package/.agents/skills/talking-head-recut/references/styles/terminal.html +196 -0
- package/.agents/skills/talking-head-recut/references/styles/whiteboard.html +170 -0
- package/.agents/skills/talking-head-recut/references/styles/xhs.html +206 -0
- package/.agents/skills/text-to-speech/SKILL.md +226 -0
- package/.agents/skills/text-to-speech/references/installation.md +90 -0
- package/.agents/skills/text-to-speech/references/streaming.md +307 -0
- package/.agents/skills/text-to-speech/references/voice-settings.md +115 -0
- package/.agents/skills/vidfarm-director/SKILL.md +179 -0
- package/.agents/skills/vidfarm-director/recipes/find-and-fork-template.md +16 -0
- package/.agents/skills/vidfarm-director/recipes/local-edit-render-approve.md +13 -0
- package/.agents/skills/vidfarm-director/recipes/onboard-a-new-director.md +13 -0
- package/.agents/skills/vidfarm-director/recipes/retheme-template.md +17 -0
- package/.agents/skills/vidfarm-director/references/assets-and-sourcing.md +117 -0
- package/.agents/skills/vidfarm-director/references/automation-and-local-dev.md +276 -0
- package/.agents/skills/vidfarm-director/references/core-workflows.md +301 -0
- package/.agents/skills/vidfarm-director/references/editor-workflows.md +367 -0
- package/.agents/skills/vidfarm-director/references/onboarding.md +28 -0
- package/.agents/skills/vidfarm-director/references/primitives.md +307 -0
- package/.agents/skills/vidfarm-director/references/rest-api.md +84 -0
- package/.agents/skills/vidfarm-media/SKILL.md +158 -0
- package/.agents/skills/vidfarm-media/references/tts.md +111 -0
- package/.agents/skills/vidfarm-media/scripts/audio.mjs +628 -0
- package/.agents/skills/vidfarm-media/scripts/wait-bgm.mjs +31 -0
- package/.agents/skills/website-to-video/SKILL.md +145 -0
- package/.agents/skills/website-to-video/assets/sfx/CREDITS.md +35 -0
- package/.agents/skills/website-to-video/assets/sfx/manifest.json +97 -0
- package/.agents/skills/website-to-video/references/beat-builder-guide.md +263 -0
- package/.agents/skills/website-to-video/references/capabilities.md +713 -0
- package/.agents/skills/website-to-video/references/step-0-capture.md +55 -0
- package/.agents/skills/website-to-video/references/step-1-design.md +333 -0
- package/.agents/skills/website-to-video/references/step-2-brief.md +178 -0
- package/.agents/skills/website-to-video/references/step-3-storyboard.md +572 -0
- package/.agents/skills/website-to-video/references/step-4-vo.md +225 -0
- package/.agents/skills/website-to-video/references/step-5-build.md +483 -0
- package/.agents/skills/website-to-video/references/step-6-validate.md +341 -0
- package/.agents/skills/website-to-video/scripts/w2h-verify.mjs +759 -0
- package/README.md +97 -0
- package/SKILL.director.md +1644 -0
- package/SKILL.md +83 -0
- package/demo/README.md +28 -0
- package/demo/dist/app.css +1 -0
- package/demo/dist/app.js +968 -0
- package/demo/dist/chunks/chunk-3OT2D42H.js +1 -0
- package/demo/dist/chunks/chunk-DXB73IDG.js +1 -0
- package/demo/dist/chunks/domEditingLayers-AT7G6F4L-ZTHJHB7R.js +1 -0
- package/demo/dist/chunks/hyperframes-player-7HKH6NSO.js +459 -0
- package/demo/dist/chunks/lib-XAQ37YOE.js +1 -0
- package/demo/dist/chunks/src-TJ2QYA4U.js +207 -0
- package/demo/dist/favicon.ico +0 -0
- package/demo/dist/icons/timeline/audio.svg +7 -0
- package/demo/dist/icons/timeline/captions.svg +5 -0
- package/demo/dist/icons/timeline/composition.svg +12 -0
- package/demo/dist/icons/timeline/image.svg +18 -0
- package/demo/dist/icons/timeline/music.svg +10 -0
- package/demo/dist/icons/timeline/text.svg +3 -0
- package/demo/dist/index.html +16 -0
- package/dist/src/cli.js +7258 -0
- package/dist/src/devcli/auth-store.js +67 -0
- package/dist/src/devcli/captions.js +310 -0
- package/dist/src/devcli/clip-store.js +368 -0
- package/dist/src/devcli/clips.js +1138 -0
- package/dist/src/devcli/composition-edit.js +1292 -0
- package/dist/src/devcli/cost-mode.js +149 -0
- package/dist/src/devcli/doctor.js +192 -0
- package/dist/src/devcli/hyperframes-cli.js +118 -0
- package/dist/src/devcli/local-backend.js +167 -0
- package/dist/src/devcli/local-frontend-server.js +681 -0
- package/dist/src/devcli/local-render.js +136 -0
- package/dist/src/devcli/skills.js +476 -0
- package/dist/src/devcli/speech.js +178 -0
- package/dist/src/devcli/stills.js +249 -0
- package/dist/src/devcli/telemetry.js +236 -0
- package/dist/src/devcli/timeline-edit.js +490 -0
- package/dist/src/devcli/transitions.js +205 -0
- package/dist/src/hyperframes/composition.js +780 -0
- package/dist/src/lib/crypto.js +45 -0
- package/dist/src/lib/dev-log.js +54 -0
- package/dist/src/lib/display-name.js +11 -0
- package/dist/src/lib/ids.js +24 -0
- package/dist/src/lib/images.js +19 -0
- package/dist/src/lib/json.js +15 -0
- package/dist/src/lib/package-root.js +47 -0
- package/dist/src/lib/render-media-prep.js +293 -0
- package/dist/src/lib/template-paths.js +28 -0
- package/dist/src/lib/time.js +7 -0
- package/dist/src/lib/url-clean.js +85 -0
- package/dist/src/services/captions.js +123 -0
- package/dist/src/services/clip-curation/cost.js +116 -0
- package/dist/src/services/clip-curation/ffmpeg.js +352 -0
- package/dist/src/services/clip-curation/gemini.js +418 -0
- package/dist/src/services/clip-curation/hunt.js +470 -0
- package/dist/src/services/clip-curation/index.js +19 -0
- package/dist/src/services/clip-curation/local-agent.js +248 -0
- package/dist/src/services/clip-curation/media-select.js +152 -0
- package/dist/src/services/clip-curation/presets.js +20 -0
- package/dist/src/services/clip-curation/presets.v1.json +59 -0
- package/dist/src/services/clip-curation/query.js +167 -0
- package/dist/src/services/clip-curation/refine.js +165 -0
- package/dist/src/services/clip-curation/scan.js +189 -0
- package/dist/src/services/clip-curation/source-naming.js +131 -0
- package/dist/src/services/clip-curation/taxonomy.js +73 -0
- package/dist/src/services/clip-curation/taxonomy.v1.json +102 -0
- package/dist/src/services/clip-curation/types.js +7 -0
- package/dist/src/services/composition-lint.js +199 -0
- package/dist/src/services/provider-errors.js +128 -0
- package/dist/src/services/speech.js +629 -0
- package/package.json +154 -0
- package/public/assets/discover-client-app.js +1 -0
- package/public/assets/favicon.ico +0 -0
- package/public/assets/file-directory-app.js +89 -0
- package/public/assets/homepage-app.js +54 -0
- package/public/assets/homepage-client-app.js +80 -0
- package/public/assets/landing-page-client-app.js +87 -0
- package/public/assets/logo-vidfarm.png +0 -0
- package/public/assets/page-runtime-client-app.js +94 -0
- package/public/assets/placeholders/scene-placeholder.png +0 -0
- package/public/serve-shells/editor.html +3146 -0
- package/public/serve-shells/library-files.html +3450 -0
- package/public/serve-shells/library-raws.html +4404 -0
- package/public/serve-shells/tools-clipper.html +3991 -0
- package/public/serve-shells/tools-image.html +5584 -0
- package/public/serve-shells/tools-video.html +4404 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Cost mode — the devcli's money-saving preference. Vidfarm is founder-friendly:
|
|
2
|
+
// most work can be done on FREE local compute (local render, local TTS/STT,
|
|
3
|
+
// local greenscreen/matting, the raw-clip + HTML-hyperframe "paintbrushes")
|
|
4
|
+
// before any billed AI credit is spent on the account's provider keys / wallet.
|
|
5
|
+
//
|
|
6
|
+
// The mode is a single durable preference the human picks ONCE (ideally asked by
|
|
7
|
+
// their AI agent up front), then every billed command respects it:
|
|
8
|
+
// - minimize : never burn AI credits by surprise. Prefer free local engines;
|
|
9
|
+
// refuse billed cloud/AI ops unless the user re-confirms (--yes).
|
|
10
|
+
// - hybrid : free where it's free, spend on AI only where it clearly wins.
|
|
11
|
+
// (default recommendation.) Billed ops run but print a cost line.
|
|
12
|
+
// - pure-ai : best-quality; AI image/video/voice/music used freely. Billed
|
|
13
|
+
// ops run; cost is still surfaced.
|
|
14
|
+
//
|
|
15
|
+
// This module lives in the CLI's static import closure and is BACKEND-FREE (only
|
|
16
|
+
// Node built-ins) so it ships in the public cloud-only package.
|
|
17
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
import { resolveDevcliHome } from "./auth-store.js";
|
|
20
|
+
export const COST_MODES = ["minimize", "hybrid", "pure-ai"];
|
|
21
|
+
/** What we assume when nothing is set. Hybrid is the founder-friendly middle,
|
|
22
|
+
* but callers can tell it apart from an explicit choice via `isSet`. */
|
|
23
|
+
export const DEFAULT_COST_MODE = "hybrid";
|
|
24
|
+
function costModeFilePath(home) {
|
|
25
|
+
return path.join(resolveDevcliHome(home), "cost-mode.json");
|
|
26
|
+
}
|
|
27
|
+
/** Normalize loose spellings ("min", "cheap", "pureai", "best") to a CostMode. */
|
|
28
|
+
export function normalizeCostMode(raw) {
|
|
29
|
+
const v = (raw ?? "").trim().toLowerCase().replace(/[\s_]+/g, "-");
|
|
30
|
+
if (!v)
|
|
31
|
+
return null;
|
|
32
|
+
if (["minimize", "min", "cheap", "thrift", "budget", "save", "free"].includes(v))
|
|
33
|
+
return "minimize";
|
|
34
|
+
if (["hybrid", "mixed", "balanced", "smart", "default"].includes(v))
|
|
35
|
+
return "hybrid";
|
|
36
|
+
if (["pure-ai", "pureai", "ai", "best", "best-quality", "premium", "max"].includes(v))
|
|
37
|
+
return "pure-ai";
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
/** Read the persisted cost mode, or null if absent/unparseable. */
|
|
41
|
+
export function readStoredCostMode(home) {
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(readFileSync(costModeFilePath(home), "utf8"));
|
|
44
|
+
const mode = normalizeCostMode(parsed?.mode);
|
|
45
|
+
if (mode)
|
|
46
|
+
return { mode, note: parsed.note ?? null, savedAt: String(parsed.savedAt ?? "") };
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Persist the cost mode. Returns the file path written. */
|
|
54
|
+
export function writeStoredCostMode(mode, savedAt, note, home) {
|
|
55
|
+
const dir = resolveDevcliHome(home);
|
|
56
|
+
mkdirSync(dir, { recursive: true });
|
|
57
|
+
const file = costModeFilePath(home);
|
|
58
|
+
const payload = { mode, note: note ?? null, savedAt };
|
|
59
|
+
writeFileSync(file, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
60
|
+
return file;
|
|
61
|
+
}
|
|
62
|
+
/** Delete the persisted cost mode. Returns true if a file was removed. */
|
|
63
|
+
export function clearStoredCostMode(home) {
|
|
64
|
+
const file = costModeFilePath(home);
|
|
65
|
+
if (!existsSync(file))
|
|
66
|
+
return false;
|
|
67
|
+
rmSync(file, { force: true });
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Resolve the effective cost mode for a command run. Precedence:
|
|
72
|
+
* --cost-mode flag → VIDFARM_COST_MODE env → stored preference → default.
|
|
73
|
+
* `isSet` is false only for the last case, so callers can nudge the agent to
|
|
74
|
+
* ASK the user and record a choice the first time real money is on the line.
|
|
75
|
+
*/
|
|
76
|
+
export function resolveCostMode(values) {
|
|
77
|
+
const flag = normalizeCostMode(values["cost-mode"]);
|
|
78
|
+
if (flag)
|
|
79
|
+
return { mode: flag, isSet: true, source: "flag" };
|
|
80
|
+
const env = normalizeCostMode(process.env.VIDFARM_COST_MODE);
|
|
81
|
+
if (env)
|
|
82
|
+
return { mode: env, isSet: true, source: "env" };
|
|
83
|
+
const stored = readStoredCostMode(values.home);
|
|
84
|
+
if (stored)
|
|
85
|
+
return { mode: stored.mode, isSet: true, source: "stored" };
|
|
86
|
+
return { mode: DEFAULT_COST_MODE, isSet: false, source: "default" };
|
|
87
|
+
}
|
|
88
|
+
export const COST_MODE_BLURB = {
|
|
89
|
+
minimize: "Minimize costs — stay on FREE local compute wherever possible (local render, " +
|
|
90
|
+
"local TTS/STT, local greenscreen/matting, reused clips + HTML motion). Billed " +
|
|
91
|
+
"cloud/AI generation is refused unless you re-confirm it (--yes).",
|
|
92
|
+
hybrid: "Hybrid (recommended) — free where it's free, spend AI credits only where they " +
|
|
93
|
+
"clearly win (a hero shot, a voice you can't fake locally). Billed ops run but " +
|
|
94
|
+
"each prints its cost so nothing is a surprise.",
|
|
95
|
+
"pure-ai": "Pure AI — best quality; AI image/video/voice/music used freely. Billed ops run " +
|
|
96
|
+
"without gating; cost is still shown."
|
|
97
|
+
};
|
|
98
|
+
/** One short human line summarizing the active mode. */
|
|
99
|
+
export function costModeSummaryLine(resolved) {
|
|
100
|
+
const setNote = resolved.isSet ? `set via ${resolved.source}` : "NOT set — assuming hybrid";
|
|
101
|
+
return `cost mode: ${resolved.mode} (${setNote})`;
|
|
102
|
+
}
|
|
103
|
+
/** The 3-line "explain it simply" block an agent should relay to the user. */
|
|
104
|
+
export function costModeExplainer() {
|
|
105
|
+
return [
|
|
106
|
+
"How much do you want Vidfarm to spend on AI credits?",
|
|
107
|
+
" • minimize — cheapest: free local compute, no surprise AI spend.",
|
|
108
|
+
" • hybrid — recommended: free where free, pay AI only where it clearly wins.",
|
|
109
|
+
" • pure-ai — best quality: use AI image/video/voice/music freely."
|
|
110
|
+
].join("\n");
|
|
111
|
+
}
|
|
112
|
+
export class CostModeBlockedError extends Error {
|
|
113
|
+
constructor(message) {
|
|
114
|
+
super(message);
|
|
115
|
+
this.name = "CostModeBlockedError";
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Gate a BILLED cloud/AI operation against the active cost mode. Call this at the
|
|
120
|
+
* top of any command that spends the account's wallet or provider-key AI credits
|
|
121
|
+
* (cloud render, generate, music, cloud TTS/STT, inpaint, overlays, cloud
|
|
122
|
+
* greenscreen, decompose, etc.).
|
|
123
|
+
*
|
|
124
|
+
* - minimize: throws unless `yes` is set — the agent must confirm with the user
|
|
125
|
+
* (or use the free local alternative named in `freeAlternative`).
|
|
126
|
+
* - hybrid / pure-ai: allowed; prints a one-line cost notice (unless json).
|
|
127
|
+
* - unset: allowed like hybrid, but prints a "no preference set — ask the user"
|
|
128
|
+
* nudge once so the default posture really is "ask before spending."
|
|
129
|
+
*/
|
|
130
|
+
export function assertBilledAllowed(input) {
|
|
131
|
+
const { resolved, yes, json, label, estimate, freeAlternative } = input;
|
|
132
|
+
const log = input.log ?? ((line) => console.error(line));
|
|
133
|
+
const cost = estimate ? ` (${estimate})` : "";
|
|
134
|
+
if (resolved.mode === "minimize" && !yes) {
|
|
135
|
+
const alt = freeAlternative ? `\nFree alternative: ${freeAlternative}` : "";
|
|
136
|
+
throw new CostModeBlockedError(`Blocked by cost mode "minimize": ${label}${cost} spends billed AI credits.\n` +
|
|
137
|
+
`Confirm the spend with the user, then re-run with --yes (or switch modes: ` +
|
|
138
|
+
`vidfarm cost-mode hybrid).${alt}`);
|
|
139
|
+
}
|
|
140
|
+
if (json)
|
|
141
|
+
return;
|
|
142
|
+
if (!resolved.isSet) {
|
|
143
|
+
log(`[cost] No spend preference set — ${label}${cost} will bill the account. ` +
|
|
144
|
+
`Ask the user minimize / hybrid / pure-ai and save it: vidfarm cost-mode <choice>.`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
log(`[cost] ${label}${cost} — billed (mode: ${resolved.mode}${yes ? ", confirmed" : ""}).`);
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=cost-mode.js.map
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// `vidfarm doctor` — one-shot health check of everything the devcli's local
|
|
2
|
+
// loops depend on: node, the bundled ffmpeg/ffprobe, the hyperframes local
|
|
3
|
+
// engines, Chrome for in-process rendering, cloud auth, provider keys, agent
|
|
4
|
+
// CLIs, poisoned-env traps, port 3000, and installed agent skills.
|
|
5
|
+
//
|
|
6
|
+
// Exit code: 0 unless a HARD requirement (ffmpeg) is missing — everything
|
|
7
|
+
// else prints as ⚠/✗ but does not fail the command, so agents can run doctor
|
|
8
|
+
// unconditionally at session start.
|
|
9
|
+
import { spawnSync } from "node:child_process";
|
|
10
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
11
|
+
import net from "node:net";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import { parseArgs } from "node:util";
|
|
15
|
+
import { detectLocalAgent } from "../services/clip-curation/index.js";
|
|
16
|
+
import { hasFfmpeg, resolveFfmpeg, resolveFfprobe } from "../services/clip-curation/ffmpeg.js";
|
|
17
|
+
import { resolveHyperframesCli } from "./hyperframes-cli.js";
|
|
18
|
+
import { resolveSkillsRoot } from "./skills.js";
|
|
19
|
+
const GREEN = "\x1b[32m";
|
|
20
|
+
const RED = "\x1b[31m";
|
|
21
|
+
const YELLOW = "\x1b[33m";
|
|
22
|
+
const DIM = "\x1b[2m";
|
|
23
|
+
const RESET = "\x1b[0m";
|
|
24
|
+
// The cloud ARNs/URLs the `serve` command blanks before booting (see
|
|
25
|
+
// runServeCommand in src/cli.ts). Any of these set in a plain dev shell will
|
|
26
|
+
// silently route local work to cloud infra — the classic poisoned-.env trap.
|
|
27
|
+
const SERVE_BLANKED_ENV_VARS = [
|
|
28
|
+
"VIDFARM_JOB_STATE_MACHINE_ARN",
|
|
29
|
+
"VIDFARM_CLIP_SCAN_STATE_MACHINE_ARN",
|
|
30
|
+
"VIDFARM_PRIMITIVE_MEDIA_LAMBDA_URL",
|
|
31
|
+
"VIDFARM_PRIMITIVE_MEDIA_LAMBDA_SECRET",
|
|
32
|
+
"AWS_S3_BUCKET"
|
|
33
|
+
];
|
|
34
|
+
const PROVIDER_KEY_ENV_VARS = ["OPENAI_API_KEY", "GEMINI_API_KEY", "OPENROUTER_API_KEY", "ELEVENLABS_API_KEY"];
|
|
35
|
+
function isPortInUse(port) {
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
const server = net.createServer();
|
|
38
|
+
server.once("error", (error) => {
|
|
39
|
+
resolve(error.code === "EADDRINUSE");
|
|
40
|
+
});
|
|
41
|
+
server.once("listening", () => {
|
|
42
|
+
server.close(() => resolve(false));
|
|
43
|
+
});
|
|
44
|
+
server.listen(port, "127.0.0.1");
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Best-effort Chrome availability for the in-process HyperFrames render:
|
|
48
|
+
// explicit env overrides, the puppeteer download cache, or a system Chrome.
|
|
49
|
+
function detectChromeForRender() {
|
|
50
|
+
for (const envName of ["PUPPETEER_EXECUTABLE_PATH", "CHROME_PATH", "HYPERFRAMES_CHROME_PATH"]) {
|
|
51
|
+
const value = process.env[envName]?.trim();
|
|
52
|
+
if (value && existsSync(value))
|
|
53
|
+
return { found: true, detail: `${envName}=${value}` };
|
|
54
|
+
}
|
|
55
|
+
const cacheDir = process.env.PUPPETEER_CACHE_DIR?.trim() || path.join(homedir(), ".cache", "puppeteer");
|
|
56
|
+
try {
|
|
57
|
+
const entries = readdirSync(cacheDir).filter((name) => /chrome/i.test(name));
|
|
58
|
+
if (entries.length > 0)
|
|
59
|
+
return { found: true, detail: `puppeteer cache ${cacheDir} (${entries.join(", ")})` };
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// no cache dir — fall through
|
|
63
|
+
}
|
|
64
|
+
const systemCandidates = process.platform === "darwin"
|
|
65
|
+
? ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "/Applications/Chromium.app/Contents/MacOS/Chromium"]
|
|
66
|
+
: ["/usr/bin/google-chrome", "/usr/bin/chromium", "/usr/bin/chromium-browser"];
|
|
67
|
+
for (const candidate of systemCandidates) {
|
|
68
|
+
if (existsSync(candidate))
|
|
69
|
+
return { found: true, detail: candidate };
|
|
70
|
+
}
|
|
71
|
+
return { found: false, detail: `no PUPPETEER_EXECUTABLE_PATH/CHROME_PATH, no ${cacheDir}, no system Chrome` };
|
|
72
|
+
}
|
|
73
|
+
// Count installed skills under the SAME root the `vidfarm skills` command
|
|
74
|
+
// resolves (resolveSkillsRoot: walk up from cwd to the first dir with
|
|
75
|
+
// .agents/skills or .git, else cwd) — one resolution, no drift.
|
|
76
|
+
function countInstalledSkills() {
|
|
77
|
+
const root = resolveSkillsRoot();
|
|
78
|
+
const skillsDir = path.join(root, ".agents", "skills");
|
|
79
|
+
if (!existsSync(skillsDir))
|
|
80
|
+
return { root: null, count: 0, names: [] };
|
|
81
|
+
try {
|
|
82
|
+
const names = readdirSync(skillsDir).filter((name) => existsSync(path.join(skillsDir, name, "SKILL.md")));
|
|
83
|
+
return { root, count: names.length, names };
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return { root, count: 0, names: [] };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function fetchWhoami(host, apiKey) {
|
|
90
|
+
try {
|
|
91
|
+
const res = await fetch(new URL("/api/v1/user/me", host), {
|
|
92
|
+
headers: { "vidfarm-api-key": apiKey, accept: "application/json" }
|
|
93
|
+
});
|
|
94
|
+
if (!res.ok)
|
|
95
|
+
return { ok: false, detail: `GET /api/v1/user/me → ${res.status} (check the key/host)` };
|
|
96
|
+
const json = await res.json().catch(() => null);
|
|
97
|
+
const email = json?.email ?? json?.user?.email ?? json?.customer?.email;
|
|
98
|
+
return { ok: true, detail: email ? `authenticated as ${email} (${host})` : `authenticated (${host})` };
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
return { ok: false, detail: `could not reach ${host}: ${error instanceof Error ? error.message : String(error)}` };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export async function runDoctorCommand(argv) {
|
|
105
|
+
const parsed = parseArgs({
|
|
106
|
+
args: argv,
|
|
107
|
+
allowPositionals: false,
|
|
108
|
+
options: {
|
|
109
|
+
host: { type: "string", default: "https://vidfarm.cc" },
|
|
110
|
+
"api-key": { type: "string" },
|
|
111
|
+
json: { type: "boolean", default: false }
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
const json = Boolean(parsed.values.json);
|
|
115
|
+
const checks = [];
|
|
116
|
+
const add = (name, level, detail) => checks.push({ name, level, detail });
|
|
117
|
+
// 1. Node version.
|
|
118
|
+
const nodeMajor = Number(process.versions.node.split(".")[0]);
|
|
119
|
+
add("node", nodeMajor >= 22 ? "ok" : "fail", `v${process.versions.node}${nodeMajor >= 22 ? "" : " — vidfarm-devcli needs Node >= 22"}`);
|
|
120
|
+
// 2. ffmpeg / ffprobe (HARD requirement).
|
|
121
|
+
const ffmpegPath = await resolveFfmpeg();
|
|
122
|
+
const ffprobePath = await resolveFfprobe();
|
|
123
|
+
const ffmpegOk = await hasFfmpeg();
|
|
124
|
+
add("ffmpeg", ffmpegOk ? "ok" : "fail", ffmpegOk ? ffmpegPath : "not found (bundled ffmpeg-static missing and none on PATH) — media commands cannot run");
|
|
125
|
+
add("ffprobe", existsSync(ffprobePath) || spawnSync(ffprobePath, ["-version"], { stdio: "ignore" }).status === 0 ? "ok" : "warn", ffprobePath);
|
|
126
|
+
// 3. hyperframes CLI (local engines: Kokoro tts, whisper stt, matting, capture, beats).
|
|
127
|
+
const hyperframesCli = resolveHyperframesCli();
|
|
128
|
+
add("hyperframes", hyperframesCli ? "ok" : "warn", hyperframesCli ?? "not installed — local engines (tts/transcribe/remove-background/capture/beats) will fall back to `npx -y hyperframes`");
|
|
129
|
+
// 4. Chrome for the in-process render (stills / serve local render).
|
|
130
|
+
const chrome = detectChromeForRender();
|
|
131
|
+
add("chrome", chrome.found ? "ok" : "warn", chrome.found ? chrome.detail : `${chrome.detail} — local render/stills will try to download one on first run`);
|
|
132
|
+
// 5. Vidfarm cloud auth.
|
|
133
|
+
const apiKey = parsed.values["api-key"] ?? process.env.VIDFARM_API_KEY;
|
|
134
|
+
if (apiKey) {
|
|
135
|
+
const who = await fetchWhoami(String(parsed.values.host).replace(/\/+$/, ""), apiKey);
|
|
136
|
+
add("vidfarm auth", who.ok ? "ok" : "warn", who.ok ? who.detail : `${who.detail} — serve will fall back to local browse mode`);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
add("vidfarm auth", "warn", "VIDFARM_API_KEY not set — serve will fall back to local browse mode; cloud catalog/bulk routes need it");
|
|
140
|
+
}
|
|
141
|
+
// 6. Provider keys in env (BYOK local-first engines).
|
|
142
|
+
const presentKeys = PROVIDER_KEY_ENV_VARS.filter((name) => process.env[name]?.trim());
|
|
143
|
+
add("provider keys", presentKeys.length > 0 ? "ok" : "warn", presentKeys.length > 0
|
|
144
|
+
? presentKeys.join(", ")
|
|
145
|
+
: "none of OPENAI/GEMINI/OPENROUTER/ELEVENLABS_API_KEY set — BYOK speech/clip tagging unavailable (keyless local engines still work)");
|
|
146
|
+
// 7. Local agent CLI (claude / codex) for clips scan etc.
|
|
147
|
+
const agent = detectLocalAgent();
|
|
148
|
+
add("agent CLI", agent ? "ok" : "warn", agent ? `${agent.kind} (${agent.bin})` : "no claude/codex CLI on PATH — `clips scan` falls back to provider keys");
|
|
149
|
+
// 8. Poisoned-env traps.
|
|
150
|
+
if (process.env.AWS_PROFILE?.trim()) {
|
|
151
|
+
add("env AWS_PROFILE", "warn", `AWS_PROFILE=${process.env.AWS_PROFILE} is set — it can hijack AWS SDK auth; run \`env -u AWS_PROFILE\` or unset it`);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
add("env AWS_PROFILE", "ok", "not set");
|
|
155
|
+
}
|
|
156
|
+
const poisoned = SERVE_BLANKED_ENV_VARS.filter((name) => process.env[name]?.trim());
|
|
157
|
+
add("env cloud ARNs/URLs", poisoned.length > 0 ? "warn" : "ok", poisoned.length > 0
|
|
158
|
+
? `${poisoned.join(", ")} set — outside \`vidfarm serve\` these route local work to cloud infra (serve blanks them itself)`
|
|
159
|
+
: "no stray cloud ARNs/URLs in env");
|
|
160
|
+
// 9. Port 3000 (default serve port).
|
|
161
|
+
const portBusy = await isPortInUse(3000);
|
|
162
|
+
add("port 3000", portBusy ? "warn" : "ok", portBusy ? "in use — a serve box may already be running (or pass --port to serve)" : "free");
|
|
163
|
+
// 10. HeyGen credential file — vidfarm never uses it.
|
|
164
|
+
const heygenCredentials = path.join(homedir(), ".heygen", "credentials");
|
|
165
|
+
if (existsSync(heygenCredentials) || existsSync(path.join(homedir(), ".heygen", "credentials.json"))) {
|
|
166
|
+
add("heygen credentials", "warn", "found a HeyGen credential file — vidfarm never uses it; local engines and vidfarm BYOK keys are the only auth");
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
add("heygen credentials", "ok", "none (vidfarm never uses HeyGen accounts)");
|
|
170
|
+
}
|
|
171
|
+
// 11. Installed agent skills.
|
|
172
|
+
const skills = countInstalledSkills();
|
|
173
|
+
add("agent skills", skills.count > 0 ? "ok" : "warn", skills.count > 0
|
|
174
|
+
? `${skills.count} installed under ${skills.root}/.agents/skills`
|
|
175
|
+
: "no .agents/skills found walking up from cwd — run `vidfarm skills add <names…>`");
|
|
176
|
+
const ffmpegMissing = checks.some((check) => check.name === "ffmpeg" && check.level === "fail");
|
|
177
|
+
if (json) {
|
|
178
|
+
process.stdout.write(`${JSON.stringify({ ok: !ffmpegMissing, checks }, null, 2)}\n`);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
for (const check of checks) {
|
|
182
|
+
const mark = check.level === "ok" ? `${GREEN}✓${RESET}` : check.level === "warn" ? `${YELLOW}⚠${RESET}` : `${RED}✗${RESET}`;
|
|
183
|
+
console.log(`${mark} ${check.name.padEnd(20)} ${DIM}${check.detail}${RESET}`);
|
|
184
|
+
}
|
|
185
|
+
if (ffmpegMissing) {
|
|
186
|
+
console.log(`\n${RED}ffmpeg is a hard requirement — install it (or \`npm i ffmpeg-static\`) and re-run.${RESET}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (ffmpegMissing)
|
|
190
|
+
process.exitCode = 1;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Guarded bridge to the bundled `hyperframes` npm CLI — the devcli's local
|
|
2
|
+
// media engine. Only the LOCAL, account-free commands are reachable through
|
|
3
|
+
// this module (tts / transcribe / remove-background / capture / beats / …);
|
|
4
|
+
// the HeyGen account + telemetry surface (`auth`, `cloud`, `publish`, `play`,
|
|
5
|
+
// `feedback`, `telemetry`) is rejected outright so no vidfarm command can ever
|
|
6
|
+
// touch a HeyGen account, even by accident.
|
|
7
|
+
//
|
|
8
|
+
// Every spawn additionally hardens the child env:
|
|
9
|
+
// - HYPERFRAMES_NO_TELEMETRY=1 → no anonymous usage pings
|
|
10
|
+
// - HYPERFRAMES_SKIP_SKILLS=1 → no skill-install prompts in pipelines
|
|
11
|
+
// - HEYGEN_CONFIG_DIR=<fresh empty temp dir> → a stray ~/.heygen credential
|
|
12
|
+
// can NEVER be picked up (some hyperframes commands silently flip their
|
|
13
|
+
// audio-provider preference when a HeyGen credential is present).
|
|
14
|
+
import { spawn } from "node:child_process";
|
|
15
|
+
import { mkdtempSync } from "node:fs";
|
|
16
|
+
import { createRequire } from "node:module";
|
|
17
|
+
import os from "node:os";
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
import { fileURLToPath } from "node:url";
|
|
20
|
+
const BLOCKED_SUBCOMMANDS = new Set(["auth", "cloud", "publish", "play", "feedback", "telemetry"]);
|
|
21
|
+
/**
|
|
22
|
+
* Locate the bundled hyperframes CLI entrypoint by walking node_modules from
|
|
23
|
+
* this module's directory first (the published devcli package carries the
|
|
24
|
+
* dependency), then from process.cwd() (running inside a repo that installed
|
|
25
|
+
* it). Returns null when the package is not installed anywhere reachable.
|
|
26
|
+
*/
|
|
27
|
+
export function resolveHyperframesCli() {
|
|
28
|
+
const anchors = [path.dirname(fileURLToPath(import.meta.url)), process.cwd()];
|
|
29
|
+
for (const anchor of anchors) {
|
|
30
|
+
try {
|
|
31
|
+
const localRequire = createRequire(path.join(anchor, "__resolve__.js"));
|
|
32
|
+
return localRequire.resolve("hyperframes/dist/cli.js");
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// keep walking — try the next anchor
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Run `hyperframes <subcommand> ...args` with the hardened env described in
|
|
42
|
+
* the module header. Falls back to `npx -y hyperframes` when the package
|
|
43
|
+
* cannot be resolved locally. Throws on blocked subcommands; resolves with
|
|
44
|
+
* the exit code + captured output (empty strings in inherit mode).
|
|
45
|
+
*/
|
|
46
|
+
export async function runHyperframesCommand(subcommand, args, opts = {}) {
|
|
47
|
+
if (BLOCKED_SUBCOMMANDS.has(subcommand)) {
|
|
48
|
+
throw new Error(`hyperframes ${subcommand} is blocked: vidfarm never uses HeyGen accounts or telemetry. ` +
|
|
49
|
+
"Local engines and vidfarm BYOK keys are the only auth.");
|
|
50
|
+
}
|
|
51
|
+
const cli = resolveHyperframesCli();
|
|
52
|
+
// Fresh empty config dir per invocation — guarantees no ~/.heygen credential
|
|
53
|
+
// (or any other persisted account state) leaks into the child process.
|
|
54
|
+
const emptyConfigDir = mkdtempSync(path.join(os.tmpdir(), "vidfarm-hf-noauth-"));
|
|
55
|
+
const env = {
|
|
56
|
+
...process.env,
|
|
57
|
+
HYPERFRAMES_NO_TELEMETRY: "1",
|
|
58
|
+
HYPERFRAMES_SKIP_SKILLS: "1",
|
|
59
|
+
HEYGEN_CONFIG_DIR: emptyConfigDir,
|
|
60
|
+
...opts.env
|
|
61
|
+
};
|
|
62
|
+
const [bin, baseArgs] = cli
|
|
63
|
+
? [process.execPath, [cli]]
|
|
64
|
+
: ["npx", ["-y", "hyperframes"]];
|
|
65
|
+
const capture = opts.stdio === "capture";
|
|
66
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
67
|
+
const child = spawn(bin, [...baseArgs, subcommand, ...args], {
|
|
68
|
+
cwd: opts.cwd,
|
|
69
|
+
env,
|
|
70
|
+
stdio: capture ? ["ignore", "pipe", "pipe"] : "inherit"
|
|
71
|
+
});
|
|
72
|
+
let stdout = "";
|
|
73
|
+
let stderr = "";
|
|
74
|
+
if (capture) {
|
|
75
|
+
child.stdout?.on("data", (chunk) => (stdout += chunk.toString()));
|
|
76
|
+
child.stderr?.on("data", (chunk) => (stderr += chunk.toString()));
|
|
77
|
+
}
|
|
78
|
+
child.on("error", (error) => {
|
|
79
|
+
rejectPromise(error.code === "ENOENT"
|
|
80
|
+
? new Error("Could not launch the hyperframes CLI (not installed and npx unavailable). Run `npm i hyperframes` in your project.")
|
|
81
|
+
: error);
|
|
82
|
+
});
|
|
83
|
+
child.on("close", (code) => {
|
|
84
|
+
resolvePromise({ code: code ?? 1, stdout, stderr });
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/** Parse the last JSON object printed by a captured hyperframes --json run
|
|
89
|
+
* (tolerates both compact single-line and pretty multi-line output, with log
|
|
90
|
+
* lines interleaved before it). */
|
|
91
|
+
export function parseHyperframesJson(output) {
|
|
92
|
+
const trimmed = output.trim();
|
|
93
|
+
if (!trimmed)
|
|
94
|
+
return null;
|
|
95
|
+
// Whole output is the JSON document (the common --json case).
|
|
96
|
+
try {
|
|
97
|
+
const whole = JSON.parse(trimmed);
|
|
98
|
+
if (whole && typeof whole === "object")
|
|
99
|
+
return whole;
|
|
100
|
+
}
|
|
101
|
+
catch { /* fall through */ }
|
|
102
|
+
// Log lines first, JSON at the end: parse from each line that opens an
|
|
103
|
+
// object through the end of the output, scanning bottom-up.
|
|
104
|
+
const lines = trimmed.split("\n");
|
|
105
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
106
|
+
if (!lines[i].trimStart().startsWith("{"))
|
|
107
|
+
continue;
|
|
108
|
+
const candidate = lines.slice(i).join("\n").trim();
|
|
109
|
+
try {
|
|
110
|
+
const parsed = JSON.parse(candidate);
|
|
111
|
+
if (parsed && typeof parsed === "object")
|
|
112
|
+
return parsed;
|
|
113
|
+
}
|
|
114
|
+
catch { /* keep scanning upward */ }
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=hyperframes-cli.js.map
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// In-process LOCAL backend for the devcli — the "local" half of local-first,
|
|
2
|
+
// dual local/cloud operation.
|
|
3
|
+
//
|
|
4
|
+
// The whole Vidfarm backend already runs over disk-backed drivers when
|
|
5
|
+
// RECORDS_DRIVER=local + STORAGE_DRIVER=local (the same drivers `vidfarm serve`
|
|
6
|
+
// uses). Rather than re-implement the directory / files / raws logic a second
|
|
7
|
+
// time, we boot the real Hono `app` in-process and drive it with `app.request()`
|
|
8
|
+
// — Hono's fetch interface runs the full middleware + handler stack WITHOUT
|
|
9
|
+
// binding a socket. So `vidfarm directory ls --local` and `vidfarm serve` share
|
|
10
|
+
// one on-disk backend, and a `clips scan --local` is instantly browsable in a
|
|
11
|
+
// running serve UI.
|
|
12
|
+
//
|
|
13
|
+
// IMPORTANT (env-before-import): `config.ts` binds the driver + data dir from
|
|
14
|
+
// env at module load. We MUST set the local env BEFORE the first `import` of
|
|
15
|
+
// `../app.js` / any service. `cli.ts`'s static import graph deliberately does
|
|
16
|
+
// not reach `config.js`, so setting env here (then dynamic-importing) flips the
|
|
17
|
+
// drivers correctly — exactly the discipline `runServeCommand` follows.
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
import { homedir } from "node:os";
|
|
20
|
+
import { existsSync } from "node:fs";
|
|
21
|
+
import { fileURLToPath } from "node:url";
|
|
22
|
+
/**
|
|
23
|
+
* Thrown when a local / `serve` command is invoked in the PUBLISHED CLI, which
|
|
24
|
+
* ships as a cloud client only — the in-process backend (`app.js` et al.) is
|
|
25
|
+
* deliberately excluded from the npm tarball so the server is never open-sourced.
|
|
26
|
+
* A full source checkout (where `app.js` sits next to the CLI on disk) still runs
|
|
27
|
+
* local mode; the published package degrades to this friendly error instead.
|
|
28
|
+
*/
|
|
29
|
+
export class LocalModeUnavailableError extends Error {
|
|
30
|
+
constructor() {
|
|
31
|
+
super("Local / serve mode isn't available in the published Vidfarm CLI — it would require the full backend. " +
|
|
32
|
+
"Use cloud mode (the default): drop --local/--both, or pass --cloud. " +
|
|
33
|
+
"(Local mode is available when running the CLI from a full source checkout.)");
|
|
34
|
+
this.name = "LocalModeUnavailableError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** True only when the in-process backend (`app.js`) is present next to the CLI
|
|
38
|
+
* on disk — i.e. a full source/dist checkout, never the published npm package. */
|
|
39
|
+
export function localBackendAvailable() {
|
|
40
|
+
try {
|
|
41
|
+
const here = path.dirname(fileURLToPath(import.meta.url)); // dist/src/devcli
|
|
42
|
+
return existsSync(path.join(here, "..", "app.js"));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Wrap a dynamic import of a backend module so an absent file (published CLI)
|
|
49
|
+
* surfaces as a clean LocalModeUnavailableError, not a raw ERR_MODULE_NOT_FOUND. */
|
|
50
|
+
export async function importBackendModule(loader) {
|
|
51
|
+
try {
|
|
52
|
+
return await loader();
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error && typeof error === "object" && error.code === "ERR_MODULE_NOT_FOUND") {
|
|
56
|
+
throw new LocalModeUnavailableError();
|
|
57
|
+
}
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** The durable per-user local home. Everything the local backend persists lives
|
|
62
|
+
* under here: records + storage at `<home>/data`, legacy clips at
|
|
63
|
+
* `<home>/clips.db`, provider config at `<home>/config.json`. */
|
|
64
|
+
export function resolveLocalHome(overrideDir) {
|
|
65
|
+
if (overrideDir)
|
|
66
|
+
return path.resolve(overrideDir);
|
|
67
|
+
if (process.env.VIDFARM_HOME)
|
|
68
|
+
return path.resolve(process.env.VIDFARM_HOME);
|
|
69
|
+
return path.join(homedir(), ".vidfarm");
|
|
70
|
+
}
|
|
71
|
+
/** The data dir (records + storage) for the local backend. */
|
|
72
|
+
export function resolveLocalDataDir(overrideDir) {
|
|
73
|
+
return path.join(resolveLocalHome(overrideDir), "data");
|
|
74
|
+
}
|
|
75
|
+
let cached = null;
|
|
76
|
+
/**
|
|
77
|
+
* Boot (once) the in-process local backend and return a handle. Idempotent:
|
|
78
|
+
* repeated calls return the same booted app. Safe to call from any local
|
|
79
|
+
* command; cloud-only commands never call this, so the cloud path is untouched.
|
|
80
|
+
*/
|
|
81
|
+
export async function withLocalBackend(opts = {}) {
|
|
82
|
+
if (cached)
|
|
83
|
+
return cached;
|
|
84
|
+
const home = resolveLocalHome(opts.home);
|
|
85
|
+
const dataDir = resolveLocalDataDir(opts.home);
|
|
86
|
+
// Force the fully-local drivers, and blank every knob that would otherwise
|
|
87
|
+
// route this in-process box at the cloud (mirrors runServeCommand). These
|
|
88
|
+
// MUST be set before app.js / config.js is imported below.
|
|
89
|
+
process.env.RECORDS_DRIVER = "local";
|
|
90
|
+
process.env.STORAGE_DRIVER = "local";
|
|
91
|
+
process.env.AWS_S3_BUCKET = "";
|
|
92
|
+
process.env.VIDFARM_JOB_STATE_MACHINE_ARN = "";
|
|
93
|
+
process.env.VIDFARM_CLIP_SCAN_STATE_MACHINE_ARN = "";
|
|
94
|
+
process.env.VIDFARM_PRIMITIVE_MEDIA_LAMBDA_URL = "";
|
|
95
|
+
process.env.VIDFARM_PRIMITIVE_MEDIA_LAMBDA_SECRET = "";
|
|
96
|
+
// The one records-touching service that bypasses the local shim and talks to a
|
|
97
|
+
// real DynamoDB table via middleware — blank it or every /api/* 500s when a
|
|
98
|
+
// dev-shell .env carries a table name. In-process service calls don't hit
|
|
99
|
+
// middleware, but app.request() does, so this must be blank.
|
|
100
|
+
process.env.VIDFARM_RATE_LIMITS_TABLE_NAME = "";
|
|
101
|
+
process.env.VIDFARM_DATA_DIR = dataDir;
|
|
102
|
+
if (!process.env.NODE_ENV)
|
|
103
|
+
process.env.NODE_ENV = "development";
|
|
104
|
+
process.env.HYPERFRAMES_NO_TELEMETRY ||= "1";
|
|
105
|
+
process.env.HYPERFRAMES_SKIP_SKILLS ||= "1";
|
|
106
|
+
// No cloud passthrough by default for pure-local commands; sync/`--cloud` reach
|
|
107
|
+
// the cloud host directly via the devcli's own apiRequest, not this app.
|
|
108
|
+
process.env.VIDFARM_UPSTREAM_HOST ||= "";
|
|
109
|
+
process.env.VIDFARM_UPSTREAM_API_KEY ||= "";
|
|
110
|
+
// A stable local bootstrap key. The same value auto-provisions the local
|
|
111
|
+
// customer (tryBootstrapFromEnv) and authenticates app.request() calls. An
|
|
112
|
+
// empty/whitespace override falls through to the env key or the fixed default
|
|
113
|
+
// (so `--api-key ""` never breaks the local backend).
|
|
114
|
+
const apiKey = (opts.apiKey && opts.apiKey.trim()) ||
|
|
115
|
+
(process.env.VIDFARM_API_KEY && process.env.VIDFARM_API_KEY.trim()) ||
|
|
116
|
+
"vidfarm-local-dev-key";
|
|
117
|
+
process.env.VIDFARM_API_KEY = apiKey;
|
|
118
|
+
// Dynamic imports AFTER env is set, so config.ts binds the local drivers.
|
|
119
|
+
// Wrapped so the published (cloud-only) CLI — which ships without these backend
|
|
120
|
+
// modules — fails with a friendly LocalModeUnavailableError instead of a raw
|
|
121
|
+
// module-not-found stack trace.
|
|
122
|
+
const { ServerlessAuthService } = await importBackendModule(() => import("../services/serverless-auth.js"));
|
|
123
|
+
const customer = await new ServerlessAuthService().authenticate(apiKey);
|
|
124
|
+
const appMod = await importBackendModule(() => import("../app.js"));
|
|
125
|
+
const app = appMod.default;
|
|
126
|
+
cached = { app, apiKey, ownerId: customer.id, home };
|
|
127
|
+
return cached;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Dispatch a REST call to the in-process local app. Mirrors the cloud
|
|
131
|
+
* `apiRequest` shape so commands can branch on target without reshaping results.
|
|
132
|
+
*/
|
|
133
|
+
export async function localApiRequest(input) {
|
|
134
|
+
const backend = await withLocalBackend({ home: input.home, apiKey: input.auth?.apiKey });
|
|
135
|
+
// A synthetic origin — only the path + query matter to Hono routing.
|
|
136
|
+
const url = new URL(input.path, "http://vidfarm.local");
|
|
137
|
+
for (const [key, value] of Object.entries(input.query ?? {})) {
|
|
138
|
+
if (value !== undefined && value !== null && value !== "")
|
|
139
|
+
url.searchParams.set(key, value);
|
|
140
|
+
}
|
|
141
|
+
const headers = {
|
|
142
|
+
accept: "application/json",
|
|
143
|
+
"vidfarm-api-key": input.auth?.apiKey || backend.apiKey
|
|
144
|
+
};
|
|
145
|
+
if (input.auth?.shareToken)
|
|
146
|
+
headers["vidfarm-share-token"] = input.auth.shareToken;
|
|
147
|
+
let body;
|
|
148
|
+
if (input.body !== undefined) {
|
|
149
|
+
headers["content-type"] = "application/json";
|
|
150
|
+
body = JSON.stringify(input.body);
|
|
151
|
+
}
|
|
152
|
+
const res = await backend.app.request(url.pathname + url.search, {
|
|
153
|
+
method: input.method.toUpperCase(),
|
|
154
|
+
headers,
|
|
155
|
+
body
|
|
156
|
+
});
|
|
157
|
+
const text = await res.text();
|
|
158
|
+
let json = null;
|
|
159
|
+
try {
|
|
160
|
+
json = text ? JSON.parse(text) : null;
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
json = null;
|
|
164
|
+
}
|
|
165
|
+
return { status: res.status, ok: res.ok, json, text };
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=local-backend.js.map
|