opendevbrowser 0.0.34 → 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-VCBXK47S.js → accessibility-snapshot-TAFPVLZN.js} +8 -8
- package/dist/{active-window-7EUN36LZ.js → active-window-MHFMC6NQ.js} +8 -8
- package/dist/{annotate-VLBK7YB6.js → annotate-5ZFRFQ4B.js} +7 -7
- package/dist/{attr-JNANQKM6.js → attr-MBF2UCRF.js} +7 -7
- 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 +48 -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/{canvas-V5LO4JVL.js → canvas-CAMD22YU.js} +7 -7
- package/dist/{capture-desktop-FKVDWTVG.js → capture-desktop-TMZSFA5R.js} +8 -8
- package/dist/{capture-window-QVPM2DN2.js → capture-window-NZDKD2AE.js} +8 -8
- package/dist/{check-V3CWZ56S.js → check-MO33GTQ4.js} +7 -7
- package/dist/{checked-Q27Q6YZN.js → checked-3HDF5X2M.js} +7 -7
- package/dist/{chunk-VX47SJZM.js → chunk-32ZSOZND.js} +2 -2
- package/dist/{chunk-XRDCSHKZ.js → chunk-AHQC4A6P.js} +744 -14
- 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-OJAUKABV.js → chunk-BHZLEFXW.js} +2 -2
- package/dist/{chunk-VY47VKXU.js → chunk-FJZY3Z3X.js} +2 -2
- package/dist/{chunk-GC2FWISX.js → chunk-HM4CO3EW.js} +20 -16
- package/dist/chunk-HM4CO3EW.js.map +1 -0
- package/dist/{chunk-Z3HIX2SE.js → chunk-UEAXTWGT.js} +2 -2
- package/dist/{chunk-ZGCTC5YM.js → chunk-UVD34RA2.js} +33 -1
- package/dist/chunk-UVD34RA2.js.map +1 -0
- package/dist/{chunk-5FDXH4CS.js → chunk-WTWSBEBW.js} +5659 -419
- package/dist/chunk-WTWSBEBW.js.map +1 -0
- package/dist/{chunk-NX2XYJP5.js → chunk-XSSPNVMS.js} +3 -3
- package/dist/{chunk-NX2XYJP5.js.map → chunk-XSSPNVMS.js.map} +1 -1
- package/dist/{chunk-QXJDJDSZ.js → chunk-Z3ADLR7I.js} +667 -8
- 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/workflow-message.d.ts.map +1 -1
- package/dist/{click-EQDRSLR3.js → click-SWZPJO2U.js} +7 -7
- package/dist/{clone-component-SISUXTJS.js → clone-component-YTB46YU4.js} +7 -7
- package/dist/{clone-page-MLDPCBOY.js → clone-page-5FMPHQ3A.js} +7 -7
- package/dist/{close-7J7EV237.js → close-22SNMDX3.js} +7 -7
- package/dist/{close-2LQMJVOA.js → close-ORQZCZ2E.js} +7 -7
- package/dist/{connect-JFRSIW5M.js → connect-EWYITNQU.js} +7 -7
- package/dist/{console-poll-NSVVUNEC.js → console-poll-LJR6ZTDK.js} +7 -7
- package/dist/{cookie-import-B7IQTGTN.js → cookie-import-PTAIWPEC.js} +7 -7
- package/dist/{cookie-list-YHG7JCZZ.js → cookie-list-76C35B5B.js} +7 -7
- package/dist/{daemon-ENU4FOV4.js → daemon-UKJMDLCB.js} +6 -6
- package/dist/daemon-fingerprint.json +1 -1
- package/dist/{debug-trace-snapshot-KLGU2AWY.js → debug-trace-snapshot-PQ5FJART.js} +7 -7
- package/dist/{dialog-MUVQIERS.js → dialog-WLJDWJV4.js} +7 -7
- package/dist/{disconnect-KELQJ45J.js → disconnect-FNB4JC2U.js} +7 -7
- package/dist/{enabled-SF6UU5HG.js → enabled-PYMCOQPC.js} +7 -7
- package/dist/{goto-AZQWXYPG.js → goto-UNTEW4VI.js} +7 -7
- 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/types.d.ts +4 -0
- package/dist/guidance/types.d.ts.map +1 -1
- package/dist/{help-B44IBHXL.js → help-QOLCIB3P.js} +8 -7
- package/dist/{help-B44IBHXL.js.map → help-QOLCIB3P.js.map} +1 -1
- package/dist/{hover-MQRAKKVU.js → hover-ZWY4YOM4.js} +7 -7
- package/dist/{html-PLRTU2WS.js → html-M46YBFT3.js} +7 -7
- package/dist/index.js +43 -18
- package/dist/index.js.map +1 -1
- package/dist/{inspector-IY4GBIT6.js → inspector-6YAOI74U.js} +8 -8
- package/dist/{inspector-audit-7MQCRJHD.js → inspector-audit-PF64X6SJ.js} +9 -9
- package/dist/{inspector-plan-ZAUDHBET.js → inspector-plan-IUGTQV3Q.js} +9 -9
- 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 +24 -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 +27 -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-VHPEO3UK.js → inspiredesign-GZIEXETS.js} +29 -12
- package/dist/inspiredesign-GZIEXETS.js.map +1 -0
- package/dist/{launch-OCTWPTV5.js → launch-I7WNLWLY.js} +7 -7
- package/dist/{list-HUSYADUS.js → list-BAECFJI7.js} +7 -7
- package/dist/{list-JWKAMAUA.js → list-BCF4HZ2K.js} +7 -7
- package/dist/{macro-resolve-WOXMPZDQ.js → macro-resolve-4GNZYHHW.js} +8 -8
- package/dist/{network-poll-WHB62OEF.js → network-poll-DCZ5ZNLP.js} +7 -7
- package/dist/{new-IKZBYBNK.js → new-6KZYJTJG.js} +7 -7
- package/dist/{open-UA2VI6ZP.js → open-JPGEAJHJ.js} +7 -7
- package/dist/opendevbrowser.js +43 -18
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/{perf-DICS3VKH.js → perf-5X367PRP.js} +7 -7
- package/dist/{pointer-down-2XPRZFJC.js → pointer-down-5OAUDDNR.js} +7 -7
- package/dist/{pointer-drag-7NY4BOLH.js → pointer-drag-LIW5PY5P.js} +7 -7
- package/dist/{pointer-move-FWEXMH37.js → pointer-move-7AMURLJD.js} +7 -7
- package/dist/{pointer-up-VU2OHK5D.js → pointer-up-EY652YWL.js} +7 -7
- package/dist/{press-W7IZ3FCX.js → press-UIAE5XEF.js} +7 -7
- package/dist/{product-video-XCZ6CHR5.js → product-video-B6TLS7VC.js} +9 -9
- package/dist/providers/browser-native-discovery.d.ts.map +1 -1
- 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-XCNSU3T6.js → providers-AERTX6X4.js} +5 -3
- package/dist/public-surface/generated-manifest.d.ts +2 -2
- 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-AYCKHOWK.js → research-AJH6ECYW.js} +9 -9
- package/dist/{review-PP2UNSMJ.js → review-RN6XF2YB.js} +7 -7
- package/dist/{review-desktop-3JOJFUEJ.js → review-desktop-UJOUS7K2.js} +7 -7
- package/dist/{rpc-7EPTJQQ6.js → rpc-VS5Y5FUT.js} +7 -7
- package/dist/{run-P6UJS3D4.js → run-EVRIQW7S.js} +5 -5
- package/dist/{screencast-start-ZZYNH2HT.js → screencast-start-U6J4FYU4.js} +7 -7
- package/dist/{screencast-stop-Y6ADFOFA.js → screencast-stop-EQUPRGMP.js} +7 -7
- package/dist/{screenshot-CJB7PMAF.js → screenshot-BENYGC36.js} +7 -7
- package/dist/{scroll-BP5MA4ZT.js → scroll-3OALQLX2.js} +7 -7
- package/dist/{scroll-into-view-O3RDWLM2.js → scroll-into-view-SNZKBIVB.js} +7 -7
- package/dist/{select-QLCNRI36.js → select-JDZDDC3Y.js} +7 -7
- package/dist/{serve-OO2MQWGL.js → serve-LOC6ESJ4.js} +6 -6
- package/dist/{shopping-UYHCYPAH.js → shopping-267OAYGM.js} +9 -9
- package/dist/{snapshot-SXYZ3CMC.js → snapshot-ASYI5UFR.js} +7 -7
- package/dist/{status-AL2AHVA5.js → status-47CI4LJX.js} +7 -7
- package/dist/{status-QQW7REK4.js → status-N4O6DJTF.js} +8 -8
- package/dist/{status-capabilities-AVHJYQQQ.js → status-capabilities-C777JZG4.js} +8 -8
- package/dist/{text-B6Z47EOA.js → text-MS2653MW.js} +7 -7
- package/dist/tools/inspiredesign_run.d.ts.map +1 -1
- package/dist/{type-LR3F3SQY.js → type-UMPSDACC.js} +7 -7
- package/dist/{uncheck-5PJEHR7J.js → uncheck-2OZ56D42.js} +7 -7
- package/dist/{upload-HQ3QN2OW.js → upload-CD7PRH54.js} +7 -7
- package/dist/{use-KFZLMRUH.js → use-MO67AGG7.js} +7 -7
- package/dist/{value-TKUFUK5I.js → value-4GI2LRUY.js} +7 -7
- package/dist/{visible-P5Z2N2QR.js → visible-VSUFGRFZ.js} +7 -7
- package/dist/{wait-BYSHJPSC.js → wait-OQYMFENT.js} +7 -7
- package/dist/{windows-6GTD25EU.js → windows-75W2JCW7.js} +8 -8
- 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-5FDXH4CS.js.map +0 -1
- package/dist/chunk-GC2FWISX.js.map +0 -1
- package/dist/chunk-IBIHDGTZ.js.map +0 -1
- package/dist/chunk-QXJDJDSZ.js.map +0 -1
- package/dist/chunk-XRDCSHKZ.js.map +0 -1
- package/dist/chunk-ZGCTC5YM.js.map +0 -1
- package/dist/inspiredesign-VHPEO3UK.js.map +0 -1
- /package/dist/{accessibility-snapshot-VCBXK47S.js.map → accessibility-snapshot-TAFPVLZN.js.map} +0 -0
- /package/dist/{active-window-7EUN36LZ.js.map → active-window-MHFMC6NQ.js.map} +0 -0
- /package/dist/{annotate-VLBK7YB6.js.map → annotate-5ZFRFQ4B.js.map} +0 -0
- /package/dist/{attr-JNANQKM6.js.map → attr-MBF2UCRF.js.map} +0 -0
- /package/dist/{canvas-V5LO4JVL.js.map → canvas-CAMD22YU.js.map} +0 -0
- /package/dist/{capture-desktop-FKVDWTVG.js.map → capture-desktop-TMZSFA5R.js.map} +0 -0
- /package/dist/{capture-window-QVPM2DN2.js.map → capture-window-NZDKD2AE.js.map} +0 -0
- /package/dist/{check-V3CWZ56S.js.map → check-MO33GTQ4.js.map} +0 -0
- /package/dist/{checked-Q27Q6YZN.js.map → checked-3HDF5X2M.js.map} +0 -0
- /package/dist/{chunk-VX47SJZM.js.map → chunk-32ZSOZND.js.map} +0 -0
- /package/dist/{chunk-OJAUKABV.js.map → chunk-BHZLEFXW.js.map} +0 -0
- /package/dist/{chunk-VY47VKXU.js.map → chunk-FJZY3Z3X.js.map} +0 -0
- /package/dist/{chunk-Z3HIX2SE.js.map → chunk-UEAXTWGT.js.map} +0 -0
- /package/dist/{click-EQDRSLR3.js.map → click-SWZPJO2U.js.map} +0 -0
- /package/dist/{clone-component-SISUXTJS.js.map → clone-component-YTB46YU4.js.map} +0 -0
- /package/dist/{clone-page-MLDPCBOY.js.map → clone-page-5FMPHQ3A.js.map} +0 -0
- /package/dist/{close-7J7EV237.js.map → close-22SNMDX3.js.map} +0 -0
- /package/dist/{close-2LQMJVOA.js.map → close-ORQZCZ2E.js.map} +0 -0
- /package/dist/{connect-JFRSIW5M.js.map → connect-EWYITNQU.js.map} +0 -0
- /package/dist/{console-poll-NSVVUNEC.js.map → console-poll-LJR6ZTDK.js.map} +0 -0
- /package/dist/{cookie-import-B7IQTGTN.js.map → cookie-import-PTAIWPEC.js.map} +0 -0
- /package/dist/{cookie-list-YHG7JCZZ.js.map → cookie-list-76C35B5B.js.map} +0 -0
- /package/dist/{daemon-ENU4FOV4.js.map → daemon-UKJMDLCB.js.map} +0 -0
- /package/dist/{debug-trace-snapshot-KLGU2AWY.js.map → debug-trace-snapshot-PQ5FJART.js.map} +0 -0
- /package/dist/{dialog-MUVQIERS.js.map → dialog-WLJDWJV4.js.map} +0 -0
- /package/dist/{disconnect-KELQJ45J.js.map → disconnect-FNB4JC2U.js.map} +0 -0
- /package/dist/{enabled-SF6UU5HG.js.map → enabled-PYMCOQPC.js.map} +0 -0
- /package/dist/{goto-AZQWXYPG.js.map → goto-UNTEW4VI.js.map} +0 -0
- /package/dist/{hover-MQRAKKVU.js.map → hover-ZWY4YOM4.js.map} +0 -0
- /package/dist/{html-PLRTU2WS.js.map → html-M46YBFT3.js.map} +0 -0
- /package/dist/{inspector-IY4GBIT6.js.map → inspector-6YAOI74U.js.map} +0 -0
- /package/dist/{inspector-audit-7MQCRJHD.js.map → inspector-audit-PF64X6SJ.js.map} +0 -0
- /package/dist/{inspector-plan-ZAUDHBET.js.map → inspector-plan-IUGTQV3Q.js.map} +0 -0
- /package/dist/{launch-OCTWPTV5.js.map → launch-I7WNLWLY.js.map} +0 -0
- /package/dist/{list-HUSYADUS.js.map → list-BAECFJI7.js.map} +0 -0
- /package/dist/{list-JWKAMAUA.js.map → list-BCF4HZ2K.js.map} +0 -0
- /package/dist/{macro-resolve-WOXMPZDQ.js.map → macro-resolve-4GNZYHHW.js.map} +0 -0
- /package/dist/{network-poll-WHB62OEF.js.map → network-poll-DCZ5ZNLP.js.map} +0 -0
- /package/dist/{new-IKZBYBNK.js.map → new-6KZYJTJG.js.map} +0 -0
- /package/dist/{open-UA2VI6ZP.js.map → open-JPGEAJHJ.js.map} +0 -0
- /package/dist/{perf-DICS3VKH.js.map → perf-5X367PRP.js.map} +0 -0
- /package/dist/{pointer-down-2XPRZFJC.js.map → pointer-down-5OAUDDNR.js.map} +0 -0
- /package/dist/{pointer-drag-7NY4BOLH.js.map → pointer-drag-LIW5PY5P.js.map} +0 -0
- /package/dist/{pointer-move-FWEXMH37.js.map → pointer-move-7AMURLJD.js.map} +0 -0
- /package/dist/{pointer-up-VU2OHK5D.js.map → pointer-up-EY652YWL.js.map} +0 -0
- /package/dist/{press-W7IZ3FCX.js.map → press-UIAE5XEF.js.map} +0 -0
- /package/dist/{product-video-XCZ6CHR5.js.map → product-video-B6TLS7VC.js.map} +0 -0
- /package/dist/{providers-XCNSU3T6.js.map → providers-AERTX6X4.js.map} +0 -0
- /package/dist/{research-AYCKHOWK.js.map → research-AJH6ECYW.js.map} +0 -0
- /package/dist/{review-PP2UNSMJ.js.map → review-RN6XF2YB.js.map} +0 -0
- /package/dist/{review-desktop-3JOJFUEJ.js.map → review-desktop-UJOUS7K2.js.map} +0 -0
- /package/dist/{rpc-7EPTJQQ6.js.map → rpc-VS5Y5FUT.js.map} +0 -0
- /package/dist/{run-P6UJS3D4.js.map → run-EVRIQW7S.js.map} +0 -0
- /package/dist/{screencast-start-ZZYNH2HT.js.map → screencast-start-U6J4FYU4.js.map} +0 -0
- /package/dist/{screencast-stop-Y6ADFOFA.js.map → screencast-stop-EQUPRGMP.js.map} +0 -0
- /package/dist/{screenshot-CJB7PMAF.js.map → screenshot-BENYGC36.js.map} +0 -0
- /package/dist/{scroll-BP5MA4ZT.js.map → scroll-3OALQLX2.js.map} +0 -0
- /package/dist/{scroll-into-view-O3RDWLM2.js.map → scroll-into-view-SNZKBIVB.js.map} +0 -0
- /package/dist/{select-QLCNRI36.js.map → select-JDZDDC3Y.js.map} +0 -0
- /package/dist/{serve-OO2MQWGL.js.map → serve-LOC6ESJ4.js.map} +0 -0
- /package/dist/{shopping-UYHCYPAH.js.map → shopping-267OAYGM.js.map} +0 -0
- /package/dist/{snapshot-SXYZ3CMC.js.map → snapshot-ASYI5UFR.js.map} +0 -0
- /package/dist/{status-AL2AHVA5.js.map → status-47CI4LJX.js.map} +0 -0
- /package/dist/{status-QQW7REK4.js.map → status-N4O6DJTF.js.map} +0 -0
- /package/dist/{status-capabilities-AVHJYQQQ.js.map → status-capabilities-C777JZG4.js.map} +0 -0
- /package/dist/{text-B6Z47EOA.js.map → text-MS2653MW.js.map} +0 -0
- /package/dist/{type-LR3F3SQY.js.map → type-UMPSDACC.js.map} +0 -0
- /package/dist/{uncheck-5PJEHR7J.js.map → uncheck-2OZ56D42.js.map} +0 -0
- /package/dist/{upload-HQ3QN2OW.js.map → upload-CD7PRH54.js.map} +0 -0
- /package/dist/{use-KFZLMRUH.js.map → use-MO67AGG7.js.map} +0 -0
- /package/dist/{value-TKUFUK5I.js.map → value-4GI2LRUY.js.map} +0 -0
- /package/dist/{visible-P5Z2N2QR.js.map → visible-VSUFGRFZ.js.map} +0 -0
- /package/dist/{wait-BYSHJPSC.js.map → wait-OQYMFENT.js.map} +0 -0
- /package/dist/{windows-6GTD25EU.js.map → windows-75W2JCW7.js.map} +0 -0
|
@@ -52,11 +52,13 @@ import {
|
|
|
52
52
|
createDefaultRuntime,
|
|
53
53
|
extractStructuredContent,
|
|
54
54
|
inspectChallengePlanFromRuntime,
|
|
55
|
+
inspectPinterestPinMediaBuffer,
|
|
56
|
+
isPinterestPinMediaEvidenceContentType,
|
|
55
57
|
resolveChallengeAutomationPolicy,
|
|
56
58
|
resolveProviderRuntimePolicy,
|
|
57
59
|
resolveWorkflowArtifactRoot,
|
|
58
60
|
toSnippet
|
|
59
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-WTWSBEBW.js";
|
|
60
62
|
import {
|
|
61
63
|
buildBlockerArtifacts,
|
|
62
64
|
classifyBlockerSignal,
|
|
@@ -3664,8 +3666,9 @@ import { parse, resolve as resolve6 } from "path";
|
|
|
3664
3666
|
|
|
3665
3667
|
// src/browser/browser-manager.ts
|
|
3666
3668
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
3667
|
-
import {
|
|
3668
|
-
import {
|
|
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";
|
|
3669
3672
|
import { freemem, totalmem } from "os";
|
|
3670
3673
|
import { Mutex } from "async-mutex";
|
|
3671
3674
|
|
|
@@ -6713,6 +6716,469 @@ var BrowserScreencastRecorder = class {
|
|
|
6713
6716
|
|
|
6714
6717
|
// src/browser/browser-manager.ts
|
|
6715
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
|
+
}
|
|
6716
7182
|
var DOM_GET_ATTR_DECLARATION = `
|
|
6717
7183
|
function(name) {
|
|
6718
7184
|
/* odb-dom-get-attr */
|
|
@@ -6916,6 +7382,104 @@ var DOM_FILE_INPUT_INFO_DECLARATION = `
|
|
|
6916
7382
|
};
|
|
6917
7383
|
}
|
|
6918
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
|
+
};
|
|
6919
7483
|
var BrowserManager = class {
|
|
6920
7484
|
store = new SessionStore();
|
|
6921
7485
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -8258,6 +8822,166 @@ var BrowserManager = class {
|
|
|
8258
8822
|
}
|
|
8259
8823
|
});
|
|
8260
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
|
+
}
|
|
8881
|
+
}
|
|
8882
|
+
}
|
|
8883
|
+
throw lastFailure instanceof Error ? lastFailure : new Error("Pinterest pin media capture failed.");
|
|
8884
|
+
});
|
|
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
|
+
}
|
|
8261
8985
|
async startScreencast(sessionId, options = {}) {
|
|
8262
8986
|
return await this.runStructural(sessionId, async () => {
|
|
8263
8987
|
const managed = this.getManaged(sessionId);
|
|
@@ -11365,6 +12089,12 @@ var OpsBrowserManager = class {
|
|
|
11365
12089
|
...warnings ? { warnings } : {}
|
|
11366
12090
|
};
|
|
11367
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.");
|
|
12097
|
+
}
|
|
11368
12098
|
async startScreencast(sessionId, options = {}) {
|
|
11369
12099
|
if (!this.opsSessions.has(sessionId)) {
|
|
11370
12100
|
return await this.base.startScreencast(sessionId, options);
|
|
@@ -12916,7 +13646,7 @@ var parseJson2 = (data) => {
|
|
|
12916
13646
|
// src/browser/canvas-manager.ts
|
|
12917
13647
|
import { randomUUID as randomUUID19 } from "crypto";
|
|
12918
13648
|
import { mkdir as mkdir9 } from "fs/promises";
|
|
12919
|
-
import { dirname as
|
|
13649
|
+
import { dirname as dirname6 } from "path";
|
|
12920
13650
|
|
|
12921
13651
|
// src/browser/canvas-client.ts
|
|
12922
13652
|
import { randomUUID as randomUUID15 } from "crypto";
|
|
@@ -24983,7 +25713,7 @@ function listBuiltInCanvasKitIds() {
|
|
|
24983
25713
|
|
|
24984
25714
|
// src/canvas/repo-store.ts
|
|
24985
25715
|
import { access as access3, mkdir as mkdir6, readFile as readFile2 } from "fs/promises";
|
|
24986
|
-
import { join as join13, dirname as
|
|
25716
|
+
import { join as join13, dirname as dirname3, isAbsolute as isAbsolute3, resolve as resolve2 } from "path";
|
|
24987
25717
|
|
|
24988
25718
|
// src/canvas/code-sync/manifest.ts
|
|
24989
25719
|
var isRecord6 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
@@ -25184,7 +25914,7 @@ function resolveCanvasFigmaAssetPath(worktree, fileKey, assetId, extension) {
|
|
|
25184
25914
|
}
|
|
25185
25915
|
async function saveCanvasDocument(worktree, document2, repoPath) {
|
|
25186
25916
|
const resolvedPath = resolveCanvasRepoPath(worktree, document2.documentId, repoPath);
|
|
25187
|
-
await mkdir6(
|
|
25917
|
+
await mkdir6(dirname3(resolvedPath), { recursive: true });
|
|
25188
25918
|
writeFileAtomic(resolvedPath, `${JSON.stringify(stableValue(document2), null, 2)}
|
|
25189
25919
|
`, { encoding: "utf-8" });
|
|
25190
25920
|
return resolvedPath;
|
|
@@ -25206,7 +25936,7 @@ async function loadCanvasDocumentById(worktree, documentId) {
|
|
|
25206
25936
|
}
|
|
25207
25937
|
async function saveCanvasCodeSyncManifest(worktree, manifest, repoPath) {
|
|
25208
25938
|
const resolvedPath = resolveCanvasCodeSyncManifestPath(worktree, manifest.documentId, manifest.bindingId, repoPath);
|
|
25209
|
-
await mkdir6(
|
|
25939
|
+
await mkdir6(dirname3(resolvedPath), { recursive: true });
|
|
25210
25940
|
writeFileAtomic(resolvedPath, `${JSON.stringify(stableValue(manifest), null, 2)}
|
|
25211
25941
|
`, { encoding: "utf-8" });
|
|
25212
25942
|
return resolvedPath;
|
|
@@ -25588,7 +26318,7 @@ import { resolve as resolve5, isAbsolute as isAbsolute5 } from "path";
|
|
|
25588
26318
|
// src/canvas/adapter-plugins/loader.ts
|
|
25589
26319
|
import { createHash as createHash4 } from "crypto";
|
|
25590
26320
|
import { access as access4, readFile as readFile3 } from "fs/promises";
|
|
25591
|
-
import { dirname as
|
|
26321
|
+
import { dirname as dirname4, isAbsolute as isAbsolute4, join as join14, resolve as resolve4 } from "path";
|
|
25592
26322
|
import { pathToFileURL } from "url";
|
|
25593
26323
|
|
|
25594
26324
|
// src/canvas/adapter-plugins/manifest.ts
|
|
@@ -25734,7 +26464,7 @@ async function resolveDeclarationRef(worktree, ref) {
|
|
|
25734
26464
|
if (await exists(direct)) {
|
|
25735
26465
|
const manifestPath2 = direct.endsWith(".json") ? direct : join14(direct, "canvas-adapter.plugin.json");
|
|
25736
26466
|
return {
|
|
25737
|
-
packageRoot: direct.endsWith(".json") ?
|
|
26467
|
+
packageRoot: direct.endsWith(".json") ? dirname4(direct) : direct,
|
|
25738
26468
|
manifestPath: manifestPath2
|
|
25739
26469
|
};
|
|
25740
26470
|
}
|
|
@@ -27384,9 +28114,9 @@ function importCodeSyncGraph(options) {
|
|
|
27384
28114
|
|
|
27385
28115
|
// src/canvas/code-sync/write.ts
|
|
27386
28116
|
import { mkdir as mkdir7 } from "fs/promises";
|
|
27387
|
-
import { dirname as
|
|
28117
|
+
import { dirname as dirname5 } from "path";
|
|
27388
28118
|
async function writeCodeSyncSource(repoPath, sourceText) {
|
|
27389
|
-
await mkdir7(
|
|
28119
|
+
await mkdir7(dirname5(repoPath), { recursive: true });
|
|
27390
28120
|
writeFileAtomic(repoPath, sourceText, { encoding: "utf-8" });
|
|
27391
28121
|
}
|
|
27392
28122
|
function finalizeCodeSyncManifest(manifest, updates) {
|
|
@@ -30458,7 +31188,7 @@ var CanvasManager = class {
|
|
|
30458
31188
|
const repoRoot = this.resolveSessionRepoRoot(session, params2);
|
|
30459
31189
|
const warnings = evaluateCanvasWarnings(document2, { forSave: exportTarget === "design_document" });
|
|
30460
31190
|
const exportBase = resolveCanvasRepoPath(repoRoot, document2.documentId, ".opendevbrowser/canvas/exports");
|
|
30461
|
-
await mkdir9(
|
|
31191
|
+
await mkdir9(dirname6(exportBase), { recursive: true });
|
|
30462
31192
|
if (exportTarget === "design_document") {
|
|
30463
31193
|
const validation = validateCanvasSave(document2);
|
|
30464
31194
|
if (validation.missingBlocks.length > 0) {
|
|
@@ -33055,7 +33785,7 @@ function toAbsoluteUrl(value) {
|
|
|
33055
33785
|
}
|
|
33056
33786
|
}
|
|
33057
33787
|
async function saveText(path4, content) {
|
|
33058
|
-
await mkdir9(
|
|
33788
|
+
await mkdir9(dirname6(path4), { recursive: true });
|
|
33059
33789
|
const { writeFileAtomic: writeFileAtomic2 } = await import("./fs-UMRKOBNN.js");
|
|
33060
33790
|
writeFileAtomic2(path4, `${content}
|
|
33061
33791
|
`, { encoding: "utf-8" });
|
|
@@ -35483,4 +36213,4 @@ export {
|
|
|
35483
36213
|
createOpenDevBrowserCore
|
|
35484
36214
|
};
|
|
35485
36215
|
/* v8 ignore next -- @preserve */
|
|
35486
|
-
//# sourceMappingURL=chunk-
|
|
36216
|
+
//# sourceMappingURL=chunk-AHQC4A6P.js.map
|