hyperframes 0.8.193 → 0.8.195

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 (191) hide show
  1. package/dist/{add-JC6DKZKC.js → add-NL6XABRV.js} +12 -12
  2. package/dist/{animatedGifPrep-S6KXJGEL.js → animatedGifPrep-JD4BBM2L.js} +8 -7
  3. package/dist/api.js +18 -17
  4. package/dist/{asset-XITFIFE6.js → asset-LRRHLG4L.js} +2 -2
  5. package/dist/{assetCataloger-K5FNKG35.js → assetCataloger-D7KGO346.js} +8 -7
  6. package/dist/{audio-364UHTY4.js → audio-34CZM4HF.js} +14 -13
  7. package/dist/{auth-5JEESRE6.js → auth-FL5ZMOXB.js} +1 -1
  8. package/dist/{autoUpdate-RVVYEHAA.js → autoUpdate-FZTJFLIH.js} +2 -2
  9. package/dist/{backgroundChecks-DCBIYWIQ.js → backgroundChecks-6ZKDCQET.js} +3 -3
  10. package/dist/backgroundChecksWorker.js +3 -3
  11. package/dist/{batchRender-ZZ4QMBAA.js → batchRender-KDZ4F4QT.js} +4 -4
  12. package/dist/{beats-YEL65M6G.js → beats-7PK677VR.js} +9 -9
  13. package/dist/{benchmark-RBTRPA76.js → benchmark-LO36QH5D.js} +9 -9
  14. package/dist/{browser-BVAYXT4R.js → browser-3F7NDHU2.js} +5 -5
  15. package/dist/{bundleWithLocalizedFonts-JLB2OYMT.js → bundleWithLocalizedFonts-JL5J52L6.js} +2 -2
  16. package/dist/{capture-GBXTMYLZ.js → capture-DOP3ONNZ.js} +13 -12
  17. package/dist/{capture-NIFX6IRS.js → capture-JOSZZYUW.js} +2 -2
  18. package/dist/{captureCompositionFrame-ATNNKUL5.js → captureCompositionFrame-SWZ4GEJP.js} +13 -12
  19. package/dist/{catalog-AGIF5SM5.js → catalog-EZLHZMLM.js} +12 -12
  20. package/dist/{catch-up-SZ3ULDTI.js → catch-up-6B7VY43I.js} +4 -4
  21. package/dist/{check-YLQS3TF4.js → check-QGELCBBF.js} +38 -37
  22. package/dist/{checkBrowser-QH4FMCBO.js → checkBrowser-A5C2AB4L.js} +33 -32
  23. package/dist/{chunk-L5YLA54L.js → chunk-2G6JZJAV.js} +2 -2
  24. package/dist/{chunk-M3KZBDPB.js → chunk-2HSRLKZR.js} +3 -3
  25. package/dist/{chunk-FBVUAH7N.js → chunk-2OYYNKJ4.js} +1 -1
  26. package/dist/{chunk-2VXY3PEF.js → chunk-2TU4OKIR.js} +280 -114
  27. package/dist/{chunk-4PPWAQYV.js → chunk-3OAFRLD3.js} +7 -7
  28. package/dist/{chunk-ZT45TCY3.js → chunk-3PYIQLPL.js} +1 -1
  29. package/dist/{chunk-DYNHVCBF.js → chunk-4R2NWLQL.js} +2 -2
  30. package/dist/{chunk-SOY2FPOR.js → chunk-636WBDXB.js} +5 -5
  31. package/dist/{chunk-LFUVTS6V.js → chunk-66Q27H72.js} +2 -2
  32. package/dist/{chunk-MFUNDJEV.js → chunk-6ORTRIDW.js} +3 -3
  33. package/dist/{chunk-D625D4TV.js → chunk-7DFIVUOW.js} +6 -6
  34. package/dist/{chunk-ZH7J2ZUL.js → chunk-7G2LQM3J.js} +14 -14
  35. package/dist/{chunk-6LWUPIKD.js → chunk-7PXVXRVX.js} +10 -10
  36. package/dist/{chunk-XQPA4W3M.js → chunk-7Y5RVQQ7.js} +4 -4
  37. package/dist/{chunk-2MCXIY4B.js → chunk-B7RJV74O.js} +28 -11
  38. package/dist/{chunk-BJAS2JLW.js → chunk-B7Y2DGU6.js} +7 -3
  39. package/dist/{chunk-YS4JUGNI.js → chunk-BBXZPDEA.js} +2 -2
  40. package/dist/{chunk-RWGASWT7.js → chunk-BL4U6U52.js} +1 -0
  41. package/dist/{chunk-VW63MHQU.js → chunk-CCZMCX3F.js} +1 -1
  42. package/dist/{chunk-BY6OQ6XP.js → chunk-CZNSLFYD.js} +3 -1
  43. package/dist/{chunk-X5CECNCK.js → chunk-D6XDOYMB.js} +8 -3
  44. package/dist/{chunk-F5LLORBP.js → chunk-E527A6RS.js} +2 -2
  45. package/dist/{chunk-7HTH5PFK.js → chunk-E74JMKSK.js} +58 -8
  46. package/dist/{chunk-TZEKVLPV.js → chunk-ELQ2QQC5.js} +1 -1
  47. package/dist/{chunk-4LXZJIVY.js → chunk-ES7KSCSO.js} +10 -10
  48. package/dist/{chunk-KU3UFQN7.js → chunk-F2ASNL2K.js} +1 -1
  49. package/dist/{chunk-VLLFORE2.js → chunk-F4T7XYMF.js} +1 -1
  50. package/dist/{chunk-E3P3LJG6.js → chunk-FLREUEHW.js} +28 -11
  51. package/dist/{chunk-TY3LDJA3.js → chunk-FWDDLW2H.js} +2 -2
  52. package/dist/{chunk-7YSFE4SZ.js → chunk-GJG4CTXD.js} +2 -2
  53. package/dist/{chunk-2NERNYCJ.js → chunk-GKMRLES4.js} +3 -3
  54. package/dist/{chunk-4TKJWWPL.js → chunk-GOOE33GV.js} +1 -1
  55. package/dist/{chunk-DIKAPMMF.js → chunk-GQVTTWZF.js} +144 -39
  56. package/dist/{chunk-L4JB7LI4.js → chunk-HJINEUHY.js} +84 -61
  57. package/dist/{chunk-7QNIXBQD.js → chunk-HT33OHQL.js} +3 -2
  58. package/dist/{chunk-AR3DQYRR.js → chunk-HTLCE7M2.js} +18 -18
  59. package/dist/{chunk-ZTKFRXJB.js → chunk-IA7HZ4CM.js} +4 -4
  60. package/dist/{chunk-WFS6S65A.js → chunk-IZR7U27Z.js} +12 -12
  61. package/dist/chunk-K4MJX7SR.js +17 -0
  62. package/dist/{chunk-ZZPBXRYQ.js → chunk-KJ6ZQL34.js} +1 -1
  63. package/dist/{chunk-VPC4XIVI.js → chunk-KVLGJJTE.js} +5 -5
  64. package/dist/{chunk-CGTZOY53.js → chunk-L2EBYFU7.js} +1 -1
  65. package/dist/{chunk-UNATIAOT.js → chunk-L4BFXWHC.js} +144 -67
  66. package/dist/{chunk-IW5G323T.js → chunk-LTGTN2TH.js} +8 -9
  67. package/dist/{chunk-EFXMETRK.js → chunk-NKNRVPNV.js} +2 -2
  68. package/dist/{chunk-2SFDWMSW.js → chunk-NOHH25WS.js} +2 -2
  69. package/dist/{chunk-7YKJF5JV.js → chunk-OB4GJZTY.js} +1 -1
  70. package/dist/{chunk-C4Y3ZREE.js → chunk-OJNNKHAZ.js} +75 -22
  71. package/dist/{chunk-OFYW4J7Y.js → chunk-ORZMO6NY.js} +3 -3
  72. package/dist/{chunk-BP4EMEGH.js → chunk-P5X5URNQ.js} +2 -2
  73. package/dist/{chunk-6XUJVEY2.js → chunk-RAACYYWX.js} +1 -1
  74. package/dist/{chunk-QFPBRZJD.js → chunk-ROEW726S.js} +1 -1
  75. package/dist/{chunk-WIVOXGEP.js → chunk-RZUEXJRC.js} +2 -2
  76. package/dist/{chunk-V7ZA2BNW.js → chunk-SC6NILKD.js} +1 -1
  77. package/dist/{chunk-2LSCYS2H.js → chunk-SMROKE63.js} +2 -2
  78. package/dist/{chunk-REUL2KH2.js → chunk-ST35C4K6.js} +1 -1
  79. package/dist/{chunk-OFV3WSOE.js → chunk-TE6VGYHQ.js} +1 -1
  80. package/dist/{chunk-3W4B6G7Y.js → chunk-VNWX5GBF.js} +19 -15
  81. package/dist/{chunk-QKX7ITER.js → chunk-W4SSWOOD.js} +2 -2
  82. package/dist/{chunk-6DLCOQR4.js → chunk-W7GMPEY3.js} +142 -44
  83. package/dist/{chunk-UIC7B5KW.js → chunk-WUL5LPI2.js} +12 -2
  84. package/dist/{chunk-5J6TWLFG.js → chunk-XC7SJ2UR.js} +3 -3
  85. package/dist/{chunk-E77ALFLW.js → chunk-XOUWCZHD.js} +1 -1
  86. package/dist/{chunk-GR5DQKDR.js → chunk-YFTO5YD7.js} +5 -5
  87. package/dist/{chunk-UB7BIDBS.js → chunk-YSXCPSJ4.js} +3 -3
  88. package/dist/{chunk-GKHMSSGY.js → chunk-YUFECVHG.js} +1 -1
  89. package/dist/{chunk-LMNZLZMJ.js → chunk-ZAVUASNT.js} +1 -1
  90. package/dist/{chunk-RTLPWOO6.js → chunk-ZL6ZCLY6.js} +1 -1
  91. package/dist/{chunk-DSQ72G5I.js → chunk-ZOJHEN3C.js} +1 -1
  92. package/dist/chunk-ZQRD62QZ.js +3901 -0
  93. package/dist/{clean-5HGESK5A.js → clean-PI4JLT6O.js} +21 -20
  94. package/dist/cli.js +53 -53
  95. package/dist/{cloud-746PHS32.js → cloud-SQRY723M.js} +4 -4
  96. package/dist/{cloudrun-DO7WFLSM.js → cloudrun-VMPROR43.js} +6 -6
  97. package/dist/commands/layout-audit.browser.js +1 -1
  98. package/dist/{compare-66YPRNG2.js → compare-EHX4APTP.js} +31 -30
  99. package/dist/{compiler-R4UYDWXO.js → compiler-FZCJGGBF.js} +5 -5
  100. package/dist/{component-EQ3H6RFP.js → component-I75ZKJYH.js} +3 -3
  101. package/dist/{compositions-ZZ7P5HT2.js → compositions-YNYYUEQD.js} +12 -11
  102. package/dist/{contactSheet-SZBJDOMT.js → contactSheet-5APX35L3.js} +1 -1
  103. package/dist/{delete-Z5MSLJSR.js → delete-7BVTBKOC.js} +2 -2
  104. package/dist/{deploy-RGSAC2K5.js → deploy-TUEEJP3W.js} +1 -1
  105. package/dist/{deterministicFonts-RO2TCMLZ.js → deterministicFonts-RADD3BSX.js} +2 -2
  106. package/dist/{dist-QQ26RUDV.js → dist-VRGIE57H.js} +1 -1
  107. package/dist/{dist-RKK4YLAD.js → dist-VVROHSP4.js} +3 -3
  108. package/dist/{doctor-W4ZZDRTU.js → doctor-53DSQFW4.js} +14 -13
  109. package/dist/{events-BSSL4A4W.js → events-AD3U6E7I.js} +2 -2
  110. package/dist/{events-UACT7PX3.js → events-M6FIUDNQ.js} +3 -3
  111. package/dist/{feedback-47ILDLQG.js → feedback-7SQ7KKAR.js} +8 -8
  112. package/dist/{ffmpeg-IEHSUNUT.js → ffmpeg-3HSSPXS4.js} +9 -8
  113. package/dist/{figma-PLFIIYRU.js → figma-B5XII2BO.js} +3 -3
  114. package/dist/fontLocalizeCli.js +11 -10
  115. package/dist/{get-PDWGJYNL.js → get-RZKNBIRD.js} +2 -2
  116. package/dist/{gpuPolicy-6UBXO6ME.js → gpuPolicy-77LOK3K6.js} +8 -7
  117. package/dist/{grade-compare-5VWLQGM7.js → grade-compare-K3YB3FQA.js} +37 -35
  118. package/dist/{gsapParser-UP3PNPC2.js → gsapParser-IEUSLYDJ.js} +11 -11
  119. package/dist/{gsapParserAcorn-OOTY2MVN.js → gsapParserAcorn-LZJKCFQI.js} +1 -1
  120. package/dist/{help-DS3KMWYO.js → help-UM6INVL5.js} +1 -1
  121. package/dist/{history-OC326NVZ.js → history-EWKPACWR.js} +7 -7
  122. package/dist/hyperframe.manifest.json +1 -1
  123. package/dist/hyperframe.runtime.iife.js +72 -66
  124. package/dist/hyperframes-player.global.js +3 -3
  125. package/dist/hyperframes-slideshow.global.js +1 -1
  126. package/dist/{info-AUIFV6MX.js → info-KY3MFTCY.js} +8 -8
  127. package/dist/{init-MRTWWDFW.js → init-LURF2PL5.js} +30 -29
  128. package/dist/{inspect-55NOAXI2.js → inspect-46CZJM6P.js} +31 -30
  129. package/dist/{installer-YSFFGBBV.js → installer-NGFX6INI.js} +5 -5
  130. package/dist/{keyframes-OO2BX2IB.js → keyframes-YCSK6POI.js} +59 -33
  131. package/dist/{lambda-CXXY6QT3.js → lambda-5KXULI2S.js} +8 -8
  132. package/dist/{layout-57GJXKDK.js → layout-WOLH24YE.js} +31 -30
  133. package/dist/{lint-J4FK3Z6G.js → lint-P3P2LX6S.js} +7 -7
  134. package/dist/{lintProject-52SLJPRC.js → lintProject-ESAJKFOX.js} +1 -1
  135. package/dist/{list-VDQUJ76B.js → list-RUYQWMF2.js} +2 -2
  136. package/dist/{login-TJSEALWW.js → login-THBBWZAY.js} +4 -4
  137. package/dist/{manager-MZIJY73J.js → manager-COSJVRAE.js} +2 -2
  138. package/dist/{manager-4PLYEEWP.js → manager-V34BMSAG.js} +10 -9
  139. package/dist/{media-treatment-GXP4PMJH.js → media-treatment-IMBLTYGV.js} +15 -14
  140. package/dist/{models-HQQQKEEP.js → models-3NW7HU72.js} +14 -13
  141. package/dist/{motionShot-2BT5D7DC.js → motionShot-VTTYZ6KW.js} +17 -16
  142. package/dist/{normalize-audio-SOLFMHNP.js → normalize-audio-ME3X7HBX.js} +6 -6
  143. package/dist/{open-KHEUODFQ.js → open-GLGSJISM.js} +12 -12
  144. package/dist/{parakeetRunner-BHU5NCAX.js → parakeetRunner-T3UGRZWC.js} +15 -14
  145. package/dist/{pipeline-WFV5HDTD.js → pipeline-IJXVEQCU.js} +10 -9
  146. package/dist/{play-GB34CANJ.js → play-HFFGGAZH.js} +21 -21
  147. package/dist/{preflight-REF3VSJ7.js → preflight-QV6V3UO2.js} +11 -10
  148. package/dist/{present-SIUTA7TD.js → present-TH34CTYY.js} +17 -17
  149. package/dist/{preview-T2GE7Z4A.js → preview-R67EQGQP.js} +100 -65
  150. package/dist/{producer-23KVQZAB.js → producer-HWPFETDU.js} +1 -1
  151. package/dist/{projectConfig-DBSNBPNP.js → projectConfig-AO4V3RHS.js} +7 -7
  152. package/dist/{publication-IXPUKYWJ.js → publication-BDQ3PXYG.js} +3 -3
  153. package/dist/{publish-3BA5VHXJ.js → publish-PXYTWSXN.js} +10 -10
  154. package/dist/{remove-background-RMSCJVVQ.js → remove-background-BVDJPT3Z.js} +11 -10
  155. package/dist/{render-Y6CTQ3YW.js → render-45YHWV6W.js} +6 -6
  156. package/dist/{render-6RNE2MLU.js → render-5MZY4TAB.js} +17 -16
  157. package/dist/{render-XGOZMMWX.js → render-5RQUYPIV.js} +35 -34
  158. package/dist/{render-batch-VUR6N6EY.js → render-batch-ZUTUBTHX.js} +6 -6
  159. package/dist/renderSetupWorker.js +42 -4
  160. package/dist/{resolver-GJCUH57W.js → resolver-FN2M3XVM.js} +5 -5
  161. package/dist/{sherpa-VVAKRCPL.js → sherpa-6KWNPRWB.js} +14 -13
  162. package/dist/skills/media-use/scripts/lib/duck.mjs +18 -2
  163. package/dist/skills/media-use/scripts/lib/duck.test.mjs +79 -0
  164. package/dist/{skills-ZHBURVQG.js → skills-PWQCM2BT.js} +5 -5
  165. package/dist/{skillsUpdateCheck-VMDAL2O2.js → skillsUpdateCheck-EHV2G3JX.js} +3 -3
  166. package/dist/{snapshot-KEOG56SL.js → snapshot-7Q24NFEI.js} +39 -38
  167. package/dist/{src-TZLGFRRX.js → src-J43SXEHJ.js} +10 -9
  168. package/dist/{src-BH5NICGQ.js → src-OS2FRVZV.js} +9 -6
  169. package/dist/{staticProjectServer-BKXL5CXB.js → staticProjectServer-YJWOQJF4.js} +18 -18
  170. package/dist/studio/assets/{hyperframes-player-BMcUdmDb.js → hyperframes-player-DnIPEARk.js} +1 -1
  171. package/dist/studio/assets/{index-Ci6GuloR.js → index-CVppCm_X.js} +1 -1
  172. package/dist/studio/assets/{index-Ca-mgTnS.js → index-Dkt4c1MV.js} +161 -161
  173. package/dist/studio/index.html +1 -1
  174. package/dist/{studio-api-A5U6QAMC.js → studio-api-CZBZ4D65.js} +11 -11
  175. package/dist/{studioServer-5EC5CP4W.js → studioServer-U6EX5DSB.js} +94 -53
  176. package/dist/{telemetry-BCKJXDSW.js → telemetry-VP4UWWO3.js} +3 -3
  177. package/dist/{timeline-AZWAXTAY.js → timeline-LMSUKEG6.js} +20 -19
  178. package/dist/{tokens-X7NC3V7C.js → tokens-FQ5AI5H4.js} +2 -2
  179. package/dist/{transcribe-7NCY7QZ2.js → transcribe-DNQFPZ2S.js} +13 -12
  180. package/dist/{transcribe-SH26H755.js → transcribe-VAMXV7QS.js} +19 -18
  181. package/dist/{updateCheck-Y7FUWQM4.js → updateCheck-TOU7VLZK.js} +2 -2
  182. package/dist/{upgrade-ZHGEVL65.js → upgrade-CJRMRR2S.js} +2 -2
  183. package/dist/{urlDownloader-FPILIT7M.js → urlDownloader-GETNWEIT.js} +7 -6
  184. package/dist/{validate-KQOZR4F6.js → validate-PRI2UTQS.js} +25 -24
  185. package/dist/vendor/npm/gsap@3.15.0/dist/CustomEase.min.js +11 -0
  186. package/dist/vendor/npm/gsap@3.15.0/dist/MotionPathPlugin.min.js +11 -0
  187. package/dist/vendor/npm/gsap@3.15.0/dist/gsap.min.js +11 -0
  188. package/dist/{video-N2QAETFB.js → video-VOCQA6AG.js} +8 -7
  189. package/dist/warmCheck.js +38 -37
  190. package/package.json +1 -1
  191. package/dist/chunk-USWPZXEA.js +0 -3897
