dsh-drawai 0.3.4 → 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 (538) hide show
  1. package/LICENSE +4154 -0
  2. package/README.md +49 -11
  3. package/lib/audio-media.js +150 -0
  4. package/lib/audio-service.js +66 -0
  5. package/lib/canvas-format.js +134 -0
  6. package/lib/client.js +5090 -184
  7. package/lib/comfyui-default-workflow.mjs +1825 -0
  8. package/lib/comfyui-workflow.mjs +426 -0
  9. package/lib/document-commands.js +12 -0
  10. package/lib/document-core.js +29 -0
  11. package/lib/drawing-runner.js +6 -4
  12. package/lib/drawing-tasks.js +26 -0
  13. package/lib/ffmpeg-manager.js +1056 -0
  14. package/lib/imagegen.mjs +596 -0
  15. package/lib/index.js +1762 -129
  16. package/lib/media.js +26 -13
  17. package/lib/mgstyle-core.js +75 -0
  18. package/lib/motion/apply.js +181 -0
  19. package/lib/motion/asset-pack-lock.js +10 -0
  20. package/lib/motion/asset-pack.js +335 -0
  21. package/lib/motion/assets.js +291 -0
  22. package/lib/motion/audio.js +103 -0
  23. package/lib/motion/audiolevel.js +63 -0
  24. package/lib/motion/audiomix.js +144 -0
  25. package/lib/motion/beats.js +338 -0
  26. package/lib/motion/builtin-assets.js +62 -0
  27. package/lib/motion/canvas-spec.js +442 -0
  28. package/lib/motion/capture.js +95 -0
  29. package/lib/motion/cards.js +80 -0
  30. package/lib/motion/collect.js +449 -0
  31. package/lib/motion/delivery.js +140 -0
  32. package/lib/motion/edge-speech.py +90 -0
  33. package/lib/motion/entry.jsx +73 -0
  34. package/lib/motion/export.js +200 -0
  35. package/lib/motion/ffmpeg.js +43 -0
  36. package/lib/motion/fonts.js +71 -0
  37. package/lib/motion/jobs.js +117 -0
  38. package/lib/motion/json.js +4 -0
  39. package/lib/motion/media-catalog.js +59 -0
  40. package/lib/motion/mgstyles/BRIEF-TEMPLATE.md +63 -0
  41. package/lib/motion/mgstyles/briefs/01-flat-vector.md +104 -0
  42. package/lib/motion/mgstyles/briefs/02-line-art.md +97 -0
  43. package/lib/motion/mgstyles/briefs/03-isometric.md +108 -0
  44. package/lib/motion/mgstyles/briefs/05-cel-boil.md +145 -0
  45. package/lib/motion/mgstyles/briefs/06-collage.md +149 -0
  46. package/lib/motion/mgstyles/briefs/07-liquid.md +106 -0
  47. package/lib/motion/mgstyles/briefs/08-morph.md +111 -0
  48. package/lib/motion/mgstyles/briefs/09-bauhaus.md +150 -0
  49. package/lib/motion/mgstyles/briefs/10-synthwave.md +151 -0
  50. package/lib/motion/mgstyles/briefs/12-aurora-glass.md +147 -0
  51. package/lib/motion/mgstyles/briefs/18-hanazi.md +140 -0
  52. package/lib/motion/mgstyles/briefs/19-paperclip.md +156 -0
  53. package/lib/motion/mgstyles/briefs/20-pixel.md +118 -0
  54. package/lib/motion/mgstyles/briefs/22-hud.md +118 -0
  55. package/lib/motion/mgstyles/catalog.d/01-flat-vector.json +34 -0
  56. package/lib/motion/mgstyles/catalog.d/02-line-art.json +34 -0
  57. package/lib/motion/mgstyles/catalog.d/03-isometric.json +35 -0
  58. package/lib/motion/mgstyles/catalog.d/05-cel-boil.json +28 -0
  59. package/lib/motion/mgstyles/catalog.d/06-collage.json +28 -0
  60. package/lib/motion/mgstyles/catalog.d/07-liquid.json +28 -0
  61. package/lib/motion/mgstyles/catalog.d/08-morph.json +28 -0
  62. package/lib/motion/mgstyles/catalog.d/09-bauhaus.json +28 -0
  63. package/lib/motion/mgstyles/catalog.d/10-synthwave.json +28 -0
  64. package/lib/motion/mgstyles/catalog.d/12-aurora-glass.json +28 -0
  65. package/lib/motion/mgstyles/catalog.d/18-hanazi.json +28 -0
  66. package/lib/motion/mgstyles/catalog.d/19-paperclip.json +28 -0
  67. package/lib/motion/mgstyles/catalog.d/20-pixel.json +28 -0
  68. package/lib/motion/mgstyles/catalog.d/22-hud.json +28 -0
  69. package/lib/motion/mgstyles/catalog.json +1356 -0
  70. package/lib/motion/mgstyles/upstream/README.md +147 -0
  71. package/lib/motion/mgstyles/upstream/README.zh-CN.md +147 -0
  72. package/lib/motion/mgstyles/upstream/demos/01-flat-vector/cues.json +1 -0
  73. package/lib/motion/mgstyles/upstream/demos/01-flat-vector/index.html +712 -0
  74. package/lib/motion/mgstyles/upstream/demos/02-line-art/cues.json +331 -0
  75. package/lib/motion/mgstyles/upstream/demos/02-line-art/film.js +676 -0
  76. package/lib/motion/mgstyles/upstream/demos/02-line-art/index.html +18 -0
  77. package/lib/motion/mgstyles/upstream/demos/02-line-art/tools/dump_timing.mjs +26 -0
  78. package/lib/motion/mgstyles/upstream/demos/03-isometric/cues.json +109 -0
  79. package/lib/motion/mgstyles/upstream/demos/03-isometric/index.html +25 -0
  80. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/anim.js +82 -0
  81. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/main.js +219 -0
  82. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/night5.js +180 -0
  83. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/render.js +202 -0
  84. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/title.js +167 -0
  85. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/title5.js +294 -0
  86. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/ui.js +141 -0
  87. package/lib/motion/mgstyles/upstream/demos/03-isometric/js/world.js +1399 -0
  88. package/lib/motion/mgstyles/upstream/demos/05-cel-boil/cues.json +157 -0
  89. package/lib/motion/mgstyles/upstream/demos/05-cel-boil/index.html +34 -0
  90. package/lib/motion/mgstyles/upstream/demos/05-cel-boil/js/engine.js +326 -0
  91. package/lib/motion/mgstyles/upstream/demos/05-cel-boil/js/scene.js +2036 -0
  92. package/lib/motion/mgstyles/upstream/demos/06-collage/assets/gen/layout.json +157 -0
  93. package/lib/motion/mgstyles/upstream/demos/06-collage/cues.json +80 -0
  94. package/lib/motion/mgstyles/upstream/demos/06-collage/index.html +889 -0
  95. package/lib/motion/mgstyles/upstream/demos/07-liquid/cues.json +100 -0
  96. package/lib/motion/mgstyles/upstream/demos/07-liquid/index.html +108 -0
  97. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/engine.js +153 -0
  98. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/links.js +64 -0
  99. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/lookdev.js +46 -0
  100. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/scene.js +963 -0
  101. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/shaders.js +647 -0
  102. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/textsdf.js +114 -0
  103. package/lib/motion/mgstyles/upstream/demos/07-liquid/js/type.js +50 -0
  104. package/lib/motion/mgstyles/upstream/demos/08-morph/cues.json +131 -0
  105. package/lib/motion/mgstyles/upstream/demos/08-morph/glyphs.json +1 -0
  106. package/lib/motion/mgstyles/upstream/demos/08-morph/index.html +901 -0
  107. package/lib/motion/mgstyles/upstream/demos/09-bauhaus/cues.json +270 -0
  108. package/lib/motion/mgstyles/upstream/demos/09-bauhaus/film.js +697 -0
  109. package/lib/motion/mgstyles/upstream/demos/09-bauhaus/index.html +12 -0
  110. package/lib/motion/mgstyles/upstream/demos/10-synthwave/cues.json +44 -0
  111. package/lib/motion/mgstyles/upstream/demos/10-synthwave/index.html +1028 -0
  112. package/lib/motion/mgstyles/upstream/demos/12-aurora-glass/cues.json +67 -0
  113. package/lib/motion/mgstyles/upstream/demos/12-aurora-glass/index.html +16 -0
  114. package/lib/motion/mgstyles/upstream/demos/12-aurora-glass/main.js +967 -0
  115. package/lib/motion/mgstyles/upstream/demos/12-aurora-glass/shaders.js +468 -0
  116. package/lib/motion/mgstyles/upstream/demos/18-hanazi/cues.json +117 -0
  117. package/lib/motion/mgstyles/upstream/demos/18-hanazi/index.html +541 -0
  118. package/lib/motion/mgstyles/upstream/demos/19-paperclip/assets/countries-110m.json +1 -0
  119. package/lib/motion/mgstyles/upstream/demos/19-paperclip/assets/stickers/meta.json +34 -0
  120. package/lib/motion/mgstyles/upstream/demos/19-paperclip/cues.json +285 -0
  121. package/lib/motion/mgstyles/upstream/demos/19-paperclip/index.html +599 -0
  122. package/lib/motion/mgstyles/upstream/demos/20-pixel/cues.json +42 -0
  123. package/lib/motion/mgstyles/upstream/demos/20-pixel/film.js +914 -0
  124. package/lib/motion/mgstyles/upstream/demos/20-pixel/index.html +18 -0
  125. package/lib/motion/mgstyles/upstream/demos/22-hud/cues.json +108 -0
  126. package/lib/motion/mgstyles/upstream/demos/22-hud/index.html +125 -0
  127. package/lib/motion/mgstyles/upstream/demos/22-hud/js/holo.js +275 -0
  128. package/lib/motion/mgstyles/upstream/demos/22-hud/js/hud.js +855 -0
  129. package/lib/motion/mgstyles/upstream/demos/22-hud/js/post.js +150 -0
  130. package/lib/motion/mgstyles/upstream/demos/22-hud/js/util.js +65 -0
  131. package/lib/motion/mgstyles/upstream/demos/22-hud/js/v5.js +142 -0
  132. package/lib/motion/mgstyles/upstream/harness/render.mjs +319 -0
  133. package/lib/motion/mgstyles/upstream/manifest.json +269 -0
  134. package/lib/motion/mgstyles/upstream/prompts/01-flat-vector.md +98 -0
  135. package/lib/motion/mgstyles/upstream/prompts/02-line-art.md +95 -0
  136. package/lib/motion/mgstyles/upstream/prompts/03-isometric.md +97 -0
  137. package/lib/motion/mgstyles/upstream/prompts/05-cel-boil.md +95 -0
  138. package/lib/motion/mgstyles/upstream/prompts/06-collage.md +95 -0
  139. package/lib/motion/mgstyles/upstream/prompts/07-liquid.md +98 -0
  140. package/lib/motion/mgstyles/upstream/prompts/08-morph.md +95 -0
  141. package/lib/motion/mgstyles/upstream/prompts/09-bauhaus.md +96 -0
  142. package/lib/motion/mgstyles/upstream/prompts/10-synthwave.md +95 -0
  143. package/lib/motion/mgstyles/upstream/prompts/12-aurora-glass.md +96 -0
  144. package/lib/motion/mgstyles/upstream/prompts/18-hanazi.md +95 -0
  145. package/lib/motion/mgstyles/upstream/prompts/19-paperclip.md +96 -0
  146. package/lib/motion/mgstyles/upstream/prompts/20-pixel.md +96 -0
  147. package/lib/motion/mgstyles/upstream/prompts/22-hud.md +95 -0
  148. package/lib/motion/mgstyles/upstream/rubric.md +51 -0
  149. package/lib/motion/mgstyles/upstream/template.md +36 -0
  150. package/lib/motion/pixelqa.js +198 -0
  151. package/lib/motion/preview.js +97 -0
  152. package/lib/motion/project.js +395 -0
  153. package/lib/motion/qa.js +290 -0
  154. package/lib/motion/reference-media.jsx +10 -0
  155. package/lib/motion/render-settings.js +112 -0
  156. package/lib/motion/render.js +161 -0
  157. package/lib/motion/runtime/package-lock.json +3058 -0
  158. package/lib/motion/runtime/package.json +16 -0
  159. package/lib/motion/scene-kit.js +183 -0
  160. package/lib/motion/sfx.js +232 -0
  161. package/lib/motion/shotcraft/ClipCard.tsx +204 -0
  162. package/lib/motion/shotcraft/catalog.json +2461 -0
  163. package/lib/motion/shotcraft/upstream/SKILL.md +286 -0
  164. package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -0
  165. package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -0
  166. package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -0
  167. package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -0
  168. package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -0
  169. package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -0
  170. package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -0
  171. package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -0
  172. package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -0
  173. package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -0
  174. package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -0
  175. package/lib/motion/shotcraft/upstream/assets/scripts/__pycache__/sfx-source.cpython-313.pyc +0 -0
  176. package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -0
  177. package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -0
  178. package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -0
  179. package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -0
  180. package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -0
  181. package/lib/motion/shotcraft/upstream/demos/README.md +120 -0
  182. package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -0
  183. package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -0
  184. package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -0
  185. package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -0
  186. package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -0
  187. package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -0
  188. package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +389 -0
  189. package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -0
  190. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -0
  191. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -0
  192. package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -0
  193. package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -0
  194. package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -0
  195. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -0
  196. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -0
  197. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -0
  198. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -0
  199. package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -0
  200. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -0
  201. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -0
  202. package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -0
  203. package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -0
  204. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -0
  205. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -0
  206. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -0
  207. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -0
  208. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -0
  209. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -0
  210. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -0
  211. package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -0
  212. package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -0
  213. package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -0
  214. package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -0
  215. package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -0
  216. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -0
  217. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -0
  218. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -0
  219. package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -0
  220. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -0
  221. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -0
  222. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -0
  223. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -0
  224. package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -0
  225. package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -0
  226. package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -0
  227. package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -0
  228. package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -0
  229. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -0
  230. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -0
  231. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -0
  232. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -0
  233. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -0
  234. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -0
  235. package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -0
  236. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -0
  237. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -0
  238. package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -0
  239. package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -0
  240. package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -0
  241. package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -0
  242. package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -0
  243. package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -0
  244. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -0
  245. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -0
  246. package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -0
  247. package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -0
  248. package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -0
  249. package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -0
  250. package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -0
  251. package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -0
  252. package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -0
  253. package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -0
  254. package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -0
  255. package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -0
  256. package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -0
  257. package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -0
  258. package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -0
  259. package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -0
  260. package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -0
  261. package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -0
  262. package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -0
  263. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -0
  264. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -0
  265. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -0
  266. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -0
  267. package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -0
  268. package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -0
  269. package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -0
  270. package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -0
  271. package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -0
  272. package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -0
  273. package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -0
  274. package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -0
  275. package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -0
  276. package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -0
  277. package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -0
  278. package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -0
  279. package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -0
  280. package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -0
  281. package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -0
  282. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -0
  283. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -0
  284. package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -0
  285. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -0
  286. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -0
  287. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -0
  288. package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -0
  289. package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -0
  290. package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -0
  291. package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -0
  292. package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -0
  293. package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -0
  294. package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -0
  295. package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -0
  296. package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -0
  297. package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -0
  298. package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -0
  299. package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -0
  300. package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -0
  301. package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -0
  302. package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -0
  303. package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -0
  304. package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -0
  305. package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -0
  306. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -0
  307. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -0
  308. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -0
  309. package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -0
  310. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -0
  311. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -0
  312. package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -0
  313. package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -0
  314. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -0
  315. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -0
  316. package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -0
  317. package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -0
  318. package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -0
  319. package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -0
  320. package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -0
  321. package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -0
  322. package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -0
  323. package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -0
  324. package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -0
  325. package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -0
  326. package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -0
  327. package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -0
  328. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -0
  329. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -0
  330. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -0
  331. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -0
  332. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -0
  333. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -0
  334. package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -0
  335. package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -0
  336. package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -0
  337. package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -0
  338. package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -0
  339. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -0
  340. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -0
  341. package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -0
  342. package/lib/motion/shotcraft/upstream/manifest.json +2715 -0
  343. package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -0
  344. package/lib/motion/shotcraft/upstream/references/final-review.md +121 -0
  345. package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -0
  346. package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -0
  347. package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -0
  348. package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -0
  349. package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -0
  350. package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -0
  351. package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -0
  352. package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -0
  353. package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -0
  354. package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -0
  355. package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -0
  356. package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -0
  357. package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -0
  358. package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -0
  359. package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -0
  360. package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -0
  361. package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -0
  362. package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -0
  363. package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -0
  364. package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -0
  365. package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -0
  366. package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -0
  367. package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -0
  368. package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -0
  369. package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -0
  370. package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -0
  371. package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -0
  372. package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -0
  373. package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -0
  374. package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -0
  375. package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -0
  376. package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -0
  377. package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -0
  378. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -0
  379. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -0
  380. package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -0
  381. package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -0
  382. package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -0
  383. package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -0
  384. package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -0
  385. package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -0
  386. package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -0
  387. package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -0
  388. package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -0
  389. package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -0
  390. package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -0
  391. package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -0
  392. package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -0
  393. package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -0
  394. package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -0
  395. package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -0
  396. package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -0
  397. package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -0
  398. package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -0
  399. package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -0
  400. package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -0
  401. package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -0
  402. package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -0
  403. package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -0
  404. package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -0
  405. package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -0
  406. package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -0
  407. package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -0
  408. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -0
  409. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -0
  410. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -0
  411. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -0
  412. package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -0
  413. package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -0
  414. package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -0
  415. package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -0
  416. package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -0
  417. package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -0
  418. package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -0
  419. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -0
  420. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -0
  421. package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -0
  422. package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -0
  423. package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -0
  424. package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -0
  425. package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -0
  426. package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -0
  427. package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -0
  428. package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -0
  429. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -0
  430. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -0
  431. package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -0
  432. package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -0
  433. package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -0
  434. package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -0
  435. package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -0
  436. package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -0
  437. package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -0
  438. package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -0
  439. package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -0
  440. package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -0
  441. package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -0
  442. package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -0
  443. package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -0
  444. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -0
  445. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -0
  446. package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -0
  447. package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -0
  448. package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -0
  449. package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -0
  450. package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -0
  451. package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -0
  452. package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -0
  453. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -0
  454. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -0
  455. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -0
  456. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -0
  457. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -0
  458. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -0
  459. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -0
  460. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -0
  461. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -0
  462. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -0
  463. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -0
  464. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -0
  465. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -0
  466. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -0
  467. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -0
  468. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -0
  469. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -0
  470. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -0
  471. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -0
  472. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -0
  473. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -0
  474. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -0
  475. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -0
  476. package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -0
  477. package/lib/motion/shotcraft/upstream/references/workbench.md +157 -0
  478. package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -0
  479. package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -0
  480. package/lib/motion/shotcraft/upstream/template/package.json +20 -0
  481. package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -0
  482. package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -0
  483. package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -0
  484. package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -0
  485. package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -0
  486. package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -0
  487. package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -0
  488. package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -0
  489. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -0
  490. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -0
  491. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -0
  492. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -0
  493. package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -0
  494. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -0
  495. package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +389 -0
  496. package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -0
  497. package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -0
  498. package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -0
  499. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -0
  500. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -0
  501. package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -0
  502. package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -0
  503. package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -0
  504. package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -0
  505. package/lib/motion/spec.js +113 -0
  506. package/lib/motion/style-engine.js +153 -0
  507. package/lib/motion/style-frames.js +271 -0
  508. package/lib/motion/sync.js +214 -0
  509. package/lib/motion/theme.js +121 -0
  510. package/lib/motion/video-runtime.js +192 -0
  511. package/lib/motion/voice.js +417 -0
  512. package/lib/motion-agent-files.js +82 -0
  513. package/lib/motion-agent-protocol.js +66 -0
  514. package/lib/motion-agent-tools.js +196 -0
  515. package/lib/motion-agent.js +171 -0
  516. package/lib/motion-capture.js +93 -0
  517. package/lib/motion-core.js +238 -0
  518. package/lib/motion-film-review.js +71 -0
  519. package/lib/motion-library.js +210 -0
  520. package/lib/motion-planner.js +254 -0
  521. package/lib/motion-project.js +87 -0
  522. package/lib/motion-render-worker.js +153 -0
  523. package/lib/motion-session.js +32 -0
  524. package/lib/motion-source.js +49 -0
  525. package/lib/motion-tasks.js +452 -0
  526. package/lib/motion-vision.js +44 -0
  527. package/lib/mxfile.js +27 -7
  528. package/lib/routing/node-runtime.js +14 -0
  529. package/lib/routing/router.js +211 -0
  530. package/lib/routing/vendor/README.md +96 -0
  531. package/lib/routing/vendor/libavoid-routing.js +753 -0
  532. package/lib/routing/vendor/libavoid.min.js +59 -0
  533. package/lib/shotcard-core.js +39 -0
  534. package/lib/shotcard-reference.js +56 -0
  535. package/lib/style-kernel.js +37 -3
  536. package/lib/task-patches.js +26 -2
  537. package/lib/video-export.js +49 -22
  538. package/package.json +34 -4
