opendevbrowser 0.0.33 → 0.0.35

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 (301) hide show
  1. package/README.md +1 -1
  2. package/dist/{accessibility-snapshot-JSPFVWZ6.js → accessibility-snapshot-TAFPVLZN.js} +9 -9
  3. package/dist/{active-window-2OB2MSCR.js → active-window-MHFMC6NQ.js} +9 -9
  4. package/dist/{annotate-VDZBZBKZ.js → annotate-5ZFRFQ4B.js} +8 -8
  5. package/dist/{attr-7XIO4MCH.js → attr-MBF2UCRF.js} +8 -8
  6. package/dist/browser/browser-manager.d.ts +6 -1
  7. package/dist/browser/browser-manager.d.ts.map +1 -1
  8. package/dist/browser/manager-types.d.ts +51 -0
  9. package/dist/browser/manager-types.d.ts.map +1 -1
  10. package/dist/browser/ops-browser-manager.d.ts +2 -1
  11. package/dist/browser/ops-browser-manager.d.ts.map +1 -1
  12. package/dist/browser/screencast-recorder.d.ts +1 -0
  13. package/dist/browser/screencast-recorder.d.ts.map +1 -1
  14. package/dist/{canvas-N4PAA274.js → canvas-CAMD22YU.js} +8 -8
  15. package/dist/{capture-desktop-T5YO3EBI.js → capture-desktop-TMZSFA5R.js} +9 -9
  16. package/dist/{capture-window-UKEUBWKH.js → capture-window-NZDKD2AE.js} +9 -9
  17. package/dist/{check-PQB6KKMN.js → check-MO33GTQ4.js} +8 -8
  18. package/dist/{checked-RNZIMCU6.js → checked-3HDF5X2M.js} +8 -8
  19. package/dist/{chunk-YRRRUGSQ.js → chunk-32ZSOZND.js} +2 -2
  20. package/dist/{chunk-EOX6U6Q4.js → chunk-AHQC4A6P.js} +896 -118
  21. package/dist/chunk-AHQC4A6P.js.map +1 -0
  22. package/dist/{chunk-IBIHDGTZ.js → chunk-B5XIJQXO.js} +32 -4
  23. package/dist/chunk-B5XIJQXO.js.map +1 -0
  24. package/dist/{chunk-FDBUB7BM.js → chunk-BHZLEFXW.js} +2 -2
  25. package/dist/{chunk-JROW6ZNN.js → chunk-FJZY3Z3X.js} +3 -3
  26. package/dist/{chunk-J3KYGJRQ.js → chunk-G6NQ7WYD.js} +2 -2
  27. package/dist/{chunk-27W46IKI.js → chunk-HM4CO3EW.js} +38 -23
  28. package/dist/chunk-HM4CO3EW.js.map +1 -0
  29. package/dist/{chunk-SKFB5ICF.js → chunk-TI5I6UWY.js} +8 -3
  30. package/dist/chunk-TI5I6UWY.js.map +1 -0
  31. package/dist/{chunk-52ZIOWVU.js → chunk-UEAXTWGT.js} +3 -3
  32. package/dist/{chunk-ZGCTC5YM.js → chunk-UVD34RA2.js} +33 -1
  33. package/dist/chunk-UVD34RA2.js.map +1 -0
  34. package/dist/{chunk-W6YPVNDX.js → chunk-VTGG5ZU2.js} +2 -2
  35. package/dist/{chunk-FBKPDILE.js → chunk-WTWSBEBW.js} +5954 -436
  36. package/dist/chunk-WTWSBEBW.js.map +1 -0
  37. package/dist/{chunk-NURQB55J.js → chunk-WY72GYAH.js} +2 -2
  38. package/dist/{chunk-MJF67OTH.js → chunk-XSSPNVMS.js} +3 -3
  39. package/dist/{chunk-MJF67OTH.js.map → chunk-XSSPNVMS.js.map} +1 -1
  40. package/dist/{chunk-HMRANSDX.js → chunk-Z3ADLR7I.js} +698 -18
  41. package/dist/chunk-Z3ADLR7I.js.map +1 -0
  42. package/dist/cli/commands/inspiredesign.d.ts +12 -1
  43. package/dist/cli/commands/inspiredesign.d.ts.map +1 -1
  44. package/dist/cli/daemon-commands.d.ts.map +1 -1
  45. package/dist/cli/help.d.ts.map +1 -1
  46. package/dist/cli/index.js +76 -76
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cli/utils/parse.d.ts +1 -0
  49. package/dist/cli/utils/parse.d.ts.map +1 -1
  50. package/dist/cli/utils/workflow-message.d.ts.map +1 -1
  51. package/dist/{click-U7ZFKSB4.js → click-SWZPJO2U.js} +8 -8
  52. package/dist/{clone-component-SWYAORTU.js → clone-component-YTB46YU4.js} +7 -7
  53. package/dist/{clone-page-WJ6UJOJG.js → clone-page-5FMPHQ3A.js} +7 -7
  54. package/dist/{close-NAVIHZ2T.js → close-22SNMDX3.js} +7 -7
  55. package/dist/{close-VKIGIKVT.js → close-ORQZCZ2E.js} +7 -7
  56. package/dist/{connect-XVG2MOZL.js → connect-EWYITNQU.js} +8 -8
  57. package/dist/{console-poll-XI5BZPL7.js → console-poll-LJR6ZTDK.js} +8 -8
  58. package/dist/{cookie-import-QELKE7TK.js → cookie-import-PTAIWPEC.js} +7 -7
  59. package/dist/{cookie-list-QDA6KWIY.js → cookie-list-76C35B5B.js} +7 -7
  60. package/dist/{daemon-CA4UIIZQ.js → daemon-UKJMDLCB.js} +6 -6
  61. package/dist/daemon-fingerprint.json +1 -1
  62. package/dist/{debug-trace-snapshot-AT4GAO57.js → debug-trace-snapshot-PQ5FJART.js} +8 -8
  63. package/dist/{dialog-O3V2IBFH.js → dialog-WLJDWJV4.js} +8 -8
  64. package/dist/{disconnect-NAX5TPTG.js → disconnect-FNB4JC2U.js} +7 -7
  65. package/dist/{enabled-VT4FJXDX.js → enabled-PYMCOQPC.js} +8 -8
  66. package/dist/{goto-GBJG5NC4.js → goto-UNTEW4VI.js} +8 -8
  67. package/dist/guidance/context.d.ts +10 -0
  68. package/dist/guidance/context.d.ts.map +1 -1
  69. package/dist/guidance/readiness.d.ts.map +1 -1
  70. package/dist/guidance/recipes/generic.d.ts.map +1 -1
  71. package/dist/guidance/recipes/pinterest.d.ts.map +1 -1
  72. package/dist/guidance/recipes/site-recipe-validation.d.ts +27 -0
  73. package/dist/guidance/recipes/site-recipe-validation.d.ts.map +1 -0
  74. package/dist/guidance/types.d.ts +5 -0
  75. package/dist/guidance/types.d.ts.map +1 -1
  76. package/dist/{help-SUI4H77K.js → help-QOLCIB3P.js} +8 -7
  77. package/dist/{help-SUI4H77K.js.map → help-QOLCIB3P.js.map} +1 -1
  78. package/dist/{hover-476ZNQZE.js → hover-ZWY4YOM4.js} +8 -8
  79. package/dist/{html-5C4TXOV3.js → html-M46YBFT3.js} +8 -8
  80. package/dist/index.js +83 -23
  81. package/dist/index.js.map +1 -1
  82. package/dist/{inspector-73ARPCIV.js → inspector-6YAOI74U.js} +10 -10
  83. package/dist/{inspector-audit-QT6QY7KS.js → inspector-audit-PF64X6SJ.js} +12 -12
  84. package/dist/{inspector-plan-JRNSGN2Z.js → inspector-plan-IUGTQV3Q.js} +10 -10
  85. package/dist/inspiredesign/capture-mode.d.ts +8 -0
  86. package/dist/inspiredesign/capture-mode.d.ts.map +1 -1
  87. package/dist/inspiredesign/capture.d.ts +36 -1
  88. package/dist/inspiredesign/capture.d.ts.map +1 -1
  89. package/dist/inspiredesign/contract.d.ts +25 -0
  90. package/dist/inspiredesign/contract.d.ts.map +1 -1
  91. package/dist/inspiredesign/handoff.d.ts +6 -2
  92. package/dist/inspiredesign/handoff.d.ts.map +1 -1
  93. package/dist/inspiredesign/media-analysis/analyzer.d.ts +13 -0
  94. package/dist/inspiredesign/media-analysis/analyzer.d.ts.map +1 -0
  95. package/dist/inspiredesign/media-analysis/design-guidance.d.ts +11 -0
  96. package/dist/inspiredesign/media-analysis/design-guidance.d.ts.map +1 -0
  97. package/dist/inspiredesign/media-analysis/ffmpeg.d.ts +21 -0
  98. package/dist/inspiredesign/media-analysis/ffmpeg.d.ts.map +1 -0
  99. package/dist/inspiredesign/media-analysis/ffprobe.d.ts +8 -0
  100. package/dist/inspiredesign/media-analysis/ffprobe.d.ts.map +1 -0
  101. package/dist/inspiredesign/media-analysis/index.d.ts +10 -0
  102. package/dist/inspiredesign/media-analysis/index.d.ts.map +1 -0
  103. package/dist/inspiredesign/media-analysis/persist.d.ts +6 -0
  104. package/dist/inspiredesign/media-analysis/persist.d.ts.map +1 -0
  105. package/dist/inspiredesign/media-analysis/pixel.d.ts +9 -0
  106. package/dist/inspiredesign/media-analysis/pixel.d.ts.map +1 -0
  107. package/dist/inspiredesign/media-analysis/types.d.ts +163 -0
  108. package/dist/inspiredesign/media-analysis/types.d.ts.map +1 -0
  109. package/dist/inspiredesign/media-analysis/typography-structure.d.ts +3 -0
  110. package/dist/inspiredesign/media-analysis/typography-structure.d.ts.map +1 -0
  111. package/dist/inspiredesign/meta-prompt.d.ts.map +1 -1
  112. package/dist/inspiredesign/motion-evidence.d.ts +73 -0
  113. package/dist/inspiredesign/motion-evidence.d.ts.map +1 -0
  114. package/dist/inspiredesign/pinterest-media-classification.d.ts +27 -0
  115. package/dist/inspiredesign/pinterest-media-classification.d.ts.map +1 -0
  116. package/dist/inspiredesign/pinterest-pin-media-evidence.d.ts +151 -0
  117. package/dist/inspiredesign/pinterest-pin-media-evidence.d.ts.map +1 -0
  118. package/dist/inspiredesign/product-readiness.d.ts +97 -0
  119. package/dist/inspiredesign/product-readiness.d.ts.map +1 -0
  120. package/dist/inspiredesign/reference-pattern-board.d.ts +32 -2
  121. package/dist/inspiredesign/reference-pattern-board.d.ts.map +1 -1
  122. package/dist/inspiredesign/visual-evidence.d.ts +5 -0
  123. package/dist/inspiredesign/visual-evidence.d.ts.map +1 -1
  124. package/dist/{inspiredesign-IPVZDLSQ.js → inspiredesign-GZIEXETS.js} +101 -31
  125. package/dist/inspiredesign-GZIEXETS.js.map +1 -0
  126. package/dist/{launch-B35YDRQC.js → launch-I7WNLWLY.js} +8 -8
  127. package/dist/{list-YETWKTKY.js → list-BAECFJI7.js} +7 -7
  128. package/dist/{list-JV55JVGB.js → list-BCF4HZ2K.js} +7 -7
  129. package/dist/{macro-resolve-DQK4B3W3.js → macro-resolve-4GNZYHHW.js} +9 -9
  130. package/dist/{network-poll-4GWHCJXI.js → network-poll-DCZ5ZNLP.js} +8 -8
  131. package/dist/{new-XDCQPIEG.js → new-6KZYJTJG.js} +7 -7
  132. package/dist/{open-GIM3ZCSV.js → open-JPGEAJHJ.js} +7 -7
  133. package/dist/opendevbrowser.js +83 -23
  134. package/dist/opendevbrowser.js.map +1 -1
  135. package/dist/{perf-26VBXDPI.js → perf-5X367PRP.js} +8 -8
  136. package/dist/{pointer-down-O3VSNAXW.js → pointer-down-5OAUDDNR.js} +9 -9
  137. package/dist/{pointer-drag-WQ5QGE6J.js → pointer-drag-LIW5PY5P.js} +9 -9
  138. package/dist/{pointer-move-4N4D7JY2.js → pointer-move-7AMURLJD.js} +9 -9
  139. package/dist/{pointer-up-CQC4NPDX.js → pointer-up-EY652YWL.js} +9 -9
  140. package/dist/{press-XGJD45CU.js → press-UIAE5XEF.js} +8 -8
  141. package/dist/{product-video-HD4ZOUI7.js → product-video-B6TLS7VC.js} +10 -10
  142. package/dist/providers/browser-native-discovery.d.ts.map +1 -1
  143. package/dist/providers/browser-output-artifacts.d.ts +13 -0
  144. package/dist/providers/browser-output-artifacts.d.ts.map +1 -0
  145. package/dist/providers/renderer.d.ts +10 -1
  146. package/dist/providers/renderer.d.ts.map +1 -1
  147. package/dist/providers/workflows.d.ts +53 -2
  148. package/dist/providers/workflows.d.ts.map +1 -1
  149. package/dist/{providers-KKNPJSQK.js → providers-AERTX6X4.js} +5 -3
  150. package/dist/public-surface/generated-manifest.d.ts +4 -4
  151. package/dist/public-surface/generated-manifest.d.ts.map +1 -1
  152. package/dist/public-surface/source.d.ts +2 -2
  153. package/dist/public-surface/source.d.ts.map +1 -1
  154. package/dist/{research-VUWWEQ4R.js → research-AJH6ECYW.js} +10 -10
  155. package/dist/{review-LZ3TA7U7.js → review-RN6XF2YB.js} +9 -9
  156. package/dist/{review-desktop-LAO7U7T3.js → review-desktop-UJOUS7K2.js} +9 -9
  157. package/dist/{rpc-HKNIVFGC.js → rpc-VS5Y5FUT.js} +8 -8
  158. package/dist/{run-SHCF53FO.js → run-EVRIQW7S.js} +6 -6
  159. package/dist/{screencast-start-JHMQZVWJ.js → screencast-start-U6J4FYU4.js} +8 -8
  160. package/dist/{screencast-stop-RWQTWWQS.js → screencast-stop-EQUPRGMP.js} +8 -8
  161. package/dist/{screenshot-QHFYO6PB.js → screenshot-BENYGC36.js} +8 -8
  162. package/dist/{scroll-L3FTMAV4.js → scroll-3OALQLX2.js} +8 -8
  163. package/dist/{scroll-into-view-JVDHX4WU.js → scroll-into-view-SNZKBIVB.js} +8 -8
  164. package/dist/{select-X4BO7GTB.js → select-JDZDDC3Y.js} +8 -8
  165. package/dist/{serve-JIMIBCNO.js → serve-LOC6ESJ4.js} +7 -7
  166. package/dist/{shopping-EGSDP2GL.js → shopping-267OAYGM.js} +10 -10
  167. package/dist/{snapshot-QGJ7RDNV.js → snapshot-ASYI5UFR.js} +8 -8
  168. package/dist/{status-CKGPNYIH.js → status-47CI4LJX.js} +7 -7
  169. package/dist/{status-LEBY2X7N.js → status-N4O6DJTF.js} +9 -9
  170. package/dist/{status-capabilities-6QTWNGKM.js → status-capabilities-C777JZG4.js} +9 -9
  171. package/dist/{text-VUZU7D3L.js → text-MS2653MW.js} +8 -8
  172. package/dist/tools/inspiredesign_run.d.ts.map +1 -1
  173. package/dist/tools/product_video_run.d.ts.map +1 -1
  174. package/dist/{type-N5SURP74.js → type-UMPSDACC.js} +8 -8
  175. package/dist/{uncheck-JFMK3SSY.js → uncheck-2OZ56D42.js} +8 -8
  176. package/dist/{upload-KFUYLL7M.js → upload-CD7PRH54.js} +8 -8
  177. package/dist/{use-CNMPP2ED.js → use-MO67AGG7.js} +7 -7
  178. package/dist/{value-J335MPZE.js → value-4GI2LRUY.js} +8 -8
  179. package/dist/{visible-YQZWWPBZ.js → visible-VSUFGRFZ.js} +8 -8
  180. package/dist/{wait-IC7YJJPJ.js → wait-OQYMFENT.js} +8 -8
  181. package/dist/{windows-AGVQ3KX3.js → windows-75W2JCW7.js} +9 -9
  182. package/extension/manifest.json +1 -1
  183. package/package.json +1 -1
  184. package/skills/opendevbrowser-best-practices/SKILL.md +41 -30
  185. package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +12 -8
  186. package/skills/opendevbrowser-best-practices/artifacts/parity-gates.md +1 -0
  187. package/skills/opendevbrowser-best-practices/artifacts/provider-workflows.md +19 -0
  188. package/skills/opendevbrowser-best-practices/assets/templates/mode-flag-matrix.json +23 -13
  189. package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +3 -1
  190. package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +62 -21
  191. package/skills/opendevbrowser-best-practices/scripts/resolve-odb-cli.sh +28 -0
  192. package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +15 -0
  193. package/skills/opendevbrowser-best-practices/scripts/validator-fixture-cli.sh +13 -0
  194. package/skills/opendevbrowser-design-agent/SKILL.md +2 -0
  195. package/skills/opendevbrowser-design-agent/artifacts/design-workflows.md +15 -13
  196. package/skills/opendevbrowser-design-agent/artifacts/isolated-preview-validation.md +1 -1
  197. package/skills/opendevbrowser-design-agent/artifacts/research-harvest-workflow.md +14 -7
  198. package/skills/opendevbrowser-design-agent/assets/templates/reference-pattern-board.v1.json +1 -0
  199. package/skills/opendevbrowser-design-agent/scripts/design-workflow.sh +10 -7
  200. package/skills/opendevbrowser-motion-design/SKILL.md +1 -1
  201. package/skills/opendevbrowser-product-presentation-asset/SKILL.md +5 -4
  202. package/skills/opendevbrowser-product-presentation-asset/scripts/capture-screenshots.sh +1 -0
  203. package/skills/opendevbrowser-product-presentation-asset/scripts/collect-product.sh +1 -0
  204. package/skills/opendevbrowser-product-presentation-asset/scripts/download-images.sh +1 -0
  205. package/skills/opendevbrowser-product-presentation-asset/scripts/validate-skill-assets.sh +4 -0
  206. package/skills/opendevbrowser-product-presentation-asset/scripts/write-manifest.sh +1 -0
  207. package/skills/opendevbrowser-research/SKILL.md +1 -0
  208. package/skills/opendevbrowser-research/scripts/render-output.sh +1 -0
  209. package/skills/opendevbrowser-research/scripts/run-research.sh +1 -0
  210. package/skills/opendevbrowser-research/scripts/validate-skill-assets.sh +4 -0
  211. package/skills/opendevbrowser-research/scripts/write-artifacts.sh +1 -0
  212. package/skills/opendevbrowser-shopping/SKILL.md +1 -0
  213. package/skills/opendevbrowser-shopping/scripts/normalize-offers.sh +1 -0
  214. package/skills/opendevbrowser-shopping/scripts/run-deal-hunt.sh +1 -0
  215. package/skills/opendevbrowser-shopping/scripts/run-shopping.sh +1 -0
  216. package/skills/opendevbrowser-shopping/scripts/validate-skill-assets.sh +4 -0
  217. package/dist/chunk-27W46IKI.js.map +0 -1
  218. package/dist/chunk-EOX6U6Q4.js.map +0 -1
  219. package/dist/chunk-FBKPDILE.js.map +0 -1
  220. package/dist/chunk-HMRANSDX.js.map +0 -1
  221. package/dist/chunk-IBIHDGTZ.js.map +0 -1
  222. package/dist/chunk-SKFB5ICF.js.map +0 -1
  223. package/dist/chunk-ZGCTC5YM.js.map +0 -1
  224. package/dist/inspiredesign-IPVZDLSQ.js.map +0 -1
  225. /package/dist/{accessibility-snapshot-JSPFVWZ6.js.map → accessibility-snapshot-TAFPVLZN.js.map} +0 -0
  226. /package/dist/{active-window-2OB2MSCR.js.map → active-window-MHFMC6NQ.js.map} +0 -0
  227. /package/dist/{annotate-VDZBZBKZ.js.map → annotate-5ZFRFQ4B.js.map} +0 -0
  228. /package/dist/{attr-7XIO4MCH.js.map → attr-MBF2UCRF.js.map} +0 -0
  229. /package/dist/{canvas-N4PAA274.js.map → canvas-CAMD22YU.js.map} +0 -0
  230. /package/dist/{capture-desktop-T5YO3EBI.js.map → capture-desktop-TMZSFA5R.js.map} +0 -0
  231. /package/dist/{capture-window-UKEUBWKH.js.map → capture-window-NZDKD2AE.js.map} +0 -0
  232. /package/dist/{check-PQB6KKMN.js.map → check-MO33GTQ4.js.map} +0 -0
  233. /package/dist/{checked-RNZIMCU6.js.map → checked-3HDF5X2M.js.map} +0 -0
  234. /package/dist/{chunk-YRRRUGSQ.js.map → chunk-32ZSOZND.js.map} +0 -0
  235. /package/dist/{chunk-FDBUB7BM.js.map → chunk-BHZLEFXW.js.map} +0 -0
  236. /package/dist/{chunk-JROW6ZNN.js.map → chunk-FJZY3Z3X.js.map} +0 -0
  237. /package/dist/{chunk-J3KYGJRQ.js.map → chunk-G6NQ7WYD.js.map} +0 -0
  238. /package/dist/{chunk-52ZIOWVU.js.map → chunk-UEAXTWGT.js.map} +0 -0
  239. /package/dist/{chunk-W6YPVNDX.js.map → chunk-VTGG5ZU2.js.map} +0 -0
  240. /package/dist/{chunk-NURQB55J.js.map → chunk-WY72GYAH.js.map} +0 -0
  241. /package/dist/{click-U7ZFKSB4.js.map → click-SWZPJO2U.js.map} +0 -0
  242. /package/dist/{clone-component-SWYAORTU.js.map → clone-component-YTB46YU4.js.map} +0 -0
  243. /package/dist/{clone-page-WJ6UJOJG.js.map → clone-page-5FMPHQ3A.js.map} +0 -0
  244. /package/dist/{close-NAVIHZ2T.js.map → close-22SNMDX3.js.map} +0 -0
  245. /package/dist/{close-VKIGIKVT.js.map → close-ORQZCZ2E.js.map} +0 -0
  246. /package/dist/{connect-XVG2MOZL.js.map → connect-EWYITNQU.js.map} +0 -0
  247. /package/dist/{console-poll-XI5BZPL7.js.map → console-poll-LJR6ZTDK.js.map} +0 -0
  248. /package/dist/{cookie-import-QELKE7TK.js.map → cookie-import-PTAIWPEC.js.map} +0 -0
  249. /package/dist/{cookie-list-QDA6KWIY.js.map → cookie-list-76C35B5B.js.map} +0 -0
  250. /package/dist/{daemon-CA4UIIZQ.js.map → daemon-UKJMDLCB.js.map} +0 -0
  251. /package/dist/{debug-trace-snapshot-AT4GAO57.js.map → debug-trace-snapshot-PQ5FJART.js.map} +0 -0
  252. /package/dist/{dialog-O3V2IBFH.js.map → dialog-WLJDWJV4.js.map} +0 -0
  253. /package/dist/{disconnect-NAX5TPTG.js.map → disconnect-FNB4JC2U.js.map} +0 -0
  254. /package/dist/{enabled-VT4FJXDX.js.map → enabled-PYMCOQPC.js.map} +0 -0
  255. /package/dist/{goto-GBJG5NC4.js.map → goto-UNTEW4VI.js.map} +0 -0
  256. /package/dist/{hover-476ZNQZE.js.map → hover-ZWY4YOM4.js.map} +0 -0
  257. /package/dist/{html-5C4TXOV3.js.map → html-M46YBFT3.js.map} +0 -0
  258. /package/dist/{inspector-73ARPCIV.js.map → inspector-6YAOI74U.js.map} +0 -0
  259. /package/dist/{inspector-audit-QT6QY7KS.js.map → inspector-audit-PF64X6SJ.js.map} +0 -0
  260. /package/dist/{inspector-plan-JRNSGN2Z.js.map → inspector-plan-IUGTQV3Q.js.map} +0 -0
  261. /package/dist/{launch-B35YDRQC.js.map → launch-I7WNLWLY.js.map} +0 -0
  262. /package/dist/{list-YETWKTKY.js.map → list-BAECFJI7.js.map} +0 -0
  263. /package/dist/{list-JV55JVGB.js.map → list-BCF4HZ2K.js.map} +0 -0
  264. /package/dist/{macro-resolve-DQK4B3W3.js.map → macro-resolve-4GNZYHHW.js.map} +0 -0
  265. /package/dist/{network-poll-4GWHCJXI.js.map → network-poll-DCZ5ZNLP.js.map} +0 -0
  266. /package/dist/{new-XDCQPIEG.js.map → new-6KZYJTJG.js.map} +0 -0
  267. /package/dist/{open-GIM3ZCSV.js.map → open-JPGEAJHJ.js.map} +0 -0
  268. /package/dist/{perf-26VBXDPI.js.map → perf-5X367PRP.js.map} +0 -0
  269. /package/dist/{pointer-down-O3VSNAXW.js.map → pointer-down-5OAUDDNR.js.map} +0 -0
  270. /package/dist/{pointer-drag-WQ5QGE6J.js.map → pointer-drag-LIW5PY5P.js.map} +0 -0
  271. /package/dist/{pointer-move-4N4D7JY2.js.map → pointer-move-7AMURLJD.js.map} +0 -0
  272. /package/dist/{pointer-up-CQC4NPDX.js.map → pointer-up-EY652YWL.js.map} +0 -0
  273. /package/dist/{press-XGJD45CU.js.map → press-UIAE5XEF.js.map} +0 -0
  274. /package/dist/{product-video-HD4ZOUI7.js.map → product-video-B6TLS7VC.js.map} +0 -0
  275. /package/dist/{providers-KKNPJSQK.js.map → providers-AERTX6X4.js.map} +0 -0
  276. /package/dist/{research-VUWWEQ4R.js.map → research-AJH6ECYW.js.map} +0 -0
  277. /package/dist/{review-LZ3TA7U7.js.map → review-RN6XF2YB.js.map} +0 -0
  278. /package/dist/{review-desktop-LAO7U7T3.js.map → review-desktop-UJOUS7K2.js.map} +0 -0
  279. /package/dist/{rpc-HKNIVFGC.js.map → rpc-VS5Y5FUT.js.map} +0 -0
  280. /package/dist/{run-SHCF53FO.js.map → run-EVRIQW7S.js.map} +0 -0
  281. /package/dist/{screencast-start-JHMQZVWJ.js.map → screencast-start-U6J4FYU4.js.map} +0 -0
  282. /package/dist/{screencast-stop-RWQTWWQS.js.map → screencast-stop-EQUPRGMP.js.map} +0 -0
  283. /package/dist/{screenshot-QHFYO6PB.js.map → screenshot-BENYGC36.js.map} +0 -0
  284. /package/dist/{scroll-L3FTMAV4.js.map → scroll-3OALQLX2.js.map} +0 -0
  285. /package/dist/{scroll-into-view-JVDHX4WU.js.map → scroll-into-view-SNZKBIVB.js.map} +0 -0
  286. /package/dist/{select-X4BO7GTB.js.map → select-JDZDDC3Y.js.map} +0 -0
  287. /package/dist/{serve-JIMIBCNO.js.map → serve-LOC6ESJ4.js.map} +0 -0
  288. /package/dist/{shopping-EGSDP2GL.js.map → shopping-267OAYGM.js.map} +0 -0
  289. /package/dist/{snapshot-QGJ7RDNV.js.map → snapshot-ASYI5UFR.js.map} +0 -0
  290. /package/dist/{status-CKGPNYIH.js.map → status-47CI4LJX.js.map} +0 -0
  291. /package/dist/{status-LEBY2X7N.js.map → status-N4O6DJTF.js.map} +0 -0
  292. /package/dist/{status-capabilities-6QTWNGKM.js.map → status-capabilities-C777JZG4.js.map} +0 -0
  293. /package/dist/{text-VUZU7D3L.js.map → text-MS2653MW.js.map} +0 -0
  294. /package/dist/{type-N5SURP74.js.map → type-UMPSDACC.js.map} +0 -0
  295. /package/dist/{uncheck-JFMK3SSY.js.map → uncheck-2OZ56D42.js.map} +0 -0
  296. /package/dist/{upload-KFUYLL7M.js.map → upload-CD7PRH54.js.map} +0 -0
  297. /package/dist/{use-CNMPP2ED.js.map → use-MO67AGG7.js.map} +0 -0
  298. /package/dist/{value-J335MPZE.js.map → value-4GI2LRUY.js.map} +0 -0
  299. /package/dist/{visible-YQZWWPBZ.js.map → visible-VSUFGRFZ.js.map} +0 -0
  300. /package/dist/{wait-IC7YJJPJ.js.map → wait-OQYMFENT.js.map} +0 -0
  301. /package/dist/{windows-AGVQ3KX3.js.map → windows-75W2JCW7.js.map} +0 -0
