dsh-hyperframes 0.3.2 → 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.
Files changed (375) hide show
  1. package/README.en.md +4 -3
  2. package/README.md +5 -4
  3. package/lib/index.d.ts +1 -1
  4. package/lib/index.js +1 -0
  5. package/package.json +2 -2
  6. package/skills/embedded-captions/SKILL.md +28 -3
  7. package/skills/embedded-captions/references/aesthetic-principles.md +2 -3
  8. package/skills/embedded-captions/references/rail.md +1 -1
  9. package/skills/embedded-captions/scripts/check-occlusion.cjs +4 -1
  10. package/skills/embedded-captions/scripts/check-overflow.cjs +1 -0
  11. package/skills/embedded-captions/scripts/check-rail-climax.cjs +5 -1
  12. package/skills/embedded-captions/scripts/fixtures/heroless/theme.json +11 -0
  13. package/skills/embedded-captions/scripts/hf-cli.cjs +33 -0
  14. package/skills/embedded-captions/scripts/make-theme.cjs +95 -57
  15. package/skills/embedded-captions/scripts/make-theme.test.mjs +131 -0
  16. package/skills/embedded-captions/scripts/matte.cjs +1 -13
  17. package/skills/embedded-captions/scripts/measure-layout.cjs +2 -1
  18. package/skills/embedded-captions/scripts/preview-frames.cjs +39 -11
  19. package/skills/embedded-captions/scripts/preview-frames.test.mjs +24 -0
  20. package/skills/embedded-captions/scripts/render-and-composite.sh +8 -52
  21. package/skills/embedded-captions/scripts/safe-zones.cjs +4 -1
  22. package/skills/embedded-captions/scripts/transcribe.cjs +5 -14
  23. package/skills/embedded-captions/scripts/transcribe.test.mjs +41 -0
  24. package/skills/faceless-explainer/SKILL.md +20 -16
  25. package/skills/faceless-explainer/references/story-design.md +1 -1
  26. package/skills/faceless-explainer/scripts/assemble-index.mjs +6 -4
  27. package/skills/faceless-explainer/scripts/assemble-index.test.mjs +57 -2
  28. package/skills/faceless-explainer/scripts/audio.mjs +2 -0
  29. package/skills/faceless-explainer/scripts/build-frame.mjs +6 -3
  30. package/skills/faceless-explainer/scripts/captions.mjs +7 -4
  31. package/skills/faceless-explainer/scripts/frame-packets.mjs +4 -4
  32. package/skills/faceless-explainer/scripts/lib/bgm-volume.mjs +4 -0
  33. package/skills/faceless-explainer/scripts/lib/captured-fonts.mjs +58 -0
  34. package/skills/{hyperframes-core → faceless-explainer}/scripts/lib/frame-packets-core.mjs +5 -23
  35. package/skills/faceless-explainer/scripts/lib/storyboard.mjs +1 -1
  36. package/skills/faceless-explainer/scripts/lib/transitions.json +3 -3
  37. package/skills/faceless-explainer/scripts/transitions.mjs +1 -0
  38. package/skills/faceless-explainer/scripts/transitions.test.mjs +2 -0
  39. package/skills/faceless-explainer/sub-agents/frame-worker.md +1 -1
  40. package/skills/figma/SKILL.md +2 -0
  41. package/skills/general-video/SKILL.md +13 -11
  42. package/skills/general-video/scripts/frame-packets.mjs +4 -4
  43. package/skills/general-video/scripts/lib/frame-packets-core.mjs +194 -0
  44. package/skills/general-video/sub-agents/frame-worker.md +1 -1
  45. package/skills/hyperframes/SKILL.md +40 -30
  46. package/skills/{hyperframes-core → hyperframes}/references/brief-contract.md +15 -15
  47. package/skills/{hyperframes-core → hyperframes}/references/brief-format.md +8 -8
  48. package/skills/hyperframes/references/capability-menu.md +2 -2
  49. package/skills/{hyperframes-core → hyperframes}/references/frame-worker-core.md +1 -1
  50. package/skills/hyperframes/references/intent-interview.md +16 -16
  51. package/skills/hyperframes/references/plugin-installation.md +43 -0
  52. package/skills/{hyperframes-core → hyperframes}/references/production-loop.md +11 -11
  53. package/skills/hyperframes/references/review-loop.md +37 -0
  54. package/skills/hyperframes/references/route-briefs.md +1 -1
  55. package/skills/hyperframes/references/routes/motion-graphics.md +1 -1
  56. package/skills/{hyperframes-core → hyperframes}/references/script-format.md +3 -3
  57. package/skills/hyperframes/references/skill-lifecycle.md +2 -0
  58. package/skills/{hyperframes-core → hyperframes}/references/storyboard-format.md +3 -34
  59. package/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
  60. package/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
  61. package/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
  62. package/skills/hyperframes-animation/SKILL.md +5 -1
  63. package/skills/hyperframes-animation/adapters/gsap.md +1 -1
  64. package/skills/hyperframes-animation/adapters/lottie.md +15 -2
  65. package/skills/hyperframes-animation/adapters/three.md +14 -0
  66. package/skills/hyperframes-animation/blueprints/titlecard-reveal.md +1 -1
  67. package/skills/hyperframes-animation/references/motion-blur.md +133 -0
  68. package/skills/hyperframes-animation/rules/cursor-click-ripple.md +1 -1
  69. package/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +1 -1
  70. package/skills/hyperframes-animation/rules/hacker-flip-3d.md +1 -1
  71. package/skills/hyperframes-animation/rules/kinetic-beat-slam.md +2 -2
  72. package/skills/hyperframes-animation/rules/motion-blur-streak.md +1 -1
  73. package/skills/hyperframes-animation/rules/vertical-spring-ticker.md +1 -1
  74. package/skills/hyperframes-animation/scripts/package-loader.mjs +47 -16
  75. package/skills/hyperframes-animation/scripts/package-loader.test.mjs +52 -0
  76. package/skills/hyperframes-animation/techniques.md +1 -1
  77. package/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +3 -3
  78. package/skills/hyperframes-animation/transitions/css-push.md +4 -4
  79. package/skills/hyperframes-audio/SKILL.md +30 -22
  80. package/skills/hyperframes-audio/scripts/carve.mjs +6 -3
  81. package/skills/hyperframes-audio/scripts/carve.test.mjs +16 -1
  82. package/skills/hyperframes-cli/SKILL.md +44 -35
  83. package/skills/hyperframes-cli/references/init-and-scaffold.md +8 -6
  84. package/skills/hyperframes-cli/references/lint-validate-inspect.md +3 -3
  85. package/skills/hyperframes-cli/references/preview-render.md +35 -32
  86. package/skills/hyperframes-cli/references/upgrade-info-misc.md +50 -1
  87. package/skills/hyperframes-core/SKILL.md +30 -24
  88. package/skills/hyperframes-core/references/composition-patterns.md +3 -42
  89. package/skills/hyperframes-core/references/creator-editing-recipes.md +131 -7
  90. package/skills/hyperframes-core/references/data-attributes.md +11 -11
  91. package/skills/hyperframes-core/references/determinism-rules.md +2 -19
  92. package/skills/hyperframes-core/references/full-screen-motion.md +0 -9
  93. package/skills/hyperframes-core/references/minimal-composition.md +2 -2
  94. package/skills/hyperframes-core/references/sub-compositions.md +3 -66
  95. package/skills/hyperframes-core/references/tailwind.md +1 -20
  96. package/skills/hyperframes-core/references/tracks-and-clips.md +2 -6
  97. package/skills/hyperframes-core/references/variables-and-media.md +3 -3
  98. package/skills/hyperframes-creative/SKILL.md +2 -0
  99. package/skills/hyperframes-creative/references/house-style.md +15 -15
  100. package/skills/hyperframes-creative/references/story-spine.md +3 -1
  101. package/skills/hyperframes-creative/references/storyboard-recipe.md +57 -0
  102. package/skills/hyperframes-creative/references/typography.md +1 -1
  103. package/skills/hyperframes-creative/scripts/package-loader.mjs +47 -16
  104. package/skills/hyperframes-creative/scripts/package-loader.test.mjs +52 -0
  105. package/skills/hyperframes-keyframes/SKILL.md +4 -2
  106. package/skills/hyperframes-registry/SKILL.md +3 -1
  107. package/skills/hyperframes-registry/references/contributing.md +8 -2
  108. package/skills/hyperframes-registry/references/discovery.md +20 -34
  109. package/skills/hyperframes-studio/SKILL.md +77 -0
  110. package/skills/media-use/SKILL.md +14 -12
  111. package/skills/media-use/audio/references/captions/authoring.md +4 -0
  112. package/skills/media-use/audio/references/remove-background.md +1 -1
  113. package/skills/media-use/audio/references/tts-to-captions.md +11 -2
  114. package/skills/media-use/audio/references/tts.md +84 -6
  115. package/skills/media-use/audio/scripts/audio.mjs +15 -6
  116. package/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +113 -0
  117. package/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
  118. package/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
  119. package/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
  120. package/skills/media-use/audio/scripts/lib/bgm.mjs +2 -6
  121. package/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
  122. package/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
  123. package/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
  124. package/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
  125. package/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
  126. package/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
  127. package/skills/media-use/audio/scripts/lib/heygen.mjs +2 -1
  128. package/skills/media-use/audio/scripts/lib/tts.mjs +15 -3
  129. package/skills/media-use/audio/scripts/wait-bgm.mjs +8 -4
  130. package/skills/media-use/audio/scripts/wait-bgm.test.mjs +65 -0
  131. package/skills/media-use/references/audio.md +3 -2
  132. package/skills/media-use/references/grading.md +7 -7
  133. package/skills/media-use/references/media-treatment-recipes.md +1 -1
  134. package/skills/media-use/references/memory.md +2 -2
  135. package/skills/media-use/references/meta.md +2 -2
  136. package/skills/media-use/references/operations.md +15 -13
  137. package/skills/media-use/references/resolve.md +22 -11
  138. package/skills/media-use/references/setup-providers.md +11 -11
  139. package/skills/media-use/scripts/audio-duck.mjs +19 -27
  140. package/skills/media-use/scripts/compatibility.test.mjs +96 -0
  141. package/skills/media-use/scripts/lib/config-lock.mjs +45 -0
  142. package/skills/media-use/scripts/lib/duck.mjs +16 -10
  143. package/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
  144. package/skills/media-use/scripts/lib/media-home.mjs +20 -0
  145. package/skills/media-use/scripts/lib/npx-sync.mjs +28 -2
  146. package/skills/media-use/scripts/lib/prefs-store.mjs +2 -2
  147. package/skills/media-use/scripts/lib/recipe-store.mjs +2 -2
  148. package/skills/media-use/scripts/lib/telemetry.mjs +29 -41
  149. package/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
  150. package/skills/media-use/scripts/prefs.mjs +1 -1
  151. package/skills/media-use/scripts/recipe.mjs +1 -1
  152. package/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
  153. package/skills/media-use/scripts/resolve.mjs +27 -1267
  154. package/skills/media-use/scripts/transcribe.mjs +39 -25
  155. package/skills/media-use/scripts/transcribe.test.mjs +112 -0
  156. package/skills/media-use/scripts/transcript-cut.mjs +39 -8
  157. package/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
  158. package/skills/motion-graphics/SKILL.md +3 -1
  159. package/skills/motion-graphics/agents/builder.md +1 -0
  160. package/skills/motion-graphics/agents/director.md +2 -1
  161. package/skills/motion-graphics/catalog-map.md +25 -13
  162. package/skills/motion-graphics/categories/charts/module.md +2 -1
  163. package/skills/motion-graphics/categories/lower-thirds/module.md +4 -0
  164. package/skills/motion-graphics/categories/news/module.md +1 -1
  165. package/skills/motion-graphics/references/motion-vocabulary.md +4 -0
  166. package/skills/music-to-video/SKILL.md +8 -6
  167. package/skills/music-to-video/references/montage.md +3 -6
  168. package/skills/music-to-video/references/motion-primitives/3d-card-flip/index.html +10 -111
  169. package/skills/music-to-video/references/motion-primitives/3d-card-flip/scene.html +119 -0
  170. package/skills/music-to-video/references/motion-primitives/bg-flow-field/index.html +11 -284
  171. package/skills/music-to-video/references/motion-primitives/bg-flow-field/scene.html +294 -0
  172. package/skills/music-to-video/references/motion-primitives/binary-decrypt/index.html +10 -76
  173. package/skills/music-to-video/references/motion-primitives/binary-decrypt/scene.html +85 -0
  174. package/skills/music-to-video/references/motion-primitives/blur-resolve/index.html +10 -52
  175. package/skills/music-to-video/references/motion-primitives/blur-resolve/scene.html +60 -0
  176. package/skills/music-to-video/references/motion-primitives/braam-punch/index.html +10 -92
  177. package/skills/music-to-video/references/motion-primitives/braam-punch/scene.html +100 -0
  178. package/skills/music-to-video/references/motion-primitives/chromatic-split/index.html +10 -103
  179. package/skills/music-to-video/references/motion-primitives/chromatic-split/scene.html +111 -0
  180. package/skills/music-to-video/references/motion-primitives/chrome-sweep/index.html +10 -60
  181. package/skills/music-to-video/references/motion-primitives/chrome-sweep/scene.html +68 -0
  182. package/skills/music-to-video/references/motion-primitives/counting-punch/index.html +10 -110
  183. package/skills/music-to-video/references/motion-primitives/counting-punch/scene.html +119 -0
  184. package/skills/music-to-video/references/motion-primitives/crash-zoom-in/index.html +10 -112
  185. package/skills/music-to-video/references/motion-primitives/crash-zoom-in/scene.html +120 -0
  186. package/skills/music-to-video/references/motion-primitives/datamosh-smear/index.html +10 -121
  187. package/skills/music-to-video/references/motion-primitives/datamosh-smear/scene.html +131 -0
  188. package/skills/music-to-video/references/motion-primitives/directional-fill/index.html +10 -90
  189. package/skills/music-to-video/references/motion-primitives/directional-fill/scene.html +103 -0
  190. package/skills/music-to-video/references/motion-primitives/dolly-zoom/index.html +10 -94
  191. package/skills/music-to-video/references/motion-primitives/dolly-zoom/scene.html +102 -0
  192. package/skills/music-to-video/references/motion-primitives/electric-arc/index.html +10 -100
  193. package/skills/music-to-video/references/motion-primitives/electric-arc/scene.html +105 -0
  194. package/skills/music-to-video/references/motion-primitives/flash-cut/index.html +10 -89
  195. package/skills/music-to-video/references/motion-primitives/flash-cut/scene.html +97 -0
  196. package/skills/music-to-video/references/motion-primitives/gooey-metaball/index.html +10 -197
  197. package/skills/music-to-video/references/motion-primitives/gooey-metaball/scene.html +206 -0
  198. package/skills/music-to-video/references/motion-primitives/hard-cut/index.html +10 -74
  199. package/skills/music-to-video/references/motion-primitives/hard-cut/scene.html +82 -0
  200. package/skills/music-to-video/references/motion-primitives/hypercut-whip/index.html +10 -36
  201. package/skills/music-to-video/references/motion-primitives/hypercut-whip/scene.html +44 -0
  202. package/skills/music-to-video/references/motion-primitives/iris-open/index.html +10 -61
  203. package/skills/music-to-video/references/motion-primitives/iris-open/scene.html +69 -0
  204. package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/index.html +10 -55
  205. package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/scene.html +64 -0
  206. package/skills/music-to-video/references/motion-primitives/liquid-morph/index.html +10 -88
  207. package/skills/music-to-video/references/motion-primitives/liquid-morph/scene.html +96 -0
  208. package/skills/music-to-video/references/motion-primitives/mask-reveal/index.html +10 -66
  209. package/skills/music-to-video/references/motion-primitives/mask-reveal/scene.html +74 -0
  210. package/skills/music-to-video/references/motion-primitives/mosaic-pack/index.html +10 -81
  211. package/skills/music-to-video/references/motion-primitives/mosaic-pack/scene.html +89 -0
  212. package/skills/music-to-video/references/motion-primitives/neon-flicker/index.html +10 -65
  213. package/skills/music-to-video/references/motion-primitives/neon-flicker/scene.html +73 -0
  214. package/skills/music-to-video/references/motion-primitives/outline-to-fill/index.html +10 -74
  215. package/skills/music-to-video/references/motion-primitives/outline-to-fill/scene.html +82 -0
  216. package/skills/music-to-video/references/motion-primitives/palette-flip/index.html +10 -89
  217. package/skills/music-to-video/references/motion-primitives/palette-flip/scene.html +97 -0
  218. package/skills/music-to-video/references/motion-primitives/particle-burst/index.html +10 -98
  219. package/skills/music-to-video/references/motion-primitives/particle-burst/scene.html +106 -0
  220. package/skills/music-to-video/references/motion-primitives/pixel-dissolve/index.html +10 -78
  221. package/skills/music-to-video/references/motion-primitives/pixel-dissolve/scene.html +86 -0
  222. package/skills/music-to-video/references/motion-primitives/radial-burst-lines/index.html +10 -117
  223. package/skills/music-to-video/references/motion-primitives/radial-burst-lines/scene.html +130 -0
  224. package/skills/music-to-video/references/motion-primitives/screen-shake/index.html +10 -70
  225. package/skills/music-to-video/references/motion-primitives/screen-shake/scene.html +78 -0
  226. package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/index.html +10 -87
  227. package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/scene.html +100 -0
  228. package/skills/music-to-video/references/motion-primitives/spotlight-sweep/index.html +10 -94
  229. package/skills/music-to-video/references/motion-primitives/spotlight-sweep/scene.html +102 -0
  230. package/skills/music-to-video/references/motion-primitives/staggered-exit/index.html +10 -74
  231. package/skills/music-to-video/references/motion-primitives/staggered-exit/scene.html +82 -0
  232. package/skills/music-to-video/references/motion-primitives/text-spectral-rays/index.html +11 -271
  233. package/skills/music-to-video/references/motion-primitives/text-spectral-rays/scene.html +280 -0
  234. package/skills/music-to-video/references/motion-primitives/text-wave-distort/index.html +10 -92
  235. package/skills/music-to-video/references/motion-primitives/text-wave-distort/scene.html +106 -0
  236. package/skills/music-to-video/references/motion-primitives/tile-mosaic/index.html +10 -101
  237. package/skills/music-to-video/references/motion-primitives/tile-mosaic/scene.html +109 -0
  238. package/skills/music-to-video/references/motion-primitives/typewriter-reveal/index.html +10 -79
  239. package/skills/music-to-video/references/motion-primitives/typewriter-reveal/scene.html +91 -0
  240. package/skills/music-to-video/references/motion-primitives/word-grid-burst/index.html +10 -83
  241. package/skills/music-to-video/references/motion-primitives/word-grid-burst/scene.html +96 -0
  242. package/skills/music-to-video/references/planning.md +2 -2
  243. package/skills/music-to-video/scripts/lib/storyboard.mjs +1 -1
  244. package/skills/music-to-video/sub-agents/frame-worker.md +2 -2
  245. package/skills/pr-to-video/SKILL.md +20 -16
  246. package/skills/pr-to-video/references/code-vocabulary.md +14 -12
  247. package/skills/pr-to-video/references/story-design.md +1 -1
  248. package/skills/pr-to-video/scripts/assemble-index.mjs +6 -4
  249. package/skills/pr-to-video/scripts/assemble-index.test.mjs +57 -2
  250. package/skills/pr-to-video/scripts/audio.mjs +2 -0
  251. package/skills/pr-to-video/scripts/build-frame.mjs +6 -3
  252. package/skills/pr-to-video/scripts/captions.mjs +7 -4
  253. package/skills/pr-to-video/scripts/captions.test.mjs +41 -0
  254. package/skills/pr-to-video/scripts/frame-packets.mjs +4 -4
  255. package/skills/pr-to-video/scripts/lib/bgm-volume.mjs +4 -0
  256. package/skills/pr-to-video/scripts/lib/captured-fonts.mjs +58 -0
  257. package/skills/pr-to-video/scripts/lib/frame-packets-core.mjs +194 -0
  258. package/skills/pr-to-video/scripts/lib/storyboard.mjs +1 -1
  259. package/skills/pr-to-video/scripts/lib/transitions.json +3 -3
  260. package/skills/pr-to-video/scripts/transitions.mjs +7 -5
  261. package/skills/pr-to-video/sub-agents/frame-worker.md +1 -1
  262. package/skills/product-launch-video/SKILL.md +20 -16
  263. package/skills/product-launch-video/references/story-design.md +1 -1
  264. package/skills/product-launch-video/scripts/assemble-index.mjs +6 -4
  265. package/skills/product-launch-video/scripts/assemble-index.test.mjs +57 -2
  266. package/skills/product-launch-video/scripts/audio.mjs +2 -0
  267. package/skills/product-launch-video/scripts/audio.test.mjs +16 -0
  268. package/skills/product-launch-video/scripts/build-frame-subsets.test.mjs +152 -0
  269. package/skills/product-launch-video/scripts/build-frame.mjs +6 -3
  270. package/skills/product-launch-video/scripts/captions.mjs +7 -4
  271. package/skills/product-launch-video/scripts/frame-packets.mjs +4 -4
  272. package/skills/product-launch-video/scripts/lib/bgm-volume.mjs +4 -0
  273. package/skills/product-launch-video/scripts/lib/captured-fonts.mjs +58 -0
  274. package/skills/product-launch-video/scripts/lib/frame-packets-core.mjs +194 -0
  275. package/skills/product-launch-video/scripts/lib/storyboard.mjs +1 -1
  276. package/skills/product-launch-video/scripts/lib/transitions.json +3 -3
  277. package/skills/product-launch-video/scripts/transitions.mjs +7 -5
  278. package/skills/product-launch-video/scripts/transitions.test.mjs +68 -0
  279. package/skills/product-launch-video/sub-agents/frame-worker.md +1 -1
  280. package/skills/remotion-to-hyperframes/SKILL.md +7 -4
  281. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/expected.json +5 -5
  282. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/compositions/title.html +31 -0
  283. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/index.html +10 -25
  284. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/README.md +8 -8
  285. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/expected.json +9 -9
  286. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-1.html +35 -0
  287. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-2.html +35 -0
  288. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-3.html +36 -0
  289. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/index.html +28 -71
  290. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/expected.json +3 -3
  291. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-1.html +52 -0
  292. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-2.html +99 -0
  293. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-3.html +55 -0
  294. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/index.html +13 -212
  295. package/skills/remotion-to-hyperframes/references/api-map.md +16 -16
  296. package/skills/remotion-to-hyperframes/references/limitations.md +7 -7
  297. package/skills/remotion-to-hyperframes/references/lottie.md +5 -7
  298. package/skills/remotion-to-hyperframes/references/media.md +3 -3
  299. package/skills/remotion-to-hyperframes/references/parameters.md +5 -0
  300. package/skills/remotion-to-hyperframes/references/sequencing.md +71 -18
  301. package/skills/slideshow/SKILL.md +4 -1
  302. package/skills/slideshow/references/standalone-harness.md +0 -3
  303. package/skills/talking-head-recut/SKILL.md +10 -1
  304. package/skills/hyperframes-core/references/review-loop.md +0 -41
  305. package/skills/media-use/scripts/lib/adopt.mjs +0 -128
  306. package/skills/media-use/scripts/lib/adopt.test.mjs +0 -95
  307. package/skills/media-use/scripts/lib/bgm-provider.mjs +0 -20
  308. package/skills/media-use/scripts/lib/brand-provider.mjs +0 -59
  309. package/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +0 -108
  310. package/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +0 -85
  311. package/skills/media-use/scripts/lib/cache.mjs +0 -150
  312. package/skills/media-use/scripts/lib/candidates.mjs +0 -91
  313. package/skills/media-use/scripts/lib/candidates.test.mjs +0 -155
  314. package/skills/media-use/scripts/lib/codex-provider.mjs +0 -161
  315. package/skills/media-use/scripts/lib/codex-provider.test.mjs +0 -34
  316. package/skills/media-use/scripts/lib/coverage.test.mjs +0 -117
  317. package/skills/media-use/scripts/lib/cube-build.mjs +0 -181
  318. package/skills/media-use/scripts/lib/cube-build.test.mjs +0 -80
  319. package/skills/media-use/scripts/lib/cube-validate.mjs +0 -198
  320. package/skills/media-use/scripts/lib/cube-validate.test.mjs +0 -125
  321. package/skills/media-use/scripts/lib/cutlist.test.mjs +0 -148
  322. package/skills/media-use/scripts/lib/duck.test.mjs +0 -118
  323. package/skills/media-use/scripts/lib/error-diffusion.test.mjs +0 -102
  324. package/skills/media-use/scripts/lib/freeze.mjs +0 -70
  325. package/skills/media-use/scripts/lib/freeze.test.mjs +0 -46
  326. package/skills/media-use/scripts/lib/grade-analyzer.mjs +0 -264
  327. package/skills/media-use/scripts/lib/grade-analyzer.test.mjs +0 -285
  328. package/skills/media-use/scripts/lib/heygen-cli.mjs +0 -191
  329. package/skills/media-use/scripts/lib/heygen-cli.test.mjs +0 -301
  330. package/skills/media-use/scripts/lib/heygen-search.mjs +0 -45
  331. package/skills/media-use/scripts/lib/heygen-search.test.mjs +0 -49
  332. package/skills/media-use/scripts/lib/heygen-video-provider.mjs +0 -127
  333. package/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +0 -344
  334. package/skills/media-use/scripts/lib/image-provider.mjs +0 -44
  335. package/skills/media-use/scripts/lib/local-models.mjs +0 -318
  336. package/skills/media-use/scripts/lib/local-models.test.mjs +0 -220
  337. package/skills/media-use/scripts/lib/local-run.mjs +0 -78
  338. package/skills/media-use/scripts/lib/local-run.test.mjs +0 -121
  339. package/skills/media-use/scripts/lib/logo-provider.mjs +0 -222
  340. package/skills/media-use/scripts/lib/logo-provider.test.mjs +0 -137
  341. package/skills/media-use/scripts/lib/ltx-video-provider.mjs +0 -94
  342. package/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +0 -316
  343. package/skills/media-use/scripts/lib/lut-preset-provider.mjs +0 -266
  344. package/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +0 -176
  345. package/skills/media-use/scripts/lib/manifest.test.mjs +0 -388
  346. package/skills/media-use/scripts/lib/match.mjs +0 -47
  347. package/skills/media-use/scripts/lib/mflux-provider.mjs +0 -128
  348. package/skills/media-use/scripts/lib/mflux-provider.test.mjs +0 -174
  349. package/skills/media-use/scripts/lib/misses.mjs +0 -49
  350. package/skills/media-use/scripts/lib/misses.test.mjs +0 -78
  351. package/skills/media-use/scripts/lib/npx-sync.test.mjs +0 -50
  352. package/skills/media-use/scripts/lib/parakeet-words.test.mjs +0 -44
  353. package/skills/media-use/scripts/lib/prefs-store.test.mjs +0 -189
  354. package/skills/media-use/scripts/lib/probe.mjs +0 -39
  355. package/skills/media-use/scripts/lib/probe.test.mjs +0 -31
  356. package/skills/media-use/scripts/lib/providers.mjs +0 -5
  357. package/skills/media-use/scripts/lib/recipe-store.test.mjs +0 -367
  358. package/skills/media-use/scripts/lib/registry.mjs +0 -218
  359. package/skills/media-use/scripts/lib/registry.test.mjs +0 -261
  360. package/skills/media-use/scripts/lib/search.mjs +0 -24
  361. package/skills/media-use/scripts/lib/search.test.mjs +0 -32
  362. package/skills/media-use/scripts/lib/sfx-provider.mjs +0 -23
  363. package/skills/media-use/scripts/lib/specs.mjs +0 -132
  364. package/skills/media-use/scripts/lib/specs.test.mjs +0 -157
  365. package/skills/media-use/scripts/lib/stats.mjs +0 -117
  366. package/skills/media-use/scripts/lib/stats.test.mjs +0 -165
  367. package/skills/media-use/scripts/lib/telemetry.test.mjs +0 -373
  368. package/skills/media-use/scripts/lib/tts-local-provider.mjs +0 -92
  369. package/skills/media-use/scripts/lib/tts-local-provider.test.mjs +0 -72
  370. package/skills/media-use/scripts/lib/usage.mjs +0 -57
  371. package/skills/media-use/scripts/lib/usage.test.mjs +0 -54
  372. package/skills/media-use/scripts/lib/voice-provider.mjs +0 -57
  373. package/skills/media-use/scripts/lib/voice-provider.test.mjs +0 -46
  374. package/skills/media-use/scripts/resolve.test.mjs +0 -1120
  375. /package/skills/{hyperframes-core → hyperframes}/references/subagent-dispatch.md +0 -0
