@mevdragon/vidfarm-devcli 0.14.0 → 0.15.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/.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/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/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/vidfarm-media/SKILL.md +85 -0
- package/.agents/skills/vidfarm-media/references/tts.md +54 -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/SKILL.director.md +37 -0
- package/SKILL.platform.md +6 -1
- package/demo/dist/app.js +295 -11
- package/dist/src/app.js +317 -133
- package/dist/src/cli.js +529 -12
- package/dist/src/composition-runtime.js +262 -3
- package/dist/src/devcli/doctor.js +192 -0
- package/dist/src/devcli/hyperframes-cli.js +118 -0
- package/dist/src/devcli/skills.js +476 -0
- package/dist/src/devcli/stills.js +249 -0
- package/dist/src/editor-chat.js +255 -0
- package/dist/src/hyperframes/composition.js +5 -5
- package/dist/src/services/composition-lint.js +199 -0
- package/dist/src/services/hyperframes.js +67 -13
- package/package.json +2 -1
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
9
9
|
(() => {
|
|
10
10
|
const root = document.querySelector("[data-composition-id]");
|
|
11
|
-
|
|
11
|
+
let declaredDuration = Number(root?.getAttribute("data-duration") || 0);
|
|
12
|
+
let duration = declaredDuration;
|
|
12
13
|
let time = 0;
|
|
13
14
|
let playing = false;
|
|
14
15
|
let playbackRate = 1;
|
|
@@ -53,6 +54,11 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
function refreshClips() {
|
|
57
|
+
// The parent editor can live-patch the composition DOM. Re-read the root's
|
|
58
|
+
// declared duration so a patched data-duration followed by refreshClips()
|
|
59
|
+
// never leaves the player clamped to a stale duration.
|
|
60
|
+
declaredDuration = Number(root?.getAttribute("data-duration") || 0);
|
|
61
|
+
duration = declaredDuration;
|
|
56
62
|
clips = Array.from(document.querySelectorAll("[data-start]")).filter((node) => node !== root);
|
|
57
63
|
for (const clip of clips) {
|
|
58
64
|
if (clip instanceof HTMLMediaElement && !initialMuted.has(clip)) {
|
|
@@ -74,6 +80,7 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
74
80
|
activeVideoProxyKey = null;
|
|
75
81
|
activeVideoProxyNode = null;
|
|
76
82
|
hasVideoProxies = clips.some((clip) => clip instanceof Element && clip.getAttribute("data-vf-timeline-proxy") === "video");
|
|
83
|
+
discoverGeneralCssAnimations();
|
|
77
84
|
apply(time, { forceSeek: true });
|
|
78
85
|
}
|
|
79
86
|
|
|
@@ -146,6 +153,130 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
146
153
|
}
|
|
147
154
|
}
|
|
148
155
|
|
|
156
|
+
// Runtime-adapter bridge — mirrors the official @hyperframes/producer
|
|
157
|
+
// deterministic adapters so compositions driven by a registered GSAP
|
|
158
|
+
// timeline (window.__timelines), Anime.js (window.__hfAnime), Lottie
|
|
159
|
+
// (window.__hfLottie), or Three.js/TypeGPU (window.__hfThreeTime/
|
|
160
|
+
// __hfTypegpuTime + the hf-seek CustomEvent) scrub with the player instead
|
|
161
|
+
// of running on the wall clock. Everything is duck-typed and try/caught so
|
|
162
|
+
// a broken composition script never kills the apply loop.
|
|
163
|
+
function compositionTimeline() {
|
|
164
|
+
let registry = null;
|
|
165
|
+
try { registry = window.__timelines; } catch { return null; }
|
|
166
|
+
if (!registry || typeof registry !== "object") return null;
|
|
167
|
+
const compId = root?.getAttribute("data-composition-id") || "";
|
|
168
|
+
let timeline = compId ? registry[compId] : null;
|
|
169
|
+
if (!timeline) {
|
|
170
|
+
const keys = Object.keys(registry);
|
|
171
|
+
if (keys.length === 1) timeline = registry[keys[0]];
|
|
172
|
+
}
|
|
173
|
+
if (!timeline || typeof timeline.pause !== "function") return null;
|
|
174
|
+
if (typeof timeline.totalTime !== "function" && typeof timeline.seek !== "function") return null;
|
|
175
|
+
return timeline;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function timelineDuration(timeline) {
|
|
179
|
+
try {
|
|
180
|
+
const value = typeof timeline.duration === "function" ? Number(timeline.duration()) : Number(timeline.duration);
|
|
181
|
+
if (Number.isFinite(value) && value > 0) return value;
|
|
182
|
+
} catch {}
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function syncTimeline() {
|
|
187
|
+
const timeline = compositionTimeline();
|
|
188
|
+
if (!timeline) return;
|
|
189
|
+
try {
|
|
190
|
+
timeline.pause();
|
|
191
|
+
// Official gsap adapter seek: nudge to time+1ms with suppressed events,
|
|
192
|
+
// then land exactly, so gsap re-renders even when the target equals the
|
|
193
|
+
// timeline's current time.
|
|
194
|
+
if (typeof timeline.totalTime === "function") {
|
|
195
|
+
timeline.totalTime(time + 0.001, true);
|
|
196
|
+
timeline.totalTime(time, false);
|
|
197
|
+
} else {
|
|
198
|
+
timeline.seek(time, false);
|
|
199
|
+
}
|
|
200
|
+
} catch {}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function syncAnimeInstances() {
|
|
204
|
+
let instances = null;
|
|
205
|
+
try { instances = window.__hfAnime; } catch { return; }
|
|
206
|
+
if (!Array.isArray(instances) || instances.length === 0) return;
|
|
207
|
+
const ms = Math.max(0, time) * 1000;
|
|
208
|
+
for (const instance of instances) {
|
|
209
|
+
try {
|
|
210
|
+
if (instance && typeof instance.seek === "function") instance.seek(ms);
|
|
211
|
+
} catch {}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function syncLottiePlayers() {
|
|
216
|
+
let players = null;
|
|
217
|
+
try { players = window.__hfLottie; } catch { return; }
|
|
218
|
+
if (!Array.isArray(players) || players.length === 0) return;
|
|
219
|
+
const safe = Math.max(0, time);
|
|
220
|
+
for (const player of players) {
|
|
221
|
+
try {
|
|
222
|
+
if (!player || typeof player !== "object") continue;
|
|
223
|
+
if (typeof player.goToAndStop === "function") {
|
|
224
|
+
player.goToAndStop(safe * 1000, false);
|
|
225
|
+
} else if (typeof player.pause === "function" && ("totalFrames" in player || "duration" in player)) {
|
|
226
|
+
if (typeof player.setCurrentRawFrameValue === "function") {
|
|
227
|
+
const totalFrames = player.totalFrames ?? 0;
|
|
228
|
+
const frameRate = player.frameRate ?? 30;
|
|
229
|
+
if (totalFrames > 0) player.setCurrentRawFrameValue(Math.min(safe * frameRate, totalFrames - 1));
|
|
230
|
+
} else if (typeof player.seek === "function") {
|
|
231
|
+
player.seek(Math.min(100, (safe / (player.duration ?? 1)) * 100));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
} catch {}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
let lastDispatchedSeekTime = -1;
|
|
239
|
+
function syncSeekGlobals() {
|
|
240
|
+
const safe = Math.max(0, time);
|
|
241
|
+
try { window.__hfThreeTime = safe; } catch {}
|
|
242
|
+
try { window.__hfTypegpuTime = safe; } catch {}
|
|
243
|
+
// The official three/typegpu adapters dedupe the hf-seek dispatch on the
|
|
244
|
+
// last dispatched time.
|
|
245
|
+
if (safe === lastDispatchedSeekTime) return;
|
|
246
|
+
lastDispatchedSeekTime = safe;
|
|
247
|
+
try { window.dispatchEvent(new CustomEvent("hf-seek", { detail: { time: safe } })); } catch {}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function syncRuntimeAdapters() {
|
|
251
|
+
syncTimeline();
|
|
252
|
+
syncAnimeInstances();
|
|
253
|
+
syncLottiePlayers();
|
|
254
|
+
syncSeekGlobals();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// data-duration on the root is authoritative when present. Arbitrary
|
|
258
|
+
// compositions may omit it, so infer the duration from clip extents,
|
|
259
|
+
// preferring a registered GSAP timeline that reports a longer duration.
|
|
260
|
+
// Recomputed on every apply so a timeline registered after load still
|
|
261
|
+
// corrects the duration (and seek clamping) lazily.
|
|
262
|
+
function ensureDuration() {
|
|
263
|
+
if (declaredDuration > 0) {
|
|
264
|
+
duration = declaredDuration;
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
let inferred = 0;
|
|
268
|
+
for (const clip of clips) {
|
|
269
|
+
const timing = readTiming(clip);
|
|
270
|
+
if (timing.end > inferred) inferred = timing.end;
|
|
271
|
+
}
|
|
272
|
+
const timeline = compositionTimeline();
|
|
273
|
+
if (timeline) {
|
|
274
|
+
const reported = timelineDuration(timeline);
|
|
275
|
+
if (reported > inferred) inferred = reported;
|
|
276
|
+
}
|
|
277
|
+
duration = inferred;
|
|
278
|
+
}
|
|
279
|
+
|
|
149
280
|
// Ken Burns image clips carry a CSS transform animation (vf-kb-* keyframes)
|
|
150
281
|
// directly on the [data-kenburns] <img>. CSS animations run on the wall clock,
|
|
151
282
|
// not player time, so the runtime scrubs them: pause + set currentTime from
|
|
@@ -313,19 +444,138 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
313
444
|
}
|
|
314
445
|
}
|
|
315
446
|
|
|
447
|
+
// Generalized CSS keyframe scrub — the preview twin of the official
|
|
448
|
+
// producer CSS adapter: every element whose computed animation-name is set
|
|
449
|
+
// gets its animations paused and scrubbed to the player time relative to
|
|
450
|
+
// the nearest ancestor-or-self [data-start] (0 when none). vf-* animations
|
|
451
|
+
// (Ken Burns, transitions, captions) keep their dedicated machinery above.
|
|
452
|
+
// Discovery is cached per refreshClips like the official adapter's discover
|
|
453
|
+
// pass; elements added by live patches are picked up on the next refresh.
|
|
454
|
+
// Each entry also caches its clip-relative start at discovery so the
|
|
455
|
+
// per-frame sync skips the ancestor walk; a re-parented or retimed element
|
|
456
|
+
// is likewise re-resolved on the next refreshClips discovery.
|
|
457
|
+
let generalCssEntries = [];
|
|
458
|
+
|
|
459
|
+
function discoverGeneralCssAnimations() {
|
|
460
|
+
generalCssEntries = [];
|
|
461
|
+
let nodes = [];
|
|
462
|
+
try { nodes = document.querySelectorAll("*"); } catch { return; }
|
|
463
|
+
for (const node of nodes) {
|
|
464
|
+
if (!(node instanceof HTMLElement) || typeof node.getAnimations !== "function") continue;
|
|
465
|
+
let names = "";
|
|
466
|
+
try { names = getComputedStyle(node).animationName || ""; } catch { continue; }
|
|
467
|
+
if (!names || names === "none") continue;
|
|
468
|
+
const expected = [];
|
|
469
|
+
for (const name of names.split(",")) {
|
|
470
|
+
const trimmed = name.trim();
|
|
471
|
+
if (!trimmed || trimmed === "none" || trimmed.indexOf("vf-") === 0) continue;
|
|
472
|
+
expected.push(trimmed);
|
|
473
|
+
}
|
|
474
|
+
if (expected.length) generalCssEntries.push({ el: node, names: expected, start: generalClipStartFor(node) });
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function hasAnimationNamed(anims, name) {
|
|
479
|
+
for (const anim of anims) {
|
|
480
|
+
if (anim.animationName === name) return true;
|
|
481
|
+
}
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function generalClipStartFor(node) {
|
|
486
|
+
const holder = node.closest("[data-start]");
|
|
487
|
+
return holder ? readNumberAttr(holder, ["data-start"], 0) : 0;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Cycling animation-name through none re-creates dropped CSS animations
|
|
491
|
+
// declaratively (same trick as the caption resurrection above), preserving
|
|
492
|
+
// any authored inline animation-name.
|
|
493
|
+
function resurrectCssAnimations(node) {
|
|
494
|
+
try {
|
|
495
|
+
const inline = node.style.animationName;
|
|
496
|
+
node.style.animationName = "none";
|
|
497
|
+
void node.offsetWidth;
|
|
498
|
+
if (inline && inline !== "none") {
|
|
499
|
+
node.style.animationName = inline;
|
|
500
|
+
} else {
|
|
501
|
+
node.style.removeProperty("animation-name");
|
|
502
|
+
}
|
|
503
|
+
} catch {}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function scrubGeneralAnimation(anim, offsetMs) {
|
|
507
|
+
let target = offsetMs;
|
|
508
|
+
try {
|
|
509
|
+
const computed = anim.effect && typeof anim.effect.getComputedTiming === "function"
|
|
510
|
+
? anim.effect.getComputedTiming()
|
|
511
|
+
: null;
|
|
512
|
+
const endTime = computed && typeof computed.endTime === "number" ? computed.endTime : NaN;
|
|
513
|
+
if (Number.isFinite(endTime) && offsetMs >= endTime) {
|
|
514
|
+
// Same Chrome guard as the caption scrub: paused fill:none/backwards
|
|
515
|
+
// animations pushed past their effect end are destroyed permanently,
|
|
516
|
+
// so park them at 0; fill:forwards/both hold their final keyframe at
|
|
517
|
+
// the clamped end. Infinite-iteration animations (endTime Infinity)
|
|
518
|
+
// take the raw clip-relative offset like the official CSS adapter —
|
|
519
|
+
// the browser resolves the iteration phase.
|
|
520
|
+
target = computed.fill === "forwards" || computed.fill === "both" ? endTime : 0;
|
|
521
|
+
}
|
|
522
|
+
} catch {}
|
|
523
|
+
try {
|
|
524
|
+
anim.pause();
|
|
525
|
+
anim.currentTime = target;
|
|
526
|
+
} catch {}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function syncGeneralCssAnimations() {
|
|
530
|
+
for (const entry of generalCssEntries) {
|
|
531
|
+
const node = entry.el;
|
|
532
|
+
if (!node.isConnected) continue;
|
|
533
|
+
const offsetMs = Math.max(0, time - entry.start) * 1000;
|
|
534
|
+
let anims = [];
|
|
535
|
+
try { anims = node.getAnimations(); } catch { continue; }
|
|
536
|
+
let missing = null;
|
|
537
|
+
for (const name of entry.names) {
|
|
538
|
+
if (!hasAnimationNamed(anims, name)) (missing || (missing = [])).push(name);
|
|
539
|
+
}
|
|
540
|
+
if (missing) {
|
|
541
|
+
resurrectCssAnimations(node);
|
|
542
|
+
try { anims = node.getAnimations(); } catch { anims = []; }
|
|
543
|
+
// Names that still have no live animation (e.g. a display:none
|
|
544
|
+
// subtree) are dropped until the next discovery so a hidden element
|
|
545
|
+
// is not forced through a reflow every frame.
|
|
546
|
+
entry.names = entry.names.filter((name) => missing.indexOf(name) === -1 || hasAnimationNamed(anims, name));
|
|
547
|
+
}
|
|
548
|
+
for (const anim of anims) {
|
|
549
|
+
if (typeof anim.animationName !== "string" || anim.animationName.indexOf("vf-") === 0) continue;
|
|
550
|
+
scrubGeneralAnimation(anim, offsetMs);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
316
555
|
function apply(nextTime, options = {}) {
|
|
317
556
|
const forceSeek = Boolean(options.forceSeek);
|
|
318
557
|
const fromClock = Boolean(options.fromClock);
|
|
558
|
+
ensureDuration();
|
|
319
559
|
time = clampTime(nextTime);
|
|
320
560
|
let activeVideoProxy = null;
|
|
561
|
+
let activeVideoProxyStart = -Infinity;
|
|
321
562
|
const transitionWindows = collectTransitionWindows();
|
|
322
563
|
for (const clip of clips) {
|
|
323
564
|
const timing = readTiming(clip);
|
|
324
565
|
const hold = transitionHoldFor(clip, timing, transitionWindows);
|
|
325
|
-
|
|
566
|
+
// hyperframes-core clip windows are inclusive of both ends — the final
|
|
567
|
+
// frame holds.
|
|
568
|
+
const active = time >= timing.start && time <= timing.end + hold;
|
|
326
569
|
if (clip instanceof HTMLElement && !(clip instanceof HTMLAudioElement)) {
|
|
327
570
|
if (clip.getAttribute("data-vf-timeline-proxy") === "video") {
|
|
328
|
-
|
|
571
|
+
// Clip windows are inclusive of both ends, so at an exact butt-cut
|
|
572
|
+
// the outgoing AND incoming proxies are both active. Prefer the
|
|
573
|
+
// greatest data-start (timeline order — the incoming clip wins);
|
|
574
|
+
// DOM order only breaks ties between equal starts.
|
|
575
|
+
if (active && timing.start >= activeVideoProxyStart) {
|
|
576
|
+
activeVideoProxy = clip;
|
|
577
|
+
activeVideoProxyStart = timing.start;
|
|
578
|
+
}
|
|
329
579
|
} else {
|
|
330
580
|
setVisibility(clip, active);
|
|
331
581
|
}
|
|
@@ -349,6 +599,8 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
349
599
|
}
|
|
350
600
|
}
|
|
351
601
|
}
|
|
602
|
+
syncGeneralCssAnimations();
|
|
603
|
+
syncRuntimeAdapters();
|
|
352
604
|
if (backingVideo instanceof HTMLVideoElement) {
|
|
353
605
|
applyMediaState(backingVideo);
|
|
354
606
|
const shouldShowBackingVideo = !hasVideoProxies || Boolean(activeVideoProxy);
|
|
@@ -457,6 +709,13 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
457
709
|
if (!playing) apply(time, { forceSeek: true });
|
|
458
710
|
});
|
|
459
711
|
}
|
|
712
|
+
window.addEventListener("load", () => {
|
|
713
|
+
// Composition scripts may register adapter instances (GSAP timelines,
|
|
714
|
+
// Lottie players, ...) or start CSS animations on the load event —
|
|
715
|
+
// re-discover and re-scrub so late registrations preview correctly.
|
|
716
|
+
discoverGeneralCssAnimations();
|
|
717
|
+
if (!playing) apply(time, { forceSeek: true });
|
|
718
|
+
});
|
|
460
719
|
|
|
461
720
|
// Cache the parent frame's origin from the first accepted control message
|
|
462
721
|
// and pin all outbound postMessages to it. Falls back to document.referrer's
|
|
@@ -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.detail);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
add("vidfarm auth", "warn", "VIDFARM_API_KEY not set — cloud commands need it (local serve/lint/stills/speech engines work without 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
|