@@ -59,6 +59,33 @@ function editabilityForProvenance(provenance) {
59
59
  if (provenance.kind === "runtime-dynamic") return "source";
60
60
  return "unroll";
61
61
  }
62
+ function mergePercentageKeyframes(keyframes) {
63
+ const byPercentage = /* @__PURE__ */ new Map();
64
+ for (const keyframe of keyframes) {
65
+ const existing = byPercentage.get(keyframe.percentage);
66
+ if (!existing) {
67
+ byPercentage.set(keyframe.percentage, {
68
+ ...keyframe,
69
+ properties: { ...keyframe.properties }
70
+ });
71
+ continue;
72
+ }
73
+ existing.properties = { ...existing.properties, ...keyframe.properties };
74
+ if (keyframe.ease !== void 0) existing.ease = keyframe.ease;
75
+ if (keyframe.auto !== void 0) existing.auto = keyframe.auto;
76
+ }
77
+ return [...byPercentage.values()].sort((a, b) => a.percentage - b.percentage);
78
+ }
79
+ function distributeArrayKeyframes(channels) {
80
+ return mergePercentageKeyframes(
81
+ [...channels].flatMap(
82
+ ([key, values]) => values.map((value, index) => ({
83
+ percentage: values.length > 1 ? Math.round(index / (values.length - 1) * 100) : 0,
84
+ properties: { [key]: value }
85
+ }))
86
+ )
87
+ );
88
+ }
62
89
  function buildArcPath(coords, curviness, autoRotate, isCubic) {
63
90
  const first = coords[0];
64
91
  if (coords.length < 2 || !first) return void 0;
@@ -1355,19 +1382,9 @@ function parseSimpleArrayKeyframes(node, scope) {
1355
1382
  easeEach = tryResolveStringProp(prop.value, scope) ?? easeEach;
1356
1383
  }
1357
1384
  }