@@ -52,10 +52,13 @@ import {
52
52
  createDefaultRuntime,
53
53
  extractStructuredContent,
54
54
  inspectChallengePlanFromRuntime,
55
+ inspectPinterestPinMediaBuffer,
56
+ isPinterestPinMediaEvidenceContentType,
55
57
  resolveChallengeAutomationPolicy,
56
58
  resolveProviderRuntimePolicy,
59
+ resolveWorkflowArtifactRoot,
57
60
  toSnippet
58
- } from "./chunk-FBKPDILE.js";
61
+ } from "./chunk-WTWSBEBW.js";
59
62
  import {
60
63
  buildBlockerArtifacts,
61
64
  classifyBlockerSignal,
@@ -3662,9 +3665,10 @@ function createCoreRuntimeAssemblies(args2) {
3662
3665
  import { parse, resolve as resolve6 } from "path";
3663
3666
 
3664
3667
  // src/browser/browser-manager.ts
3665
- import { randomUUID as randomUUID10 } from "crypto";
3666
- import { access as access2, mkdir as mkdir5, rm as rm3, writeFile as writeFile3 } from "fs/promises";
3667
- import { join as join9 } from "path";
3668
+ import { randomUUID as randomUUID11 } from "crypto";
3669
+ import { constants as fsConstants } from "fs";
3670
+ import { access as access2, mkdir as mkdir5, open, rm as rm3, unlink, writeFile as writeFile3 } from "fs/promises";
3671
+ import { dirname as dirname2, join as join10 } from "path";
3668
3672
  import { freemem, totalmem } from "os";
3669
3673
  import { Mutex } from "async-mutex";
3670
3674
 
@@ -4952,6 +4956,28 @@ function sanitizeWsEndpoint(wsEndpoint) {
4952
4956
  }
4953
4957
  }
4954
4958
 
4959
+ // src/providers/browser-output-artifacts.ts
4960
+ import { randomUUID as randomUUID7 } from "crypto";
4961
+ import { mkdirSync as mkdirSync2 } from "fs";
4962
+ import { join as join7 } from "path";
4963
+ var BROWSER_SCREENSHOT_ARTIFACT_NAMESPACE = "screenshot";
4964
+ var BROWSER_SCREENCAST_ARTIFACT_NAMESPACE = "screencast";
4965
+ var SAFE_BROWSER_ARTIFACT_NAMESPACE_PATTERN = /^[a-z0-9_-]+$/;
4966
+ function createBrowserOutputArtifactDirectory(input) {
4967
+ const namespace = input.namespace.trim();
4968
+ if (namespace.length === 0) {
4969
+ throw new Error("Browser output artifact namespace cannot be empty.");
4970
+ }
4971
+ if (!SAFE_BROWSER_ARTIFACT_NAMESPACE_PATTERN.test(namespace)) {
4972
+ throw new Error("Browser output artifact namespace can only contain lowercase letters, numbers, underscores, and hyphens.");
4973
+ }
4974
+ const root = resolveWorkflowArtifactRoot(void 0, { workspaceRoot: input.workspaceRoot });
4975
+ const runId = randomUUID7();
4976
+ const artifactPath = join7(root, namespace, runId);
4977
+ mkdirSync2(artifactPath, { recursive: true, mode: 448 });
4978
+ return { artifactPath, namespace, runId };
4979
+ }
4980
+
4955
4981
  // src/browser/manager-types.ts
4956
4982
  var SCREENCAST_RETENTION_MS = 10 * 6e4;
4957
4983
 
@@ -5575,7 +5601,7 @@ var SessionStore = class {
5575
5601
  };
5576
5602
 
5577
5603
  // src/browser/target-manager.ts
5578
- import { randomUUID as randomUUID7 } from "crypto";
5604
+ import { randomUUID as randomUUID8 } from "crypto";
5579
5605
  var TARGET_INFO_TIMEOUT_MS = 2e3;
5580
5606
  var TargetManager = class {
5581
5607
  targets = /* @__PURE__ */ new Map();
@@ -5583,7 +5609,7 @@ var TargetManager = class {
5583
5609
  nameToTarget = /* @__PURE__ */ new Map();
5584
5610
  targetToName = /* @__PURE__ */ new Map();
5585
5611
  registerPage(page, name) {
5586
- const targetId = randomUUID7();
5612
+ const targetId = randomUUID8();
5587
5613
  this.targets.set(targetId, page);
5588
5614
  if (!this.activeTargetId) {
5589
5615
  this.activeTargetId = targetId;
@@ -5901,7 +5927,7 @@ import { execFileSync } from "child_process";
5901
5927
  import { createDecipheriv, createHash as createHash3, pbkdf2Sync } from "crypto";
5902
5928
  import { cp, mkdtemp as mkdtemp2, mkdir as mkdir3, rm as rm2, stat as stat3 } from "fs/promises";
5903
5929
  import { tmpdir } from "os";
5904
- import { dirname, join as join7 } from "path";
5930
+ import { dirname, join as join8 } from "path";
5905
5931
  var ROOT_COPY_ENTRIES = ["Local State"];
5906
5932
  var PROFILE_COPY_ENTRIES = [
5907
5933
  "Preferences",
@@ -5959,7 +5985,7 @@ async function stageSystemChromeProfile(source, stagingRoot) {
5959
5985
  let copiedCookieStore = false;
5960
5986
  for (const entry of ROOT_COPY_ENTRIES) {
5961
5987
  try {
5962
- await copyEntry(join7(source.userDataDir, entry), join7(stagingRoot, entry));
5988
+ await copyEntry(join8(source.userDataDir, entry), join8(stagingRoot, entry));
5963
5989
  } catch (error) {
5964
5990
  warnings.push(`Chrome bootstrap skipped ${entry}: ${getErrorMessage(error)}`);
5965
5991
  }
@@ -5967,8 +5993,8 @@ async function stageSystemChromeProfile(source, stagingRoot) {
5967
5993
  for (const entry of PROFILE_COPY_ENTRIES) {
5968
5994
  try {
5969
5995
  const copied = await copyEntry(
5970
- join7(source.profilePath, entry),
5971
- join7(stagingRoot, source.profileDirectory, entry)
5996
+ join8(source.profilePath, entry),
5997
+ join8(stagingRoot, source.profileDirectory, entry)
5972
5998
  );
5973
5999
  if (copied && COOKIE_STORE_ENTRY_SET.has(entry)) {
5974
6000
  copiedCookieStore = true;
@@ -6074,8 +6100,8 @@ async function loadSystemChromeCookiesFromSqlite(source, platform = process.plat
6074
6100
  return { cookies: [], warnings: [], attempted: false };
6075
6101
  }
6076
6102
  const cookieDbCandidates = [
6077
- join7(source.profilePath, "Cookies"),
6078
- join7(source.profilePath, "Network", "Cookies")
6103
+ join8(source.profilePath, "Cookies"),
6104
+ join8(source.profilePath, "Network", "Cookies")
6079
6105
  ];
6080
6106
  const cookieDbPath = await firstExistingPath(cookieDbCandidates);
6081
6107
  if (!cookieDbPath) {
@@ -6145,7 +6171,7 @@ async function loadSystemChromeCookies(executablePath) {
6145
6171
  warnings: direct.warnings
6146
6172
  };
6147
6173
  }
6148
- const stagingRoot = await mkdtemp2(join7(tmpdir(), "opendevbrowser-chrome-cookie-bootstrap-"));
6174
+ const stagingRoot = await mkdtemp2(join8(tmpdir(), "opendevbrowser-chrome-cookie-bootstrap-"));
6149
6175
  try {
6150
6176
  const staged = await stageSystemChromeProfile(source, stagingRoot);
6151
6177
  if (!staged.copiedCookieStore) {
@@ -6203,7 +6229,7 @@ function getErrorMessage(error) {
6203
6229
  }
6204
6230
 
6205
6231
  // src/browser/global-challenge-coordinator.ts
6206
- import { randomUUID as randomUUID8 } from "crypto";
6232
+ import { randomUUID as randomUUID9 } from "crypto";
6207
6233
  var PRESERVE_WINDOW_MS = 15 * 60 * 1e3;
6208
6234
  var VERIFY_WINDOW_MS = 5 * 60 * 1e3;
6209
6235
  var toIso = (value) => value.toISOString();
@@ -6225,7 +6251,7 @@ var GlobalChallengeCoordinator = class {
6225
6251
  claimOrRefresh(args2) {
6226
6252
  const now = args2.now ?? /* @__PURE__ */ new Date();
6227
6253
  const existing = this.bySessionId.get(args2.sessionId);
6228
- const challengeId = existing?.summary.challengeId ?? randomUUID8();
6254
+ const challengeId = existing?.summary.challengeId ?? randomUUID9();
6229
6255
  const previousTimeline = existing?.timeline ?? [];
6230
6256
  const nextEntry = {
6231
6257
  at: toIso(now),
@@ -6317,8 +6343,8 @@ var GlobalChallengeCoordinator = class {
6317
6343
 
6318
6344
  // src/browser/screencast-recorder.ts
6319
6345
  import { copyFile, mkdir as mkdir4, readdir, writeFile as writeFile2 } from "fs/promises";
6320
- import { randomUUID as randomUUID9 } from "crypto";
6321
- import { isAbsolute as isAbsolute2, join as join8, resolve } from "path";
6346
+ import { randomUUID as randomUUID10 } from "crypto";
6347
+ import { isAbsolute as isAbsolute2, join as join9, resolve } from "path";
6322
6348
  var DEFAULT_SCREENCAST_INTERVAL_MS = 1e3;
6323
6349
  var MIN_SCREENCAST_INTERVAL_MS = 250;
6324
6350
  var DEFAULT_SCREENCAST_MAX_FRAMES = 300;
@@ -6365,12 +6391,16 @@ async function ensureEmptyDirectory(path4) {
6365
6391
  }
6366
6392
  await mkdir4(path4, { recursive: true });
6367
6393
  }
6368
- function resolveOutputDir(worktree, sessionId, screencastId, outputDir) {
6394
+ function resolveOutputDir(worktree, outputDir) {
6369
6395
  if (typeof outputDir === "string" && outputDir.trim().length > 0) {
6370
6396
  const trimmed = outputDir.trim();
6371
- return isAbsolute2(trimmed) ? trimmed : resolve(worktree, trimmed);
6397
+ return { outputDir: isAbsolute2(trimmed) ? trimmed : resolve(worktree, trimmed) };
6372
6398
  }
6373
- return join8(worktree, ".opendevbrowser", "replays", "screencasts", sessionId, screencastId);
6399
+ const artifact = createBrowserOutputArtifactDirectory({
6400
+ workspaceRoot: worktree,
6401
+ namespace: BROWSER_SCREENCAST_ARTIFACT_NAMESPACE
6402
+ });
6403
+ return { outputDir: artifact.artifactPath, artifactPath: artifact.artifactPath };
6374
6404
  }
6375
6405
  function renderReplayHtml(manifest) {
6376
6406
  const encodedManifest = JSON.stringify(manifest).replaceAll("<", "\\u003c");
@@ -6470,6 +6500,7 @@ var BrowserScreencastRecorder = class {
6470
6500
  sessionId;
6471
6501
  targetId;
6472
6502
  outputDir;
6503
+ artifactPath;
6473
6504
  startedAt;
6474
6505
  intervalMs;
6475
6506
  maxFrames;
@@ -6490,18 +6521,20 @@ var BrowserScreencastRecorder = class {
6490
6521
  finalPage;
6491
6522
  frames = [];
6492
6523
  constructor(args2) {
6493
- this.screencastId = args2.screencastId ?? randomUUID9();
6524
+ this.screencastId = args2.screencastId ?? randomUUID10();
6494
6525
  this.sessionId = args2.sessionId;
6495
6526
  this.targetId = args2.targetId;
6496
- this.outputDir = resolveOutputDir(args2.worktree, args2.sessionId, this.screencastId, args2.options?.outputDir);
6527
+ const output = resolveOutputDir(args2.worktree, args2.options?.outputDir);
6528
+ this.outputDir = output.outputDir;
6529
+ this.artifactPath = output.artifactPath;
6497
6530
  this.intervalMs = resolveIntervalMs(args2.options?.intervalMs);
6498
6531
  this.maxFrames = resolveMaxFrames(args2.options?.maxFrames);
6499
6532
  this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
6500
6533
  this.startedAtMs = Date.parse(this.startedAt);
6501
- this.framesDir = join8(this.outputDir, FRAMES_DIRECTORY);
6502
- this.manifestPath = join8(this.outputDir, MANIFEST_FILENAME);
6503
- this.replayHtmlPath = join8(this.outputDir, REPLAY_FILENAME);
6504
- this.previewPath = join8(this.outputDir, PREVIEW_FILENAME);
6534
+ this.framesDir = join9(this.outputDir, FRAMES_DIRECTORY);
6535
+ this.manifestPath = join9(this.outputDir, MANIFEST_FILENAME);
6536
+ this.replayHtmlPath = join9(this.outputDir, REPLAY_FILENAME);
6537
+ this.previewPath = join9(this.outputDir, PREVIEW_FILENAME);
6505
6538
  this.captureFrameImpl = args2.captureFrame;
6506
6539
  this.completionPromise = new Promise((resolvePromise) => {
6507
6540
  this.resolveCompletion = resolvePromise;
@@ -6539,6 +6572,7 @@ var BrowserScreencastRecorder = class {
6539
6572
  sessionId: this.sessionId,
6540
6573
  targetId: this.targetId,
6541
6574
  outputDir: this.outputDir,
6575
+ ...this.artifactPath ? { artifact_path: this.artifactPath } : {},
6542
6576
  startedAt: this.startedAt,
6543
6577
  intervalMs: this.intervalMs,
6544
6578
  maxFrames: this.maxFrames,
@@ -6583,7 +6617,7 @@ var BrowserScreencastRecorder = class {
6583
6617
  async captureFrame() {
6584
6618
  const index = this.frames.length + 1;
6585
6619
  const frameFilename = `${String(index).padStart(6, "0")}.png`;
6586
- const framePath = join8(this.framesDir, frameFilename);
6620
+ const framePath = join9(this.framesDir, frameFilename);
6587
6621
  const task = Promise.resolve().then(async () => {
6588
6622
  const capturedAt = (/* @__PURE__ */ new Date()).toISOString();
6589
6623
  const result = await this.captureFrameImpl(framePath);
@@ -6599,7 +6633,7 @@ var BrowserScreencastRecorder = class {
6599
6633
  index,
6600
6634
  capturedAt,
6601
6635
  elapsedMs: Math.max(Date.parse(capturedAt) - this.startedAtMs, 0),
6602
- relativePath: normalizeRelativePath(join8(FRAMES_DIRECTORY, frameFilename))
6636
+ relativePath: normalizeRelativePath(join9(FRAMES_DIRECTORY, frameFilename))
6603
6637
  });
6604
6638
  if (this.frames.length === 1) {
6605
6639
  await copyFile(framePath, this.previewPath);
@@ -6664,6 +6698,7 @@ var BrowserScreencastRecorder = class {
6664
6698
  sessionId: this.sessionId,
6665
6699
  targetId: this.targetId,
6666
6700
  outputDir: this.outputDir,
6701
+ ...this.artifactPath ? { artifact_path: this.artifactPath } : {},
6667
6702
  startedAt: this.startedAt,
6668
6703
  endedAt,
6669
6704
  endedReason: reason,
@@ -6681,6 +6716,469 @@ var BrowserScreencastRecorder = class {
6681
6716
 
6682
6717
  // src/browser/browser-manager.ts
6683
6718
  var LEGACY_EXTENSION_OPERATION_TIMEOUT_MS = 5e3;
6719
+ var PINTEREST_PIN_MEDIA_DEFAULT_TIMEOUT_MS = 5e3;
6720
+ var PINTEREST_PIN_MEDIA_DOM_INSPECTION_MAX_TIMEOUT_MS = 1e4;
6721
+ var PINTEREST_PIN_MEDIA_CDP_SESSION_MAX_TIMEOUT_MS = 5e3;
6722
+ var PINTEREST_PIN_MEDIA_CDP_DETACH_MAX_TIMEOUT_MS = 1e3;
6723
+ var PINTEREST_PIN_MEDIA_FETCH_MAX_TIMEOUT_MS = 2e4;
6724
+ var PINTEREST_PIN_MEDIA_MAX_BYTES = 2e7;
6725
+ var PINTEREST_PIN_MEDIA_MAX_REDIRECTS = 3;
6726
+ var PINTEREST_PIN_MEDIA_MIN_EDGE_PX = 160;
6727
+ var PINTEREST_PIN_MEDIA_REJECTION_LIMIT = 12;
6728
+ var PINTEREST_PIN_IMAGE_MEDIA_HOST = "i.pinimg.com";
6729
+ var PINTEREST_PIN_VIDEO_MEDIA_HOST = "v.pinimg.com";
6730
+ var PINTEREST_PIN_VIDEO_MEDIA_HOST_PATTERN = /^v\d+(?:-[a-z]+)?\.pinimg\.com$/i;
6731
+ var PINTEREST_PIN_MEDIA_VIDEO_CONTENT_TYPE = "video/mp4";
6732
+ var PINTEREST_PIN_MEDIA_GENERIC_BINARY_CONTENT_TYPES = /* @__PURE__ */ new Set([
6733
+ "application/octet-stream",
6734
+ "application/x-binary",
6735
+ "binary/octet-stream"
6736
+ ]);
6737
+ var MP4_FILE_TYPE_BOX_MIN_BYTES = 12;
6738
+ var MP4_FILE_TYPE_BOX_MARKER_START = 4;
6739
+ var MP4_FILE_TYPE_BOX_MARKER_END = 8;
6740
+ var MP4_FILE_TYPE_BOX_MARKER = "ftyp";
6741
+ var HTTP_REDIRECT_STATUS_MIN = 300;
6742
+ var HTTP_REDIRECT_STATUS_MAX_EXCLUSIVE = 400;
6743
+ var PINTEREST_PIN_MEDIA_NOFOLLOW_FLAG = typeof fsConstants.O_NOFOLLOW === "number" ? fsConstants.O_NOFOLLOW : 0;
6744
+ var PINTEREST_PIN_MEDIA_OUTPUT_OPEN_FLAGS = fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | PINTEREST_PIN_MEDIA_NOFOLLOW_FLAG;
6745
+ function pinterestPinSourceChanged(pageUrl, extractedSourceUrl) {
6746
+ const pagePinId = extractPinterestPinId(pageUrl);
6747
+ const extractedPinId = extractPinterestPinId(extractedSourceUrl);
6748
+ return Boolean(pagePinId && extractedPinId && pagePinId !== extractedPinId);
6749
+ }
6750
+ function readAuthoritativePinterestSourceUrl(pageUrl, extractedSourceUrl) {
6751
+ return extractPinterestPinId(extractedSourceUrl) ? extractedSourceUrl : pageUrl;
6752
+ }
6753
+ function extractPinterestPinId(value) {
6754
+ if (!value) {
6755
+ return void 0;
6756
+ }
6757
+ const match = value.match(/\/pin\/(\d+)/i);
6758
+ return match?.[1];
6759
+ }
6760
+ function isFirstPartyPinterestMediaUrl(value) {
6761
+ if (!value) {
6762
+ return false;
6763
+ }
6764
+ try {
6765
+ const parsed = new URL(value);
6766
+ const hostname = parsed.hostname.toLowerCase();
6767
+ return parsed.protocol === "https:" && (hostname === PINTEREST_PIN_IMAGE_MEDIA_HOST || hostname === PINTEREST_PIN_VIDEO_MEDIA_HOST || PINTEREST_PIN_VIDEO_MEDIA_HOST_PATTERN.test(hostname));
6768
+ } catch {
6769
+ return false;
6770
+ }
6771
+ }
6772
+ function isFirstPartyPinterestVideoMediaUrl(value) {
6773
+ if (!value) {
6774
+ return false;
6775
+ }
6776
+ try {
6777
+ const parsed = new URL(value);
6778
+ const hostname = parsed.hostname.toLowerCase();
6779
+ return parsed.protocol === "https:" && parsed.pathname.toLowerCase().endsWith(".mp4") && (hostname === PINTEREST_PIN_VIDEO_MEDIA_HOST || PINTEREST_PIN_VIDEO_MEDIA_HOST_PATTERN.test(hostname));
6780
+ } catch {
6781
+ return false;
6782
+ }
6783
+ }
6784
+ function normalizePinterestResponseContentType(contentType) {
6785
+ const normalized = contentType?.split(";")[0]?.trim().toLowerCase();
6786
+ return normalized && normalized.length > 0 ? normalized : void 0;
6787
+ }
6788
+ function isLikelyMp4Bytes(bytes) {
6789
+ return bytes.length >= MP4_FILE_TYPE_BOX_MIN_BYTES && bytes.subarray(MP4_FILE_TYPE_BOX_MARKER_START, MP4_FILE_TYPE_BOX_MARKER_END).toString("ascii") === MP4_FILE_TYPE_BOX_MARKER;
6790
+ }
6791
+ function isCompatiblePinterestVideoContentType(contentType) {
6792
+ return !contentType || contentType === PINTEREST_PIN_MEDIA_VIDEO_CONTENT_TYPE || PINTEREST_PIN_MEDIA_GENERIC_BINARY_CONTENT_TYPES.has(contentType);
6793
+ }
6794
+ function isCompatiblePinterestImageContentType(contentType) {
6795
+ return !contentType || PINTEREST_PIN_MEDIA_GENERIC_BINARY_CONTENT_TYPES.has(contentType) || isPinterestPinMediaEvidenceContentType(contentType) && contentType.startsWith("image/");
6796
+ }
6797
+ function assertFetchedPinterestCandidateMatchesKind(candidate, fetched) {
6798
+ const contentType = normalizePinterestResponseContentType(fetched.contentType);
6799
+ if (candidate.kind === "video") {
6800
+ if (!isFirstPartyPinterestVideoMediaUrl(fetched.finalUrl)) {
6801
+ throw new Error("Pinterest pin media video fetch returned a non-MP4 final URL.");
6802
+ }
6803
+ if (!isCompatiblePinterestVideoContentType(contentType)) {
6804
+ throw new Error("Pinterest pin media video fetch returned non-MP4 content.");
6805
+ }
6806
+ if (!isLikelyMp4Bytes(fetched.bytes)) {
6807
+ throw new Error("Pinterest pin media video fetch returned bytes without an MP4 file type box.");
6808
+ }
6809
+ return;
6810
+ }
6811
+ if (!isCompatiblePinterestImageContentType(contentType)) {
6812
+ throw new Error("Pinterest pin media image fetch returned non-image content.");
6813
+ }
6814
+ const byteInspection = inspectPinterestPinMediaBuffer(fetched.bytes);
6815
+ if (!byteInspection.contentType?.startsWith("image/")) {
6816
+ throw new Error("Pinterest pin media image fetch returned bytes without an image signature.");
6817
+ }
6818
+ if (contentType && !PINTEREST_PIN_MEDIA_GENERIC_BINARY_CONTENT_TYPES.has(contentType) && contentType !== byteInspection.contentType) {
6819
+ throw new Error("Pinterest pin media image fetch returned bytes that do not match the response content type.");
6820
+ }
6821
+ }
6822
+ function pinterestCandidateArea(candidate) {
6823
+ const width = candidate.width ?? candidate.naturalWidth ?? candidate.rect?.width ?? 0;
6824
+ const height = candidate.height ?? candidate.naturalHeight ?? candidate.rect?.height ?? 0;
6825
+ return width * height;
6826
+ }
6827
+ function summarizeRejectedPinterestCandidate(candidate, reasons) {
6828
+ return {
6829
+ kind: candidate.kind,
6830
+ ...candidate.mediaUrl ? { mediaUrl: candidate.mediaUrl } : {},
6831
+ ...candidate.candidateSelector ? { candidateSelector: candidate.candidateSelector } : {},
6832
+ ...candidate.candidateRole ? { candidateRole: candidate.candidateRole } : {},
6833
+ ...candidate.alt ? { alt: candidate.alt } : {},
6834
+ ...candidate.width ? { width: candidate.width } : {},
6835
+ ...candidate.height ? { height: candidate.height } : {},
6836
+ ...candidate.rect ? { rect: candidate.rect } : {},
6837
+ ancestry: candidate.ancestry.slice(0, 6),
6838
+ reasons
6839
+ };
6840
+ }
6841
+ function rejectionReasonsForPinterestCandidate(candidate, sourcePinId) {
6842
+ const reasons = [];
6843
+ if (!isFirstPartyPinterestMediaUrl(candidate.mediaUrl)) {
6844
+ reasons.push("non_first_party_media_url");
6845
+ }
6846
+ if (!candidate.visible) {
6847
+ reasons.push("not_visible");
6848
+ }
6849
+ const width = candidate.width ?? candidate.naturalWidth ?? candidate.rect?.width ?? 0;
6850
+ const height = candidate.height ?? candidate.naturalHeight ?? candidate.rect?.height ?? 0;
6851
+ if (width < PINTEREST_PIN_MEDIA_MIN_EDGE_PX || height < PINTEREST_PIN_MEDIA_MIN_EDGE_PX) {
6852
+ reasons.push("media_too_small");
6853
+ }
6854
+ if (!sourcePinId) {
6855
+ reasons.push("missing_source_pin_id");
6856
+ }
6857
+ if (sourcePinId && candidate.linkedPinId && candidate.linkedPinId !== sourcePinId) {
6858
+ reasons.push("linked_to_different_pin");
6859
+ }
6860
+ if (sourcePinId && !candidate.linkedPinId && !candidate.insideCanonicalMainPinMediaContainer) {
6861
+ reasons.push("missing_pin_source_proof");
6862
+ }
6863
+ const noiseHasCanonicalSourceProof = Boolean(
6864
+ candidate.insideCanonicalMainPinMediaContainer && sourcePinId && (!candidate.linkedPinId || candidate.linkedPinId === sourcePinId)
6865
+ );
6866
+ if (candidate.noiseSignals.length > 0 && !noiseHasCanonicalSourceProof) {
6867
+ reasons.push(`noise_ancestry:${candidate.noiseSignals[0]}`);
6868
+ }
6869
+ return reasons;
6870
+ }
6871
+ function selectPinterestPinMediaCandidate(extraction, pageUrl) {
6872
+ const sourcePinId = extractPinterestPinId(pageUrl);
6873
+ const accepted = [];
6874
+ const rejected = [];
6875
+ for (const candidate of extraction.candidates) {
6876
+ const reasons = rejectionReasonsForPinterestCandidate(candidate, sourcePinId);
6877
+ if (reasons.length === 0) {
6878
+ accepted.push(candidate);
6879
+ } else if (rejected.length < PINTEREST_PIN_MEDIA_REJECTION_LIMIT) {
6880
+ rejected.push(summarizeRejectedPinterestCandidate(candidate, reasons));
6881
+ }
6882
+ }
6883
+ accepted.sort((left, right) => {
6884
+ const scoreDelta = right.score - left.score;
6885
+ return scoreDelta !== 0 ? scoreDelta : pinterestCandidateArea(right) - pinterestCandidateArea(left);
6886
+ });
6887
+ return { selected: accepted[0], acceptedCandidates: accepted, rejectedCandidates: rejected };
6888
+ }
6889
+ function warningsForSelectedPinterestCandidate(candidate) {
6890
+ const warnings = /* @__PURE__ */ new Set();
6891
+ for (const signal of candidate.noiseSignals) {
6892
+ warnings.add(signal === "shopping" ? "pin_media_noise:ad_shopping" : `pin_media_noise:${signal}`);
6893
+ }
6894
+ return Array.from(warnings);
6895
+ }
6896
+ function pinterestCandidateCaptureFailureReason(error) {
6897
+ if (error instanceof Error && error.name === "AbortError") return "selected_candidate_fetch_failed:aborted";
6898
+ return "selected_candidate_fetch_failed";
6899
+ }
6900
+ function clampPinterestPinMediaOperationTimeout(timeoutMs, maxTimeoutMs) {
6901
+ if (!Number.isFinite(timeoutMs)) {
6902
+ return maxTimeoutMs;
6903
+ }
6904
+ return Math.max(1, Math.min(timeoutMs, maxTimeoutMs));
6905
+ }
6906
+ function isPinterestPinMediaDomInspectionTimeout(error) {
6907
+ return error instanceof Error && error.message.startsWith("Pinterest pin media DOM inspection timed out");
6908
+ }
6909
+ function parsePinterestPinMediaCdpExtraction(result) {
6910
+ if (result.exceptionDetails) {
6911
+ const detail = result.exceptionDetails.exception?.description ?? result.exceptionDetails.text;
6912
+ throw new Error(detail ?? "Pinterest pin media CDP inspection failed.");
6913
+ }
6914
+ const value = result.result?.value;
6915
+ if (!value || typeof value.sourceUrl !== "string" || !Array.isArray(value.candidates)) {
6916
+ throw new Error("Pinterest pin media CDP inspection returned an invalid result.");
6917
+ }
6918
+ return value;
6919
+ }
6920
+ async function withPinterestPinMediaOperationTimeout(operation, timeoutMs, message) {
6921
+ let timer = null;
6922
+ try {
6923
+ return await Promise.race([
6924
+ operation,
6925
+ new Promise((_resolve, reject) => {
6926
+ timer = setTimeout(() => reject(new Error(message)), timeoutMs);
6927
+ })
6928
+ ]);
6929
+ } finally {
6930
+ if (timer) {
6931
+ clearTimeout(timer);
6932
+ }
6933
+ }
6934
+ }
6935
+ function detachPinterestPinMediaCdpSession(session) {
6936
+ void withPinterestPinMediaOperationTimeout(
6937
+ session.detach(),
6938
+ PINTEREST_PIN_MEDIA_CDP_DETACH_MAX_TIMEOUT_MS,
6939
+ `Pinterest pin media CDP session detach timed out after ${PINTEREST_PIN_MEDIA_CDP_DETACH_MAX_TIMEOUT_MS}ms.`
6940
+ ).catch(() => void 0);
6941
+ }
6942
+ function readPinterestPinMediaCandidatesInPage() {
6943
+ const maxCandidates = 30;
6944
+ const ancestryLimit = 6;
6945
+ const selectors = [
6946
+ "img.closeup-image-main-MainPinImage",
6947
+ "img[class*='closeup-image-main-MainPinImage']",
6948
+ "img[elementtiming='closeup-image-main-MainPinImage']",
6949
+ "img.StoryPinImageBlock-MainPinImage",
6950
+ "img[class*='StoryPinImageBlock-MainPinImage']",
6951
+ "[data-test-id='closeup-image-main'] img",
6952
+ "[data-test-id='closeup-image'] img",
6953
+ "[id^='closeup-image-container-'] img",
6954
+ "[class*='closeup-image-main-MainPinImage'] img",
6955
+ "[class*='StoryPinImageBlock-MainPinImage'] img",
6956
+ "video",
6957
+ "video[poster]",
6958
+ "[data-test-id*='pin'] video",
6959
+ "[data-test-id*='pin'] video[poster]",
6960
+ "[data-test-id*='closeup'] video",
6961
+ "[data-test-id*='closeup'] video[poster]"
6962
+ ];
6963
+ const elements = [];
6964
+ const seen = /* @__PURE__ */ new Set();
6965
+ for (const selector of selectors) {
6966
+ for (const element of Array.from(document.querySelectorAll(selector))) {
6967
+ if (!seen.has(element) && elements.length < maxCandidates) {
6968
+ seen.add(element);
6969
+ elements.push(element);
6970
+ }
6971
+ }
6972
+ }
6973
+ const describeElement = (element) => {
6974
+ const tag = element.tagName.toLowerCase();
6975
+ const id2 = element.id ? `#${element.id.slice(0, 48)}` : "";
6976
+ const classes = Array.from(element.classList).slice(0, 4).map((value) => `.${value.slice(0, 48)}`).join("");
6977
+ const testId = element.getAttribute("data-test-id");
6978
+ const role = element.getAttribute("role");
6979
+ return [tag + id2 + classes, testId ? `data-test-id=${testId.slice(0, 80)}` : "", role ? `role=${role}` : ""].filter(Boolean).join(" ");
6980
+ };
6981
+ const ancestryFor = (element) => {
6982
+ const ancestry = [];
6983
+ let current = element;
6984
+ while (current && ancestry.length < ancestryLimit) {
6985
+ ancestry.push(describeElement(current));
6986
+ current = current.parentElement;
6987
+ }
6988
+ return { ancestry, combined: ancestry.join(" ").toLowerCase() };
6989
+ };
6990
+ const readPinId = (element) => {
6991
+ const link = element.closest("a[href*='/pin/']");
6992
+ const href = link?.getAttribute("href") ?? "";
6993
+ const match = href.match(/\/pin\/(\d+)/i);
6994
+ return match?.[1];
6995
+ };
6996
+ const isInsideCanonicalMainPinMediaContainer = (element) => {
6997
+ const container = element.closest([
6998
+ "[data-test-id='pin-closeup']",
6999
+ "[data-test-id='story-pin']",
7000
+ "[data-test-id='closeup-layout']",
7001
+ "[data-test-id='closeup-image']",
7002
+ "[data-test-id='closeup-image-main']",
7003
+ "[data-test-id='pdp-container']",
7004
+ "[data-test-id='pin-closeup-image']",
7005
+ "[data-test-id='pin-closeup-image-container']",
7006
+ "[data-test-id='visual-content-container']"
7007
+ ].join(","));
7008
+ if (!container) {
7009
+ return false;
7010
+ }
7011
+ let current = element;
7012
+ while (current && current !== container) {
7013
+ if (readNoiseSignals(describeElement(current).toLowerCase()).length > 0) {
7014
+ return false;
7015
+ }
7016
+ current = current.parentElement;
7017
+ }
7018
+ return true;
7019
+ };
7020
+ const hasDelimitedNoiseToken = (combined, token) => new RegExp(`(^|[^a-z0-9])${token}($|[^a-z0-9])`).test(combined);
7021
+ const readNoiseSignals = (combined) => {
7022
+ const signals = [];
7023
+ const checks = [
7024
+ [(value) => value.includes("related"), "related"],
7025
+ [(value) => value.includes("recommend"), "recommendation"],
7026
+ [(value) => value.includes("rail"), "rail"],
7027
+ [(value) => value.includes("carousel"), "carousel"],
7028
+ [(value) => value.includes("grid"), "grid"],
7029
+ [(value) => value.includes("search"), "search"],
7030
+ [(value) => value.includes("avatar"), "avatar"],
7031
+ [(value) => value.includes("profile"), "profile"],
7032
+ [(value) => value.includes("comment"), "comment"],
7033
+ [(value) => hasDelimitedNoiseToken(value, "ad") || hasDelimitedNoiseToken(value, "ads"), "ad"],
7034
+ [(value) => value.includes("promoted"), "ad"],
7035
+ [(value) => value.includes("sponsor"), "ad"],
7036
+ [(value) => value.includes("shopping"), "shopping"],
7037
+ [(value) => value.includes("shop"), "shopping"],
7038
+ [(value) => value.includes("thumbnail"), "thumbnail"],
7039
+ [(value) => value.includes("thumb"), "thumbnail"]
7040
+ ];
7041
+ for (const [matches, signal] of checks) {
7042
+ if (matches(combined) && !signals.includes(signal)) {
7043
+ signals.push(signal);
7044
+ }
7045
+ }
7046
+ return signals;
7047
+ };
7048
+ const readRect = (element) => {
7049
+ const rect = element.getBoundingClientRect();
7050
+ return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
7051
+ };
7052
+ const isVisible2 = (element, rect) => {
7053
+ const style = window.getComputedStyle(element);
7054
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && rect.width > 0 && rect.height > 0;
7055
+ };
7056
+ const pickSrcsetUrl = (srcset) => {
7057
+ const entries = srcset.split(",").map((entry) => entry.trim()).filter(Boolean);
7058
+ const last2 = entries.at(-1);
7059
+ return last2?.split(/\s+/)[0];
7060
+ };
7061
+ const isFirstPartyPinterestVideoHost = (hostname) => hostname === "v.pinimg.com" || /^v\d+(?:-[a-z]+)?\.pinimg\.com$/i.test(hostname);
7062
+ const isFirstPartyPinterestVideoUrl = (value) => {
7063
+ if (!value) return false;
7064
+ try {
7065
+ const parsed = new URL(value);
7066
+ return parsed.protocol === "https:" && isFirstPartyPinterestVideoHost(parsed.hostname.toLowerCase()) && parsed.pathname.toLowerCase().endsWith(".mp4");
7067
+ } catch {
7068
+ return false;
7069
+ }
7070
+ };
7071
+ const derivePinterestMp4UrlFromHls = (value) => {
7072
+ if (!value) return void 0;
7073
+ try {
7074
+ const parsed = new URL(value);
7075
+ const hostname = parsed.hostname.toLowerCase();
7076
+ if (parsed.protocol !== "https:" || !isFirstPartyPinterestVideoHost(hostname)) {
7077
+ return void 0;
7078
+ }
7079
+ const match = parsed.pathname.match(/^\/videos\/([^/]+)\/hls\/([a-f0-9]{2})\/([a-f0-9]{2})\/([a-f0-9]{2})\/([a-f0-9]+)(?:_\d+w)?\.m3u8$/i);
7080
+ if (!match) return void 0;
7081
+ const [, lane, first, second, third, digest] = match;
7082
+ if (!lane || !first || !second || !third || !digest) return void 0;
7083
+ parsed.pathname = `/videos/${lane}/720p/${first}/${second}/${third}/${digest}.mp4`;
7084
+ parsed.search = "";
7085
+ parsed.hash = "";
7086
+ return parsed.toString();
7087
+ } catch {
7088
+ return void 0;
7089
+ }
7090
+ };
7091
+ const readPinterestVideoUrl = (value) => isFirstPartyPinterestVideoUrl(value) ? value : derivePinterestMp4UrlFromHls(value);
7092
+ const readVideoSourceUrl = (video) => {
7093
+ const candidateUrls = [video.currentSrc, video.src];
7094
+ for (const source of Array.from(video.querySelectorAll("source"))) {
7095
+ const sourceUrl = source.src || source.getAttribute("src");
7096
+ candidateUrls.push(sourceUrl ?? "");
7097
+ }
7098
+ const firstPartyDirectUrl = candidateUrls.map(readPinterestVideoUrl).find(Boolean);
7099
+ if (firstPartyDirectUrl) return firstPartyDirectUrl;
7100
+ return candidateUrls.find(Boolean);
7101
+ };
7102
+ const candidates = elements.flatMap((element) => {
7103
+ const tag = element.tagName.toLowerCase();
7104
+ const rect = readRect(element);
7105
+ const { ancestry, combined } = ancestryFor(element);
7106
+ const classText = (element.getAttribute("class") ?? "").toLowerCase();
7107
+ const positiveSignals = [
7108
+ classText.includes("closeup-image-main-mainpinimage") ? "closeup-image-main-MainPinImage" : "",
7109
+ element.getAttribute("elementtiming") === "closeup-image-main-MainPinImage" ? "closeup-image-main-MainPinImage" : "",
7110
+ classText.includes("storypinimageblock-mainpinimage") ? "StoryPinImageBlock-MainPinImage" : "",
7111
+ tag === "video" ? "video" : "",
7112
+ tag === "video" && element.hasAttribute("poster") ? "video[poster]" : ""
7113
+ ].filter(Boolean);
7114
+ if (tag === "video") {
7115
+ const video = element;
7116
+ const sharedVideoCandidate = {
7117
+ poster: video.poster || void 0,
7118
+ candidateRole: element.getAttribute("role") ?? element.closest("[role]")?.getAttribute("role") ?? void 0,
7119
+ width: video.videoWidth || rect.width,
7120
+ height: video.videoHeight || rect.height,
7121
+ rect,
7122
+ visible: isVisible2(element, rect),
7123
+ ancestry,
7124
+ linkedPinId: readPinId(element),
7125
+ noiseSignals: readNoiseSignals(combined),
7126
+ insideCanonicalMainPinMediaContainer: isInsideCanonicalMainPinMediaContainer(element)
7127
+ };
7128
+ const videoCandidates = [];
7129
+ const videoSourceUrl = readVideoSourceUrl(video);
7130
+ if (videoSourceUrl) {
7131
+ videoCandidates.push({
7132
+ ...sharedVideoCandidate,
7133
+ kind: "video",
7134
+ mediaUrl: videoSourceUrl,
7135
+ candidateSelector: "video",
7136
+ positiveSignals: [...positiveSignals, "video[source]"],
7137
+ score: positiveSignals.length * 100 + 250 + rect.width * rect.height / 1e4
7138
+ });
7139
+ }
7140
+ if (video.poster) {
7141
+ videoCandidates.push({
7142
+ ...sharedVideoCandidate,
7143
+ kind: "video_poster",
7144
+ mediaUrl: video.poster,
7145
+ candidateSelector: "video[poster]",
7146
+ positiveSignals,
7147
+ score: positiveSignals.length * 100 + rect.width * rect.height / 1e4
7148
+ });
7149
+ }
7150
+ return videoCandidates;
7151
+ }
7152
+ const image = tag === "img" ? element : element.querySelector("img");
7153
+ if (!image) {
7154
+ return [];
7155
+ }
7156
+ const imageRect = tag === "img" ? rect : readRect(image);
7157
+ const srcset = image.getAttribute("srcset") ?? void 0;
7158
+ const mediaUrl = image.currentSrc || image.src || pickSrcsetUrl(srcset ?? "");
7159
+ return [{
7160
+ kind: "image",
7161
+ mediaUrl,
7162
+ srcset,
7163
+ candidateSelector: positiveSignals[0] ?? describeElement(image),
7164
+ candidateRole: image.getAttribute("role") ?? image.closest("[role]")?.getAttribute("role") ?? void 0,
7165
+ alt: image.getAttribute("alt") ?? void 0,
7166
+ width: image.naturalWidth || imageRect.width,
7167
+ height: image.naturalHeight || imageRect.height,
7168
+ naturalWidth: image.naturalWidth || void 0,
7169
+ naturalHeight: image.naturalHeight || void 0,
7170
+ rect: imageRect,
7171
+ visible: isVisible2(image, imageRect),
7172
+ ancestry,
7173
+ linkedPinId: readPinId(image),
7174
+ positiveSignals,
7175
+ noiseSignals: readNoiseSignals(combined),
7176
+ insideCanonicalMainPinMediaContainer: isInsideCanonicalMainPinMediaContainer(image),
7177
+ score: positiveSignals.length * 100 + imageRect.width * imageRect.height / 1e4
7178
+ }];
7179
+ });
7180
+ return { sourceUrl: document.URL, candidates };
7181
+ }
6684
7182
  var DOM_GET_ATTR_DECLARATION = `
6685
7183
  function(name) {
6686
7184
  /* odb-dom-get-attr */
@@ -6884,6 +7382,104 @@ var DOM_FILE_INPUT_INFO_DECLARATION = `
6884
7382
  };
6885
7383
  }
6886
7384
  `;
7385
+ var assertPinterestPinMediaByteLimit = (byteLength) => {
7386
+ if (byteLength > PINTEREST_PIN_MEDIA_MAX_BYTES) {
7387
+ throw new Error(`Pinterest pin media fetch exceeded ${PINTEREST_PIN_MEDIA_MAX_BYTES} bytes.`);
7388
+ }
7389
+ };
7390
+ var readPinterestPinMediaContentLength = (headers) => {
7391
+ const value = headers.get("content-length");
7392
+ if (!value) return void 0;
7393
+ const parsed = Number(value);
7394
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
7395
+ };
7396
+ var isPinterestPinMediaRedirectStatus = (status) => status >= HTTP_REDIRECT_STATUS_MIN && status < HTTP_REDIRECT_STATUS_MAX_EXCLUSIVE;
7397
+ var readFirstPartyPinterestPinMediaRedirect = (baseUrl, location2) => {
7398
+ if (!location2) {
7399
+ throw new Error("Pinterest pin media fetch redirected without a location header.");
7400
+ }
7401
+ let redirectedUrl;
7402
+ try {
7403
+ redirectedUrl = new URL(location2, baseUrl).href;
7404
+ } catch {
7405
+ throw new Error("Pinterest pin media fetch redirected to an invalid media URL.");
7406
+ }
7407
+ if (!isFirstPartyPinterestMediaUrl(redirectedUrl)) {
7408
+ throw new Error("Pinterest pin media fetch redirected outside first-party media.");
7409
+ }
7410
+ return redirectedUrl;
7411
+ };
7412
+ var discardPinterestPinMediaResponseBody = async (response) => {
7413
+ await response.body?.cancel().catch(() => void 0);
7414
+ };
7415
+ var fetchPinterestPinMediaResponse = async (mediaUrl, signal) => {
7416
+ let nextUrl = mediaUrl;
7417
+ for (let redirectCount = 0; redirectCount <= PINTEREST_PIN_MEDIA_MAX_REDIRECTS; redirectCount += 1) {
7418
+ const response = await fetch(nextUrl, { signal, redirect: "manual" });
7419
+ if (!isPinterestPinMediaRedirectStatus(response.status)) {
7420
+ const finalUrl = response.url || nextUrl;
7421
+ if (!isFirstPartyPinterestMediaUrl(finalUrl)) {
7422
+ await discardPinterestPinMediaResponseBody(response);
7423
+ throw new Error("Pinterest pin media fetch redirected outside first-party media.");
7424
+ }
7425
+ return { response, finalUrl };
7426
+ }
7427
+ let redirectedUrl;
7428
+ try {
7429
+ redirectedUrl = readFirstPartyPinterestPinMediaRedirect(nextUrl, response.headers.get("location"));
7430
+ } catch (error) {
7431
+ await discardPinterestPinMediaResponseBody(response);
7432
+ throw error;
7433
+ }
7434
+ nextUrl = redirectedUrl;
7435
+ await discardPinterestPinMediaResponseBody(response);
7436
+ }
7437
+ throw new Error("Pinterest pin media fetch exceeded the first-party redirect limit.");
7438
+ };
7439
+ var readBoundedPinterestPinMediaBytes = async (response) => {
7440
+ const reader = response.body?.getReader();
7441
+ if (!reader) {
7442
+ throw new Error("Pinterest pin media fetch returned an empty media body.");
7443
+ }
7444
+ const chunks = [];
7445
+ let totalBytes = 0;
7446
+ try {
7447
+ while (true) {
7448
+ const { done, value } = await reader.read();
7449
+ if (done) break;
7450
+ if (!value) continue;
7451
+ totalBytes += value.byteLength;
7452
+ assertPinterestPinMediaByteLimit(totalBytes);
7453
+ chunks.push(Buffer.from(value));
7454
+ }
7455
+ if (totalBytes === 0) {
7456
+ throw new Error("Pinterest pin media fetch returned an empty media body.");
7457
+ }
7458
+ return Buffer.concat(chunks, totalBytes);
7459
+ } catch (error) {
7460
+ await reader.cancel().catch(() => void 0);
7461
+ throw error;
7462
+ }
7463
+ };
7464
+ var writePinterestPinMediaOutput = async (path4, bytes) => {
7465
+ await mkdir5(dirname2(path4), { recursive: true });
7466
+ let handle;
7467
+ let createdOutput = false;
7468
+ let writeFailed = false;
7469
+ try {
7470
+ handle = await open(path4, PINTEREST_PIN_MEDIA_OUTPUT_OPEN_FLAGS, 384);
7471
+ createdOutput = true;
7472
+ await handle.writeFile(bytes);
7473
+ } catch {
7474
+ writeFailed = createdOutput;
7475
+ throw new Error("Pinterest pin media output path could not be opened as a new non-symlink file.");
7476
+ } finally {
7477
+ await handle?.close().catch(() => void 0);
7478
+ if (writeFailed) {
7479
+ await unlink(path4).catch(() => void 0);
7480
+ }
7481
+ }
7482
+ };
6887
7483
  var BrowserManager = class {
6888
7484
  store = new SessionStore();
6889
7485
  sessions = /* @__PURE__ */ new Map();
@@ -7060,7 +7656,7 @@ var BrowserManager = class {
7060
7656
  warnings.push("System Chrome not found. Downloaded Chrome for Testing.");
7061
7657
  executablePath = download.executablePath;
7062
7658
  }
7063
- const profileDir = persistProfile ? cachePaths.profileDir : join9(cachePaths.projectRoot, "temp-profiles", randomUUID10());
7659
+ const profileDir = persistProfile ? cachePaths.profileDir : join10(cachePaths.projectRoot, "temp-profiles", randomUUID11());
7064
7660
  await mkdir5(profileDir, { recursive: true });
7065
7661
  let context = null;
7066
7662
  try {
@@ -7075,7 +7671,7 @@ var BrowserManager = class {
7075
7671
  if (!browser) {
7076
7672
  throw new Error("Browser instance unavailable");
7077
7673
  }
7078
- const sessionId = randomUUID10();
7674
+ const sessionId = randomUUID11();
7079
7675
  const targets = new TargetManager();
7080
7676
  const pages = context.pages();
7081
7677
  if (pages.length === 0) {
@@ -8182,9 +8778,18 @@ var BrowserManager = class {
8182
8778
  throw new Error("Screenshot ref and fullPage options are mutually exclusive.");
8183
8779
  }
8184
8780
  return this.runTargetScoped(sessionId, options.targetId, async ({ managed, page, targetId: resolvedTargetId }) => {
8781
+ let artifact;
8782
+ let outputPath = options.path;
8783
+ if (typeof outputPath !== "string") {
8784
+ artifact = createBrowserOutputArtifactDirectory({
8785
+ workspaceRoot: this.worktree,
8786
+ namespace: BROWSER_SCREENSHOT_ARTIFACT_NAMESPACE
8787
+ });
8788
+ outputPath = join10(artifact.artifactPath, "capture.png");
8789
+ }
8185
8790
  const screenshotOptions = {
8186
8791
  type: "png",
8187
- path: options.path
8792
+ path: outputPath
8188
8793
  };
8189
8794
  if (options.ref) {
8190
8795
  await this.callFunctionOnResolvedRef(managed, options.ref, DOM_SCROLL_INTO_VIEW_DECLARATION, [], resolvedTargetId);
@@ -8194,33 +8799,189 @@ var BrowserManager = class {
8194
8799
  screenshotOptions.fullPage = true;
8195
8800
  }
8196
8801
  try {
8197
- if (options.path) {
8198
- await this.withLegacyExtensionOperationTimeout(
8199
- managed,
8200
- page.screenshot(screenshotOptions),
8201
- `page.screenshot: Timeout ${LEGACY_EXTENSION_OPERATION_TIMEOUT_MS}ms exceeded.`
8202
- );
8203
- return { path: options.path };
8204
- }
8205
- const buffer = await this.withLegacyExtensionOperationTimeout(
8802
+ await this.withLegacyExtensionOperationTimeout(
8206
8803
  managed,
8207
8804
  page.screenshot(screenshotOptions),
8208
8805
  `page.screenshot: Timeout ${LEGACY_EXTENSION_OPERATION_TIMEOUT_MS}ms exceeded.`
8209
8806
  );
8210
- return { base64: buffer.toString("base64") };
8807
+ return {
8808
+ path: outputPath,
8809
+ ...artifact ? { artifact_path: artifact.artifactPath } : {}
8810
+ };
8211
8811
  } catch (error) {
8212
8812
  const fallback = await this.captureScreenshotViaCdp(managed, page, error, options);
8213
8813
  if (!fallback) {
8214
8814
  throw error;
8215
8815
  }
8216
- if (options.path) {
8217
- await writeFile3(options.path, Buffer.from(fallback.base64, "base64"));
8218
- return fallback.warnings ? { path: options.path, warnings: fallback.warnings } : { path: options.path };
8816
+ await writeFile3(outputPath, Buffer.from(fallback.base64, "base64"));
8817
+ return {
8818
+ path: outputPath,
8819
+ ...artifact ? { artifact_path: artifact.artifactPath } : {},
8820
+ ...fallback.warnings ? { warnings: fallback.warnings } : {}
8821
+ };
8822
+ }
8823
+ });
8824
+ }
8825
+ async capturePinterestPinMedia(sessionId, options) {
8826
+ if (!options.path) {
8827
+ throw new Error("Pinterest pin media capture requires an output path.");
8828
+ }
8829
+ return this.runTargetScoped(sessionId, options.targetId, async ({ managed, page, targetId }) => {
8830
+ const pageSourceUrl = this.safePageUrl(page, "BrowserManager.capturePinterestPinMedia") ?? "";
8831
+ const extraction = await this.evaluatePinterestPinMediaCandidates(managed, page, options.timeoutMs);
8832
+ const sourceUrl = readAuthoritativePinterestSourceUrl(pageSourceUrl, extraction.sourceUrl);
8833
+ if (pinterestPinSourceChanged(pageSourceUrl, extraction.sourceUrl)) {
8834
+ return {
8835
+ status: "not_found",
8836
+ sourceUrl,
8837
+ targetId,
8838
+ rejectedCandidates: extraction.candidates.slice(0, PINTEREST_PIN_MEDIA_REJECTION_LIMIT).map((candidate) => summarizeRejectedPinterestCandidate(candidate, ["source_url_changed"]))
8839
+ };
8840
+ }
8841
+ const selection = selectPinterestPinMediaCandidate(extraction, sourceUrl);
8842
+ if (!selection.selected) {
8843
+ return {
8844
+ status: "not_found",
8845
+ sourceUrl,
8846
+ targetId,
8847
+ rejectedCandidates: selection.rejectedCandidates
8848
+ };
8849
+ }
8850
+ const rejectedCandidates = [...selection.rejectedCandidates];
8851
+ let lastFailure;
8852
+ const fetchTimeoutMs = clampPinterestPinMediaOperationTimeout(
8853
+ options.timeoutMs ?? PINTEREST_PIN_MEDIA_DEFAULT_TIMEOUT_MS,
8854
+ PINTEREST_PIN_MEDIA_FETCH_MAX_TIMEOUT_MS
8855
+ );
8856
+ for (const candidate of selection.acceptedCandidates) {
8857
+ try {
8858
+ const fetched = await this.fetchPinterestPinMediaBytes(candidate.mediaUrl ?? "", fetchTimeoutMs);
8859
+ assertFetchedPinterestCandidateMatchesKind(candidate, fetched);
8860
+ await writePinterestPinMediaOutput(options.path, fetched.bytes);
8861
+ return this.buildPinterestPinMediaResult(
8862
+ candidate,
8863
+ rejectedCandidates,
8864
+ {
8865
+ contentType: fetched.contentType,
8866
+ byteLength: fetched.bytes.byteLength,
8867
+ path: options.path,
8868
+ sourceUrl,
8869
+ targetId,
8870
+ mediaUrl: fetched.finalUrl
8871
+ }
8872
+ );
8873
+ } catch (error) {
8874
+ lastFailure = error;
8875
+ if (rejectedCandidates.length < PINTEREST_PIN_MEDIA_REJECTION_LIMIT) {
8876
+ rejectedCandidates.push(summarizeRejectedPinterestCandidate(
8877
+ candidate,
8878
+ [pinterestCandidateCaptureFailureReason(error)]
8879
+ ));
8880
+ }
8219
8881
  }
8220
- return fallback;
8221
8882
  }
8883
+ throw lastFailure instanceof Error ? lastFailure : new Error("Pinterest pin media capture failed.");
8222
8884
  });
8223
8885
  }
8886
+ async evaluatePinterestPinMediaCandidates(managed, page, timeoutMs = PINTEREST_PIN_MEDIA_DEFAULT_TIMEOUT_MS) {
8887
+ const inspectionTimeoutMs = clampPinterestPinMediaOperationTimeout(
8888
+ timeoutMs,
8889
+ PINTEREST_PIN_MEDIA_DOM_INSPECTION_MAX_TIMEOUT_MS
8890
+ );
8891
+ try {
8892
+ return await withPinterestPinMediaOperationTimeout(
8893
+ page.evaluate(readPinterestPinMediaCandidatesInPage),
8894
+ inspectionTimeoutMs,
8895
+ `Pinterest pin media DOM inspection timed out after ${inspectionTimeoutMs}ms.`
8896
+ );
8897
+ } catch (error) {
8898
+ if (!isPinterestPinMediaDomInspectionTimeout(error)) {
8899
+ throw error;
8900
+ }
8901
+ return await this.evaluatePinterestPinMediaCandidatesViaCdp(managed, page, inspectionTimeoutMs, error);
8902
+ }
8903
+ }
8904
+ async evaluatePinterestPinMediaCandidatesViaCdp(managed, page, timeoutMs, originalError) {
8905
+ const sessionTimeoutMs = clampPinterestPinMediaOperationTimeout(
8906
+ timeoutMs,
8907
+ PINTEREST_PIN_MEDIA_CDP_SESSION_MAX_TIMEOUT_MS
8908
+ );
8909
+ const session = await withPinterestPinMediaOperationTimeout(
8910
+ managed.context.newCDPSession(page),
8911
+ sessionTimeoutMs,
8912
+ `Pinterest pin media CDP session attach timed out after ${sessionTimeoutMs}ms.`
8913
+ );
8914
+ try {
8915
+ const result = await withPinterestPinMediaOperationTimeout(
8916
+ session.send("Runtime.evaluate", {
8917
+ expression: `(${readPinterestPinMediaCandidatesInPage.toString()})()`,
8918
+ awaitPromise: true,
8919
+ returnByValue: true
8920
+ }),
8921
+ timeoutMs,
8922
+ `Pinterest pin media CDP inspection timed out after ${timeoutMs}ms.`
8923
+ );
8924
+ return parsePinterestPinMediaCdpExtraction(result);
8925
+ } catch {
8926
+ throw originalError;
8927
+ } finally {
8928
+ detachPinterestPinMediaCdpSession(session);
8929
+ }
8930
+ }
8931
+ async fetchPinterestPinMediaBytes(mediaUrl, timeoutMs = PINTEREST_PIN_MEDIA_DEFAULT_TIMEOUT_MS) {
8932
+ if (!isFirstPartyPinterestMediaUrl(mediaUrl)) {
8933
+ throw new Error("Pinterest pin media fetch rejected a non-first-party media URL.");
8934
+ }
8935
+ const controller = new AbortController();
8936
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
8937
+ try {
8938
+ const { response, finalUrl } = await fetchPinterestPinMediaResponse(mediaUrl, controller.signal);
8939
+ if (!response.ok) {
8940
+ await discardPinterestPinMediaResponseBody(response);
8941
+ throw new Error(`Pinterest pin media fetch failed with status ${response.status}.`);
8942
+ }
8943
+ const contentLength = readPinterestPinMediaContentLength(response.headers);
8944
+ if (contentLength !== void 0) {
8945
+ try {
8946
+ assertPinterestPinMediaByteLimit(contentLength);
8947
+ } catch (error) {
8948
+ await discardPinterestPinMediaResponseBody(response);
8949
+ throw error;
8950
+ }
8951
+ }
8952
+ const bytes = await readBoundedPinterestPinMediaBytes(response);
8953
+ const contentType = response.headers.get("content-type") ?? void 0;
8954
+ return { bytes, finalUrl, ...contentType ? { contentType } : {} };
8955
+ } finally {
8956
+ clearTimeout(timer);
8957
+ }
8958
+ }
8959
+ buildPinterestPinMediaResult(candidate, rejectedCandidates, metadata) {
8960
+ const contentType = candidate.kind === "video" ? PINTEREST_PIN_MEDIA_VIDEO_CONTENT_TYPE : normalizePinterestResponseContentType(metadata.contentType);
8961
+ return {
8962
+ status: "captured",
8963
+ sourceUrl: metadata.sourceUrl,
8964
+ targetId: metadata.targetId,
8965
+ kind: candidate.kind,
8966
+ path: metadata.path,
8967
+ mediaUrl: metadata.mediaUrl,
8968
+ bytes: metadata.byteLength,
8969
+ ...contentType ? { contentType } : {},
8970
+ ...candidate.candidateSelector ? { candidateSelector: candidate.candidateSelector } : {},
8971
+ ...candidate.candidateRole ? { candidateRole: candidate.candidateRole } : {},
8972
+ ...candidate.alt ? { alt: candidate.alt } : {},
8973
+ ...candidate.srcset ? { srcset: candidate.srcset } : {},
8974
+ ...candidate.width ? { width: candidate.width } : {},
8975
+ ...candidate.height ? { height: candidate.height } : {},
8976
+ ...candidate.naturalWidth ? { naturalWidth: candidate.naturalWidth } : {},
8977
+ ...candidate.naturalHeight ? { naturalHeight: candidate.naturalHeight } : {},
8978
+ ...candidate.poster ? { poster: candidate.poster } : {},
8979
+ ...candidate.rect ? { rect: candidate.rect } : {},
8980
+ ancestry: candidate.ancestry.slice(0, 6),
8981
+ rejectedCandidates,
8982
+ ...warningsForSelectedPinterestCandidate(candidate).length > 0 ? { warnings: warningsForSelectedPinterestCandidate(candidate) } : {}
8983
+ };
8984
+ }
8224
8985
  async startScreencast(sessionId, options = {}) {
8225
8986
  return await this.runStructural(sessionId, async () => {
8226
8987
  const managed = this.getManaged(sessionId);
@@ -10512,7 +11273,7 @@ var BrowserManager = class {
10512
11273
  }
10513
11274
  context = await browser.newContext();
10514
11275
  }
10515
- const sessionId = randomUUID10();
11276
+ const sessionId = randomUUID11();
10516
11277
  const targets = new TargetManager();
10517
11278
  const pages = context.pages();
10518
11279
  if (pages.length === 0) {
@@ -10705,7 +11466,8 @@ function truncateText(value, maxChars) {
10705
11466
 
10706
11467
  // src/browser/ops-browser-manager.ts
10707
11468
  import { writeFile as writeFile4 } from "fs/promises";
10708
- import { randomUUID as randomUUID11 } from "crypto";
11469
+ import { randomUUID as randomUUID12 } from "crypto";
11470
+ import { join as join11 } from "path";
10709
11471
  var OpsBrowserManager = class {
10710
11472
  base;
10711
11473
  config;
@@ -10839,7 +11601,7 @@ var OpsBrowserManager = class {
10839
11601
  config: this.config
10840
11602
  });
10841
11603
  const client = await this.ensureOpsClient(connectEndpoint);
10842
- const leaseId = randomUUID11();
11604
+ const leaseId = randomUUID12();
10843
11605
  const result = await client.request(
10844
11606
  "session.connect",
10845
11607
  {
@@ -11311,11 +12073,27 @@ var OpsBrowserManager = class {
11311
12073
  throw new Error("Screenshot failed");
11312
12074
  }
11313
12075
  const warnings = Array.isArray(result.warnings) ? result.warnings : typeof result.warning === "string" ? [result.warning] : void 0;
11314
- if (options.path) {
11315
- await writeFile4(options.path, Buffer.from(result.base64, "base64"));
11316
- return warnings ? { path: options.path, warnings } : { path: options.path };
12076
+ let artifact;
12077
+ let outputPath = options.path;
12078
+ if (typeof outputPath !== "string") {
12079
+ artifact = createBrowserOutputArtifactDirectory({
12080
+ workspaceRoot: this.worktree,
12081
+ namespace: BROWSER_SCREENSHOT_ARTIFACT_NAMESPACE
12082
+ });
12083
+ outputPath = join11(artifact.artifactPath, "capture.png");
11317
12084
  }
11318
- return warnings ? { base64: result.base64, warnings } : { base64: result.base64 };
12085
+ await writeFile4(outputPath, Buffer.from(result.base64, "base64"));
12086
+ return {
12087
+ path: outputPath,
12088
+ ...artifact ? { artifact_path: artifact.artifactPath } : {},
12089
+ ...warnings ? { warnings } : {}
12090
+ };
12091
+ }
12092
+ async capturePinterestPinMedia(sessionId, options) {
12093
+ if (!this.opsSessions.has(sessionId)) {
12094
+ return await this.base.capturePinterestPinMedia(sessionId, options);
12095
+ }
12096
+ throw new Error("Pinterest pin media capture is not supported through extension ops sessions.");
11319
12097
  }
11320
12098
  async startScreencast(sessionId, options = {}) {
11321
12099
  if (!this.opsSessions.has(sessionId)) {
@@ -12210,7 +12988,7 @@ var normalizeRecoverableOpsUrl = (url) => {
12210
12988
  };
12211
12989
 
12212
12990
  // src/browser/annotation-manager.ts
12213
- import { randomUUID as randomUUID13 } from "crypto";
12991
+ import { randomUUID as randomUUID14 } from "crypto";
12214
12992
  import { WebSocket as WebSocket2 } from "ws";
12215
12993
 
12216
12994
  // src/annotate/timeout-messages.ts
@@ -12221,9 +12999,9 @@ var getAnnotationTimeoutMessage = (readySeen) => {
12221
12999
  };
12222
13000
 
12223
13001
  // src/annotate/direct-annotator.ts
12224
- import { randomUUID as randomUUID12 } from "crypto";
13002
+ import { randomUUID as randomUUID13 } from "crypto";
12225
13003
  import { existsSync as existsSync2 } from "fs";
12226
- import { join as join10 } from "path";
13004
+ import { join as join12 } from "path";
12227
13005
  var DEFAULT_TIMEOUT_MS = 12e4;
12228
13006
  var DIRECT_ANNOTATE_REQUIRED_FILES = [
12229
13007
  "dist/annotate-content.js",
@@ -12238,15 +13016,15 @@ function resolveDirectAnnotateAssets(resolvePath = () => getExtensionRuntimePath
12238
13016
  if (!extensionPath) {
12239
13017
  return { error: "Extension assets unavailable." };
12240
13018
  }
12241
- const scriptPath = join10(extensionPath, "dist", "annotate-content.js");
12242
- const stylePath = join10(extensionPath, "dist", "annotate-content.css");
13019
+ const scriptPath = join12(extensionPath, "dist", "annotate-content.js");
13020
+ const stylePath = join12(extensionPath, "dist", "annotate-content.css");
12243
13021
  if (!existsSync2(scriptPath) || !existsSync2(stylePath)) {
12244
13022
  return { error: "Direct annotate assets missing. Run `npm run extension:build` and retry." };
12245
13023
  }
12246
13024
  return { assets: { scriptPath, stylePath } };
12247
13025
  }
12248
13026
  async function runDirectAnnotate(manager, assets, request) {
12249
- const requestId = randomUUID12();
13027
+ const requestId = randomUUID13();
12250
13028
  const timeoutMs = request.timeoutMs ?? DEFAULT_TIMEOUT_MS;
12251
13029
  return manager.withPage(request.sessionId, request.targetId ?? null, async (page) => {
12252
13030
  await ensureBindings(page);
@@ -12546,7 +13324,7 @@ var AnnotationManager = class {
12546
13324
  return this.requestRelay(options, false);
12547
13325
  }
12548
13326
  async requestStored(options) {
12549
- const requestId = randomUUID13();
13327
+ const requestId = randomUUID14();
12550
13328
  const sharedPayload = this.agentInbox?.latestPayload();
12551
13329
  if (sharedPayload) {
12552
13330
  return {
@@ -12591,7 +13369,7 @@ var AnnotationManager = class {
12591
13369
  return this.relay?.getAnnotationUrl?.() ?? (this.config.relayPort > 0 ? `ws://127.0.0.1:${this.config.relayPort}/annotation` : null);
12592
13370
  }
12593
13371
  async requestDirect(options) {
12594
- const requestId = randomUUID13();
13372
+ const requestId = randomUUID14();
12595
13373
  if (!options.sessionId) {
12596
13374
  return {
12597
13375
  version: 1,
@@ -12639,7 +13417,7 @@ var AnnotationManager = class {
12639
13417
  }
12640
13418
  }
12641
13419
  async requestRelay(options, requireExtension, commandName = "start") {
12642
- const requestId = randomUUID13();
13420
+ const requestId = randomUUID14();
12643
13421
  const timeoutMs = options.timeoutMs ?? 12e4;
12644
13422
  let resolvedTabId = options.tabId;
12645
13423
  if (requireExtension && options.sessionId && this.manager) {
@@ -12866,12 +13644,12 @@ var parseJson2 = (data) => {
12866
13644
  };
12867
13645
 
12868
13646
  // src/browser/canvas-manager.ts
12869
- import { randomUUID as randomUUID18 } from "crypto";
13647
+ import { randomUUID as randomUUID19 } from "crypto";
12870
13648
  import { mkdir as mkdir9 } from "fs/promises";
12871
- import { dirname as dirname5 } from "path";
13649
+ import { dirname as dirname6 } from "path";
12872
13650
 
12873
13651
  // src/browser/canvas-client.ts
12874
- import { randomUUID as randomUUID14 } from "crypto";
13652
+ import { randomUUID as randomUUID15 } from "crypto";
12875
13653
  import { WebSocket as WebSocket3 } from "ws";
12876
13654
  var CanvasClient = class {
12877
13655
  url;
@@ -13047,7 +13825,7 @@ var CanvasClient = class {
13047
13825
  if (!this.socket || this.socket.readyState !== WebSocket3.OPEN) {
13048
13826
  await this.connect();
13049
13827
  }
13050
- const requestId = randomUUID14();
13828
+ const requestId = randomUUID15();
13051
13829
  const request = {
13052
13830
  type: "canvas_request",
13053
13831
  requestId,
@@ -13193,7 +13971,7 @@ var CanvasClient = class {
13193
13971
  if (!this.socket || this.socket.readyState !== WebSocket3.OPEN) {
13194
13972
  return;
13195
13973
  }
13196
- const id2 = randomUUID14();
13974
+ const id2 = randomUUID15();
13197
13975
  const ping = { type: "canvas_ping", id: id2 };
13198
13976
  await new Promise((resolve7, reject) => {
13199
13977
  const timeoutId = setTimeout(() => {
@@ -13260,7 +14038,7 @@ var isCanvasEvent = (value) => {
13260
14038
  var isRecord2 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
13261
14039
 
13262
14040
  // src/canvas/document-store.ts
13263
- import { randomUUID as randomUUID15 } from "crypto";
14041
+ import { randomUUID as randomUUID16 } from "crypto";
13264
14042
 
13265
14043
  // node_modules/lib0/map.js
13266
14044
  var create = () => /* @__PURE__ */ new Map();
@@ -21567,7 +22345,7 @@ function createDefaultNode(pageId, nodeId, name) {
21567
22345
  metadata: {}
21568
22346
  };
21569
22347
  }
21570
- function createDefaultCanvasDocument(documentId = `dc_${randomUUID15()}`) {
22348
+ function createDefaultCanvasDocument(documentId = `dc_${randomUUID16()}`) {
21571
22349
  const createdAt = nowIso();
21572
22350
  const rootNodeId = `node_root_${documentId.slice(-8)}`;
21573
22351
  const pageId = "page_home";
@@ -21615,7 +22393,7 @@ function normalizeCanvasDocument(input) {
21615
22393
  const updatedAt = typeof base.updatedAt === "string" ? base.updatedAt : createdAt;
21616
22394
  return {
21617
22395
  schemaVersion: typeof base.schemaVersion === "string" ? base.schemaVersion : CANVAS_SCHEMA_VERSION,
21618
- documentId: typeof base.documentId === "string" ? base.documentId : `dc_${randomUUID15()}`,
22396
+ documentId: typeof base.documentId === "string" ? base.documentId : `dc_${randomUUID16()}`,
21619
22397
  title: typeof base.title === "string" && base.title.trim() ? base.title : "Untitled Design Canvas",
21620
22398
  createdAt,
21621
22399
  updatedAt,
@@ -21648,7 +22426,7 @@ function normalizeCanvasDocument(input) {
21648
22426
  componentInventory: normalizeArray(base.componentInventory, normalizeCanvasComponentInventoryItem),
21649
22427
  tokens: normalizeCanvasTokenStore(base.tokens),
21650
22428
  assets: Array.isArray(base.assets) ? base.assets.map((asset) => ({
21651
- id: typeof asset.id === "string" ? asset.id : `asset_${randomUUID15()}`,
22429
+ id: typeof asset.id === "string" ? asset.id : `asset_${randomUUID16()}`,
21652
22430
  sourceType: typeof asset.sourceType === "string" ? asset.sourceType : void 0,
21653
22431
  kind: typeof asset.kind === "string" ? asset.kind : void 0,
21654
22432
  repoPath: typeof asset.repoPath === "string" ? asset.repoPath : null,
@@ -21880,7 +22658,7 @@ function buildInventoryItemFromNode(document2, nodeId, options = {}) {
21880
22658
  const origin = options.origin && CANVAS_INVENTORY_ORIGINS.has(options.origin) ? options.origin : baseOrigin;
21881
22659
  const template = buildInventoryTemplate(document2, nodeId);
21882
22660
  return normalizeCanvasComponentInventoryItem({
21883
- id: options.itemId ?? `inventory_${randomUUID15().slice(0, 8)}`,
22661
+ id: options.itemId ?? `inventory_${randomUUID16().slice(0, 8)}`,
21884
22662
  name: options.name ?? node.name,
21885
22663
  componentName: binding?.componentName ?? node.name,
21886
22664
  description: options.description ?? null,
@@ -22873,7 +23651,7 @@ var CanvasDocumentStore = class {
22873
23651
  }
22874
23652
  this.replaceDocument(nextDocument, this.revision + 1, "canvas.store.apply-patches");
22875
23653
  return {
22876
- transactionId: `txn_${randomUUID15()}`,
23654
+ transactionId: `txn_${randomUUID16()}`,
22877
23655
  appliedRevision: this.revision,
22878
23656
  warnings: evaluateCanvasWarnings(this.document),
22879
23657
  evidenceRefs: []
@@ -22888,7 +23666,7 @@ var CanvasDocumentStore = class {
22888
23666
  }
22889
23667
  this.replaceDocument(normalizeCanvasDocument(document2), this.revision + 1, "canvas.store.replace-document");
22890
23668
  return {
22891
- transactionId: `txn_${randomUUID15()}`,
23669
+ transactionId: `txn_${randomUUID16()}`,
22892
23670
  appliedRevision: this.revision,
22893
23671
  warnings: evaluateCanvasWarnings(this.document),
22894
23672
  evidenceRefs: []
@@ -23383,7 +24161,7 @@ function duplicateNodeSubtree(document2, nodeId, parentId, index, idMapInput) {
23383
24161
  throw new Error(`Unknown node: ${sourceNodeId}`);
23384
24162
  }
23385
24163
  const mappedId = isRecord4(idMapInput) ? idMapInput[sourceNode.id] : null;
23386
- const duplicateId = typeof mappedId === "string" && mappedId.trim().length > 0 ? mappedId : `${sourceNode.id}_copy_${randomUUID15().slice(0, 8)}`;
24164
+ const duplicateId = typeof mappedId === "string" && mappedId.trim().length > 0 ? mappedId : `${sourceNode.id}_copy_${randomUUID16().slice(0, 8)}`;
23387
24165
  idMap.set(sourceNode.id, duplicateId);
23388
24166
  const nextMetadata = clone(sourceNode.metadata);
23389
24167
  if (isRecord4(nextMetadata.codeSync)) {
@@ -24935,7 +25713,7 @@ function listBuiltInCanvasKitIds() {
24935
25713
 
24936
25714
  // src/canvas/repo-store.ts
24937
25715
  import { access as access3, mkdir as mkdir6, readFile as readFile2 } from "fs/promises";
24938
- import { join as join11, dirname as dirname2, isAbsolute as isAbsolute3, resolve as resolve2 } from "path";
25716
+ import { join as join13, dirname as dirname3, isAbsolute as isAbsolute3, resolve as resolve2 } from "path";
24939
25717
 
24940
25718
  // src/canvas/code-sync/manifest.ts
24941
25719
  var isRecord6 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -25119,24 +25897,24 @@ function resolveCanvasRepoPath(worktree, documentId, repoPath) {
25119
25897
  if (repoPath && repoPath.trim()) {
25120
25898
  return isAbsolute3(repoPath) ? repoPath : resolve2(worktree, repoPath);
25121
25899
  }
25122
- return join11(worktree, ".opendevbrowser", "canvas", `${documentId}.canvas.json`);
25900
+ return join13(worktree, ".opendevbrowser", "canvas", `${documentId}.canvas.json`);
25123
25901
  }
25124
25902
  function resolveCanvasCodeSyncManifestPath(worktree, documentId, bindingId, repoPath) {
25125
25903
  if (repoPath && repoPath.trim()) {
25126
25904
  return isAbsolute3(repoPath) ? repoPath : resolve2(worktree, repoPath);
25127
25905
  }
25128
- return join11(worktree, ".opendevbrowser", "canvas", "code-sync", documentId, `${bindingId}.json`);
25906
+ return join13(worktree, ".opendevbrowser", "canvas", "code-sync", documentId, `${bindingId}.json`);
25129
25907
  }
25130
25908
  function resolveCanvasFigmaAssetDir(worktree, fileKey) {
25131
- return join11(worktree, ".opendevbrowser", "canvas", "assets", "figma", fileKey);
25909
+ return join13(worktree, ".opendevbrowser", "canvas", "assets", "figma", fileKey);
25132
25910
  }
25133
25911
  function resolveCanvasFigmaAssetPath(worktree, fileKey, assetId, extension) {
25134
25912
  const normalizedExtension = extension.startsWith(".") ? extension : `.${extension}`;
25135
- return join11(resolveCanvasFigmaAssetDir(worktree, fileKey), `${assetId}${normalizedExtension}`);
25913
+ return join13(resolveCanvasFigmaAssetDir(worktree, fileKey), `${assetId}${normalizedExtension}`);
25136
25914
  }
25137
25915
  async function saveCanvasDocument(worktree, document2, repoPath) {
25138
25916
  const resolvedPath = resolveCanvasRepoPath(worktree, document2.documentId, repoPath);
25139
- await mkdir6(dirname2(resolvedPath), { recursive: true });
25917
+ await mkdir6(dirname3(resolvedPath), { recursive: true });
25140
25918
  writeFileAtomic(resolvedPath, `${JSON.stringify(stableValue(document2), null, 2)}
25141
25919
  `, { encoding: "utf-8" });
25142
25920
  return resolvedPath;
@@ -25158,7 +25936,7 @@ async function loadCanvasDocumentById(worktree, documentId) {
25158
25936
  }
25159
25937
  async function saveCanvasCodeSyncManifest(worktree, manifest, repoPath) {
25160
25938
  const resolvedPath = resolveCanvasCodeSyncManifestPath(worktree, manifest.documentId, manifest.bindingId, repoPath);
25161
- await mkdir6(dirname2(resolvedPath), { recursive: true });
25939
+ await mkdir6(dirname3(resolvedPath), { recursive: true });
25162
25940
  writeFileAtomic(resolvedPath, `${JSON.stringify(stableValue(manifest), null, 2)}
25163
25941
  `, { encoding: "utf-8" });
25164
25942
  return resolvedPath;
@@ -25540,7 +26318,7 @@ import { resolve as resolve5, isAbsolute as isAbsolute5 } from "path";
25540
26318
  // src/canvas/adapter-plugins/loader.ts
25541
26319
  import { createHash as createHash4 } from "crypto";
25542
26320
  import { access as access4, readFile as readFile3 } from "fs/promises";
25543
- import { dirname as dirname3, isAbsolute as isAbsolute4, join as join12, resolve as resolve4 } from "path";
26321
+ import { dirname as dirname4, isAbsolute as isAbsolute4, join as join14, resolve as resolve4 } from "path";
25544
26322
  import { pathToFileURL } from "url";
25545
26323
 
25546
26324
  // src/canvas/adapter-plugins/manifest.ts
@@ -25636,7 +26414,7 @@ async function readJson(filePath) {
25636
26414
  return JSON.parse(await readFile3(filePath, "utf8"));
25637
26415
  }
25638
26416
  async function loadPackageJson(worktree) {
25639
- const packagePath = join12(worktree, "package.json");
26417
+ const packagePath = join14(worktree, "package.json");
25640
26418
  try {
25641
26419
  return await readJson(packagePath);
25642
26420
  } catch (error) {
@@ -25684,14 +26462,14 @@ function applyDeclarationOverrides(manifest, declaration) {
25684
26462
  async function resolveDeclarationRef(worktree, ref) {
25685
26463
  const direct = isAbsolute4(ref) ? ref : resolve4(worktree, ref);
25686
26464
  if (await exists(direct)) {
25687
- const manifestPath2 = direct.endsWith(".json") ? direct : join12(direct, "canvas-adapter.plugin.json");
26465
+ const manifestPath2 = direct.endsWith(".json") ? direct : join14(direct, "canvas-adapter.plugin.json");
25688
26466
  return {
25689
- packageRoot: direct.endsWith(".json") ? dirname3(direct) : direct,
26467
+ packageRoot: direct.endsWith(".json") ? dirname4(direct) : direct,
25690
26468
  manifestPath: manifestPath2
25691
26469
  };
25692
26470
  }
25693
- const nodeModulesPath = join12(worktree, "node_modules", ref);
25694
- const manifestPath = join12(nodeModulesPath, "canvas-adapter.plugin.json");
26471
+ const nodeModulesPath = join14(worktree, "node_modules", ref);
26472
+ const manifestPath = join14(nodeModulesPath, "canvas-adapter.plugin.json");
25695
26473
  return {
25696
26474
  packageRoot: nodeModulesPath,
25697
26475
  manifestPath
@@ -25702,7 +26480,7 @@ async function readDeclarationSource(worktree) {
25702
26480
  const openDevBrowserConfig = isRecord7(packageJson.opendevbrowser) ? packageJson.opendevbrowser : null;
25703
26481
  const canvasConfig = openDevBrowserConfig && isRecord7(openDevBrowserConfig.canvas) ? openDevBrowserConfig.canvas : null;
25704
26482
  const packageDeclarations = Array.isArray(canvasConfig?.adapterPlugins) ? canvasConfig.adapterPlugins : [];
25705
- const repoFile = join12(worktree, ".opendevbrowser", "canvas", "adapters.json");
26483
+ const repoFile = join14(worktree, ".opendevbrowser", "canvas", "adapters.json");
25706
26484
  const repoDeclarations = await exists(repoFile) ? (await readJson(repoFile)).adapterPlugins ?? [] : [];
25707
26485
  return { packageDeclarations, repoDeclarations };
25708
26486
  }
@@ -25748,7 +26526,7 @@ function applyCapabilityOverridesToRegisteredAdapters(params2) {
25748
26526
  async function fingerprintPluginFiles(manifestPath, packageRoot, manifest) {
25749
26527
  const entryPath = resolve4(packageRoot, manifest.entry);
25750
26528
  const fixturePath = resolve4(packageRoot, manifest.fixtureDir);
25751
- const packageJsonPath = join12(packageRoot, "package.json");
26529
+ const packageJsonPath = join14(packageRoot, "package.json");
25752
26530
  const [manifestContent, entryContent, packageJsonContent] = await Promise.all([
25753
26531
  readFile3(manifestPath, "utf8"),
25754
26532
  readFile3(entryPath, "utf8"),
@@ -27102,7 +27880,7 @@ function collectGraphOrder(graph, nodeKey) {
27102
27880
  }
27103
27881
 
27104
27882
  // src/canvas/code-sync/import.ts
27105
- import { randomUUID as randomUUID16 } from "crypto";
27883
+ import { randomUUID as randomUUID17 } from "crypto";
27106
27884
 
27107
27885
  // src/canvas/code-sync/graph.ts
27108
27886
  function locatorKey(locator) {
@@ -27232,7 +28010,7 @@ function buildNodeName(graphNode) {
27232
28010
  return graphNode.tagName ?? "Element";
27233
28011
  }
27234
28012
  function buildNodeId(graphNode, manifestLookup) {
27235
- return manifestLookup.get(locatorKey(graphNode.locator)) ?? `node_sync_${randomUUID16().slice(0, 8)}`;
28013
+ return manifestLookup.get(locatorKey(graphNode.locator)) ?? `node_sync_${randomUUID17().slice(0, 8)}`;
27236
28014
  }
27237
28015
  function preorder(graph, nodeKey) {
27238
28016
  const node = graph.nodes[nodeKey];
@@ -27336,9 +28114,9 @@ function importCodeSyncGraph(options) {
27336
28114
 
27337
28115
  // src/canvas/code-sync/write.ts
27338
28116
  import { mkdir as mkdir7 } from "fs/promises";
27339
- import { dirname as dirname4 } from "path";
28117
+ import { dirname as dirname5 } from "path";
27340
28118
  async function writeCodeSyncSource(repoPath, sourceText) {
27341
- await mkdir7(dirname4(repoPath), { recursive: true });
28119
+ await mkdir7(dirname5(repoPath), { recursive: true });
27342
28120
  writeFileAtomic(repoPath, sourceText, { encoding: "utf-8" });
27343
28121
  }
27344
28122
  function finalizeCodeSyncManifest(manifest, updates) {
@@ -28200,11 +28978,11 @@ function maxIso(values) {
28200
28978
  }
28201
28979
 
28202
28980
  // src/browser/canvas-session-sync-manager.ts
28203
- import { randomUUID as randomUUID17 } from "crypto";
28981
+ import { randomUUID as randomUUID18 } from "crypto";
28204
28982
  var CanvasSessionSyncManager = class {
28205
28983
  sessions = /* @__PURE__ */ new Map();
28206
28984
  initializeSession(canvasSessionId, leaseId, clientId) {
28207
- const initialClientId = normalizeClientId(clientId) ?? `canvas_owner_${randomUUID17().slice(0, 8)}`;
28985
+ const initialClientId = normalizeClientId(clientId) ?? `canvas_owner_${randomUUID18().slice(0, 8)}`;
28208
28986
  const attachedAt = (/* @__PURE__ */ new Date()).toISOString();
28209
28987
  const attachedClients = /* @__PURE__ */ new Map();
28210
28988
  attachedClients.set(initialClientId, {
@@ -28232,7 +29010,7 @@ var CanvasSessionSyncManager = class {
28232
29010
  if (!state) {
28233
29011
  throw new Error(`Unknown canvas session for attach: ${canvasSessionId}`);
28234
29012
  }
28235
- const resolvedClientId = normalizeClientId(clientId) ?? `canvas_client_${randomUUID17().slice(0, 8)}`;
29013
+ const resolvedClientId = normalizeClientId(clientId) ?? `canvas_client_${randomUUID18().slice(0, 8)}`;
28236
29014
  const previous = state.attachedClients.get(resolvedClientId);
28237
29015
  const attachedAt = previous?.attachedAt ?? (/* @__PURE__ */ new Date()).toISOString();
28238
29016
  let role = "observer";
@@ -29675,8 +30453,8 @@ var CanvasManager = class {
29675
30453
  const repoRoot = optionalString5(params2.repoRoot) ?? this.worktree;
29676
30454
  const mode = requireCanvasSessionMode(params2.mode);
29677
30455
  const document2 = repoPath ? normalizeCanvasDocument(await loadCanvasDocument(repoRoot, repoPath)) : createDefaultCanvasDocument(requestedDocumentId ?? void 0);
29678
- const sessionId = `canvas_${randomUUID18()}`;
29679
- const leaseId = `lease_${randomUUID18()}`;
30456
+ const sessionId = `canvas_${randomUUID19()}`;
30457
+ const leaseId = `lease_${randomUUID19()}`;
29680
30458
  const planState = resolveGenerationPlanState(document2.designGovernance.generationPlan);
29681
30459
  const session = {
29682
30460
  canvasSessionId: sessionId,
@@ -29718,7 +30496,7 @@ var CanvasManager = class {
29718
30496
  attachSession(params2) {
29719
30497
  const session = this.requireSession(params2);
29720
30498
  const attachMode = requireAttachMode(params2.attachMode);
29721
- const nextLeaseId = attachMode === "lease_reclaim" ? `lease_${randomUUID18()}` : session.leaseId;
30499
+ const nextLeaseId = attachMode === "lease_reclaim" ? `lease_${randomUUID19()}` : session.leaseId;
29722
30500
  const attached = this.sessionSyncManager.attach(
29723
30501
  session.canvasSessionId,
29724
30502
  nextLeaseId,
@@ -30075,7 +30853,7 @@ var CanvasManager = class {
30075
30853
  const session = this.requireSession(params2);
30076
30854
  this.assertLease(session, params2);
30077
30855
  const nodeId = requireString2(params2.nodeId, "nodeId");
30078
- const bindingId = optionalString5(params2.bindingId) ?? `binding_sync_${randomUUID18().slice(0, 8)}`;
30856
+ const bindingId = optionalString5(params2.bindingId) ?? `binding_sync_${randomUUID19().slice(0, 8)}`;
30079
30857
  const binding = createCodeSyncBinding(params2, nodeId, bindingId);
30080
30858
  const baseRevision = session.store.getRevision();
30081
30859
  await this.applyDocumentPatches(session, baseRevision, [{
@@ -30410,7 +31188,7 @@ var CanvasManager = class {
30410
31188
  const repoRoot = this.resolveSessionRepoRoot(session, params2);
30411
31189
  const warnings = evaluateCanvasWarnings(document2, { forSave: exportTarget === "design_document" });
30412
31190
  const exportBase = resolveCanvasRepoPath(repoRoot, document2.documentId, ".opendevbrowser/canvas/exports");
30413
- await mkdir9(dirname5(exportBase), { recursive: true });
31191
+ await mkdir9(dirname6(exportBase), { recursive: true });
30414
31192
  if (exportTarget === "design_document") {
30415
31193
  const validation = validateCanvasSave(document2);
30416
31194
  if (validation.missingBlocks.length > 0) {
@@ -30859,7 +31637,7 @@ var CanvasManager = class {
30859
31637
  prototypeId
30860
31638
  });
30861
31639
  } else if (status.mode === "extension" && this.supportsOpsOverlayTransport(session) && typeof this.browserManager.mountCanvasOverlay === "function") {
30862
- const mountId2 = `mount_${randomUUID18()}`;
31640
+ const mountId2 = `mount_${randomUUID19()}`;
30863
31641
  result = await this.browserManager.mountCanvasOverlay(session.browserSessionId, targetId, {
30864
31642
  mountId: mountId2,
30865
31643
  title: session.store.getDocument().title,
@@ -30869,7 +31647,7 @@ var CanvasManager = class {
30869
31647
  } else {
30870
31648
  result = await this.mountDirectOverlay(session.browserSessionId, targetId, session.store.getDocument(), prototypeId);
30871
31649
  }
30872
- const mountId = typeof result.mountId === "string" ? result.mountId : `mount_${randomUUID18()}`;
31650
+ const mountId = typeof result.mountId === "string" ? result.mountId : `mount_${randomUUID19()}`;
30873
31651
  session.overlayMounts.set(mountId, { mountId, targetId, mountedAt: (/* @__PURE__ */ new Date()).toISOString() });
30874
31652
  const previewState = session.activeTargets.get(targetId)?.previewState ?? "background";
30875
31653
  if (!usesCanvasRelayOverlay) {
@@ -31209,7 +31987,7 @@ var CanvasManager = class {
31209
31987
  subscribeFeedback(params2) {
31210
31988
  const session = this.requireSession(params2);
31211
31989
  const polled = this.pollFeedback(params2);
31212
- const subscriptionId = `canvas_sub_${randomUUID18()}`;
31990
+ const subscriptionId = `canvas_sub_${randomUUID19()}`;
31213
31991
  const heartbeatMs = FEEDBACK_HEARTBEAT_MS;
31214
31992
  const subscription = {
31215
31993
  id: subscriptionId,
@@ -32507,7 +33285,7 @@ function readInsertPlacement(params2) {
32507
33285
  }
32508
33286
  function materializeInventoryItem(item, pageId, parentId, placement) {
32509
33287
  const template = readInventoryTemplate(item);
32510
- const idMap = new Map(template.nodes.map((node) => [node.id, `node_inventory_${randomUUID18().slice(0, 8)}`]));
33288
+ const idMap = new Map(template.nodes.map((node) => [node.id, `node_inventory_${randomUUID19().slice(0, 8)}`]));
32511
33289
  const root = template.nodes.find((node) => node.id === template.rootNodeId) ?? template.nodes[0];
32512
33290
  const offsetX = (placement.x ?? root.rect.x) - root.rect.x;
32513
33291
  const offsetY = (placement.y ?? root.rect.y) - root.rect.y;
@@ -32683,11 +33461,11 @@ function buildStarterInventoryUpsertPatches(kitIds, frameworkId, adapterId) {
32683
33461
  }));
32684
33462
  }
32685
33463
  function buildStarterShell(definition, pageId, parentId, placement) {
32686
- const rootNodeId = `node_starter_${randomUUID18().slice(0, 8)}`;
32687
- const eyebrowNodeId = `node_starter_${randomUUID18().slice(0, 8)}`;
32688
- const headlineNodeId = `node_starter_${randomUUID18().slice(0, 8)}`;
32689
- const bodyNodeId = `node_starter_${randomUUID18().slice(0, 8)}`;
32690
- const actionNodeId = definition.shell.actionLabel ? `node_starter_${randomUUID18().slice(0, 8)}` : null;
33464
+ const rootNodeId = `node_starter_${randomUUID19().slice(0, 8)}`;
33465
+ const eyebrowNodeId = `node_starter_${randomUUID19().slice(0, 8)}`;
33466
+ const headlineNodeId = `node_starter_${randomUUID19().slice(0, 8)}`;
33467
+ const bodyNodeId = `node_starter_${randomUUID19().slice(0, 8)}`;
33468
+ const actionNodeId = definition.shell.actionLabel ? `node_starter_${randomUUID19().slice(0, 8)}` : null;
32691
33469
  const rect = {
32692
33470
  ...definition.shell.rect,
32693
33471
  x: placement.x ?? definition.shell.rect.x,
@@ -33007,7 +33785,7 @@ function toAbsoluteUrl(value) {
33007
33785
  }
33008
33786
  }
33009
33787
  async function saveText(path4, content) {
33010
- await mkdir9(dirname5(path4), { recursive: true });
33788
+ await mkdir9(dirname6(path4), { recursive: true });
33011
33789
  const { writeFileAtomic: writeFileAtomic2 } = await import("./fs-UMRKOBNN.js");
33012
33790
  writeFileAtomic2(path4, `${content}
33013
33791
  `, { encoding: "utf-8" });
@@ -33338,7 +34116,7 @@ function ensureDuplicatePatchIds(document2, patch) {
33338
34116
  }
33339
34117
  const subtreeNodeIds = collectSubtreeNodeIds(document2, patch.nodeId);
33340
34118
  const idMap = Object.fromEntries(
33341
- subtreeNodeIds.map((nodeId) => [nodeId, `${nodeId}_copy_${randomUUID18().slice(0, 8)}`])
34119
+ subtreeNodeIds.map((nodeId) => [nodeId, `${nodeId}_copy_${randomUUID19().slice(0, 8)}`])
33342
34120
  );
33343
34121
  return {
33344
34122
  ...patch,
@@ -33357,7 +34135,7 @@ function buildCanvasHistoryEntry(beforeDocument, patches, options) {
33357
34135
  scratchStore.applyPatches(scratchStore.getRevision(), [patch]);
33358
34136
  }
33359
34137
  return {
33360
- id: `history_${randomUUID18().slice(0, 8)}`,
34138
+ id: `history_${randomUUID19().slice(0, 8)}`,
33361
34139
  source: options.source,
33362
34140
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
33363
34141
  forwardPatches: structuredClone(patches),
@@ -33588,7 +34366,7 @@ function attachDetails(error, details) {
33588
34366
 
33589
34367
  // src/relay/relay-server.ts
33590
34368
  import { createServer } from "http";
33591
- import { timingSafeEqual, randomUUID as randomUUID19 } from "crypto";
34369
+ import { timingSafeEqual, randomUUID as randomUUID20 } from "crypto";
33592
34370
  import { WebSocket as WebSocket4, WebSocketServer } from "ws";
33593
34371
  var DEFAULT_DISCOVERY_PORT = 8787;
33594
34372
  var CONFIG_PATH = "/config";
@@ -33596,7 +34374,7 @@ var PAIR_PATH = "/pair";
33596
34374
  var STATUS_PATH = "/status";
33597
34375
  var CDP_TOKEN_QUERY_KEY = "token";
33598
34376
  var RelayServer = class _RelayServer {
33599
- instanceId = randomUUID19();
34377
+ instanceId = randomUUID20();
33600
34378
  epoch = Date.now();
33601
34379
  running = false;
33602
34380
  baseUrl = null;
@@ -33729,7 +34507,7 @@ var RelayServer = class _RelayServer {
33729
34507
  });
33730
34508
  });
33731
34509
  this.opsWss.on("connection", (socket, _request) => {
33732
- const clientId = randomUUID19();
34510
+ const clientId = randomUUID20();
33733
34511
  this.opsClients.set(clientId, socket);
33734
34512
  socket.on("message", (data) => {
33735
34513
  this.handleOpsClientMessage(clientId, data);
@@ -33753,7 +34531,7 @@ var RelayServer = class _RelayServer {
33753
34531
  void _request;
33754
34532
  });
33755
34533
  this.canvasWss.on("connection", (socket, _request) => {
33756
- const clientId = randomUUID19();
34534
+ const clientId = randomUUID20();
33757
34535
  this.canvasClients.set(clientId, socket);
33758
34536
  socket.on("message", (data) => {
33759
34537
  this.handleCanvasClientMessage(clientId, data);
@@ -35435,4 +36213,4 @@ export {
35435
36213
  createOpenDevBrowserCore
35436
36214
  };
35437
36215
  /* v8 ignore next -- @preserve */
35438
- //# sourceMappingURL=chunk-EOX6U6Q4.js.map
36216
+ //# sourceMappingURL=chunk-AHQC4A6P.js.map