@@ -0,0 +1,596 @@
1
+ /* 由 tools/build.mjs 生成 —— 请勿直接编辑;改 src/ 下的源文件。 */
2
+ /**
3
+ * 文生图 provider 层(宿主半边·源文件)。
4
+ *
5
+ * 一次生成请求的完整链路都在这里,客户端只拿最后那张图的 data URI:
6
+ *
7
+ * comfyui:工作流(内置 / 用户粘的 UI 或 API 格式)→ 需要时现场转 API → 注入提示词与参数
8
+ * → POST /prompt → 轮询 /history → GET /view 取 PNG
9
+ * openai :POST <base>/images/generations(b64_json)→ base64 直接回来
10
+ *
11
+ * 三条设计约束:
12
+ * 1. **不碰画布、不写文件**:结果只以 data URI 返回,落节点由客户端走它唯一的 applyLocal 通道 ——
13
+ * 否则宿主写盘 + 客户端写盘会撞 .drawio 的 revision 乐观锁。
14
+ * 2. **不缓存图片**:ComfyUI 自己的 output 目录就是缓存,插件不再存一份;
15
+ * `*.media/` 是画布旁的媒体包,只给需要"重开还能看"的东西用(P2 参考图再议)。
16
+ * 3. **不带密钥落盘**:API Key 由客户端每次随请求 body 传(存哪、存不存由设置页决定),宿主不持久化。
17
+ */
18
+
19
+ import { randomInt, randomUUID } from 'node:crypto'
20
+ import { FRONTEND_ONLY, convertToApi, detectRoles } from './comfyui-workflow.mjs'
21
+ import { DEFAULT_T2I_WORKFLOW, DEFAULT_T2I_WORKFLOW_NAME } from './comfyui-default-workflow.mjs'
22
+
23
+ export { DEFAULT_T2I_WORKFLOW_NAME }
24
+
25
+ /** 没配置时默认连本地 ComfyUI。 */
26
+ export const DEFAULT_COMFY_URL = 'http://127.0.0.1:8188'
27
+ /** 没配置时的默认生图 API(OpenAI 兼容)。 */
28
+ export const DEFAULT_OPENAI_URL = 'https://api.openai.com/v1'
29
+ /** 生成尺寸/步数的默认值:1024×1024、20 步 —— 实测 8 步偏糊、40 步以上对 8G 显存太慢。 */
30
+ export const DEFAULT_IMAGE_SIZE = 1024
31
+ export const DEFAULT_IMAGE_STEPS = 20
32
+ export const DEFAULT_IMAGE_CFG = undefined
33
+ /** 一次生成的等待上限。ComfyUI 首次加载 Qwen-Image 2.1 的量化权重约 40–60 秒,8G 显存 20 步约 1 分钟。 */
34
+ export const IMAGE_GEN_TIMEOUT_MS = 5 * 60 * 1000
35
+ /** 连不上 / 探活超时:设置页点「检测连接」要立刻给结论,不能陪着等模型。 */
36
+ const PROBE_TIMEOUT_MS = 6000
37
+ const SUBMIT_TIMEOUT_MS = 60 * 1000
38
+ const OBJECT_INFO_TIMEOUT_MS = 20000
39
+ /** /object_info 按进程缓存:节点定义基本不变,转换一次工作流要问十几个类型,不缓存会把启动拖慢。 */
40
+ const OBJECT_INFO_TTL_MS = 10 * 60 * 1000
41
+ const POLL_INTERVAL_MS = 1000
42
+ const MAX_IMAGE_BYTES = 32 * 1024 * 1024
43
+ const MIN_IMAGE_SIDE = 64
44
+ const MAX_IMAGE_SIDE = 4096
45
+ const MIN_STEPS = 1
46
+ const MAX_STEPS = 150
47
+ const MAX_PROMPT_CHARS = 8000
48
+ /** 出图统一放 ComfyUI output 下的这个子目录,方便用户自己去找/清理。 */
49
+ const OUTPUT_PREFIX = 'drawai/gen'
50
+
51
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
52
+
53
+ function messageOf(error) {
54
+ if (error instanceof Error) return error.message
55
+ return String(error)
56
+ }
57
+
58
+ /** 内置默认工作流(设置页可「载入默认」)。 */
59
+ export function defaultWorkflow() {
60
+ return DEFAULT_T2I_WORKFLOW
61
+ }
62
+
63
+ function withTimeout(ms) {
64
+ if (typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function') return AbortSignal.timeout(ms)
65
+ const controller = new AbortController()
66
+ const timer = setTimeout(() => controller.abort(), ms)
67
+ if (timer !== null && typeof timer.unref === 'function') timer.unref()
68
+ return controller.signal
69
+ }
70
+
71
+ /** 校验并规范化 http(s) 地址 —— 宿主会替客户端去请求这个地址,协议必须收窄。 */
72
+ export function normalizeHttpUrl(value, fallback, label) {
73
+ const raw = (typeof value === 'string' && value.trim().length > 0 ? value.trim() : fallback).replace(/\/+$/, '')
74
+ let parsed
75
+ try {
76
+ parsed = new URL(raw)
77
+ } catch (error) {
78
+ throw new Error(label + '不是合法的 URL:' + raw)
79
+ }
80
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') throw new Error(label + '只支持 http / https:' + raw)
81
+ return raw
82
+ }
83
+
84
+ function clampInt(value, fallback, min, max) {
85
+ if (value === undefined || value === null || value === '') return fallback
86
+ const number = Number(value)
87
+ if (!Number.isFinite(number)) return fallback
88
+ return Math.min(max, Math.max(min, Math.round(number)))
89
+ }
90
+
91
+ function timeoutOf(body, fallback) {
92
+ const value = clampInt(body.timeoutMs, fallback, 10000, 10 * 60 * 1000)
93
+ return value
94
+ }
95
+
96
+ function randomSeed() {
97
+ return randomInt(0, 2 ** 32 - 1)
98
+ }
99
+
100
+ async function request(url, init, timeoutMs, label) {
101
+ try {
102
+ return await fetch(url, { ...(init || {}), signal: withTimeout(timeoutMs) })
103
+ } catch (error) {
104
+ if (error !== null && typeof error === 'object' && (error.name === 'TimeoutError' || error.name === 'AbortError')) {
105
+ throw new Error(label + '超时(' + Math.round(timeoutMs / 1000) + ' 秒)')
106
+ }
107
+ const cause = error !== null && typeof error === 'object' && error.cause !== undefined && error.cause !== null && error.cause.code !== undefined
108
+ ? '(' + error.cause.code + ')'
109
+ : ''
110
+ throw new Error(label + '失败' + cause + ':' + messageOf(error))
111
+ }
112
+ }
113
+
114
+ async function readPayload(res) {
115
+ const text = await res.text()
116
+ let payload = null
117
+ if (text.length > 0) {
118
+ try {
119
+ payload = JSON.parse(text)
120
+ } catch (error) {
121
+ payload = null
122
+ }
123
+ }
124
+ return { payload, text }
125
+ }
126
+
127
+ function describeHttpError(res, payload, text) {
128
+ const detail = payload !== null && typeof payload === 'object'
129
+ ? (typeof payload.error === 'string' ? payload.error : payload.message !== undefined ? String(payload.message) : '')
130
+ : ''
131
+ return 'HTTP ' + res.status + (detail.length > 0 ? ':' + detail.slice(0, 400) : text.length > 0 ? ':' + text.slice(0, 300) : '')
132
+ }
133
+
134
+ async function requestJson(url, init, timeoutMs, label) {
135
+ const res = await request(url, init, timeoutMs, label)
136
+ const { payload, text } = await readPayload(res)
137
+ if (!res.ok) throw new Error(label + '失败(' + describeHttpError(res, payload, text) + ')')
138
+ if (payload === null && text.length > 0) throw new Error(label + '返回的不是 JSON:' + text.slice(0, 200))
139
+ return payload
140
+ }
141
+
142
+ async function requestBuffer(url, init, timeoutMs, label) {
143
+ const res = await request(url, init, timeoutMs, label)
144
+ if (!res.ok) {
145
+ const { payload, text } = await readPayload(res)
146
+ throw new Error(label + '失败(' + describeHttpError(res, payload, text) + ')')
147
+ }
148
+ return Buffer.from(await res.arrayBuffer())
149
+ }
150
+
151
+ /** /object_info 的按类型缓存(键 = 服务地址 + 类型,避免换了 ComfyUI 端口还吃旧定义)。 */
152
+ const objectInfoCache = new Map()
153
+
154
+ async function fetchObjectInfo(base, type, fetchImpl) {
155
+ const key = base + '\n' + type
156
+ const hit = objectInfoCache.get(key)
157
+ if (hit !== undefined && Date.now() - hit.at < OBJECT_INFO_TTL_MS) return hit.value
158
+ const payload = await fetchImpl
159
+ ? await requestJsonWith(fetchImpl, base + '/object_info/' + encodeURIComponent(type), undefined, OBJECT_INFO_TIMEOUT_MS, '读取 ComfyUI 节点定义(' + type + ')')
160
+ : await requestJson(base + '/object_info/' + encodeURIComponent(type), undefined, OBJECT_INFO_TIMEOUT_MS, '读取 ComfyUI 节点定义(' + type + ')')
161
+ const value = payload !== null && typeof payload === 'object' ? payload[type] : undefined
162
+ if (value !== undefined) objectInfoCache.set(key, { at: Date.now(), value })
163
+ return value
164
+ }
165
+
166
+ /** 测试注入用:给定 fetchImpl 时走它,其余逻辑与 requestJson 一致。 */
167
+ async function requestJsonWith(fetchImpl, url, init, timeoutMs, label) {
168
+ const res = await fetchImpl(url, { ...(init || {}), signal: withTimeout(timeoutMs) })
169
+ const { payload, text } = await readPayload(res)
170
+ if (!res.ok) throw new Error(label + '失败(' + describeHttpError(res, payload, text) + ')')
171
+ if (payload === null && text.length > 0) throw new Error(label + '返回的不是 JSON:' + text.slice(0, 200))
172
+ return payload
173
+ }
174
+
175
+ /** 递归收集工作流里用到的 class_type(含子图内部;子图节点自身不算)。 */
176
+ export function collectWorkflowTypes(workflow) {
177
+ const types = new Set()
178
+ const subgraphs = new Map(((workflow.definitions && workflow.definitions.subgraphs) || []).map((sub) => [sub.id, sub]))
179
+ const walk = (scope, depth) => {
180
+ if (depth > 8) return
181
+ const nodes = Array.isArray(scope.nodes) ? scope.nodes : []
182
+ for (const node of nodes) {
183
+ if (subgraphs.has(node.type)) walk(subgraphs.get(node.type), depth + 1)
184
+ else types.add(node.type)
185
+ }
186
+ }
187
+ walk(workflow, 0)
188
+ return types
189
+ }
190
+
191
+ /** 'ui' | 'api' | 'unknown' —— UI 格式是画布形态,API 格式是 `{ id: { class_type, inputs } }`。 */
192
+ export function workflowFormat(workflow) {
193
+ if (workflow === null || typeof workflow !== 'object') return 'unknown'
194
+ if (Array.isArray(workflow.nodes) && workflow.definitions !== undefined) return 'ui'
195
+ const keys = Object.keys(workflow)
196
+ if (keys.length === 0) return 'unknown'
197
+ const first = workflow[keys[0]]
198
+ if (first !== null && typeof first === 'object' && typeof first.class_type === 'string') return 'api'
199
+ return 'unknown'
200
+ }
201
+
202
+ /** 把内置默认工作流或用户粘贴的工作流统一成「可提交的 API prompt + 参数角色表」。 */
203
+ export async function convertWorkflow(workflow, comfyUrl, fetchImpl) {
204
+ const format = workflowFormat(workflow)
205
+ if (format === 'api') {
206
+ return { prompt: JSON.parse(JSON.stringify(workflow)), roles: detectRoles(workflow), warnings: [], converted: false }
207
+ }
208
+ if (format !== 'ui') {
209
+ throw new Error('工作流格式认不出来:既不是 ComfyUI 的 UI 格式(含 nodes / links),也不是 API 格式(含 class_type)')
210
+ }
211
+ const base = comfyUrl
212
+ const types = [...collectWorkflowTypes(workflow)]
213
+ const objectInfo = {}
214
+ const missing = []
215
+ for (const type of types) {
216
+ // 显示用节点(MarkdownNote / Note / Reroute / PrimitiveNode)在后端没有定义,转换时本就会跳过。
217
+ if (FRONTEND_ONLY.has(type)) continue
218
+ const wanted = [type]
219
+ // 转换时 SaveImageAdvanced 会被换成内置 SaveImage,所以两份定义都要取。
220
+ if (type === 'SaveImageAdvanced') wanted.push('SaveImage')
221
+ for (const wantedType of wanted) {
222
+ if (objectInfo[wantedType] !== undefined) continue
223
+ let info
224
+ try {
225
+ info = await fetchObjectInfo(base, wantedType, fetchImpl)
226
+ } catch (error) {
227
+ if (wantedType === type) missing.push(type + '(' + messageOf(error) + ')')
228
+ continue
229
+ }
230
+ if (info !== undefined) objectInfo[wantedType] = info
231
+ else if (wantedType === type) missing.push(type)
232
+ }
233
+ }
234
+ if (missing.length > 0) throw new Error('这个 ComfyUI 里没有这些节点类型(自定义节点没装?):' + missing.join('、'))
235
+ const { prompt, roles, warnings } = convertToApi(workflow, objectInfo)
236
+ return { prompt, roles, warnings, converted: true }
237
+ }
238
+
239
+ /** 解析用户粘贴的工作流文本(空 = 用内置默认工作流)。 */
240
+ export function parseWorkflow(value) {
241
+ if (value === undefined || value === null) return DEFAULT_T2I_WORKFLOW
242
+ if (typeof value === 'object') return value
243
+ if (typeof value !== 'string') throw new Error('工作流必须是 JSON 对象或字符串')
244
+ const text = value.trim()
245
+ if (text.length === 0) return DEFAULT_T2I_WORKFLOW
246
+ try {
247
+ return JSON.parse(text)
248
+ } catch (error) {
249
+ throw new Error('工作流 JSON 解析失败:' + messageOf(error))
250
+ }
251
+ }
252
+
253
+ /**
254
+ * 把提示词与参数写回 API prompt。
255
+ * 没找到对应角色时:提示词/尺寸这种「必须生效」的报错,可选参数静默跳过并记进 applied。
256
+ */
257
+ export function applyImageParameters(prompt, roles, params) {
258
+ const applied = {}
259
+ const put = (nodeId, key, value) => {
260
+ const node = prompt[nodeId]
261
+ if (node === undefined || node === null) return false
262
+ if (node.inputs === undefined || node.inputs === null) node.inputs = {}
263
+ node.inputs[key] = value
264
+ return true
265
+ }
266
+ if (typeof params.prompt === 'string' && params.prompt.length > 0) {
267
+ if (roles.positive === undefined) throw new Error('这个工作流里没找到提示词输入(需要 TextEncodeQwenImage21.prompt 或 CLIPTextEncode.text)')
268
+ put(roles.positive.node, roles.positive.key, params.prompt)
269
+ applied.prompt = params.prompt
270
+ }
271
+ if (typeof params.negativePrompt === 'string' && params.negativePrompt.length > 0 && roles.negative !== undefined) {
272
+ put(roles.negative.node, roles.negative.key, params.negativePrompt)
273
+ applied.negativePrompt = params.negativePrompt
274
+ }
275
+ if (roles.sampler !== undefined) {
276
+ const keys = roles.sampler.keys
277
+ if (params.seed !== undefined && params.seed !== null) {
278
+ put(roles.sampler.node, keys.seed, params.seed)
279
+ applied.seed = params.seed
280
+ }
281
+ if (params.steps !== undefined && params.steps !== null) {
282
+ put(roles.sampler.node, keys.steps, params.steps)
283
+ applied.steps = params.steps
284
+ }
285
+ if (params.cfg !== undefined && params.cfg !== null) {
286
+ put(roles.sampler.node, keys.cfg, params.cfg)
287
+ applied.cfg = params.cfg
288
+ }
289
+ if (typeof params.sampler === 'string' && params.sampler.length > 0) put(roles.sampler.node, keys.sampler, params.sampler)
290
+ if (typeof params.scheduler === 'string' && params.scheduler.length > 0) put(roles.sampler.node, keys.scheduler, params.scheduler)
291
+ }
292
+ if (roles.latent !== undefined) {
293
+ const keys = roles.latent.keys
294
+ if (params.width !== undefined && params.width !== null) {
295
+ put(roles.latent.node, keys.width, params.width)
296
+ applied.width = params.width
297
+ }
298
+ if (params.height !== undefined && params.height !== null) {
299
+ put(roles.latent.node, keys.height, params.height)
300
+ applied.height = params.height
301
+ }
302
+ }
303
+ if (roles.output !== undefined) put(roles.output.node, roles.output.key, OUTPUT_PREFIX)
304
+ return applied
305
+ }
306
+
307
+ /** 从图片头里读真实尺寸与 MIME(ComfyUI 出图可能被自定义节点改过尺寸,不能信请求参数)。 */
308
+ export function imageInfoOf(buffer) {
309
+ if (buffer.length >= 24 && buffer.readUInt32BE(0) === 0x89504e47) {
310
+ return { mime: 'image/png', width: buffer.readUInt32BE(16), height: buffer.readUInt32BE(20) }
311
+ }
312
+ if (buffer.length >= 4 && buffer[0] === 0xff && buffer[1] === 0xd8) {
313
+ let offset = 2
314
+ while (offset + 9 < buffer.length) {
315
+ if (buffer[offset] !== 0xff) { offset += 1; continue }
316
+ const marker = buffer[offset + 1]
317
+ if (marker === 0xd8 || marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) { offset += 2; continue }
318
+ const length = buffer.readUInt16BE(offset + 2)
319
+ if (marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc) {
320
+ return { mime: 'image/jpeg', height: buffer.readUInt16BE(offset + 5), width: buffer.readUInt16BE(offset + 7) }
321
+ }
322
+ if (length <= 0) break
323
+ offset += 2 + length
324
+ }
325
+ return { mime: 'image/jpeg', width: 0, height: 0 }
326
+ }
327
+ if (buffer.length >= 12 && buffer.toString('ascii', 0, 4) === 'RIFF' && buffer.toString('ascii', 8, 12) === 'WEBP') {
328
+ return { mime: 'image/webp', width: 0, height: 0 }
329
+ }
330
+ if (buffer.length >= 10 && buffer.toString('ascii', 0, 3) === 'GIF') {
331
+ return { mime: 'image/gif', width: buffer.readUInt16LE(6), height: buffer.readUInt16LE(8) }
332
+ }
333
+ return { mime: '', width: 0, height: 0 }
334
+ }
335
+
336
+ /** 图片字节 → data URI(客户端 styleWithImageDataUri 只认 raster data URI)。 */
337
+ export function toImageDataUri(buffer, fallbackWidth, fallbackHeight) {
338
+ const info = imageInfoOf(buffer)
339
+ if (info.mime.length === 0) throw new Error('生成结果不是可识别的图片(PNG / JPEG / WebP / GIF)')
340
+ return {
341
+ dataUri: 'data:' + info.mime + ';base64,' + buffer.toString('base64'),
342
+ mime: info.mime,
343
+ width: info.width > 0 ? info.width : fallbackWidth,
344
+ height: info.height > 0 ? info.height : fallbackHeight,
345
+ }
346
+ }
347
+
348
+ function collectOutputImages(entry) {
349
+ const found = []
350
+ const outputs = (entry && entry.outputs) || {}
351
+ for (const [nodeId, output] of Object.entries(outputs)) {
352
+ const images = (output && output.images) || []
353
+ for (const image of images) {
354
+ if (image !== null && typeof image === 'object' && typeof image.filename === 'string') found.push({ ...image, nodeId })
355
+ }
356
+ }
357
+ return found
358
+ }
359
+
360
+ async function downloadComfyImage(base, image, fetchImpl) {
361
+ const query = new URLSearchParams({ filename: image.filename, subfolder: image.subfolder || '', type: image.type || 'output' })
362
+ const url = base + '/view?' + query.toString()
363
+ const buffer = fetchImpl
364
+ ? Buffer.from(await (async () => {
365
+ const res = await fetchImpl(url, { signal: withTimeout(60000) })
366
+ if (!res.ok) throw new Error('取回 ComfyUI 出图失败(HTTP ' + res.status + ')')
367
+ return res.arrayBuffer()
368
+ })())
369
+ : await requestBuffer(url, undefined, 60000, '取回 ComfyUI 出图')
370
+ if (buffer.length > MAX_IMAGE_BYTES) throw new Error('出图超过 ' + Math.round(MAX_IMAGE_BYTES / 1024 / 1024) + 'MB,无法内嵌到画布')
371
+ return buffer
372
+ }
373
+
374
+ /** 轮询 /history 直到任务完成;顺便用 /queue 判断当前是「排队」「生成中」还是「加载模型」。 */
375
+ async function waitForComfyHistory(base, promptId, timeoutMs, fetchImpl, onProgress) {
376
+ const started = Date.now()
377
+ let lastNote = ''
378
+ const getJson = async (path, label) => (fetchImpl
379
+ ? requestJsonWith(fetchImpl, base + path, undefined, 15000, label)
380
+ : requestJson(base + path, undefined, 15000, label))
381
+ while (Date.now() - started < timeoutMs) {
382
+ const history = await getJson('/history/' + encodeURIComponent(promptId), '查询 ComfyUI 任务状态')
383
+ const entry = history !== null && typeof history === 'object' ? history[promptId] : undefined
384
+ if (entry !== undefined && entry !== null) {
385
+ const status = entry.status || {}
386
+ if (status.status_str === 'error') throw new Error('ComfyUI 执行失败:' + JSON.stringify(status.messages || status).slice(0, 800))
387
+ if (status.completed === true || (entry.outputs !== undefined && Object.keys(entry.outputs).length > 0)) return entry
388
+ }
389
+ let note = '正在生成'
390
+ try {
391
+ const queue = await getJson('/queue', '查询 ComfyUI 队列')
392
+ const running = ((queue && queue.queue_running) || []).map((item) => item[1])
393
+ const pending = ((queue && queue.queue_pending) || []).map((item) => item[1])
394
+ if (pending.includes(promptId)) note = '排队中(前面 ' + pending.indexOf(promptId) + ' 个任务)'
395
+ else if (!running.includes(promptId)) note = '正在加载模型'
396
+ } catch (error) {
397
+ // 队列查询失败不致命:history 才是权威,继续等。
398
+ }
399
+ if (note !== lastNote && typeof onProgress === 'function') onProgress({ state: note, elapsedMs: Date.now() - started })
400
+ lastNote = note
401
+ await sleep(POLL_INTERVAL_MS)
402
+ }
403
+ throw new Error('等 ComfyUI 出图超时(' + Math.round(timeoutMs / 1000) + ' 秒)。可能是模型还在加载、队列在排队,或显卡太慢 —— 稍后重试即可。')
404
+ }
405
+
406
+ async function generateWithComfy(body, options) {
407
+ const fetchImpl = options.fetchImpl
408
+ const base = normalizeHttpUrl(body.comfyUrl, DEFAULT_COMFY_URL, 'ComfyUI 地址')
409
+ const workflow = parseWorkflow(body.workflow)
410
+ const { prompt, roles, warnings, converted } = await convertWorkflow(workflow, base, fetchImpl)
411
+ if (roles.sampler === undefined) throw new Error('这个工作流里没有 KSampler,插件不知道该怎么改采样参数')
412
+ if (roles.positive === undefined) throw new Error('这个工作流里没找到提示词输入(需要 TextEncodeQwenImage21.prompt 或 CLIPTextEncode.text)')
413
+ const width = clampInt(body.width, DEFAULT_IMAGE_SIZE, MIN_IMAGE_SIDE, MAX_IMAGE_SIDE)
414
+ const height = clampInt(body.height, DEFAULT_IMAGE_SIZE, MIN_IMAGE_SIDE, MAX_IMAGE_SIDE)
415
+ const steps = clampInt(body.steps, DEFAULT_IMAGE_STEPS, MIN_STEPS, MAX_STEPS)
416
+ const seed = Number.isInteger(Number(body.seed)) && Number(body.seed) >= 0 ? Number(body.seed) : randomSeed()
417
+ const params = {
418
+ prompt: body.prompt,
419
+ negativePrompt: body.negativePrompt,
420
+ seed, steps, width, height,
421
+ cfg: body.cfg === undefined || body.cfg === null ? DEFAULT_IMAGE_CFG : Number(body.cfg),
422
+ sampler: body.sampler,
423
+ scheduler: body.scheduler,
424
+ }
425
+ const applied = applyImageParameters(prompt, roles, params)
426
+ const started = Date.now()
427
+ const clientId = 'drawai-' + randomUUID()
428
+ const submit = await (fetchImpl
429
+ ? requestJsonWith(fetchImpl, base + '/prompt', {
430
+ method: 'POST',
431
+ headers: { 'content-type': 'application/json' },
432
+ body: JSON.stringify({ prompt, client_id: clientId }),
433
+ }, SUBMIT_TIMEOUT_MS, '提交 ComfyUI 任务')
434
+ : requestJson(base + '/prompt', {
435
+ method: 'POST',
436
+ headers: { 'content-type': 'application/json' },
437
+ body: JSON.stringify({ prompt, client_id: clientId }),
438
+ }, SUBMIT_TIMEOUT_MS, '提交 ComfyUI 任务'))
439
+ const promptId = submit !== null && typeof submit === 'object' ? submit.prompt_id : undefined
440
+ if (typeof promptId !== 'string' || promptId.length === 0) throw new Error('ComfyUI 没有返回 prompt_id:' + JSON.stringify(submit).slice(0, 400))
441
+ const entry = await waitForComfyHistory(base, promptId, timeoutOf(body, IMAGE_GEN_TIMEOUT_MS), fetchImpl, options.onProgress)
442
+ const images = collectOutputImages(entry)
443
+ if (images.length === 0) throw new Error('ComfyUI 跑完了但没有出图:' + JSON.stringify(entry.outputs || {}).slice(0, 600))
444
+ const buffer = await downloadComfyImage(base, images[0], fetchImpl)
445
+ const image = toImageDataUri(buffer, width, height)
446
+ return {
447
+ dataUri: image.dataUri,
448
+ mime: image.mime,
449
+ width: image.width,
450
+ height: image.height,
451
+ provider: 'comfyui',
452
+ seed: applied.seed !== undefined ? applied.seed : seed,
453
+ steps: applied.steps !== undefined ? applied.steps : steps,
454
+ prompt: body.prompt,
455
+ converted,
456
+ warnings,
457
+ fileName: images[0].filename,
458
+ elapsedMs: Date.now() - started,
459
+ }
460
+ }
461
+
462
+ /** OpenAI 兼容的图片接口:base 可给到 /v1、给到 /images/generations,或只给域名。 */
463
+ export function openaiImagesEndpoint(value) {
464
+ let base = normalizeHttpUrl(value, DEFAULT_OPENAI_URL, '生图 API 地址')
465
+ if (/\/images\/generations$/.test(base)) return base
466
+ if (!/\/v\d+$/.test(base)) base += '/v1'
467
+ return base + '/images/generations'
468
+ }
469
+
470
+ function openaiModelsEndpoint(value) {
471
+ let base = normalizeHttpUrl(value, DEFAULT_OPENAI_URL, '生图 API 地址')
472
+ if (/\/images\/generations$/.test(base)) base = base.slice(0, -'/images/generations'.length)
473
+ if (!/\/v\d+$/.test(base)) base += '/v1'
474
+ return base + '/models'
475
+ }
476
+
477
+ function authHeaders(body) {
478
+ const headers = {}
479
+ if (typeof body.apiKey === 'string' && body.apiKey.length > 0) headers.authorization = 'Bearer ' + body.apiKey
480
+ return headers
481
+ }
482
+
483
+ async function generateWithOpenai(body, options) {
484
+ const fetchImpl = options.fetchImpl
485
+ const endpoint = openaiImagesEndpoint(body.apiUrl)
486
+ const model = typeof body.model === 'string' && body.model.trim().length > 0 ? body.model.trim() : 'gpt-image-1'
487
+ const width = clampInt(body.width, DEFAULT_IMAGE_SIZE, MIN_IMAGE_SIDE, MAX_IMAGE_SIDE)
488
+ const height = clampInt(body.height, DEFAULT_IMAGE_SIZE, MIN_IMAGE_SIDE, MAX_IMAGE_SIDE)
489
+ const started = Date.now()
490
+ const requestBody = JSON.stringify({ model, prompt: body.prompt, n: 1, size: width + 'x' + height, response_format: 'b64_json' })
491
+ const payload = fetchImpl
492
+ ? await requestJsonWith(fetchImpl, endpoint, { method: 'POST', headers: { 'content-type': 'application/json', ...authHeaders(body) }, body: requestBody }, timeoutOf(body, IMAGE_GEN_TIMEOUT_MS), '调用生图 API')
493
+ : await requestJson(endpoint, { method: 'POST', headers: { 'content-type': 'application/json', ...authHeaders(body) }, body: requestBody }, timeoutOf(body, IMAGE_GEN_TIMEOUT_MS), '调用生图 API')
494
+ const first = payload !== null && payload !== undefined && Array.isArray(payload.data) ? payload.data[0] : undefined
495
+ if (first === undefined || first === null) throw new Error('生图 API 没有返回图片:' + JSON.stringify(payload).slice(0, 400))
496
+ let buffer
497
+ if (typeof first.b64_json === 'string' && first.b64_json.length > 0) {
498
+ buffer = Buffer.from(first.b64_json, 'base64')
499
+ } else if (typeof first.url === 'string' && first.url.length > 0) {
500
+ buffer = fetchImpl
501
+ ? Buffer.from(await (async () => {
502
+ const res = await fetchImpl(first.url, { signal: withTimeout(120000) })
503
+ if (!res.ok) throw new Error('下载生图结果失败(HTTP ' + res.status + ')')
504
+ return res.arrayBuffer()
505
+ })())
506
+ : await requestBuffer(first.url, undefined, 120000, '下载生图结果')
507
+ } else {
508
+ throw new Error('生图 API 返回里既没有 b64_json 也没有 url:' + JSON.stringify(first).slice(0, 300))
509
+ }
510
+ if (buffer.length > MAX_IMAGE_BYTES) throw new Error('出图超过 ' + Math.round(MAX_IMAGE_BYTES / 1024 / 1024) + 'MB,无法内嵌到画布')
511
+ const image = toImageDataUri(buffer, width, height)
512
+ return {
513
+ dataUri: image.dataUri,
514
+ mime: image.mime,
515
+ width: image.width,
516
+ height: image.height,
517
+ provider: 'openai',
518
+ model,
519
+ seed: null,
520
+ prompt: body.prompt,
521
+ converted: false,
522
+ warnings: [],
523
+ elapsedMs: Date.now() - started,
524
+ }
525
+ }
526
+
527
+ /**
528
+ * 一次文生图请求(客户端 action: 'imagegen-generate' 调它)。
529
+ * 返回 { dataUri, mime, width, height, provider, seed, … };失败抛 Error(调用方统一 sendJson 400)。
530
+ */
531
+ export async function generateImage(body, options = {}) {
532
+ if (body === null || typeof body !== 'object' || Array.isArray(body)) throw new Error('请求体必须是 JSON 对象')
533
+ const prompt = typeof body.prompt === 'string' ? body.prompt.trim() : ''
534
+ if (prompt.length === 0) throw new Error('先在节点里写提示词,再点生成')
535
+ if (prompt.length > MAX_PROMPT_CHARS) throw new Error('提示词太长(上限 ' + MAX_PROMPT_CHARS + ' 字),建议写成一段具体描述')
536
+ const request = { ...body, prompt }
537
+ const provider = body.provider === 'openai' ? 'openai' : 'comfyui'
538
+ if (provider === 'openai') {
539
+ if (typeof request.apiUrl !== 'string' || request.apiUrl.trim().length === 0) request.apiUrl = DEFAULT_OPENAI_URL
540
+ return generateWithOpenai(request, options)
541
+ }
542
+ return generateWithComfy(request, options)
543
+ }
544
+
545
+ async function probeComfy(body, options) {
546
+ const fetchImpl = options.fetchImpl
547
+ const base = normalizeHttpUrl(body.comfyUrl, DEFAULT_COMFY_URL, 'ComfyUI 地址')
548
+ const started = Date.now()
549
+ try {
550
+ const stats = fetchImpl
551
+ ? await requestJsonWith(fetchImpl, base + '/system_stats', undefined, PROBE_TIMEOUT_MS, '连接 ComfyUI')
552
+ : await requestJson(base + '/system_stats', undefined, PROBE_TIMEOUT_MS, '连接 ComfyUI')
553
+ const system = (stats && stats.system) || {}
554
+ const devices = ((stats && stats.devices) || []).map((device) => ({
555
+ name: device.name,
556
+ type: device.type,
557
+ vramTotal: device.vram_total,
558
+ vramFree: device.vram_free,
559
+ }))
560
+ return {
561
+ provider: 'comfyui',
562
+ online: true,
563
+ url: base,
564
+ version: typeof system.comfyui_version === 'string' ? system.comfyui_version : '',
565
+ python: typeof system.python_version === 'string' ? system.python_version : '',
566
+ devices,
567
+ elapsedMs: Date.now() - started,
568
+ }
569
+ } catch (error) {
570
+ return { provider: 'comfyui', online: false, url: base, error: messageOf(error), elapsedMs: Date.now() - started }
571
+ }
572
+ }
573
+
574
+ async function probeOpenai(body, options) {
575
+ const fetchImpl = options.fetchImpl
576
+ const endpoint = openaiModelsEndpoint(body.apiUrl)
577
+ const started = Date.now()
578
+ try {
579
+ const payload = fetchImpl
580
+ ? await requestJsonWith(fetchImpl, endpoint, { headers: authHeaders(body) }, PROBE_TIMEOUT_MS, '连接生图 API')
581
+ : await requestJson(endpoint, { headers: authHeaders(body) }, PROBE_TIMEOUT_MS, '连接生图 API')
582
+ const models = payload !== null && payload !== undefined && Array.isArray(payload.data)
583
+ ? payload.data.map((item) => item && item.id).filter((id) => typeof id === 'string')
584
+ : []
585
+ return { provider: 'openai', online: true, url: endpoint, models, elapsedMs: Date.now() - started }
586
+ } catch (error) {
587
+ return { provider: 'openai', online: false, url: endpoint, error: messageOf(error), elapsedMs: Date.now() - started }
588
+ }
589
+ }
590
+
591
+ /** 设置页「检测连接」(客户端 action: 'imagegen-status' 调它)。失败不抛错,用 online:false 报告。 */
592
+ export async function imagegenStatus(body = {}, options = {}) {
593
+ if (body === null || typeof body !== 'object') return { online: false, error: '请求体必须是 JSON 对象' }
594
+ if (body.provider === 'openai') return probeOpenai(body, options)
595
+ return probeComfy(body, options)
596
+ }