@@ -1,128 +0,0 @@
1
- import { execFileSync } from "node:child_process";
2
- import { existsSync, unlinkSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- import { describeDownload, probeSpecs } from "./specs.mjs";
6
- import { buildArgv, selectModelLadder } from "./local-models.mjs";
7
-
8
- // Local image generation via mflux (FLUX-on-MLX), the Mac-native runner.
9
- // Spec-gated: selectModelLadder("imagegen", specs) returns every FLUX-class
10
- // model the machine's AVAILABLE RAM can actually run (medium FLUX-schnell
11
- // --low-ram on ~24GB, up to Qwen-Image on 64GB+), best first. When nothing
12
- // local fits, or no fitting tier can actually run here, this returns null so
13
- // the registry falls through to the codex image upsell.
14
- //
15
- // The official FLUX repos are HF-gated, so the model entries point --path at
16
- // non-gated community 4-bit re-uploads; the repo is resolved to a local snapshot
17
- // (hf download, idempotent) because a bare repo id breaks mlx unflatten.
18
-
19
- // Resolve an HF repo to its local snapshot dir. `hf download` is idempotent and
20
- // prints the snapshot path as its last line.
21
- function resolveSnapshot(repo, execFn, pathExists) {
22
- const out = execFn("hf", ["download", repo], {
23
- encoding: "utf8",
24
- timeout: 1_800_000,
25
- stdio: ["ignore", "pipe", "pipe"],
26
- });
27
- const path = out?.trim().split(/\r?\n/).pop()?.trim();
28
- return path && pathExists(path) ? path : null;
29
- }
30
-
31
- export async function mfluxImageGenerate(
32
- intent,
33
- ctx,
34
- execFn = execFileSync,
35
- pathExists = existsSync,
36
- unlinkFn = unlinkSync,
37
- ) {
38
- const specs = ctx?.specs || probeSpecs();
39
- const ladder = selectModelLadder("imagegen", specs, { preferTier: ctx?.preferTier });
40
- if (!ladder.length) return null; // no local model fits -> codex upsell/fallback
41
-
42
- // Each attempt mints its own timestamped output path, so a partial artifact
43
- // from a failed tier is orphaned rather than overwritten - and a lower tier
44
- // then succeeding hides it. Discard it before demoting. Best-effort: a
45
- // partial we cannot remove must never mask the real failure.
46
- const discardPartial = (path) => {
47
- try {
48
- if (pathExists(path)) unlinkFn(path);
49
- } catch {
50
- // nothing actionable: the generate failure below is the real story
51
- }
52
- };
53
-
54
- // Best tier first, demoting past any tier that cannot run here (runner off
55
- // PATH, a snapshot that won't download, an OOM) rather than failing local
56
- // image gen outright. Every demotion is reported, so a quietly smaller model
57
- // is never mistaken for the tier the machine nominally qualified for.
58
- for (const model of ladder) {
59
- const bin = model.invoke.trim().split(/\s+/)[0];
60
- // Not installed? Surface the exact enable-command (before the model
61
- // download) so the agent learns the free local path is available instead of
62
- // silently taking the codex upsell.
63
- try {
64
- execFn("which", [bin], { stdio: ["ignore", "ignore", "ignore"] });
65
- } catch {
66
- console.error(
67
- `media-use: local image gen not enabled (\`${bin}\` not on PATH). Install for free on-device FLUX: ${model.install}. Heads up: ${model.id} ${describeDownload(model.sizeMB)}.`,
68
- );
69
- continue;
70
- }
71
-
72
- const outPath = join(tmpdir(), `media-use-mflux-${process.pid}-${Date.now()}.png`);
73
- const vars = {
74
- prompt: intent,
75
- w: ctx?.width || 512,
76
- h: ctx?.height || 512,
77
- seed: ctx?.seed ?? 42,
78
- out: outPath,
79
- };
80
- if (model.repo && model.invoke.includes("{model_path}")) {
81
- let snap = null;
82
- let why = `could not resolve a local snapshot of ${model.repo}`;
83
- try {
84
- snap = resolveSnapshot(model.repo, execFn, pathExists);
85
- } catch (err) {
86
- why = `hf download failed: ${err.stderr?.toString().trim().slice(-200) || err.message}`;
87
- }
88
- if (!snap) {
89
- console.error(`media-use: local image gen (${model.id}): ${why}`);
90
- continue;
91
- }
92
- vars.model_path = snap;
93
- }
94
-
95
- const argv = buildArgv(model.invoke, vars);
96
- argv.shift(); // drop the bin (already validated)
97
- try {
98
- execFn(bin, argv, {
99
- encoding: "utf8",
100
- timeout: 1_800_000,
101
- stdio: ["ignore", "pipe", "pipe"],
102
- });
103
- } catch (err) {
104
- discardPartial(outPath);
105
- console.error(
106
- `media-use: local image gen (${model.id}) failed: ${err.stderr?.toString().trim().slice(-200) || err.message}`,
107
- );
108
- continue;
109
- }
110
- if (!pathExists(outPath)) {
111
- console.error(
112
- `media-use: local image gen (${model.id}) exited cleanly but wrote no output file`,
113
- );
114
- continue;
115
- }
116
- return {
117
- localPath: outPath,
118
- ext: ".png",
119
- source: "generated",
120
- metadata: {
121
- description: intent,
122
- provider: `mflux.${model.id}`,
123
- provenance: { model: model.id, tier: model.tier, prompt: intent },
124
- },
125
- };
126
- }
127
- return null;
128
- }
@@ -1,174 +0,0 @@
1
- import { test } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { mfluxImageGenerate } from "./mflux-provider.mjs";
4
-
5
- // 40GB clears the 32GB klein tier and the 8GB schnell tier below it; the 64GB
6
- // qwen tier stays out of reach. Two rungs is what makes demotion observable.
7
- const bothTiersSpecs = { availableRamMB: 40000, gpu: { present: true } };
8
- const SNAPSHOT = "/tmp/hf-snapshot";
9
-
10
- // exec stub covering all three shells-out mflux does: the PATH probe, the
11
- // idempotent `hf download`, and the generate itself.
12
- function stubExec({ failGenerateFor = [], failWhichFor = [] } = {}) {
13
- const calls = [];
14
- const exec = (...call) => {
15
- calls.push(call);
16
- const [bin, argv] = call;
17
- if (bin === "which") {
18
- if (failWhichFor.includes(argv[0])) throw new Error("not found");
19
- return "";
20
- }
21
- if (bin === "hf") return `Fetching 6 files...\n${SNAPSHOT}\n`;
22
- if (failGenerateFor.some((id) => argv.join(" ").includes(id))) {
23
- const err = new Error("exit 1");
24
- err.stderr = "mlx.core.metal: out of memory";
25
- throw err;
26
- }
27
- return "";
28
- };
29
- return { calls, exec };
30
- }
31
-
32
- const generateCalls = (calls) =>
33
- calls.filter(([bin]) => bin !== "which" && bin !== "hf").map(([, argv]) => argv.join(" "));
34
-
35
- test("no local model fits: falls through to the upsell without shelling out", async () => {
36
- const { calls, exec } = stubExec();
37
-
38
- const result = await mfluxImageGenerate(
39
- "a red bicycle",
40
- { specs: { availableRamMB: 100, gpu: { present: true } } },
41
- exec,
42
- () => true,
43
- );
44
-
45
- assert.equal(result, null);
46
- assert.deepEqual(calls, []);
47
- });
48
-
49
- test("a top tier that cannot run demotes to the next fitting tier", async (t) => {
50
- const errors = [];
51
- t.mock.method(console, "error", (message) => errors.push(message));
52
- const { calls, exec } = stubExec({ failGenerateFor: ["flux2-klein-4b"] });
53
-
54
- const result = await mfluxImageGenerate(
55
- "a red bicycle",
56
- { specs: bothTiersSpecs },
57
- exec,
58
- () => true,
59
- );
60
-
61
- assert.ok(result, "the schnell tier still produced an image");
62
- assert.equal(result.metadata.provider, "mflux.flux-schnell-mflux-q4");
63
- const generated = generateCalls(calls);
64
- assert.equal(generated.length, 2, "klein attempted first, then schnell");
65
- assert.match(generated[0], /flux2-klein-4b/);
66
- assert.match(generated[1], /--model schnell/);
67
- assert.equal(errors.length, 1, "the demotion is reported, not silent");
68
- assert.match(errors[0], /flux2-klein-mflux-q4\) failed/);
69
- });
70
-
71
- test("a snapshot that will not resolve demotes rather than failing outright", async (t) => {
72
- const errors = [];
73
- t.mock.method(console, "error", (message) => errors.push(message));
74
- const calls = [];
75
- const exec = (...call) => {
76
- calls.push(call);
77
- const [bin, argv] = call;
78
- if (bin === "which") return "";
79
- // klein's weights won't download; schnell's do
80
- if (bin === "hf") {
81
- if (argv[1].includes("FLUX.2-klein")) throw new Error("403 Forbidden");
82
- return `${SNAPSHOT}\n`;
83
- }
84
- return "";
85
- };
86
-
87
- const result = await mfluxImageGenerate(
88
- "a red bicycle",
89
- { specs: bothTiersSpecs },
90
- exec,
91
- () => true,
92
- );
93
-
94
- assert.ok(result, "demoted past the ungettable weights");
95
- assert.equal(result.metadata.provider, "mflux.flux-schnell-mflux-q4");
96
- assert.equal(errors.length, 1);
97
- assert.match(errors[0], /hf download failed/);
98
- });
99
-
100
- test("runner missing from PATH reports the install hint per tier and returns null", async (t) => {
101
- const errors = [];
102
- t.mock.method(console, "error", (message) => errors.push(message));
103
- const { exec } = stubExec({ failWhichFor: ["mflux-generate"] });
104
-
105
- const result = await mfluxImageGenerate(
106
- "a red bicycle",
107
- { specs: bothTiersSpecs },
108
- exec,
109
- () => true,
110
- );
111
-
112
- assert.equal(result, null);
113
- assert.equal(errors.length, 2, "both fitting tiers reported");
114
- assert.match(errors[0], /uv pip install mflux/);
115
- // each hint states that tier's download cost before the user commits
116
- assert.match(errors[0], /GB of weights to/);
117
- assert.match(errors[1], /GB of weights to/);
118
- });
119
-
120
- // Same per-attempt temp path, same orphaning risk as the LTX provider: a
121
- // partial png from a failed tier must not survive a lower tier succeeding.
122
- const outputOf = (argv) => argv[argv.indexOf("--output") + 1];
123
- const attemptedOutputs = (calls) =>
124
- calls.filter(([bin]) => bin !== "which" && bin !== "hf").map(([, argv]) => outputOf(argv));
125
-
126
- test("a failed attempt's partial output is discarded before demoting", async (t) => {
127
- t.mock.method(console, "error", () => {});
128
- const unlinked = [];
129
- const { calls, exec } = stubExec({ failGenerateFor: ["flux2-klein-4b"] });
130
-
131
- const result = await mfluxImageGenerate(
132
- "a red bicycle",
133
- { specs: bothTiersSpecs },
134
- exec,
135
- () => true,
136
- (path) => unlinked.push(path),
137
- );
138
-
139
- assert.ok(result, "the schnell tier still produced an image");
140
- assert.deepEqual(unlinked, [attemptedOutputs(calls)[0]], "the failed klein partial is removed");
141
- });
142
-
143
- test("every tier failing discards every partial, one per attempt", async (t) => {
144
- t.mock.method(console, "error", () => {});
145
- const unlinked = [];
146
- const { calls, exec } = stubExec({ failGenerateFor: ["flux2-klein-4b", "schnell"] });
147
-
148
- const result = await mfluxImageGenerate(
149
- "a red bicycle",
150
- { specs: bothTiersSpecs },
151
- exec,
152
- () => true,
153
- (path) => unlinked.push(path),
154
- );
155
-
156
- assert.equal(result, null);
157
- assert.deepEqual(unlinked, attemptedOutputs(calls), "nothing is left behind");
158
- });
159
-
160
- test("a successful generation is never discarded", async () => {
161
- const unlinked = [];
162
- const { exec } = stubExec();
163
-
164
- const result = await mfluxImageGenerate(
165
- "a red bicycle",
166
- { specs: bothTiersSpecs },
167
- exec,
168
- () => true,
169
- (path) => unlinked.push(path),
170
- );
171
-
172
- assert.ok(result);
173
- assert.deepEqual(unlinked, [], "the returned artifact must survive");
174
- });
@@ -1,49 +0,0 @@
1
- import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
-
5
- const MISSES_FILE = "misses.jsonl";
6
-
7
- function missesPath() {
8
- return join(homedir(), ".media", MISSES_FILE);
9
- }
10
-
11
- export function recordMiss({ type, intent, provider_override, local_only }) {
12
- try {
13
- const dir = join(homedir(), ".media");
14
- mkdirSync(dir, { recursive: true });
15
- appendFileSync(
16
- join(dir, MISSES_FILE),
17
- JSON.stringify({
18
- ts: new Date().toISOString(),
19
- type,
20
- intent,
21
- provider_override: !!provider_override,
22
- local_only: !!local_only,
23
- }) + "\n",
24
- );
25
- } catch {
26
- // local miss logging is best-effort; never surface into resolve
27
- }
28
- }
29
-
30
- export function readMisses() {
31
- const p = missesPath();
32
- try {
33
- if (!existsSync(p)) return [];
34
- const raw = readFileSync(p, "utf8");
35
- const records = [];
36
- for (const line of raw.split(/\r?\n/)) {
37
- const trimmed = line.trim();
38
- if (!trimmed) continue;
39
- try {
40
- records.push(JSON.parse(trimmed));
41
- } catch {
42
- // skip malformed local lines, don't crash stats
43
- }
44
- }
45
- return records;
46
- } catch {
47
- return [];
48
- }
49
- }
@@ -1,78 +0,0 @@
1
- import { strict as assert } from "node:assert";
2
- import { test } from "node:test";
3
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- import { readMisses, recordMiss } from "./misses.mjs";
7
-
8
- function sandbox() {
9
- const root = mkdtempSync(join(tmpdir(), "mu-misses-"));
10
- const home = join(root, "home");
11
- mkdirSync(home, { recursive: true });
12
- process.env.HOME = home;
13
- return { root, home };
14
- }
15
-
16
- function restoreEnv(saved) {
17
- for (const k of Object.keys(process.env)) if (!(k in saved)) delete process.env[k];
18
- Object.assign(process.env, saved);
19
- }
20
-
21
- test("recordMiss appends a well-formed local miss", () => {
22
- const savedEnv = { ...process.env };
23
- const { root, home } = sandbox();
24
- try {
25
- recordMiss({ type: "bgm", intent: "moody synth pulse", provider_override: true });
26
- const misses = readMisses();
27
- assert.equal(misses.length, 1);
28
- assert.equal(misses[0].type, "bgm");
29
- assert.equal(misses[0].intent, "moody synth pulse");
30
- assert.equal(misses[0].provider_override, true);
31
- assert.equal(misses[0].local_only, false);
32
- assert.ok(!Number.isNaN(Date.parse(misses[0].ts)));
33
-
34
- const raw = readFileSync(join(home, ".media/misses.jsonl"), "utf8");
35
- assert.match(raw, /moody synth pulse/);
36
- } finally {
37
- restoreEnv(savedEnv);
38
- rmSync(root, { recursive: true, force: true });
39
- }
40
- });
41
-
42
- test("recordMiss swallows filesystem failures", () => {
43
- const savedEnv = { ...process.env };
44
- const { root, home } = sandbox();
45
- try {
46
- writeFileSync(join(home, ".media"), "not a directory");
47
- assert.doesNotThrow(() =>
48
- recordMiss({ type: "image", intent: "unwritable", local_only: true }),
49
- );
50
- assert.equal(existsSync(join(home, ".media/misses.jsonl")), false);
51
- } finally {
52
- restoreEnv(savedEnv);
53
- rmSync(root, { recursive: true, force: true });
54
- }
55
- });
56
-
57
- test("readMisses skips corrupt lines", () => {
58
- const savedEnv = { ...process.env };
59
- const { root, home } = sandbox();
60
- try {
61
- mkdirSync(join(home, ".media"), { recursive: true });
62
- writeFileSync(
63
- join(home, ".media/misses.jsonl"),
64
- [
65
- JSON.stringify({ ts: "2026-07-09T00:00:00.000Z", type: "bgm", intent: "one" }),
66
- "{not json",
67
- JSON.stringify({ ts: "2026-07-09T00:00:01.000Z", type: "sfx", intent: "two" }),
68
- ].join("\n"),
69
- );
70
- assert.deepEqual(
71
- readMisses().map((miss) => miss.intent),
72
- ["one", "two"],
73
- );
74
- } finally {
75
- restoreEnv(savedEnv);
76
- rmSync(root, { recursive: true, force: true });
77
- }
78
- });
@@ -1,50 +0,0 @@
1
- import { test } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { resolveNpxInvocation } from "./npx-sync.mjs";
4
-
5
- // Coverage parity with tts-local-provider.test.mjs, for the whisper.cpp
6
- // fallback's call-site shape (transcribe.mjs runWhisper): the same three
7
- // branches, but with the hard-fail contract — no fallback provider exists,
8
- // so an unresolvable npx must throw actionably instead of returning null.
9
-
10
- const envWithNpxCli = {
11
- npm_execpath: "C:/Program Files/nodejs/node_modules/npm/bin/npm-cli.js",
12
- npm_node_execpath: "C:/Program Files/nodejs/node.exe",
13
- };
14
- const npxCliPath = "C:/Program Files/nodejs/node_modules/npm/bin/npx-cli.js";
15
- const pathExists = (path) => path === npxCliPath;
16
-
17
- const WHISPER_ARGV = ["hyperframes", "transcribe", "C:\\media\\input.wav", "--dir", "C:\\work"];
18
- const WHISPER_OPTS = { stdio: ["ignore", "pipe", "pipe"], timeout: 1_800_000 };
19
-
20
- test("win32: routes the whisper fallback through node + npx-cli, never bare npx", () => {
21
- const resolved = resolveNpxInvocation(
22
- WHISPER_ARGV,
23
- WHISPER_OPTS,
24
- "win32",
25
- envWithNpxCli,
26
- pathExists,
27
- );
28
-
29
- assert.equal(resolved.cmd, envWithNpxCli.npm_node_execpath);
30
- assert.equal(resolved.args[0], npxCliPath);
31
- assert.deepEqual(resolved.args.slice(1, 3), ["hyperframes", "transcribe"]);
32
- // execFileSync options survive the rerouting (the timeout bounds the
33
- // whisper build/model download; the pipes surface its errors).
34
- assert.deepEqual(resolved.opts.stdio, ["ignore", "pipe", "pipe"]);
35
- assert.equal(resolved.opts.timeout, 1_800_000);
36
- });
37
-
38
- test("win32 without a resolvable npx-cli: throws the actionable install hint", () => {
39
- assert.throws(
40
- () => resolveNpxInvocation(WHISPER_ARGV, WHISPER_OPTS, "win32", {}, () => false),
41
- /npx-cli\.js was not found/,
42
- );
43
- });
44
-
45
- test("non-win32: spawns plain npx unchanged", () => {
46
- const resolved = resolveNpxInvocation(WHISPER_ARGV, WHISPER_OPTS, "darwin", {}, () => false);
47
-
48
- assert.equal(resolved.cmd, "npx");
49
- assert.deepEqual(resolved.args, WHISPER_ARGV);
50
- });
@@ -1,44 +0,0 @@
1
- import { strict as assert } from "node:assert";
2
- import { test } from "node:test";
3
- import { mergeTokensToWords } from "./parakeet-words.mjs";
4
-
5
- test("mergeTokensToWords joins sub-word tokens on the space boundary", () => {
6
- const parakeet = {
7
- text: "Hello everyone. Um,",
8
- sentences: [
9
- {
10
- tokens: [
11
- { text: " H", start: 0.0, end: 0.24 },
12
- { text: "ello", start: 0.24, end: 0.48 },
13
- { text: " everyone.", start: 0.48, end: 1.28 },
14
- { text: " Um,", start: 1.28, end: 1.92 },
15
- ],
16
- },
17
- ],
18
- };
19
- const { words } = mergeTokensToWords(parakeet);
20
- assert.deepEqual(words, [
21
- { text: "Hello", start: 0.0, end: 0.48 },
22
- { text: "everyone.", start: 0.48, end: 1.28 },
23
- { text: "Um,", start: 1.28, end: 1.92 },
24
- ]);
25
- });
26
-
27
- test("mergeTokensToWords spans multiple sentences and drops empties", () => {
28
- const parakeet = {
29
- text: "Hi there",
30
- sentences: [
31
- { tokens: [{ text: "Hi", start: 0, end: 0.2 }] },
32
- { tokens: [{ text: " there", start: 0.5, end: 0.9 }] },
33
- ],
34
- };
35
- const { words } = mergeTokensToWords(parakeet);
36
- assert.equal(words.length, 2);
37
- assert.equal(words[1].text, "there");
38
- assert.equal(words[1].start, 0.5);
39
- });
40
-
41
- test("mergeTokensToWords tolerates missing sentences/tokens", () => {
42
- assert.deepEqual(mergeTokensToWords({}).words, []);
43
- assert.deepEqual(mergeTokensToWords({ sentences: [{}] }).words, []);
44
- });