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,127 +0,0 @@
1
- import { execFileSync } from "node:child_process";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { freezeUrl } from "./freeze.mjs";
5
- import {
6
- classifyHeygenErrorCode,
7
- HEYGEN_AUTH_COMMAND,
8
- HEYGEN_CLIENT_SOURCE_ARGV,
9
- reportHeygenFailure,
10
- runHeygenJson,
11
- } from "./heygen-cli.mjs";
12
-
13
- export const AVATAR_VIDEO_SIGNIN_MESSAGE = `media-use: avatar video is free for new API users — sign in: ${HEYGEN_AUTH_COMMAND}`;
14
-
15
- // Cache only a truthy id -- a transient discovery failure must not poison the
16
- // cache with `null` and permanently disable heygen.video for the rest of the
17
- // process. `onError` lets the caller distinguish not_authenticated (and nudge
18
- // onboarding) from any other discovery failure.
19
- let cachedAvatarId;
20
- function defaultAvatarId(onError) {
21
- if (cachedAvatarId) return cachedAvatarId;
22
- const j = runHeygenJson(
23
- "heygen",
24
- ["avatar", "list", "--ownership", "public", "--limit", "1"],
25
- "avatar list",
26
- onError,
27
- );
28
- cachedAvatarId = j?.data?.[0]?.avatar_id || null;
29
- return cachedAvatarId;
30
- }
31
-
32
- let cachedStarfishVoiceId;
33
- function defaultStarfishVoiceId(onError) {
34
- if (cachedStarfishVoiceId) return cachedStarfishVoiceId;
35
- const j = runHeygenJson(
36
- "heygen",
37
- ["voice", "list", "--engine", "starfish", "--limit", "1"],
38
- "voice list",
39
- onError,
40
- );
41
- cachedStarfishVoiceId = j?.data?.[0]?.voice_id || null;
42
- return cachedStarfishVoiceId;
43
- }
44
-
45
- export async function heygenVideoGenerate(intent, ctx) {
46
- let discoveryFailureReason = null;
47
- const captureReason = (reason) => {
48
- discoveryFailureReason ??= reason;
49
- };
50
-
51
- // Short-circuit: once one discovery call fails, the result is null either
52
- // way, so don't attempt the second -- that would double-fire the onboarding
53
- // message and the provider-error telemetry ping for what's really one failure.
54
- const avatarId = ctx?.avatarId || defaultAvatarId(captureReason);
55
- if (!avatarId) {
56
- if (discoveryFailureReason === "not_authenticated") console.error(AVATAR_VIDEO_SIGNIN_MESSAGE);
57
- return null;
58
- }
59
- const voiceId = ctx?.voiceId || defaultStarfishVoiceId(captureReason);
60
- if (!voiceId) {
61
- if (discoveryFailureReason === "not_authenticated") console.error(AVATAR_VIDEO_SIGNIN_MESSAGE);
62
- return null;
63
- }
64
-
65
- let out;
66
- try {
67
- out = execFileSync(
68
- "heygen",
69
- [
70
- ...HEYGEN_CLIENT_SOURCE_ARGV,
71
- "video",
72
- "create",
73
- "--wait",
74
- "-d",
75
- JSON.stringify({
76
- type: "avatar",
77
- avatar_id: avatarId,
78
- script: intent,
79
- voice_id: voiceId,
80
- }),
81
- ],
82
- {
83
- encoding: "utf8",
84
- timeout: 300000,
85
- stdio: ["pipe", "pipe", "pipe"],
86
- },
87
- );
88
- } catch (err) {
89
- if (classifyHeygenErrorCode(err) === "not_authenticated") {
90
- console.error(AVATAR_VIDEO_SIGNIN_MESSAGE);
91
- }
92
- reportHeygenFailure(err, "heygen video create");
93
- return null;
94
- }
95
-
96
- let parsed;
97
- try {
98
- parsed = JSON.parse(out);
99
- } catch {
100
- console.error("media-use: `heygen video create` returned invalid JSON");
101
- return null;
102
- }
103
- const videoUrl = parsed?.data?.video_url;
104
- if (typeof videoUrl !== "string" || !videoUrl) {
105
- console.error("media-use: `heygen video create` returned no video URL");
106
- return null;
107
- }
108
-
109
- const tmpPath = join(tmpdir(), `media-use-heygen-video-${process.pid}-${Date.now()}.mp4`);
110
- try {
111
- await freezeUrl(videoUrl, tmpPath);
112
- } catch (err) {
113
- console.error(`media-use: heygen video download failed: ${err.message}`);
114
- return null;
115
- }
116
-
117
- return {
118
- localPath: tmpPath,
119
- ext: ".mp4",
120
- source: "generated",
121
- metadata: {
122
- description: intent,
123
- provider: "heygen.video",
124
- provenance: { prompt: intent },
125
- },
126
- };
127
- }
@@ -1,344 +0,0 @@
1
- import { strict as assert } from "node:assert";
2
- import { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
- import http from "node:http";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- import { test } from "node:test";
7
- import { HEYGEN_NOT_AUTHENTICATED_MESSAGE } from "./heygen-cli.mjs";
8
- import { AVATAR_VIDEO_SIGNIN_MESSAGE } from "./heygen-video-provider.mjs";
9
-
10
- const VIDEO_FIXTURE = Buffer.from("tiny heygen video fixture");
11
- let importCount = 0;
12
-
13
- async function freshGenerate() {
14
- importCount += 1;
15
- const module = await import(`./heygen-video-provider.mjs?test=${importCount}`);
16
- return module.heygenVideoGenerate;
17
- }
18
-
19
- async function listenVideoServer() {
20
- const server = http.createServer((req, res) => {
21
- if (req.url !== "/video.mp4") {
22
- res.writeHead(404).end();
23
- return;
24
- }
25
- res.writeHead(200, {
26
- "content-length": VIDEO_FIXTURE.length,
27
- "content-type": "video/mp4",
28
- });
29
- res.end(VIDEO_FIXTURE);
30
- });
31
- await new Promise((resolve) => server.listen(0, resolve));
32
- const address = server.address();
33
- assert.ok(address && typeof address !== "string");
34
- return {
35
- server,
36
- url: `http://127.0.0.1:${address.port}/video.mp4`,
37
- };
38
- }
39
-
40
- async function listenFailingVideoServer() {
41
- const server = http.createServer((req, res) => {
42
- res.writeHead(500).end();
43
- });
44
- await new Promise((resolve) => server.listen(0, resolve));
45
- const address = server.address();
46
- assert.ok(address && typeof address !== "string");
47
- return {
48
- server,
49
- url: `http://127.0.0.1:${address.port}/video.mp4`,
50
- };
51
- }
52
-
53
- function closeServer(server) {
54
- return new Promise((resolve, reject) => {
55
- server.close((err) => (err ? reject(err) : resolve()));
56
- });
57
- }
58
-
59
- async function withFakeHeygen(options, run) {
60
- const dir = mkdtempSync(join(tmpdir(), "media-use-heygen-video-provider-"));
61
- const capturePath = join(dir, "argv.log");
62
- const heygenPath = join(dir, "heygen");
63
- const previousEnv = {
64
- PATH: process.env.PATH,
65
- HEYGEN_CAPTURE_PATH: process.env.HEYGEN_CAPTURE_PATH,
66
- HEYGEN_VIDEO_MODE: process.env.HEYGEN_VIDEO_MODE,
67
- HEYGEN_VIDEO_RESPONSE: process.env.HEYGEN_VIDEO_RESPONSE,
68
- HEYGEN_DISCOVERY_MODE: process.env.HEYGEN_DISCOVERY_MODE,
69
- HYPERFRAMES_NO_TELEMETRY: process.env.HYPERFRAMES_NO_TELEMETRY,
70
- };
71
-
72
- writeFileSync(
73
- heygenPath,
74
- `#!/bin/sh
75
- printf '%s\\n' "$*" >> "$HEYGEN_CAPTURE_PATH"
76
- case "$*" in
77
- *"avatar list"*)
78
- case "$HEYGEN_DISCOVERY_MODE" in
79
- auth) printf '%s\\n' 'HTTP 401 Unauthorized' >&2; exit 1 ;;
80
- *) printf '%s\\n' '{"data":[{"avatar_id":"avatar-public-1"}]}' ;;
81
- esac
82
- ;;
83
- *"voice list"*)
84
- case "$HEYGEN_DISCOVERY_MODE" in
85
- auth) printf '%s\\n' 'HTTP 401 Unauthorized' >&2; exit 1 ;;
86
- *) printf '%s\\n' '{"data":[{"voice_id":"voice-starfish-1"}]}' ;;
87
- esac
88
- ;;
89
- *"video create"*)
90
- case "$HEYGEN_VIDEO_MODE" in
91
- auth) printf '%s\\n' 'HTTP 401 Unauthorized' >&2; exit 1 ;;
92
- other) printf '%s\\n' 'provider unavailable' >&2; exit 1 ;;
93
- *) printf '%s\\n' "$HEYGEN_VIDEO_RESPONSE" ;;
94
- esac
95
- ;;
96
- esac
97
- `,
98
- );
99
- chmodSync(heygenPath, 0o755);
100
- process.env.PATH = `${dir}:${previousEnv.PATH ?? ""}`;
101
- process.env.HEYGEN_CAPTURE_PATH = capturePath;
102
- process.env.HEYGEN_VIDEO_MODE = options.mode ?? "success";
103
- process.env.HEYGEN_VIDEO_RESPONSE = options.response ?? "";
104
- process.env.HEYGEN_DISCOVERY_MODE = options.discoveryMode ?? "";
105
- process.env.HYPERFRAMES_NO_TELEMETRY = "1";
106
-
107
- try {
108
- return await run({
109
- invocations: () => readFileSync(capturePath, "utf8").trim().split("\n"),
110
- });
111
- } finally {
112
- for (const [key, value] of Object.entries(previousEnv)) {
113
- if (value === undefined) delete process.env[key];
114
- else process.env[key] = value;
115
- }
116
- rmSync(dir, { recursive: true, force: true });
117
- }
118
- }
119
-
120
- function bodyFromInvocation(invocation) {
121
- const marker = " -d ";
122
- const start = invocation.indexOf(marker);
123
- assert.notEqual(start, -1);
124
- return JSON.parse(invocation.slice(start + marker.length));
125
- }
126
-
127
- test("downloads a generated avatar video and returns the generated MP4 result", async () => {
128
- const { server, url } = await listenVideoServer();
129
- let localPath;
130
- try {
131
- await withFakeHeygen(
132
- { response: JSON.stringify({ data: { video_url: url } }) },
133
- async ({ invocations }) => {
134
- const heygenVideoGenerate = await freshGenerate();
135
- const intent = "Welcome to the HyperFrames launch";
136
- const result = await heygenVideoGenerate(intent, {});
137
- localPath = result?.localPath;
138
- const calls = invocations();
139
- const create = calls.find((call) => call.includes("video create"));
140
-
141
- assert.ok(create);
142
- assert.match(create, /--headers X-HeyGen-Client-Source: media-use/);
143
- assert.deepEqual(bodyFromInvocation(create), {
144
- type: "avatar",
145
- avatar_id: "avatar-public-1",
146
- script: intent,
147
- voice_id: "voice-starfish-1",
148
- });
149
- assert.ok(result);
150
- assert.equal(join(tmpdir(), result.localPath.slice(tmpdir().length + 1)), result.localPath);
151
- assert.match(result.localPath, /media-use-heygen-video-\d+-\d+\.mp4$/);
152
- assert.deepEqual(result, {
153
- localPath: result.localPath,
154
- ext: ".mp4",
155
- source: "generated",
156
- metadata: {
157
- description: intent,
158
- provider: "heygen.video",
159
- provenance: { prompt: intent },
160
- },
161
- });
162
- assert.deepEqual(readFileSync(result.localPath), VIDEO_FIXTURE);
163
- },
164
- );
165
- } finally {
166
- if (localPath) rmSync(localPath, { force: true });
167
- await closeServer(server);
168
- }
169
- });
170
-
171
- test("tags video creation but not avatar or voice discovery", async () => {
172
- const { server, url } = await listenVideoServer();
173
- let localPath;
174
- try {
175
- await withFakeHeygen(
176
- { response: JSON.stringify({ data: { video_url: url } }) },
177
- async ({ invocations }) => {
178
- const heygenVideoGenerate = await freshGenerate();
179
- const result = await heygenVideoGenerate("Header regression guard", {});
180
- localPath = result?.localPath;
181
- const calls = invocations();
182
-
183
- assert.equal(calls.length, 3);
184
- assert.match(calls[0], /^avatar list --ownership public --limit 1$/);
185
- assert.doesNotMatch(calls[0], /X-HeyGen-Client-Source/);
186
- assert.match(calls[1], /^voice list --engine starfish --limit 1$/);
187
- assert.doesNotMatch(calls[1], /X-HeyGen-Client-Source/);
188
- assert.match(calls[2], /video create/);
189
- assert.match(calls[2], /X-HeyGen-Client-Source: media-use/);
190
- },
191
- );
192
- } finally {
193
- if (localPath) rmSync(localPath, { force: true });
194
- await closeServer(server);
195
- }
196
- });
197
-
198
- test("uses explicit avatar and voice overrides without discovery", async () => {
199
- const { server, url } = await listenVideoServer();
200
- let localPath;
201
- try {
202
- await withFakeHeygen(
203
- { response: JSON.stringify({ data: { video_url: url } }) },
204
- async ({ invocations }) => {
205
- const heygenVideoGenerate = await freshGenerate();
206
- const result = await heygenVideoGenerate("Use my presenter", {
207
- avatarId: "avatar-override",
208
- voiceId: "voice-override",
209
- });
210
- localPath = result?.localPath;
211
- const calls = invocations();
212
-
213
- assert.equal(calls.length, 1);
214
- assert.match(calls[0], /video create/);
215
- assert.deepEqual(bodyFromInvocation(calls[0]), {
216
- type: "avatar",
217
- avatar_id: "avatar-override",
218
- script: "Use my presenter",
219
- voice_id: "voice-override",
220
- });
221
- },
222
- );
223
- } finally {
224
- if (localPath) rmSync(localPath, { force: true });
225
- await closeServer(server);
226
- }
227
- });
228
-
229
- test("caches discovered avatar and voice IDs for the process", async () => {
230
- const { server, url } = await listenVideoServer();
231
- const localPaths = new Set();
232
- try {
233
- await withFakeHeygen(
234
- { response: JSON.stringify({ data: { video_url: url } }) },
235
- async ({ invocations }) => {
236
- const heygenVideoGenerate = await freshGenerate();
237
- for (const intent of ["First avatar video", "Second avatar video"]) {
238
- const result = await heygenVideoGenerate(intent, {});
239
- if (result) localPaths.add(result.localPath);
240
- }
241
- const calls = invocations();
242
-
243
- assert.equal(calls.filter((call) => call.startsWith("avatar list ")).length, 1);
244
- assert.equal(calls.filter((call) => call.startsWith("voice list ")).length, 1);
245
- assert.equal(calls.filter((call) => call.includes("video create")).length, 2);
246
- },
247
- );
248
- } finally {
249
- for (const localPath of localPaths) rmSync(localPath, { force: true });
250
- await closeServer(server);
251
- }
252
- });
253
-
254
- test("prints auth onboarding and reports an unauthenticated create failure", async (t) => {
255
- const errors = [];
256
- t.mock.method(console, "error", (message) => errors.push(message));
257
-
258
- await withFakeHeygen({ mode: "auth" }, async () => {
259
- const heygenVideoGenerate = await freshGenerate();
260
- const result = await heygenVideoGenerate("Sign-in failure", {
261
- avatarId: "avatar-override",
262
- voiceId: "voice-override",
263
- });
264
-
265
- assert.equal(result, null);
266
- assert.ok(errors.includes(AVATAR_VIDEO_SIGNIN_MESSAGE));
267
- assert.ok(errors.includes(HEYGEN_NOT_AUTHENTICATED_MESSAGE));
268
- });
269
- });
270
-
271
- test("reports other create failures without auth onboarding", async (t) => {
272
- const errors = [];
273
- t.mock.method(console, "error", (message) => errors.push(message));
274
-
275
- await withFakeHeygen({ mode: "other" }, async () => {
276
- const heygenVideoGenerate = await freshGenerate();
277
- const result = await heygenVideoGenerate("Provider failure", {
278
- avatarId: "avatar-override",
279
- voiceId: "voice-override",
280
- });
281
-
282
- assert.equal(result, null);
283
- assert.ok(!errors.includes(AVATAR_VIDEO_SIGNIN_MESSAGE));
284
- assert.ok(errors.includes("media-use: `heygen video create` failed: provider unavailable"));
285
- });
286
- });
287
-
288
- test("falls through on non-JSON and error responses", async (t) => {
289
- t.mock.method(console, "error", () => {});
290
-
291
- for (const response of ["not JSON", '{"error":{"message":"render failed"}}']) {
292
- await withFakeHeygen({ response }, async () => {
293
- const heygenVideoGenerate = await freshGenerate();
294
- const result = await heygenVideoGenerate("Unusable response", {
295
- avatarId: "avatar-override",
296
- voiceId: "voice-override",
297
- });
298
-
299
- assert.equal(result, null);
300
- });
301
- }
302
- });
303
-
304
- test("onboards and returns null when avatar/voice discovery itself is unauthenticated", async (t) => {
305
- const errors = [];
306
- t.mock.method(console, "error", (message) => errors.push(message));
307
-
308
- // Both avatar list AND voice list would fail unauthenticated (discoveryMode
309
- // "auth" applies to both in the fake CLI) -- the short-circuit after the
310
- // first failure must mean only one is ever attempted, so the onboarding
311
- // message and the provider-error telemetry ping each fire exactly once
312
- // instead of double-firing for what's really one auth failure.
313
- await withFakeHeygen({ discoveryMode: "auth" }, async ({ invocations }) => {
314
- const heygenVideoGenerate = await freshGenerate();
315
- const result = await heygenVideoGenerate("Discovery auth failure", {});
316
-
317
- assert.equal(result, null);
318
- assert.equal(
319
- errors.filter((message) => message === AVATAR_VIDEO_SIGNIN_MESSAGE).length,
320
- 1,
321
- "onboarding message must fire exactly once, not once per failed discovery call",
322
- );
323
- const calls = invocations();
324
- assert.equal(calls.length, 1, "must short-circuit after the first discovery failure");
325
- assert.match(calls[0], /^avatar list /);
326
- });
327
- });
328
-
329
- test("download failure after a successful create returns null and logs a diagnostic", async () => {
330
- const { server, url } = await listenFailingVideoServer();
331
- try {
332
- await withFakeHeygen({ response: JSON.stringify({ data: { video_url: url } }) }, async () => {
333
- const heygenVideoGenerate = await freshGenerate();
334
- const result = await heygenVideoGenerate("Download failure", {
335
- avatarId: "avatar-override",
336
- voiceId: "voice-override",
337
- });
338
-
339
- assert.equal(result, null);
340
- });
341
- } finally {
342
- await closeServer(server);
343
- }
344
- });
@@ -1,44 +0,0 @@
1
- import { heygenSearch } from "./heygen-search.mjs";
2
-
3
- export const imageProvider = {
4
- async search(intent) {
5
- const results = heygenSearch("asset search", intent, { type: "image" });
6
- if (!results) return null;
7
- const best = results[0];
8
- return {
9
- url: best.url,
10
- source: "search",
11
- // ext derived from the asset URL by resolve.mjs (.jpg/.png/.webp)
12
- metadata: {
13
- description: intent,
14
- width: best.width || null,
15
- height: best.height || null,
16
- transparent: best.is_transparent || false,
17
- provider: "heygen.asset.search",
18
- provenance: { asset_id: best.id, score: best.score },
19
- },
20
- };
21
- },
22
- };
23
-
24
- export const iconProvider = {
25
- async search(intent) {
26
- // No minScore: the `asset search` backend rejects --min-score and returns no score field.
27
- const results = heygenSearch("asset search", intent, { type: "icon" });
28
- if (!results) return null;
29
- const best = results[0];
30
- return {
31
- url: best.url,
32
- source: "search",
33
- // ext derived from the asset URL by resolve.mjs — catalog icons are .png, not .svg
34
- metadata: {
35
- description: intent,
36
- width: best.width || null,
37
- height: best.height || null,
38
- transparent: best.is_transparent ?? true,
39
- provider: "heygen.asset.search",
40
- provenance: { asset_id: best.id, score: best.score, type: "icon" },
41
- },
42
- };
43
- },
44
- };