@higgsfield/video-editor-mcp 1.0.7 → 1.1.1-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/THIRD_PARTY_NOTICES.md +24 -24
  2. package/dist/cli.mjs +134 -125
  3. package/dist/index.html +136 -133
  4. package/dist/launcher.mjs +90 -90
  5. package/dist/server.mjs +1553 -1389
  6. package/node_modules/@higgsfield/higgsedit/README.md +181 -1
  7. package/node_modules/@higgsfield/higgsedit/dist/capture-page.js +902 -314
  8. package/node_modules/@higgsfield/higgsedit/dist/chunk-2JYLVSVV.mjs +1594 -0
  9. package/node_modules/@higgsfield/higgsedit/dist/chunk-2WKNH7OL.mjs +16 -0
  10. package/node_modules/@higgsfield/higgsedit/dist/{chunk-OMKZ5BXM.mjs → chunk-5LTTL3Q3.mjs} +1 -1
  11. package/node_modules/@higgsfield/higgsedit/dist/chunk-7PYXSJS7.mjs +717 -0
  12. package/node_modules/@higgsfield/higgsedit/dist/{chunk-MLJAIZGP.mjs → chunk-BH2QF635.mjs} +33 -326
  13. package/node_modules/@higgsfield/higgsedit/dist/{chunk-WZR5PZM7.mjs → chunk-BV5COOQZ.mjs} +250 -161
  14. package/node_modules/@higgsfield/higgsedit/dist/{chunk-HTCYVKFX.mjs → chunk-C3GSB3XZ.mjs} +8 -7
  15. package/node_modules/@higgsfield/higgsedit/dist/{chunk-CYH2EUQV.mjs → chunk-DVN4LUXV.mjs} +13 -4
  16. package/node_modules/@higgsfield/higgsedit/dist/chunk-F4CMIG5G.mjs +36 -0
  17. package/node_modules/@higgsfield/higgsedit/dist/chunk-IEPPEDEU.mjs +33 -0
  18. package/node_modules/@higgsfield/higgsedit/dist/{chunk-UVAZ6I6U.mjs → chunk-KIWGVAPJ.mjs} +16 -12
  19. package/node_modules/@higgsfield/higgsedit/dist/{chunk-L6QDNSL3.mjs → chunk-L5LWBA6A.mjs} +5 -5
  20. package/node_modules/@higgsfield/higgsedit/dist/chunk-LMQR3DHT.mjs +37 -0
  21. package/node_modules/@higgsfield/higgsedit/dist/chunk-LTKMGZ6T.mjs +58 -0
  22. package/node_modules/@higgsfield/higgsedit/dist/{chunk-VI6IV6JP.mjs → chunk-MV2JTTBQ.mjs} +65 -47
  23. package/node_modules/@higgsfield/higgsedit/dist/{chunk-4D6AXU4B.mjs → chunk-NARTAWRN.mjs} +50 -30
  24. package/node_modules/@higgsfield/higgsedit/dist/{chunk-27NBQ5FA.mjs → chunk-NUXTKQNM.mjs} +33 -21
  25. package/node_modules/@higgsfield/higgsedit/dist/chunk-OCIZ36XD.mjs +40 -0
  26. package/node_modules/@higgsfield/higgsedit/dist/{chunk-MK6PL7N4.mjs → chunk-OF6RMSM2.mjs} +19 -17
  27. package/node_modules/@higgsfield/higgsedit/dist/{chunk-6BETMESC.mjs → chunk-P2BGHTRR.mjs} +2 -2
  28. package/node_modules/@higgsfield/higgsedit/dist/{chunk-EKFC4S4M.mjs → chunk-PAHMD6SU.mjs} +5 -0
  29. package/node_modules/@higgsfield/higgsedit/dist/{chunk-QVLAEV3U.mjs → chunk-PFQYUJQL.mjs} +3 -4
  30. package/node_modules/@higgsfield/higgsedit/dist/chunk-QJTILFBS.mjs +335 -0
  31. package/node_modules/@higgsfield/higgsedit/dist/chunk-QQ3GGKDN.mjs +21 -0
  32. package/node_modules/@higgsfield/higgsedit/dist/chunk-TH7TK67K.mjs +23 -0
  33. package/node_modules/@higgsfield/higgsedit/dist/{chunk-SIMO6I3D.mjs → chunk-UDL5AHKO.mjs} +163 -158
  34. package/node_modules/@higgsfield/higgsedit/dist/chunk-UMWOUQN3.mjs +60 -0
  35. package/node_modules/@higgsfield/higgsedit/dist/{chunk-3AIM3THH.mjs → chunk-VLM5EOWJ.mjs} +4 -4
  36. package/node_modules/@higgsfield/higgsedit/dist/chunk-WENFTPXQ.mjs +403 -0
  37. package/node_modules/@higgsfield/higgsedit/dist/chunk-YLVXQIPX.mjs +464 -0
  38. package/node_modules/@higgsfield/higgsedit/dist/editor/.vite/manifest.json +559 -506
  39. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/agent-corner-bottom-q4hZltI-.svg +431 -0
  40. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/agent-corner-top-BJYI-I24.svg +431 -0
  41. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/confirmation-BTnwl3LS.css +1 -0
  42. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/drag-Bt_t4HZO.css +1 -0
  43. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/local-B3OTAV_A.css +1 -0
  44. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/menubar-2Y1Y2XJt.css +1 -0
  45. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/model-DdE4hCgf.css +1 -0
  46. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/{IconText1-CzbCrP7v.css → notifications-B08L1jSe.css} +1 -1
  47. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/{panel-g852pZf_.css → panel-BRN_AbBM.css} +1 -1
  48. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/panel-CYELNqrv.css +1 -0
  49. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/panel-DYLpT6oA.css +1 -0
  50. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/panel-v84HaGTZ.css +1 -0
  51. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconChainLink1-Bxb1Or0F.js +1 -0
  52. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/{IconCheckmark2Medium-daaES9uF.js → IconCheckmark2Medium-hegaz9mQ.js} +1 -1
  53. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/{IconChevronDownSmall-BhTBJk26.js → IconChevronDownSmall-DaruzJwU.js} +1 -1
  54. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconClosedCaptioning-BPqcqKsD.js +1 -0
  55. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/{IconCrossMedium-acfnCXOM.js → IconCrossMedium-BsPFJzc6.js} +1 -1
  56. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconOpenaiFilled-D1fzthmi.js +1 -0
  57. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/{IconPause-pTeVSvUe.js → IconPause-ClNg8pao.js} +1 -1
  58. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/{IconPlayFilled-CwdgIuDG.js → IconPlayFilled-CHb-7GSx.js} +1 -1
  59. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconSparklesSoftFilled-o7o33KRn.js +1 -0
  60. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/ai-composer-B9h-eaki.js +567 -0
  61. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/auto-layout-BO20Tg4B.js +1 -0
  62. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/{button-CjG6GcgF.js → button-Cg0U0zpV.js} +1 -1
  63. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/canvas-Bw4CVzfw.js +1 -0
  64. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/capabilities-BCd4-zPF.js +1 -0
  65. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/commands-QeSqAbCt.js +1 -0
  66. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/components-tXMtIZNL.js +51 -0
  67. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/confirmation-CO2PHR_z.js +1 -0
  68. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/dom-6aoQn29n.js +1 -0
  69. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/drag-Dw8b_vO2.js +1 -0
  70. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/{editing-CjWbiCxv.js → editing-Cy-SaOyB.js} +1 -1
  71. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/edits-CqLBqir0.js +1 -0
  72. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/export-dialog-BjBskOe3.js +2 -0
  73. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/factories-Bw_iQrUL.js +1 -0
  74. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/id3-CSR0NCRI.js +2 -0
  75. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/import-DP49i4ke.js +1 -0
  76. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/import-error-CMz9sLPe.js +1 -0
  77. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/ingest-DsmIc415.js +1 -0
  78. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/jsx-runtime-B5yqYJvp.js +1 -0
  79. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/{media-Bwjxu-0U.js → media-DQw6vU_T.js} +1 -1
  80. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/menubar-D31srALX.js +1 -0
  81. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/meters-D0nZVEJs.js +1 -0
  82. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/mode-DEG6doKF.js +1 -0
  83. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/model-Duf9fszJ.js +2 -0
  84. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/model-DyAkLA69.js +1 -0
  85. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/notifications-DqWZNIrK.js +9 -0
  86. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/palette-HT83gWgL.js +1 -0
  87. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-B5Mvm6dg.js +7 -0
  88. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-BC90wyvd.js +1 -0
  89. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-Bw_ZJ2JI.js +3 -0
  90. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-DNS060Nt.js +3 -0
  91. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-DSgxIrEq.js +2 -0
  92. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-DgBttE5O.js +1 -0
  93. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-assets-_T2bHsHW.js +771 -0
  94. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-inspector-DfHvAt5X.js +2 -0
  95. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-nBZvHlkA.js +1 -0
  96. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-timeline-DsCpJVSt.js +327 -0
  97. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-viewport-CEhZwZ67.js +280 -0
  98. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/projects-2_tW9Do7.js +1 -0
  99. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/react-dom-1uB7Vbbb.js +1 -0
  100. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/schemas-CddYAOcj.js +64 -0
  101. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/session-BpFeKAI2.js +1 -0
  102. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/src-BLG3tYBa.js +2 -0
  103. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/styles-e2n2A_JN.js +284 -0
  104. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/supercomputer-CuV0zYKd.js +24 -0
  105. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/tabs-XeAgs9cs.js +1 -0
  106. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/toggle-DbNEaSIl.js +1 -0
  107. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/transport-C8Ll3qFl.js +69 -0
  108. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/transport-bar-Dv1LPFbu.js +1 -0
  109. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/useOpenInteractionType-HWSfSsp2.js +1 -0
  110. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/useRenderElement-D4SOg3N_.js +1 -0
  111. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/value-EB7YmAdS.js +1 -0
  112. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/writeback-support-fj5rA9k3.js +1 -0
  113. package/node_modules/@higgsfield/higgsedit/dist/editor/editor-B-WAkLt7.js +372 -0
  114. package/node_modules/@higgsfield/higgsedit/dist/higgsedit.mjs +39 -24
  115. package/node_modules/@higgsfield/higgsedit/dist/jsx/hooks.d.ts +26 -0
  116. package/node_modules/@higgsfield/higgsedit/dist/jsx/index.d.ts +17 -0
  117. package/node_modules/@higgsfield/higgsedit/dist/jsx/inspect.d.ts +42 -0
  118. package/node_modules/@higgsfield/higgsedit/dist/jsx/jsx-runtime.d.ts +28 -0
  119. package/node_modules/@higgsfield/higgsedit/dist/jsx/svg.d.ts +9 -0
  120. package/node_modules/@higgsfield/higgsedit/dist/jsx/time.d.ts +6 -0
  121. package/node_modules/@higgsfield/higgsedit/dist/jsx/types.d.ts +420 -0
  122. package/node_modules/@higgsfield/higgsedit/package.json +28 -20
  123. package/package.json +4 -3
  124. package/plugin/.codex-plugin/plugin.json +1 -1
  125. package/plugin/plugin.json +1 -1
  126. package/plugin/skills/video-editing/references/caption-titling.md +1 -1
  127. package/plugin/skills/video-editing/references/local-setup.md +3 -3
  128. package/node_modules/@higgsfield/higgsedit/dist/chunk-C6SASQHE.mjs +0 -424
  129. package/node_modules/@higgsfield/higgsedit/dist/chunk-FZ5U36SQ.mjs +0 -83
  130. package/node_modules/@higgsfield/higgsedit/dist/chunk-QLPCYN6K.mjs +0 -292
  131. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/edit-drag-D2EV5ddd.css +0 -1
  132. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/editor-CuRHT75g.css +0 -1
  133. package/node_modules/@higgsfield/higgsedit/dist/editor/assets/panel-DnuQD7ja.css +0 -1
  134. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/FieldControl-B0fenhBJ.js +0 -2
  135. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconChainLink1-Cwv1X7hi.js +0 -1
  136. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconEyeOpen-BqTT9_VV.js +0 -1
  137. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconEyeSlash-Whv58c1m.js +0 -1
  138. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconPencil-Dr17k_7e.js +0 -1
  139. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconPlay-BroH3ziH.js +0 -1
  140. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconPlusSmall-43T9aE3d.js +0 -1
  141. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconText1-BaP_p9DW.js +0 -1
  142. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/IconTrashCan-DX2w2AIC.js +0 -1
  143. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/ai-composer-C-l0eIdP.js +0 -560
  144. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/captions-Cd-bDG3G.js +0 -1
  145. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/clip-highlight-DpAvcA4x.js +0 -1
  146. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/components-e3ZbUVns.js +0 -1
  147. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/disposables-CwUPjcuA.js +0 -1
  148. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/drag-HLBkto5o.js +0 -1
  149. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/dropdown-BJ04G_X3.js +0 -1
  150. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/edit-drag-Bg6LggKC.js +0 -1
  151. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/edits-a2IixhrN.js +0 -1
  152. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/export-dialog-4I4gqI5V.js +0 -2
  153. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/face-tracker-DzVfjVOO.js +0 -1
  154. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/fit-imported-media-CaCB0x0b.js +0 -1
  155. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/generation-queue-DuL2F4-_.js +0 -1
  156. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/import-error-CMARA0Hy.js +0 -1
  157. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/jsx-runtime-B-hcVAMW.js +0 -1
  158. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/menubar-Bs26OdwP.js +0 -1
  159. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/meters-YEr9OQjq.js +0 -1
  160. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/paints-DS2Msf91.js +0 -67
  161. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/palette-CcS9IcAC.js +0 -1
  162. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-7M3uQokX.js +0 -1
  163. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-BBK1NyG-.js +0 -1
  164. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-CHZTs7By.js +0 -4
  165. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-DaSOa3MP.js +0 -2
  166. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-DlK3RYVo.js +0 -1
  167. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-Dst5OKWu.js +0 -2
  168. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-H_ZoDiKK.js +0 -2
  169. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-Rn9Z7Eek.js +0 -3
  170. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-assets-FAghGFG3.js +0 -678
  171. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-inspector-DEqULBNF.js +0 -260
  172. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-timeline-0GYNz1uc.js +0 -333
  173. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/panel-viewport-DOWjJi5-.js +0 -317
  174. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/projects-BBJc7h5_.js +0 -2
  175. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/session-B9sZaFKC.js +0 -1
  176. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/supercomputer-CX-LCL6Y.js +0 -24
  177. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/tabs-CvKQ-eas.js +0 -1
  178. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/toggle-CrzrwiDZ.js +0 -1
  179. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/transport-BgRfk-Qq.js +0 -69
  180. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/transport-bar-C9nqAfE2.js +0 -1
  181. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/typography-C5-w9LOu-kD3uLKkf.js +0 -1
  182. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/useOpenInteractionType-DbrQ6Ehu.js +0 -1
  183. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/useRenderElement-bbxXdYq0.js +0 -1
  184. package/node_modules/@higgsfield/higgsedit/dist/editor/chunks/writeback-support-BZfNpkmB.js +0 -1
  185. package/node_modules/@higgsfield/higgsedit/dist/editor/editor-Csn2_T_e.js +0 -293
  186. package/node_modules/@higgsfield/higgsedit/dist/export-settings.mjs +0 -75
  187. package/node_modules/@higgsfield/higgsedit/dist/history.mjs +0 -295
  188. package/node_modules/@higgsfield/higgsedit/dist/media-upload.mjs +0 -381
  189. package/node_modules/@higgsfield/higgsedit/dist/proxy.mjs +0 -170
