dsh-hyperframes 0.3.2 → 0.4.1

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 +5 -4
  2. package/README.md +6 -5
  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,121 +0,0 @@
1
- import { strict as assert } from "node:assert";
2
- import { test } from "node:test";
3
- import { runLocalModel } from "./local-run.mjs";
4
-
5
- const strongCpu = { ramMB: 16000, gpu: { present: false, vramMB: 0 }, appleSilicon: false };
6
- const tiny = { ramMB: 512, gpu: { present: false, vramMB: 0 }, appleSilicon: false };
7
- const ok = () => {}; // which/exec that succeed
8
-
9
- test("recommends the CLI path when no local tier fits the machine", () => {
10
- const r = runLocalModel("tts", { specs: tiny, which: ok, exec: ok });
11
- assert.equal(r.recommend, "cli");
12
- });
13
-
14
- test("recommends install when the tool is not on PATH", () => {
15
- const r = runLocalModel("tts", {
16
- specs: strongCpu,
17
- which: () => {
18
- throw new Error("not found");
19
- },
20
- exec: ok,
21
- vars: { text: "hi", out: "/tmp/v.wav" },
22
- });
23
- assert.equal(r.recommend, "install");
24
- assert.equal(r.model, "kokoro");
25
- assert.match(r.command, /pip install kokoro/);
26
- });
27
-
28
- test("runs the model and returns the output path when installed", () => {
29
- let ran = "";
30
- const r = runLocalModel("tts", {
31
- specs: strongCpu,
32
- which: ok,
33
- exec: (cmd) => {
34
- ran = cmd;
35
- },
36
- vars: { text: "hello world", voice: "af_heart", out: "/tmp/v.wav" },
37
- });
38
- assert.equal(r.model, "kokoro");
39
- assert.equal(r.out, "/tmp/v.wav");
40
- assert.match(ran, /hello world/, "invoke template filled with vars");
41
- assert.match(ran, /\/tmp\/v\.wav/);
42
- });
43
-
44
- test("a failing run degrades to an install recommendation, never throws", () => {
45
- const r = runLocalModel("upscale", {
46
- specs: strongCpu,
47
- which: ok,
48
- exec: () => {
49
- throw new Error("boom");
50
- },
51
- vars: { in: "a.png", out: "b.png" },
52
- });
53
- assert.equal(r.recommend, "install");
54
- });
55
-
56
- test("a tier whose tool is missing demotes to the next tier that fits", () => {
57
- // 64GB + GPU fits BOTH tts tiers, so the ladder has two rungs: fish-speech
58
- // (its own binary) above Kokoro (`python -m kokoro`). fish-speech absent must
59
- // not cost the user Kokoro.
60
- const strongGpu = { ramMB: 64000, gpu: { present: true, vramMB: 24000 } };
61
- let ran = "";
62
- const r = runLocalModel("tts", {
63
- specs: strongGpu,
64
- which: (bin) => {
65
- if (bin === "fish-speech") throw new Error("not found");
66
- },
67
- exec: (cmd) => {
68
- ran = cmd;
69
- },
70
- vars: { text: "hello", voice: "af_heart", out: "/tmp/v.wav" },
71
- });
72
-
73
- assert.equal(r.model, "kokoro", "demoted past the missing fish-speech binary");
74
- assert.equal(r.tier, "medium");
75
- assert.match(ran, /kokoro/);
76
- });
77
-
78
- test("every fitting tier failing reports the last tier's install command", () => {
79
- const strongGpu = { ramMB: 64000, gpu: { present: true, vramMB: 24000 } };
80
- const r = runLocalModel("tts", {
81
- specs: strongGpu,
82
- which: ok,
83
- exec: () => {
84
- throw new Error("boom");
85
- },
86
- vars: { text: "hi", out: "/tmp/v.wav" },
87
- });
88
-
89
- assert.equal(r.recommend, "install");
90
- assert.equal(r.model, "kokoro", "the smallest fitting tier is the actionable one");
91
- });
92
-
93
- test("the install recommendation states the download size", () => {
94
- // nothing today tells the user what they are agreeing to before a tool
95
- // starts pulling weights, so the size travels in the payload AND in the
96
- // text a caller shows them
97
- const r = runLocalModel("tts", {
98
- specs: strongCpu,
99
- which: () => {
100
- throw new Error("not found");
101
- },
102
- });
103
-
104
- assert.equal(r.recommend, "install");
105
- assert.equal(typeof r.sizeMB, "number");
106
- assert.ok(r.sizeMB > 0);
107
- assert.match(r.reason, /GB to download/);
108
- });
109
-
110
- test("a failed run still reports the tier's size", () => {
111
- const r = runLocalModel("tts", {
112
- specs: strongCpu,
113
- which: ok,
114
- exec: () => {
115
- throw new Error("boom");
116
- },
117
- });
118
-
119
- assert.equal(r.recommend, "install");
120
- assert.equal(typeof r.sizeMB, "number");
121
- });
@@ -1,222 +0,0 @@
1
- // Official brand marks — the `logo` type's provider tiers, tried in registry
2
- // order. Every tier was verified against a 54-brand stress test (2026-07,
3
- // 100% cascade hit). Hit counts below are a snapshot of that run — they
4
- // drift as the alias/org maps grow; re-run the stress test to refresh them.
5
- //
6
- // 1. svgl — official full-color vector SVGs (+ wordmark variants);
7
- // 40/54 first-hits. Search is substring-based, so
8
- // entities go through alias normalization first
9
- // ("nextjs" never matches "Next.js" raw).
10
- // 2. simple-icons — monochrome official glyphs; caught the long tail the
11
- // others miss (nike, visa, toyota, wechat, bytedance).
12
- // Pinned CDN build for determinism.
13
- // 3. github avatar — the org's official logo for brands with a GitHub
14
- // presence. Known orgs only: guessing a login risks a
15
- // same-named personal account.
16
- // 4. domain favicon — small-raster last resort (DuckDuckGo ip3). Responses
17
- // under ~500B are DDG's globe placeholder, not a hit.
18
- //
19
- // HeyGen asset search is deliberately absent: for brand queries it returns
20
- // generic look-alike icons (0/3 in testing) — worse than a miss. A total miss
21
- // falls through to resolve's normal failure path (`no provider could resolve
22
- // logo`, exit 1).
23
-
24
- import { mkdtempSync, writeFileSync } from "node:fs";
25
- import { tmpdir } from "node:os";
26
- import { join } from "node:path";
27
-
28
- const SVGL_API = "https://api.svgl.app";
29
- const SIMPLE_ICONS_CDN = "https://cdn.jsdelivr.net/npm/simple-icons@16.25.0/icons";
30
- const FAVICON_MIN_BYTES = 500;
31
-
32
- // svgl search queries per entity, tried in order after the raw entity.
33
- const SVGL_ALIASES = {
34
- nextjs: ["next.js", "next"],
35
- aws: ["amazon web services"],
36
- huggingface: ["hugging face"],
37
- cocacola: ["coca-cola"],
38
- mcdonalds: ["mcdonald's"],
39
- };
40
-
41
- // simple-icons slugs that differ from the normalized entity.
42
- const SIMPLE_ICON_SLUGS = {
43
- nextjs: "nextdotjs",
44
- aws: "amazonwebservices",
45
- };
46
-
47
- // Known GitHub orgs. Only mapped entities resolve at this tier — a brand name
48
- // is NOT a GitHub login, and guessing hits same-named personal accounts.
49
- const GITHUB_ORGS = {
50
- slack: "slackhq",
51
- meta: "facebook",
52
- google: "google",
53
- microsoft: "microsoft",
54
- aws: "aws",
55
- vercel: "vercel",
56
- nextjs: "vercel",
57
- alibaba: "alibaba",
58
- heygen: "heygen-com",
59
- };
60
-
61
- // Favicon domains that aren't `<entity>.com`.
62
- const FAVICON_DOMAINS = {
63
- cocacola: "coca-cola.com",
64
- aws: "aws.amazon.com",
65
- nextjs: "nextjs.org",
66
- };
67
-
68
- const norm = (s) =>
69
- String(s)
70
- .toLowerCase()
71
- .replace(/[^a-z0-9]/g, "");
72
-
73
- /** The brand entity for a query: --entity wins; else the intent minus filler. */
74
- export function entityFrom(intent, entity) {
75
- if (entity) return entity.toLowerCase().trim();
76
- return String(intent)
77
- .toLowerCase()
78
- .replace(/\b(logo|logos|icon|brand|official|mark)\b/g, "")
79
- .trim()
80
- .replace(/\s+/g, " ");
81
- }
82
-
83
- /** Exact match after stripping case/spacing/punctuation — "Next.js" ≡ "nextjs". */
84
- export function titleMatches(title, entity) {
85
- return norm(title) === norm(entity);
86
- }
87
-
88
- export function svglQueriesFor(entity) {
89
- return [entity, ...(SVGL_ALIASES[norm(entity)] || [])];
90
- }
91
-
92
- export function simpleIconSlugsFor(entity) {
93
- const slugs = [norm(entity)];
94
- const alias = SIMPLE_ICON_SLUGS[norm(entity)];
95
- if (alias) slugs.push(alias);
96
- return slugs;
97
- }
98
-
99
- export function githubOrgFor(entity) {
100
- return GITHUB_ORGS[norm(entity)] || null;
101
- }
102
-
103
- export function faviconDomainFor(entity) {
104
- return FAVICON_DOMAINS[norm(entity)] || `${norm(entity)}.com`;
105
- }
106
-
107
- async function fetchJson(url) {
108
- const res = await fetch(url, { signal: AbortSignal.timeout(10_000) });
109
- if (!res.ok) return null;
110
- return res.json();
111
- }
112
-
113
- async function urlExists(url) {
114
- const res = await fetch(url, { method: "HEAD", signal: AbortSignal.timeout(10_000) });
115
- return res.ok;
116
- }
117
-
118
- export async function svglSearch(intent, ctx = {}) {
119
- const entity = entityFrom(intent, ctx.entity);
120
- for (const q of svglQueriesFor(entity)) {
121
- let items;
122
- try {
123
- items = await fetchJson(`${SVGL_API}?search=${encodeURIComponent(q)}`);
124
- } catch {
125
- return null; // network down — let the next tier try its own host
126
- }
127
- if (!Array.isArray(items)) continue;
128
- const hit = items.find((it) => titleMatches(it.title, q) || titleMatches(it.title, entity));
129
- if (!hit) continue;
130
- const route = typeof hit.route === "string" ? hit.route : hit.route?.light;
131
- if (!route) continue;
132
- return {
133
- url: route,
134
- ext: ".svg",
135
- source: "search",
136
- metadata: {
137
- description: `${hit.title} logo (official mark)`,
138
- provider: "svgl",
139
- provenance: { entity, query: q, route, wordmark: Boolean(hit.wordmark) },
140
- },
141
- };
142
- }
143
- return null;
144
- }
145
-
146
- export async function simpleIconsSearch(intent, ctx = {}) {
147
- const entity = entityFrom(intent, ctx.entity);
148
- for (const slug of simpleIconSlugsFor(entity)) {
149
- const url = `${SIMPLE_ICONS_CDN}/${slug}.svg`;
150
- let ok;
151
- try {
152
- ok = await urlExists(url);
153
- } catch {
154
- return null;
155
- }
156
- if (!ok) continue;
157
- return {
158
- url,
159
- ext: ".svg",
160
- source: "search",
161
- metadata: {
162
- description: `${entity} logo (official monochrome glyph)`,
163
- provider: "simple-icons",
164
- provenance: { entity, slug, pinned: "simple-icons@16.25.0" },
165
- },
166
- };
167
- }
168
- return null;
169
- }
170
-
171
- export async function githubAvatarSearch(intent, ctx = {}) {
172
- const entity = entityFrom(intent, ctx.entity);
173
- const org = githubOrgFor(entity);
174
- if (!org) return null;
175
- const url = `https://github.com/${org}.png?size=460`;
176
- try {
177
- if (!(await urlExists(url))) return null;
178
- } catch {
179
- return null;
180
- }
181
- return {
182
- url,
183
- ext: ".png",
184
- source: "search",
185
- metadata: {
186
- description: `${entity} logo (GitHub org avatar)`,
187
- provider: "github.avatar",
188
- provenance: { entity, org },
189
- },
190
- };
191
- }
192
-
193
- export async function faviconSearch(intent, ctx = {}) {
194
- const entity = entityFrom(intent, ctx.entity);
195
- const domain = faviconDomainFor(entity);
196
- const url = `https://icons.duckduckgo.com/ip3/${domain}.ico`;
197
- let body;
198
- try {
199
- const res = await fetch(url, { signal: AbortSignal.timeout(10_000) });
200
- if (!res.ok) return null;
201
- body = Buffer.from(await res.arrayBuffer());
202
- } catch {
203
- return null;
204
- }
205
- if (body.byteLength < FAVICON_MIN_BYTES) return null; // DDG placeholder, not a logo
206
- // Hand the verified bytes over as a local file: the freeze step copies it
207
- // instead of re-downloading, so the size check is authoritative over what
208
- // gets frozen and the favicon tier costs one network round-trip, not two.
209
- const bytes = body.byteLength;
210
- const tmp = join(mkdtempSync(join(tmpdir(), "media-use-logo-")), `${domain}.ico`);
211
- writeFileSync(tmp, body);
212
- return {
213
- localPath: tmp,
214
- ext: ".ico",
215
- source: "search",
216
- metadata: {
217
- description: `${entity} favicon (small raster — chip-size use only)`,
218
- provider: "favicon.ddg",
219
- provenance: { entity, domain, bytes, low_res: true },
220
- },
221
- };
222
- }
@@ -1,137 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert";
3
- import { readFileSync } from "node:fs";
4
- import {
5
- entityFrom,
6
- titleMatches,
7
- svglQueriesFor,
8
- simpleIconSlugsFor,
9
- githubOrgFor,
10
- faviconDomainFor,
11
- svglSearch,
12
- simpleIconsSearch,
13
- githubAvatarSearch,
14
- faviconSearch,
15
- } from "./logo-provider.mjs";
16
- import { getProviders, runProviders } from "./registry.mjs";
17
-
18
- test("entityFrom strips filler words from the intent; --entity wins", () => {
19
- assert.equal(entityFrom("LinkedIn logo"), "linkedin");
20
- assert.equal(entityFrom("official Slack brand mark"), "slack");
21
- assert.equal(entityFrom("anything", "Notion"), "notion");
22
- });
23
-
24
- test("titleMatches ignores case, spacing, punctuation — and rejects lookalikes", () => {
25
- assert.ok(titleMatches("Next.js", "nextjs"));
26
- assert.ok(titleMatches("Coca-Cola", "coca cola"));
27
- assert.ok(!titleMatches("Slackware", "slack"));
28
- });
29
-
30
- test("svgl queries include the alias forms the raw entity can't match", () => {
31
- assert.ok(svglQueriesFor("nextjs").includes("next.js"));
32
- assert.ok(svglQueriesFor("aws").includes("amazon web services"));
33
- assert.deepEqual(svglQueriesFor("figma"), ["figma"]);
34
- });
35
-
36
- test("simple-icons slugs cover the renamed entries", () => {
37
- assert.ok(simpleIconSlugsFor("nextjs").includes("nextdotjs"));
38
- assert.ok(simpleIconSlugsFor("aws").includes("amazonwebservices"));
39
- assert.deepEqual(simpleIconSlugsFor("nike"), ["nike"]);
40
- });
41
-
42
- test("github avatar tier never guesses an org", () => {
43
- assert.equal(githubOrgFor("slack"), "slackhq");
44
- assert.equal(githubOrgFor("heygen"), "heygen-com");
45
- assert.equal(githubOrgFor("some-random-startup"), null);
46
- });
47
-
48
- test("favicon domain defaults to <entity>.com with explicit overrides", () => {
49
- assert.equal(faviconDomainFor("cocacola"), "coca-cola.com");
50
- assert.equal(faviconDomainFor("stripe"), "stripe.com");
51
- });
52
-
53
- // --- async tiers, network mocked -------------------------------------------
54
- // The 54-brand stress test is a manual snapshot; these pin the same behavior
55
- // as CI gates: descriptor shape, alias retry, error→null fallthrough, the
56
- // placeholder filter, and the real cascade order under a mocked network.
57
-
58
- const json = (data) => new Response(JSON.stringify(data), { status: 200 });
59
- const status = (code) => new Response(null, { status: code });
60
- const bin = (n) => new Response(new Uint8Array(n), { status: 200 });
61
-
62
- test("svglSearch returns the descriptor shape on an exact title hit", async (t) => {
63
- t.mock.method(globalThis, "fetch", async () =>
64
- json([{ title: "Figma", route: "https://svgl.app/library/figma.svg" }]),
65
- );
66
- const res = await svglSearch("Figma logo", {});
67
- assert.equal(res.url, "https://svgl.app/library/figma.svg");
68
- assert.equal(res.ext, ".svg");
69
- assert.equal(res.metadata.provider, "svgl");
70
- });
71
-
72
- test("svglSearch skips a non-array payload and retries with the alias query", async (t) => {
73
- const seen = [];
74
- t.mock.method(globalThis, "fetch", async (url) => {
75
- seen.push(decodeURIComponent(String(url)));
76
- return seen.length === 1
77
- ? json({ error: "unexpected shape" })
78
- : json([{ title: "Next.js", route: "https://svgl.app/library/nextjs.svg" }]);
79
- });
80
- const res = await svglSearch("nextjs logo", {});
81
- assert.equal(res.metadata.provenance.query, "next.js", "hit came from the alias query");
82
- assert.ok(seen.length >= 2, "raw query then alias");
83
- });
84
-
85
- test("svglSearch returns null when the network is down — the cascade falls through", async (t) => {
86
- t.mock.method(globalThis, "fetch", async () => {
87
- throw new Error("network down");
88
- });
89
- assert.equal(await svglSearch("figma logo", {}), null);
90
- });
91
-
92
- test("simpleIconsSearch falls to the next slug on a 404", async (t) => {
93
- const seen = [];
94
- t.mock.method(globalThis, "fetch", async (url) => {
95
- seen.push(String(url));
96
- return String(url).includes("amazonwebservices") ? status(200) : status(404);
97
- });
98
- const res = await simpleIconsSearch("aws logo", {});
99
- assert.ok(res.url.endsWith("amazonwebservices.svg"));
100
- assert.equal(seen.length, 2, "plain slug 404s first, alias slug hits");
101
- });
102
-
103
- test("faviconSearch rejects DDG's sub-500B placeholder with null", async (t) => {
104
- t.mock.method(globalThis, "fetch", async () => bin(120));
105
- assert.equal(await faviconSearch("someco logo", {}), null);
106
- });
107
-
108
- test("faviconSearch hands verified bytes over as a local file — one fetch, no re-download", async (t) => {
109
- const fetchMock = t.mock.method(globalThis, "fetch", async () => bin(600));
110
- const res = await faviconSearch("someco logo", {});
111
- assert.ok(res.localPath, "returns a localPath, not a url");
112
- assert.equal(readFileSync(res.localPath).byteLength, 600, "frozen bytes are the verified bytes");
113
- assert.equal(fetchMock.mock.callCount(), 1, "single network round-trip");
114
- assert.equal(res.metadata.provenance.low_res, true);
115
- });
116
-
117
- test("githubAvatarSearch never touches the network for an unmapped entity", async (t) => {
118
- const fetchMock = t.mock.method(globalThis, "fetch", async () => status(200));
119
- assert.equal(await githubAvatarSearch("some-random-startup logo", {}), null);
120
- assert.equal(fetchMock.mock.callCount(), 0);
121
- });
122
-
123
- test("the real logo cascade falls through tier by tier to the first hit", async (t) => {
124
- t.mock.method(globalThis, "fetch", async (url) => {
125
- const u = String(url);
126
- if (u.includes("api.svgl.app")) return json([]); // tier 1: no hit
127
- if (u.includes("jsdelivr")) return status(404); // tier 2: no such slug
128
- // tier 3 (github) is never called: entity is unmapped
129
- if (u.includes("duckduckgo")) return bin(600); // tier 4: real favicon
130
- throw new Error(`unexpected fetch: ${u}`);
131
- });
132
- const res = await runProviders(getProviders("logo"), "search", "zzzbrand logo", {
133
- entity: "zzzbrand",
134
- });
135
- assert.ok(res, "cascade must land on the favicon tier");
136
- assert.equal(res.metadata.provider, "favicon.ddg");
137
- });
@@ -1,94 +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, selectModel, selectModelLadder } from "./local-models.mjs";
7
-
8
- export async function ltxVideoGenerate(
9
- intent,
10
- ctx,
11
- execFn = execFileSync,
12
- pathExists = existsSync,
13
- unlinkFn = unlinkSync,
14
- ) {
15
- const specs = ctx?.specs || probeSpecs();
16
- const ladder = selectModelLadder("videogen", specs, { preferTier: ctx?.preferTier });
17
- if (!ladder.length) {
18
- const { reason } = selectModel("videogen", specs, { preferTier: ctx?.preferTier });
19
- console.error(
20
- `media-use: local video gen not enabled (${reason}). Enable a fitting free on-device LTX model to use this provider.`,
21
- );
22
- return null;
23
- }
24
-
25
- // Each attempt mints its own timestamped output path, so a partial artifact
26
- // from a failed tier is orphaned rather than overwritten - and a lower tier
27
- // then succeeding hides it. Discard it before demoting. Best-effort: a
28
- // partial we cannot remove must never mask the real failure.
29
- const discardPartial = (path) => {
30
- try {
31
- if (pathExists(path)) unlinkFn(path);
32
- } catch {
33
- // nothing actionable: the generate failure below is the real story
34
- }
35
- };
36
-
37
- // Walk the whole ladder, best tier first. A tier that cannot run on this
38
- // machine for a reason no spec check sees (runner off PATH, gated weights, an
39
- // OOM) demotes to the next fitting tier instead of failing local video gen
40
- // outright. Every demotion is reported: a silent drop to a smaller model
41
- // leaves the caller wondering why the output looks the way it does.
42
- for (const model of ladder) {
43
- const bin = model.invoke.trim().split(/\s+/)[0];
44
- try {
45
- execFn("which", [bin], { stdio: ["ignore", "ignore", "ignore"] });
46
- } catch {
47
- console.error(
48
- `media-use: local video gen not enabled (\`${bin}\` not on PATH). Install for free on-device LTX: ${model.install}. Heads up: ${model.id} ${describeDownload(model.sizeMB)}.`,
49
- );
50
- continue;
51
- }
52
-
53
- const outPath = join(tmpdir(), `media-use-ltx-${process.pid}-${Date.now()}.mp4`);
54
- const argv = buildArgv(model.invoke, {
55
- prompt: intent,
56
- w: ctx?.width || 512,
57
- h: ctx?.height || 320,
58
- frames: ctx?.frames || 33,
59
- out: outPath,
60
- });
61
- argv.shift();
62
-
63
- try {
64
- execFn(bin, argv, {
65
- encoding: "utf8",
66
- timeout: 1_800_000,
67
- stdio: ["ignore", "pipe", "pipe"],
68
- });
69
- } catch (err) {
70
- discardPartial(outPath);
71
- console.error(
72
- `media-use: local video gen (${model.id}) failed: ${err.stderr?.toString().trim().slice(-200) || err.message}`,
73
- );
74
- continue;
75
- }
76
- if (!pathExists(outPath)) {
77
- console.error(
78
- `media-use: local video gen (${model.id}) exited cleanly but wrote no output file`,
79
- );
80
- continue;
81
- }
82
- return {
83
- localPath: outPath,
84
- ext: ".mp4",
85
- source: "generated",
86
- metadata: {
87
- description: intent,
88
- provider: "ltx.local",
89
- provenance: { prompt: intent },
90
- },
91
- };
92
- }
93
- return null;
94
- }