1358
- const maxLen = Math.max(...[...arrayProps.values()].map((a) => a.length), 0);
1359
- const keyframes = [];
1360
- for (let i = 0; i < maxLen; i++) {
1361
- const percentage = maxLen > 1 ? Math.round(i / (maxLen - 1) * 100) : 0;
1362
- const properties = {};
1363
- for (const [key, values] of arrayProps) {
1364
- if (i < values.length) properties[key] = values[i];
1365
- }
1366
- keyframes.push({ percentage, properties });
1367
- }
1368
1385
  return {
1369
1386
  format: "simple-array",
1370
- keyframes,
1387
+ keyframes: distributeArrayKeyframes(arrayProps),
1371
1388
  ...ease ? { ease } : {},
1372
1389
  ...easeEach ? { easeEach } : {}
1373
1390
  };
@@ -9,10 +9,10 @@ import {
9
9
  isHttpUrl,
10
10
  renameWithRetry,
11
11
  runFfmpeg
12
- } from "./chunk-L4JB7LI4.js";
12
+ } from "./chunk-HJINEUHY.js";
13
13
  import {
14
14
  parseAnimatedGifMetadata
15
- } from "./chunk-7HTH5PFK.js";
15
+ } from "./chunk-E74JMKSK.js";
16
16
  import {
17
17
  parseHTML
18
18
  } from "./chunk-SDYDNHEE.js";
