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.
- package/README.md +1 -1
- package/dist/{accessibility-snapshot-JSPFVWZ6.js → accessibility-snapshot-TAFPVLZN.js} +9 -9
- package/dist/{active-window-2OB2MSCR.js → active-window-MHFMC6NQ.js} +9 -9
- package/dist/{annotate-VDZBZBKZ.js → annotate-5ZFRFQ4B.js} +8 -8
- package/dist/{attr-7XIO4MCH.js → attr-MBF2UCRF.js} +8 -8
- package/dist/browser/browser-manager.d.ts +6 -1
- package/dist/browser/browser-manager.d.ts.map +1 -1
- package/dist/browser/manager-types.d.ts +51 -0
- package/dist/browser/manager-types.d.ts.map +1 -1
- package/dist/browser/ops-browser-manager.d.ts +2 -1
- package/dist/browser/ops-browser-manager.d.ts.map +1 -1
- package/dist/browser/screencast-recorder.d.ts +1 -0
- package/dist/browser/screencast-recorder.d.ts.map +1 -1
- package/dist/{canvas-N4PAA274.js → canvas-CAMD22YU.js} +8 -8
- package/dist/{capture-desktop-T5YO3EBI.js → capture-desktop-TMZSFA5R.js} +9 -9
- package/dist/{capture-window-UKEUBWKH.js → capture-window-NZDKD2AE.js} +9 -9
- package/dist/{check-PQB6KKMN.js → check-MO33GTQ4.js} +8 -8
- package/dist/{checked-RNZIMCU6.js → checked-3HDF5X2M.js} +8 -8
- package/dist/{chunk-YRRRUGSQ.js → chunk-32ZSOZND.js} +2 -2
- package/dist/{chunk-EOX6U6Q4.js → chunk-AHQC4A6P.js} +896 -118
- package/dist/chunk-AHQC4A6P.js.map +1 -0
- package/dist/{chunk-IBIHDGTZ.js → chunk-B5XIJQXO.js} +32 -4
- package/dist/chunk-B5XIJQXO.js.map +1 -0
- package/dist/{chunk-FDBUB7BM.js → chunk-BHZLEFXW.js} +2 -2
- package/dist/{chunk-JROW6ZNN.js → chunk-FJZY3Z3X.js} +3 -3
- package/dist/{chunk-J3KYGJRQ.js → chunk-G6NQ7WYD.js} +2 -2
- package/dist/{chunk-27W46IKI.js → chunk-HM4CO3EW.js} +38 -23
- package/dist/chunk-HM4CO3EW.js.map +1 -0
- package/dist/{chunk-SKFB5ICF.js → chunk-TI5I6UWY.js} +8 -3
- package/dist/chunk-TI5I6UWY.js.map +1 -0
- package/dist/{chunk-52ZIOWVU.js → chunk-UEAXTWGT.js} +3 -3
- package/dist/{chunk-ZGCTC5YM.js → chunk-UVD34RA2.js} +33 -1
- package/dist/chunk-UVD34RA2.js.map +1 -0
- package/dist/{chunk-W6YPVNDX.js → chunk-VTGG5ZU2.js} +2 -2
- package/dist/{chunk-FBKPDILE.js → chunk-WTWSBEBW.js} +5954 -436
- package/dist/chunk-WTWSBEBW.js.map +1 -0
- package/dist/{chunk-NURQB55J.js → chunk-WY72GYAH.js} +2 -2
- package/dist/{chunk-MJF67OTH.js → chunk-XSSPNVMS.js} +3 -3
- package/dist/{chunk-MJF67OTH.js.map → chunk-XSSPNVMS.js.map} +1 -1
- package/dist/{chunk-HMRANSDX.js → chunk-Z3ADLR7I.js} +698 -18
- package/dist/chunk-Z3ADLR7I.js.map +1 -0
- package/dist/cli/commands/inspiredesign.d.ts +12 -1
- package/dist/cli/commands/inspiredesign.d.ts.map +1 -1
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.js +76 -76
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/parse.d.ts +1 -0
- package/dist/cli/utils/parse.d.ts.map +1 -1
- package/dist/cli/utils/workflow-message.d.ts.map +1 -1
- package/dist/{click-U7ZFKSB4.js → click-SWZPJO2U.js} +8 -8
- package/dist/{clone-component-SWYAORTU.js → clone-component-YTB46YU4.js} +7 -7
- package/dist/{clone-page-WJ6UJOJG.js → clone-page-5FMPHQ3A.js} +7 -7
- package/dist/{close-NAVIHZ2T.js → close-22SNMDX3.js} +7 -7
- package/dist/{close-VKIGIKVT.js → close-ORQZCZ2E.js} +7 -7
- package/dist/{connect-XVG2MOZL.js → connect-EWYITNQU.js} +8 -8
- package/dist/{console-poll-XI5BZPL7.js → console-poll-LJR6ZTDK.js} +8 -8
- package/dist/{cookie-import-QELKE7TK.js → cookie-import-PTAIWPEC.js} +7 -7
- package/dist/{cookie-list-QDA6KWIY.js → cookie-list-76C35B5B.js} +7 -7
- package/dist/{daemon-CA4UIIZQ.js → daemon-UKJMDLCB.js} +6 -6
- package/dist/daemon-fingerprint.json +1 -1
- package/dist/{debug-trace-snapshot-AT4GAO57.js → debug-trace-snapshot-PQ5FJART.js} +8 -8
- package/dist/{dialog-O3V2IBFH.js → dialog-WLJDWJV4.js} +8 -8
- package/dist/{disconnect-NAX5TPTG.js → disconnect-FNB4JC2U.js} +7 -7
- package/dist/{enabled-VT4FJXDX.js → enabled-PYMCOQPC.js} +8 -8
- package/dist/{goto-GBJG5NC4.js → goto-UNTEW4VI.js} +8 -8
- package/dist/guidance/context.d.ts +10 -0
- package/dist/guidance/context.d.ts.map +1 -1
- package/dist/guidance/readiness.d.ts.map +1 -1
- package/dist/guidance/recipes/generic.d.ts.map +1 -1
- package/dist/guidance/recipes/pinterest.d.ts.map +1 -1
- package/dist/guidance/recipes/site-recipe-validation.d.ts +27 -0
- package/dist/guidance/recipes/site-recipe-validation.d.ts.map +1 -0
- package/dist/guidance/types.d.ts +5 -0
- package/dist/guidance/types.d.ts.map +1 -1
- package/dist/{help-SUI4H77K.js → help-QOLCIB3P.js} +8 -7
- package/dist/{help-SUI4H77K.js.map → help-QOLCIB3P.js.map} +1 -1
- package/dist/{hover-476ZNQZE.js → hover-ZWY4YOM4.js} +8 -8
- package/dist/{html-5C4TXOV3.js → html-M46YBFT3.js} +8 -8
- package/dist/index.js +83 -23
- package/dist/index.js.map +1 -1
- package/dist/{inspector-73ARPCIV.js → inspector-6YAOI74U.js} +10 -10
- package/dist/{inspector-audit-QT6QY7KS.js → inspector-audit-PF64X6SJ.js} +12 -12
- package/dist/{inspector-plan-JRNSGN2Z.js → inspector-plan-IUGTQV3Q.js} +10 -10
- package/dist/inspiredesign/capture-mode.d.ts +8 -0
- package/dist/inspiredesign/capture-mode.d.ts.map +1 -1
- package/dist/inspiredesign/capture.d.ts +36 -1
- package/dist/inspiredesign/capture.d.ts.map +1 -1
- package/dist/inspiredesign/contract.d.ts +25 -0
- package/dist/inspiredesign/contract.d.ts.map +1 -1
- package/dist/inspiredesign/handoff.d.ts +6 -2
- package/dist/inspiredesign/handoff.d.ts.map +1 -1
- package/dist/inspiredesign/media-analysis/analyzer.d.ts +13 -0
- package/dist/inspiredesign/media-analysis/analyzer.d.ts.map +1 -0
- package/dist/inspiredesign/media-analysis/design-guidance.d.ts +11 -0
- package/dist/inspiredesign/media-analysis/design-guidance.d.ts.map +1 -0
- package/dist/inspiredesign/media-analysis/ffmpeg.d.ts +21 -0
- package/dist/inspiredesign/media-analysis/ffmpeg.d.ts.map +1 -0
- package/dist/inspiredesign/media-analysis/ffprobe.d.ts +8 -0
- package/dist/inspiredesign/media-analysis/ffprobe.d.ts.map +1 -0
- package/dist/inspiredesign/media-analysis/index.d.ts +10 -0
- package/dist/inspiredesign/media-analysis/index.d.ts.map +1 -0
- package/dist/inspiredesign/media-analysis/persist.d.ts +6 -0
- package/dist/inspiredesign/media-analysis/persist.d.ts.map +1 -0
- package/dist/inspiredesign/media-analysis/pixel.d.ts +9 -0
- package/dist/inspiredesign/media-analysis/pixel.d.ts.map +1 -0
- package/dist/inspiredesign/media-analysis/types.d.ts +163 -0
- package/dist/inspiredesign/media-analysis/types.d.ts.map +1 -0
- package/dist/inspiredesign/media-analysis/typography-structure.d.ts +3 -0
- package/dist/inspiredesign/media-analysis/typography-structure.d.ts.map +1 -0
- package/dist/inspiredesign/meta-prompt.d.ts.map +1 -1
- package/dist/inspiredesign/motion-evidence.d.ts +73 -0
- package/dist/inspiredesign/motion-evidence.d.ts.map +1 -0
- package/dist/inspiredesign/pinterest-media-classification.d.ts +27 -0
- package/dist/inspiredesign/pinterest-media-classification.d.ts.map +1 -0
- package/dist/inspiredesign/pinterest-pin-media-evidence.d.ts +151 -0
- package/dist/inspiredesign/pinterest-pin-media-evidence.d.ts.map +1 -0
- package/dist/inspiredesign/product-readiness.d.ts +97 -0
- package/dist/inspiredesign/product-readiness.d.ts.map +1 -0
- package/dist/inspiredesign/reference-pattern-board.d.ts +32 -2
- package/dist/inspiredesign/reference-pattern-board.d.ts.map +1 -1
- package/dist/inspiredesign/visual-evidence.d.ts +5 -0
- package/dist/inspiredesign/visual-evidence.d.ts.map +1 -1
- package/dist/{inspiredesign-IPVZDLSQ.js → inspiredesign-GZIEXETS.js} +101 -31
- package/dist/inspiredesign-GZIEXETS.js.map +1 -0
- package/dist/{launch-B35YDRQC.js → launch-I7WNLWLY.js} +8 -8
- package/dist/{list-YETWKTKY.js → list-BAECFJI7.js} +7 -7
- package/dist/{list-JV55JVGB.js → list-BCF4HZ2K.js} +7 -7
- package/dist/{macro-resolve-DQK4B3W3.js → macro-resolve-4GNZYHHW.js} +9 -9
- package/dist/{network-poll-4GWHCJXI.js → network-poll-DCZ5ZNLP.js} +8 -8
- package/dist/{new-XDCQPIEG.js → new-6KZYJTJG.js} +7 -7
- package/dist/{open-GIM3ZCSV.js → open-JPGEAJHJ.js} +7 -7
- package/dist/opendevbrowser.js +83 -23
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/{perf-26VBXDPI.js → perf-5X367PRP.js} +8 -8
- package/dist/{pointer-down-O3VSNAXW.js → pointer-down-5OAUDDNR.js} +9 -9
- package/dist/{pointer-drag-WQ5QGE6J.js → pointer-drag-LIW5PY5P.js} +9 -9
- package/dist/{pointer-move-4N4D7JY2.js → pointer-move-7AMURLJD.js} +9 -9
- package/dist/{pointer-up-CQC4NPDX.js → pointer-up-EY652YWL.js} +9 -9
- package/dist/{press-XGJD45CU.js → press-UIAE5XEF.js} +8 -8
- package/dist/{product-video-HD4ZOUI7.js → product-video-B6TLS7VC.js} +10 -10
- package/dist/providers/browser-native-discovery.d.ts.map +1 -1
- package/dist/providers/browser-output-artifacts.d.ts +13 -0
- package/dist/providers/browser-output-artifacts.d.ts.map +1 -0
- package/dist/providers/renderer.d.ts +10 -1
- package/dist/providers/renderer.d.ts.map +1 -1
- package/dist/providers/workflows.d.ts +53 -2
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/{providers-KKNPJSQK.js → providers-AERTX6X4.js} +5 -3
- package/dist/public-surface/generated-manifest.d.ts +4 -4
- package/dist/public-surface/generated-manifest.d.ts.map +1 -1
- package/dist/public-surface/source.d.ts +2 -2
- package/dist/public-surface/source.d.ts.map +1 -1
- package/dist/{research-VUWWEQ4R.js → research-AJH6ECYW.js} +10 -10
- package/dist/{review-LZ3TA7U7.js → review-RN6XF2YB.js} +9 -9
- package/dist/{review-desktop-LAO7U7T3.js → review-desktop-UJOUS7K2.js} +9 -9
- package/dist/{rpc-HKNIVFGC.js → rpc-VS5Y5FUT.js} +8 -8
- package/dist/{run-SHCF53FO.js → run-EVRIQW7S.js} +6 -6
- package/dist/{screencast-start-JHMQZVWJ.js → screencast-start-U6J4FYU4.js} +8 -8
- package/dist/{screencast-stop-RWQTWWQS.js → screencast-stop-EQUPRGMP.js} +8 -8
- package/dist/{screenshot-QHFYO6PB.js → screenshot-BENYGC36.js} +8 -8
- package/dist/{scroll-L3FTMAV4.js → scroll-3OALQLX2.js} +8 -8
- package/dist/{scroll-into-view-JVDHX4WU.js → scroll-into-view-SNZKBIVB.js} +8 -8
- package/dist/{select-X4BO7GTB.js → select-JDZDDC3Y.js} +8 -8
- package/dist/{serve-JIMIBCNO.js → serve-LOC6ESJ4.js} +7 -7
- package/dist/{shopping-EGSDP2GL.js → shopping-267OAYGM.js} +10 -10
- package/dist/{snapshot-QGJ7RDNV.js → snapshot-ASYI5UFR.js} +8 -8
- package/dist/{status-CKGPNYIH.js → status-47CI4LJX.js} +7 -7
- package/dist/{status-LEBY2X7N.js → status-N4O6DJTF.js} +9 -9
- package/dist/{status-capabilities-6QTWNGKM.js → status-capabilities-C777JZG4.js} +9 -9
- package/dist/{text-VUZU7D3L.js → text-MS2653MW.js} +8 -8
- package/dist/tools/inspiredesign_run.d.ts.map +1 -1
- package/dist/tools/product_video_run.d.ts.map +1 -1
- package/dist/{type-N5SURP74.js → type-UMPSDACC.js} +8 -8
- package/dist/{uncheck-JFMK3SSY.js → uncheck-2OZ56D42.js} +8 -8
- package/dist/{upload-KFUYLL7M.js → upload-CD7PRH54.js} +8 -8
- package/dist/{use-CNMPP2ED.js → use-MO67AGG7.js} +7 -7
- package/dist/{value-J335MPZE.js → value-4GI2LRUY.js} +8 -8
- package/dist/{visible-YQZWWPBZ.js → visible-VSUFGRFZ.js} +8 -8
- package/dist/{wait-IC7YJJPJ.js → wait-OQYMFENT.js} +8 -8
- package/dist/{windows-AGVQ3KX3.js → windows-75W2JCW7.js} +9 -9
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
- package/skills/opendevbrowser-best-practices/SKILL.md +41 -30
- package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +12 -8
- package/skills/opendevbrowser-best-practices/artifacts/parity-gates.md +1 -0
- package/skills/opendevbrowser-best-practices/artifacts/provider-workflows.md +19 -0
- package/skills/opendevbrowser-best-practices/assets/templates/mode-flag-matrix.json +23 -13
- package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +3 -1
- package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +62 -21
- package/skills/opendevbrowser-best-practices/scripts/resolve-odb-cli.sh +28 -0
- package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +15 -0
- package/skills/opendevbrowser-best-practices/scripts/validator-fixture-cli.sh +13 -0
- package/skills/opendevbrowser-design-agent/SKILL.md +2 -0
- package/skills/opendevbrowser-design-agent/artifacts/design-workflows.md +15 -13
- package/skills/opendevbrowser-design-agent/artifacts/isolated-preview-validation.md +1 -1
- package/skills/opendevbrowser-design-agent/artifacts/research-harvest-workflow.md +14 -7
- package/skills/opendevbrowser-design-agent/assets/templates/reference-pattern-board.v1.json +1 -0
- package/skills/opendevbrowser-design-agent/scripts/design-workflow.sh +10 -7
- package/skills/opendevbrowser-motion-design/SKILL.md +1 -1
- package/skills/opendevbrowser-product-presentation-asset/SKILL.md +5 -4
- package/skills/opendevbrowser-product-presentation-asset/scripts/capture-screenshots.sh +1 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/collect-product.sh +1 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/download-images.sh +1 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/validate-skill-assets.sh +4 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/write-manifest.sh +1 -0
- package/skills/opendevbrowser-research/SKILL.md +1 -0
- package/skills/opendevbrowser-research/scripts/render-output.sh +1 -0
- package/skills/opendevbrowser-research/scripts/run-research.sh +1 -0
- package/skills/opendevbrowser-research/scripts/validate-skill-assets.sh +4 -0
- package/skills/opendevbrowser-research/scripts/write-artifacts.sh +1 -0
- package/skills/opendevbrowser-shopping/SKILL.md +1 -0
- package/skills/opendevbrowser-shopping/scripts/normalize-offers.sh +1 -0
- package/skills/opendevbrowser-shopping/scripts/run-deal-hunt.sh +1 -0
- package/skills/opendevbrowser-shopping/scripts/run-shopping.sh +1 -0
- package/skills/opendevbrowser-shopping/scripts/validate-skill-assets.sh +4 -0
- package/dist/chunk-27W46IKI.js.map +0 -1
- package/dist/chunk-EOX6U6Q4.js.map +0 -1
- package/dist/chunk-FBKPDILE.js.map +0 -1
- package/dist/chunk-HMRANSDX.js.map +0 -1
- package/dist/chunk-IBIHDGTZ.js.map +0 -1
- package/dist/chunk-SKFB5ICF.js.map +0 -1
- package/dist/chunk-ZGCTC5YM.js.map +0 -1
- package/dist/inspiredesign-IPVZDLSQ.js.map +0 -1
- /package/dist/{accessibility-snapshot-JSPFVWZ6.js.map → accessibility-snapshot-TAFPVLZN.js.map} +0 -0
- /package/dist/{active-window-2OB2MSCR.js.map → active-window-MHFMC6NQ.js.map} +0 -0
- /package/dist/{annotate-VDZBZBKZ.js.map → annotate-5ZFRFQ4B.js.map} +0 -0
- /package/dist/{attr-7XIO4MCH.js.map → attr-MBF2UCRF.js.map} +0 -0
- /package/dist/{canvas-N4PAA274.js.map → canvas-CAMD22YU.js.map} +0 -0
- /package/dist/{capture-desktop-T5YO3EBI.js.map → capture-desktop-TMZSFA5R.js.map} +0 -0
- /package/dist/{capture-window-UKEUBWKH.js.map → capture-window-NZDKD2AE.js.map} +0 -0
- /package/dist/{check-PQB6KKMN.js.map → check-MO33GTQ4.js.map} +0 -0
- /package/dist/{checked-RNZIMCU6.js.map → checked-3HDF5X2M.js.map} +0 -0
- /package/dist/{chunk-YRRRUGSQ.js.map → chunk-32ZSOZND.js.map} +0 -0
- /package/dist/{chunk-FDBUB7BM.js.map → chunk-BHZLEFXW.js.map} +0 -0
- /package/dist/{chunk-JROW6ZNN.js.map → chunk-FJZY3Z3X.js.map} +0 -0
- /package/dist/{chunk-J3KYGJRQ.js.map → chunk-G6NQ7WYD.js.map} +0 -0
- /package/dist/{chunk-52ZIOWVU.js.map → chunk-UEAXTWGT.js.map} +0 -0
- /package/dist/{chunk-W6YPVNDX.js.map → chunk-VTGG5ZU2.js.map} +0 -0
- /package/dist/{chunk-NURQB55J.js.map → chunk-WY72GYAH.js.map} +0 -0
- /package/dist/{click-U7ZFKSB4.js.map → click-SWZPJO2U.js.map} +0 -0
- /package/dist/{clone-component-SWYAORTU.js.map → clone-component-YTB46YU4.js.map} +0 -0
- /package/dist/{clone-page-WJ6UJOJG.js.map → clone-page-5FMPHQ3A.js.map} +0 -0
- /package/dist/{close-NAVIHZ2T.js.map → close-22SNMDX3.js.map} +0 -0
- /package/dist/{close-VKIGIKVT.js.map → close-ORQZCZ2E.js.map} +0 -0
- /package/dist/{connect-XVG2MOZL.js.map → connect-EWYITNQU.js.map} +0 -0
- /package/dist/{console-poll-XI5BZPL7.js.map → console-poll-LJR6ZTDK.js.map} +0 -0
- /package/dist/{cookie-import-QELKE7TK.js.map → cookie-import-PTAIWPEC.js.map} +0 -0
- /package/dist/{cookie-list-QDA6KWIY.js.map → cookie-list-76C35B5B.js.map} +0 -0
- /package/dist/{daemon-CA4UIIZQ.js.map → daemon-UKJMDLCB.js.map} +0 -0
- /package/dist/{debug-trace-snapshot-AT4GAO57.js.map → debug-trace-snapshot-PQ5FJART.js.map} +0 -0
- /package/dist/{dialog-O3V2IBFH.js.map → dialog-WLJDWJV4.js.map} +0 -0
- /package/dist/{disconnect-NAX5TPTG.js.map → disconnect-FNB4JC2U.js.map} +0 -0
- /package/dist/{enabled-VT4FJXDX.js.map → enabled-PYMCOQPC.js.map} +0 -0
- /package/dist/{goto-GBJG5NC4.js.map → goto-UNTEW4VI.js.map} +0 -0
- /package/dist/{hover-476ZNQZE.js.map → hover-ZWY4YOM4.js.map} +0 -0
- /package/dist/{html-5C4TXOV3.js.map → html-M46YBFT3.js.map} +0 -0
- /package/dist/{inspector-73ARPCIV.js.map → inspector-6YAOI74U.js.map} +0 -0
- /package/dist/{inspector-audit-QT6QY7KS.js.map → inspector-audit-PF64X6SJ.js.map} +0 -0
- /package/dist/{inspector-plan-JRNSGN2Z.js.map → inspector-plan-IUGTQV3Q.js.map} +0 -0
- /package/dist/{launch-B35YDRQC.js.map → launch-I7WNLWLY.js.map} +0 -0
- /package/dist/{list-YETWKTKY.js.map → list-BAECFJI7.js.map} +0 -0
- /package/dist/{list-JV55JVGB.js.map → list-BCF4HZ2K.js.map} +0 -0
- /package/dist/{macro-resolve-DQK4B3W3.js.map → macro-resolve-4GNZYHHW.js.map} +0 -0
- /package/dist/{network-poll-4GWHCJXI.js.map → network-poll-DCZ5ZNLP.js.map} +0 -0
- /package/dist/{new-XDCQPIEG.js.map → new-6KZYJTJG.js.map} +0 -0
- /package/dist/{open-GIM3ZCSV.js.map → open-JPGEAJHJ.js.map} +0 -0
- /package/dist/{perf-26VBXDPI.js.map → perf-5X367PRP.js.map} +0 -0
- /package/dist/{pointer-down-O3VSNAXW.js.map → pointer-down-5OAUDDNR.js.map} +0 -0
- /package/dist/{pointer-drag-WQ5QGE6J.js.map → pointer-drag-LIW5PY5P.js.map} +0 -0
- /package/dist/{pointer-move-4N4D7JY2.js.map → pointer-move-7AMURLJD.js.map} +0 -0
- /package/dist/{pointer-up-CQC4NPDX.js.map → pointer-up-EY652YWL.js.map} +0 -0
- /package/dist/{press-XGJD45CU.js.map → press-UIAE5XEF.js.map} +0 -0
- /package/dist/{product-video-HD4ZOUI7.js.map → product-video-B6TLS7VC.js.map} +0 -0
- /package/dist/{providers-KKNPJSQK.js.map → providers-AERTX6X4.js.map} +0 -0
- /package/dist/{research-VUWWEQ4R.js.map → research-AJH6ECYW.js.map} +0 -0
- /package/dist/{review-LZ3TA7U7.js.map → review-RN6XF2YB.js.map} +0 -0
- /package/dist/{review-desktop-LAO7U7T3.js.map → review-desktop-UJOUS7K2.js.map} +0 -0
- /package/dist/{rpc-HKNIVFGC.js.map → rpc-VS5Y5FUT.js.map} +0 -0
- /package/dist/{run-SHCF53FO.js.map → run-EVRIQW7S.js.map} +0 -0
- /package/dist/{screencast-start-JHMQZVWJ.js.map → screencast-start-U6J4FYU4.js.map} +0 -0
- /package/dist/{screencast-stop-RWQTWWQS.js.map → screencast-stop-EQUPRGMP.js.map} +0 -0
- /package/dist/{screenshot-QHFYO6PB.js.map → screenshot-BENYGC36.js.map} +0 -0
- /package/dist/{scroll-L3FTMAV4.js.map → scroll-3OALQLX2.js.map} +0 -0
- /package/dist/{scroll-into-view-JVDHX4WU.js.map → scroll-into-view-SNZKBIVB.js.map} +0 -0
- /package/dist/{select-X4BO7GTB.js.map → select-JDZDDC3Y.js.map} +0 -0
- /package/dist/{serve-JIMIBCNO.js.map → serve-LOC6ESJ4.js.map} +0 -0
- /package/dist/{shopping-EGSDP2GL.js.map → shopping-267OAYGM.js.map} +0 -0
- /package/dist/{snapshot-QGJ7RDNV.js.map → snapshot-ASYI5UFR.js.map} +0 -0
- /package/dist/{status-CKGPNYIH.js.map → status-47CI4LJX.js.map} +0 -0
- /package/dist/{status-LEBY2X7N.js.map → status-N4O6DJTF.js.map} +0 -0
- /package/dist/{status-capabilities-6QTWNGKM.js.map → status-capabilities-C777JZG4.js.map} +0 -0
- /package/dist/{text-VUZU7D3L.js.map → text-MS2653MW.js.map} +0 -0
- /package/dist/{type-N5SURP74.js.map → type-UMPSDACC.js.map} +0 -0
- /package/dist/{uncheck-JFMK3SSY.js.map → uncheck-2OZ56D42.js.map} +0 -0
- /package/dist/{upload-KFUYLL7M.js.map → upload-CD7PRH54.js.map} +0 -0
- /package/dist/{use-CNMPP2ED.js.map → use-MO67AGG7.js.map} +0 -0
- /package/dist/{value-J335MPZE.js.map → value-4GI2LRUY.js.map} +0 -0
- /package/dist/{visible-YQZWWPBZ.js.map → visible-VSUFGRFZ.js.map} +0 -0
- /package/dist/{wait-IC7YJJPJ.js.map → wait-OQYMFENT.js.map} +0 -0
- /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-
|
|
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
|
|
3666
|
-
import {
|
|
3667
|
-
import {
|
|
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
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
-
|
|
5971
|
-
|
|
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
|
-
|
|
6078
|
-
|
|
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(
|
|
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
|
|
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 ??
|
|
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
|
|
6321
|
-
import { isAbsolute as isAbsolute2, join as
|
|
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,
|
|
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
|
-
|
|
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 ??
|
|
6524
|
+
this.screencastId = args2.screencastId ?? randomUUID10();
|
|
6494
6525
|
this.sessionId = args2.sessionId;
|
|
6495
6526
|
this.targetId = args2.targetId;
|
|
6496
|
-
|
|
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 =
|
|
6502
|
-
this.manifestPath =
|
|
6503
|
-
this.replayHtmlPath =
|
|
6504
|
-
this.previewPath =
|
|
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 =
|
|
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(
|
|
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 :
|
|
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 =
|
|
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:
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
13002
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
12225
13003
|
import { existsSync as existsSync2 } from "fs";
|
|
12226
|
-
import { join as
|
|
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 =
|
|
12242
|
-
const stylePath =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
13647
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
12870
13648
|
import { mkdir as mkdir9 } from "fs/promises";
|
|
12871
|
-
import { dirname as
|
|
13649
|
+
import { dirname as dirname6 } from "path";
|
|
12872
13650
|
|
|
12873
13651
|
// src/browser/canvas-client.ts
|
|
12874
|
-
import { randomUUID as
|
|
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 =
|
|
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 =
|
|
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
|
|
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_${
|
|
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_${
|
|
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_${
|
|
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_${
|
|
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_${
|
|
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_${
|
|
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_${
|
|
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
|
|
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
|
|
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
|
|
25906
|
+
return join13(worktree, ".opendevbrowser", "canvas", "code-sync", documentId, `${bindingId}.json`);
|
|
25129
25907
|
}
|
|
25130
25908
|
function resolveCanvasFigmaAssetDir(worktree, fileKey) {
|
|
25131
|
-
return
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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 :
|
|
26465
|
+
const manifestPath2 = direct.endsWith(".json") ? direct : join14(direct, "canvas-adapter.plugin.json");
|
|
25688
26466
|
return {
|
|
25689
|
-
packageRoot: direct.endsWith(".json") ?
|
|
26467
|
+
packageRoot: direct.endsWith(".json") ? dirname4(direct) : direct,
|
|
25690
26468
|
manifestPath: manifestPath2
|
|
25691
26469
|
};
|
|
25692
26470
|
}
|
|
25693
|
-
const nodeModulesPath =
|
|
25694
|
-
const manifestPath =
|
|
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 =
|
|
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 =
|
|
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
|
|
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_${
|
|
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
|
|
28117
|
+
import { dirname as dirname5 } from "path";
|
|
27340
28118
|
async function writeCodeSyncSource(repoPath, sourceText) {
|
|
27341
|
-
await mkdir7(
|
|
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
|
|
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_${
|
|
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_${
|
|
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_${
|
|
29679
|
-
const leaseId = `lease_${
|
|
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_${
|
|
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_${
|
|
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(
|
|
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_${
|
|
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_${
|
|
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_${
|
|
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_${
|
|
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_${
|
|
32687
|
-
const eyebrowNodeId = `node_starter_${
|
|
32688
|
-
const headlineNodeId = `node_starter_${
|
|
32689
|
-
const bodyNodeId = `node_starter_${
|
|
32690
|
-
const actionNodeId = definition.shell.actionLabel ? `node_starter_${
|
|
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(
|
|
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_${
|
|
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_${
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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-
|
|
36216
|
+
//# sourceMappingURL=chunk-AHQC4A6P.js.map
|