dsh-hyperframes 0.3.1 → 0.4.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/README.en.md +6 -5
- package/README.md +7 -6
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -0
- package/package.json +63 -63
- package/skills/embedded-captions/SKILL.md +28 -3
- package/skills/embedded-captions/references/aesthetic-principles.md +2 -3
- package/skills/embedded-captions/references/rail.md +1 -1
- package/skills/embedded-captions/scripts/check-occlusion.cjs +4 -1
- package/skills/embedded-captions/scripts/check-overflow.cjs +1 -0
- package/skills/embedded-captions/scripts/check-rail-climax.cjs +5 -1
- package/skills/embedded-captions/scripts/fixtures/heroless/theme.json +11 -0
- package/skills/embedded-captions/scripts/hf-cli.cjs +33 -0
- package/skills/embedded-captions/scripts/make-theme.cjs +95 -57
- package/skills/embedded-captions/scripts/make-theme.test.mjs +131 -0
- package/skills/embedded-captions/scripts/matte.cjs +1 -13
- package/skills/embedded-captions/scripts/measure-layout.cjs +2 -1
- package/skills/embedded-captions/scripts/preview-frames.cjs +39 -11
- package/skills/embedded-captions/scripts/preview-frames.test.mjs +24 -0
- package/skills/embedded-captions/scripts/render-and-composite.sh +8 -52
- package/skills/embedded-captions/scripts/safe-zones.cjs +4 -1
- package/skills/embedded-captions/scripts/transcribe.cjs +5 -14
- package/skills/embedded-captions/scripts/transcribe.test.mjs +41 -0
- package/skills/faceless-explainer/SKILL.md +20 -16
- package/skills/faceless-explainer/references/story-design.md +1 -1
- package/skills/faceless-explainer/scripts/assemble-index.mjs +6 -4
- package/skills/faceless-explainer/scripts/assemble-index.test.mjs +57 -2
- package/skills/faceless-explainer/scripts/audio.mjs +2 -0
- package/skills/faceless-explainer/scripts/build-frame.mjs +6 -3
- package/skills/faceless-explainer/scripts/captions.mjs +7 -4
- package/skills/faceless-explainer/scripts/frame-packets.mjs +4 -4
- package/skills/faceless-explainer/scripts/lib/bgm-volume.mjs +4 -0
- package/skills/faceless-explainer/scripts/lib/captured-fonts.mjs +58 -0
- package/skills/{hyperframes-core → faceless-explainer}/scripts/lib/frame-packets-core.mjs +5 -23
- package/skills/faceless-explainer/scripts/lib/storyboard.mjs +1 -1
- package/skills/faceless-explainer/scripts/lib/transitions.json +3 -3
- package/skills/faceless-explainer/scripts/transitions.mjs +1 -0
- package/skills/faceless-explainer/scripts/transitions.test.mjs +2 -0
- package/skills/faceless-explainer/sub-agents/frame-worker.md +1 -1
- package/skills/figma/SKILL.md +2 -0
- package/skills/general-video/SKILL.md +13 -11
- package/skills/general-video/scripts/frame-packets.mjs +4 -4
- package/skills/general-video/scripts/lib/frame-packets-core.mjs +194 -0
- package/skills/general-video/sub-agents/frame-worker.md +1 -1
- package/skills/hyperframes/SKILL.md +40 -30
- package/skills/{hyperframes-core → hyperframes}/references/brief-contract.md +15 -15
- package/skills/{hyperframes-core → hyperframes}/references/brief-format.md +8 -8
- package/skills/hyperframes/references/capability-menu.md +2 -2
- package/skills/{hyperframes-core → hyperframes}/references/frame-worker-core.md +1 -1
- package/skills/hyperframes/references/intent-interview.md +16 -16
- package/skills/hyperframes/references/plugin-installation.md +43 -0
- package/skills/{hyperframes-core → hyperframes}/references/production-loop.md +11 -11
- package/skills/hyperframes/references/review-loop.md +37 -0
- package/skills/hyperframes/references/route-briefs.md +1 -1
- package/skills/hyperframes/references/routes/motion-graphics.md +1 -1
- package/skills/{hyperframes-core → hyperframes}/references/script-format.md +3 -3
- package/skills/hyperframes/references/skill-lifecycle.md +2 -0
- package/skills/{hyperframes-core → hyperframes}/references/storyboard-format.md +3 -34
- package/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
- package/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
- package/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
- package/skills/hyperframes-animation/SKILL.md +5 -1
- package/skills/hyperframes-animation/adapters/gsap.md +1 -1
- package/skills/hyperframes-animation/adapters/lottie.md +15 -2
- package/skills/hyperframes-animation/adapters/three.md +14 -0
- package/skills/hyperframes-animation/blueprints/titlecard-reveal.md +1 -1
- package/skills/hyperframes-animation/references/motion-blur.md +133 -0
- package/skills/hyperframes-animation/rules/cursor-click-ripple.md +1 -1
- package/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +1 -1
- package/skills/hyperframes-animation/rules/hacker-flip-3d.md +1 -1
- package/skills/hyperframes-animation/rules/kinetic-beat-slam.md +2 -2
- package/skills/hyperframes-animation/rules/motion-blur-streak.md +1 -1
- package/skills/hyperframes-animation/rules/vertical-spring-ticker.md +1 -1
- package/skills/hyperframes-animation/scripts/package-loader.mjs +47 -16
- package/skills/hyperframes-animation/scripts/package-loader.test.mjs +52 -0
- package/skills/hyperframes-animation/techniques.md +1 -1
- package/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +3 -3
- package/skills/hyperframes-animation/transitions/css-push.md +4 -4
- package/skills/hyperframes-audio/SKILL.md +30 -22
- package/skills/hyperframes-audio/scripts/carve.mjs +6 -3
- package/skills/hyperframes-audio/scripts/carve.test.mjs +16 -1
- package/skills/hyperframes-cli/SKILL.md +44 -35
- package/skills/hyperframes-cli/references/init-and-scaffold.md +8 -6
- package/skills/hyperframes-cli/references/lint-validate-inspect.md +3 -3
- package/skills/hyperframes-cli/references/preview-render.md +35 -32
- package/skills/hyperframes-cli/references/upgrade-info-misc.md +50 -1
- package/skills/hyperframes-core/SKILL.md +30 -24
- package/skills/hyperframes-core/references/composition-patterns.md +3 -42
- package/skills/hyperframes-core/references/creator-editing-recipes.md +131 -7
- package/skills/hyperframes-core/references/data-attributes.md +11 -11
- package/skills/hyperframes-core/references/determinism-rules.md +2 -19
- package/skills/hyperframes-core/references/full-screen-motion.md +0 -9
- package/skills/hyperframes-core/references/minimal-composition.md +2 -2
- package/skills/hyperframes-core/references/sub-compositions.md +3 -66
- package/skills/hyperframes-core/references/tailwind.md +1 -20
- package/skills/hyperframes-core/references/tracks-and-clips.md +2 -6
- package/skills/hyperframes-core/references/variables-and-media.md +3 -3
- package/skills/hyperframes-creative/SKILL.md +2 -0
- package/skills/hyperframes-creative/references/house-style.md +15 -15
- package/skills/hyperframes-creative/references/story-spine.md +3 -1
- package/skills/hyperframes-creative/references/storyboard-recipe.md +57 -0
- package/skills/hyperframes-creative/references/typography.md +1 -1
- package/skills/hyperframes-creative/scripts/package-loader.mjs +47 -16
- package/skills/hyperframes-creative/scripts/package-loader.test.mjs +52 -0
- package/skills/hyperframes-keyframes/SKILL.md +4 -2
- package/skills/hyperframes-registry/SKILL.md +3 -1
- package/skills/hyperframes-registry/references/contributing.md +8 -2
- package/skills/hyperframes-registry/references/discovery.md +20 -34
- package/skills/hyperframes-studio/SKILL.md +77 -0
- package/skills/media-use/SKILL.md +14 -12
- package/skills/media-use/audio/references/captions/authoring.md +4 -0
- package/skills/media-use/audio/references/remove-background.md +1 -1
- package/skills/media-use/audio/references/tts-to-captions.md +11 -2
- package/skills/media-use/audio/references/tts.md +84 -6
- package/skills/media-use/audio/scripts/audio.mjs +15 -6
- package/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +113 -0
- package/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
- package/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
- package/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
- package/skills/media-use/audio/scripts/lib/bgm.mjs +2 -6
- package/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
- package/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
- package/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
- package/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
- package/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
- package/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
- package/skills/media-use/audio/scripts/lib/heygen.mjs +2 -1
- package/skills/media-use/audio/scripts/lib/tts.mjs +15 -3
- package/skills/media-use/audio/scripts/wait-bgm.mjs +8 -4
- package/skills/media-use/audio/scripts/wait-bgm.test.mjs +65 -0
- package/skills/media-use/references/audio.md +3 -2
- package/skills/media-use/references/grading.md +7 -7
- package/skills/media-use/references/media-treatment-recipes.md +1 -1
- package/skills/media-use/references/memory.md +2 -2
- package/skills/media-use/references/meta.md +2 -2
- package/skills/media-use/references/operations.md +15 -13
- package/skills/media-use/references/resolve.md +22 -11
- package/skills/media-use/references/setup-providers.md +11 -11
- package/skills/media-use/scripts/audio-duck.mjs +19 -27
- package/skills/media-use/scripts/compatibility.test.mjs +96 -0
- package/skills/media-use/scripts/lib/config-lock.mjs +45 -0
- package/skills/media-use/scripts/lib/duck.mjs +16 -10
- package/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
- package/skills/media-use/scripts/lib/media-home.mjs +20 -0
- package/skills/media-use/scripts/lib/npx-sync.mjs +28 -2
- package/skills/media-use/scripts/lib/prefs-store.mjs +2 -2
- package/skills/media-use/scripts/lib/recipe-store.mjs +2 -2
- package/skills/media-use/scripts/lib/telemetry.mjs +29 -41
- package/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
- package/skills/media-use/scripts/prefs.mjs +1 -1
- package/skills/media-use/scripts/recipe.mjs +1 -1
- package/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
- package/skills/media-use/scripts/resolve.mjs +27 -1267
- package/skills/media-use/scripts/transcribe.mjs +39 -25
- package/skills/media-use/scripts/transcribe.test.mjs +112 -0
- package/skills/media-use/scripts/transcript-cut.mjs +39 -8
- package/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
- package/skills/motion-graphics/SKILL.md +3 -1
- package/skills/motion-graphics/agents/builder.md +1 -0
- package/skills/motion-graphics/agents/director.md +2 -1
- package/skills/motion-graphics/catalog-map.md +25 -13
- package/skills/motion-graphics/categories/charts/module.md +2 -1
- package/skills/motion-graphics/categories/lower-thirds/module.md +4 -0
- package/skills/motion-graphics/categories/news/module.md +1 -1
- package/skills/motion-graphics/references/motion-vocabulary.md +4 -0
- package/skills/music-to-video/SKILL.md +8 -6
- package/skills/music-to-video/references/montage.md +3 -6
- package/skills/music-to-video/references/motion-primitives/3d-card-flip/index.html +10 -111
- package/skills/music-to-video/references/motion-primitives/3d-card-flip/scene.html +119 -0
- package/skills/music-to-video/references/motion-primitives/bg-flow-field/index.html +11 -284
- package/skills/music-to-video/references/motion-primitives/bg-flow-field/scene.html +294 -0
- package/skills/music-to-video/references/motion-primitives/binary-decrypt/index.html +10 -76
- package/skills/music-to-video/references/motion-primitives/binary-decrypt/scene.html +85 -0
- package/skills/music-to-video/references/motion-primitives/blur-resolve/index.html +10 -52
- package/skills/music-to-video/references/motion-primitives/blur-resolve/scene.html +60 -0
- package/skills/music-to-video/references/motion-primitives/braam-punch/index.html +10 -92
- package/skills/music-to-video/references/motion-primitives/braam-punch/scene.html +100 -0
- package/skills/music-to-video/references/motion-primitives/chromatic-split/index.html +10 -103
- package/skills/music-to-video/references/motion-primitives/chromatic-split/scene.html +111 -0
- package/skills/music-to-video/references/motion-primitives/chrome-sweep/index.html +10 -60
- package/skills/music-to-video/references/motion-primitives/chrome-sweep/scene.html +68 -0
- package/skills/music-to-video/references/motion-primitives/counting-punch/index.html +10 -110
- package/skills/music-to-video/references/motion-primitives/counting-punch/scene.html +119 -0
- package/skills/music-to-video/references/motion-primitives/crash-zoom-in/index.html +10 -112
- package/skills/music-to-video/references/motion-primitives/crash-zoom-in/scene.html +120 -0
- package/skills/music-to-video/references/motion-primitives/datamosh-smear/index.html +10 -121
- package/skills/music-to-video/references/motion-primitives/datamosh-smear/scene.html +131 -0
- package/skills/music-to-video/references/motion-primitives/directional-fill/index.html +10 -90
- package/skills/music-to-video/references/motion-primitives/directional-fill/scene.html +103 -0
- package/skills/music-to-video/references/motion-primitives/dolly-zoom/index.html +10 -94
- package/skills/music-to-video/references/motion-primitives/dolly-zoom/scene.html +102 -0
- package/skills/music-to-video/references/motion-primitives/electric-arc/index.html +10 -100
- package/skills/music-to-video/references/motion-primitives/electric-arc/scene.html +105 -0
- package/skills/music-to-video/references/motion-primitives/flash-cut/index.html +10 -89
- package/skills/music-to-video/references/motion-primitives/flash-cut/scene.html +97 -0
- package/skills/music-to-video/references/motion-primitives/gooey-metaball/index.html +10 -197
- package/skills/music-to-video/references/motion-primitives/gooey-metaball/scene.html +206 -0
- package/skills/music-to-video/references/motion-primitives/hard-cut/index.html +10 -74
- package/skills/music-to-video/references/motion-primitives/hard-cut/scene.html +82 -0
- package/skills/music-to-video/references/motion-primitives/hypercut-whip/index.html +10 -36
- package/skills/music-to-video/references/motion-primitives/hypercut-whip/scene.html +44 -0
- package/skills/music-to-video/references/motion-primitives/iris-open/index.html +10 -61
- package/skills/music-to-video/references/motion-primitives/iris-open/scene.html +69 -0
- package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/index.html +10 -55
- package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/scene.html +64 -0
- package/skills/music-to-video/references/motion-primitives/liquid-morph/index.html +10 -88
- package/skills/music-to-video/references/motion-primitives/liquid-morph/scene.html +96 -0
- package/skills/music-to-video/references/motion-primitives/mask-reveal/index.html +10 -66
- package/skills/music-to-video/references/motion-primitives/mask-reveal/scene.html +74 -0
- package/skills/music-to-video/references/motion-primitives/mosaic-pack/index.html +10 -81
- package/skills/music-to-video/references/motion-primitives/mosaic-pack/scene.html +89 -0
- package/skills/music-to-video/references/motion-primitives/neon-flicker/index.html +10 -65
- package/skills/music-to-video/references/motion-primitives/neon-flicker/scene.html +73 -0
- package/skills/music-to-video/references/motion-primitives/outline-to-fill/index.html +10 -74
- package/skills/music-to-video/references/motion-primitives/outline-to-fill/scene.html +82 -0
- package/skills/music-to-video/references/motion-primitives/palette-flip/index.html +10 -89
- package/skills/music-to-video/references/motion-primitives/palette-flip/scene.html +97 -0
- package/skills/music-to-video/references/motion-primitives/particle-burst/index.html +10 -98
- package/skills/music-to-video/references/motion-primitives/particle-burst/scene.html +106 -0
- package/skills/music-to-video/references/motion-primitives/pixel-dissolve/index.html +10 -78
- package/skills/music-to-video/references/motion-primitives/pixel-dissolve/scene.html +86 -0
- package/skills/music-to-video/references/motion-primitives/radial-burst-lines/index.html +10 -117
- package/skills/music-to-video/references/motion-primitives/radial-burst-lines/scene.html +130 -0
- package/skills/music-to-video/references/motion-primitives/screen-shake/index.html +10 -70
- package/skills/music-to-video/references/motion-primitives/screen-shake/scene.html +78 -0
- package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/index.html +10 -87
- package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/scene.html +100 -0
- package/skills/music-to-video/references/motion-primitives/spotlight-sweep/index.html +10 -94
- package/skills/music-to-video/references/motion-primitives/spotlight-sweep/scene.html +102 -0
- package/skills/music-to-video/references/motion-primitives/staggered-exit/index.html +10 -74
- package/skills/music-to-video/references/motion-primitives/staggered-exit/scene.html +82 -0
- package/skills/music-to-video/references/motion-primitives/text-spectral-rays/index.html +11 -271
- package/skills/music-to-video/references/motion-primitives/text-spectral-rays/scene.html +280 -0
- package/skills/music-to-video/references/motion-primitives/text-wave-distort/index.html +10 -92
- package/skills/music-to-video/references/motion-primitives/text-wave-distort/scene.html +106 -0
- package/skills/music-to-video/references/motion-primitives/tile-mosaic/index.html +10 -101
- package/skills/music-to-video/references/motion-primitives/tile-mosaic/scene.html +109 -0
- package/skills/music-to-video/references/motion-primitives/typewriter-reveal/index.html +10 -79
- package/skills/music-to-video/references/motion-primitives/typewriter-reveal/scene.html +91 -0
- package/skills/music-to-video/references/motion-primitives/word-grid-burst/index.html +10 -83
- package/skills/music-to-video/references/motion-primitives/word-grid-burst/scene.html +96 -0
- package/skills/music-to-video/references/planning.md +2 -2
- package/skills/music-to-video/scripts/lib/storyboard.mjs +1 -1
- package/skills/music-to-video/sub-agents/frame-worker.md +2 -2
- package/skills/pr-to-video/SKILL.md +20 -16
- package/skills/pr-to-video/references/code-vocabulary.md +14 -12
- package/skills/pr-to-video/references/story-design.md +1 -1
- package/skills/pr-to-video/scripts/assemble-index.mjs +6 -4
- package/skills/pr-to-video/scripts/assemble-index.test.mjs +57 -2
- package/skills/pr-to-video/scripts/audio.mjs +2 -0
- package/skills/pr-to-video/scripts/build-frame.mjs +6 -3
- package/skills/pr-to-video/scripts/captions.mjs +7 -4
- package/skills/pr-to-video/scripts/captions.test.mjs +41 -0
- package/skills/pr-to-video/scripts/frame-packets.mjs +4 -4
- package/skills/pr-to-video/scripts/lib/bgm-volume.mjs +4 -0
- package/skills/pr-to-video/scripts/lib/captured-fonts.mjs +58 -0
- package/skills/pr-to-video/scripts/lib/frame-packets-core.mjs +194 -0
- package/skills/pr-to-video/scripts/lib/storyboard.mjs +1 -1
- package/skills/pr-to-video/scripts/lib/transitions.json +3 -3
- package/skills/pr-to-video/scripts/transitions.mjs +7 -5
- package/skills/pr-to-video/sub-agents/frame-worker.md +1 -1
- package/skills/product-launch-video/SKILL.md +20 -16
- package/skills/product-launch-video/references/story-design.md +1 -1
- package/skills/product-launch-video/scripts/assemble-index.mjs +6 -4
- package/skills/product-launch-video/scripts/assemble-index.test.mjs +57 -2
- package/skills/product-launch-video/scripts/audio.mjs +2 -0
- package/skills/product-launch-video/scripts/audio.test.mjs +16 -0
- package/skills/product-launch-video/scripts/build-frame-subsets.test.mjs +152 -0
- package/skills/product-launch-video/scripts/build-frame.mjs +6 -3
- package/skills/product-launch-video/scripts/captions.mjs +7 -4
- package/skills/product-launch-video/scripts/frame-packets.mjs +4 -4
- package/skills/product-launch-video/scripts/lib/bgm-volume.mjs +4 -0
- package/skills/product-launch-video/scripts/lib/captured-fonts.mjs +58 -0
- package/skills/product-launch-video/scripts/lib/frame-packets-core.mjs +194 -0
- package/skills/product-launch-video/scripts/lib/storyboard.mjs +1 -1
- package/skills/product-launch-video/scripts/lib/transitions.json +3 -3
- package/skills/product-launch-video/scripts/transitions.mjs +7 -5
- package/skills/product-launch-video/scripts/transitions.test.mjs +68 -0
- package/skills/product-launch-video/sub-agents/frame-worker.md +1 -1
- package/skills/remotion-to-hyperframes/SKILL.md +7 -4
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/expected.json +5 -5
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/compositions/title.html +31 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/index.html +10 -25
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/README.md +8 -8
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/expected.json +9 -9
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-1.html +35 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-2.html +35 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-3.html +36 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/index.html +28 -71
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/expected.json +3 -3
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-1.html +52 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-2.html +99 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-3.html +55 -0
- package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/index.html +13 -212
- package/skills/remotion-to-hyperframes/references/api-map.md +16 -16
- package/skills/remotion-to-hyperframes/references/limitations.md +7 -7
- package/skills/remotion-to-hyperframes/references/lottie.md +5 -7
- package/skills/remotion-to-hyperframes/references/media.md +3 -3
- package/skills/remotion-to-hyperframes/references/parameters.md +5 -0
- package/skills/remotion-to-hyperframes/references/sequencing.md +71 -18
- package/skills/slideshow/SKILL.md +4 -1
- package/skills/slideshow/references/standalone-harness.md +0 -3
- package/skills/talking-head-recut/SKILL.md +10 -1
- package/skills/hyperframes-core/references/review-loop.md +0 -41
- package/skills/media-use/scripts/lib/adopt.mjs +0 -128
- package/skills/media-use/scripts/lib/adopt.test.mjs +0 -95
- package/skills/media-use/scripts/lib/bgm-provider.mjs +0 -20
- package/skills/media-use/scripts/lib/brand-provider.mjs +0 -59
- package/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +0 -108
- package/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +0 -85
- package/skills/media-use/scripts/lib/cache.mjs +0 -150
- package/skills/media-use/scripts/lib/candidates.mjs +0 -91
- package/skills/media-use/scripts/lib/candidates.test.mjs +0 -155
- package/skills/media-use/scripts/lib/codex-provider.mjs +0 -161
- package/skills/media-use/scripts/lib/codex-provider.test.mjs +0 -34
- package/skills/media-use/scripts/lib/coverage.test.mjs +0 -117
- package/skills/media-use/scripts/lib/cube-build.mjs +0 -181
- package/skills/media-use/scripts/lib/cube-build.test.mjs +0 -80
- package/skills/media-use/scripts/lib/cube-validate.mjs +0 -198
- package/skills/media-use/scripts/lib/cube-validate.test.mjs +0 -125
- package/skills/media-use/scripts/lib/cutlist.test.mjs +0 -148
- package/skills/media-use/scripts/lib/duck.test.mjs +0 -118
- package/skills/media-use/scripts/lib/error-diffusion.test.mjs +0 -102
- package/skills/media-use/scripts/lib/freeze.mjs +0 -70
- package/skills/media-use/scripts/lib/freeze.test.mjs +0 -46
- package/skills/media-use/scripts/lib/grade-analyzer.mjs +0 -264
- package/skills/media-use/scripts/lib/grade-analyzer.test.mjs +0 -285
- package/skills/media-use/scripts/lib/heygen-cli.mjs +0 -191
- package/skills/media-use/scripts/lib/heygen-cli.test.mjs +0 -301
- package/skills/media-use/scripts/lib/heygen-search.mjs +0 -45
- package/skills/media-use/scripts/lib/heygen-search.test.mjs +0 -49
- package/skills/media-use/scripts/lib/heygen-video-provider.mjs +0 -127
- package/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +0 -344
- package/skills/media-use/scripts/lib/image-provider.mjs +0 -44
- package/skills/media-use/scripts/lib/local-models.mjs +0 -318
- package/skills/media-use/scripts/lib/local-models.test.mjs +0 -220
- package/skills/media-use/scripts/lib/local-run.mjs +0 -78
- package/skills/media-use/scripts/lib/local-run.test.mjs +0 -121
- package/skills/media-use/scripts/lib/logo-provider.mjs +0 -222
- package/skills/media-use/scripts/lib/logo-provider.test.mjs +0 -137
- package/skills/media-use/scripts/lib/ltx-video-provider.mjs +0 -94
- package/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +0 -316
- package/skills/media-use/scripts/lib/lut-preset-provider.mjs +0 -266
- package/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +0 -176
- package/skills/media-use/scripts/lib/manifest.test.mjs +0 -388
- package/skills/media-use/scripts/lib/match.mjs +0 -47
- package/skills/media-use/scripts/lib/mflux-provider.mjs +0 -128
- package/skills/media-use/scripts/lib/mflux-provider.test.mjs +0 -174
- package/skills/media-use/scripts/lib/misses.mjs +0 -49
- package/skills/media-use/scripts/lib/misses.test.mjs +0 -78
- package/skills/media-use/scripts/lib/npx-sync.test.mjs +0 -50
- package/skills/media-use/scripts/lib/parakeet-words.test.mjs +0 -44
- package/skills/media-use/scripts/lib/prefs-store.test.mjs +0 -189
- package/skills/media-use/scripts/lib/probe.mjs +0 -39
- package/skills/media-use/scripts/lib/probe.test.mjs +0 -31
- package/skills/media-use/scripts/lib/providers.mjs +0 -5
- package/skills/media-use/scripts/lib/recipe-store.test.mjs +0 -367
- package/skills/media-use/scripts/lib/registry.mjs +0 -218
- package/skills/media-use/scripts/lib/registry.test.mjs +0 -261
- package/skills/media-use/scripts/lib/search.mjs +0 -24
- package/skills/media-use/scripts/lib/search.test.mjs +0 -32
- package/skills/media-use/scripts/lib/sfx-provider.mjs +0 -23
- package/skills/media-use/scripts/lib/specs.mjs +0 -132
- package/skills/media-use/scripts/lib/specs.test.mjs +0 -157
- package/skills/media-use/scripts/lib/stats.mjs +0 -117
- package/skills/media-use/scripts/lib/stats.test.mjs +0 -165
- package/skills/media-use/scripts/lib/telemetry.test.mjs +0 -373
- package/skills/media-use/scripts/lib/tts-local-provider.mjs +0 -92
- package/skills/media-use/scripts/lib/tts-local-provider.test.mjs +0 -72
- package/skills/media-use/scripts/lib/usage.mjs +0 -57
- package/skills/media-use/scripts/lib/usage.test.mjs +0 -54
- package/skills/media-use/scripts/lib/voice-provider.mjs +0 -57
- package/skills/media-use/scripts/lib/voice-provider.test.mjs +0 -46
- package/skills/media-use/scripts/resolve.test.mjs +0 -1120
- /package/skills/{hyperframes-core → hyperframes}/references/subagent-dispatch.md +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Media downloads use public HTTP(S) URLs. Validate every redirect target;
|
|
2
|
+
// a provider result must meet the same host policy as a direct ingest URL.
|
|
3
|
+
// Public HTTPS-to-HTTP redirects are allowed, matching direct HTTP support.
|
|
4
|
+
// This is a literal-host policy, not DNS pinning: DNS resolution remains trusted.
|
|
5
|
+
|
|
6
|
+
import { BlockList, isIP } from "node:net";
|
|
7
|
+
|
|
8
|
+
const blocked = new BlockList();
|
|
9
|
+
for (const [network, prefix] of [
|
|
10
|
+
["0.0.0.0", 8],
|
|
11
|
+
["10.0.0.0", 8],
|
|
12
|
+
["100.64.0.0", 10],
|
|
13
|
+
["127.0.0.0", 8],
|
|
14
|
+
["169.254.0.0", 16],
|
|
15
|
+
["172.16.0.0", 12],
|
|
16
|
+
["192.0.0.0", 24],
|
|
17
|
+
["192.0.2.0", 24],
|
|
18
|
+
["192.88.99.0", 24],
|
|
19
|
+
["192.168.0.0", 16],
|
|
20
|
+
["198.18.0.0", 15],
|
|
21
|
+
["198.51.100.0", 24],
|
|
22
|
+
["203.0.113.0", 24],
|
|
23
|
+
["224.0.0.0", 4],
|
|
24
|
+
["240.0.0.0", 4],
|
|
25
|
+
])
|
|
26
|
+
blocked.addSubnet(network, prefix, "ipv4");
|
|
27
|
+
for (const [network, prefix] of [
|
|
28
|
+
["::", 128],
|
|
29
|
+
["::1", 128],
|
|
30
|
+
["fc00::", 7],
|
|
31
|
+
["fe80::", 10],
|
|
32
|
+
["fec0::", 10],
|
|
33
|
+
["ff00::", 8],
|
|
34
|
+
["2001:db8::", 32],
|
|
35
|
+
])
|
|
36
|
+
blocked.addSubnet(network, prefix, "ipv6");
|
|
37
|
+
|
|
38
|
+
export function isPublicMediaUrl(value) {
|
|
39
|
+
try {
|
|
40
|
+
const url = new URL(value);
|
|
41
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
42
|
+
const host = url.hostname.replace(/\.$/, "");
|
|
43
|
+
if (
|
|
44
|
+
host === "localhost" ||
|
|
45
|
+
host.endsWith(".localhost") ||
|
|
46
|
+
host.endsWith(".local") ||
|
|
47
|
+
host.endsWith(".internal")
|
|
48
|
+
)
|
|
49
|
+
return false;
|
|
50
|
+
const address = host.replace(/^\[|\]$/g, "");
|
|
51
|
+
const family = isIP(address);
|
|
52
|
+
return family === 0 || !blocked.check(address, family === 4 ? "ipv4" : "ipv6");
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function fetchMedia(url, { method = "GET", signal, fetchImpl = fetch } = {}) {
|
|
59
|
+
let current = String(url);
|
|
60
|
+
for (let hop = 0; hop <= 5; hop++) {
|
|
61
|
+
if (!isPublicMediaUrl(current))
|
|
62
|
+
throw new Error("Media download blocked: URL is not public HTTP(S)");
|
|
63
|
+
const response = await fetchImpl(current, { method, signal, redirect: "manual" });
|
|
64
|
+
if (!(response.status >= 300 && response.status < 400)) return response;
|
|
65
|
+
const location = response.headers.get("location");
|
|
66
|
+
if (!location) return response;
|
|
67
|
+
await response.body?.cancel();
|
|
68
|
+
current = new URL(location, current).href;
|
|
69
|
+
}
|
|
70
|
+
throw new Error("Media download exceeded redirect limit");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Stream and abort once the cap is crossed, so a lying or chunked body can't buffer past it.
|
|
74
|
+
export async function readCappedBody(res, maxBytes, label) {
|
|
75
|
+
const declared = Number(res.headers.get("content-length"));
|
|
76
|
+
if (declared > maxBytes) throw new Error(`${label}: ${declared} bytes exceeds ${maxBytes} cap`);
|
|
77
|
+
const chunks = [];
|
|
78
|
+
let total = 0;
|
|
79
|
+
for await (const chunk of res.body) {
|
|
80
|
+
total += chunk.length;
|
|
81
|
+
if (total > maxBytes) throw new Error(`${label}: stream exceeds ${maxBytes} cap`);
|
|
82
|
+
chunks.push(chunk);
|
|
83
|
+
}
|
|
84
|
+
return Buffer.concat(chunks, total);
|
|
85
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
// The one owner of where the person's media library lives. This repo's test runs set
|
|
5
|
+
// HYPERFRAMES_MEDIA_HOME_REQUIRED, so a test that forgot HYPERFRAMES_MEDIA_HOME fails instead
|
|
6
|
+
// of writing fixtures into the media library apps list as the person's own files.
|
|
7
|
+
export function mediaHome() {
|
|
8
|
+
const override = process.env.HYPERFRAMES_MEDIA_HOME;
|
|
9
|
+
if (override) return override;
|
|
10
|
+
if (process.env.HYPERFRAMES_MEDIA_HOME_REQUIRED) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
"media-use: a test reached the real ~/.media; set HYPERFRAMES_MEDIA_HOME to a temp dir",
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
return homedir();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function globalMediaDir() {
|
|
19
|
+
return join(mediaHome(), ".media");
|
|
20
|
+
}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import {
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
|
|
4
|
+
function resolveNpxCliPath(env, pathExists) {
|
|
5
|
+
const npmExecPath = env.npm_execpath;
|
|
6
|
+
const nodeExecPath = env.npm_node_execpath || process.execPath;
|
|
7
|
+
if (npmExecPath) {
|
|
8
|
+
const fileName = npmExecPath.replace(/\\/g, "/").split("/").pop()?.toLowerCase();
|
|
9
|
+
const candidate =
|
|
10
|
+
fileName === "npx-cli.js" ? npmExecPath : join(dirname(npmExecPath), "npx-cli.js");
|
|
11
|
+
if (pathExists(candidate)) return candidate;
|
|
12
|
+
}
|
|
13
|
+
const besideNode = join(dirname(nodeExecPath), "node_modules", "npm", "bin", "npx-cli.js");
|
|
14
|
+
return pathExists(besideNode) ? besideNode : null;
|
|
15
|
+
}
|
|
3
16
|
|
|
4
17
|
// Sync-spawn analog of the audio engine's spawnP, for execFileSync call sites
|
|
5
18
|
// that must hard-fail (rather than fall through to another provider) when npx
|
|
@@ -18,7 +31,20 @@ export function resolveNpxInvocation(
|
|
|
18
31
|
env = process.env,
|
|
19
32
|
pathExists = existsSync,
|
|
20
33
|
) {
|
|
21
|
-
const resolved =
|
|
34
|
+
const resolved =
|
|
35
|
+
platform !== "win32"
|
|
36
|
+
? { cmd: "npx", args: argv, opts: { stdio: "ignore", ...opts } }
|
|
37
|
+
: (() => {
|
|
38
|
+
const nodeExecPath = env.npm_node_execpath || process.execPath;
|
|
39
|
+
const npxCliPath = resolveNpxCliPath(env, pathExists);
|
|
40
|
+
return npxCliPath
|
|
41
|
+
? {
|
|
42
|
+
cmd: nodeExecPath,
|
|
43
|
+
args: [npxCliPath, ...argv.map((arg) => String(arg))],
|
|
44
|
+
opts: { stdio: "ignore", windowsHide: true, ...opts },
|
|
45
|
+
}
|
|
46
|
+
: null;
|
|
47
|
+
})();
|
|
22
48
|
if (!resolved) {
|
|
23
49
|
// npx-on-win32 with no resolvable npx-cli.js — same terminal condition
|
|
24
50
|
// spawnP warns about, surfaced as a throw for callers with no fallback.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
|
+
import { globalMediaDir } from "./media-home.mjs";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Remembered defaults — the lightweight tier of HyperFrames user memory.
|
|
@@ -41,7 +41,7 @@ export function projectPrefsPath(projectDir) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export function userPrefsPath() {
|
|
44
|
-
return join(
|
|
44
|
+
return join(globalMediaDir(), PREFS_FILE);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function emptyFile() {
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
rmSync,
|
|
9
9
|
writeFileSync,
|
|
10
10
|
} from "node:fs";
|
|
11
|
-
import { homedir } from "node:os";
|
|
12
11
|
import { basename, join, resolve } from "node:path";
|
|
12
|
+
import { globalMediaDir } from "./media-home.mjs";
|
|
13
13
|
import { appendRecord, mediaDir, nextId } from "./manifest.mjs";
|
|
14
14
|
import { regenerateIndex } from "./index-gen.mjs";
|
|
15
15
|
import { mergedPreferences } from "./prefs-store.mjs";
|
|
@@ -58,7 +58,7 @@ export function projectRecipesDir(projectDir) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export function userRecipesDir() {
|
|
61
|
-
return join(
|
|
61
|
+
return join(globalMediaDir(), "recipes");
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
export function slugifyRecipeName(name) {
|
|
@@ -1,20 +1,13 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// ~/.hyperframes/config.json, plus a $identify to the HeyGen account on sign-in,
|
|
4
|
-
// so a person is one PostHog profile across surfaces — not a fresh id per tool.
|
|
5
|
-
// Not fully anonymous by design (it must dedupe): pseudonymous before sign-in,
|
|
6
|
-
// account-linked after. Event PROPERTIES stay coarse — media TYPE, resolution
|
|
7
|
-
// SOURCE, winning PROVIDER — never the intent text, file names, or paths.
|
|
8
|
-
//
|
|
9
|
-
// Same public PostHog project key as the CLI (a write-only ingestion key, safe
|
|
10
|
-
// to ship), same opt-outs (DO_NOT_TRACK / HYPERFRAMES_NO_TELEMETRY / CI / dev),
|
|
11
|
-
// and $ip:null so no IP is recorded. Fire-and-forget: telemetry never blocks a
|
|
12
|
-
// resolve and never throws into it.
|
|
1
|
+
// Usage tracking shares the CLI and Studio identity. Properties stay coarse and
|
|
2
|
+
// never carry intent text, file names, or paths.
|
|
13
3
|
|
|
14
4
|
import { randomUUID } from "node:crypto";
|
|
15
|
-
import
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
16
7
|
import { homedir } from "node:os";
|
|
17
|
-
import { join } from "node:path";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
import { withFileLock } from "./config-lock.mjs";
|
|
10
|
+
import { globalMediaDir } from "./media-home.mjs";
|
|
18
11
|
|
|
19
12
|
const POSTHOG_API_KEY = "phc_zjjbX0PnWxERXrMHhkEJWj9A9BhGVLRReICgsfTMmpx";
|
|
20
13
|
const POSTHOG_HOST = "https://us.i.posthog.com";
|
|
@@ -22,10 +15,6 @@ const TIMEOUT_MS = 1500;
|
|
|
22
15
|
let identifiedAccount = false;
|
|
23
16
|
let warnedNonDefaultHost = false;
|
|
24
17
|
|
|
25
|
-
// Same CI/test signals the test suite itself sets (resolve.test.mjs's U7 test
|
|
26
|
-
// sets NODE_ENV=test and clears CI to prove the interception seam works) —
|
|
27
|
-
// reused here, not a new heuristic, so that deliberate test usage never
|
|
28
|
-
// triggers the warning below.
|
|
29
18
|
function isTestOrCiContext() {
|
|
30
19
|
return (
|
|
31
20
|
process.env.CI === "true" ||
|
|
@@ -35,16 +24,6 @@ function isTestOrCiContext() {
|
|
|
35
24
|
);
|
|
36
25
|
}
|
|
37
26
|
|
|
38
|
-
// Test-only interception seam: a real HTTP destination a test can point at,
|
|
39
|
-
// so a spawned-child test (resolve.test.mjs) can prove track() never reaches
|
|
40
|
-
// production rather than trusting DO_NOT_TRACK alone (a future call site or
|
|
41
|
-
// test could forget to set that env var). Falls back to the real production
|
|
42
|
-
// host whenever unset — production behavior is unchanged.
|
|
43
|
-
//
|
|
44
|
-
// Safety net: if this ever leaks into a real user's shell, track() would
|
|
45
|
-
// silently redirect to a likely-dead host and postBatch()'s catch{} would
|
|
46
|
-
// swallow the failure with zero signal. Surface one stderr warning outside
|
|
47
|
-
// test/CI contexts so a real user gets some indication instead of silence.
|
|
48
27
|
function posthogHost() {
|
|
49
28
|
const override = process.env.MEDIA_USE_TELEMETRY_HOST;
|
|
50
29
|
if (override && !warnedNonDefaultHost && !isTestOrCiContext()) {
|
|
@@ -67,12 +46,7 @@ export function optedOut() {
|
|
|
67
46
|
);
|
|
68
47
|
}
|
|
69
48
|
|
|
70
|
-
//
|
|
71
|
-
// (packages/cli/src/telemetry/config.ts — same path, same `anonymousId` /
|
|
72
|
-
// `telemetryNoticeShown` fields). Read and write that same file so media-use is
|
|
73
|
-
// the same PostHog person and shows the notice once per person, not per tool.
|
|
74
|
-
// Computed per call (not a module const) so it honors HOME at runtime — tests
|
|
75
|
-
// sandbox HOME, and os.homedir() re-reads it each call.
|
|
49
|
+
// Read and write the shared config so media-use keeps one identity per install.
|
|
76
50
|
function sharedConfigPath() {
|
|
77
51
|
return join(homedir(), ".hyperframes", "config.json");
|
|
78
52
|
}
|
|
@@ -90,10 +64,24 @@ function readSharedConfig() {
|
|
|
90
64
|
return {};
|
|
91
65
|
}
|
|
92
66
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
67
|
+
// Best effort: skipped when the lock cannot be taken or the file cannot be read, never written unlocked.
|
|
68
|
+
function updateSharedConfig(patch) {
|
|
69
|
+
const file = sharedConfigPath();
|
|
70
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
71
|
+
try {
|
|
72
|
+
withFileLock(`${file}.lock`, fs, () => {
|
|
73
|
+
let config = {};
|
|
74
|
+
try {
|
|
75
|
+
config = JSON.parse(readFileSync(file, "utf8"));
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error.code !== "ENOENT") return;
|
|
78
|
+
}
|
|
79
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) return;
|
|
80
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
81
|
+
writeFileSync(tmp, JSON.stringify({ ...config, ...patch }, null, 2) + "\n", { mode: 0o600 });
|
|
82
|
+
renameSync(tmp, file);
|
|
83
|
+
});
|
|
84
|
+
} catch {}
|
|
97
85
|
}
|
|
98
86
|
|
|
99
87
|
// Adopt a pre-existing media-use-only id (~/.media/anon-id from before this
|
|
@@ -101,7 +89,7 @@ function writeSharedConfig(config) {
|
|
|
101
89
|
// one — otherwise cross-surface continuity would start over on upgrade.
|
|
102
90
|
function legacyMediaAnonId() {
|
|
103
91
|
try {
|
|
104
|
-
const file = join(
|
|
92
|
+
const file = join(globalMediaDir(), "anon-id");
|
|
105
93
|
if (existsSync(file)) {
|
|
106
94
|
const id = readFileSync(file, "utf8").trim();
|
|
107
95
|
if (id) return id;
|
|
@@ -121,7 +109,7 @@ function anonymousId() {
|
|
|
121
109
|
return config.anonymousId.trim();
|
|
122
110
|
}
|
|
123
111
|
const id = legacyMediaAnonId() || randomUUID();
|
|
124
|
-
|
|
112
|
+
updateSharedConfig({ anonymousId: id });
|
|
125
113
|
return id;
|
|
126
114
|
} catch {
|
|
127
115
|
return "anon"; // best-effort; a shared bucket is fine if the fs is read-only
|
|
@@ -161,7 +149,7 @@ function showTelemetryNotice() {
|
|
|
161
149
|
"If you sign in to HeyGen, usage links to your account email or username. Opt out with HYPERFRAMES_NO_TELEMETRY=1 or DO_NOT_TRACK=1.",
|
|
162
150
|
].join("\n"),
|
|
163
151
|
);
|
|
164
|
-
|
|
152
|
+
updateSharedConfig({ telemetryNoticeShown: true });
|
|
165
153
|
} catch {
|
|
166
154
|
// notice is best-effort; never surface into the command
|
|
167
155
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function round3(n) {
|
|
2
|
+
return Math.round(Number(n) * 1000) / 1000;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
// 30ms in/out ramps kill the click at every concat boundary. A segment shorter
|
|
6
|
+
// than 4x the ramp would spend its whole length fading, so scale down there and
|
|
7
|
+
// skip entirely on a degenerate one. fadeIn/fadeOut are false at the export's
|
|
8
|
+
// own true start/end, where there is no splice to smooth.
|
|
9
|
+
export function fadeFilterFor(durationSeconds, { fadeIn, fadeOut }) {
|
|
10
|
+
if (!fadeIn && !fadeOut) return null;
|
|
11
|
+
const FADE_SECONDS = 0.03;
|
|
12
|
+
if (!Number.isFinite(durationSeconds) || durationSeconds <= 0.01) return null;
|
|
13
|
+
const d = Math.min(FADE_SECONDS, durationSeconds / 4);
|
|
14
|
+
const parts = [];
|
|
15
|
+
if (fadeIn) parts.push(`afade=t=in:st=0:d=${round3(d)}`);
|
|
16
|
+
if (fadeOut) {
|
|
17
|
+
const out = round3(durationSeconds - d);
|
|
18
|
+
if (out > 0) parts.push(`afade=t=out:st=${out}:d=${round3(d)}`);
|
|
19
|
+
}
|
|
20
|
+
return parts.length ? parts.join(",") : null;
|
|
21
|
+
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Record one confirmed brief answer into the project tier; the same value
|
|
12
12
|
* confirmed in two different projects promotes the key to the user tier.
|
|
13
13
|
*
|
|
14
|
-
* Consumption rules live in hyperframes
|
|
14
|
+
* Consumption rules live in hyperframes/references/brief-contract.md § 2
|
|
15
15
|
* (Remembered defaults): a remembered value becomes the recommended option
|
|
16
16
|
* with a receipt — it never skips a question.
|
|
17
17
|
*/
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* frame.md over the project's, and print the brief values + skeleton path.
|
|
20
20
|
*
|
|
21
21
|
* When recipes are offered/consumed is the review loop's and the intent
|
|
22
|
-
* layer's business — see hyperframes
|
|
22
|
+
* layer's business — see hyperframes/references/review-loop.md § 4 and
|
|
23
23
|
* the intent layer's recipe check (hyperframes SKILL.md § 4).
|
|
24
24
|
*/
|
|
25
25
|
import { parseArgs } from "node:util";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { copyFileSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { delimiter, join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { test } from "node:test";
|
|
8
|
+
|
|
9
|
+
test(
|
|
10
|
+
"plugin resolver uses the release CLI without a repository checkout",
|
|
11
|
+
{ skip: process.platform === "win32" },
|
|
12
|
+
(t) => {
|
|
13
|
+
const dir = mkdtempSync(join(tmpdir(), "hf-resolve-plugin-"));
|
|
14
|
+
t.after(() => rmSync(dir, { recursive: true, force: true }));
|
|
15
|
+
mkdirSync(join(dir, "lib"));
|
|
16
|
+
for (const file of ["resolve.mjs", "lib/npx-sync.mjs"]) {
|
|
17
|
+
copyFileSync(fileURLToPath(new URL(file, import.meta.url)), join(dir, file));
|
|
18
|
+
}
|
|
19
|
+
writeFileSync(
|
|
20
|
+
join(dir, "npx"),
|
|
21
|
+
`#!${process.execPath}\nconsole.log(JSON.stringify({args:process.argv.slice(2),skip:process.env.HYPERFRAMES_SKIP_SKILLS}));process.exit(7);`,
|
|
22
|
+
{ mode: 0o755 },
|
|
23
|
+
);
|
|
24
|
+
const result = spawnSync(process.execPath, [join(dir, "resolve.mjs"), "--intent", "a & b"], {
|
|
25
|
+
cwd: dir,
|
|
26
|
+
encoding: "utf8",
|
|
27
|
+
env: {
|
|
28
|
+
...process.env,
|
|
29
|
+
PATH: `${dir}${delimiter}${process.env.PATH}`,
|
|
30
|
+
HYPERFRAMES_PLUGIN_VERSION: "1.2.3",
|
|
31
|
+
HYPERFRAMES_SKIP_SKILLS: "1",
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
assert.equal(result.status, 7, result.stderr);
|
|
35
|
+
assert.deepEqual(JSON.parse(result.stdout), {
|
|
36
|
+
args: ["--yes", "hyperframes@1.2.3", "media-use", "resolve", "--intent", "a & b"],
|
|
37
|
+
skip: "1",
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
test("helper package override keeps a contributor's local CLI", (t) => {
|
|
43
|
+
const root = mkdtempSync(join(tmpdir(), "hf-resolve-local-"));
|
|
44
|
+
t.after(() => rmSync(root, { recursive: true, force: true }));
|
|
45
|
+
const scripts = join(root, "skills/media-use/scripts");
|
|
46
|
+
mkdirSync(join(scripts, "lib"), { recursive: true });
|
|
47
|
+
mkdirSync(join(root, "packages/cli/dist"), { recursive: true });
|
|
48
|
+
for (const file of ["resolve.mjs", "lib/npx-sync.mjs"]) {
|
|
49
|
+
copyFileSync(fileURLToPath(new URL(file, import.meta.url)), join(scripts, file));
|
|
50
|
+
}
|
|
51
|
+
writeFileSync(join(root, "packages/cli/dist/cli.js"), 'console.log("local-cli");');
|
|
52
|
+
const result = spawnSync(process.execPath, [join(scripts, "resolve.mjs")], {
|
|
53
|
+
encoding: "utf8",
|
|
54
|
+
env: {
|
|
55
|
+
...process.env,
|
|
56
|
+
HYPERFRAMES_PLUGIN_VERSION: "",
|
|
57
|
+
HYPERFRAMES_SKILL_PKG_VERSION: "0.8.79",
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
assert.equal(result.status, 0, result.stderr);
|
|
61
|
+
assert.equal(result.stdout.trim(), "local-cli");
|
|
62
|
+
});
|