@@ -13,11 +13,11 @@ import {
13
13
  formatPreviewProxyBox,
14
14
  hdrToSdrToneMapFilter,
15
15
  parseFirstFrameColour
16
- } from "./chunk-7HTH5PFK.js";
16
+ } from "./chunk-E74JMKSK.js";
17
17
  import {
18
18
  decodeAuthoredAttribute,
19
19
  scanHtmlOpeningTags
20
- } from "./chunk-2MCXIY4B.js";
20
+ } from "./chunk-B7RJV74O.js";
21
21
  import {
22
22
  mkdirWithinProject,
23
23
  realProjectRoot,
@@ -11,14 +11,14 @@ import {
11
11
  distroLabel,
12
12
  getFFmpegInstallHint,
13
13
  parseLddMissingLibs
14
- } from "./chunk-DYNHVCBF.js";
14
+ } from "./chunk-4R2NWLQL.js";
15
15
  import {
16
16
  ensureBrowser,
17
17
  findBrowser
18
- } from "./chunk-DIKAPMMF.js";
18
+ } from "./chunk-GQVTTWZF.js";
19
19
  import {
20
20
  runCancellableProcess
21
- } from "./chunk-RWGASWT7.js";
21
+ } from "./chunk-BL4U6U52.js";
22
22
  import {
23
23
  getFreeDiskMb
24
24
  } from "./chunk-T6AGUTZJ.js";
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-442JNXRM.js";
10
10
  import {
11
11
  quantizePreviewProxyBox
12
- } from "./chunk-7HTH5PFK.js";
12
+ } from "./chunk-E74JMKSK.js";
13
13
 