@@ -0,0 +1,464 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __higgseditRequire } from "node:module";
3
+ import { fileURLToPath as __higgseditPath } from "node:url";
4
+ const require = __higgseditRequire(import.meta.url);
5
+ const __filename = __higgseditPath(import.meta.url);
6
+ const __dirname = __filename.slice(0, __filename.lastIndexOf("/"));
7
+ import {
8
+ SourceProject,
9
+ applyEdit,
10
+ isLiteral,
11
+ literalValue,
12
+ require_ts_morph
13
+ } from "./chunk-MV2JTTBQ.mjs";
14
+ import {
15
+ findTool,
16
+ requireTool
17
+ } from "./chunk-PAHMD6SU.mjs";
18
+ import {
19
+ flag
20
+ } from "./chunk-MCVD2ZQV.mjs";
21
+ import {
22
+ __toESM
23
+ } from "./chunk-75WO2NOF.mjs";
24
+
25
+ // src/presets.ts
26
+ var import_ts_morph = __toESM(require_ts_morph(), 1);
27
+ import { execFile } from "node:child_process";
28
+ import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
29
+ import { homedir, tmpdir } from "node:os";
30
+ import { basename, dirname, extname, join, posix, resolve } from "node:path";
31
+ import { promisify } from "node:util";
32
+ var run = promisify(execFile);
33
+ var PRESET_CATEGORIES = ["hook", "proof", "turn", "cta"];
34
+ var AUTHORED = { width: 1920, height: 1080 };
35
+ var POSTER_WIDTH = 320;
36
+ var POSTER_LIMIT = 20 * 1024;
37
+ var PREVIEW_WIDTH = 480;
38
+ var PREVIEW_LIMIT = 600 * 1024;
39
+ var presetsDir = (flagged) => resolve(flagged ?? process.env.HIGGSEDIT_PRESETS_DIR ?? join(process.env.HIGGSEDIT_HOME ?? join(homedir(), ".higgsedit-next"), "presets"));
40
+ function readManifest(dir = presetsDir()) {
41
+ const file = join(dir, "manifest.json");
42
+ return existsSync(file) ? JSON.parse(readFileSync(file, "utf8")).presets : void 0;
43
+ }
44
+ function walk(root, sub) {
45
+ if (!existsSync(join(root, sub))) return [];
46
+ return readdirSync(join(root, sub), { withFileTypes: true }).filter((e) => !e.name.startsWith(".")).flatMap((e) => e.isDirectory() ? walk(root, posix.join(sub, e.name)) : [posix.join(sub, e.name)]).toSorted();
47
+ }
48
+ var parser = new import_ts_morph.Project({ useInMemoryFileSystem: true, skipLoadingLibFiles: true, compilerOptions: { jsx: 1 } });
49
+ function readComponent(text) {
50
+ const sf = parser.createSourceFile("/component.tsx", text, { overwrite: true });
51
+ const init = sf.getVariableDeclaration("info")?.getInitializer();
52
+ if (!init || !isLiteral(init)) throw new Error("`info` is not a plain object literal");
53
+ const info = literalValue(init);
54
+ const { category, name, description, duration } = info;
55
+ if (!PRESET_CATEGORIES.includes(category)) throw new Error(`info.category ${JSON.stringify(category)} is not one of ${PRESET_CATEGORIES.join(", ")}`);
56
+ if (typeof name !== "string" || typeof description !== "string" || typeof duration !== "number") throw new Error("info needs a string name and description and a number duration");
57
+ const components = sf.getFunctions().flatMap((f) => {
58
+ const props2 = f.getParameters()[0]?.getTypeNode()?.getText();
59
+ return f.isExported() && f.getName() && props2?.endsWith("Props") ? [{ name: f.getName(), props: props2 }] : [];
60
+ });
61
+ if (components.length !== 1) throw new Error(`expected one exported component taking \u2026Props, found ${components.length}`);
62
+ const { name: component, props } = components[0];
63
+ const type = sf.getTypeAlias(props)?.getTypeNode() ?? sf.getInterface(props);
64
+ const names = import_ts_morph.Node.isTypeLiteral(type) || import_ts_morph.Node.isInterfaceDeclaration(type) ? type.getProperties().map((m) => m.getName()) : [];
65
+ const adapts = names.includes("width") && names.includes("height");
66
+ return { category, name, description, duration, component, adapts, propsType: props, props: names };
67
+ }
68
+ var VIDEO_EXT = /\.(mp4|mov|webm|m4v)$/i;
69
+ var IMAGE_EXT = /\.(png|jpe?g|webp)$/i;
70
+ var ASPECT = /^\d+(\.\d+)?:\d+(\.\d+)?$/;
71
+ var placeholderPath = (kind, aspect) => `_core/media/placeholder/${kind}-${aspect.replace(":", "x")}.${kind === "image" ? "jpg" : "mp4"}`;
72
+ function fail(what) {
73
+ throw new Error(`slots.json: ${what}`);
74
+ }
75
+ var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
76
+ function parseSlots(raw, ids) {
77
+ if (!isObject(raw)) fail("expected an object keyed by preset id");
78
+ for (const [id, entry] of Object.entries(raw)) {
79
+ if (!ids.includes(id)) fail(`no preset ${id} in the pack`);
80
+ if (!isObject(entry) || !Array.isArray(entry.slots) || !isObject(entry.content) || !Array.isArray(entry.texture)) fail(`${id} needs slots [], content {} and texture []`);
81
+ const { slots, content, texture } = entry;
82
+ slots.forEach((s, i) => {
83
+ const at = `${id}.slots[${i}]`;
84
+ if (!isObject(s) || typeof s.prop !== "string" || typeof s.label !== "string") fail(`${at} needs a string prop and label`);
85
+ if (s.kind !== "image" && s.kind !== "video") fail(`${at}.kind must be "image" or "video"`);
86
+ if (typeof s.aspect !== "string" || !ASPECT.test(s.aspect)) fail(`${at}.aspect must look like "16:9"`);
87
+ if (s.count !== void 0 && !(Number.isInteger(s.count) && s.count > 0)) fail(`${at}.count must be a positive integer`);
88
+ });
89
+ for (const [file, aspect] of Object.entries(content)) {
90
+ if (typeof aspect !== "string" || !ASPECT.test(aspect)) fail(`${id}.content[${file}] must be an aspect like "16:9"`);
91
+ if (!IMAGE_EXT.test(file) && !VIDEO_EXT.test(file)) fail(`${id}.content: ${file} is not an image or a video`);
92
+ }
93
+ if (texture.some((f) => typeof f !== "string")) fail(`${id}.texture must list paths`);
94
+ }
95
+ return raw;
96
+ }
97
+ function rewriteMedia(text, path, plan) {
98
+ const sf = parser.createSourceFile(`/rewrite${extname(path)}`, text, { overwrite: true });
99
+ const edits = [];
100
+ const referenced = [];
101
+ for (const node of sf.getDescendants()) {
102
+ if (import_ts_morph.Node.isStringLiteral(node) || import_ts_morph.Node.isNoSubstitutionTemplateLiteral(node)) {
103
+ const value = node.getLiteralText();
104
+ if (!plan.known.includes(value)) continue;
105
+ referenced.push(value);
106
+ const to = plan.rewrite.get(value);
107
+ const quote = node.getText()[0];
108
+ if (to) edits.push({ start: node.getStart(), end: node.getEnd(), text: `${quote}${to}${quote}` });
109
+ } else if (import_ts_morph.Node.isTemplateExpression(node)) {
110
+ const parts = [node.getHead().getLiteralText(), ...node.getTemplateSpans().map((s) => s.getLiteral().getLiteralText())];
111
+ if (!/\.\w+$/.test(parts.at(-1))) continue;
112
+ const pattern = new RegExp(`^${parts.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*")}$`);
113
+ const matches = plan.known.filter((k) => pattern.test(k));
114
+ if (!matches.length) continue;
115
+ referenced.push(...matches);
116
+ const targets = matches.map((m) => plan.rewrite.get(m) ?? m);
117
+ if (targets.every((t, i) => t === matches[i])) continue;
118
+ const literal = node.getText();
119
+ if (matches.every((m) => plan.content.has(m)) && new Set(targets).size === 1) {
120
+ edits.push({ start: node.getStart(), end: node.getEnd(), text: `"${targets[0]}"` });
121
+ } else if (matches.every((m, i) => targets[i] === m.slice(0, -extname(m).length) + extname(targets[i])) && new Set(matches.map((m) => extname(m))).size === 1 && new Set(targets.map((t) => extname(t))).size === 1 && literal.endsWith(`${extname(matches[0])}\``)) {
122
+ edits.push({ start: node.getEnd() - extname(matches[0]).length - 1, end: node.getEnd() - 1, text: extname(targets[0]) });
123
+ } else {
124
+ throw new Error(`${path}: cannot rewrite ${literal}, it names ${matches.join(", ")}`);
125
+ }
126
+ }
127
+ }
128
+ let out = text;
129
+ for (const e of edits.toSorted((a, b) => b.start - a.start)) out = out.slice(0, e.start) + e.text + out.slice(e.end);
130
+ return { text: out, referenced };
131
+ }
132
+ var PLACEHOLDER_EDGE = 640;
133
+ var PLACEHOLDER_SECONDS = 60;
134
+ async function writePlaceholders(files, wanted) {
135
+ const { frame } = await import("./chunk-F4CMIG5G.mjs");
136
+ const ffmpeg = requireTool("ffmpeg");
137
+ const work = mkdtempSync(join(tmpdir(), "higgsedit-placeholder-"));
138
+ try {
139
+ for (const { kind, aspect } of wanted) {
140
+ const [w, h] = aspect.split(":").map(Number);
141
+ const [width, height] = w >= h ? [PLACEHOLDER_EDGE, Math.round(PLACEHOLDER_EDGE * h / w / 2) * 2] : [Math.round(PLACEHOLDER_EDGE * w / h / 2) * 2, PLACEHOLDER_EDGE];
142
+ const size = Math.round(Math.min(width, height) / 7);
143
+ writeFileSync(
144
+ join(work, "index.tsx"),
145
+ `export default () => (
146
+ <stage id="st">
147
+ <scene id="main" width={${width}} height={${height}} fps={30} fill="#808080">
148
+ <text id="label" y={${Math.round(height / 2 - size)}} width={${width}} align="center" fontSize={${size}} fontWeight={600} fill="#f2f2f2" end={1}>Replace me</text>
149
+ <text id="aspect" y={${Math.round(height / 2 + size * 0.25)}} width={${width}} align="center" fontSize={${Math.round(size * 0.55)}} fill="#d9d9d9" end={1}>${aspect} ${kind}</text>
150
+ </scene>
151
+ </stage>
152
+ );
153
+ `
154
+ );
155
+ const png = join(work, "frame.png");
156
+ await frame(work, "0", png);
157
+ const out = join(files, placeholderPath(kind, aspect));
158
+ mkdirSync(dirname(out), { recursive: true });
159
+ const encode = kind === "image" ? ["-i", png, "-q:v", "5", out] : ["-loop", "1", "-framerate", "1", "-i", png, "-t", String(PLACEHOLDER_SECONDS), "-c:v", "libx264", "-tune", "stillimage", "-crf", "30", "-pix_fmt", "yuv420p", "-movflags", "+faststart", out];
160
+ await run(ffmpeg, ["-v", "error", "-y", ...encode]);
161
+ }
162
+ } finally {
163
+ rmSync(work, { recursive: true, force: true });
164
+ }
165
+ }
166
+ var MAX_EDGE = 1920;
167
+ async function writeTexture(src, files, to) {
168
+ const ffmpeg = requireTool("ffmpeg");
169
+ const stem = to.slice(0, -extname(to).length);
170
+ const fit = `scale='if(gte(iw,ih),min(${MAX_EDGE},iw),-2)':'if(gte(iw,ih),-2,min(${MAX_EDGE},ih))'`;
171
+ let out = to;
172
+ let args;
173
+ if (VIDEO_EXT.test(to)) {
174
+ out = `${stem}.mp4`;
175
+ args = ["-i", src, "-vf", `scale='min(1920,iw)':'min(1080,ih)':force_original_aspect_ratio=decrease,scale=trunc(iw/2)*2:trunc(ih/2)*2`, "-an", "-c:v", "libx264", "-crf", "28", "-pix_fmt", "yuv420p", "-movflags", "+faststart"];
176
+ } else if (IMAGE_EXT.test(to)) {
177
+ const { stdout } = await run(ffmpeg, ["-v", "error", "-i", src, "-vf", "format=rgba,alphaextract", "-f", "rawvideo", "-pix_fmt", "gray", "-"], { encoding: "buffer", maxBuffer: 1 << 28 });
178
+ const alpha = stdout.some((v) => v < 255);
179
+ const soft = stdout.reduce((n, v) => n + (v > 2 && v < 250 ? 1 : 0), 0) / stdout.length;
180
+ const palette = `${fit},split[a][b];[a]palettegen=reserve_transparent=1[p];[b][p]paletteuse=alpha_threshold=128`;
181
+ out = alpha ? `${stem}.png` : /\.jpe?g$/i.test(to) ? to : `${stem}.jpg`;
182
+ args = ["-i", src, ...!alpha ? ["-vf", fit, "-q:v", "5"] : soft < 0.1 ? ["-filter_complex", palette] : ["-vf", fit, "-compression_level", "9"], "-frames:v", "1"];
183
+ } else {
184
+ mkdirSync(dirname(join(files, to)), { recursive: true });
185
+ copyFileSync(src, join(files, to));
186
+ return to;
187
+ }
188
+ mkdirSync(dirname(join(files, out)), { recursive: true });
189
+ await run(ffmpeg, ["-v", "error", "-y", ...args, join(files, out)]);
190
+ if (out === to && statSync(join(files, out)).size >= statSync(src).size) copyFileSync(src, join(files, out));
191
+ return out;
192
+ }
193
+ async function smallest(out, limit, attempts) {
194
+ let size = 0;
195
+ for (const attempt of attempts) {
196
+ await attempt();
197
+ size = statSync(out).size;
198
+ if (size <= limit) break;
199
+ }
200
+ return size;
201
+ }
202
+ async function encodePoster(src, outDir, cwebp) {
203
+ const out = join(outDir, cwebp ? "poster.webp" : "poster.jpg");
204
+ const attempts = cwebp ? [80, 60, 40, 20].map((q) => () => run(cwebp, ["-quiet", "-q", String(q), "-resize", String(POSTER_WIDTH), "0", src, "-o", out])) : [3, 6, 10, 16].map((q) => () => run(requireTool("ffmpeg"), ["-v", "error", "-y", "-i", src, "-vf", `scale=${POSTER_WIDTH}:-2`, "-frames:v", "1", "-q:v", String(q), out]));
205
+ const size = await smallest(out, POSTER_LIMIT, attempts);
206
+ if (size > POSTER_LIMIT) throw new Error(`poster is ${size} bytes at the lowest quality, over ${POSTER_LIMIT}`);
207
+ return basename(out);
208
+ }
209
+ async function encodePreview(src, out) {
210
+ const ffmpeg = requireTool("ffmpeg");
211
+ const encode = (crf) => () => run(ffmpeg, ["-v", "error", "-y", "-i", src, "-vf", `scale=${PREVIEW_WIDTH}:-2`, "-an", "-c:v", "libx264", "-crf", String(crf), "-pix_fmt", "yuv420p", "-movflags", "+faststart", out]);
212
+ return smallest(out, PREVIEW_LIMIT, [28, 32, 36].map(encode));
213
+ }
214
+ async function planMedia(pack, folders, slots, files, origin) {
215
+ const known = [...new Set(folders.flatMap((id) => [...walk(join(pack, id), "media"), ...walk(join(pack, id), "_core/media")]))].toSorted();
216
+ const content = /* @__PURE__ */ new Map();
217
+ const wanted = /* @__PURE__ */ new Map();
218
+ const want = (kind, aspect) => {
219
+ const path = placeholderPath(kind, aspect);
220
+ wanted.set(path, { kind, aspect });
221
+ return path;
222
+ };
223
+ const textures = /* @__PURE__ */ new Map();
224
+ for (const [id, entry] of Object.entries(slots)) {
225
+ for (const [file, aspect] of Object.entries(entry.content)) {
226
+ const placeholder = want(VIDEO_EXT.test(file) ? "video" : "image", aspect);
227
+ if ((content.get(file) ?? placeholder) !== placeholder) throw new Error(`slots.json: ${file} has more than one aspect`);
228
+ content.set(file, placeholder);
229
+ }
230
+ for (const slot of entry.slots) want(slot.kind, slot.aspect);
231
+ for (const file of entry.texture) if (!textures.has(file) && existsSync(join(pack, id, file))) textures.set(file, id);
232
+ }
233
+ const both = [...textures.keys()].find((f) => content.has(f));
234
+ if (both) throw new Error(`slots.json: ${both} is both content and texture`);
235
+ await writePlaceholders(files, [...wanted.values()]);
236
+ const rewrite = new Map(content);
237
+ for (const [file, id] of textures) {
238
+ const to = await writeTexture(join(pack, id, file), files, file);
239
+ origin.set(to, readFileSync(join(pack, id, file)));
240
+ if (to !== file) rewrite.set(file, to);
241
+ }
242
+ return { rewrite, content, known, textures: new Set(textures.keys()) };
243
+ }
244
+ function importClosure(entry, paths, read) {
245
+ const seen = /* @__PURE__ */ new Set();
246
+ const visit = (path) => {
247
+ seen.add(path);
248
+ const sf = parser.createSourceFile(`/closure${extname(path)}`, read(path), { overwrite: true });
249
+ const specs = [...sf.getImportDeclarations(), ...sf.getExportDeclarations()].map((d) => d.getModuleSpecifierValue() ?? "").filter((m) => m.startsWith("."));
250
+ for (const spec of specs) {
251
+ const base = posix.join(posix.dirname(path), spec);
252
+ const hit = [base, `${base}.ts`, `${base}.tsx`, `${base}/index.ts`, `${base}/index.tsx`].find((c) => paths.includes(c));
253
+ if (hit && !seen.has(hit)) visit(hit);
254
+ }
255
+ };
256
+ visit(entry);
257
+ return seen;
258
+ }
259
+ var isMedia = (path) => /^(_core\/)?media\//.test(path);
260
+ async function installPresets(pack, dir = presetsDir(), options = { cwebp: findTool("cwebp") }) {
261
+ const folders = readdirSync(pack, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).toSorted();
262
+ const slotsFile = options.slots ?? (existsSync(join(pack, "slots.json")) ? join(pack, "slots.json") : void 0);
263
+ const slots = slotsFile === void 0 ? void 0 : parseSlots(JSON.parse(readFileSync(slotsFile, "utf8")), folders);
264
+ const staging = `${dir}.installing-${process.pid}`;
265
+ rmSync(staging, { recursive: true, force: true });
266
+ mkdirSync(join(staging, "files"), { recursive: true });
267
+ const result = { dir, installed: [], failed: [] };
268
+ const origin = /* @__PURE__ */ new Map();
269
+ const plan = slots && await planMedia(pack, folders, slots, join(staging, "files"), origin).catch((error) => {
270
+ rmSync(staging, { recursive: true, force: true });
271
+ throw error;
272
+ });
273
+ for (const id of folders) {
274
+ const root = join(pack, id);
275
+ try {
276
+ const sources = walk(root, "").filter((f) => f.endsWith(".tsx") && f !== "index.tsx" && !/^(_core|media|node_modules)\//.test(f));
277
+ const found = sources.filter((f) => /^export const info\b/m.test(readFileSync(join(root, f), "utf8")));
278
+ if (found.length !== 1) throw new Error(found.length ? `more than one file exports info: ${found.join(", ")}` : "no .tsx exports info");
279
+ const source = found[0];
280
+ const { props, propsType, ...meta } = readComponent(readFileSync(join(root, source), "utf8"));
281
+ const stem = basename(source, ".tsx");
282
+ const beside = (names) => names.map((n) => join(root, dirname(source), n)).find((f) => existsSync(f));
283
+ const poster = beside(["poster.jpg", `${stem}.jpg`]);
284
+ if (!poster) throw new Error(`no poster.jpg or ${stem}.jpg beside ${basename(source)}`);
285
+ const preview = beside(["preview.mp4", `${stem}.mp4`]);
286
+ if (!preview) throw new Error(`no preview.mp4 or ${stem}.mp4 beside ${basename(source)}`);
287
+ const entry = `presets/${id}/${basename(source)}`;
288
+ let copies = [{ to: entry, from: source }, ...[...walk(root, "media"), ...walk(root, "_core")].map((f) => ({ to: f, from: f }))];
289
+ const fromOf = new Map(copies.map((c) => [c.to, c.from]));
290
+ const imported = importClosure(entry, [...fromOf.keys()].filter((p) => /\.tsx?$/.test(p)), (p) => readFileSync(join(root, fromOf.get(p)), "utf8"));
291
+ copies = copies.filter((c) => !/\.tsx?$/.test(c.to) || imported.has(c.to));
292
+ const own = slots?.[id] ?? { slots: [], content: {}, texture: [] };
293
+ let presetSlots;
294
+ if (plan) {
295
+ const listed = [...Object.keys(own.content), ...own.texture].find((f) => !existsSync(join(root, f)));
296
+ if (listed) throw new Error(`slots.json lists ${listed}, which the preset does not have`);
297
+ const unknown = own.slots.find((s) => !props.includes(s.prop));
298
+ if (unknown) throw new Error(`slot ${unknown.prop} is not a prop of ${propsType}`);
299
+ const referenced = /* @__PURE__ */ new Set();
300
+ for (const c of copies.filter((c2) => /\.tsx?$/.test(c2.to))) {
301
+ const r = rewriteMedia(readFileSync(join(root, c.from), "utf8"), c.from, plan);
302
+ c.text = r.text;
303
+ for (const m of r.referenced) referenced.add(m);
304
+ }
305
+ copies = copies.flatMap((c) => {
306
+ if (!isMedia(c.to)) return [c];
307
+ if (plan.content.has(c.to)) return [];
308
+ if (plan.textures.has(c.to)) return [{ to: plan.rewrite.get(c.to) ?? c.to, from: c.from }];
309
+ return referenced.has(c.to) ? [c] : [];
310
+ });
311
+ presetSlots = own.slots.map((s) => ({ ...s, placeholder: placeholderPath(s.kind, s.aspect) }));
312
+ const placeholders = /* @__PURE__ */ new Set([...Object.keys(own.content).map((f) => plan.content.get(f)), ...presetSlots.map((s) => s.placeholder)]);
313
+ copies.push(...[...placeholders].toSorted().map((to) => ({ to })));
314
+ }
315
+ for (const { to, from } of copies) {
316
+ const prior = from === void 0 ? void 0 : origin.get(to);
317
+ if (prior && !prior.equals(readFileSync(join(root, from)))) throw new Error(`${to} differs from another preset's copy`);
318
+ }
319
+ mkdirSync(join(staging, id));
320
+ const posterName = await encodePoster(poster, join(staging, id), options.cwebp);
321
+ const previewBytes = await encodePreview(preview, join(staging, id, "preview.mp4"));
322
+ for (const { to, from, text } of copies) {
323
+ if (from === void 0 || (plan?.textures.has(from) ?? false)) continue;
324
+ const target = join(staging, "files", to);
325
+ mkdirSync(dirname(target), { recursive: true });
326
+ if (text === void 0) copyFileSync(join(root, from), target);
327
+ else writeFileSync(target, text);
328
+ origin.set(to, readFileSync(join(root, from)));
329
+ }
330
+ const row = {
331
+ id,
332
+ ...meta,
333
+ entry,
334
+ files: copies.map((c) => c.to),
335
+ poster: `${id}/${posterName}`,
336
+ preview: `${id}/preview.mp4`,
337
+ ...presetSlots ? { slots: presetSlots } : {}
338
+ };
339
+ const posterBytes = statSync(join(staging, row.poster)).size;
340
+ result.installed.push({ ...row, posterBytes, previewBytes });
341
+ options.log?.(`installed ${id} ${row.category} ${row.name} ${row.duration} s poster ${kb(posterBytes)} ${extname(posterName).slice(1)} preview ${kb(previewBytes)}`);
342
+ } catch (error) {
343
+ result.failed.push({ id, error: error instanceof Error ? error.message : String(error) });
344
+ rmSync(join(staging, id), { recursive: true, force: true });
345
+ }
346
+ }
347
+ const presets = result.installed.map(({ posterBytes: _p, previewBytes: _v, ...row }) => row);
348
+ writeFileSync(join(staging, "manifest.json"), `${JSON.stringify({ presets }, null, 2)}
349
+ `);
350
+ rmSync(dir, { recursive: true, force: true });
351
+ renameSync(staging, dir);
352
+ return result;
353
+ }
354
+ var kb = (bytes) => `${(bytes / 1024).toFixed(1)} KB`;
355
+ var MIME = { ".webp": "image/webp", ".jpg": "image/jpeg" };
356
+ function presetCatalogue(dir = presetsDir()) {
357
+ const presets = readManifest(dir);
358
+ return {
359
+ installed: presets !== void 0,
360
+ presets: (presets ?? []).map(({ files: _f, poster, preview: _p, ...row }) => ({
361
+ ...row,
362
+ poster: `data:${MIME[extname(poster)]};base64,${readFileSync(join(dir, poster)).toString("base64")}`,
363
+ preview: `/api/presets/${row.id}/preview.mp4`
364
+ }))
365
+ };
366
+ }
367
+ var milli = (n) => Math.round(n * 1e3) / 1e3;
368
+ function fitInto(width, height) {
369
+ const scale = Math.ceil(Math.min(width / AUTHORED.width, height / AUTHORED.height) * 1e3 - 1e-9) / 1e3;
370
+ return { x: milli((width - AUTHORED.width * scale) / 2), y: milli((height - AUTHORED.height * scale) / 2), scale };
371
+ }
372
+ function copyFiles(dir, from, preset) {
373
+ const copied = [];
374
+ const skipped = [];
375
+ for (const file of preset.files) {
376
+ const source = join(from, "files", file);
377
+ const target = join(dir, file);
378
+ if (existsSync(target)) {
379
+ if (!readFileSync(target).equals(readFileSync(source))) skipped.push(file);
380
+ continue;
381
+ }
382
+ mkdirSync(dirname(target), { recursive: true });
383
+ copyFileSync(source, target);
384
+ copied.push(file);
385
+ }
386
+ return { copied, skipped };
387
+ }
388
+ function fillSlots(slots, media) {
389
+ const target = media && slots.find((s) => s.kind === media.kind);
390
+ return slots.map((s) => {
391
+ const filled = s === target;
392
+ const first = filled ? media.src : s.placeholder;
393
+ return { prop: s.prop, src: s.count ? [first, ...Array(s.count - 1).fill(s.placeholder)] : first, filled };
394
+ });
395
+ }
396
+ function addPreset(dir, preset, at, onWrite, from = presetsDir()) {
397
+ const { media } = at;
398
+ if (media !== void 0 && !(typeof media?.src === "string" && media.src && (media.kind === "image" || media.kind === "video"))) {
399
+ return { ok: false, error: 'media needs a non-empty src and kind "image" or "video"' };
400
+ }
401
+ const scenes = new SourceProject(dir).byId(at.sceneId);
402
+ if (scenes.length !== 1) return { ok: false, error: scenes.length ? `${at.sceneId} is used more than once` : `no element ${at.sceneId}` };
403
+ const sceneFile = scenes[0].file.path;
404
+ const files = copyFiles(dir, from, preset);
405
+ const slots = fillSlots(preset.slots ?? [], media);
406
+ const fit = !preset.adapts && (at.width !== AUTHORED.width || at.height !== AUTHORED.height);
407
+ const module = posix.relative(posix.dirname(sceneFile), preset.entry.replace(/\.tsx$/, ""));
408
+ const component = {
409
+ op: "insert",
410
+ tag: preset.component,
411
+ props: { start: fit ? 0 : at.start, ...preset.adapts ? { width: at.width, height: at.height } : {}, ...Object.fromEntries(slots.map((s) => [s.prop, s.src])) },
412
+ import: { from: module.startsWith(".") ? module : `./${module}` }
413
+ };
414
+ const results = [];
415
+ let group = null;
416
+ if (fit) {
417
+ const { x, y, scale } = fitInto(at.width, at.height);
418
+ const insert = { op: "insert", tag: "group", props: { x, y, ...AUTHORED, scale, anchorX: 0, anchorY: 0, clip: true, start: at.start, end: at.start + preset.duration } };
419
+ results.push(applyEdit(dir, at.sceneId, insert, { onWrite }));
420
+ group = results[0].id ?? null;
421
+ }
422
+ if (results.every((r) => r.ok)) results.push(applyEdit(dir, group ?? at.sceneId, component, { onWrite }));
423
+ const ok = results.every((r) => r.ok);
424
+ return { ok, id: ok ? results.at(-1).id : void 0, group, ...files, slots, results };
425
+ }
426
+ async function runPresets(args, print) {
427
+ const [sub, pack] = args.positional;
428
+ if (sub === "install") {
429
+ if (!pack) throw new Error("usage: higgsedit presets install <pack-dir> [--out <dir>] [--slots <slots.json>]");
430
+ const slots = flag(args, "slots");
431
+ const out = flag(args, "out");
432
+ const r = await installPresets(resolve(pack), out ? resolve(out) : presetsDir(), {
433
+ cwebp: findTool("cwebp"),
434
+ slots: slots && resolve(slots),
435
+ ...args.flags.json === true ? {} : { log: (line) => console.log(line) }
436
+ });
437
+ for (const f of r.failed) console.error(`FAILED ${f.id}: ${f.error}`);
438
+ print(r, () => `${r.installed.length} presets in ${r.dir}`);
439
+ return r.failed.length ? 1 : 0;
440
+ }
441
+ if (sub) throw new Error("usage: higgsedit presets [--json] [--presets <dir>] | higgsedit presets install <pack-dir> [--out <dir>] [--slots <slots.json>]");
442
+ const manifest = readManifest(presetsDir(flag(args, "presets")));
443
+ const presets = manifest ?? [];
444
+ const listed = { installed: manifest !== void 0, presets: presets.map(({ id, category, name, duration }) => ({ id, category, name, duration })) };
445
+ const idWidth = Math.max(0, ...presets.map((p) => p.id.length));
446
+ const categoryWidth = Math.max(0, ...presets.map((p) => p.category.length));
447
+ print(
448
+ listed,
449
+ () => presets.length ? presets.map((p) => `${p.id.padEnd(idWidth)} ${p.category.padEnd(categoryWidth)} ${p.duration} s ${p.name}`).join("\n") : "no presets installed; run `higgsedit presets install <pack-dir>`"
450
+ );
451
+ return 0;
452
+ }
453
+
454
+ export {
455
+ PRESET_CATEGORIES,
456
+ presetsDir,
457
+ readManifest,
458
+ placeholderPath,
459
+ installPresets,
460
+ presetCatalogue,
461
+ fitInto,
462
+ addPreset,
463
+ runPresets
464
+ };