14
14
  // src/utils/compositionViewport.ts
15
15
  var DEFAULT_VIEWPORT = { width: 1920, height: 1080 };
@@ -7,7 +7,7 @@ var __dirname = __hf_dirname(__filename);
7
7
  import {
8
8
  runCancellableProcess,
9
9
  runRenderSetupWorker
10
- } from "./chunk-RWGASWT7.js";
10
+ } from "./chunk-BL4U6U52.js";
11
11
  import {
12
12
  getFreeDiskMb
13
13
  } from "./chunk-T6AGUTZJ.js";
@@ -35,9 +35,81 @@ import {
35
35
  writeFileSync
36
36
  } from "fs";
37
37
  import { homedir } from "os";
38
- import { debuglog } from "util";
39
38
  import { basename, dirname as dirname2, join, relative } from "path";
40
39
 
40
+ // src/browser/installProtocol.ts
41
+ var PROGRESS_PREFIX = "HYPERFRAMES_BROWSER_INSTALL_PROGRESS:";
42
+ var LOG_PREFIX = "HYPERFRAMES_BROWSER_INSTALL_LOG:";
43
+ function installProgressLine(downloaded, total) {
44
+ return `${PROGRESS_PREFIX}${JSON.stringify([downloaded, total])}
45
+ `;
46
+ }
47
+ function installLogLine(text) {
48
+ return `${LOG_PREFIX}${JSON.stringify(text)}
49
+ `;
50
+ }
51
+ function parseInstallLine(line) {
52
+ try {
53
+ if (line.startsWith(PROGRESS_PREFIX)) {
54
+ const [downloaded, total] = JSON.parse(line.slice(PROGRESS_PREFIX.length));
55
+ return { kind: "progress", downloaded, total };
56
+ }
57
+ if (line.startsWith(LOG_PREFIX)) {
58
+ return { kind: "log", text: JSON.parse(line.slice(LOG_PREFIX.length)) };
59
+ }
60
+ } catch {
61
+ }
62
+ return null;
63
+ }
64
+
65
+ // src/browser/installInChild.ts
66
+ var CHILD_STARTUP_MS = 15e3;
67
+ var BrowserDownloadStalledError = class extends Error {
68
+ };
69
+ function lineReader(onLine) {
70
+ let pending = "";
71
+ return (chunk) => {
72
+ const lines = (pending + chunk).split("\n");
73
+ pending = lines.pop() ?? "";
74
+ for (const line of lines) onLine(line);
75
+ };
76
+ }
77
+ async function installInChild(input, hooks) {
78
+ const abort = new AbortController();
79
+ let timer;
80
+ const arm = (waitMs) => {
81
+ clearTimeout(timer);
82
+ timer = setTimeout(
83
+ () => abort.abort(
84
+ new BrowserDownloadStalledError(
85
+ `The Chrome download from ${hooks.host} stalled: no data for ${hooks.stallMs / 1e3}s.`
86
+ )
87
+ ),
88
+ waitMs
89
+ );
90
+ timer.unref();
91
+ };
92
+ const onStdout = lineReader((line) => {
93
+ const event = parseInstallLine(line);
94
+ if (event?.kind === "log") hooks.onLog(event.text);
95
+ if (event?.kind !== "progress") return;
96
+ if (event.total > 0) hooks.onProgress?.(event.downloaded, event.total);
97
+ if (event.total > 0 && event.downloaded >= event.total) clearTimeout(timer);
98
+ else arm(hooks.stallMs);
99
+ });
100
+ arm(CHILD_STARTUP_MS + hooks.stallMs);
101
+ try {
102
+ return await runRenderSetupWorker("browser-install", input, {
103
+ signal: abort.signal,
104
+ detached: false,
105
+ maxBufferBytes: 4 * 1024 * 1024,
106
+ onStdout
107
+ });
108
+ } finally {
109
+ clearTimeout(timer);
110
+ }
111
+ }
112
+
41
113
  // src/browser/unzipArchive.ts
42
114
  import { mkdir } from "fs/promises";
43
115
  import { dirname } from "path";
@@ -486,10 +558,33 @@ Point hyperframes at an already-installed Chrome/Chromium instead:
486
558
  Then re-run your command. Any Chrome build works for the screenshot capture path; install a real chrome-headless-shell later if you need the perf-optimized BeginFrame path. Alternatively, run inside the hyperframes Docker image which ships a compatible headless-shell.`;
487
559
  return new Error(message, { cause: cause instanceof Error ? cause : void 0 });
488
560
  }
489
- async function downloadBrowser(options) {
490
- if (isLinuxArm()) {
491
- return ensureLinuxArmBrowser(options);
561
+ var DOWNLOAD_STALL_MS = 6e4;
562
+ var DOWNLOAD_ATTEMPTS = 3;
563
+ async function retryOnStall(run, clear) {
564
+ for (let attempt = 1; ; attempt++) {
565
+ try {
566
+ return await run();
567
+ } catch (err) {
568
+ if (!(err instanceof BrowserDownloadStalledError) || attempt >= DOWNLOAD_ATTEMPTS) throw err;
569
+ console.warn(`[hyperframes] ${err.message} Retrying (${attempt}/${DOWNLOAD_ATTEMPTS - 1}).`);
570
+ clear();
571
+ }
492
572
  }
573
+ }
574
+ function downloadHostOf(browsers, platform, buildId, baseUrl) {
575
+ try {
576
+ const url = browsers.getDownloadUrl(
577
+ browsers.Browser.CHROMEHEADLESSSHELL,
578
+ platform,
579
+ buildId,
580
+ baseUrl
581
+ );
582
+ return new URL(url).host;
583
+ } catch {
584
+ return "the Chrome download host";
585
+ }
586
+ }
587
+ function assertRoomToDownload() {
493
588
  removeInstallLeftovers();
494
589
  const freeMb = getFreeDiskMb(CACHE_ROOT_DIR);
495
590
  if (freeMb !== null && freeMb < ARCHIVE_PLUS_UNPACKED_SHELL_MB) {
@@ -497,55 +592,63 @@ async function downloadBrowser(options) {
497
592
  `Low disk space: Chrome Headless Shell needs about ${ARCHIVE_PLUS_UNPACKED_SHELL_MB} MB to download, ${freeMb} MB free at ${CACHE_ROOT_DIR}. Free disk space, then retry.`
498
593
  );
499
594
  }
500
- const { Browser, Cache, detectBrowserPlatform, install } = await loadPuppeteerBrowsers();
501
- const platform = detectBrowserPlatform();
502
- if (!platform) {
503
- throw new Error(`Unsupported platform: ${process.platform} ${process.arch}`);
504
- }
505
- const stagingDir = join(CACHE_ROOT_DIR, `${STAGING_PREFIX}${randomUUID()}`);
506
- const clearStaging = () => rmSync(stagingDir, { recursive: true, force: true });
507
- let unzipLog = [];
595
+ }
596
+ function stagedInstaller(browsers, platform, stagingDir, options, unzipLog) {
508
597
  const buildId = managedChromeVersion();
509
- const runInstall = async () => {
510
- unzipLog = [];
511
- const installOptions = {
598
+ const hooks = {
599
+ stallMs: options?.downloadStallMs ?? DOWNLOAD_STALL_MS,
600
+ host: downloadHostOf(browsers, platform, buildId, options?.downloadBaseUrl),
601
+ onProgress: options?.onProgress,
602
+ onLog: (line) => unzipLog.lines.push(line)
603
+ };
604
+ return async () => {
605
+ unzipLog.lines = [];
606
+ const input = {
512
607
  cacheDir: stagingDir,
513
- browser: Browser.CHROMEHEADLESSSHELL,
608
+ browser: browsers.Browser.CHROMEHEADLESSSHELL,
514
609
  buildId,
515
610
  platform,
516
- downloadProgressCallback: options?.onProgress,
517
- logger: (prefix) => {
518
- const debug = debuglog(prefix);
519
- const isUnzip = prefix === "puppeteer:browsers:fileUtil";
520
- if (!isUnzip && !debug.enabled) return void 0;
521
- return (...args) => {
522
- const line = args.join(" ");
523
- if (isUnzip) unzipLog.push(line);
524
- if (debug.enabled) debug(line);
525
- };
526
- }
611
+ baseUrl: options?.downloadBaseUrl
527
612
  };
528
613
  const unzipMayAskOnInput = process.platform !== "win32";
529
614
  if (unzipMayAskOnInput) {
530
- const archive = await install({ ...installOptions, unpack: false });
531
- const into = new Cache(stagingDir).installationDir(installOptions.browser, platform, buildId);
615
+ const archive = await installInChild({ ...input, unpack: false }, hooks);
616
+ const into = new browsers.Cache(stagingDir).installationDir(input.browser, platform, buildId);
532
617
  await unzipArchive(archive, into);
533
618
  }
534
- return install(installOptions);
619
+ return installInChild(input, hooks);
535
620
  };
621
+ }
622
+ async function downloadBrowser(options) {
623
+ if (isLinuxArm()) {
624
+ return ensureLinuxArmBrowser(options);
625
+ }
626
+ assertRoomToDownload();
627
+ const browsers = await loadPuppeteerBrowsers();
628
+ const platform = browsers.detectBrowserPlatform();
629
+ if (!platform) {
630
+ throw new Error(`Unsupported platform: ${process.platform} ${process.arch}`);
631
+ }
632
+ const stagingDir = join(CACHE_ROOT_DIR, `${STAGING_PREFIX}${randomUUID()}`);
633
+ const clearStaging = () => rmSync(stagingDir, { recursive: true, force: true });
634
+ const unzipLog = { lines: [] };
635
+ const runInstall = stagedInstaller(browsers, platform, stagingDir, options, unzipLog);
536
636
  try {
537
- const staged = await installWithCorruptArchiveRecovery(
538
- runInstall,
539
- clearStaging,
540
- (err) => console.warn(
541
- `[hyperframes] Downloaded browser archive was corrupt (${normalizeErrorMessage(err)}); re-downloading.`
542
- )
637
+ const staged = await retryOnStall(
638
+ () => installWithCorruptArchiveRecovery(
639
+ runInstall,
640
+ clearStaging,
641
+ (err) => console.warn(
642
+ `[hyperframes] Downloaded browser archive was corrupt (${normalizeErrorMessage(err)}); re-downloading.`
643
+ )
644
+ ),
645
+ clearStaging
543
646
  );
544
647
  assertExecutableUnpacked(stagingDir, staged.executablePath);
545
- unzipLog = [];
648
+ unzipLog.lines = [];
546
649
  return { executablePath: moveStagedInstallIntoCache(stagingDir, staged), source: "download" };
547
650
  } catch (err) {
548
- throw wrapDownloadFailureWithBrowserPathHint(err, unzipLog);
651
+ throw wrapDownloadFailureWithBrowserPathHint(err, unzipLog.lines);
549
652
  } finally {
550
653
  clearStaging();
551
654
  }
@@ -622,6 +725,8 @@ function isLinuxArm() {
622
725
  }
623
726
 
624
727
  export {
728
+ installProgressLine,
729
+ installLogLine,
625
730
  CACHE_DIR,
626
731
  withInstallLock,
627
732
  releaseOwnedBrowserInstallLock,